Le griglie possono essere formose. Quanto dura il tuo?


12

Considera di rappresentare una curva bidimensionale semplice , aperta su una griglia di testo larga W per altezza in cui Xrappresenta parte della curva e .rappresenta lo spazio vuoto e non vengono utilizzati altri caratteri.

Ogni spazio griglia ha 8 spazi griglia vicini, il suo quartiere Moore . Gli spazi griglia oltre i bordi sono considerati vuoti.

Una griglia contiene una curva se ne ha esattamente una X O se ne ha più di una Xdove:

  • Esattamente due Xsecondi hanno un solo vicino X. Questi sono gli endpoint della curva.
  • Ognuno Xoltre agli endpoint vicini esattamente due Xs. Questi formano il grosso della curva.

Ad esempio, questa griglia in cui W = 9 e H = 4 contiene una curva:

....X....
.X.X.X.X.
X..X..X.X
.XX.....X

Allo stesso modo, queste griglie (W = 4, H = 3) hanno curve:

....  .X..  ....  ....  .X.X
....  X..X  ..X.  XX..  X.X.
..X.  .XX.  .X..  ....  ....

Queste griglie, tuttavia, non contengono una curva:

....  .XX.  ...X  XX..  ....  X.X.
....  X..X  ..XX  XX..  .X.X  .X..
....  .XX.  .X..  ....  ...X  X.X.

Possiamo trovare la lunghezza di una curva sommando le distanze tra tutte le coppie vicine di Xs:

  • La distanza tra due Xs ortogonalmente vicine è 1 unità.

    XX
    X
    X
  • La distanza tra due Xs diagonalmente vicine è di √2 unità.

    X.
    .X
    .X
    X.

Ad esempio, la lunghezza della curva nella griglia

XXX.
...X
..X.

può essere visualizzato come

esempio di lunghezza

quindi possiamo vedere che è 1 + 1 + √2 + √2 = 4.828427 ...

La lunghezza di una curva con una sola Xè zero.

Quando una griglia non forma una curva, la sua lunghezza non è ben definita.

Sfida

Data una griglia di testo di Xs e .s, uscita la lunghezza della curva che contiene, o qualcosa di uscita altro esempio -1o Nullper indicare la griglia ha alcuna curva.

Per l'input è possibile utilizzare caratteri diversi da Xe, .se lo si desidera, e H e W possono essere presi come input, se necessario. Anche l'inserimento come elenco nidificato o matrice riempito con 1 e 0 invece di una stringa va bene.

È possibile generare un valore float per la lunghezza della curva o in alternativa due numeri interi A e B dove length = A + B*√2.

Vince il codice più breve in byte.

Casi test

XXX.
...X
..X.
2 + 2*√2 = 4.828427...

....X....
.X.X.X.X.
X..X..X.X
.XX.....X
3 + 8*√2 = 14.313708...

....
....
..X.
0 + 0*√2 = 0

.X..
X..X
.XX.
1 + 3*√2 = 5.242640...

....
..X.
.X..
0 + 1*√2 = 1.414213...

....
XX..
....
1 + 0*√2 = 1

.X.X
X.X.
....
0 + 3*√2 = 4.242640...

....
....
....
....
-1

.XX.
X..X
.XX.
-1

...X
..XX
.X..
-1

....
.X.X
...X
-1

X.X.
.X..
X.X.
-1

Consiglio di consentire al solutore di scegliere il formato di output per le griglie che non hanno curve (qualsiasi valore coerente che non sia della forma m + n * sqrt (2) per qualsiasi m, n≥0).
Greg Martin,

@Greg Suona bene. Fatto
Calvin's Hobbies,

[x.x,...,.x.]non è una curva valida, giusto?
Magic Octopus Urn

@carusocomputing correct
Calvin's Hobbies

Risposte:


3

MATL , 52 51 byte

t2Y6~Z+*ssGt3Y6Z+*tt1=z2=wssGzqE=*Gz1=+?}_q]ssy-h2/

L'input è una matrice di zero e uno.

L'output è B, quindi A. Le non curve danno un negativo A.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Il calcolo della lunghezza della curva utilizza due convoluzioni 2D 1 : una con la maschera Moore e un'altra con una maschera contenente solo i vicini diagonali. I risultati sono due matrici con la stessa dimensione dell'input, che sarà indicata come M e D , rispettivamente. M indica il numero totale di vicini per ciascun punto, mentre D indica il numero di vicini diagonali.

I risultati in M e D devono essere filtrati per scartare i punti che non appartengono alla curva. Inoltre, devono essere divisi per 2, perché "essere vicini di" è una relazione simmetrica, quindi ogni punto della curva viene contato due volte.

Determinare se la curva è valida è più ingombrante di quanto mi aspettassi. Per fare ciò, il codice verifica tre condizioni:

  1. Il numero di quelli in M è uguale 2? (Cioè, ci sono esattamente due punti con un solo vicino?)
  2. La somma totale di M equivale al numero di punti nella curva di input volte 2meno 2? (Insieme alla condizione 1, verifica se tutti i valori diversi da zero in M tranne due sono uguali 2)
  3. La curva di input contiene un singolo punto?

La curva è valida se le condizioni 1 e 2 sono vere o se la condizione 3 lo è.

t       % Implicit input matrix of zeros and ones. Duplicate
2Y6~    % Push [1 0 1; 0 0 0; 1 0 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix D
ss      % Sum of matrix D
Gt      % Push input again wtice
3Y6     % Push [1 1 1; 1 0 1; 1 1 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix M
tt      % Duplicate twice
1=z     % Number of ones
2=      % Does it equal 2? This is condition 1
wss     % Swap. Sum of matrix
G       % Push input again
zqE     % Number of nonzeros values minus 1, and then multiplied by 2
=       % Are they equal? This is condition 2
*       % Multiply. This is a logical AND of conditions 1 and 2
G       % Push input again
z1=     % Does it contain exactly one nonzero value? This is condition 3
+       % Add. This is a logical OR with condition 3
?}      % If result was false
  _q    %   Negate and subtract 1. This makes sure we get a negative value
]       % End
ss      % Sum of matrix M
y       % Duplicate sum of matrix D from below
-       % Subtract
h       % Concatenate horizontally
2/      % Divide by 2. Implicitly display

1 La convoluzione è la chiave del successo .


1

Python 3 , 316 315 311 byte

Penso che questo copra tutti i casi; almeno i casi di test funzionano.

Inoltre, sicuramente c'è ancora molto da golf, probabilmente all'inizio dove vengono gestiti i casi limite.

def f(d,R,C):
 s=sum;d=[0]*(C+2),*[[0,*r,0]for r in d],[0]*(C+2);o=-1,0,1;k=[[[(1,0),(0,1)][i*j]for i in o for j in o if d[r+i][c+j]and i|j]for c in range(1,-~C)for r in range(1,-~R)if d[r][c]];w=[x/2for x in map(s,zip(*s(k,[])))]or[0,0];print([w,-1][s(w)!=s([s(z)for z in d])-1or[len(t)for t in k].count(1)>2])

Provalo online!

Come funziona:

  1. d,R,C sono 1. un elenco di elenchi con 1 come curva e 0 come sfondo, 2. conteggio di righe e colonne
  2. Inserisci una riga di 0 prima e dopo e una colonna di 0 prima e dopo, dquindi non dobbiamo preoccuparci del bordo dell'array 2d
  3. Per ogni 1 nell'array 2d, scansiona il vicinato per 1 e aggiungi (1,0) a un elenco se la relazione è diagonale, altrimenti aggiungi (0,1)
  4. Somma tutte le tuple, in modo che (n, m) rappresenti il ​​numero di vicini diagonali e non diagonali, rispettivamente
  5. Controlla se il numero di relazioni è esattamente il numero di 1 meno uno; in caso contrario, non una curva.

Grazie a @Helka Homba per aver segnalato un caso mancante. Grazie a @TuukkaX e @Trelzevir per i suggerimenti sul golf.


Sembra d=[[1,0,1],[0,1,0],[1,0,1]]che qui fallirà (aggiunta la testcase).
Calvin's Hobbies

@HelkaHomba Hai ragione, l'ho supervisionato. Grazie! Risolto il problema (ora purtroppo con più byte).
nilo,

1
s=sumsalva 4 byte.
Trelzevir,

0

Mathematica, 153 150 byte

Switch[Sort[Join@@BlockMap[If[#[[2,2]]<1,Nothing,Tr[Tr/@#]]&,#~ArrayPad~1,{3,3},1]],{1},0,{2,2,3...},1/.#~ComponentMeasurements~"PolygonalLength",_,]&

Prende un array 2D, con 0s per .s e 1s per Xs. Uscite Nullper non curve.

1/.#~ComponentMeasurements~"PolygonalLength"&

Mathematica ha un built-in a 45 byte per questo, ma produce alcuni numeri per non curve e 1 / sqrt (2) per l'input {{1}}. Correggere questi costa 105 byte (si potrebbe giocare a golf?).

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.