私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「正二十面体の隣の面」(CodeIQ)を参照してください。
【概要】
展開すると右図のようになる正二十面体があります。
面の番号を指定します。
その面の、隣(つまり、辺を共有する)面の番号を昇順にコンマ区切りで出力して下さい。
【入出力】
入力は
2
のようになっています。
面の番号を示す 1〜20 のいずれかの数です。
出力は2 の隣の面の番号を昇順にコンマ区切りで出力すればよいので
1,3,7
のような感じです。
【例】
入力 出力 2 1,3,7 10 5,14,15
【補足】
不正な入力に対処する必要はありません。
Rubyで解答しています。
#!/usr/bin/ruby DICE = [ [ 1, nil, 2, nil, 3, nil, 4, nil, 5, nil], [ 6, 11, 7, 12, 8, 13, 9, 14, 10, 15], [nil, 16, nil, 17, nil, 18, nil, 19, nil, 20], ] def solve(n) y = -1 x = -1 catch(:found){ for y in 0...DICE.size for x in 0...DICE[y].size throw :found if n == DICE[y][x] end end } u = (y-1) >= 0 ? (y-1) : DICE.size-1 d = (y+1) < DICE.size ? (y+1) : 0 if y == 0 then l = (x-2) >= 0 ? (x-2) : DICE[y].size-2 r = (x+2) < DICE[y].size ? (x+2) : 0 elsif y == 1 l = (x-1) >= 0 ? (x-1) : DICE[y].size-1 r = (x+1) < DICE[y].size ? (x+1) : 0 elsif y == 2 l = (x-2) >= 0 ? (x-2) : DICE[y].size-1 r = (x+2) < DICE[y].size ? (x+2) : 1 end return [DICE[u][x], DICE[d][x], DICE[y][l], DICE[y][r]].compact.sort end # main while line = gets line.strip! next if line.empty? puts solve(line.to_i).join(",") end
特に難しい部分はなく、展開図を二次元配列で表現して上下左右を求めればできます。
DICEは20面体のの展開図を二次元配列で表現したものです。
入力値を数値にしてsolve()に渡します。
結果が配列で帰るのでjoin()して印字します。
問題を解きます。
xとyは入力値の座標です。
13〜19行目で入力値の座標を求めます。
21行目で上、22行目で下の値を求めます。上は配列の添え字が0未満になったら3行目、下は配列の添え字が2を超えたら1行目になるのでそれも考慮します。
24〜26行目は1行目の左右、27〜29行目は2行目、30〜32行目は3行目の左右を求めます。1行目と3行目は隣がnilの場合さらにその隣が隣接する面になるのでそれを考慮します。
両端を超えたら反対側になります。
結果からnilをcompact()で除いて、sort()して結果を返します。
単純な方法ですが十分と思います。
ゲームに使うちなみに、12面体のダイスを眺めてみましたが、配列はこの問題とは違いました。