Tạo một giải pháp sudoku CHECKER


21

Tạo một giải pháp Sudoku KIỂM TRA

Có rất nhiều GIẢI PHÁP Sudoku ở đây, nhưng tôi muốn bạn tạo ra một giải pháp CHECKER nhỏ nhất có thể như con người (code-golf).

  • Một mục nhập hợp lệ sẽ có thể lấy một mảng 9x9 làm đối số (được truyền bằng tham chiếu, được xê-ri hóa trên dòng lệnh hoặc tuy nhiên bạn muốn lấy nó) hoặc chấp nhận một tệp đầu vào gồm chín dòng chín số cho lưới cuối cùng . Xem ví dụ về đầu vào bên dưới.

  • Đầu vào hợp lệ phải là số cơ sở 10 (1-9)

  • Các vị trí bị thiếu, trống, thêm, không phải là số hoặc các vị trí có số ngoài 1-9 phải được loại bỏ làm đầu vào không hợp lệ bằng cách trả về kết quả khác không, in lỗi hoặc cả hai.

  • Chương trình của bạn cần kiểm tra xem mỗi số xuất hiện một lần trên mỗi cột, một lần trên mỗi dòng và một lần trên mỗi lưới con 3x3. Nếu nó vượt qua, trả về "0" và nếu không, trả về kết quả khác không.

  • Sử dụng các nguồn lực bên ngoài (trang web, vv) là phải tránh.

  • Nếu giải pháp của bạn là một chương trình độc lập, thoát ra với trạng thái thoát hoặc in, "0" hoặc khác không cho "Đạt" hoặc "Không", tương ứng, là ok.

Hãy để câu trả lời nhỏ nhất giành chiến thắng!

Ví dụ đầu vào:

mảng 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}
                };

tập tin:

123456789
456789123
789123456
231564897
564897231
897231564
312645978
645978312
978312645

9 lưới con:

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

Câu trả lời:


5

GolfScript, 39 ký tự

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

Nó lấy một mảng các mảng làm đầu vào (xem ví dụ trực tuyến ) và đầu ra 0nếu đó là một lưới hợp lệ.

Giải thích ngắn về mã

.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

Tôi thích rằng đầu ra khác không của mã của bạn có ý nghĩa hơn là chỉ 1hoặc-1
David Wilkins

Tôi thực sự thích câu trả lời của bạn nhưng cuối cùng tôi đã chọn không đi với một giải pháp golfscript. Tôi thực sự hy vọng bạn hiểu
David Wilkins

2
@DavidWilkins Thật ra tôi không hiểu - bạn đã đưa ra các quy tắc (!) Và không nêu bất cứ nơi nào mà GolfScript không được phép.
Howard

Quan điểm của bạn là hoàn toàn hợp lệ ... sự thật tôi không có gì để biện minh cho việc không chọn câu trả lời của bạn. Chơi tốt
David Wilkins

10

Con trăn, 103

Tôi ghét 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))))

Cách thức hoạt động: mỗi hàng, cột và khối phải có mỗi số từ 1 đến 9. Vì vậy, đối với mỗi 0 <= i, j < 9, ô i,jnằm trong khối 3*floor(i/3) + floor(j/3). Như vậy, có 243 yêu cầu để thỏa mãn. Tôi thực hiện mỗi yêu cầu một tuple ((item index,item type number),symbol)trong đó item indexmột số từ 0 đến 8 (đã bao gồm), item type numberlà 0,1 hoặc 2 để biểu thị hàng, cột hoặc khối tương ứng và symbollà mục nhập b[i][j].

Chỉnh sửa: Tôi nhầm không kiểm tra các mục hợp lệ. Bây giờ tôi làm.


Chương trình của bạn sẽ xuất ra 0nếu giải pháp vượt qua, không phảiTrue
David Wilkins

@DavidWilkins những gì một yêu cầu kỳ lạ. Đã sửa.
gian hàng ngày

Bạn nhận được phiếu bầu của tôi chỉ vì cách bạn bắt đầu câu trả lời của mình: D
Teun Pronk

9

APL (46)

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

Điều này cần một ma trận 9-9. Một ví dụ có thể được nhập trên TryAPL như vậy:

     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

Giải trình:

  • ↓⍉⍵: lấy các cột của ,
  • ↓⍵: lấy các hàng của ,
  • 3/3⌿3 3⍴Z←⍳9: tạo ma trận 3 nhân 3 chứa các số 1thành 9, sau đó nhân ba số theo cả hai hướng, đưa ra ma trận 9 x 9 với các số 1để 9chỉ ra từng nhóm,
  • Z∘.=: Cho mỗi số 1để 9, làm cho một bitmask cho nhóm nhất định,
  • /∘(,⍵)¨: và mặt nạ với nhau, đưa ra các nhóm .
  • ∊∘Z¨: cho mỗi mảng con, xem nó có chứa các số 1đến không 9,
  • ∧/,↑: lấy logic andcủa tất cả các số này với nhau.

+1 Tốt đẹp! Nhưng các nhóm 3 × 3 có thể được đánh gôn thêm. Ví dụ, điều này ↓9 9⍴1 3 2⍉3 3 9⍴⍵tương đương với /∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9nhưng khá ngắn. Tôi chắc chắn có những công thức thậm chí còn ngắn hơn.
Tobia

Ngoài ra, bạn có thể ghép các ma trận theo chiều thứ nhất và thực hiện một lần phân tách duy nhất ở cuối:↓(9 9⍴1 3 2⍉3 3 9⍴⍵)⍪⍵⍪⍉⍵
Tobia

Có một lỗi: mã ∊∘Z¨này đang kiểm tra xem mỗi mảng con (hàng, cột hoặc khối) chỉ được tạo từ các số từ 1 đến 9. Nó không kiểm tra xem tất cả các số có được biểu diễn hay không. Bạn cần làm một cái gì đó giống như Z∘.∊kiểm tra mà mọi số trong Z được chứa trong mỗi mảng con.
Tobia

Và điều này ∧/,↑có thể được rút ngắn ∧/∊. Tôi đã xong, tôi đã hoàn tất! ;-)
Tobia

Rất nhỏ gọn, nhưng bạn đã bỏ lỡ một điểm quan trọng mà tôi có thể thấy ngay:If it passes, return "0" and if not, return a non-zero result.
David Wilkins

5

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

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

(Thay đổi booleanthành boolC #)

Định dạng:

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

Phương thức tạo ra một mảng uvới 27 bitmasks, biểu thị các chữ số được tìm thấy trong chín hàng, cột và hình vuông.

Sau đó, nó lặp lại trên tất cả các ô, thực hiện thao tác 1 << a[x][y]để tạo một bitmask đại diện cho chữ số và ORs cột, hàng và bitmask vuông của nó với nó.

Sau đó, nó lặp đi lặp lại trên tất cả 27 bitmasks, đảm bảo rằng tất cả chúng đều cộng tới 27594 (1022 * 9, 1022 là bitmask cho tất cả các chữ số 1-9 có mặt). (Lưu ý rằng ykết thúc là 27603 do nó đã chứa 9 theo vòng lặp kép.)

Chỉnh sửa: Vô tình để lại trong %3đó không còn cần thiết.

Chỉnh sửa 2: Lấy cảm hứng từ bình luận của Bryce Wagner, mã đã được nén thêm một chút.


Hầu như cùng một thuật toán trong ký tự C # 149 (nhưng chỉ khi Linq được phép): 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;} trả lại u.Sum () == 27594;}
Bryce Wagner

@BryceWagner Linq thực sự sẽ hữu ích. Tuy nhiên, giải pháp của tôi là dành cho Java với C # là một suy nghĩ lại (thậm chí không được đề cập trong bài viết gốc) và do đó mức độ ưu tiên thấp hơn. Tôi cũng đã sử dụng các mảng một chiều cho sự gọn nhẹ khi bắt đầu trước khi quyết định chống lại nó (vì các ví dụ sử dụng các mảng hai chiều). Tuy nhiên, mã của bạn đã cho tôi một vài ý tưởng về cách loại bỏ một vài byte nữa. :)
Smallhacker

3

trăn = 196

Không phải là golf nhất, nhưng ý tưởng là ở đó. Bộ khá hữu ích.

Bảng:

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

Chương trình:

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} / bộ (phạm vi (1,10)) / lưu 3 ký tự.
MatrixFrog

Trong Python 3.5 bạn có thể sử dụng n={*range(1,10)}, nhưng điều đó mới hơn thử thách. Thay vì sử dụng set(range(1,10))như MatrixFrog đã nói.
mbomb007

3

Java - 385 306 328 260 ký tự

Chỉnh sửa: Tôi dại dột đọc sai hướng dẫn rằng câu trả lời phải là một chương trình hoàn chỉnh. Vì nó có thể chỉ là một hàm hợp lệ, tôi đã viết lại và thu nhỏ thành một hàm và viết lại phần giới thiệu giải pháp của tôi với ý nghĩ đó.

Vì vậy, như một thách thức đối với bản thân tôi, tôi nghĩ rằng tôi đã cố gắng thực hiện trình kiểm tra giải pháp Java nhỏ nhất.

Để đạt được điều này, tôi giả định rằng câu đố sudoku sẽ được truyền vào dưới dạng một mảng đa chiều java, như vậy:

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

Sau đó, chúng ta có bộ giải thực tế, trả về "0" nếu giải pháp hợp lệ, "1" nếu không.

Chơi golf đầy đủ:

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

Có thể đọc được

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

Vậy làm thế nào để làm việc này? Về cơ bản, tôi chỉ tạo cơ sở số của riêng mình với độ phân giải đủ trong mỗi chữ số mà tôi chỉ phải thực hiện ba phép so sánh số sau khi đi qua câu đố một lần để biết nó có hợp lệ không. Tôi đã chọn cơ sở 49 cho vấn đề này, nhưng bất kỳ cơ sở nào lớn hơn 45 sẽ là đủ.

Một ví dụ rõ ràng (hy vọng): tưởng tượng rằng mọi "hàng" trong câu đố sudoku là một chữ số trong một số cơ sở 49. Chúng tôi sẽ biểu diễn mỗi chữ số trong số cơ sở 49 dưới dạng số cơ sở 10 trong một vectơ để đơn giản. Vì vậy, nếu tất cả các hàng là "chính xác", chúng tôi mong đợi số cơ sở 49 sau (dưới dạng vectơ cơ sở 10):

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

hoặc được chuyển đổi thành một số 10 cơ sở duy nhất: 1526637748041045

Thực hiện theo logic tương tự cho tất cả các cột và tương tự cho "lưới con". Bất kỳ giá trị nào gặp phải trong phân tích cuối cùng không bằng "số lý tưởng" này có nghĩa là giải pháp câu đố không hợp lệ.

Chỉnh sửa để giải quyết lỗ hổng all-5s và các vấn đề liên quan khác: Tôi thêm số cơ sở thứ tư 49, dựa trên ý tưởng rằng nên có 9 số cho mỗi số trong mỗi câu đố. Vì vậy, tôi thêm 5 vào mỗi chữ số trong số cơ sở-49 cho mỗi lần xuất hiện của số cơ sở-10 đại diện cho chỉ số của chữ số. Một ví dụ, nếu có 10 9 và 9 8, 9 7, 8 6 và 9 của tất cả những người khác, bạn sẽ nhận được một số cơ sở 49 (như một vectơ cơ sở 10 có kích thước 10 để xử lý tràn)

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

Sẽ thất bại khi so sánh với số cơ sở "lý tưởng" 49 của chúng tôi.

Giải pháp của tôi tận dụng lợi thế của giải pháp toán học này, để tránh càng nhiều vòng lặp và so sánh càng tốt. Tôi chỉ đơn giản sử dụng một longgiá trị để lưu trữ mỗi số 49 cơ sở làm số 10 cơ sở và sử dụng mảng tra cứu để lấy "các yếu tố" cho mỗi chữ số cơ sở 49 trong quá trình tính toán giá trị kiểm tra cột / hàng / subgrid.

Vì Java không được thiết kế ngắn gọn, nên cẩn thận trong xây dựng toán học là cách duy nhất tôi nghĩ rằng tôi có thể xây dựng một trình kiểm tra súc tích.

Cho tôi biết bạn nghĩ gì.


1
Trên thực tế, điều này chịu cùng một lỗ hổng được đề cập bởi @ steve-verrill - tất cả 5 hoặc bất kỳ tập hợp số nào tính đến 45, sẽ "đánh lừa" người giải. Tôi sẽ sửa lại. Tôi có một ý tưởng làm thế nào để đánh bại điều đó.
Lập trình viên

Tôi đã giải quyết lỗ hổng này trong bản cập nhật mới nhất của tôi. Bây giờ trường hợp đó được giải quyết, và tất cả những người khác thuộc loại này. Về cơ bản, đó là một sự giám sát nghiêm túc khi không xử lý "số lượng" của từng loại chữ số cơ sở 10. Bây giờ tôi thực hiện kiểm tra trực tiếp, nhưng sử dụng cùng một phương pháp toán học (số cơ sở 49).
Lập trình viên

Dan, cảm ơn vì sự thừa nhận. Tôi đã nhìn thấy nó và tự hỏi tại sao tôi không được thông báo, nhưng tôi thấy bạn đặt một dấu gạch ngang trong tên của tôi. Điều này dường như đã gây nhầm lẫn cho hệ thống. Đơn giản chỉ cần bỏ qua không gian. Tôi sẽ xem xét thay đổi cách hiển thị tên của tôi.
Cấp sông St

Ahha, điều đó giải thích nó. Cảm ơn @steveverrill - Tôi vẫn đang quen với cách làm việc stackexchange. Điều đó nói rằng, khai thác ngắn gọn của bạn về nguyên tắc sum-45 đã được nêu rõ. Làm cho giải pháp của tôi lâu hơn để vượt qua nó, nhưng đó là cuộc sống!
Lập trình viên

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

Mã de-golfed (nhiều hơn hoặc ít hơn) có thể được tìm thấy ở đây /programming//a/21691541/1201032 .


bạn có thể cung cấp một ví dụ hoạt động trên một trang web như r-fiddle không? r-fiddle.org/#
David Wilkins

3

Haskell (Lambdabot), 65 byte

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

2

Perl, 193 byte

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)

Đầu vào dự kiến ​​ở dạng mảng:

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

Mã thoát là 0, nếu @alà một giải pháp, nếu không 1được trả lại.

Phiên bản bị đánh cắp:

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

Mỗi trong số 9 hàng, 9 cột và 9 mảng phụ được đặt vào một mảng được sắp xếp và kiểm tra xem nó có khớp với mảng đó không (1..9). Số lượng $rđược tăng lên cho mỗi trận đấu thành công phải tổng cộng lên tới 27 cho một giải pháp hợp lệ.


2

J 52 54

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

Làm cho đối số của nó được dán trên dòng lệnh, kết thúc bằng a) là:

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
)

Trả về 1 nếu được thông qua, 0 nếu không.

Trong nội bộ, nó chuyển đổi lưới 9x9 thành lưới 3x3x3x3 và thực hiện một số hoán vị trên các trục để có được đơn vị mong muốn (hàng, đường và hộp) trong 2 chiều cuối cùng.

Sau khi làm điều đó, kiểm tra xem mỗi đơn vị có 9 giá trị duy nhất.

Có lẽ còn lâu mới hoàn hảo, nhưng đã đánh bại phần lớn rồi ;-)


Thoạt nhìn, bạn đã bị bắt bởi cùng một yêu cầu như một số người khác .... Lợi nhuận của bạn sẽ bị đảo ngược ... 0 cho vượt qua, khác không cho thất bại
David Wilkins

0 cho vượt qua là ngu ngốc. Có một lý do Boole chọn 1 cho đúng và 0 cho sai. Nhưng bạn đúng. Thêm 2 ký tự.
jpjacobs

Hãy nghĩ về nó như một trạng thái thoát, không phải là giá trị boolean
David Wilkins

Tôi đang chọn câu trả lời của bạn vì nó hoạt động. Bạn đã tuân theo các quy tắc và chương trình của bạn rất ngắn. Cảm ơn!
David Wilkins

Chà, tôi bị xơ xác ... Thật ra tôi không thể biện minh cho việc không chọn câu trả lời Golfscript ngắn hơn câu trả lời của bạn ... Nhưng danh hiệu dành cho vị trí thứ 2
David Wilkins

2

Mathicala, 84 79 ký tự

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

Ví dụ:

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


Ví dụ đầu ra thứ ba của bạn: 3Luôn luôn là dấu hiệu của đầu vào không hợp lệ, hoặc đôi khi nó là một phản ứng đối với một giải pháp thất bại?
David Wilkins

2

Javascript ES6, 150 ký tự

Đưa đầu vào dưới dạng chuỗi 81 char mà không có bất kỳ dấu phân cách nào.

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

Hàm trả về nulldưới dạng câu trả lời phủ định và một mảng với chuỗi gốc trong phần tử đầu tiên là phần tử dương. Có thể thay đổi thành bool bằng cách thêm !!vào hàm bắt đầu.

Kiểm tra (xem thử thách liên quan để biết thêm chi tiết):

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

Đó là một regex nực cười ... Công việc tuyệt vời.
Sản phẩm ETH

2

R, 63 50 byte

Giả sử đầu vào mlà ma trận 9x9 của các số.

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

Tôi đã đúng rằng chơi golf xa hơn là có thể.

Giải trình:

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

Lấy m, và cho mỗi hàng, áp dụng matchchức năng. Chúng tôi chỉ định một đối số tiếp theo x=1:9sẽ được chuyển đến match. xlà đối số vị trí đầu tiên mặc định và do đó, mỗi hàng được đặt ở vị trí đối số thứ hai table. Hàm matchtìm kiếm các trường hợp xtrong table. Trong trường hợp này, sau đó, nó đang tìm kiếm 1:9(các số từ 1 đến 9) trong mỗi hàng. Đối với mỗi 1:9, nó sẽ trở lạiTRUE (hoặc FALSE) nếu số đó được tìm thấy (hoặc không).

Vì vậy, điều này mang lại một loạt 81 giá trị boolean.

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

Lặp lại ở trên cho mỗi cột của đầu vào.

all(                                             )

Cuối cùng, allkiểm tra xem mọi phần tử của danh sách booleans là TRUE. Đây sẽ là trường hợp nếu và chỉ khi giải pháp đúng (nghĩa là mỗi số 1:9chỉ xuất hiện một lần trong mỗi cột và mỗi hàng).

Cách tiếp cận cũ:

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

Nó nhận từng hàng, sắp xếp nó, và sau đó so sánh nó với [1, 2, ... 9]. Một hàng đúng phải khớp chính xác. Sau đó, nó làm tương tự cho mỗi cột. Tổng cộng, chúng ta nên có 162 trận đấu chính xác, đó là những gì phần cuối cùng kiểm tra. Có khả năng một số phạm vi để chơi gôn ở đây ...


Có vẻ như bạn đang kiểm tra các cột và hàng, nhưng không phải cho các hộp ...
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]]]

Các chức năng vlà một để gọi. Nó hoạt động bằng cách lấy sự khác biệt của từng hàng, cột và khối so với danh sách[1..9] và tổng hợp độ dài của các danh sách khác biệt đó.

Bản demo sử dụng ví dụ 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 ký tự

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]

Yêu cầu một mảng atồn tại và tạo một biến ocho đầu ra0 thành công và khác không.

Hoạt động bằng cách kiểm tra tổng của vị trí tại đó mỗi giá trị xảy ra cho mỗi hàng, cột và lưới 3 * 3 bằng 36 (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8).

Kiểm tra

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

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

(Hoán đổi 2 chữ số cuối)

Tặng 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]
  ];

Tặng o=-284


1

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

sử dụng:

-- 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 tải Data.List và Data.List.Split theo mặc định (Tôi không nghĩ giải pháp của BlackCap kiểm tra các hộp).

Ý tưởng để cải thiện chào mừng

// Chỉnh sửa: Tôi
đã gửi nhầm :) // Chỉnh sửa: 3 byte được lưu bởi BlackCap


Bạn nói đúng, tôi không nhận thấy rằng việc kiểm tra các hàng và cột không đủ ..
BlackCap

tốt, tôi cũng đã nhắn tin rồi :)
michi7x7

1
Bạn có thể thay thế (map sort)bằng(sort<$>)
BlackCap

1
.c$(sort<$>)<$>với$(sort<$>)=<<
BlackCap

ồ, đáng lẽ phải nhớ 2
michi7x7


0

Clojure, 151 byte

Khá lâu, nhưng những người khác dường như là tốt. Cũng khó chịu khi liên kết các tập hợp yêu cầu a require, vì vậy tôi đã sử dụng một vectơ thay thế.

Lặp lại trên mỗi hàng và cột và nếu giá trị nằm trong khoảng từ 1 đến 9, nó sẽ phát ra ba vectơ, một cho hàng, col và 3x3 ô. Trả về 0 khi thành công và nilnếu không, với hai ký tự phụ có thể trả về 1 khi thất bại. Xử lý các số bên ngoài 1 - 9 bằng cách quay lại nilnhưng sẽ gặp sự cố với các bất thường khác, chẳng hạn như các giá trị không nguyên. Các chỉ số là 0 - 2 nên an toàn khi sử dụng các giá trị 89phân biệt các giá trị ô với các hàng và cột.

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

Đầu vào là một vectơ lồng nhau của các vectơ (để nó nthhoạt động):

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

Ung dung:

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

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

Chương trình có 9 đối số dòng lệnh riêng biệt (một chuỗi chữ số cho mỗi dòng của lưới);
thoát với 1(lỗi) không hợp lệ,0 (ok) cho hợp lệ.

Chạy với php -nr '<code>' <row1> <row2> ....

phá vỡ

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
}

giải trình

count_charsđếm các ký tự trong một chuỗi và thường tạo ra một mảng với mã ascii là các khóa và ký tự được tính là các giá trị; nhưng với 3tham số như chế độ, nó tạo ra một chuỗi được sắp xếp từ các ký tự; và điều đó có thể dễ dàng được so sánh với số với các chữ số mong muốn.

Việc so sánh không chỉ kiểm tra các bản sao mà còn bao gồm kiểm tra các ký tự không hợp lệ. Và nó chỉ yêu cầu <, không phải !=, bởi vì đây là so sánh số: PHP sẽ diễn giải chuỗi là một số càng xa càng tốt. 123e56789, 0x3456789Hoặc tương tự không thể xuất hiện, bởi vì các nhân vật đều được sắp xếp; và bất kỳ số nguyên thuần nào có một chữ số bị thiếu đều nhỏ hơn 123456789... và .23456789dĩ nhiên.

$a=$argvlưu một byte, $d=123456789lưu chín và $u=count_charslưu 13.


-1

C # - 306 298 288 ký tự

Chương trình Console sau đây được sử dụng để gọi chức năng kiểm tra;

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

Tất cả điều này là khởi tạo mảng và chuyển nó vào hàm kiểm tra P.

Chức năng kiểm tra như dưới đây (ở dạng Golfed);

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

Hoặc ở dạng đặt ra đầy đủ;

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

Điều này sử dụng ý tưởng rằng tất cả các cột, hàng và lưới con nên thêm tới 45. Nó hoạt động thông qua mảng đầu vào và trừ giá trị của từng vị trí từ hàng, cột và lưới con của nó. Sau khi hoàn thành, nó sẽ kiểm tra xem không có hàng, cột hoặc lưới con nào có giá trị.

Khi được yêu cầu trả về 0 nếu mảng là một giải pháp Sudoku hợp lệ và khác không (1) trong trường hợp không.


Tôi nghĩ rằng bạn có thể lưu một số ký tự bằng cách sử dụng private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];thay thế. (Lưu ý xóa khoảng trống sau dấu ngoặc vuông ].) Ngoài ra, tôi không chắc nhưng tôi nghĩ bạn có thể thoát khỏi private static.
dùng12205

Ngoài ra, đối với phần cuối cùng, trong C, chúng ta có thể loại bỏ một số dấu ngoặc nhọn for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}, không chắc là nó có hoạt động trong C # hay không. (Tôi thực sự không biết C #)
user12205

@ace - Tôi đã thực hiện một số cải tiến dựa trên đề xuất của bạn. Bây giờ xuống còn 300 ký tự.
Sẽ

Cắt bớt 10 ký tự khác dựa trên nhận xét từ @ace.
Sẽ

1
Điều gì xảy ra với một mảng đầy số 5? Tất cả các hàng, cột và hình vuông cộng lại lên tới 45.
Level River St
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.