マーチングスクエアルックアップ


9

マーチングスクエアはコンピューターグラフィックスのアルゴリズムであり、サンプルのグリッドから2D等高線を復元するために使用されます(3D設定用の兄貴のマーチングキューブも参照)。アイデアは、グリッドの各セルを個別に処理し、コーナーの値に基づいてそのセルを通過する輪郭を決定することです。

このプロセスの最初のステップは、コーナーがコンターの値の上か下かに基づいて、コンターによって接続されているエッジを判別することです。簡単にするため、値0に沿ったコンターのみを考慮し、コーナーが正か負かを調べます。区別するケースがあります:24 = 16

ここに画像の説明を入力してください
画像ソース:ウィキペディア

ここでは白と黒の識別はそれほど重要ではありませんが、明確にするために、白はポジティブで黒はネガティブであると言います。コーナーの1つが正確にある場合は無視し0ます。

サドルポイント(ケース5と10)は、少し余分な難しさを提供します。コーナーを見るだけではどの対角線を使用すべきかが明確ではありません。これは、4つのコーナーの平均(つまり、中心値の概算)を見つけ、コンターが反対の符号でコーナーからセンターを分離するように対角線を選択することで解決できます。平均が正確0にの場合、どちらのケースも選択できます。

通常、これらの16のケースは単にルックアップテーブルに格納されます。これは効率的には優れていますが、もちろん、ここではコードを短くすることをお勧めします。したがって、あなたの仕事は、このルックアップ手順を実行し、ケースのASCII表現をできるだけ少ないコードで出力することです。

チャレンジ

選択した固定順序で4つのコーナー(ゼロ以外の整数)の値が与えられます。次に、等高線の正しいレイアウトを生成し、鞍点のケースを正しく解決する必要があります。

プログラムまたは関数を記述し、STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を取り、STDOUT(または最も近い代替)、関数の戻り値または関数(out)パラメーターを介して結果を出力できます。

入力は、任意の便利な文字列またはリスト形式で取得できます。

16のケースは、次の5x5ブロックのいずれかを使用してASCIIアートで表されます。

o---o  o---o  o---o
|   |  |   |  | | |
|   |  |---|  | | |
|   |  |   |  | | |
o---o  o---o  o---o

o---o  o---o  o---o  o---o
|/  |  |  \|  |   |  |   |
|   |  |   |  |   |  |   |
|   |  |   |  |\  |  |  /|
o---o  o---o  o---o  o---o

o---o  o---o
|/  |  |  \|
|   |  |   |
|  /|  |\  |
o---o  o---o

先頭または末尾の空白を印刷することはできませんが、オプションの改行を1つ印刷できます。

これはコードゴルフなので、最も短い答え(バイト単位)が勝ちます。

テストケース

テストケースでは、入力がtop-lefttop-rightbottom-leftbottom-rightの順に与えられることを前提としています。テストケースは9つのグループに分けられ、1つは上記の9つの表現のそれぞれに対応します(同じ順序で、空のセルから始まり、2つのサドルポイントで終わります)。

[1, 2, 1, 3]
[-9, -2, -2, -7]

[4, 5, -1, -2]
[-1, -2, 3, 4]

[7, -7, 7, -7]
[-5, 5, -5, 5]

[1, -6, -4, -1]
[-2, 3, 3, 4]

[-1, 6, -4, -1]
[2, -3, 3, 4]   

[-1, -6, 4, -1]
[2, 3, -3, 4]

[-1, -6, -4, 1]
[2, 3, 3, -4]

[3, -8, -9, 2]
[-3, 8, 9, -2]

[8, -3, -2, 9]
[-8, 3, 2, -9]

さらに、次のテストケースでは、どちらかのサドルポイント(選択)が返される場合があります。

[1, -4, -2, 5]
[-1, 4, 2, -5]

回答:


4

ルビー、201 180 176

これは匿名のラムダ関数であり、ゴルフの例では示されていない方法で呼び出されます。

これには変数が含まれていませんs。非ゴルフバージョンsでは、使用する前に、わかりやすくするために複雑な式が割り当てられています。ゴルフしたバージョンでは、インラインで4バイト保存されます。バージョン間の他の唯一の違いは、空白とコメントです。

出力を5文字の5つの文字列の配列として返すことが許容される場合は、stdoutに出力する代わりに、1バイトを節約できます。

->a{p=t=0
4.times{|i|t+=a[i]*=a[3];p+=a[i]>>9&1<<i}
q=p==6&&t>0?19:'@AC@P*10'[p].ord
puts c='o---o',(0..2).map{|i|b=p*i==3?'|---|':'|   |';b[q%4]='|/|\|/'[q%4+(i&2)];q/=4;b},c}

配列の解析には満足していますが、出力を形成するより短い方法があるかもしれません。

入力配列の4つの要素すべてに最後の要素が乗算されます。これにより、最後の要素が正であることが保証され、ケース数が16から8に減少します。要素は9桁右シフトされるため、すべての正の数は0になり、すべての負の数は-1になります(少なくとも入力の範囲内)。テストケースで指定されます。)次に、ANDによって1<<array indexパターンを示す3ビットの2進数が与えられます(実際には4ビットですが、最後の要素は常に正なので、4番目のビットは常にゼロです)。

次に、0..7からのこの数値が(ため息)ルックアップテーブルに送られ、各行のどの文字が非空白文字かを判別します。サドルケースの2つの異なる表示が処理されるのはこの段階です。合計が正の場合、ルックアップテーブルの数値の代わりに使用されます(質問は「平均」を考慮するように言っていますが、記号に関心がある場合は、代わりに合計を考慮しても問題ありません。)

出力の表示が機能する方法は、コード内のコメントから明確にわかると思います。

テストプログラムに含まれていない

f=->a{p=t=0
  4.times{|i|                      #for each number in the input
    t+=a[i]*=a[3];                   #multiply each number by a[3]; totalize the sum in t
    p+=a[i]>>9&1<<i                  #shift right to find if negative; AND with 1<<i to build index number for pattern 
  }                                #q is a 3-digit base 4 number indicating which character of each line is non-whitespace (if any). 
  q=p==6&&t>0?19:'@AC@P*10'[p].ord #It's encoded in the magic string, except for the case of saddles with a positive total, which is encoded by the number 19.
  s=(0..2).map{|i|                 #build an array of 3 strings, indexes 0..2
    b=p*i==3?'|---|':'|   |';        #IF p is 3 and we are on row 1, the string is |---| for the horizontal line case. ELSE it is |   |.
    b[q%4]='|/|\|/'[q%4+(i&2)];      #The numbers in q indicate which character is to be modified. The characters in the string indicate the character to replace with.
    q/=4;                            #If q%4=0, the initial | is replaced by | (no change.) i&2 shifts the string index appropriately for the last row.
    b                                #divide q by 4, and terminate the loop with the expression b so that this is the object loaded into array s.  
  }
puts c='o---o',s,c}                #print the array s, capped with "o---o" above and below.


[[1, 2, 1, 3],
[-9, -2, -2, -7],

[4, 5, -1, -2],
[-1, -2, 3, 4],

[7, -7, 7, -7],
[-5, 5, -5, 5],

[1, -6, -4, -1],
[-2, 3, 3, 4],

[-1, 6, -4, -1],
[2, -3, 3, 4],

[-1, -6, 4, -1],
[2, 3, -3, 4],

[-1, -6, -4, 1],
[2, 3, 3, -4],

[3, -8, -9, 2],
[-3, 8, 9, -2],

[8, -3, -2, 9],
[-8, 3, 2, -9],

[1, -4, -2, 5],
[-1, 4, 2, -5]].each{|k|f.call(k)}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.