Verifica il puzzle delle regine


16

Se non sai cos'è una regina negli scacchi, non importa molto; è solo un nome :)

Il tuo input sarà un quadrato di larghezza e altezza arbitrarie contenente una certa quantità di regine. La scheda di input avrà questo aspetto (questa scheda ha una larghezza e un'altezza di 8):

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

Ci sono 8 regine su questa scheda. Se ci fossero, diciamo, 7, o 1, o 10 qui, la scheda non sarebbe valida.

Qui usiamo a .per uno spazio vuoto e a Qper una regina. In alternativa, puoi utilizzare qualsiasi carattere non bianco che desideri.

Questo input può essere verificato come valido e dovresti stampare (o restituire) un valore di verità (se non è valido, dovresti stampare (o restituire) un valore di falsa). È valido perché nessuna regina è nella stessa riga, colonna, diagonale o anti-diagonale di un'altra .

Esempi (non generare elementi tra parentesi):

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

1

...Q.
Q....
.Q...
....Q
..Q..

0

Q.
Q.

0

..Q
...
.Q.

0 (this is 0 because there are only 2 queens on a 3x3 board)


..Q.
Q...
...Q
.Q..

1

Q

1 (this is valid, because the board is only 1x1, so there's no queen that can take another)

Vorrei sottolineare che un input è valido solo se nessuna regina è nella stessa riga, colonna, diagonale o anti-diagonale di un'altra .

Regole

  • Non riceverai mai un input vuoto
  • Se l'input contiene meno regine rispetto alla radice sqaure dell'area della scheda, non è valido.
  • Nota che non esistono soluzioni valide per una scheda 2x2 o 3x3, ma esiste una soluzione per ogni altra scheda quadrata di dimensioni , in cui larghezza e altezza sono un numero naturale.
  • L'input può essere in qualsiasi formato ragionevole, secondo le regole PPCG
  • L'input sarà sempre un sqaure
  • Ho usato 1 e 0 negli esempi, ma puoi usare qualsiasi valore di verità o falsità (come Why yes, sir, that is indeed the casee Why no, sir, that is not the case)

Dato che si tratta di , vince il codice più corto!



1
Would {(x, y, v)}con vin [., Q]essere un formato di input valido?
PidgeyUsedGust

@DuctrTape Non penso che abbia molto senso.
Okx,

2
@Okx In altre parole, stanno chiedendo di ricevere un elenco di coordinate e valori come input. Ad esempio: (0, 0, Q), (0, 1, .), (1, 0, Q), (1, 1, .)sarebbe il terzo caso di test.
Mego

Posso prendere una stringa senza interruzioni di riga?
Tito

Risposte:


7

Lumache , 14 byte

&
o.,\Q!(z.,\Q

Provalo online!

Niente come un linguaggio di corrispondenza dei pattern 2D per un problema di decisione 2D. :)

Spiegazione

La &prima riga è un'opzione della modalità di corrispondenza che richiede che il modello sulla seconda riga corrisponda da ogni posizione possibile nell'input. In tal caso, il programma stampa 1, altrimenti stampa 0.

Per quanto riguarda il modello stesso, nota che )alla fine c'è un implicito .

o       ,, Move in any orthogonal direction (up, down, left or right).
.,\Q    ,, Make sure that there's a Q somewhere in that direction from the
        ,, starting position of the match.
!(      ,, After finding the Q, make sure that the following part _doesn't_ match:
  z     ,,   Move in any orthogonal or diagonal direction.
  .,\Q  ,,   Try to find another Q in a straight line.
)

Perché questo funziona è più facile da vedere partendo dal punto di vista negativo: assicurandoci che non ci sia Quna linea retta dall'altra Qche abbiamo già trovato, ci assicuriamo che non ci siano più di N regine (altrimenti, ci sarebbe essere due di fila, e non sarebbe possibile trovare queste regine senza trovarne un'altra). Quindi la prima parte, assicurandosi che ci sia una regina raggiungibile in una direzione ortogonale da qualsiasi posizione, si accerta che ci siano esattamente N regine. Se ne mancasse uno, ci sarebbero una riga e una colonna senza una regina. A partire dall'intersezione di questi, non sarebbe possibile trovare una regina andando solo in una direzione ortogonale.


6

Gelatina , 17 o 15 byte

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ

Provalo online!

Utilizza per una regina e ¹per uno spazio vuoto. (Ciò è principalmente una conseguenza del divieto di accettare input come array, perché forza l'input in stringhe; la conversione di stringhe in numeri interi è difficile in Jelly, con il metodo più semplice in fase di valutazione e si scopre che invece di 1 e 0, usando "aggiungi 1" ( ) e "aggiungi 0" ( ¹) rendono possibile omettere diverse istruzioni di somma e mappa, perché possiamo contare le regine in un elenco valutandolo.) I valori di verità e falsità sono normali di Jelly 1e 0.

EDIT: La domanda è stata cambiata da quando ho scritto questa risposta per consentire di prendere input come matrice. Ciò consente di eliminare il primo Ỵµ, risparmiando 2 byte. Probabilmente consente anche di cambiare il formato di input in qualcosa di più normale, usando la Ssomma piuttosto che la Vvalutazione, ma non penso che salvi i byte e mi piace un po 'questo formato funky.

Spiegazione

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ
Ỵ                    Split on newlines.
 µ                   Set this value as the default for missing arguments.
     ;  ;            Concatenate the following three values:
  UŒD                - the antidiagonals;
      ŒD             - the diagonals;
         Z           - and the columns.
          V          Evaluate (i.e. count the queens on) all of those.
           Ṁ         Take the largest value among the results.
            ;V       Append the evaluation (i.e. queen count) of {each row}.
              =1     Compare each value to 1.
                Ṃ    Take the minimum (i.e. most falsey) result.

Quindi l'idea di base è che ci assicuriamo che ci sia al massimo una regina su ogni antidiagonale, diagonale e colonna; e esattamente una regina per ogni fila. Queste condizioni sono sufficienti per richiedere che ci sia al massimo una regina su ciascuno dei quattro tipi di linea e un numero di regine pari alla lunghezza laterale della tavola.

Per inciso, Jelly potrebbe probabilmente avere un built-in per gli antidiagonali, ma AFAICT non sembra averne uno, quindi devo accontentarmi di riflettere il tabellone e quindi prendere le diagonali.

Un'altra nota interessante è che il passaggio =1Ṃa E(tutti uguali) fornisce un checker n -queens generalizzato , che accetta anche una scheda n × n in cui ogni riga, colonna, diagonale e antidiagonale contiene non più di k regine e la scheda contiene esattamente kn queens. Limitare k a 1 equivale effettivamente a due byte.


Le regole sono state aggiornate, ora "L'input può essere in qualsiasi formato ragionevole, secondo le regole PPCG", che dovrebbe renderlo più breve :) MODIFICA - Vedo che l'hai notato.
Jonathan Allan,

5

Ottava, 57 70 67 51 52 byte

Salvato 1 byte usando flipinvece di rot90grazie a @LuisMendo, ma ho trovato un bug nel caso 1x1

@(A)all(sum([A A' (d=@spdiags)(A) d(flip(A))],1)==1)

Prende l'input come matrice binaria con 1 che rappresenta una regina e 0 che rappresenta uno spazio vuoto.

Crea una funzione anonima che prima concatena la matrice di input e la sua trasposizione.

spdiagscrea una matrice con lo stesso numero di righe dell'argomento, con le diagonali trasformate in colonne (con riempimento pari a zero, se necessario), quindi concatenate spdiagsla matrice di input per ottenere le diagonali e spdiagsla matrice ruotate orizzontalmente per ottenere gli antidiagonali.

Ora prendi la somma di ogni colonna della matrice concatenata e assicurati che ogni colonna sia esattamente 1.

Esempio eseguito su ideone .


Penso che puoi usare flipinvece dirot90
Luis Mendo il

@LuisMendo Sì, anche quello funzionerà. Grazie!
Becher

Inoltre, non puoi evitare all()?
Luis Mendo,

@LuisMendo Ugh ... probabilmente ... ma dovrà aspettare fino a dopo cena;)
Becher

4

MATL , 38 34 byte

4 byte di sconto grazie a @beaker !

sG!sGt&n_w&:&XdsGP5M&Xdsv2<GnGzU=*

L'input è un array 2D di zeri e uno, che utilizza i punti e virgola come separatori di riga.

Ciò genera un vettore di colonna di quelli come verità e un vettore di colonna che contiene almeno uno zero come falso.

Provalo online! Il codice a piè di pagina è un iframo per dimostrare la verità o la falsità.

Oppure verifica tutti i casi di test .

Spiegazione

s      % Input binary matrix implicitly. Sum of columns. Gives a row vector
G!     % Paste input again. Transpose
s      % Sum of columns (rows in the original matrix). Gives a row vector
G      % Paste input again
t&n    % Duplicate. Push number of rows and number of columns (will be equal)
_w     % Negate, flip
&:     % Binary range. Gives [-n -n+1 ... n] for input of size n×n
&Xd    % Get diagonals -n through n. This gives all diagonals as colums
s      % Sum of each column (diagonals of original matrix). Gives a row vector
GP     % Paste input again. Flip vertically
5M     % Push [-n -n+1 ... n] again
&Xd    % Get diagonals -n through n (anti-diagonals of original matrix)
s      % Sum of each column. Gives a row vector
v      % Concatenate everything into a column vector
2<     % True for elements that are less than 2
Gn     % Paste input again. Number of elements
Gz     % Paste input again. Number of nonzeros (i.e. of queens)
U      % Square
=      % True if equal
*      % Mutiply, element-wise

È possibile salvare 2 byte ora che è possibile prendere una matrice binaria come input.
Becher

2

J , 37 byte

(+/&,=#)*1=[:>./+//.,+//.&|.,+/,+/&|:

Train funzionale anonimo che prende come argomento la matrice booleana.

Provalo online!

( +/la somma &del ,corvo è =uguale #al conteggio delle file)

* e (lit. volte)

1uno è =uguale [:al >./massimo di

+/le somme in /.diagonale ,e (lett. catenate a)

+/le somme in /.diagonale &del |.contrario ,e

+/le somme attraverso ,e

+/le somme &del |:recepimento


2

SnakeEx , 67 byte

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}
e:.$
q:_*Q_*$
n:_+$

Utilizza _al posto di .nell'input. Restituisce 1 o più corrispondenze per verità, 0 corrispondenze per falsità. È possibile trovare un interprete online al link nell'intestazione.

Spiegazione

SnakeEx è un linguaggio della sfida 2-D Pattern Matching . Definisce "serpenti" che si muovono attorno alla roba corrispondente alla griglia. I serpenti possono generare altri serpenti, rendendo la lingua abbastanza potente.

Diamo un'occhiata a questo programma dal basso verso l'alto.

n:_+$

Questo definisce un serpente nche corrisponde a 1 o più caratteri di sottolineatura e quindi al bordo della griglia. Nota che ciò può avvenire in una qualsiasi delle 8 direzioni cardinali: la direzione viene determinata quando viene generato il serpente.

q:_*Q_*$

Simile a nsopra, questo definisce qun serpente che corrisponde a qualsiasi numero di caratteri di sottolineatura, a un singolo Qnumero di caratteri di sottolineatura e al bordo della griglia. In altre parole, una riga / colonna / diagonale che contiene solo una regina.

e:.$

e è un serpente che corrisponde a un personaggio e al bordo della griglia.

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}

Il serpente principale m usa questi blocchi per controllare l'intera scheda. Concettualmente, corre attorno ai bordi esterni della griglia, generando altri serpenti per verificare che tutte le colonne e le righe abbiano esattamente una regina e tutte le diagonali abbiano al massimo una regina. Se uno dei serpenti generati non riesce a combaciare, l'intera partita fallisce. Analizziamolo.

  • ( )%{4}esegue ciò che è racchiuso tra parentesi 4 volte, una volta per lato. (Di seguito, è utile immaginare un lato particolare, ad esempio il bordo superiore della griglia, a partire dall'angolo in alto a sinistra e spostandosi a destra.)
  • {q<>}genera un qserpente nella stessa direzione in cui si muove il serpente principale. Ciò verifica che il limite corrente soddisfi la regola "esattamente una regina". Nota che i serpenti generati non spostano il puntatore della partita del serpente principale, quindi siamo ancora all'inizio del bordo.
  • ( )* corrisponde a 0 o più di ciò che è racchiuso tra parentesi.
  • {q<R>}genera un qserpente girato a destra dalla direzione del serpente principale. (Ad esempio se il serpente principale si muove verso destra lungo il bordo superiore, questo serpente si sposta verso il basso.) Questo controlla ogni colonna / riga.
  • [ ] corrisponde a una delle opzioni tra parentesi:
    • {q<RF>}genera un qserpente ruotato di 45 gradi verso destra (cioè verso destra Re verso l' Finterno) dalla direzione del serpente principale. Il qserpente si abbina se la diagonale contiene esattamente una regina.
    • {n<RF>}genera ninvece un serpente. Il nserpente si abbina se la diagonale non contiene regine.
  • . corrisponde a qualsiasi personaggio, spostando il puntatore della corrispondenza in avanti.
  • Dopo aver verificato il maggior numero possibile di orizzontali e diagonali, verifichiamo di essere al limite generando {e<>}.
  • Infine, <R>gira a destra il serpente principale, pronto per abbinare il bordo successivo.

Cose strane

  • Non c'è nulla nel programma per garantire che la corrispondenza inizi in un angolo esterno. In effetti, i casi di test veritieri producono diverse partite, alcune delle quali iniziano da qualche parte all'interno. Nonostante ciò, nessuno dei casi di falsità che ho provato ha generato falsi positivi.
  • Se sto leggendo correttamente le specifiche della lingua , avrei dovuto essere in grado di utilizzare X(ramo in tutte le direzioni diagonali) al posto di RF. Sfortunatamente, l'interprete online ha affermato che si è trattato di un errore di sintassi. Ho anche provato *(ramo in tutte le direzioni), ma questo ha appeso l'interprete.
  • Teoricamente, qualcosa di simile _*Q?_*$dovrebbe funzionare per abbinare "al massimo una regina" nelle diagonali, ma ciò ha anche appeso l'interprete. La mia ipotesi è che la possibilità di partite vuote causi problemi.

2

Rubino, 120 byte

Funzione lambda basata sulle specifiche originali che richiedono input come stringa.

->s{t=k=0
a=[]
s.bytes{|i|i>65&&(a.map{|j|t&&=((k-j)**4).imag!=0};a<<k)
k=i<11?k.real+1:k+?i.to_c}
t&&~a.size**2>s.size}

converte le Q in numeri complessi e le sottrae le une dalle altre. Se la differenza tra le coordinate di una qualsiasi delle due regine è orizzontale, verticale o diagonale, aumentandola alla 4a potenza si otterrà un numero reale e la disposizione non sarà valida.

Non registrato nel programma di test

f=->s{                                 #Take input as string argument.
  t=k=0                                #k=coordinate of character. t=0 (truthy in ruby.)
  a=[]                                 #Empty array for storing coordinates.
  s.bytes{                             #Iterate through all characters as bytes.
    |i|i>65&&(                         #If alphabetical, compare the current value of k to the contents of a
      a.map{|j|t&&=((k-j)**4).imag!=0} #If k-j is horizontal, vertical or diagonal, (k-j)**4 will be real and t will be false
      a<<k)                            #Add the new value of k to the end of a.
    k=i<11?k.real+1:k+?i.to_c          #If not a newline, increment the imaginary part of k. If a newline, set imaginary to 0 and increment real
  }                                    #s.size should be a*a + a newlines. ~a.size = -1-a.size, so ~a.size**2 = (a.size+1)**2
t&&~a.size**2>s.size}                  #compare a.size with s.size and AND the result with t. Return value. 


p f["...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q.."]

p f["...Q.
Q....
.Q...
....Q
..Q.."]

p f["Q.
Q."]

p f["..Q
...
.Q."]

p f["..Q.
Q...
...Q
.Q.."]

p f["Q"]

2

Python 3 , 232 200 155 byte

d=1
f=input()
Q=[]
for i in f:d=[0,d][i.count('Q')==1];Q+=[(len(Q),i.index('Q'))]
print[0,d][sum(k[1]==i[1]or sum(k)==sum(i)for k in Q for i in Q)==len(Q)]

Provalo online!

-32 byte grazie a @beaker notando un cambiamento nelle specifiche di input; Ho cambiato la lingua da Python 3 a 2, permettendomi così di utilizzare inputinput come array di stringhe o array di array di caratteri.

-45 byte grazie a @Leaky Nun


I requisiti di input sono stati ridotti, se ciò ti aiuta.
bicchiere

@beaker Va bene, grazie. Prenderò input invece come una matrice di stringhe. Grazie per la segnalazione!
HyperNeutrino


1

JavaScript (ES6), 115 byte

a=>!a.some((b,i)=>b.some((q,j)=>q&&h[i]|v[j]|d[i+j]|e[i-j]|!(h[i]=v[j]=d[i+j]=e[i-j]=1))|!h[i],h=[],v=[],d=[],e=[])

Ungolfed:

function queens(arr) {
    horiz = [];
    vert = [];
    diag = [];
    anti = [];
    for (i = 0; i < arr.length; i++) {
        for (j = 0; j < arr.length; j++) {
            if (arr[i][j]) { // if there is a queen...
                if (horiz[i]) return false; // not already on the same row
                if (vert[j]) return false; // or column
                if (diag[i + j]) return false; // or diagonal
                if (anti[i - j]) return false; // or antidiagonal
                horiz[i] = vert[j] = diag[i + j] = anti[i - j] = true; // mark it
            }
        }
        if (!horiz[i]) return false; // fail if no queen in this row
    }
    return true;
}

0

Rubino, 155 byte

->x{(y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2}).zip(y.rotate).map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}.inject(:+)*2==(s=x.size)*~-s}

È orribile da leggere, quindi ho una versione leggermente meno giocata di seguito

->x{
    (y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2})
    .zip(y.rotate)
    .map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}
    .inject(:+)*2==(s=x.size)*~-s
}

Questo è lo stesso codice, ma con alcune righe per separare ciò che sta accadendo.

Il codice stesso è una funzione lambda anonima che accetta una matrice di stringhe ( x) nel formato ["..Q", "Q..", ".Q."].

La prima riga sta mappando ogni stringa sull'indice del carattere Q in quella stringa. Se non è presente alcun carattere Q, viene sostituito con -2 1 . Questo nuovo array di indici è assegnato alla variabile y.

La riga successiva comprime questa matrice di indici con se stessa sfalsata di uno (ruotata). Ciò si traduce in una matrice di coppie di indici consecutivi.

La riga successiva è particolarmente complicata. Passa attraverso ciascuna delle coppie di indici e sottrae il più piccolo dal più grande. Se questo è 1 (e non siamo all'ultima coppia 2 ), allora ci sono due regine che si trovano sulla stessa diagonale e viene inserito un valore -2, altrimenti viene inserito l'indice originale della regina nella stringa .

L'ultima riga riassume tutti gli indici per ciascuno e controlla se è il numero del triangolo per n-1, dove n è la larghezza (o altezza) del quadrato.

1: -1 sarebbe stato il mio go-to, ma è 1 a parte 0, quindi farebbe casino con il controllo delle diagonali. La sua negatività è importante per rendere sbagliata la somma finale. Ho pensato a un numero elevato (con cifre singole) come 9, ma non posso essere sicuro che non comporterà una verifica errata.
2: La scheda non si avvolge, mentre la rotatefunzione array di ruby ​​lo fa, e se l'ultima coppia è diversa per una, non importa - non è una diagonale.


0

PHP, 137 143 byte

ispirato dalla soluzione di Neil

for($n=1+strlen($s=$argv[1])**.5|0;($c=$s[$p])&&!(Q==$c&&$v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++);$p++);echo$n-1==count($a)&&!$c;

accetta input dal primo argomento della riga di comando; corri con -r. Richiede interruzioni di riga a byte singolo.
In realtà puoi usare qualsiasi personaggio tranne 0l'interruzione di riga.
stampa true ( 1) o false (stringa vuota).

abbattersi

for($n=1+strlen($s=$argv[1])**.5|0; // copy input to $s, $n=size+1 (for the linebreak)
    ($c=$s[$p])&&!(                 // loop through characters
        Q==$c&&                         // if queen: test and increment lines
            $v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++
    );                                  // break if a line had been marked before
    $p++);
echo$n-1==count($a)             // print result: true for $n-1(=size) marks
    &&!$c;                      // and loop has finished

0

Python 3 , 185 176 175 172 171 byte

lambda x,c=lambda x:x.count("Q")==1:all([*map(c,x+[[l[i]for l in x]for i in range(len(x[0]))])])*~any(map(lambda s:"Q%sQ"%(s*".")in"".join(x),[len(x[0]),len(x[0])-2]))==-1

Una funzione anonima che accetta un elenco di stringhe come input.

Python 2 , 175 byte

lambda x:all([a.count("Q")==1for a in x]+[[l[i]for l in x].count("Q")==1for i in range(len(x[0]))]+[all(map(lambda s:"Q%sQ"%(s*".")not in"".join(x),[len(x[0]),len(x[0])-2]))])
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.