ラベル iml の投稿を表示しています。 すべての投稿を表示
ラベル iml の投稿を表示しています。 すべての投稿を表示

詰めSAS12回目:数字が1文字ずつに分解された、数列から100番目の値を取得する

リンクさせていただいたサイト「うずまき (3rd Gen)」の管理人じゅんさんに、あるプログラマ向けチャレンジサイトの問題を教えて貰いました。

ただ、何のサイトか書いて、そのまま問題文載せて、解答例を示してしまうと、ちょっとまずいかなと思うので、問題を参考にした上で内容を変更しています。結構ありがちで一般的な問題だと思いますが。

そもそも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に慣れていなくてわかりませんでした。どなたか教えてください。


IMLでセルオートマトンのコード紹介

他人様のネタですが、とても勉強になったので紹介。
SAS IMLのテクニック紹介ブログにセルオートマトンの表現法があがっていました。

有名なルール30ですね、なぜかある種の巻貝の模様と一致するという神秘。

http://blogs.sas.com/content/iml/2014/10/17/wolframs-rule-30/


いや、このコード、IML初心者の僕には、かなりキツいです。
取り敢えず、Nを5とかにして、rest print;入れて、全部中身を見ながら追ってなんとか、、。
肝心の法則式のところは、もはや、へ~、これでできてんだ。て程度の理解ですが。

しかし、凄い!

でもSAS Universityだとやたら時間かかるんだけど、僕のPCが貧弱なのか?

面白いな~、これ凄い面白い。
なんかIMLのデータ操作のエッセンスが詰まってるんで、これIML入門者用の教材にいいんじゃないですかね?

IML関連のテキストは、すぐ統計解析にいってしまって、基本操作が消化不良になりがちな気がしますから、こういうのいいかも。

こういうIMLの特性を活かした面白いコード持ってる人がいらっしゃれば、貼っていただければ嬉しいです。

IMLでアタック25

IMLだとヒートマップが超簡単に書けるんですね。
まあ、行列に色つけたプロットだから当たり前か
ヒートマップの説明:
http://ja.wikipedia.org/wiki/%E3%83%92%E3%83%BC%E3%83%88%E3%83%9E%E3%83%83%E3%83%97

もちろんIML使わずにGTLでもHEATMAPPARMステートメントで表現できますが、面倒くささは否めません。

proc iml;
X={1 2 3 1 1,
   1 2 2 1 4,
   2 2 1 3 4,
   3 1 2 2 2,
   1 2 3 4 3
   };
call HeatmapDisc(X) colorramp={RED GREEN BLUE WHITE};
quit;

















アタック25見ながら、適当に書いたのが上のプログラムです。
意味は全くないです。


この機能、僕の好きなセルオートマトンシミュレーションに使えそうですね。
例のGIFファイルでアニメを作るプログラムと合わせれば、面白そう。

また、これを超細かくたくさん作ればドット絵アニメできそう。
自分じゃ、絶対やりたくないけど、見てみたいな~。SAS好きで、変態な友人がいる方はそそのかしてみてください。

IMLプロシジャで全変数全obsで最大の値をとる

以前勤めていたところがSASのIMLのライセンスを導入していなかったため、IMLプロシジャを使ったことがありませんでした。
しかし、またまたSAS University EditionだとIMLが使えるということで、早速使ってみました。

僕の頁 <SASと臨床試験と雑談と>で、IMLは行列計算だけでなく、データセットの加工手段としても使えるみたいなことが示唆されていたので
「IMLによるデータセットの作成と読み込み」
http://sasboku.blog.fc2.com/blog-category-15.html

早速、前からIML使ったらどう書くんだろうと気になっていた第1回目の記事の詰めSAS一問目、
「データセット中の最大の値を1変数1obsのデータセットに格納する最善手を考えよ」
http://sas-tumesas.blogspot.jp/2013/09/sas1obs.html
という問題を考えます



さて以下のデータセットから

data Q1;
input X Y Z;
cards;
1 4 3
2 9 8
7 6 5
;
run;







から最大の値、9をとれということです。

まあ、結論としてa matsuさんの提案された

proc sql;
create table A4 as
select max(max(X,Y,Z)) as M
from Q1;
quit;


が一番すっきりしていて、SASのmax関数とSQLのmax関数の働きを併せているところが面白いというのもあり、最善手だと思っていますが、前々からこの問題はIMLが向いてそうだから、いつかやってみたいなぁと思っていたんですね。

以下が僕が書いたコードです。
ちょっとIMLに慣れてないので、できていないところがあればご指摘ください。


proc iml;
 use Q1;
 read all into _M;
 M=max(_M);
 create A5 from M[colname='M'];
 append from M;
quit;





結果は以下の通りです。


あ~、すっきりした!