Haskell , 1080 1033 byte
;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
Provalo online!
Spiegazione
Questo è stato un compito piuttosto interessante per Haskell.
Parità
Per iniziare abbiamo bisogno di un modo per determinare se un personaggio ha un punto di codice pari o dispari. Il modo normale in cui uno potrebbe fare ciò è ottenere il punto di codice e modificarlo di 2. Tuttavia, come si può essere consapevoli, ottenere il punto di codice di un carattere richiede un'importazione, che a causa della restrizione di origine significa che non può essere Usato. Un Haskeller più esperto potrebbe pensare di ricorrere alla ricorsione. Char
fanno parte della Enum
tabella dei tipi in modo che possiamo ottenere i loro predecessori e successori. Tuttavia pred
e succ
sono anche entrambi inutilizzabili perché non fanno parità byte alternate.
Quindi questo ci lascia piuttosto bloccati che praticamente non possiamo fare alcuna manipolazione con i caratteri. La soluzione a questo è di hardcode tutto. Possiamo rappresentare (la maggior parte) anche i caratteri come valori letterali, probabilità con cui abbiamo problemi perché '
è dispari, quindi non può essere accanto al carattere stesso rendendo impossibile letterale esprimere la maggior parte dei caratteri dispari. Quindi codifichiamo tutti i byte pari e quindi aggiungiamo un fermo tutto per i byte dispari alla fine.
Il problema byte
Si può notare che ci sono alcuni byte pari per i quali non è possibile creare valori letterali racchiudendoli tra virgolette singole. Sono gli stampabili, i newline e \
. Non dobbiamo preoccuparci di non stampabili dal momento che non usiamo nessuno di loro che non abbiamo bisogno di verificare. In effetti possiamo ancora usare strani non stampabili, come la scheda, non ne ho bisogno. Newline può essere sagacemente ignorato perché verrà comunque eliminato dal programma. (Potremmo includere newline, perché il suo punto di codice è piuttosto conveniente, ma non è necessario). Questo lascia \
, ora \
ha il punto di codice 92, che convenientemente è un numero dispari seguito da un numero pari, quindi si \92
alterna tra pari e dispari quindi il letterale'\92'
è perfettamente valido. Più tardi, quando avremo bisogno di rappresentare newline, noteremo che fortunatamente ha la stessa proprietà '\10'
.
Problemi di spaziatura
Ora, per iniziare a scrivere il codice effettivo, dobbiamo essere in grado di mettere un numero considerevole di caratteri su una singola riga. Per fare ciò ho scritto il tappo:
;
f=
g
ij=f
a =hi
hi = g
hij= ij
Il cappello non fa altro che essere valido Haskell. Inizialmente avevo sperato di fare delle definizioni che ci avrebbero aiutato nel codice in seguito, ma non è così. Esistono anche modi più semplici per creare il limite, ad esempio spazi bianchi e punti e virgola, ma non salvano byte in questo modo, quindi non mi sono preoccupato di cambiarlo.
Hardcoder
Quindi ora che ho abbastanza spazio su una linea inizio i valori di hardcoding. Questo è per lo più piuttosto noioso, ma ci sono alcune cose di interesse. Per uno, una volta che le linee iniziano a diventare ancora più lunghe, possiamo usare ;
per mettere più dichiarazioni su una linea, il che ci fa risparmiare un sacco di byte.
Il secondo è che dal momento che non possiamo sempre iniziare una linea con un g
ogni tanto dobbiamo indentare un po 'le linee. Ora Haskell si preoccupa davvero del rientro, quindi si lamenterà di questo. Tuttavia, se l'ultima riga prima della riga rientrata termina con un punto e virgola, lo consentirà. Perché? Non ho il più debole, ma funziona. Quindi non ci resta che ricordare di mettere i punti e virgola alla fine delle righe.
Blocchi funzione
Una volta terminato, l'hardcoder naviga senza intoppi fino alla fine del programma. Dobbiamo creare alcune semplici funzioni. Per prima cosa ho creato una versione di drop
, chiamata i
. i
è diverso dal fatto drop
che se proviamo a passare oltre la fine della stringa restituisce semplicemente "y"
. i
è diverso da drop anche in quanto se tenta di rilasciare una nuova riga tornerà "y"
, questi saranno utili perché in seguito quando verificheremo che il programma è un triangolo questo ci permetterà di tornare False
quando l'ultima riga non è completa, o quando una linea finisce presto.
k
k
nSSTrue
nk
n + 1False
Abbiamo poi creare un alias per k
, m
. m
è solo k
con 1
nel primo argomento, e una nuova riga anteporre al secondo argomento.
Quindi abbiamo o
. o
accetta un numero e una stringa. Determina se i byte di stringa (ignorando le nuove righe) si alternano in parità (usando il nostro g
) a partire dal numero di input.
Infine abbiamo quello s
che funziona o
con entrambi 1
e 0
, se uno dei due riesce, si difende m
. Se fallisce, ritorna e basta False
. Questa è la funzione che vogliamo. Determina che l'ingresso è triangolare e alternato.