Xác nhận một bảng Minesweeper


33

Mục tiêu của bạn là kiểm tra xem một bảng Minesweeper đã hoàn thành có hợp lệ hay không. Điều này có nghĩa là mỗi số là một số lượng chính xác của các mỏ trong các ô liền kề với nó, bao gồm cả các đường chéo. Bảng không quấn quanh.

Như thường lệ , bạn nên cung cấp một hàm hoặc chương trình và mã ngắn nhất tính theo byte sẽ thắng.

Xem thêm những thách thức trong quá khứ để tạo , giải quyếtthực hiện đầy đủ Minesweeper.

Đầu vào:

Một chuỗi như thế này : 02X2 13X2 X211.

  • Các hàng của bảng quét mìn được phân tách bằng khoảng trắng. Vì vậy, ở trên đại diện cho bảng 3x4:

    02X2
    13X2
    X211

  • Mỗi ô là một ký tự: Xcho một mỏ hoặc một số 0thông qua 8.

  • Tất cả các hàng có cùng chiều dài.

  • Có ít nhất 3 hàng và 3 cột.

  • Đầu vào không bắt đầu hoặc kết thúc bằng một khoảng trắng, nhưng bạn có thể bao gồm một dòng mới ở cuối nếu bạn muốn.

Đầu ra:

Một phù Truthy trên bảng đúng và phù hợp Falsey giá trị trên bảng không chính xác. Nhất quán có nghĩa là tất cả các đầu ra Truthy đều giống nhau và tất cả các đầu ra Falsey đều giống nhau.

Các trường hợp thử nghiệm

Mỗi dòng là một trường hợp thử nghiệm riêng biệt.

True:

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX

False:

02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

Bạn có thể nên chỉ định đầu ra giả nhất quán phải khác biệt với đầu ra trung thực nhất quán ;-)
John Dvorak

@JanDvorak Điều đó nên được ngụ ý bởi họ lần lượt là Truthy và Falsey.
xnor

Không hẳn vậy. "Sự thật" và "giả dối" chỉ là hai nhãn hiệu mà bạn cho phép chúng tôi xác định. Tôi có thể thấy không có hạn chế nào họ thực sự trung thực hoặc giả dối tương ứng trong ngôn ngữ chúng tôi sử dụng. Từ duy nhất có thể yêu cầu chúng phải khác biệt là động từ "chỉ". Tôi không chắc nó được tính là một thông số kỹ thuật (mặc dù vậy nó vẫn bị cấm như một lỗ hổng tiêu chuẩn).
John Dvorak

4
@JanDvorak 'thật' và 'giả' thực sự là những thuật ngữ hơi phổ biến nếu tôi không nhầm lẫn về cơ bản được sử dụng để mô tả những thứ (không nhất thiết là bool) đánh giá là đúng hay sai khi nhập vào bool. Ví dụ 0 nói chung là giả và 1 nói chung là đúng.
KSab

1
@JanDvorak Không, Truthy / Falsey phải khớp chính xác / không chính xác.
xnor

Câu trả lời:


11

Con trăn 2, 132 129 128

def f(s):w=s.find(' ');E=dict(enumerate(s));return all(E[i]in' X'+`sum(E.get(i+d/3*~w+d%3+w,5)>'O'for d in range(9))`for i in E)

Tôi đã sử dụng enumeratetrong một sân golf ... và thậm chí được sử dụng rangeở những nơi khác trong cùng một chương trình. Rõ ràng có gì đó không đúng ở đây.

Chỉnh sửa: Lặp đi lặp lại dict(enumerate(s))thay vì enumerate(s), vì vậy enumeratekhông cần phải gọi hai lần.


Thật là một cách sử dụng thông minh ~! Và từ điển để làm cho lập chỉ mục ngoài giới hạn hoạt động đúng.
xnor

@xnor Nhận xét của bạn về ~nhà điều hành trớ trêu khiến tôi nhận thấy tôi đã sử dụng nó hai lần mà không có lý do nào cả, trong đó chỉ sử dụng một lần thì rõ ràng sẽ hoàn thành điều tương tự. Tôi nghĩ rằng phần từ điển là buồn cười, cảm ơn.
frageum

9

Bình thường, 43

Jhxzd!f-@zT+" X"`sm/:+*JNztd+d2\Xm+T*kJU3Uz

Hãy thử nó ở đây .

Giải trình:

  • Jhxzd: Đây là vị trí của không gian đầu tiên trong đầu vào + 1. ( ztrong đầu vào, dlà không gian.) Đó là sự phân tách trong đầu vào giữa các ô liền kề theo chiều dọc trên bảng.
  • !f: Đây là logic không ( !) của bộ lọc ( f), sẽ là Truekhi và chỉ khi biểu thức bị sai lệch cho mọi phần tử của chuỗi.
  • -@zT: Lấy ký tự tại vị trí T(biến lambda) khỏi đầu vào và xóa bất kỳ sự xuất hiện nào của: (Điều này sẽ là sự thật nếu ký tự không bị xóa và giả mạo nếu có.
  • +" X": Xóa không gian, X và
  • `: Đại diện của
  • sm: tổng bản đồ tới
  • / \X: số "X" trong
  • :+*JNz: Phần đầu vào được thêm tiền tố bởi Jcác ký tự giả
  • td+d2: Từ d-1 đến d + 2.
  • m+T*kJU3: Với d trong [T, T + J, T + 2 * J].
  • UzCho T vào range(len(input)).

7
Downvoters: Tại sao các downvote?
isaacg

7

APL (NARS2000) (74)

{~0∊(G>9)∨G=(⍴G)↑{+/∊9<⍵∘⌷¨G∘.⊖(G←2-⍳3)∘.⌽⊂Z}¨⍳⍴Z←G↑⍨2+⍴G←¯1+⎕D⍳⊃⍵⊂⍨⍵≠' '}

Cũng hoạt động trong Dyalog APL nếu ⎕MLđược đặt thành 3.

Giải trình:

  • ⊃⍵⊂⍨⍵≠' ': chia nhỏ các khoảng trắng và sử dụng các danh sách để tạo thành ma trận.
  • G←¯1+⎕D⍳: tìm chỉ mục ⎕Dcho mỗi giá trị, trừ 1 và lưu trữ này vào G. ( ⎕Dchứa các chữ số, bất kỳ chữ số nào sẽ biến thành 10).
  • Z←G↑⍨2+⍴G: thêm hai dòng và cột số 0 ở cạnh của ma trận, để đối phó với sự bao bọc
  • {... }¨⍳⍴Z: cho mỗi vị trí trong Z, tìm số lượng bom trong khu phố Moore của vị trí đó:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂Z: xoay Ztrái, phải, lên, xuống, trái, phải, xuống, trái và phải xuống.
    • ⍵∘⌷¨: cho mỗi trong số này, tìm phần tử tại trong mỗi ma trận xoay này
    • +/∊9<: đếm có bao nhiêu phần tử cao hơn 9 (đây là số lượng bom).
  • (⍴G)↑: xóa các dòng số đã thêm một lần nữa,
  • G=: kiểm tra xem mỗi phần tử trong Gcó bằng với số lượng bom xung quanh vị trí đó hay không (điều này đúng với tất cả các ô vuông không bom),
  • (G>9)∨: và kiểm tra xem các phần tử trong Gcó cao hơn không 9(đây là những quả bom).
  • ~0∊: return 1nếu ma trận kết quả không chứa số 0 (= tất cả các ô vuông là bom hoặc số chính xác) và 0nếu có.

Bạn đã đếm byte hoặc ký tự? Bạn nên đếm byte.
Tim S.

5
@TimS.: Có rất nhiều mã hóa APL 1 byte, đây là một .
marinus

5

C #, 321 320 305

bool s(string B){var L=B.Split(' ').Select(s=>' '+s+' ').ToList();var b=new string(' ',L[0].Length);L.Insert(0,b);L.Add(b);Func<int,int,IEnumerable<int>>E=Enumerable.Range;return E(1,b.Length-2).All(x=>E(1,L.Count-2).All(y=>L[y][x]=='X'||L[y][x]-'0'==E(x-1,3).Sum(X=>E(y-1,3).Sum(Y=>L[Y][X]=='X'?1:0))));}

Lần đầu tiên thử chơi golf bất cứ điều gì và tôi biết rằng C # không phải là ngôn ngữ lý tưởng.

Tôi hy vọng viết một phương thức cá thể được cho phép, nếu không thì thêm 7 ký tự cho static.

Cách nhau ra:

bool s(string B) {
    var L = B.Split(' ').Select(s => ' ' + s + ' ').ToList();
    var b = new string(' ', L[0].Length);
    L.Insert(0, b);
    L.Add(b);
    Func<int, int, IEnumerable<int>> E = Enumerable.Range;
    return E(1, b.Length - 2).All(x =>
        E(1, L.Count - 2).All(y =>
            L[y][x] == 'X' ||
            L[y][x] - '0' == E(x - 1, 3).Sum(X =>
                E(y - 1, 3).Sum(Y =>
                  L[Y][X] == 'X' ? 1 : 0))));
}

Sử dụng Linq giúp tiết kiệm một số không gian so với các vòng lặp, nhưng khó gỡ lỗi hơn.

Tôi đã học được một vài điều như chuyển đổi char => intbằng cách trừ '0'.

Có vẻ đơn giản hơn để đệm bảng với không gian để lặp đi lặp lại sẽ dễ dàng hơn.


1
Bạn không thể thay thế -'0'bằng -48. Hoạt động cho tôi và tiết kiệm một vài byte cho nhiều 'X' và ''
Roman Gräf

5

Con trăn 2, 121

def f(B):n=B.find(' ')+1;R=range(len(B));print all(B[I]in' X'+`sum(2>I%n-i%n>-2<I/n-i/n<2<B[i]>'W'for i in R)`for I in R)

Điều này được truyền cảm hứng mạnh mẽ bởi câu trả lời của frageum . Thứ tự trong ngày là quá mức cần thiết: thay vì kiểm tra các mỏ trong 9 hàng xóm của tế bào, hãy kiểm tra từng ô để xem đó có phải là mỏ lân cận hay không.

Chúng tôi kiểm tra xem hai tế bào là hàng xóm với 2>r>-2<c<2, nơi rclà những hàng và cột khác biệt của các tế bào, tương đương với {r,c}<{-1,0,1}. Các tọa độ này được tính toán từ các chỉ số ô Iias c=I%n-i%nr=I/n-i/n. Sẽ hiệu quả hơn khi lập chỉ mục trực tiếp vào chuỗi và trích xuất các hàng và cột hơn là chuyển đổi nó thành một đối tượng 2D như một danh sách các danh sách. Kiểm tra mỏ là B[i]>'W', tương đương ở đây B[i]=='X'.

Việc sử dụng enumeratesẽ lưu hai ký tự xấu hơn range(len(B))ngoại trừ việc nó trả về một đối tượng lặp không hỗ trợ hai vòng lặp lồng nhau qua nó.


Tôi nghĩ rằng một mô-đun âm nên làm việc cho n; sau đó bạn có thể sử dụng ~B.find.
frageum

@feersum Thật không may, điều đó gây rối /vì nó làm tròn tiêu cực xuống quá.
xnor

4

Con trăn 2, 140

s=input();w=s.index(' ')+1
print all(c in'X 'or(int(c)==sum(s[max(0,a-1):max(0,a+2)].count('X')for a in[i-w,i,i+w]))for i,c in enumerate(s))

4

JavaScript (ES6), 135 133 125 122

f=s=>s.split(" ")[e="every"]((l,i,a)=>[...l][e]((c,j)=>!(-[-1,0,k=1][e]((y,m,q)=>q[e](x=>k+=(a[i+y]||0)[j+x]=="X"))-c+k)))

Cung cấp đầu vào cho hàm dưới dạng chuỗi:

f("XX4X2 5X6X4 XX6XX 4XX54 2X4XX");

Để được giải thích, xem phiên bản cũ, bên dưới. Phiên bản mới thay thế các forvòng lặp bằng everycác cuộc gọi và sử dụng biến e="every"để thực hiện someArray[e](...)thay vì someArray.every(...).

Ngoài ra, bộ đếm khiện được lập chỉ mục 1để k+=...biểu thức luôn luôn trung thực, để giữ cho everyvòng lặp chạy. Chúng tôi loại bỏ phần bổ sung đó 1bằng cách trừ đi truekết quả (mà số lượng cưỡng chế 1) được trả về bởi phép everytoán [-1,0,k=1][e](...).


Phiên bản cũ:

f=s=>s.split(" ").every((l,i,a)=>[...l].every((c,j)=>{q=[-1,k=0,1];for(y of q)for(x of q)k+=(a[i+y]||0)[j+x]=="X";return c=="X"||k==c}))

Mã có khoảng trắng và nhận xét:

f=s=>s.split(" ")                 // split on spaces
      .every((l,i,a)=>             // for every line
                                   //     l: line string, i: line number, a: whole array
          [...l].every((c,j)=>{    // for every character
                                   //     c: character, j: index in string
              q=[-1,k=0,1];        // define counter k=0 and q=[-1,0,1]
              for(y of q)          // use q to loop adjacent spaces
                  for(x of q)

                      k+=              // add the following boolean to k:

                          (a[i+y]      //   from line number i+y...
                                 ||0)  //   (or a dummy zero, to prevent lookups on undefined)
                          [j+x]        //   ...get index j+x from the above value...
                                =="X"; //   ...and compare it to "X"

              return !(k-c)     // after the loop, this character passed if
                                // the char equals the number of counted X's (so k-c is 0)
                                // or it is an X itself (so `k-c` is NaN)
          })
      )

everyPhương thức mảng JavaScript nhận một cuộc gọi lại và áp dụng cuộc gọi lại cho mọi phần tử của mảng. Nếu bất kỳ cuộc gọi lại nào trả về giá trị falsey, everycuộc gọi sẽ trả về false.

Booleans trong JS bị ép buộc thành 1 hoặc 0 khi một phần của phép cộng. Đối với mỗi không gian xung quanh, chúng tôi "thêm" kết quả boolean của việc so sánh giá trị của nó với Xvà sau đó thêm giá trị đó vào bộ đếm ktrong biểu thức k += (... == "X"). Do đó, kchứa một số lượng xung quanh Xs, bởi vì trueđếm 1falsetính là 0.


Thay vì c=="X"thử !c/1, điều này giúp bạn tiết kiệm được một lượng lớn các cặp byte! Nếu thất bại, hãy thử !!c/1. Lý do là vậy 'X'/1 => NaN, và NaNlà giả. Bạn kiểm tra xem c=='X', tại sao không thử kiểm tra nếu nó không false?
Ismael Miguel

@IsmaelMiguel Điều đó đánh giá giống như (!c)/1, không có ích gì, thật không may; Tôi cần phải có dấu ngoặc đơn !(c/1), có giá 2. Ngoài ra, 0/1là falsey, vì vậy đầu vào không hợp lệ " 0X" sẽ có kết quả không chính xác true. Điều tốt nhất tôi có thể làm trong khi vẫn tôn trọng các số 0 là kết hợp hai điều kiện thành một cụm từ phủ định, giống như !(+c+1&&k-c), nhưng đó là cùng độ dài với những gì tôi đã có.
apsillers

@IsmaelMiguel Cảm ơn vì đã khiến tôi suy nghĩ về điều đó - Tôi đã nhận ra rằng !(k-1-c)kiểm tra cả hai điều kiện, bởi vì nếu kkhớp c(trừ phần bù 1), thì phủ định làm cho 0đúng và nếu ckhông phải là số, chúng ta sẽ nhận được NaNvà phủ định cũng là true.
apsillers

Bạn thực sự đói! Bạn đã ăn 10 byte kể từ mã ban đầu! Tôi thực sự thích giải pháp bạn đưa ra. +1 cho giải pháp của bạn!
Ismael Miguel

3

CJam, 70 65 63 byte

1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI

Điều này có thể được chơi golf rất nhiều.

Cung cấp 1cho một bảng hợp lệ và 0cho một bảng không hợp lệ.

Các trường hợp thử nghiệm

{-1:W;
1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI
}6*]N*

Đầu vào

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX
02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

Đầu ra

1
1
1
0
0
0

Dùng thử trực tuyến tại đây


3

JavaScript (ES6) 98

Sử dụng một số để áp dụng một hàm cho mỗi ký tự của chuỗi.
Hàm trả về

  • sai nếu để trống
  • NaN nếu 'X' (liên tục trừ các giá trị từ một char không phải là số như 'X' sẽ cho NaN)
  • Giá trị số là 0 nếu có đúng số lượng 'X', khác không 0.
    Việc kiểm tra bên trong được thực hiện bằng bản đồ chỉ vì nó ngắn hơn forEach

một số trả về đúng ở giá trị trung thực đầu tiên (trong trường hợp này là khác không) có nghĩa là kiểm tra không thành công. Kết quả bị phủ định để đưa ra một sự thật / sai dễ nhận biết hơn.

F=v=>![...v].some(
  (x,p)=>x!=' '&&[1,-1,l=v.search(' '),-l,++l,-l,++l,-l].map(q=>x-=v[p+q]=='X')|x
)

Kiểm tra trong bảng điều khiển FireFox / FireBug

;["02X2 13X2 X212","XXXX XXXX X7XX XXXX","XX5X2 5X6X4 XX6XX 4XX54 2X5XX"
,"02X2 13X2 X211","XXXX XXXX XXXX XXXX","XX4X2 5X6X4 XX6XX 4XX54 2X4XX","111 1X1 111"]
.forEach(t => console.log(t, F(t)))

Đầu ra

02X2 13X2 X212 false
XXXX XXXX X7XX XXXX false
XX5X2 5X6X4 XX6XX 4XX54 2X5XX false
02X2 13X2 X211 true
XXXX XXXX XXXX XXXX true
XX4X2 5X6X4 XX6XX 4XX54 2X4XX true
111 1X1 111 true

1

R, 156 ký tự

a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])

Với các vết lõm, khoảng trắng và ngắt dòng, cho mức độ dễ đọc:

a = b = do.call(rbind,strsplit(scan(,""),"")) #Reads stdin and turn into a matrix
for(i in 1:nrow(a)) #Ugly, ugly loop
    for(j in 1:ncol(a))
        b[i,j] = sum(a[abs(i-row(a))<2 & abs(j-col(a))<2]=="X")
v = a!="X"
all(b[v]==a[v])

Ví dụ:

> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX4X2 5X6X4 XX6XX 4XX54 2X4XX
6: 
Read 5 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XXXX XXXX XXXX XXXX
5: 
Read 4 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX5X2 5X6X4 XX6XX 4XX54 2X5XX
6: 
Read 5 items
[1] FALSE
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.