Hasła silne przeciwko biskupom

13

Nie mylić z Hasłem Biskupa Dobroć !

Biorąc pod uwagę ciąg, odpowiedz (prawda / fałsz lub dwie spójne wartości), jeśli stanowi hasło, które jest silne przeciwko biskupom .

Hasło jest silne przeciwko biskupom, jeśli jest to ciąg składający się z naprzemiennych liter (in a-h) i cyfr (in 1-8), dzięki czemu każda para znaków może być interpretowana jako kwadrat na szachownicy i jeśli umieścisz biały pionek na każdym kwadracie o nazwie w haśle, biały biskup nie ma możliwości podróżowania, w dowolnej liczbie kolejnych ruchów, z dowolnego kwadratu w pierwszym ( 1) rzędzie do dowolnego kwadratu w ostatnim ( 8) rzędzie.

Przykłady

Silne hasła przeciwko biskupom

  • a1b1c1d1e1f1g1h1
  • a8b8c8d8e8f8g8h8
  • a1b2c3d4d5f5f4g3g4h2b5
  • h4g4f4e4c4b4a4c3e3
  • a1b1c1d1e1f1g1a8b8c8d8e8f8g8
  • b4b5d4d5f4f5g3h5

Na przykład a1b1c1d1e1f1g1a8b8c8d8e8f8g8odpowiada pozycji blai b4b5d4d5f4f5g3h5odpowiada pozycjibla

Słabe hasła wobec biskupów

  • a4c4e4g4g5d6f6e3d2b2 (dobrze uformowany, ale nie silny - dzięki Jo King za ten przykład!)
  • b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (dobrze uformowany, ale nie silny)
  • h4g4f4e4c4b4a4c3 (dobrze uformowany, ale nie silny)
  • d4 (dobrze uformowany, ale nie silny)
  • b4b5d4d5f4f5g2h5 (dobrze uformowany, ale nie silny)
  • correct horse battery staple (źle sformowany)
  • 1a1b1c1d1e1f1g8a8b8c8d8e8f8g (źle sformowany)
  • a (źle sformowany)
  • aa (źle sformowany)
Quuxplusone
źródło
1
W jakie kwadraty chodzi biskup?
Embodiment of Ignorance
2
Twój 2. ostatni przypadek testowy jest sprzeczny ze specyfikacją. Musisz także wyjaśnić, w jaki sposóbkażdą parę znaków można interpretować jako kwadrat na szachownicy ”.
Kudłaty
1
a1b2c3d4d5f5f4g3g4h2b5 nie jest silny przeciwko biskupom, ponieważ biskup może dostać się do h5, a następnie zejść do d1
Embodiment of Ignorance
2
@TRITICIMAGVS, Ourous: Wyjaśniłem, że zarówno pionki, jak i biskup są białe, więc ani nie wolno im schwytać (ani wylądować, przejść, ani przeskoczyć) drugiego.
Quuxplusone
1
Czy możesz również dodać przykład jednego z prawdziwych przypadków testowych. Ponieważ rozumiem, że kwadraty hasła są wypełnione białymi pionkami, ale nie rozumiem, gdzie jest biały biskup. A jeśli miejsce jest w porządku, to dlaczego nie mogą podróżować to do każdego wiersza 1przez 8w pierwszym przypadku testowego? Nie może przejść do każdej kolumny, ponieważ akolumna jest całkowicie wypełniona pionkami, ale może bez problemu przejść do każdego rzędu, prawda? Mam wrażenie, że czegoś mi brakuje ...: S
Kevin Cruijssen

Odpowiedzi:

4

Rubin, 115 182 163 bajtów

->s{z=('00'..'99').map{|x|x=~/[09]/||s[(x[1].ord+48).chr+x[0]]};(11..18).map &g=->x{z[x]||[x-11,x-9,x+z[x]=9,x+11].map(&g)};s=~/^([a-h][1-8])*$/&&(z[81,9]-[9])[8]}

Wypróbuj online!

Zwraca 1za mocne i nilsłabe. (Liczba bajtów +67 dotyczyła uwzględnienia „cofania się”).

->s{
 z=                             # this is the board
 ('00'..'99').map{|x|           # coordinates are described as y*10 + x
  x=~/[09]/||                   # truthy if out of bounds...
  s[(x[1].ord+48).chr+x[0]]     # ...or impassable
 }                              # now only the passable squares are falsey
 (11..18).map                   # for each x position at y=1,
  &g=->x{                       # call helper function on that square
   z[x]||                       # if the square is passable (i.e. falsey),
    [x-11,x-9,x+z[x]=9,x+11]    # mark it impassable by setting to 9 (truthy)
     .map(&g)                   # call helper recursively for each neighbor
  }
 s=~/^([a-h][1-8])*$/           # make sure the input was valid,
 &&(z[81,9]-[9])[8]             # and check that the last row was never reached
}

Kilka użytych sztuczek:

  • Zamiast zakresu liczbowego 0..99używamy zakresu ciągów,'00'..'99' dzięki czemu liczba jest automatycznie uzupełniana do lewej o 2 cyfry i dzielona. Sprawia to, że sprawdzanie poza granicami jest bardzo krótkie - dopasowanie z wyrażeniem regularnym /[09]/.

  • Wewnątrz funkcji pomocnika, budując listę nowych współrzędnych [x-11, x-9, x+9, x+11], jednocześnie przypisujemy z[x]do niej 9wartość, która okazuje się być prawdziwą wartością (oznaczenie odwiedzonego kwadratu).

  • W ostatnim wierszu chcemy sprawdzić, czy tablica z[81,9]nie zawiera 9. Robimy to, usuwając wszystkie wystąpienia funkcji 9( z[81,9]-[9]), a następnie prosząc o 9 element wynikowej tablicy ( [8]). Ponieważ wiemy, że tablica pierwotnie zawierała 9 elementów, jeśli jakieś zostały usunięte, otrzymamy nil, natomiast jeśli wszystkie pozostaną, otrzymamy ostatni element tablicy (który zawsze tak jest 1).

Klamka
źródło
2

Python 2 , 330 318 313 309 370 bajtów

import numpy as n
b=n.ones([8,8])
q=r=1
s=input()
l=len(s)
def g(x,y=0,p=0):
    if b[y,x]and p<32:
        if y<7:
            if x<7:
                g(x+1,y+1,p+1)
                if y:g(x+1,y-1,p+1)
            if x:
                g(x-1,y+1,p+1)
                if y:g(x-1,y-1,p+1)
        else:global q;q=0
for i in range(l/2):
    x=ord(s[2*i])-97;y=ord(s[2*i+1])-49
    if y>8or y<0 or l%2or x>8or x<0:r=0
    if r:b[7-y,x]=0
map(g,range(8))
print q&r

Wypróbuj online!

Wypróbuj praktyczną wersję online! (oryginał może zająć 4 ^ 32 operacji, aby sprawdzić całkowicie, sugeruję użycie tego - ta sama liczba bajtów)

Niezbyt krótkie rozwiązanie - nie mogłem wymyślić, jak zrobić wersję g funkcji lambda krótszą niż sam g.

-4 bajty dzięki Quuxplusone

+61 bajtów odpowiadających za powrót (dzięki za zwrócenie uwagi na Jo Kinga i wskazówki dotyczące gry w golfa)

Alec
źródło
Ładny. q=r=1byłoby krótsze niż q=1 r=1, prawda? I if r:krótszy niż if r>0:.
Quuxplusone
2

Python 2 , 490 476 474

def f(p):
 a=[set(ord(c)-33 for c in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()];x=set((ord(p[i+1])-49)*8+ord(p[i])-97 for i in range(0,len(p),2))
 r=set(range(8))-x
 for i in range(99):r=set().union(*[a[c]for c in r])-x
 return all(c<56 for c in r)

Wypróbuj online!

Działa to przez „flood-fill”. Najpierw tworzymy listę, aktóre kwadraty sąsiadują z innymi kwadratami, zgodnie z ruchem wskazówek zegara. Następnie tworzymy zestaw xwykluczeń (na podstawie hasła). Następnie inicjalizujemy zestaw rdostępnych kwadratów, który zaczyna się jako pierwszy rząd (bez jakichkolwiek wykluczeń) i wielokrotnie „zalewa” stamtąd stamtąd, 99 razy, co powinno wystarczyć. Na koniec sprawdzamy, czy którykolwiek z kwadratów w ostatnim rzędzie znalazł się w naszym dostępnym zestawie. Jeśli tak, to mamy słabe hasło! Jeśli nie, mamy silne hasło.

Wada, być może dyskwalifikująca (nie znam tutaj zwykłej reguły): jeśli hasło jest źle sformułowane (takie jak „prawidłowe zszywanie baterii konia”), to zamiast powrotu zwracamy wyjątek False. Ale zawsze zwracamy, Truejeśli hasło jest silne!

Minus 16 bajtów dzięki Jo King. Wstawiamy aw jednym miejscu, w którym jest używany, i stale składamy trochę matematyki.

def f(p):
 x=set(ord(p[i])-489+8*ord(p[i+1])for i in range(0,len(p),2));r=set(range(8))-x
 for i in[1]*99:r=set().union(*[[set(ord(k)-33for k in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()][c]for c in r])-x
 return all(c<56for c in r)
Quuxplusone
źródło
@JoKing dzięki! Przed dwoma sekundami wciąż jest spacja for, której nie widziałem jak usunąć. Przekonałem się, że zastąpienie range(99)go repr(f)działaniem na mojej lokalnej maszynie, ale nie na interpretera tio.run ... ale potem okazało się, że i [1]*99tak było krótsze! Dzięki temu zaoszczędzono jeszcze 4 bajty.
Quuxplusone
spacja przed dwoma forsekundami, których nie mogłem zobaczyć - Och! Najwyraźniej Python traktuje 33forjak dwa tokeny (podczas gdy for33byłby to jeden token). Dzisiaj się uczę. Pomniejsz o 2 kolejne bajty.
Quuxplusone
1

Czysty , 285 bajtów

import StdEnv,Data.List
$_[_]=1<0
$a[x,y:l]=case[[u,v]\\u<-[0..7],v<-[0..7]|u==toInt x-97&&v==toInt y-49]of[p]= $[p:a]l;_=1<0
$a _=all(\[_,y]=y<7)(iter 64(nub o\e=e++[k\\[u,v]<-e,p<-[-1,1],q<-[-1,1],k<-[[abs(u+p),abs(v+q)]]|all((<>)k)a&&all((>)8)k])(difference[[e,0]\\e<-[0..7]]a))

$[]

Wypróbuj online!

$[]jest $ :: [[Int]] [Char] -> Boolskomponowany w oparciu o pierwszy argument, dając \ [Char] -> Bool.

Funkcja działa, wykorzystując ciąg dwóch znaków na raz, natychmiast zwracając wartość false, jeśli ciąg ma nieprawidłowy format, gdy tylko zobaczy nieprawidłową część. Gdy łańcuch zostanie przetworzony, umieszcza gońca na każdym pustym polu po jednej stronie planszy i przesuwa go w każdy możliwy sposób 64 razy i sprawdza, czy którakolwiek z pozycji końcowych znajduje się w docelowym rzędzie.

Obrzydliwe
źródło
Wydaje się niepoprawnie powrócić Truedo a1b1c1d1e1f1g1? Nie, że rozumiem cokolwiek na temat tego, jak to działa. :)
Quuxplusone
2
@Quuxplusone Miałem pierdnięcie mózgu i myślałem, że biali biskupi używają tylko białych kwadratów. Dodałem również wyjaśnienie.
Οurous
1

Wolfram Language (Mathematica) , 339 316 358 353 345 bajtów

-23 bajty dzięki @Doorknob.

+42 bajty odpowiadające za cofanie.

p[m_]:=StringPartition[#,m]&;l=Range@8;f[n_]:=Check[w=(8#2+#1-8)&@@@({LetterNumber@#,FromDigits@#2}&@@@(p@1/@p[UpTo@2]@n));g=Graph[Sort/@UndirectedEdge@@@Position[Outer[EuclideanDistance@##&,#,#,1],N@Sqrt@2]&@GraphEmbedding@GridGraph@{8,8}//Union]~VertexDelete~w;c:=#~Complement~w&;m=0;Do[m+=Length@FindPath[g,i,j],{i,c@l},{j,c[l+56]}];m==0,0>1]

Wypróbuj online!

Przepisałem większość tego, aby uwzględnić powrót do przeszłości, myślę, że może być łatwiejszy sposób zdefiniowania wykresu g, Mathematica ma wykres , GraphData[{"bishop",{8,8}}]który jest wykresem wszystkich ruchów, które biskup może wykonać na szachownicy ( Bishop Graph ), ale ten wykres zawiera dalsze połączenia niż najbliższy diagonalny sąsiad. Jeśli ktoś zna krótszy sposób, aby to zrobić, daj mi znać. Podziękowania dla budowy wykresu należą do tej odpowiedzi MathematicaSE .

Zwraca Truedla silnych haseł, Falsedla słabych / źle sformułowanych haseł. Pamiętaj, że w przypadku większości źle sformułowanych haseł wygeneruje wiele komunikatów o błędach, a następnie wróci False. Jeśli nie jest to zgodne z zasadami następnie mogą być tłumione przez zmianę f[n_]:=...do f[n_]:=Quiet@...kosztują 6 bajtów.

Nie golfowany:

p[m_] := StringPartition[#, m] &;

f[n_] :=
 Check[
  w = (8 #2 + #1 - 
       8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));
  r = GridGraph[{8, 8}];
  g = Graph[Sort /@ UndirectedEdge @@@
             Position[Outer[EuclideanDistance@## &, #, #, 1],N@Sqrt@2] &@
              GraphEmbedding@r // Union]~VertexDelete~w;
  s = Complement[{1,2,3,4,5,6,7,8},w];
  e = Complement[{57,58,59,60,61,62,63,64},w];
  m = 0;
  Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
  If[m == 0,True,False]
  , False]

Awaria:

p[m_]:=StringPartition[#,m]& 

Pobiera argument ciągu i dzieli go na listę ciągów o długości m.

Check[...,False]

Zwraca, Falsejeśli zostaną wygenerowane jakiekolwiek komunikaty o błędach, w ten sposób wychwytujemy źle sformułowane ciągi (tzn. Zakładamy, że są one dobrze sformułowane, co nieuchronnie powoduje błąd wzdłuż linii).

(8*#2 + #1 - 8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));

Pobiera ciąg pozycji pionu i dzieli go w taki sposób, że "a2h5b"staje się {{"a","2"},{"h","5"},{"b"}}, a następnie LetterNumberprzekształca literę na liczbę ( a -> 1itp.) I FromDigitskonwertuje cyfrę na liczbę całkowitą. Jeśli łańcuch nie jest dobrze uformowany, ten krok spowoduje błąd, który zostanie przechwycony przez Checkpowrót False. Te dwie liczby są następnie konwertowane na liczbę całkowitą odpowiadającą kwadratowi na planszy.

r = GridGraph[{8, 8}];
g = Graph[
     Sort /@ UndirectedEdge @@@ 
          Position[Outer[EuclideanDistance@## &, #, #, 1], 
           N@Sqrt@2] &@GraphEmbedding@r // Union]~VertexDelete~w;

Tworzy wykres wszystkich ukośnych krawędzi najbliższego sąsiada z usuniętymi pozycjami pionka.

s = Complement[{1,2,3,4,5,6,7,8},w];
e = Complement[{57,58,59,60,61,62,63,64},w];

Są to odpowiednio listy niezajętych początkowych i końcowych wierzchołków

m=0
Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
If[m == 0,True,False]

Pętle nad początkowymi i końcowymi wierzchołkami, dla każdej pary FindPathbędzie lista ścieżek między nimi. Jeśli nie ma między nimi ścieżek, będzie to pusta lista, więc Length@zwraca 0. Jeśli w ogóle nie ma ścieżek, mwyniesie zero, a my wrócimy True, w przeciwnym razie wrócimy False.

Kai
źródło
Kilka wskazówek: Truei Falsemoże być 1>0i 0>1odpowiednio. p[1]@#&/@jest równoważne z just p@1/@. Sequence@@można zastąpić ##&@@. Zamiast tego {LetterNumber[#[[1]]],FromDigits[#[[2]]]}&/@możesz użyć {LetterNumber@#,FromDigits@#2}&@@@.
Klamka
@Doorknob dzięki! Gra w golfa kodowego uczy mnie wielu nowych rzeczy na temat matematyki. Nadal nie rozumiem w 100% p@1/@, ale widzę ogólny pomysł. Przypuszczam p@1 = StringPartition[#,1]&, że jest to dla mnie nieco mylące, ponieważ pprzyjmuje dwa argumenty na dwa różne sposoby, jeden m_i drugi jako #...&, myślę, że jest to tylko kwestia pierwszeństwa. Ma to jednak sens p@m = p[m].
Kai
Ma to również dla mnie! Główną zmianą jest to, że dla każdej funkcji, fktóra przyjmuje pojedynczy argument, f@#&ma takie samo zachowanie, jak właśnie f- tutaj fjest p[1]. (Potem zmieniłem []notację na @, która zawsze jest identyczna, z wyjątkiem pierwszeństwa.)
Klamka
@JoKing, który jest przebiegły, jest to bardziej skomplikowane, niż początkowo myślałem, biorąc pod uwagę również ruchy do tyłu. Dzięki
Kai
@JoKing napisał nowy, który uwzględnia cofanie się.
Kai