数独ソリューションチェッカーを作成する


21

数独ソリューションチェッカーを作成する

ここには数独ソルバーの大群がありますが、私はあなたにできる限り小さなソリューションチェッカー(コードゴルフ)を作成してほしいです。

  • 有効なエントリは、引数として9x9配列(コマンドラインでシリアル化された参照で渡される、または任意に取得する)として受け取るか、最終グリッド用の9行の9行の入力ファイルを受け入れることができます。 。以下の入力例を参照してください。

  • 有効な入力は10進数(1〜9)でなければなりません

  • 欠落している、空の、余分な、数値以外の位置、または1〜9以外の数値を持つ位置は、ゼロ以外の結果を返すか、エラーを出力するか、またはその両方によって無効な入力として拒否されます。

  • プログラムは、各数値が列ごとに1回、行ごとに1回、3x3サブグリッドごとに1回表示されるかどうかをテストする必要があります。合格した場合は「0」を返し、そうでない場合はゼロ以外の結果を返します。

  • 外部リソース(ウェブサイトなど)の使用は避けてください。

  • ソリューションがスタンドアロンプ​​ログラムである場合、終了ステータスが「0」であるか「Pass」または「Fail」でゼロ以外である場合は、終了しても問題ありません。

最小の答えを当てましょう!

入力例:

c配列:

int input[9][9]={{1,2,3,4,5,6,7,8,9},
                 {4,5,6,7,8,9,1,2,3},
                 {7,8,9,1,2,3,4,5,6},
                 {2,3,1,5,6,4,8,9,7},
                 {5,6,4,8,9,7,2,3,1},
                 {8,9,7,2,3,1,5,6,4},
                 {3,1,2,6,4,5,9,7,8},
                 {6,4,5,9,7,8,3,1,2},
                 {9,7,8,3,1,2,6,4,5}
                };

ファイル:

123456789
456789123
789123456
231564897
564897231
897231564
312645978
645978312
978312645

9つのサブグリッド:

+---+---+---+
|123|456|789|
|456|789|123|
|789|123|456|
+---+---+---+
|231|564|897|
|564|897|231|
|897|231|564|
+---+---+---+
|312|645|978|
|645|978|312|
|978|312|645|
+---+---+---+

回答:


5

GolfScript、39文字

.zip.{3/}%zip{~}%3/{[]*}%++{$10,1>=!},,

入力として配列の配列を取り(オンラインの例を参照)0、有効なグリッドである場合は出力します。

コードの簡単な説明

.zip         # Copy the input array and transpose it
.{3/}%       # Split each line into 3 blocks
zip{~}%      # Transpose these blocks
3/{[]*}%     # Do the same for the lines themselves and join again
++           # Make one large list of 27 9-element arrays 
             # (9 for rows, 9 for columns, 9 for blocks)
{$10,1>=!},  # From those 27 select the ones which are not a permutation of [1 2 3 ... 9]
             #   $      -> sort
             #   10,1>  -> [1 2 3 ... 9]
             #   =!     -> not equal
,            # Count after filtering

私はあなたのコードの非ゼロ出力はより多くの意味があることを好きなだけ1-1
デビッド・ウィルキンス

私はあなたの答えが本当に好きでしたが、最終的には私はgolfscriptソリューションを使用しないことにしました。私は本当にあなたが理解することを願っています
デビッドウィルキンス

2
@DavidWilkins実際、私は理解していません-あなたはルールを作成し(!)、GolfScriptが許可されていないことをどこにも述べていません。
ハワード14年

あなたの主張は完全に有効です...実際、私はあなたの答えを選ばないことを正当化するものは何もありません。よくやった
デビッドウィルキンス

10

Python、103

私は数独が嫌いです。

b = [[1,2,3,4,5,6,7,8,9],
     [4,5,6,7,8,9,1,2,3],
     [7,8,9,1,2,3,4,5,6],
     [2,3,1,5,6,4,8,9,7],
     [5,6,4,8,9,7,2,3,1],
     [8,9,7,2,3,1,5,6,4],
     [3,1,2,6,4,5,9,7,8],
     [6,4,5,9,7,8,3,1,2],
     [9,7,8,3,1,2,6,4,5]]

e=enumerate;print 243-len(set((a,t)for(i,r)in e(b)for(j,t)in e(r)for a in e([i,j,i/3*3+j/3]*(0<t<10))))

仕組み:各行、列、およびブロックには1から9までの各番号が必要です。したがって、それぞれ0 <= i, j < 9について、セルi,jはblockにあり3*floor(i/3) + floor(j/3)ます。したがって、243の要件を満たす必要があります。各要件をタプルにします。((item index,item type number),symbol)ここで、0〜8 item indexの数値(両端を含む)、item type number0、1、または2でsymbolあり、それぞれ行、列、またはブロックを表し、エントリb[i][j]です。

編集:誤って有効なエントリをチェックしませんでした。今私がやります。


あなたのプログラムは、出力すべき0ソリューションが合格した場合、ありませんTrue
デビッド・ウィルキンス

@DavidWilkinsなんて奇妙な要件だ。一定。
ブースビー14

あなたはあなたの答えを始めた方法のためだけに私の投票を得ます:D
Teun Pronk 14年

9

APL(46)

{∧/,↑∊∘Z¨(/∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9),(↓⍵),↓⍉⍵}

これは9行9列の行列を取ります。サンプルは、TryAPLで次のように入力できます。

     sudoku ← ↑(1 2 3 4 5 6 7 8 9)(4 5 6 7 8 9 1 2 3)(7 8 9 1 2 3 4 5 6)(2 3 1 5 6 4 8 9 7)(5 6 4 8 9 7 2 3 1)(8 9 7 2 3 1 5 6 4)(3 1 2 6 4 5 9 7 8)(6 4 5 9 7 8 3 1 2)(9 7 8 3 1 2 6 4 5)
     {∧/,↑∊∘Z¨(/∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9),(↓⍵),↓⍉⍵} sudoku
1

説明:

  • ↓⍉⍵:の列を取得し
  • ↓⍵:の行を取得
  • 3/3⌿3 3⍴Z←⍳9:の数値1を含む3行3列の行列を作成し9、次に各方向に数値を3つずつ複製して、各グループ19示す数値の9行9列の行列を作成します。
  • Z∘.=:各番号のため19、与えられたグループのビットマスクを作ります、
  • /∘(,⍵)¨:そして、それぞれでマスクし、のグループを与えます。
  • ∊∘Z¨:それは数字が含まれている場合、各サブアレイのために、参照1して9
  • ∧/,↑andこれらの数値すべての論理をまとめます。

+1いいね!しかし、3×3グループはもう少しゴルフできます。たとえば、これ↓9 9⍴1 3 2⍉3 3 9⍴⍵は同等ですが/∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9、かなり短いです。もっと短い式があるはずです。
トビア14年

また、あなたは第一次元で行列を連結でき、最後に単一の分割を実行します↓(9 9⍴1 3 2⍉3 3 9⍴⍵)⍪⍵⍪⍉⍵
トビア

バグがあります。このコード∊∘Z¨は、各サブ配列(行、列、またはブロック)が1〜9の数字のみで構成されているかどうかをテストしています。Z∘.∊Zのすべての数値がすべてのサブ配列に含まれていることをテストするようなことをする必要があります。
トビア14年

そして、これ∧/,↑はに短縮できます∧/∊。終わった、終わった!;-)
トビア14年

非常にコンパクトですが、あなたは私がすぐに見ることができる1つの重要な点を見逃しました:If it passes, return "0" and if not, return a non-zero result.
デビッドウィルキンス14

5

Java / C#-183 / 180 181/178 173/170バイト

boolean s(int[][]a){int x=0,y,j;int[]u=new int[27];for(;x<(y=9);x++)while(y>0){j=1<<a[x][--y];u[x]|=j;u[y+9]|=j;u[x/3+y/3*3+18]|=j;}for(x=0;x<27;)y+=u[x++];return y==27603;}

(変更booleanboolC#の場合)

フォーマット済み:

boolean s(int[][] a){
    int x=0, y, j;
    int[] u=new int[27];
    for(;x<(y=9);x++)
        while(y>0){
            j=1<<a[x][--y];
            u[x]|=j;
            u[y+9]|=j;
            u[x/3+y/3*3+18]|=j;
        }

    for(x=0;x<27;)
        y+=u[x++];

    return y==27603;
}

このメソッドは、u27個のビットマスクを持つ配列を作成し、9つの行、列、および正方形にある数字を表します。

次に、すべてのセルを反復処理して1 << a[x][y]、数字を表すビットマスクを作成する操作を実行し、その列、行、正方形のビットマスクの論理和をとります。

次に、27個すべてのビットマスクを反復処理し、合計で27594(1022 * 9、1022は1〜9のすべての数字のビットマスク)になるようにします。(y二重ループの後に9が既に含まれているため、最終的に27603になることに注意してください。)

編集:%3必要なくなったものを誤って残してしまった。

編集2:ブライス・ワーグナーのコメントに触発されて、コードはもう少し圧縮されました。


C#149文字とほぼ同じアルゴリズム(ただし、Linqが許可されている場合のみ):bool s(int [] a){int x = 0、y、j; var u = new int [27]; while(x ++ <(y = 9))while(y> 0){j = 1 << a [x + 9 *-y]; u [x] | = j; u [y + 9] | = j; u [x / 3 + y / 3 * 3 + 18] | = j;} return u.Sum()== 27594;}
ブライスワーグナー14年

@BryceWagner Linqは確かに役に立つでしょう。ただし、私のソリューションはJava向けであり、C#は後から考えられ(元の投稿でも言及されていません)、したがって優先順位は低くなります。また、最初にコンパクトにするために1次元配列を使用してから決定しました(例では2次元配列を使用しているため)。それにもかかわらず、あなたのコードは、さらに数バイトを削る方法についていくつかのアイデアをくれました。:)
Smallhacker 14年

3

python = 196

ほとんどのゴルフではありませんが、アイデアはそこにあります。セットは非常に便利です。

ボード:

b = [[1,2,3,4,5,6,7,8,9],
     [4,5,6,7,8,9,1,2,3],
     [7,8,9,1,2,3,4,5,6],
     [2,3,1,5,6,4,8,9,7],
     [5,6,4,8,9,7,2,3,1],
     [8,9,7,2,3,1,5,6,4],
     [3,1,2,6,4,5,9,7,8],
     [6,4,5,9,7,8,3,1,2],
     [9,7,8,3,1,2,6,4,5]]

プログラム:

n={1,2,3,4,5,6,7,8,9};z=0
for r in b:
 if set(r)!=n:z=1
for i in zip(*b):
 if set(i)!=n:z=1
for i in (0,3,6):
 for j in (0,3,6):
  k=j+3
  if set(b[i][j:k]+b[i+1][j:k]+b[i+2][j:k])!=n:z=1
print(z)

s / {1,2,3,4,5,6,7,8,9} / set(range(1,10))/は3文字を保存します。
MatrixFrog 14年

Python 3.5ではを使用できますがn={*range(1,10)}、それはチャレンジよりも新しいものです。代わりにset(range(1,10))MatrixFrogが言ったように使用します。
mbomb007

3

Java- 385306328260文字

編集: 答え完全なプログラムでなければならないという指示を愚かに誤解してます。有効な関数にしかならないため、関数に書き換えて最小化し、それを念頭に置いてソリューションの紹介を書き直しました。

それで、自分自身への挑戦として、私は最小のJavaソリューションチェッカーを作ろうと思った。

これを達成するために、数独パズルは次のようにJava多次元配列として渡されると想定しています。

s(new int[][] {
    {1,2,3,4,5,6,7,8,9},
    {4,5,6,7,8,9,1,2,3},
    {7,8,9,1,2,3,4,5,6},
    {2,3,1,5,6,4,8,9,7},
    {5,6,4,8,9,7,2,3,1},
    {8,9,7,2,3,1,5,6,4},
    {3,1,2,6,4,5,9,7,8},
    {6,4,5,9,7,8,3,1,2},
    {9,7,8,3,1,2,6,4,5}});

次に、実際のソルバーがあり、有効なソリューションの場合は「0」、そうでない場合は「1」を返します。

完全にゴルフ:

int s(int[][] s){int i=0,j,k=1;long[] f=new long[9];long r=0L,c=r,g=r,z=45L,q=r;for(f[0]=1L;k<9;){f[k]=f[k-1]*49;z+=f[k++]*45;}for(;i<9;i++){for(j=0;j<9;){k=s[i][j];r+=k*f[i];c+=k*f[j];g+=k*f[j++/3+3*(i/3)];q+=5*f[k-1];}}return (r==z&&c==z&&g==z&&q==z)?0:1;}

読みやすい:

    int s(int[][] s) {
        int i=0,j,k=1;
        long[] f=new long[9]; 
        long r=0L,c=r,g=r,z=45L,q=r;
        for(f[0]=1L;k<9;){f[k]=f[k-1]*49;z+=f[k++]*45;}
        for(;i<9;i++) {
            for (j=0;j<9;) {
                k=s[i][j];
                r+=k*f[i];
                c+=k*f[j];
                g+=k*f[j++/3+3*(i/3)];
                q+=5*f[k-1];
            }
        }
        return (r==z&&c==z&&g==z&&q==z)?0:1;
    }

では、これはどのように機能しますか?基本的に、各桁に十分な解像度を持つ独自の数値ベースを作成するだけで、パズルを1回通過した後、それが有効かどうかを知るために3回の数値比較を行うだけで済みます。この問題のためにベース49を選択しましたが、45より大きいベースであれば十分です。

(願わくば)明確な例:数独パズルのすべての「行」は、49を底とする数字の1桁であると想像してください。簡単にするために、49進数の各桁をベクトルの10進数として表します。したがって、すべての行が「正しい」場合、次のベース49の数値(ベース10のベクトルとして)が予想されます。

(45,45,45,45,45,45,45,45,45)

または、単一の10進数に変換されます: 1526637748041045

すべての列で同様のロジックに従い、「サブグリッド」でも同じです。この「理想的な数」に等しくない最終分析で出会った値は、パズルの解が無効であることを意味します。

すべての5の脆弱性およびその他の関連する問題を解決するために編集します。すべてのパズルに各番号が9個あるはずであるという考えに基づいて、4番目のbase-49番号を追加します。したがって、数字のインデックスを表す10進数の出現ごとに、49進数の各数字に5を追加します。たとえば、10個の9と9個の8個、9個の7個、8個の6個、および他のすべての9個がある場合、ベース49の数値を取得します(オーバーフローを処理するサイズ10のベース10ベクトルとして)。

(1, 1, 45, 45, 40, 45, 45, 45, 45, 45)

「理想的な」ベース49の数値と比較すると、これは失敗します。

私のソリューションは、この数学的ソリューションを利用して、ループと比較を可能な限り回避します。long値を使用して各ベース49の数値をベース10の数値として保存し、ルックアップ配列を使用して、列/行/サブグリッドチェック値の計算中に各ベース49桁の「ファクター」を取得します。

Javaは簡潔に設計されていないため、簡潔なチェッカーを作成できると考えた唯一の方法は、数学的な構成に注意することでした。

どう考えているか教えてください。


1
実際、これは@ steve-verrillで言及されているのと同じ脆弱性に悩まされています。5つすべて、または合計45の数字のセットは、ソルバーを「だまします」。修正します。私はそれを打ち負かす方法を考えています。
プログラマー14年

私は最新のアップデートでこの脆弱性に対処しました。今、そのケース、およびそのタイプの他のすべてが対処されています。基本的に、10進数の各タイプの「カウント」を処理しないことは深刻な見落としでした。今、私はそのチェックを直接実行しますが、同じ数学的アプローチ(ベース49番号)を使用します。
プログラマー

ダン、謝辞をありがとう。私はそれを見て、なぜ私に通知されなかったのか疑問に思ったが、あなたは私の名前にダッシュを入れているのを見た。これはシステムを混乱させたようです。スペースを省略します。名前の表示方法を変更することを検討します。
レベルリバーセント14年

ああ、それはそれを説明しています。@steveverrillに感謝します-私はまだ物事を行うstackexchangeの方法に慣れています。とはいえ、sum-45原則の簡潔な悪用は見事に述べられました。それを克服するために私のソリューションを長くしましたが、それは人生です!
プログラマー14年



2

Perl、193バイト

for(@x=1..9){$i=$_-1;@y=();push@y,$a[$i][$_-1]for@x;@y=sort@y;$r+=@y~~@x;@y=();push@y,$a[3*int($i/3)+$_/3][3*($i%3)+$_%3]for 0..8;@y=sort@y;$r+=@y~~@x}for(@a){@y=sort@$_;$r+=@y~~@x}exit($r!=27)

入力は配列形式で期待されます。

@a=(
    [1,2,3,4,5,6,7,8,9],
    [4,5,6,7,8,9,1,2,3],
    [7,8,9,1,2,3,4,5,6],
    [2,3,1,5,6,4,8,9,7],
    [5,6,4,8,9,7,2,3,1],
    [8,9,7,2,3,1,5,6,4],
    [3,1,2,6,4,5,9,7,8],
    [6,4,5,9,7,8,3,1,2],
    [9,7,8,3,1,2,6,4,5]
);

終了コードは0で@aあり、解決策である場合は0 1が返されます。

ゴルフされていないバージョン:

@x = (1..9);
for (@x) {
    $i = $_ - 1;
    # columns
    @y = ();
    for (@x) {
        push @y, $a[$i][$_-1];
    }
    @y = sort @y;
    $r += @y ~~ @x;
    # sub arrays
    @y = ();
    for (0..8) {
        push @y, $a[ 3 * int($i / 3) + $_ / 3 ][ 3 * ($i % 3) + $_ % 3 ];
    }
    @y = sort @y;
    $r += @y ~~ @x
}
# rows
for (@a) {
    @y = sort @$_;
    $r += @y ~~ @x
}
exit ($r != 27);

9行、9列、9サブ配列のそれぞれが、ソートされた配列に入れられ、配列と一致するかどうかがチェックされます(1..9)$r有効な解決のために合計が27になる必要のある一致が成功するたびに、番号が増分されます。


2

J 52 54

-.*/,(9=#)@~.@,"2(0 3 16 A.i.4)&|:(4#3)($,)".;._2]0 :0

コマンドラインに貼り付けられた引数を取り、次のように)で終了します:

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 5
)

渡された場合は1、そうでない場合は0を返します。

内部的には、9x9グリッドを3x3x3x3グリッドに変換し、軸上でいくつかの順列を実行して、最後の2次元で必要な単位(行、線、ボックス)を取得します。

その後、各ユニットに9つの一意の値があることを確認します。

おそらく完璧にはほど遠いが、すでに大部分を打ち負かしている;-)


一見すると、あなたが他の人の一部と同じ要件によってキャッチされてきた....あなたのリターンが失敗のために非ゼロ、0パスのための...逆転されなければならない
デビッド・ウィルキンス

パスの0はばかげています。Booleがtrueに1、falseに0を選択した理由があります。しかし、あなたは正しい。2文字を追加します。
jpjacobs 14年

ブール値ではなく、終了ステータスと考えてください
デビッドウィルキンス14年

それが機能するので、私はあなたの答えを選んでいます。あなたは規則に従い、あなたのプログラムは非常に短いです。ありがとう!
デビッドウィルキンス

いやいやいや...実際には、あなたより短いGolfscriptの答えを選ばないことを正当化することはできません...しかし、2位の称賛
デイヴィッド・ウィルキンス

2

Mathematica、84 79文字

f=Tr[Norm[Sort@#-Range@9]&/@Join[#,Thread@#,Flatten/@Join@@#~Partition~{3,3}]]&

例:

f[{{1,2,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

0

f[{{2,1,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

2

f[{{0,2,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

3


3番目の出力例:3常に無効な入力を示していますか、それとも失敗したソリューションへの応答ですか?
デビッドウィルキンス14年

2

Javascript ES6、150文字

入力をデリミタなしの81文字の文字列として受け取ります。

s=>s.match("^(?=(#.{0,8}#.{9})+$)(?=(#(.{9}){0,8}#.){9})((#.?.?(.{9}){0,2}#...){3}.{18})+$".replace(/#(.*?)#/g,"123456789".replace(/./g,"(?=$$1$&)")))

関数はnull、負の回答として返され、最初の要素に元の文字列が正の配列として返されます。!!関数の先頭に追加することにより、boolに変更できます。

テスト(詳細は関連するチャレンジを参照):

f=s=>s.match("^(?=(#.{0,8}#.{9})+$)(?=(#(.{9}){0,8}#.){9})((#.?.?(.{9}){0,2}#...){3}.{18})+$".replace(/#(.*?)#/g,"123456789".replace(/./g,"(?=$$1$&)")))
;`123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298`
.split`
`.every(f)
&&
`519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825`
.split`
`.every(s => !f(s))

それは1つのばかげた正規表現です...すばらしい仕事です。
ETHproductions 16

2

R、63 50バイト

入力mが数字の9x9行列であると仮定します。

all(apply(m,1,match,x=1:9),apply(m,2,match,x=1:9))

私は、さらにゴルフをすることが可能であったことは正しかった。

説明:

    apply(m,1,match,x=1:9),

を取得しm、各行にmatch関数を適用します。x=1:9に渡す引数をさらに指定しますmatchxはデフォルトの最初の位置引数であるため、各行は2番目の引数位置に配置されtableます。関数matchxinの インスタンスを探しますtable。この場合、1:9各行で(1〜9の数字)を探しています。のそれぞれについて1:9、その番号が見つかった場合(または見つからなかった場合)を返しますTRUE(またはFALSE)。

したがって、これにより81個のブール値のシリーズが生成されます。

                           apply(m,2,match,x=1:9)

入力の列ごとに上記を繰り返します。

all(                                             )

最後に、allブール値のリストのすべての要素がであるかどうかを確認しますTRUE。これは、解が正しい場合にのみ当てはまります(つまり、各数値1:9は各列と各行に1回だけ存在します)。

古いアプローチ:

for(i in 1:2)F=F+apply(m,i,function(x)sort(x)==1:9);sum(F)==162

各行を取得してソートし、それをと比較し[1, 2, ... 9]ます。正しい行は正確に一致する必要があります。その後、各列に対して同じことを行います。合計で、162個の完全一致が必要です。これは、最終部分がチェックするものです。ここでさらにゴルフをする可能性があります...


列と行をチェックしているように見えますが、ボックスはチェックしていないようです
...-JayCe

1

ハスケル-175

import Data.List
c=concat
m=map
q=[1..9]
w=length.c.m (\x->(x\\q)++(q\\x))
b x=c.m(take 3.drop(3*mod x 3)).take 3.drop(3*div x 3)
v i=sum$m(w)[i,transpose i,[b x i|x<-[0..8]]]

関数vは呼び出すものです。リストに対して各行、列、ブロックの差を取得し、[1..9]それらの差リストの長さを合計することで機能します。

サンプルの数独を使用したデモ:

*Main> :l so-22443.hs 
[1 of 1] Compiling Main             ( so-22443.hs, interpreted )
Ok, modules loaded: Main.
*Main> v [[1,2,3,4,5,6,7,8,9],[4,5,6,7,8,9,1,2,3],[7,8,9,1,2,3,4,5,6],[2,3,1,5,6,4,8,9,7],[5,6,4,8,9,7,2,3,1],[8,9,7,2,3,1,5,6,4],[3,1,2,6,4,5,9,7,8],[6,4,5,9,7,8,3,1,2],[9,7,8,3,1,2,6,4,5]]
0

1

Javascript-149文字

r=[];c=[];g=[];for(i=9;i;)r[o=--i]=c[i]=g[i]=36;for(x in a)for(y in z=a[x]){r[v=z[y]-1]-=y;c[v]-=x;g[v]-=3*(x/3|0)+y/3|0}for(i in r)o|=r[i]|c[i]|g[i]

配列aが存在することを期待し、成功した場合oは出力用の変数を作成し、0そうでない場合はゼロ以外の変数を作成します。

各行、列、および3 * 3グリッドで各値が発生する位置の合計が36(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)に等しいことを確認することで機能します。

テスト中

a=[
    [1,2,3, 4,5,6, 7,8,9],
    [4,5,6, 7,8,9, 1,2,3],
    [7,8,9, 1,2,3, 4,5,6],

    [2,3,1, 5,6,4, 8,9,7],
    [5,6,4, 8,9,7, 2,3,1],
    [8,9,7, 2,3,1, 5,6,4],

    [3,1,2, 6,4,5, 9,7,8],
    [6,4,5, 9,7,8, 3,1,2],
    [9,7,8, 3,1,2, 6,4,5]
  ];

「o = 0」を与える

a=[
    [1,2,3, 4,5,6, 7,8,9],
    [4,5,6, 7,8,9, 1,2,3],
    [7,8,9, 1,2,3, 4,5,6],

    [2,3,1, 5,6,4, 8,9,7],
    [5,6,4, 8,9,7, 2,3,1],
    [8,9,7, 2,3,1, 5,6,4],

    [3,1,2, 6,4,5, 9,7,8],
    [6,4,5, 9,7,8, 3,1,2],
    [9,7,8, 3,1,2, 6,5,4]
  ];

(最後の2桁が入れ替わった)

与える o=-1

a=[
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],

    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],

    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5]
  ];

与える o=-284


1

ハスケル、121 130 127バイト(87 Lambdabot)

import Data.List
import Data.List.Split
c=concat
t=transpose
k=chunksOf
p x=all(==[1..9])$(sort<$>)=<<[x,t x,k 9.c.c.t$k 3<$>x]

使用:

-- k 9.c.c.t$k 3<$> x = chunksOf 9 $ concat $ concat $ transpose $ map chunksOf 3 x

let ts = k 9$[10*a+b|a<-[1..9],b<-[1..9]] --yep, this is ugly
in k 9.c.c.t$k 3<$>ts
-- prints:
--[[11,12,13,21,22,23,31,32,33],[41,42,43,51,52,53,61,62,63],[71,72,73,81,82,83,91,92,93],[14,15,16,24,25,26,34,35,36],[44,45,46,54,55,56,64,65,66],[74,75,76,84,85,86,94,95,96],[17,18,19,27,28,29,37,38,39],[47,48,49,57,58,59,67,68,69],[77,78,79,87,88,89,97,98,99]]

LambdabotはデフォルトでData.ListとData.List.Splitをロードします(BlackCapのソリューションはチェックボックスをオンにするとは思わない)。

改善のためのアイデアを歓迎

//編集:
失敗しました:) //編集:BlackCapで3バイト保存


そうです、行と列をチェックするだけでは不十分であることに気づきませんでした。
BlackCap16年

まあ、私も台無しに:)
michi7x7

1
あなたは置き換えることができ(map sort)(sort<$>)
BlackCap

1
.c$(sort<$>)<$>$(sort<$>)=<<
BlackCap

ああ、私のことを覚えておくべきだった2
michi7x7


0

Clojure、151バイト

かなり長いですが、他の人も同じようです。また、セットの和集合にはが必要なのも面倒なrequireので、代わりにベクトルの連結を使用しました。

各行と列を反復処理し、値が1〜9の場合、行、列、および3x3セルの3つのベクトルを出力します。成功すると0を返します。nilそれ以外の場合、2つの余分な文字が失敗すると1を返します。1から9以外の数値を返すnilことにより処理しますが、非整数値などの他の異常ではクラッシュします。商は0-2であるため、値を使用して89セル値と行および列を区別しても安全です。

(fn[s](if(= 243(count(set(apply concat(for[i(range 9)j(range 9)](let[v(nth(nth s i)j)q #(quot % 3)](if(<= 1 v 9)[[8 v i][9 v j][(q i)(q j)v]])))))))0))

入力は、ベクトルのネストされたベクトルです(そのためnth)。

(def sudoku [[1 2 3 4 5 6 7 8 9]
             [4 5 6 7 8 9 1 2 3] 
             [7 8 9 1 2 3 4 5 6] 
             [2 3 1 5 6 4 8 9 7] 
             [5 6 4 8 9 7 2 3 1] 
             [8 9 7 2 3 1 5 6 4] 
             [3 1 2 6 4 5 9 7 8] 
             [6 4 5 9 7 8 3 1 2] 
             [9 7 8 3 1 2 6 4 5]])

ゴルフをしていない:

(defn f [s]
  (->> (for [i (range 9) j (range 9)]
         (let [v (-> s (nth i) (nth j)) q #(quot % 3)]
           (if (<= 1 v 9)
             [[:row v i] [:col v j] [:cell [(q i) (q j)] v]])))
    (apply concat)
    set
    count
    (#(if (= 243 %) :pass :fail))))

0

PHP、196 190バイト

while($i<9){for($b=$c=$k=$y="";$y++<9;)$b.=($a=$argv)[$y][$i];for(;$k<3;)$c.=substr($a[++$k+$i-$i%3],$i%3*3,3);if(($u=count_chars)($a[++$i],3)<($d=123456789)|$u($b,3)<$d|$u($c,3)<$d)die(1);}

プログラムは、9つの個別のコマンドライン引数(グリッドの各行に1桁の数字列)を取ります。無効な場合
1(エラー0)、有効な場合は(ok)で終了します。

で実行しphp -nr '<code>' <row1> <row2> ...ます。

壊す

while($i<9)
{
    for($b=$c=$k=$y="";$y++<9;)$b.=($a=$argv)[$y][$i];  // column to string
    for(;$k++<3;)$c.=substr($a[$i-$i%3+$k],$i%3*3,3);   // sub-grid to string
    if(($u=count_chars)($a[++$i],3)<($d=123456789)      // check row
        |$u($b,3)<$d                                    // check column
        |$u($c,3)<$d                                    // check sub-grid
    )die(1);                                            // test failed: exit with 1
}

説明

count_chars文字列内の文字をカウントし、通常、キーとしてasciiコードを、値として文字カウントを含む配列を作成します。ただし、3モードパラメータとして、文字からソートされた文字列を作成します。そして、それは、必要な桁の数字と簡単に比較できます。

比較では重複をチェックするだけでなく、無効な文字のチェックも含まれます。そして、それだけ<でなく、!=、これは数値比較であるためです。PHPは文字列を可能な限り数値として解釈します。123e567890x3456789または類似の文字は表示できません。文字がソートされているためです。もちろん、数字が欠落している純粋な整数は123456789... よりも小さくなります.23456789

$a=$argv1バイト、$d=1234567899 バイト、$u=count_chars13 バイトを保存します。


-1

C#-306 298 288文字

次のコンソールプログラムを使用して、チェック機能を呼び出しました。

static void Main(string[] args)
    {
        int[,] i={{1,2,3,4,5,6,7,8,9},
             {4,5,6,7,8,9,1,2,3},
             {7,8,9,1,2,3,4,5,6},
             {2,3,1,5,6,4,8,9,7},
             {5,6,4,8,9,7,2,3,1},
             {8,9,7,2,3,1,5,6,4},
             {3,1,2,6,4,5,9,7,8},
             {6,4,5,9,7,8,3,1,2},
             {9,7,8,3,1,2,6,4,5}
            };

            Console.Write(P(i).ToString());
    }

これは、配列を初期化し、チェック関数Pに渡すだけです。

チェック機能は次のとおりです(ゴルフ形式)。

private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];for(int p=0;p<9;p++){r[p]=45;c[p]=45;g[p]=45;}for(int y=0;y<9;y++){for(int x=0;x<9;x++){r[y]-=i[x,y];c[x]-=i[x,y];int k=(x/3)+((y/3)*3);g[k]-=i[x,y];}}for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}

または完全にレイアウトされた形式で。

    private static int P(int[,] i)
    {
        int[] r = new int[9],c = new int[9],g = new int[9];
        for (int p = 0; p < 9; p++)
        {
            r[p] = 45;
            c[p] = 45;
            g[p] = 45;
        }

        for (int y = 0; y < 9; y++)
        {
            for (int x = 0; x < 9; x++)
            {
                r[y] -= i[x, y];

                c[x] -= i[x, y];

                int k = (x / 3) + ((y / 3) * 3);
                g[k] -= i[x, y];
            }
        }

        for (int p = 0; p < 9; p++)
            if (r[p] > 0 | c[p] > 0 | g[p] > 0) return 1;

        return 0;
    }

これは、すべての列、行、およびサブグリッドを合計45まで追加するという考えを使用しています。入力配列を使用して、行、列、およびサブグリッドから各位置の値を減算します。完了すると、行、列、またはサブグリッドにまだ値がないことを確認します。

要求されたとおり、配列が有効な数独ソリューションである場合は0を返し、そうでない場合はゼロ以外(1)を返します。


private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];代わりに使用していくつかの文字を保存できると思います。(閉じ角かっこの後のスペースの削除に注意してください]。)また、よくわかりませんが、を取り除くことができると思いますprivate static
user12205 14

また、最後の部分では、Cでは一部のブレースを削除できます。つまりfor(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}、C#で機能するかどうかはわかりません。(私は実際にC#を知らない)
user12205

@ace-あなたの提案に基づいていくつかの機能強化を行いました。298文字になりました。
ウィル

@aceからのコメントに基づいて、別の10文字を削除しました。
ウィル

1
番号5でいっぱいの配列ではどうなりますか?すべての行、列、四角は45まで追加
レベル川セント
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.