Verifikasi papan Minesweeper

33

Tujuan Anda adalah untuk memeriksa apakah papan Minesweeper yang lengkap valid Ini berarti bahwa setiap angka adalah jumlah yang benar dari ranjau dalam sel yang berdekatan dengannya, termasuk diagonal. Papan tidak membungkus.

Seperti biasa , Anda harus memberikan fungsi atau program, dan kode terpendek dalam byte menang.

Lihat juga tantangan masa lalu untuk menghasilkan , memecahkan , dan sepenuhnya mengimplementasikan Minesweeper.

Memasukkan:

Sebuah string tunggal seperti ini: 02X2 13X2 X211.

  • Barisan papan kapal penyapu ranjau diberikan dipisahkan oleh spasi. Jadi, yang di atas mewakili papan 3x4:

    02X2
    13X2
    X211

  • Setiap sel adalah karakter: Xuntuk tambang, atau nomor yang 0melalui 8.

  • Semua baris memiliki panjang yang sama.

  • Setidaknya ada 3 baris dan 3 kolom.

  • Input tidak memulai atau mengakhiri dengan spasi, tetapi Anda dapat memasukkan baris baru di akhir jika Anda mau.

Keluaran:

Kebenaran yang konsisten pada papan yang benar, dan nilai Falsey yang konsisten pada papan yang salah. Konsisten berarti bahwa semua keluaran Kebenaran adalah sama dan semua keluaran Falsey adalah sama.

Uji kasus

Setiap baris adalah test case yang terpisah.

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
Tidak
sumber
Anda mungkin harus menentukan output falsy yang konsisten harus berbeda dari output kebenaran yang konsisten ;-)
John Dvorak
@JanDvorak Itu harus disiratkan oleh mereka masing-masing sebagai Truthy dan Falsey.
xnor
Tidak juga. "truthy" dan "falsy" hanyalah dua label yang Anda izinkan kami definisikan. Saya dapat melihat tidak ada batasan mereka masing-masing benar-benar benar atau salah dalam bahasa yang kita gunakan. Satu-satunya kata yang mengharuskan mereka untuk berbeda adalah kata kerja "menunjukkan". Saya tidak yakin itu dianggap sebagai spek (masih dilarang sebagai celah standar).
John Dvorak
4
@JanDvorak 'truthy' dan 'falsy' sebenarnya istilah yang agak umum jika saya tidak salah pada dasarnya digunakan untuk menggambarkan hal-hal (belum tentu bools) yang mengevaluasi benar atau salah ketika diketik ke bools. Misalnya 0 umumnya salah dan 1 umumnya benar.
KSab
1
@JanDvorak Tidak, Truthy / Falsey harus sama benar / salah.
xnor

Jawaban:

11

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

Saya menggunakan enumerategolf ... dan bahkan digunakan rangedi tempat lain dalam program yang sama. Jelas ada yang salah di sini.

Sunting: Iterate over dict(enumerate(s))alih-alih enumerate(s), jadi enumeratetidak perlu dipanggil dua kali.

feersum
sumber
Penggunaan yang cerdas ~! Dan kamus membuat pengindeksan di luar batas berfungsi dengan baik.
xnor
@ xnor Komentar Anda tentang ~operator ironisnya membuat saya memperhatikan bahwa saya menggunakannya dua kali tanpa alasan sama sekali, di mana menggunakannya hanya sekali jelas akan mencapai hal yang sama. Saya pikir bagian kamusnya lucu, terima kasih.
feersum
9

Pyth, 43

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

Coba di sini .

Penjelasan:

  • Jhxzd: Ini adalah lokasi ruang pertama di input + 1. ( zdi input, dadalah spasi.) Ini adalah pemisahan di antara sel-sel yang berdekatan secara vertikal di papan tulis.
  • !f: Ini adalah bukan logis ( !) dari filter ( f), yang akan menjadi Truejika dan hanya jika ekspresi itu palsu untuk setiap elemen dari urutan.
  • -@zT: Ambil karakter di lokasi T(variabel lambda) dari input, dan hapus tampilan apa pun dari: (Ini akan menjadi kebenaran jika karakter tidak dihapus, dan salah jika itu.
  • +" X": Hapus spasi, X, dan
  • `: Repr dari
  • sm: jumlah peta ke
  • / \X: hitungan "X" di
  • :+*JNz: Sepotong input diawali oleh Jkarakter dummy
  • td+d2: Dari d-1 ke d + 2.
  • m+T*kJU3: Untuk d di [T, T + J, T + 2 * J].
  • UzUntuk T in range(len(input)).
isaacg
sumber
7
Downvoters: Mengapa downvotes?
isaacg
7

APL (NARS2000) (74)

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

Juga berfungsi di Dyalog APL jika ⎕MLdiatur ke 3.

Penjelasan:

  • ⊃⍵⊂⍨⍵≠' ': split pada spasi dan gunakan daftar untuk membentuk matriks.
  • G←¯1+⎕D⍳: temukan indeks ⎕Duntuk setiap nilai, kurangi 1, dan simpan dalam G. ( ⎕Dberisi digit, non-digit apa pun akan berubah menjadi 10).
  • Z←G↑⍨2+⍴G: tambahkan dua baris dan kolom nol di tepi matriks, untuk menangani sampulnya
  • {... }¨⍳⍴Z: untuk setiap posisi diZ , cari jumlah bom di lingkungan Moore dari posisi itu:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂Z: putar ke Zkiri, kanan, atas, bawah, kiri-atas, kanan-atas, kiri-bawah, dan kanan-bawah.
    • ⍵∘⌷¨: untuk masing-masing ini, temukan elemen di dalam masing-masing matriks yang diputar ini
    • +/∊9<: hitung berapa banyak elemen lebih tinggi dari 9 (ini adalah jumlah bom).
  • (⍴G)↑: hapus garis nol yang ditambahkan lagi,
  • G=: periksa apakah setiap elemen dalam Gsama dengan jumlah bom di sekitar posisi itu (ini harus berlaku untuk semua kotak non-bom),
  • (G>9)∨: dan periksa apakah unsur-unsur di Glebih tinggi dari 9(ini adalah bom).
  • ~0∊: kembali 1jika matriks yang dihasilkan tidak mengandung nol (= semua kotak adalah bom atau angka yang benar), dan 0jika ada.
marinus
sumber
Apakah Anda menghitung byte atau karakter? Anda harus menghitung byte.
Tim S.
5
@TimS .: Ada banyak pengkodean APL 1-byte, ini satu .
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))));}

Upaya pertama bermain golf apa pun, dan saya tahu bahwa C # bukan bahasa yang ideal.

Saya harap menulis contoh metode diperbolehkan, jika tidak tambahkan 7 karakter untuk static.

Melamun:

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

Menggunakan Linq menghemat ruang dibandingkan dengan untuk loop, tetapi lebih sulit untuk debug.

Saya belajar beberapa hal seperti mengubah char => intdengan mengurangi '0'.

Tampaknya lebih mudah untuk membuat papan dengan spasi sehingga iterasi lebih mudah.

Carl Walsh
sumber
1
Tidak bisakah kau ganti saja -'0'dengan -48. Bekerja untuk saya dan menyimpan beberapa byte untuk berbagai 'X' dan ''
Roman Gräf
5

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

Ini sangat terinspirasi oleh jawaban feersum . Urutan hari ini berlebihan: daripada memeriksa ranjau di 9 tetangga sel, periksa setiap sel untuk melihat apakah itu ranjau tetangga.

Kami memeriksa apakah dua sel bertetangga dengan 2>r>-2<c<2, di mana rdan capakah perbedaan baris dan kolom sel, setara dengan {r,c}<{-1,0,1}. Koordinat ini dihitung dari indeks sel Idan isebagai c=I%n-i%ndan r=I/n-i/n. Lebih efisien untuk mengindeks langsung ke string dan mengekstrak baris dan kolom daripada mengubahnya menjadi objek 2D seperti daftar daftar. Cek tambang adalah B[i]>'W', setara dengan di sini untuk B[i]=='X'.

Menggunakan enumerateakan menyimpan dua karakter di atas jelek range(len(B))kecuali bahwa itu mengembalikan objek iterator yang tidak mendukung dua loop bersarang melewatinya.

Tidak
sumber
Saya pikir modulus negatif harus bekerja untuk n; maka Anda bisa menggunakannya ~B.find.
feersum
@feersum Sayangnya, itu mengacaukan /karena putaran negatif juga.
xnor
4

Python 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))
KSab
sumber
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)))

Berikan input ke fungsi sebagai string:

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

Untuk penjelasan, lihat versi lama, di bawah ini. Versi baru menggantikan forloop dengan everypanggilan, dan menggunakan variabel e="every"untuk melakukan someArray[e](...)alih - alih someArray.every(...).

Juga, penghitung ksekarang diindeks 1sehinggak+=... ekspresi selalu benar, agar everyloop tetap berjalan. Kami menghilangkan ekstra itu 1dengan mengurangi truehasil (yang secara numerik memaksa 1) dikembalikan oleh everyoperasi [-1,0,k=1][e](...).


Versi lama:

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

Kode dengan spasi dan komentar:

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

everyMetode array JavaScript mengambil panggilan balik dan menerapkan panggilan balik ke setiap elemen array. Jika ada panggilan balik mengembalikan nilai kesalahan, everypanggilan kembali false.

Boolean di JS dipaksa ke 1 atau 0 saat bagian dari tambahan. Untuk setiap ruang di sekitarnya, kami "menambahkan" hasil boolean dari membandingkan nilainya dengan Xlalu menambahkan nilai itu ke penghitung kdalam ekspresi k += (... == "X"). Oleh karena itu, kberisi hitungan jumlah sekitarnya X, karena truedianggap sebagai 1dan falsedihitung sebagai0 .

apsillers
sumber
Alih-alih c=="X"mencoba !c/1, yang menghemat sejumlah besar byte rejan! Jika gagal, coba !!c/1. Alasannya adalah itu 'X'/1 => NaN, dan NaNitu palsu. Anda memeriksa jika c=='X', mengapa tidak mencoba memeriksa jika tidak false?
Ismael Miguel
@IsmaelMiguel Itu mengevaluasi sama dengan (!c)/1, yang tidak membantu, sayangnya; Saya perlu memiliki tanda kurung untuk !(c/1), yang biayanya 2. Juga, 0/1adalah falsey, jadi input yang salah " 0X" akan memiliki hasil yang salah true. Yang terbaik yang bisa saya lakukan sambil tetap menghargai nol adalah menggabungkan dua kondisi menjadi frase yang dinegasikan, seperti !(+c+1&&k-c), tapi itu sama panjangnya dengan apa yang sudah saya miliki.
apsillers
@ IsmaelMiguel Terima kasih untuk membuat saya berpikir tentang hal itu - saya telah menyadari bahwa !(k-1-c)menguji kedua kondisi, karena jika kcocok c(minus 1 offset), maka negasi membuat 0kebenaran, dan jika cbukan angka, kita dapatkan NaNdan negasi juga true.
apsillers
Kamu benar-benar lapar! Anda makan 10 byte sejak kode awal! Saya sangat suka solusi yang Anda buat. +1 untuk solusi Anda!
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

Ini bisa bermain golf banyak.

Memberi 1untuk papan yang valid dan 0untuk papan yang tidak valid.

Uji kasus

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

Memasukkan

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

Keluaran

1
1
1
0
0
0

Cobalah online di sini

Pengoptimal
sumber
3

JavaScript (ES6) 98

Menggunakan beberapa untuk menerapkan fungsi ke setiap karakter string.
Fungsi kembali

  • salah jika kosong
  • NaN jika 'X' (berulang kali mengurangi nilai dari karakter non numerik seperti 'X' memberi NaN)
  • Nilai numerik dari 0 jika ada jumlah yang tepat dari adiacent 'X', yang lain non 0.
    The inner cek dibuat menggunakan peta hanya karena itu lebih pendek dari forEach

beberapa mengembalikan true pada nilai kebenaran pertama (dalam hal ini, bukan nol) yang berarti cek gagal. Hasilnya dinegasikan untuk memberikan benar / salah yang lebih dikenali.

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
)

Uji di konsol 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)))

Keluaran

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
edc65
sumber
1

R, 156 karakter

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

Dengan indentasi, spasi dan pemisah baris, untuk keterbacaan:

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

Contoh:

> 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
plannapus
sumber