ただ、何のサイトか書いて、そのまま問題文載せて、解答例を示してしまうと、ちょっとまずいかなと思うので、問題を参考にした上で内容を変更しています。結構ありがちで一般的な問題だと思いますが。
そもそもSASで解く人なんて皆無だから問題ないと思いますけど、、。
問題:
4,6,8,1,0,1,2,1,4,.......と続く数列のN番目の値について、Nをマクロ変数で与えて実行すれば、値が表示されるようなSASコードをかけ。そして、取り敢えずN=100のときの値を示せ
あ~!こういうの見るとダメですよね。将棋好きに詰め将棋みせるのと同じで、どれだけ忙しくても考えることを避けれない。
ようするに4から+2ずつしていくけど、値が2桁以上になったら、1桁ずつ分解されるっていうルールの数列ですね。
僕が書いたのは以下の感じです。
%let N=100;
data _NULL_;
file print;
retain K 0;
do i=1 to &N;
X=put(2+(2*i),best. -L);
do j=1 to length(X);
Y=char(X,j);
K+1;
if K=&N then do;
put Y;
return;
end;
end;
end;
run;
[1]です。
なにをしているかをわかりやすくするため、
%let N=10;
data A1;
file print;
retain K 0;
do i=1 to &N;
X=put(2+(2*i),best. -L);
do j=1 to length(X);
Y=char(X,j);
K+1;
output;
if K=&N then do;
return;
end;
end;
end;
run;
とすると
Kが実際何番目かのカウンタです。Xが加算ででてくる値で、それを1桁ずつ分解したのはYです。
Kが設定したNになった時点でループを打ち切ります。
さて、じゅんさんが提示されたコード(問題を変えたことにより、影響のあった箇所等のみかえています。)は
%let x=100;
data A2;
length line2 $ 32767;
DO num=6 TO 4+&x*2 BY 2;
numvar=num;
line=PUT(numvar,best12.);
IF num=6 THEN DO;
line2='4'||line;
line2=COMPRESS(line2,' ');
END;
IF num NE 6 THEN DO;
line2=TRIM(line2)||TRIM(line);
line2=COMPRESS(line2,' ');
END;
END;
ans=SUBSTR(line2,"&x",1);
run;
PROC PRINT data=A2;
var ans;
run;
で、結果は同じです。
なるほど、オブザベーション起こすわけではなく、1変数内で横に連結していくわけですね。問題のイメージと処理のイメージが合致しています。1変数内の文字値制限を超えない限りは、こちらの方が自然かもしれません。
さて、多分、同じ思いの方が多いと思いますが、この問題、めっちゃIML向きですよね。
というかSAS向きでないのか?
一応書いてみたのが
%let N=100;
proc iml;
X=compress(rowcat(char(shape(t((2:&N+1)*2),1))));
Y=substr(X,&N,1);
print X Y;
quit;
処理過程がわかりやすいようにX Y二つに分けていますが、答えはYです。
ただ、多分X=の部分もっと短くかけると思うのですが、まだIMLに慣れていなくてわかりませんでした。どなたか教えてください。