Utwórz rozwiązanie sudoku CHECKER


21

Utwórz kontroler sudoku

Jest tu mnóstwo Sudoku SOLVERS, ale chcę, żebyś stworzył narzędzie KONTROLER tak małe, jak to tylko możliwe (kod-golf).

  • Prawidłowy wpis będzie mógł przyjąć tablicę 9x9 jako argument (przekazany przez odniesienie, zserializowany w wierszu polecenia lub jakkolwiek chcesz go wziąć) lub zaakceptować plik wejściowy, który składa się z dziewięciu wierszy po dziewięć liczb dla ostatecznej siatki . Zobacz przykłady danych wejściowych poniżej.

  • Prawidłowe dane wejściowe powinny być liczbami podstawowymi 10 (1-9)

  • Brakujące, puste, dodatkowe, nienumeryczne pozycje lub pozycje o liczbach spoza 1-9 należy odrzucić jako nieprawidłowe dane wejściowe, zwracając wynik niezerowy, drukując błąd lub oba.

  • Twój program musi sprawdzić, czy każda liczba pojawia się raz na kolumnę, raz na linię i raz na podsiatkę 3x3. Jeśli przejdzie pomyślnie, zwróć „0”, a jeśli nie, zwróć wynik niezerowy.

  • Należy unikać korzystania z zasobów zewnętrznych (stron internetowych itp.).

  • Jeśli Twoje rozwiązanie jest samodzielnym programem, wyjście ze statusem wyjścia lub drukowanie, „0” lub niezerowe odpowiednio dla „Pass” lub „Fail” jest w porządku.

Niech wygra najmniejsza odpowiedź!

Przykłady wprowadzania:

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

plik:

123456789
456789123
789123456
231564897
564897231
897231564
312645978
645978312
978312645

9 podsiatek:

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

Odpowiedzi:


5

GolfScript, 39 znaków

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

Pobiera tablicę tablic jako dane wejściowe (patrz przykład online ) i dane wyjściowe, 0jeśli jest to poprawna siatka.

Krótkie wyjaśnienie kodu

.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

Podoba mi się, że niezerowe wyjście twojego kodu jest bardziej znaczące niż tylko 1lub-1
David Wilkins

Naprawdę podobała mi się twoja odpowiedź, ale ostatecznie zdecydowałem się nie stosować rozwiązania w golfa. Naprawdę mam nadzieję, że rozumiesz
David Wilkins,

2
@DavidWilkins Właściwie nie rozumiem - ustaliłeś zasady (!) I nigdzie nie stwierdziłeś, że GolfScript jest niedozwolony.
Howard

Twoja uwaga jest całkowicie aktualna ... tak naprawdę nie mam nic, co uzasadniałoby, że nie wybrałem twojej odpowiedzi. Dobrze zagrane
David Wilkins

10

Python, 103

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

Jak to działa: każdy wiersz, kolumna i blok musi mieć każdą liczbę od 1 do 9. Tak więc dla każdego 0 <= i, j < 9komórki i,jjest w bloku 3*floor(i/3) + floor(j/3). Tak więc należy spełnić 243 wymagania. Robię każde wymaganie krotką, ((item index,item type number),symbol)gdzie item indexjest liczbą od 0 do 8 (włącznie), item type numberwynosi 0,1 lub 2, aby oznaczać odpowiednio wiersz, kolumnę lub blok i symboljest wpisemb[i][j] .

Edycja: przez pomyłkę nie sprawdziłem poprawnych wpisów. Teraz ja robię.


Twój program powinien wypisać, 0jeśli rozwiązanie się powiedzie, a nieTrue
David Wilkins

@DavidWilkins co za dziwny wymóg. Naprawiony.
stoisko

Proszę pana o głos na sposób, w jaki zaczął pan swoją odpowiedź: D
Teun Pronk

9

APL (46)

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

Wymaga to matrycy 9 na 9. Przykład można wprowadzić na TryAPL w następujący sposób:

     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

Wyjaśnienie:

  • ↓⍉⍵: pobierz kolumny ,
  • ↓⍵: uzyskaj rzędy ,
  • 3/3⌿3 3⍴Z←⍳9:, Aby matryca 3-o-3 zawierającym cyfry 1z 9, a następnie potrójnie numer w obu kierunkach, dając matrycy 9-by-9 z numerami 1na 9co wskazuje każdej grupie
  • Z∘.=: Dla każdego numeru 1do 9, zrobić maskę bitową dla danej grupy,
  • /∘(,⍵)¨: i maska za każdym razem, podając grupy .
  • ∊∘Z¨: dla każdej pod-tablicy sprawdź, czy zawiera ona liczby 1 się 9,
  • ∧/,↑: weź logikę andwszystkich tych liczb razem.

+1 fajnie! Ale grupy 3 × 3 można jeszcze pograć w golfa. Na przykład ↓9 9⍴1 3 2⍉3 3 9⍴⍵jest to równoważne, /∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9ale dość krótsze. Jestem pewien, że istnieją jeszcze krótsze formuły.
Tobia

Możesz także połączyć macierze według pierwszego wymiaru i wykonać pojedynczy podział na końcu:↓(9 9⍴1 3 2⍉3 3 9⍴⍵)⍪⍵⍪⍉⍵
Tobia

Wystąpił błąd: ten kod ∊∘Z¨sprawdza, czy każda podgrupa (wiersz, kolumna lub blok) składa się tylko z liczb od 1 do 9. To nie sprawdza, czy wszystkie liczby są reprezentowane. Musisz zrobić coś takiego, Z∘.∊który testuje, że każda liczba w Z jest zawarta w każdej pod-macierzy.
Tobia

I ∧/,↑można to skrócić ∧/∊. Skończyłem, skończyłem! ;-)
Tobia

Bardzo kompaktowy, ale przegapiłeś jeden krytyczny punkt, który od razu widzę:If it passes, return "0" and if not, return a non-zero result.
David Wilkins

5

Java / C # - 183/180 181/178 173/170 bajtów

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

(Zmień booleanna boolna C #)

Sformatowany:

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

Metoda tworzy tablicę uz 27 maskami bitowymi, reprezentującymi cyfry znalezione w dziewięciu wierszach, kolumnach i kwadratach.

Następnie iteruje wszystkie komórki, wykonując operację mającą na 1 << a[x][y]celu utworzenie maski bitowej reprezentującej cyfrę, a także jej kolumnę, wiersz i maskę bitową z nią.

Następnie iteruje wszystkie 27 masek bitowych, zapewniając, że sumują się one do 27594 (1022 * 9, 1022 to maska ​​bitowa dla wszystkich obecnych cyfr 1-9). (Zauważ, że ykończy się na 27603, ponieważ zawiera już 9 po podwójnej pętli).

Edycja: Przypadkowo pozostawiono w %3niepotrzebnym już miejscu.

Edycja 2: Zainspirowany komentarzem Bryce Wagner kod został nieco bardziej skompresowany.


Prawie ten sam algorytm w znakach C # 149 (ale tylko jeśli Linq jest dozwolony): 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;}
Bryce Wagner

@BryceWagner Linq rzeczywiście byłby użyteczny. Jednak moim rozwiązaniem jest Java z C # będącym późniejszą refleksją (nawet nie wspomnianą w oryginalnym poście), a zatem niższym priorytetem. Na początku użyłem również jednowymiarowych tablic dla zwięzłości, zanim zdecydowałem się na nie (jako przykłady wykorzystują dwuwymiarowe). Niemniej jednak twój kod dał mi kilka pomysłów na to, jak można zgolić jeszcze kilka bajtów. :)
Smallhacker

3

python = 196

Nie najbardziej golfowy, ale pomysł już istnieje. Zestawy są bardzo przydatne.

Deska:

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

Program:

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)) / zapisuje 3 znaki.
MatrixFrog

W Pythonie 3.5 możesz używać n={*range(1,10)}, ale jest to nowsza wersja niż wyzwanie. Zamiast tego użyj, set(range(1,10))jak powiedział MatrixFrog.
mbomb007,

3

Java - 385 306 328 260 znaków

Edycja: Niemądrze źle odczytałem instrukcje, że odpowiedź musi być kompletnym programem. Ponieważ może to być tylko poprawna funkcja, przepisałem i zminimalizowałem, aby być funkcją, i przepisałem moje wprowadzenie do rozwiązania, mając to na uwadze.

Tak więc, jako wyzwanie dla siebie, pomyślałem, że spróbuję stworzyć najmniejsze narzędzie do sprawdzania rozwiązań Java.

Aby to osiągnąć, zakładam, że łamigłówka sudoku zostanie przekazana jako wielowymiarowa tablica Java, taka jak:

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

Następnie mamy rzeczywisty solver, który zwraca „0”, jeśli prawidłowe rozwiązanie, „1”, jeśli nie.

W pełni golfa:

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

Czytelny:

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

Jak to działa? Zasadniczo po prostu tworzę własną bazę liczb z wystarczającą rozdzielczością w każdej cyfrze, że muszę tylko trzy porównania numeryczne po przejściu przez układankę raz, aby wiedzieć, czy jest poprawna. Wybrałem bazę 49 dla tego problemu, ale każda baza większa niż 45 byłaby wystarczająca.

(Mam nadzieję) jasny przykład: wyobraź sobie, że każdy „wiersz” w łamigłówce sudoku to jedna cyfra w liczbie bazowej 49. Dla uproszczenia będziemy reprezentować każdą cyfrę w liczbie base-49 jako liczbę base-10 w wektorze. Tak więc, jeśli wszystkie wiersze są „poprawne”, oczekujemy następującej liczby base-49 (jako wektora base-10):

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

lub przekonwertowany na jedną liczbę podstawową 10: 1526637748041045

Postępuj zgodnie z podobną logiką dla wszystkich kolumn i tak samo dla „podsiatek”. Każda wartość napotkana w końcowej analizie, która nie jest równa tej „idealnej liczbie”, oznacza, że ​​rozwiązanie układanki jest nieprawidłowe.

Edytuj, aby rozwiązać problem podatności na wszystkie 5 i inne powiązane problemy: Dodaję czwarty numer base-49, oparty na założeniu, że w każdej układance powinno być 9 liczb. Tak więc dodaję 5 do każdej cyfry liczby podstawowej-49 dla każdego wystąpienia liczby podstawowej-10, która reprezentuje indeks cyfry. Przykład: jeśli istnieje 10 9 i 9 8, 9 7, 8 6 i 9 wszystkich innych, otrzymasz liczbę podstawową 49 (jako wektor podstawy 10 wielkości 10, aby poradzić sobie z przepełnieniem):

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

Który zawiedzie w porównaniu z naszą „idealną” liczbą base-49.

Moje rozwiązanie wykorzystuje to matematyczne rozwiązanie, aby uniknąć jak największej liczby pętli i porównań. Po prostu używam longwartości do przechowywania każdej liczby base-49 jako liczby base-10 i używam tablicy odnośników, aby uzyskać „współczynniki” dla każdej cyfry base-49 podczas obliczania wartości kontrolnej kolumny / wiersza / podsiatki.

Ponieważ Java nie została zaprojektowana tak, aby była zwięzła, uważność w matematycznej konstrukcji była jedynym sposobem, w jaki doszłam do wniosku, że mogę zbudować zwięzły moduł sprawdzający.

Powiedz mi co myślisz.


1
W rzeczywistości ma to tę samą lukę, o której wspomina @ steve-verrill - wszystkie 5 lub dowolny zestaw liczb o wartości 45 „oszukają” solver. Zamierzam skorygować. Mam pomysł, jak to pokonać.
Programator

Tę lukę usunąłem w mojej najnowszej aktualizacji. Teraz ta sprawa została rozwiązana i wszystkie inne tego typu. Zasadniczo poważnym niedopatrzeniem było nie zajmowanie się „liczeniem” każdego rodzaju cyfr 10-bazowych. Teraz wykonuję tę kontrolę bezpośrednio, ale stosując to samo podejście matematyczne (liczba podstawowa 49).
Programator

Dan, dziękuję za uznanie. Widziałem to i zastanawiałem się, dlaczego mnie nie powiadomiono, ale widzę, że wstawiasz myśl w moim imieniu. Wydaje się, że wprowadziło to system w błąd. Po prostu pomiń przestrzeń. Zastanowię się nad zmianą sposobu wyświetlania mojego imienia.
Level River St

Ahha, to wyjaśnia. Dzięki @steveverrill - Nadal przyzwyczajam się do sposobu robienia wymiany stosów. To powiedziawszy, twoje zwięzłe wykorzystanie zasady sum-45 zostało genialnie stwierdzone. Wydłużyłem moje rozwiązanie, aby je pokonać, ale takie jest życie!
Programator


3

Haskell (Lambdabot), 65 bajtów

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

2

Perl, 193 bajtów

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)

Dane wejściowe są oczekiwane w postaci tablicowej:

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

Kod zakończenia wynosi 0, jeśli @ajest rozwiązaniem, w przeciwnym razie 1jest zwracany.

Wersja bez golfa:

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

Każdy z 9 wierszy, 9 kolumn i 9 tablic podrzędnych jest umieszczany w posortowanej tablicy i sprawdzany, czy pasuje do tablicy (1..9). Liczba $rjest zwiększana dla każdego udanego dopasowania, które musi zsumować do 27 dla prawidłowego rozwiązania.


2

J 52 54

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

Pobiera argument wklejony w linii poleceń, zakończony a) jako:

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
)

Zwraca 1, jeśli minął, 0 jeśli nie.

Wewnętrznie przekształca siatkę 9x9 w siatkę 3x3x3x3 i wykonuje pewne permutacje na osiach, aby uzyskać pożądaną jednostkę (rzędy, linie i pola) w ostatnich 2 wymiarach.

Po wykonaniu tej czynności sprawdza się, czy każda jednostka ma 9 unikalnych wartości.

Prawdopodobnie daleki od ideału, ale już bije większość ;-)


Na pierwszy rzut oka zostałeś przyłapany na tych samych wymaganiach, co niektóre inne ... Twoje zwroty powinny zostać odwrócone ... 0 dla passa, niezerowe dla fail
David Wilkins

0 za podanie jest idiotyczne. Istnieje powód, dla którego Boole wybrał 1 dla wartości true i 0 dla wartości false. Ale masz rację. Dodaje 2 znaki.
jpjacobs,

Pomyśl o tym jako o statusie wyjścia, a nie o wartości logicznej
David Wilkins,

Wybieram twoją odpowiedź, ponieważ działa. Przestrzegałeś zasad, a twój program jest bardzo krótki. Dzięki!
David Wilkins,

Cóż, naciągnąłem ... Prawdę mówiąc, nie mogę usprawiedliwić, że nie wybrałem odpowiedzi Golfscript, która jest krótsza niż twoja ... Ale pochwały za 2 miejsce
David Wilkins

2

Mathematica, 84 79 znaków

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

Przykłady:

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)


Twój trzeci przykład wyjściowy: 3zawsze wskazuje na nieprawidłowe dane wejściowe, czy też czasami stanowi odpowiedź na nieudane rozwiązanie?
David Wilkins,

2

JavaScript ES6, 150 znaków

Pobiera dane wejściowe jako ciąg znaków o długości 81 znaków bez żadnych ograniczników.

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

Funkcja zwraca nullodpowiedź negatywną, a tablica z oryginalnym łańcuchem w pierwszym elemencie jako dodatnia. Można zmienić na bool, dodając !!na początku funkcji.

Test (zobacz powiązane wyzwanie, aby uzyskać więcej szczegółów):

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

To jedno śmieszne wyrażenie regularne ... Niesamowita praca.
ETHproductions

2

R, 63 50 bajtów

Przyjmuje dane wejściowe m to macierz liczb 9x9.

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

Miałem rację, że dalsza gra w golfa jest możliwa.

Wyjaśnienie:

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

Weź mi dla każdego wiersza zastosuj matchfunkcję. Podajemy kolejny argument x=1:9do przekazania match. xjest domyślnym argumentem pierwszej pozycji, dlatego też każdy wiersz jest umieszczany na drugim argumencie pozycji, czyli table. Funkcja matchszuka instancji xw table. W takim przypadku szuka 1:9(liczb od 1 do 9) w każdym rzędzie. Dla każdego 1:9powróciTRUE (lubFALSE ), jeśli ten numer zostanie znaleziony (lub nie).

To daje szereg 81 wartości logicznych.

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

Powtórz powyższe dla każdej kolumny danych wejściowych.

all(                                             )

Na koniec allsprawdza, czy każdy element listy booleanów jest TRUE. Będzie to miało miejsce wtedy i tylko wtedy, gdy rozwiązanie jest poprawne (tj. Każda liczba1:9 występuje tylko raz w każdej kolumnie i każdym wierszu).

Stare podejście:

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

Pobiera każdy wiersz, sortuje go, a następnie porównuje [1, 2, ... 9]. Prawidłowy wiersz powinien dokładnie pasować. Następnie robi to samo dla każdej kolumny. W sumie powinniśmy mieć 162 dokładne dopasowania, co sprawdza ostatnia porcja. Prawdopodobnie istnieje tu pole do dalszej gry w golfa ...


Wygląda na to, że sprawdzasz kolumny i wiersze, ale nie pola…
JayCe

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

Funkcja v można zadzwonić. Działa poprzez porównanie różnicy każdego wiersza, kolumny i bloku z listą[1..9] i zsumowanie długości tych list różnic.

Demo na przykładzie 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

1

JavaScript - 149 znaków

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]

Oczekuje, że tablica abędzie istnieć i utworzy zmienną odla wyniku, który jest0 zakończy się powodzeniem, w przeciwnym razie niezerowa.

Działa poprzez sprawdzenie, czy suma pozycji, w której występuje każda wartość dla każdego wiersza, kolumny i siatki 3 * 3, wynosi 36 (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8).

Testowanie

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

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

(Zamieniono 2 ostatnie cyfry)

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

Daje o=-284


1

Haskell, 121 130 127 bajtów (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]

wykorzystuje:

-- 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 domyślnie ładuje Data.List i Data.List.Split (nie sądzę, aby rozwiązanie BlackCap sprawdzało pola).

Pomysły na ulepszenia mile widziane

// Edycja:
Pomieszałem :) // Edycja: 3 bajty zapisane przez BlackCap


Masz rację, nie zauważyłem, że sprawdzanie wierszy i kolumn to za mało ..
BlackCap

cóż, ja też
popsułem

1
Można wymienić (map sort)z(sort<$>)
Gajówka

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

och, powinienem był pamiętać te 2
michi 7x7


0

Clojure, 151 bajtów

Dość długo, ale wydaje się, że inni też. Również denerwujące jest to, że połączenie zbiorów wymaga a require, więc zamiast tego użyłem konkat wektorów.

Iteruje po każdym wierszu i kolumnie, a jeśli wartość wynosi od 1 do 9, emituje trzy wektory, jeden dla wiersza, kolumny i komórki 3x3. Zwraca 0 w przypadku sukcesu, a w nilprzeciwnym razie dwa dodatkowe znaki mogą zwrócić 1 w przypadku niepowodzenia. Obsługuje liczby spoza 1 - 9, powracając, nilale spowoduje awarię innych anomalii, takich jak wartości inne niż całkowite. Ilości wynoszą 0–2, więc można bezpiecznie używać wartości 8i 9odróżniać wartości komórek od wierszy i kolumn.

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

Dane wejściowe to zagnieżdżony wektor wektorów (więc nthdziała):

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

Nie golfowany:

(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 bajtów

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

Program pobiera 9 oddzielnych argumentów wiersza poleceń (jeden ciąg cyfr dla każdego wiersza siatki);
wychodzi z 1(błąd) dla niepoprawnego, 0(ok) dla ważnego.

Uruchom z php -nr '<code>' <row1> <row2> ....

awaria

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
}

wyjaśnienie

count_charszlicza znaki w ciągu i zwykle tworzy tablicę z kodami ascii jako kluczami, a znaki liczą się jako wartości; ale z 3parametrem as mode tworzy posortowany ciąg znaków ze znaków; i można to łatwo porównać do liczby z poszukiwanymi cyframi.

Porównanie nie tylko sprawdza duplikaty, ale obejmuje również sprawdzenie nieprawidłowych znaków. I wymaga tylko <, nie !=, ponieważ jest to porównanie numeryczne: PHP zinterpretuje ciąg znaków jako liczbę, o ile to możliwe. 123e56789, 0x3456789lub podobne nie mogą się pojawiać, ponieważ znaki są sortowane; i każda czysta liczba całkowita z brakującą cyfrą jest mniejsza niż 123456789... i.23456789 oczywiście.

$a=$argvzapisuje jeden bajt, $d=123456789zapisuje dziewięć i $u=count_charszapisuje 13.


-1

C # - 306 298 288 znaków

Do wywołania funkcji sprawdzania użyto następującego programu konsoli;

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

Wystarczy zainicjować tablicę i przekazać ją do funkcji sprawdzającej P.

Funkcja sprawdzania jest jak poniżej (w formie gry w golfa);

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

Lub w pełni ułożonej formie;

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

Wykorzystuje to ideę, że wszystkie kolumny, wiersze i podsiatki powinny sumować do 45. Działa przez tablicę wejściową i odejmuje wartość każdej pozycji od jej wiersza, kolumny i podsiatki. Po zakończeniu sprawdza, czy żaden z wierszy, kolumn lub podsiatek nadal nie ma wartości.

Zgodnie z żądaniem zwraca wartość 0, jeśli tablica jest prawidłowym rozwiązaniem Sudoku i niezerową (1), jeśli nie jest.


Myślę, że możesz zapisać niektóre znaki, używając private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];zamiast tego. (Zwróć uwagę na usunięcie spacji po zamkniętym nawiasie kwadratowym ].) Nie jestem też pewien, ale myślę, że możesz się go pozbyć private static.
user12205

Ponadto dla ostatniej części w C możemy usunąć niektóre nawiasy klamrowe, tzn. for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}Nie jestem pewien, czy to działa w C #. (Właściwie nie znam C #)
użytkownik12205

@ace - Wprowadziłem kilka ulepszeń w oparciu o twoje sugestie. Teraz do 298 znaków.
Czy

Skróciłem kolejne 10 znaków na podstawie komentarzy z @ace.
Czy

1
Co dzieje się z tablicą pełną liczb 5? Wszystkie rzędy, kolumny i kwadraty sumują się do 45.
Level River St
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.