Erstellen Sie eine Sudoku-Lösung CHECKER

21

Erstellen Sie eine Sudoku-Lösung CHECKER

Es gibt unzählige Sudoku-LÖSER hier, aber ich möchte, dass Sie eine Lösung erstellen, die so klein wie möglich ist (Code-Golf).

  • Ein gültiger Eintrag kann entweder ein 9x9-Array als Argument verwenden (als Referenz übergeben, in der Befehlszeile serialisiert oder wie auch immer Sie es verwenden möchten) oder eine Eingabedatei akzeptieren, die neun Zeilen mit neun Zahlen für das endgültige Raster enthält . Beispiele für Eingaben finden Sie weiter unten.

  • Gültige Eingaben sollten Zahlen zur Basis 10 (1-9) sein.

  • Fehlende, leere, zusätzliche, nicht numerische Positionen oder Positionen mit Zahlen außerhalb von 1-9 sollten als ungültige Eingabe zurückgewiesen werden, indem ein Ergebnis ungleich Null zurückgegeben wird, ein Fehler gedruckt wird oder beides.

  • Ihr Programm muss testen, ob jede Zahl einmal pro Spalte, einmal pro Zeile und einmal pro 3x3-Teilraster erscheint. Wenn es erfolgreich ist, geben Sie "0" zurück, und wenn nicht, geben Sie ein Ergebnis ungleich Null zurück.

  • Die Verwendung externer Ressourcen (Websites usw.) ist zu vermeiden.

  • Wenn es sich bei Ihrer Lösung um ein eigenständiges Programm handelt, ist das Beenden mit dem Status "Bestanden" oder "Nicht bestanden" oder "Nicht bestanden" oder "Nicht bestanden" oder nicht bestanden "in Ordnung.

Lass die kleinste Antwort gewinnen!

Eingabebeispiele:

c array:

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}
                };

Datei:

123456789
456789123
789123456
231564897
564897231
897231564
312645978
645978312
978312645

Die 9 Teilraster:

+---+---+---+
|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|
+---+---+---+
David Wilkins
quelle

Antworten:

5

GolfScript, 39 Zeichen

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

Es nimmt ein Array von Arrays als Eingabe (siehe Online-Beispiel ) und gibt sie aus, 0wenn es ein gültiges Raster ist.

Kurze Erklärung des Codes

.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
Howard
quelle
Ich mag, dass die Ausgabe Ihres Codes ungleich Null aussagekräftiger ist als nur 1oder-1
David Wilkins
Ihre Antwort hat mir sehr gut gefallen, aber am Ende habe ich mich entschieden, keine Golfscript-Lösung zu wählen. Ich hoffe wirklich, Sie verstehen
David Wilkins
2
@DavidWilkins Eigentlich verstehe ich nicht - Sie haben die Regeln (!) Aufgestellt und nirgendwo angegeben, dass GolfScript nicht erlaubt war.
Howard
Ihr Punkt ist völlig gültig ... in Wahrheit habe ich nichts zu rechtfertigen, wenn Sie Ihre Antwort nicht wählen. Gut gespielt
David Wilkins
10

Python, 103

Ich hasse Sudoku.

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))))

So funktioniert es: Jede Zeile, Spalte und jeder Block muss eine Zahl von 1 bis 9 haben 0 <= i, j < 9. Die Zelle i,jbefindet sich also für jeden Block 3*floor(i/3) + floor(j/3). Somit sind 243 Anforderungen zu erfüllen. Ich mache jede Anforderung zu einem Tupel, ((item index,item type number),symbol)wobei item indexeine Zahl zwischen 0 und 8 (einschließlich), item type number0,1 oder 2 für Zeile, Spalte oder Block und symbolder Eintrag ist b[i][j].

Bearbeiten: Ich habe fälschlicherweise nicht nach gültigen Einträgen gesucht. Jetzt mache ich.

boothby
quelle
Ihr Programm sollte ausgegeben werden, 0wenn die Lösung erfolgreich ist, nichtTrue
David Wilkins
@ DavidWilkins was für eine seltsame Anforderung. Fest.
Stand
Sie, mein Herr, erhalten meine Stimme nur für die Art und Weise, wie Sie Ihre Antwort gestartet haben: D
Teun Pronk
9

APL (46)

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

Dies erfordert eine 9-mal-9-Matrix. Das Beispiel kann in TryAPL folgendermaßen eingegeben werden:

     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

Erläuterung:

  • ↓⍉⍵: Holen Sie sich die Spalten von ,
  • ↓⍵: Holen Sie sich die Reihen von ,
  • 3/3⌿3 3⍴Z←⍳9: Erstelle eine 3-mal-3-Matrix mit den Zahlen 1bis 9und dreifache jede Zahl in beide Richtungen, um eine 9-mal-9-Matrix mit den Zahlen 1für 9jede Gruppe zu erhalten.
  • Z∘.=: Für jede Zahl 1zu 9, eine Bitmaske für die gegebene Gruppe machen,
  • /∘(,⍵)¨: und maskiere mit jedem, gib die Gruppen von .
  • ∊∘Z¨: für jedes Sub-Array, sehen Sie, ob es die Zahlen 1zu enthält 9,
  • ∧/,↑: Nehmen Sie die Logik andaller dieser Zahlen zusammen.
Marinus
quelle
+1 Schön! Aber die 3 × 3-Gruppen können noch etwas mehr golfen. Zum Beispiel ist dies ↓9 9⍴1 3 2⍉3 3 9⍴⍵gleichbedeutend mit /∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9aber ziemlich kürzer. Ich bin sicher, dass es noch kürzere Formeln gibt.
Tobia
Sie können die Matrizen auch nach 1. Dimension verketten und am Ende eine einzelne Teilung durchführen:↓(9 9⍴1 3 2⍉3 3 9⍴⍵)⍪⍵⍪⍉⍵
Tobia
Es gibt einen Fehler: Dieser Code ∊∘Z¨testet, ob jedes Sub-Array (Zeile, Spalte oder Block) nur aus den Zahlen 1 bis 9 besteht. Er testet nicht, ob alle Zahlen dargestellt werden. Sie müssen so etwas wie Z∘.∊testen, dass jede Zahl in Z in jedem Sub-Array enthalten ist.
Tobia
Und das ∧/,↑kann gekürzt werden ∧/∊. Ich bin fertig, ich bin fertig! ;-)
Tobia
Sehr kompakt, aber Sie haben einen kritischen Punkt verpasst, den ich gleich sehen kann:If it passes, return "0" and if not, return a non-zero result.
David Wilkins
5

Java / C # - 183/180 181/178 173/170 Bytes

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;}

(Wechseln booleanzu boolfür C #)

Formatiert:

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;
}

Die Methode erstellt ein Array umit 27 Bitmasken, die die Ziffern in den neun Zeilen, Spalten und Quadraten darstellen.

Anschließend durchläuft es alle Zellen und führt die Operation aus 1 << a[x][y], um eine Bitmaske zu erstellen, die die Ziffer darstellt, und verknüpft damit die Spalten-, Zeilen- und Quadratbitmaske mit OR.

Anschließend werden alle 27 Bitmasken durchlaufen, wobei sichergestellt wird, dass sich alle zu 27594 addieren (1022 * 9, 1022 ist die Bitmaske für alle vorhandenen Ziffern 1-9). (Beachten Sie, dass der yWert 27603 lautet, da dieser Wert nach der Doppelschleife bereits 9 enthält.)

Bearbeiten: Versehentlich in einer gelassen %3, die nicht mehr benötigt wird.

Edit 2: Inspiriert von Bryce Wagners Kommentar wurde der Code etwas stärker komprimiert.

Smallhacker
quelle
Fast der gleiche Algorithmus in C # 149-Zeichen (jedoch nur, wenn Linq zulässig ist): bool s (int [] a) {int x = 0, y, j; var u = new int [27]; while (x ++ <(y = 9)) während (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;}
Bryce Wagner
@BryceWagner Linq wäre in der Tat nützlich. Meine Lösung ist jedoch für Java, wobei C # ein nachträglicher Gedanke ist (nicht einmal im ursprünglichen Beitrag erwähnt) und daher eine geringere Priorität hat. Ich habe auch eindimensionale Arrays für die Kompaktheit am Anfang verwendet, bevor ich mich dagegen entschieden habe (da die Beispiele zweidimensionale verwenden). Trotzdem hat Ihr Code mir ein paar Ideen gegeben, wie noch ein paar Bytes abgeschabt werden könnten. :)
Smallhacker
3

Python = 196

Nicht der Golfspieler, aber die Idee ist da. Sets sind ziemlich nützlich.

Tafel:

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]]

Programm:

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)
qwr
quelle
s / {1,2,3,4,5,6,7,8,9} / set (range (1,10)) / speichert 3 Zeichen.
MatrixFrog
In Python 3.5 können Sie verwenden n={*range(1,10)}, aber das ist neuer als die Herausforderung. Verwenden set(range(1,10))Sie stattdessen, wie MatrixFrog sagte.
mbomb007
3

Java - 385 306 328 260 Zeichen

Edit: Ich dummerweise die Anweisungen falsch verstanden , dass die Antwort hatte ein komplettes Programm sein. Da es sich nur um eine gültige Funktion handeln kann, habe ich sie umgeschrieben und zu einer Funktion verkleinert und meine Einführung in die Lösung entsprechend umgeschrieben.

Als Herausforderung für mich dachte ich, ich würde versuchen, den kleinsten Java-Lösungsprüfer zu entwickeln.

Um dies zu erreichen, gehe ich davon aus, dass das Sudoku-Puzzle als mehrdimensionales Java-Array übergeben wird:

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}});

Dann haben wir den eigentlichen Löser, der bei gültiger Lösung "0" zurückgibt, andernfalls "1".

Völlig Golf gespielt:

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;}

Lesbar:

    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;
    }

Wie funktioniert das? Ich erstelle einfach eine eigene Zahlenbasis mit einer ausreichenden Auflösung für jede Ziffer, sodass ich nur drei numerische Vergleiche durchführen muss, nachdem ich das Puzzle einmal durchlaufen habe, um zu wissen, ob es gültig ist. Ich habe Basis 49 für dieses Problem gewählt, aber jede Basis größer als 45 würde ausreichen.

Ein (hoffentlich) klares Beispiel: Stellen Sie sich vor, dass jede "Zeile" im Sudoku-Puzzle eine einzelne Ziffer in einer Basis-49-Zahl ist. Wir werden der Einfachheit halber jede Ziffer in der Zahl zur Basis 49 als Zahl zur Basis 10 in einem Vektor darstellen. Wenn also alle Zeilen "korrekt" sind, erwarten wir die folgende Basis-49-Zahl (als Basis-10-Vektor):

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

oder in eine einzelne Basis-10-Zahl umgewandelt: 1526637748041045

Befolgen Sie eine ähnliche Logik für alle Spalten und für die "Teilgitter". Jeder Wert, der letztendlich dieser "idealen Zahl" nicht entspricht, bedeutet, dass die Rätsellösung ungültig ist.

Bearbeiten, um die Sicherheitsanfälligkeit von all-5s und andere damit zusammenhängende Probleme zu lösen: Ich füge eine vierte Zahl zur Basis 49 hinzu, basierend auf der Idee, dass in jedem Rätsel 9 Zahlen enthalten sein sollten. Also addiere ich 5 zu jeder Ziffer in der Zahl zur Basis 49 für jedes Vorkommen der Zahl zur Basis 10, die den Index der Ziffer darstellt. Wenn es beispielsweise 10 9 und 9 8, 9 7, 8 6 und 9 von allen anderen gibt, erhalten Sie eine Basis-49-Zahl (als Basis-10-Vektor der Größe 10, um Überlauf zu behandeln):

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

Was im Vergleich zu unserer "idealen" Basis-49-Zahl scheitern wird.

Meine Lösung nutzt diese mathematische Lösung, um so viele Schleifen und Vergleiche wie möglich zu vermeiden. Ich verwende einfach einen longWert, um jede Basis-49-Zahl als Basis-10-Zahl zu speichern, und verwende ein Nachschlage-Array, um die "Faktoren" für jede Basis-49-Ziffer während der Spalten- / Zeilen- / Subgrid-Prüfwertberechnung zu erhalten.

Da Java nicht so konzipiert ist, dass es prägnant ist, dachte ich, ich könnte einen prägnanten Checker nur erstellen, wenn ich bei der mathematischen Konstruktion vorsichtig bin.

Lass mich wissen was du denkst.

ProgrammerDan
quelle
1
Tatsächlich leidet dies an der gleichen Sicherheitsanfälligkeit, die von @ steve-verrill erwähnt wird - alle 5en oder eine beliebige Anzahl von Zahlen, die sich auf 45 summieren, "täuschen" den Löser. Ich werde überarbeiten. Ich habe eine Idee, wie ich das schlagen kann.
ProgrammerDan
Ich habe diese Sicherheitsanfälligkeit in meinem letzten Update behoben. Nun wird dieser Fall und alle anderen seiner Art angesprochen. Grundsätzlich war es ein schwerwiegendes Versäumnis, sich nicht mit "Zählern" jeder Art von 10er-Basis zu befassen. Ich führe diese Prüfung jetzt direkt durch, aber unter Verwendung des gleichen mathematischen Ansatzes (Basis-49-Zahl).
ProgrammerDan
Dan, danke für die Anerkennung. Ich habe es gesehen und mich gefragt, warum ich nicht benachrichtigt wurde, aber ich sehe, dass Sie einen Strich in meinen Namen setzen. Dies scheint das System verwirrt zu haben. Lass einfach das Leerzeichen weg. Ich werde in Betracht ziehen, die Art und Weise zu ändern, in der mein Name angezeigt wird.
Level River St
Ahha, das erklärt es. Danke @steveverrill - ich gewöhne mich immer noch an die Art und Weise, wie Stapel ausgetauscht werden. Das heißt, Ihre prägnante Ausnutzung des Summen-45-Prinzips wurde brillant ausgedrückt. Ich habe meine Lösung länger gemacht, um sie zu überwinden, aber so ist das Leben!
ProgrammerDan
3

R 145

function(x)colSums(do.call(rbind,lapply(list(R<-row(b<-matrix(1,9,9)),C<-col(b),(R-1)%/%3+1+3*(C-1)%/%3),sapply,`==`,1:9))%*%c(2^(x-1))==511)==27

Den (mehr oder weniger) de-golfed Code finden Sie hier /programming//a/21691541/1201032 .

Flodel
quelle
Kannst du ein funktionierendes Beispiel für eine Site wie r-fiddle liefern? r-fiddle.org/#
David Wilkins
3

Haskell (Lambdabot), 65 Bytes

k x=and$(all$([1..9]==).sort)<$>[x,transpose x,join$chunksOf 3 x]
BlackCap
quelle
2

Perl, 193 Bytes

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)

Die Eingabe wird in Array-Form erwartet:

@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]
);

Der Exit-Code ist 0, wenn @aes sich um eine Lösung handelt, andernfalls 1wird zurückgegeben.

Ungolfed-Version:

@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);

Jede der 9 Zeilen, 9 Spalten und 9 Sub-Arrays wird in ein sortiertes Array gestellt und überprüft, ob es mit dem Array übereinstimmt (1..9). Die Zahl $rwird für jede erfolgreiche Übereinstimmung erhöht, die für eine gültige Lösung 27 ergeben muss.

Heiko Oberdiek
quelle
2

J 52 54

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

Nimmt das in die Kommandozeile eingefügte Argument und endet mit a) als:

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
)

Gibt 1 zurück, wenn bestanden, 0, wenn nicht.

Intern konvertiert es das 9x9-Raster in ein 3x3x3x3-Raster und führt einige Permutationen an den Achsen durch, um die gewünschte Einheit (Zeilen, Linien und Kästchen) in den letzten beiden Dimensionen zu erhalten.

Danach wird überprüft, ob jede Einheit 9 eindeutige Werte hat.

Wohl alles andere als perfekt, schlägt aber die Mehrheit schon ;-)

jpjacobs
quelle
Auf den ersten Blick haben Sie die gleichen Anforderungen wie einige der anderen ... Ihre Renditen sollten umgekehrt werden ... 0 für bestanden, ungleich Null für nicht bestanden
David Wilkins
0 für pass ist idiotisch. Es gibt einen Grund, warum Boole 1 für wahr und 0 für falsch gewählt hat. Aber Sie haben Recht. Fügt 2 Zeichen hinzu.
Jpjacobs
Stellen Sie es sich als Exit-Status vor, nicht als booleschen Wert
David Wilkins
Ich wähle deine Antwort, weil es funktioniert. Sie haben die Regeln befolgt und Ihr Programm ist sehr kurz. Vielen Dank!
David Wilkins
Nun, ich habe es geschafft ... In Wahrheit kann ich es nicht rechtfertigen, die Golfscript-Antwort nicht zu wählen, die kürzer ist als Ihre ... Aber ein dickes Lob für den 2. Platz
David Wilkins
2

Mathematica, 84 79 Zeichen

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

Beispiele:

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

Alephalpha
quelle
Ihr drittes Ausgabebeispiel: Zeigt 3immer ungültige Eingaben an, oder ist es manchmal eine Antwort auf eine fehlgeschlagene Lösung?
David Wilkins
2

Javascript ES6, 150 Zeichen

Nimmt die Eingabe als Zeichenfolge mit 81 Zeichen ohne Begrenzer auf.

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

Die Funktion gibt nulleine negative Antwort und ein Array mit der ursprünglichen Zeichenfolge im ersten Element als positive Antwort zurück. Kann durch Hinzufügen !!zu der beginnenden Funktion in bool geändert werden .

Test (siehe verwandte Challenge für mehr Details):

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))
Qwertiy
quelle
Das ist eine lächerliche Regex ... Erstaunliche Arbeit.
ETHproductions
2

R 63 50 Bytes

Angenommen, die Eingabe mist eine 9x9-Zahlenmatrix.

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

Ich hatte Recht, dass weiteres Golfen möglich war.

Erläuterung:

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

Nehmen Sie mund wenden Sie für jede Zeile die matchFunktion an. Wir geben ein weiteres Argument x=1:9an, an das weitergeleitet werden soll match. xist das Standardargument für die erste Position, und daher wird jede Zeile an der zweiten Argumentposition platziert, d. h table. Die Funktion matchsucht nach Instanzen von xin table. In diesem Fall wird 1:9in jeder Zeile nach (den Nummern 1 bis 9) gesucht . Für jedes von 1:9wird zurückgegeben TRUE(oder FALSE), ob diese Nummer gefunden wird (oder nicht).

Dies ergibt also eine Reihe von 81 Booleschen Werten.

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

Wiederholen Sie die obigen Schritte für jede Spalte der Eingabe.

all(                                             )

allPrüft abschließend , ob jedes Element der Liste der Booleschen Werte vorhanden ist TRUE. Dies ist genau dann der Fall, wenn die Lösung korrekt ist (dh jede Zahl 1:9ist in jeder Spalte und jeder Zeile nur einmal vorhanden).

Alter Ansatz:

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

Es nimmt jede Zeile, sortiert sie und vergleicht sie dann mit [1, 2, ... 9]. Eine richtige Zeile sollte genau übereinstimmen. Dann macht es für jede Spalte dasselbe. Insgesamt sollten wir 162 exakte Übereinstimmungen haben, worauf der letzte Teil prüft. Hier besteht wahrscheinlich noch Spielraum für weiteres Golfen ...

rturnbull
quelle
Es sieht so aus, als ob Sie nach Spalten und Zeilen
suchen
1

Haskell - 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]]]

Die Funktion muss vaufgerufen werden. Es funktioniert, indem die Differenz jeder Zeile, Spalte und jedes Blocks gegen die Liste [1..9]abgerufen und die Länge dieser Differenzlisten aufsummiert wird.

Demo am Beispiel Sudoku:

*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
TimWolla
quelle
1

Javascript - 149 Zeichen

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]

Erwartet, dass ein Array avorhanden ist, und erstellt eine Variable ofür die Ausgabe, die 0bei Erfolg und ansonsten ungleich Null ist.

Überprüfen Sie, ob die Summe der Positionen, an denen die einzelnen Werte für jede Zeile, Spalte und jedes 3 * 3-Raster auftreten, 36 ergibt (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8).

Testen

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]
  ];

Gibt '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]
  ];

(Die letzten 2 Ziffern wurden getauscht.)

Gibt 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]
  ];

Gibt o=-284

MT0
quelle
1

Haskell, 121 130 127 Bytes (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]

Verwendet:

-- 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 lädt standardmäßig Data.List und Data.List.Split (ich glaube nicht, dass die BlackCap-Lösung die Kontrollkästchen aktiviert).

Verbesserungsvorschläge willkommen

// Edit: Ich habe es vermasselt :)
// Edit: 3 Bytes, die von BlackCap gespeichert wurden

michi7x7
quelle
Sie haben Recht, ich habe nicht bemerkt, dass das Überprüfen der Zeilen und Spalten nicht ausreicht.
BlackCap
Nun
1
Sie können (map sort)mit(sort<$>)
BlackCap
1
Und .c$(sort<$>)<$>mit$(sort<$>)=<<
BlackCap
Oh mein
Gott
0

Clojure, 151 Bytes

Ziemlich lange, aber andere scheinen es auch zu sein. Ebenfalls ärgerlich, dass die Vereinigung von Mengen ein erfordert require, weshalb ich stattdessen ein Konzentrat von Vektoren verwendet habe.

Durchläuft jede Zeile und Spalte und gibt bei einem Wert zwischen 1 und 9 drei Vektoren aus, einen für Zeile, Spalte und 3x3-Zelle. Gibt bei Erfolg 0 zurück, nilandernfalls könnten zwei zusätzliche Zeichen bei Fehlschlagen 1 zurückgeben. Behandelt Zahlen außerhalb von 1 bis 9, indem sie zurückgegeben nilwerden, stürzt jedoch bei anderen Anomalien ab, z. B. bei nicht ganzzahligen Werten. Quotienten sind 0 - 2, sodass es sicher ist, Werte zu verwenden 8und 9Zellenwerte von Zeilen und Spalten zu unterscheiden.

(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))

Die Eingabe ist ein verschachtelter Vektor von Vektoren (so dass nthfunktioniert):

(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]])

Ungolfed:

(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))))
NikoNyrh
quelle
0

PHP 196 190 Bytes

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);}

Das Programm verwendet 9 separate Befehlszeilenargumente (eine Ziffernfolge für jede Zeile des Rasters).
Beendet mit 1(Fehler) für ungültig, 0(OK) für gültig.

Laufen Sie mit php -nr '<code>' <row1> <row2> ....

Nervenzusammenbruch

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
}

Erläuterung

count_charsZählt Zeichen in einer Zeichenfolge und erstellt normalerweise ein Array mit ASCII-Codes als Schlüssel und die Anzahl der Zeichen als Werte. Mit dem 3Parameter mode wird jedoch eine sortierte Zeichenfolge aus den Zeichen erstellt. und das kann man leicht mit der nummer mit den gewünschten ziffern vergleichen.

Der Vergleich prüft nicht nur auf Duplikate, sondern auch auf ungültige Zeichen. Und es erfordert nur <, nicht !=, weil dies ein numerischer Vergleich ist: PHP interpretiert den String so weit wie möglich als Zahl. 123e56789, 0x3456789oder ähnliches kann nicht angezeigt werden, da die Zeichen sortiert sind. und jede reine ganze Zahl mit einer fehlenden Ziffer ist kleiner als 123456789... und .23456789natürlich auch.

$a=$argvSpeichert ein Byte, $d=123456789speichert neun und $u=count_charsspeichert 13.

Titus
quelle
-1

C # - 306 298 288 Zeichen

Das folgende Konsolenprogramm wurde zum Aufrufen der Überprüfungsfunktion verwendet.

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());
    }

Dazu muss nur das Array initialisiert und an die Prüffunktion P übergeben werden.

Die Überprüfungsfunktion ist wie folgt (in Golf-Form);

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;}

Oder in vollständiger Form;

    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;
    }

Dabei wird die Idee zugrunde gelegt, dass alle Spalten, Zeilen und Teilraster 45 ergeben sollten. Dabei wird das Eingabearray durchlaufen und der Wert jeder Position von den Zeilen, Spalten und Teilrastern subtrahiert. Nach Abschluss wird überprüft, ob in keiner der Zeilen, Spalten oder Teilraster noch ein Wert vorhanden ist.

Nach Aufforderung wird eine 0 zurückgegeben, wenn das Array eine gültige Sudoku-Lösung ist und nicht Null (1), wenn dies nicht der Fall ist.

Wille
quelle
Ich denke, Sie können einige Zeichen sparen, indem Sie private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];stattdessen verwenden. (Beachten Sie das Entfernen des Leerzeichens nach der engen eckigen Klammer ].) Ich bin mir auch nicht sicher, aber ich denke, Sie können das entfernen private static.
user12205
Außerdem können wir im letzten Teil in C einige geschweifte Klammern entfernen, dh wir sind for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}nicht sicher, ob es in C # funktioniert. (C # kenne ich eigentlich nicht)
user12205
@ace - Ich habe verschiedene Verbesserungen vorgenommen, die auf Ihren Vorschlägen basieren. Jetzt auf 298 Zeichen.
Will
Weitere 10 Zeichen basierend auf Kommentaren von @ace abgeschnitten.
Will
1
Was passiert mit einem Array voller 5er? Alle Zeilen, Spalten und Quadrate addieren sich zu 45.
Level River St