Password forti contro i vescovi


13

Da non confondere con Password Bishop Goodness !

Data una stringa, rispondi (verità / falsità o due valori coerenti) se costituisce una password che è forte contro i vescovi .

Una password è forte contro i vescovi se è una stringa composta da lettere alternate (in a-h) e cifre (in 1-8) in modo tale che ogni coppia di caratteri possa essere interpretata come un quadrato su una scacchiera e se si posiziona un pedone bianco su ogni quadrato chiamato nella password, quindi non c'è modo per un vescovo bianco di viaggiare, in qualsiasi numero di mosse consecutive, da qualsiasi quadrato della prima ( 1) fila a qualsiasi quadrato dell'ultima ( 8) fila.

Esempi

Password forti contro i vescovi

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

Ad esempio, a1b1c1d1e1f1g1a8b8c8d8e8f8g8corrisponde alla posizione fooe b4b5d4d5f4f5g3h5corrisponde alla posizionefoo

Password deboli contro i vescovi

  • a4c4e4g4g5d6f6e3d2b2 (ben formato ma non forte - grazie Jo King per questo esempio!)
  • b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (ben formato ma non forte)
  • h4g4f4e4c4b4a4c3 (ben formato ma non forte)
  • d4 (ben formato ma non forte)
  • b4b5d4d5f4f5g2h5 (ben formato ma non forte)
  • correct horse battery staple (Mal formati)
  • 1a1b1c1d1e1f1g8a8b8c8d8e8f8g (Mal formati)
  • a (Mal formati)
  • aa (Mal formati)

1
Di che colore sono i quadrati del vescovo?
Incarnazione dell'ignoranza il

2
Il 2 ° ultimo test case contraddice le tue specifiche. Devi anche spiegare come " ogni coppia di personaggi può essere interpretata come un quadrato su una scacchiera ".
Shaggy,

1
a1b2c3d4d5f5f4g3g4h2b5 non è forte contro i vescovi, dal momento che un vescovo può arrivare a h5, quindi scendere a d1
Incarnazione dell'ignoranza

2
@TRITICIMAGVS, Ourous: ho chiarito che sia i pedoni che il vescovo sono bianchi, quindi nessuno dei due ha il permesso di catturare (o atterrare, attraversare o saltare) l'altro.
Quuxplusone,

1
Inoltre, potresti aggiungere un esempio per uno dei casi di test veritieri. Perché capisco che i quadrati della password sono pieni di pedine bianche, ma non capisco dove si trova il vescovo bianco. E se un posto va bene, perché non può viaggiare 1attraverso ogni riga 8nel primo caso di test? Non può viaggiare su ogni colonna, poiché la acolonna è completamente piena di pedine, ma può viaggiare su ogni riga senza problemi, non è vero? Ho la sensazione che mi manca qualcosa ..: S
Kevin Cruijssen

Risposte:


4

Rubino, 115 182 163 byte

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

Provalo online!

Restituisce 1per forte e nilper debole. (I +67 byte servivano a tenere conto del "backtracking").

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

Alcuni trucchi che sono stati utilizzati:

  • Invece dell'intervallo numerico 0..99, usiamo l' intervallo di stringhe in'00'..'99' modo tale che il numero venga automaticamente imbottito a sinistra di 2 cifre e stringito. Questo fa sì che il controllo dei limiti sia molto breve - match con regex /[09]/.

  • All'interno della funzione di supporto, durante la creazione dell'elenco di nuove coordinate [x-11, x-9, x+9, x+11], assegniamo contemporaneamente z[x]al 9processo, che risulta essere un valore veritiero (segnando il quadrato visitato).

  • Nell'ultima riga, vogliamo verificare che l'array z[81,9]non contenga 9. Lo facciamo rimuovendo tutte le istanze di 9( z[81,9]-[9]), quindi chiedendo il nono elemento dell'array risultante ( [8]). Dal momento che sappiamo che l'array aveva originariamente 9 elementi, se ne fossero stati rimossi alcuni, avremmo ottenuto nil, mentre se fossero rimasti tutti, avremmo ottenuto l'ultimo elemento dell'array (che sembra essere sempre 1).


2

Python 2 , 330 318 313 309 370 byte

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

Provalo online!

Prova la versione pratica online! (l'originale può richiedere 4 ^ 32 operazioni per controllare completamente, suggerisco di usare questo - stesso numero di byte)

Non è una soluzione super breve - non sono riuscito a capire come rendere una versione della funzione lambda di g più corta di g stessa.

-4 byte grazie a Quuxplusone

+61 byte che rappresentano il backtracking (grazie per averlo sottolineato Jo King e per i suggerimenti sul golf)


Bello. q=r=1sarebbe più corto di q=1 r=1, giusto? E if r:più breve di 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)

Provalo online!

Funziona con "flood-fill". Per prima cosa creiamo un elenco adi quali quadrati sono adiacenti a quali altri quadrati, vescovile. Quindi creiamo un insieme xdi esclusioni (basato sulla password). Quindi inizializziamo un insieme rdi quadrati raggiungibili, che inizia come solo la prima fila (meno eventuali esclusioni) e ripetutamente "inondazioni" verso l'esterno da lì, 99 volte, che dovrebbe essere più che sufficiente. Infine, testiamo per vedere se uno dei quadrati nell'ultima riga è finito nel nostro set raggiungibile. In tal caso, abbiamo una password debole! In caso contrario, abbiamo una password complessa.

Svantaggio, forse squalificante (non conosco la solita regola qui): se la password non è corretta (come "pinzatura corretta della batteria del cavallo"), lanciamo un'eccezione invece di tornare False. Ma restituiamo sempre Truese la password è forte!

Meno 16 byte grazie a Jo King. Ci allineamo anell'unico posto in cui viene utilizzato e pieghiamo costantemente la matematica.

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)

@JoKing grazie! C'è ancora spazio prima di due forsecondi che non riuscivo a vedere come rimuovere. Ho scoperto che la sostituzione range(99)con repr(f)lavori sulla mia macchina locale ma non sull'interprete di tio.run ... ma poi ho scoperto che [1]*99era comunque più breve! In questo modo sono stati salvati altri 4 byte.
Quuxplusone,

spazio bianco prima di due forsecondi che non riuscivo a vedere come rimuovere - Oh! Apparentemente Python tratta 33forcome due token (mentre for33sarebbe un token). Oggi ho imparato. Meno 2 più byte, quindi.
Quuxplusone,

1

Pulito , 285 byte

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

$[]

Provalo online!

$[]è $ :: [[Int]] [Char] -> Boolcomposto con il primo argomento, dando \ [Char] -> Bool.

La funzione funziona consumando la stringa di due caratteri alla volta, restituendo immediatamente falso se la stringa è in un formato non valido non appena vede la parte non valida. Una volta che la stringa è stata elaborata, posiziona un vescovo su ogni quadrato vuoto su un lato del tabellone e li sposta in ogni modo possibile 64 volte e controlla se una delle posizioni finali è nella riga di destinazione.


Sembra restituire erroneamente Trueper a1b1c1d1e1f1g1? Non che io capisca qualcosa su come funziona. :)
Quuxplusone,

2
@Quuxplusone Avevo una scoreggia cerebrale e pensavo che i vescovi bianchi usassero solo quadrati bianchi. Ho anche aggiunto una spiegazione.
Οuroso

1

Wolfram Language (Mathematica) , 339 316 358 353 345 byte

-23 byte grazie a @Doorknob.

+42 byte che rappresentano il backtracking.

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]

Provalo online!

Ho riscritto la maggior parte di questo per tenere conto del backtracking, penso che potrebbe esserci un modo più semplice per definire il grafico g, Mathematica ha GraphData[{"bishop",{8,8}}]quale è il grafico di tutte le mosse che un vescovo può fare su una scacchiera ( Bishop Graph ), ma questo grafico include ulteriori connessioni rispetto al vicino diagonale più vicino. Se qualcuno conosce un modo più breve per farlo, fammelo sapere. Il merito per la costruzione del grafico va a questa risposta MathematicaSE .

I ritorni Trueper password complesse, Falseper deboli / password malformati. Si noti che per la maggior parte delle password malformate produrrà un sacco di messaggi di errore e quindi ritornerà False. Se questo non è in linea con le regole, possono essere soppresse passando f[n_]:=...a f[n_]:=Quiet@...costare 6 byte.

Ungolfed:

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]

Abbattersi:

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

Accetta un argomento stringa e lo divide in un elenco di stringhe ciascuna di lunghezza m.

Check[...,False]

Restituisce Falsese vengono prodotti messaggi di errore, che è il modo in cui catturiamo le stringhe non formate (ovvero supponiamo che siano ben formate, producendo inevitabilmente un errore lungo la linea).

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

Prende la stringa di posizioni di pedone e la divide in modo che "a2h5b"diventi {{"a","2"},{"h","5"},{"b"}}, quindi LetterNumberconverte la lettera in un numero ( a -> 1, ecc.) E FromDigitsconverte il numero in un numero intero. Se la stringa non è ben formata, questo passaggio produrrà un errore che verrà intercettato Checke restituito False. Questi due numeri vengono quindi convertiti in un numero intero corrispondente a un quadrato sul tabellone.

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

Crea il grafico di tutti i bordi diagonali del vicino più vicino con le posizioni del pedone eliminate.

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

Questi sono elenchi di vertici iniziali e finali non occupati rispettivamente

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

Passa sopra i vertici iniziali e finali, per ogni coppia FindPathsarà presente un elenco di percorsi tra di loro. Se non ci sono percorsi tra loro, sarà un elenco vuoto, quindi Length@ritorna 0. Se non ci sono affatto percorsi, allora msarà zero e noi ritorneremo True, altrimenti ritorneremo False.


Alcuni consigli: Truee Falsepuò essere 1>0e 0>1rispettivamente. p[1]@#&/@è equivalente a solo p@1/@. Sequence@@può essere sostituito con ##&@@. Invece di {LetterNumber[#[[1]]],FromDigits[#[[2]]]}&/@, puoi usare {LetterNumber@#,FromDigits@#2}&@@@.
Maniglia della porta

@Doorknob grazie! Il golf del codice mi sta insegnando ogni sorta di novità su Mathematica. Ancora non capisco al 100% p@1/@, ma vedo l'idea generale. Suppongo che p@1 = StringPartition[#,1]&sia un po 'confuso per me, immagino perché pprende due argomenti in due modi diversi, uno come m_e l'altro come #...&, immagino che questa sia solo una questione di precedenza. Ha senso però p@m = p[m].
Kai,

Lo ha fatto anche per me! Il principale cambiamento è che per ogni funzione fche accetta un singolo argomento, f@#&ha lo stesso comportamento di solo f- qui fè p[1]. (Poi ho cambiato la []notazione in @, che è sempre identica tranne che per la precedenza.)
Maniglia della porta

@JoKing che è subdolo, questo è più complicato di quanto pensassi all'inizio, dovendo considerare anche i movimenti all'indietro. Grazie
Kai,

@JoKing ne ha scritto uno nuovo che rappresenta il backtracking.
Kai,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.