Zweryfikuj tablicę Saper


33

Twoim celem jest sprawdzenie, czy wypełniona tablica Saper jest ważna. Oznacza to, że każda liczba jest prawidłową liczbą min w sąsiadujących z nią komórkach, w tym przekątnych. Plansza się nie zawija.

Jak zwykle powinieneś podać funkcję lub program, a najkrótszy kod w bajtach wygrywa.

Zobacz także poprzednie wyzwania dotyczące generowania , rozwiązywania i pełnego wdrażania Saperów.

Wkład:

Pojedyncza struna tak: 02X2 13X2 X211.

  • Rzędy planszy trałowskiej są oddzielone spacjami. Tak więc powyższe przedstawia planszę 3x4:

    02X2
    13X2
    X211

  • Każda komórka ma postać: Xdla kopalni lub numer 0przez 8.

  • Wszystkie rzędy mają tę samą długość.

  • Istnieją co najmniej 3 rzędy i 3 kolumny.

  • Dane wejściowe nie zaczynają się ani nie kończą spacją, ale możesz dodać nowy wiersz na końcu, jeśli chcesz.

Wydajność:

Spójna Prawda na prawidłowych planszach i spójna wartość Falsey na niewłaściwych planszach. Konsekwencja oznacza, że ​​wszystkie dane wyjściowe Prawdy są takie same, a wszystkie dane wyjściowe Falsey są takie same.

Przypadki testowe

Każda linia to osobny przypadek testowy.

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

Prawdopodobnie powinieneś sprecyzować, że konsekwentny wynik fałszowania musi różnić się od spójnego wyniku prawdziwości ;-)
John Dvorak,

@JanDvorak Powinno to sugerować, że są to odpowiednio Prawda i Falsey.
xnor

Nie całkiem. „prawda” i „fałsz” to tylko dwie etykiety, które pozwalasz nam zdefiniować. Nie widzę żadnych ograniczeń, są one w rzeczywistości prawdą lub fałszem w języku, którego używamy. Jedynym słowem, które może wymagać ich rozróżnienia, jest czasownik „wskazujący”. Nie jestem pewien, czy liczy się to jako specyfikacja (choć nadal jest zabroniona jako standardowa luka).
John Dvorak,

4
@JanDvorak „prawda” i „fałsz” są w rzeczywistości dość powszechnymi terminami, jeśli się nie mylę, w zasadzie używa się ich do opisywania rzeczy (niekoniecznie boolowych), które po wpisaniu na boole mają wartość prawda lub fałsz. Na przykład 0 jest ogólnie fałszem, a 1 ogólnie prawdą.
KSab,

1
@JanDvorak Nie, Truthy / Falsey musi pasować poprawnie / niepoprawnie.
xnor

Odpowiedzi:


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)

Użyłem enumeratew golfa ... a nawet użyłem rangegdzie indziej w tym samym programie. Oczywiście coś jest nie tak.

Edycja: Powtarzaj dict(enumerate(s))zamiast enumerate(s), więc enumeratenie trzeba wywoływać dwa razy.


Co za sprytne wykorzystanie ~! I słowniki, aby indeksowanie poza zakresem działało poprawnie.
xnor

@xnor Twój komentarz na temat ~operatora ironicznie zwrócił uwagę, że użyłem go dwa razy bez żadnego powodu, a użycie go tylko raz oczywiście doprowadziłoby do tego samego. Pomyślałem, że część słownika jest zabawna, dzięki.
feersum

9

Pyth, 43

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

Wypróbuj tutaj .

Wyjaśnienie:

  • Jhxzd: Jest to lokalizacja pierwszego miejsca na wejściu + 1. ( zna wejściu djest spacja.) Jest to separacja na wejściu między sąsiadującymi pionowo komórkami na planszy.
  • !f: Jest to logiczne not ( !) filtru ( f), który będzie Truewtedy i tylko wtedy, gdy wyrażenie będzie fałszem dla każdego elementu sekwencji.
  • -@zT: Weź znak z lokalizacji T(zmienna lambda) z wejścia i usuń wszelkie wyglądy: (To będzie prawda, jeśli znak nie zostanie usunięty, i fałsz, jeśli tak jest.
  • +" X": Usuń spację, X i
  • `: Repr z
  • sm: suma mapy do
  • / \X: liczba „X” w
  • :+*JNz: Wycinek wejścia poprzedzony Jfikcyjnymi znakami
  • td+d2: Od d-1 do d + 2.
  • m+T*kJU3: Dla d w [T, T + J, T + 2 * J].
  • UzDla T w range(len(input)).

7
Downvoters: Dlaczego downvotes?
isaacg

7

APL (NARS2000) (74)

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

Działa również w APL Dyalog, jeśli ⎕MLjest ustawiony na 3.

Wyjaśnienie:

  • ⊃⍵⊂⍨⍵≠' ': podziel na spacje i użyj list do utworzenia matrycy.
  • G←¯1+⎕D⍳: znajdź indeks ⎕Ddla każdej wartości, odejmij 1 i zapisz go w G. ( ⎕Dzawiera cyfry, dowolna cyfra zmieni się w 10).
  • Z←G↑⍨2+⍴G: dodaj dwie linie i kolumny zer na krawędzi macierzy, aby poradzić sobie z zawijaniem
  • {... }¨⍳⍴Z: dla każdej pozycji Zznajdź liczbę bomb w sąsiedztwie Moore tej pozycji:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂Z: obracaj w Zlewo, w prawo, w górę, w dół, w lewo w górę, w prawo w górę, w lewo w dół i w prawo w dół.
    • ⍵∘⌷¨: dla każdego z nich znajdź element w każdej z tych obróconych matryc
    • +/∊9<: policz, ile elementów ma więcej niż 9 (to jest ilość bomb).
  • (⍴G)↑: ponownie usuń dodane linie zer,
  • G=: sprawdź, czy każdy element Gjest równy ilości bomb otaczających tę pozycję (powinno to być prawdziwe dla wszystkich kwadratów niebombowych),
  • (G>9)∨: i sprawdź, czy pierwiastki Gsą wyższe niż 9(to są bomby).
  • ~0∊: zwróć, 1jeśli wynikowa macierz nie zawiera zer (= wszystkie kwadraty to albo bomby, albo poprawna liczba), a 0jeśli tak.

Czy policzyłeś bajty lub znaki? Powinieneś policzyć bajty.
Tim S.

5
@TimS .: Istnieje mnóstwo 1-bajtowych kodowań APL, oto jedno .
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))));}

Pierwsza próba gry w golfa i wiem, że C # nie jest idealnym językiem.

Mam nadzieję, że pisanie metody instancji jest dozwolone, w przeciwnym razie dodaj kolejne 7 znaków dla static.

Rozmieszczone:

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

Korzystanie z Linq oszczędza trochę miejsca w porównaniu do pętli, ale trudniej jest debugować.

Nauczyłem się kilku rzeczy, takich jak konwersja char => intprzez odejmowanie '0'.

Wydawało się, że łatwiej jest wyłożyć planszę spacjami, aby iteracja nad nią była łatwiejsza.


1
Nie można po prostu wymienić -'0'się -48. Działa dla mnie i zapisuje kilka bajtów dla różnych „X” i „”
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)

Jest to w dużej mierze inspirowane odpowiedzią feersum . Kolejność dnia to przesada: zamiast sprawdzać miny w 9 sąsiadach komórki, sprawdź każdą komórkę, aby zobaczyć, czy jest to sąsiednia kopalnia.

Sprawdzamy, czy dwie komórki są sąsiadami 2>r>-2<c<2, gdzie ri gdzie csą różnice między rzędami i kolumnami komórek, równoważne {r,c}<{-1,0,1}. Te współrzędne są obliczane na podstawie indeksów komórek Ioraz ijako c=I%n-i%ni r=I/n-i/n. Bardziej efektywne jest indeksowanie bezpośrednio do ciągu i wyodrębnianie wierszy i kolumn niż przekształcanie go w obiekt 2D, taki jak lista list. Kontrola kopalni jest B[i]>'W'tutaj równoważna B[i]=='X'.

Użycie enumeratezapisałoby dwa znaki na brzydkim, range(len(B))z wyjątkiem tego, że zwraca obiekt iteratora, który nie obsługuje dwóch zagnieżdżonych pętli.


Myślę, że moduł ujemny powinien działać dla n; wtedy możesz użyć ~B.find.
feersum

@feersum Niestety, to psuje, /ponieważ zaokrągla również negatywy w dół.
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))

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

Wprowadź dane wejściowe do funkcji jako ciąg znaków:

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

Wyjaśnienie znajduje się w starej wersji poniżej. Nowa wersja zastępuje forpętle everywywołaniami i używa zmiennej e="every"do wykonania someArray[e](...)zamiast someArray.every(...).

Ponadto licznik kjest teraz indeksowany, 1dzięki czemu k+=...wyrażenie jest zawsze zgodne z prawdą, aby everypętla działała. Eliminujemy to dodatkowe 1, odejmując truewynik (który zmusza liczbowo 1) zwrócony przez everyoperację [-1,0,k=1][e](...).


Stara wersja:

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

Kod ze spacjami i komentarzami:

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

Metoda everytablicowa JavaScript przyjmuje wywołanie zwrotne i stosuje je do każdego elementu tablicy. Jeśli jakakolwiek funkcja zwrotna zwróci wartość falsey, everypołączenie zostanie zwrócone false.

Wartości logiczne w JS są wymuszane na 1 lub 0, gdy są częścią dodatku. Dla każdej otaczającej przestrzeni „dodajemy” wynik boolowski porównując jego wartość, Xa następnie dodajemy tę wartość do licznika kw wyrażeniu k += (... == "X"). Dlatego kzawiera liczbę otaczających Xs, ponieważ trueliczy się jako 1i falseliczy się jako 0.


Zamiast c=="X"próbować !c/1, co oszczędza ogromną ilość krzyczącej pary bajtów! Jeśli to się nie powiedzie, spróbuj !!c/1. Rozumowanie jest takie 'X'/1 => NaNi NaNjest falsie. Sprawdzasz, czy c=='X'nie spróbować false?
Ismael Miguel

@ IsmaelMiguel To ocenia to samo co (!c)/1, co niestety nie pomaga; Musiałbym mieć nawiasy !(c/1), które kosztują 2. Również 0/1jest falsey, więc nieprawidłowe wpisanie „ 0X” miałoby niepoprawny wynik true. Najlepsze, co mogę zrobić, wciąż przestrzegając zer, to połączenie dwóch warunków w negację, na przykład !(+c+1&&k-c), ale ta sama długość, co już mam.
apsillers

@IsmaelMiguel Dziękuję za to, że pomyślałem o tym - uświadomiłem sobie, że !(k-1-c)testuje oba warunki, ponieważ jeśli kpasuje c(minus 1 przesunięcie), to negacja staje się 0prawdą, a jeśli cnie jest liczbą, otrzymujemy NaNi negację jest również true.
apsillers

Naprawdę byłeś głodny! Zjadłeś 10 bajtów od początkowego kodu! Naprawdę podoba mi się rozwiązanie, które wymyśliłeś. +1 za twoje rozwiązanie!
Ismael Miguel

3

CJam, 70 65 63 bajtów

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

Można w to dużo grać w golfa.

Daje 1za prawidłową i 0nieprawidłową tablicę.

Przypadki testowe

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

Wkład

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

Wydajność

1
1
1
0
0
0

Wypróbuj online tutaj


3

JavaScript (ES6) 98

Używanie niektórych do zastosowania funkcji do każdego znaku ciągu.
Funkcja powraca

  • false jeśli puste
  • NaN, jeśli „X” (wielokrotne odejmowanie wartości od znaków nienumerycznych, takich jak „X”, daje NaN)
  • Wartość liczbowa 0, jeśli jest odpowiednia liczba adiacentnego „X”, w przeciwnym razie non 0.
    Wewnętrzna kontrola jest wykonywana przy użyciu mapy tylko dlatego, że jest krótsza niż dla każdego

niektóre zwracają wartość true przy pierwszej wartości zgodnej z prawdą (w tym przypadku niezerowej), co oznacza nieudane sprawdzenie. Wynik jest zanegowany, aby dać bardziej rozpoznawalną wartość prawda / fałsz.

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
)

Testuj w konsoli 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)))

Wydajność

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 znaków

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

Z wcięciami, spacjami i podziałami linii, dla czytelności:

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

Przykłady:

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