「グリッドを埋める」問題


36

単純なルールでありながら、自明でないアルゴリズムによる課題。:-)

仕事

スペースで区切られた整数の形式で入力を取得します。

N A B S

ここで、Nは、AとBの間の一意の数値(整数)で満たされた2D正方行列の辺の長さです。この行列の各行と列の合計は常に同じです:S(言い換えると、行列は半魔法の正方形です)。

注意:

すべての数値は正です。例外はAであり、0の場合があります。

ために

3 1 10000 2015

有効な解決策は

ここに画像の説明を入力してください

ために

8 1 300 500

有効な解決策は

ここに画像の説明を入力してください

出力

出力はASCIIテーブルである必要があります。上記の最初の例の例:

 384  159 1472
1174  499  342
 457 1357  201

スペースで埋められた右揃えの整数。各列の幅は、その列の最大の整数の幅です。

得点

これはであるため、バイト単位の最短コードが優先されます。標準的な抜け穴が適用されます(特に、この問題を解決するためのビルトインについて)。間違った入力や不可能な入力(負の数を含む)を気にする必要はありません。上記の2番目の例の回答(必須)にサンプル出力を提供してください。


1
AとBの間で乱数が正しく加算されて一意になるまで、乱数を生成できますか?
リルトシアスト

ただ、チェックするために、AB、およびN負になることができますか?
-xnor

2
minxomat、私はそれが私が思い付くことができる最高の解決策だと言っているのではなく、私はそれが可能な限り短いかもしれないと言っています。
リトシアスト

3
@LuisMendoタスクに従ってサンプル出力を生成する必要があります。あなたが一生のうちに総当たり的なアプローチでこれを管理できるなら、私は感銘を受けるでしょう。:-)。私はそれを除外することはできましたが、最も一般的なソリューション(GA)にはまだランダム性が関係しているため、あいまいすぎます。また、誰かがすでにソリューションに取り組んでいる可能性があるときに、ルールを変更したくありません。
mınxomaτ

1
@minxomatあなたの3つの議論はすべて非常に良い点です:
ルイス・メンド

回答:


19

CJam、119 91バイト

q~:M;),>:R;(:L{{R{ML)d/-Y#)mr}$L/L<2{{M1$:+-+}%z}*:U:+__O|=R*-}gU{:s_:,:e>f{Se[}}%zSf*N*}M?

これは、間違いなく正しい、非決定論的なアプローチです。

私のデスクトップでは、2番目のテストケースは通常10分以内に終了します。

最初のケースはすぐに終了します。CJamインタプリタでオンラインで試してください。

サンプル実行

$ cjam grid.cjam <<< '8 1 300 500'
77  66  37 47  56  46 86  85
63 102  70 72  49  54 81   9
62  69  58 57  71  17 48 118
64  65  67 87  53  44 80  40
73  60  55 89  51  76 84  12
68  59  28 78  74  38 50 105
61  75  52 43 125  83 42  19
32   4 133 27  21 142 29 112

アイディア

時間制限がなければ、有効な正方形が見つかるまで正方形をランダムに生成できます。このアプローチはその考えに基づいており、2つの最適化を追加します。

  • 辺の長さNの正方形を擬似ランダムに生成する代わりに、辺の長さN-1の正方形を生成し、1列を追加して、行の合計がSであるN×(N-1)の長方形を形成し、次に1行で辺の長さNを持つ列和持っSを

    すべての列の要素の合計はNSであり、最初のN-1行の要素の合計は(N-1)Sであるため、最後の行も合計Sになります。

    ただし、最後の行と列のすべての要素が一意であるか、範囲[A ... B]に収まる保証がないため、このプロセスでは無効なマトリックスが生成される場合があります。

  • [A ... B]の一意の整数の正方形と辺の長さN-1を一様にランダムに選択すると、時間がかかりすぎます。前の箇条書きで詳しく説明したプロセスを適用した後、辺の長さNの有効な正方形になる可能性が高い正方形に何らかの方法で優先順位を付ける必要があります。

    各行と列の合計がSでなければならないことを考えると、その要素の平均はS / Nです。したがって、その平均に近い要素をさらに選択すると、チャンスが増えるはずです。

    Iにおける[A ... B] 、我々は、擬似ランダム間フロートピック0及び(I - S / N)2 + 1とを並べ替えの要素[A ... B]選んだフロートによって。最初のN 2番号を保持し、正方形の読み取り順序に配置します。

    各ステップで0から(I-S / N)2 + 1までのすべての実数の完全に均一な分布を仮定すると、すべての正方形は選択される確率がゼロではなく、プロセスが最終的に終了することを意味します。

コード

q~          e# Read all input from STDIN and evaluate it.
:M;         e# Save "S" in M and discard it from the stack.
),>:R;      e# Transform "A B" into [A ... B], save in R and discard.
(:L         e# Save "N - 1" in L and keep it on the stack.
{           e# If L is non-zero:
  {         e#   Do:
    R{      e#     For each I in R:
      ML)d/ e#       Compute M/Double(L+1).
      -Y#   e#       Subtract the result from I and square the difference.
      )mr   e#       Add 1 and pick a non-negative Double below the result.
    }$      e#     Sort the values of I according to the picks.
    L/      e#     Split the shuffled R into chunks of length L.
    L<      e#     Keep only the first L chunks.
    2{      e#     Do twice:
      {     e#       For each row of the  L x L array.
        M1$ e#       Push M and a copy of the row.
        :+- e#       Add the integers of the row and subtract their sum from M.
        +   e#       Append the difference to the row.
      }%    e#
      z     e#       Transpose rows and columns.
    }*      e#
    :U:+    e#     Save the result in U and concatenate its rows.
    __O|    e#     Push two copies. Deduplicate the second copy.
    =R*     e#     Push R if all elements are unique, an empty array otherwise.
    -       e#     Remove the result's elements from U's elements.
  }g        e#   If the resulting array is non-empty, repeat the loop.
  U{        e#   For each row in U:
    :s      e#     Convert its integers into strings.
    _:,     e#     Copy and replace each string with its length.
    :e>     e#     Compute the maximum length.
    f{      e#     For each integer, push the maximum length; then
      Se[   e#       Left-pad the integer with spaces to that length.
    }       e#
  }%        e#
  z         e#   Transpose rows with columns.
  Sf*N*     e#   Join columns by spaces, rows by linefeeds.
}M?         e# Else, push M.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.