詰めSAS12回目_カラーパレット問題:組み合わせと結果がデータセットで与えられ、それに基づいて処理する場合

僕が実際に、最近悩んだ処理を、詰めSAS問題にしました。
答えは何種類もありえますが、とりあえず、現実に僕が採用したものを回答例としてあげます。
カラーパレット問題とか適当に名前つけていますが、勝手に僕が作った名前なので気にしないでください。


まず、以下のデータセットを見て下さい。

data RULE;
C1='赤';C2='青';COLOR='紫';output;
C1='青';C2='黄';COLOR='緑';output;
C1='黄';C2='赤';COLOR='橙';output;
run;

【データセット:RULE】






これは、2色の絵の具を混ぜた時に、できる色を示したパターン表です。
例えば1オブザベーション目は、赤と青を混ぜると紫ができるよということを示しています。


次にもう一つデータセットを見て下さい。

data Q1;
X='黄';Y='青';output;
X='赤';Y='赤';output;
X='黄';Y='赤';output;
X='赤';Y='青';output;
X='青';Y='青';output;
X='青';Y='黒';output;
run;

【データセット:Q1】








6オブザベーションあって、変数XとYそれぞれに色が入っています。

さて、今回の問題は、先に提示されたデータセット「RULE」の内容に基づいて
データセット[Q1]の6オブザベーション、全てに対して、混ぜたら何色になるかを
値として持たせなさいというものです。

ただし、以下の条件があります。
①同じ色を混ぜても、同じ色にしかなりません。つまり赤と赤を混ぜたら結果は赤です。
②RULEの中に存在しない組み合わせの色に対しては、結果が不明なので「×」といれます
③赤と青を混ぜるということと、青と赤を混ぜるということは同じとします。混ぜる際の色の指定順序に意味はありません。

さて、あなたなら、こういった処理をどのように解きますか?
ポイントは与えられたパターン表と色の順序が逆の場合の対応ですね。
順番が固定ならマージすりゃ終わりです。

なので、データセットRULEをいじって、C1とC2が逆の場合のデータも作って、6オブザベーションの
パターンが格納されたデータセットにしてからマージするのも、正解です。

でもなんかステップ数がかさむし、嫌だなと思って、以下のようにしました

data A1;
informat X Y COLOR;
 if _N_=0 then set RULE;
 if _N_=1 then do;
  declare hash pallet(dataset:'RULE');
   pallet.definekey('C1','C2');
   pallet.definedata('COLOR');
   pallet.definedone();
  end;
 set Q1;
  if X=Y then COLOR=X;
  else do;
   C1=X;
   C2=Y;
   rc=pallet.find();
    if rc^=0 then do;
     C1=Y;
     C2=X;
     rc=pallet.find();
     if rc^=0 then COLOR='×';
end;
   end;
keep X Y COLOR;
run;

結果は










こんな感じで合ってます。

はい、つまりハッシュオブジェクト使いました。
このケースでは、使うべき処理でハッシュオブジェクト使えた気がします。

いや、1ステップだけど、こんな長いわけわからんコード書くぐらいなら細かくステップ分けるわ!
っていうご意見もごもっともです。

でも、SQLもそうだと思うのですが、最初、読み書きに抵抗があっても、
慣れればどうってことないっていうより、むしろ普通のデータセステップより読みやすいし、すらすら書けるってなります。

僕としては、多次元配列のARRAYで、深いループ書かれるより、ハッシュで書かれたコードの方が
行数があっても読みやすいと思っています。


で、実は今回は、今度のユーザー総会で発表する、ハッシュオブジェクトの前ふりでした。
上記コードの詳しい意味が知りたい方は是非、発表を聞いていただけると嬉しいです。
(もしからした発表時間のスケジュールが変わって、ハッシュはDAY1になるかも、、)

ただ、そのうち、このブログでもハッシュオブジェクトについて書いていきます。





0 件のコメント:

コメントを投稿