I numeri di un cavaliere di Numpad


33

Per le cifre diverse da zero su un tastierino numerico standard

789
456
123

considera di posizionare un cavaliere di scacchi a qualsiasi cifra e spostarlo con un numero qualsiasi di salti a forma di L normali, tracciando un numero intero decimale positivo. Quali numeri interi positivi possono essere espressi in questo modo?

Uno di questi è 38, dal momento che il cavaliere potrebbe iniziare sul 3e spostarsi a sinistra e in alto 8. 381e 383sono anche possibili.

3stesso è possibile se non vengono effettuati salti (il che è consentito). 5è anche, ma non è possibile raggiungere altre cifre da 5, quindi è l'unico numero in cui 5appare la cifra .

Scrivi un programma o una funzione che accetta un numero intero decimale positivo (puoi volerlo come stringa se lo desideri) e stampa o restituisce un valore veritiero se il numero può essere espresso da un cavaliere su un tastierino numerico nel modo descritto, ma altrimenti genera un valore falso .

Vince il codice più breve in byte. Tiebreaker è la risposta precedente

Esempi

Truthy:

1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 18, 38, 61, 81, 294, 349, 381, 383, 729, 767, 38183, 38383, 18349276, 183492761, 618349276

Falsy:

10, 11, 50, 53, 55, 65, 95, 100, 180, 182, 184, 185, 186, 187, 188, 189, 209, 305, 2009, 5030, 3838384, 4838383, 183492760

2
Cosa succede oggi con i cavalieri di scacchi ? MrGreen
Luis Mendo il

1
Suggerimento: se scrivi i numeri come linea di avvolgimento, il cavaliere salta sempre o quattro spazi in senso orario o un contatore di quattro spazi. Non so se sia utile.
Finanzia la causa di Monica il

3
@LuisMendo Wrapping. Come in, se trattate è come un elenco infinito di 78963214, ripetuto più e più volte. Conta le distanze: sono sempre quattro, in un modo o nell'altro. Avrei dovuto essere più chiaro ed esplicitamente detto che devi scriverlo in ordine circolare.
Finanzia la causa di Monica il

@QPaysTaxes Oh, pensavo volessi dire cerchio ma 123...9. Siamo spiacenti
Luis Mendo il

@LuisMendo Nessun problema. Come ho detto, avrei dovuto essere più chiaro su cosa intendevo.
Finanzi la causa di Monica il

Risposte:


16

Gelatina, 19 15 14 byte

Doȷ’d3ạ2\P€=2P

Provalo online! o verifica tutti i casi di test .

Come funziona

Doȷ’d3ạ2\P€=2P  Main link. Argument: n (integer)

D               Convert n to base 10 (digit array).
  ȷ             Yield 1000.
 o              Logical OR. This replaces each 0 with 1000.
   ’            Decrement each digit.
    d3          Divmod; replace each digit k with [k:3, k%3].
      ạ2\       Pairwise reduce by absolute difference.
                For each pair of adjacent digits [i, j], this computes
                [abs(i:3 - j:3), abs(i%3 - j%3)].
         P€     Compute the product of each result.
                n is a Numpad's Knight Number iff all products yield 2.
           =2   Compare each product with 2.
             P  Multiply the resulting Booleans.

18

Python 2, 52 byte

f=lambda n:n<6or`n%100`in'18349276167294381'*f(n/10)

Verifica che nella stringa siano presenti due cifre consecutive '18349276167294381'. Per ottenere cifre consecutive, anziché farlo zip(`n`,`n`[1:]), la funzione controlla ripetutamente le ultime due cifre e rimuove l'ultima cifra.


13

Retina , 58 40 byte

Grazie a Sp3000 per aver suggerito questa idea:

M&!`..
O%`.
A`16|18|27|29|34|38|49|67
^$

Provalo online! (Leggermente modificato per eseguire l'intera suite di test contemporaneamente.)

Stampa 1per verità e 0per risultati falsi.

Spiegazione

M&!`..

Trova tutte le partite sovrapposte di .., vale a dire tutte le coppie consecutive di cifre, e uniscile a avanzamenti di riga.

O%`.

Ordina le cifre in ciascuna riga, in modo che sia necessario controllare solo la metà del numero di coppie.

A`16|18|27|29|34|38|49|67

Rimuovi tutte le linee che corrispondono a una mossa valida.

^$

Conta le partite di questa regex. Cioè, se tutte le linee sono state rimosse, questo corrisponde una volta alla stringa vuota risultante, altrimenti non riesce a corrispondere e dà invece zero.



7

Rubino, 57 byte

Funzione anonima. L'argomento è una stringa.

->n{(0..n.size).count{|i|!"16729438183492761"[n[i,2]]}<1}

Programma con la suite di test:

f=->n{(0..n.size).count{|i|!"16729438183492761"[n[i,2]]}<1}

a=%w{1 2 3 4 5 6 7 8 9 16 18 38 61 81 294 349 381 383 729 767 38183 38383 18349276 183492761 618349276
10 11 50 53 55 65 95 100 180 182 184 185 186 187 188 189 209 305 2009 5030 3838384 4838383 183492760}

a.each {|e|p [e, f[e]]}

Ho appena codificato tutti i possibili movimenti del cavaliere in una stringa e verificato se ogni 2 cifre all'interno dell'input esistevano in quella stringa.


Oh, quella stringa di ricerca mi farebbe anche risparmiare 17 byte. Ti dispiace se lo uso per la mia risposta Retina?
Martin Ender,

Fallo! Basta dare credito, immagino.
Valore inchiostro

Grazie, ma ho finito con una soluzione ancora più breve basata su un suggerimento di Sp3000 :)
Martin Ender

6

grep 58 byte

grep "^((?=18|16|29|27|34|38|49|43|61|67|72|76|81|83|94|92).)*.$"

Perché davvero, se non puoi battere grep ...


2
5185emettono 1con la linea di comando, mentre 5è in truthy, e 185nella lista falsy.
Guntram Blohm sostiene Monica il

1
@GuntramBlohm riparato - perso in una negazione regolare
Yakk,

6

Haskell 46 byte

q=zip<*>tail
all(`elem`q"16729438183492761").q

Esempio di utilizzo: all(`elem`q"16729438183492761").q $ "183492761"->True

Come funziona: utilizza la stringa di ricerca trovata nella risposta di @Kevin Lau . qcrea un elenco di coppie di caratteri adiacenti da una stringa, ad es q "1672" -> [('1','6'),('6','7'),('7','2')]. La funzione restituisce true se tutte le coppie dell'input appaiono nelle coppie della stringa di ricerca. qtrasforma gli input a una cifra nell'elenco vuoto, quindi ha elemsempre successo.


Perché zip<*>tailfunziona come una versione capovolta di zip=<<tail? Penso di non capire cosa generalizzano gli applicativi.
xnor

@xnor: lo uso e basta. <*> è definito come (<*>) f g x = f x (g x) .
nimi,

6

JavaScript (ES6), 65 62 byte

s=>[...s].every((c,i)=>!i|"16729438183492761".match(s[i-1]+c))

Restituisce vero o falso. In precedenza avevo provato una soluzione ricorsiva, che richiede 63 byte, mape anche reducema mi hanno preso 73 byte.

Modifica: salvato 3 byte grazie a @ user81655.


Non avrei potuto fare di meglio, il mio miglior tentativo è stato di 88 byte. Bravo!
Naouak,

@ user81655 Vuoi dire che matchfunziona invece di ~search(ma in entrambi i casi, è davvero subdolo) e |può sostituire ||(ma non nella versione ricorsiva, purtroppo).
Neil

@ user81655 Mi riferivo al modo in cui !i|...matchfunziona perché il risultato della corrispondenza, in caso di successo, è una matrice di una singola stringa di due cifre, che l' |operatore finisce per creare un intero valido.
Neil,

@Neil Ah, giusto.
user81655

6

C, 85 81 byte

golfed:

i;f(char*b){i=*b++-49;return*b?(*b=="8749x7214"[i]||*b=="6983x1632"[i])&&f(b):1;}

Vecchia versione non ricorsiva (85 byte):

i;f(char*b){for(;(i=*b++-49),*b&&*b=="8749x7214"[i]||*b=="6983x1632"[i];);return!*b;}

Vecchio codice con spazi bianchi e programma principale:

i;
f(char*b){
    for (; (i=*b++-49), *b     // i = index of digit + 1 in following arrays
        &&*b=="8749x7214"[i]   // 1st possible jump for 1..9
        ||*b=="6983x1632"[i];  // 2nd possible jump for 1..9
    );
    return !*b;
}

main(){
    char b[16];
    while(scanf("%s", b) == 1) printf("%d",f(b));
    return 0;
}

Questo accetta numeri delimitati da spazi tramite input standard e output 0 se non numpad-knight, o 1 altrimenti.

La nuova versione ricorsiva a 81 byte rade 4 byte.


5

MATL , 38 37 29 byte

Questo utilizza l'idea di @QPaysTaxes .

I:8JK5:7Pvj!Uttnqh?)d|2:EQm}h

L'output è un array 2D, complesso, non vuoto. È vero se tutti i suoi valori hanno una parte reale diversa da zero e falsa altrimenti.

Provalo online!


1
È anche permesso ??
Calcolatrice

La domanda chiede un truthy o un valore falsy, non un intero array.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2
@CatsAreFluffy Questa è la nostra definizione di verità / falsità. Come in MATLAB / Octave, le matrici sono veritiere in MATL se tutti i suoi elementi sono veritieri. ( esempio )
Dennis

CC @ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Dennis


4

MATL, 25 24 33 26 byte

Rasato di 1 byte grazie a @LuisMendo!
@Dennis ha trovato un bug e lo ha risolto! Grazie!

'bSVYXbTUZW'j47-)d2^48\1=A

Prende intero come input. Uscite 1/0.

Provalo online!


@LuisMendo Proprio su entrambi i fronti, grazie!
becher

@Dennis Aggiornato e, si spera, corretto. Grazie per l'aiuto.
becher

Non credo che tu abbia bisogno Adi alla fine. I vettori di MATL sono veritieri se non contengono 0.
Dennis

4

C, 140 92 byte

c;L(char*i){while(*i&&(!c||*i=="6743x1212"[c-49]||*i=="8989x7634"[c-49]))c=*i++;return !*i;}

Supponendo ASCII

Dettagliato Provalo qui

// valid transition from x to n[x-'1'][0 or 1]

int n[9][2] =
{
    {'6','8'},{'7','9'},{'4','8'},
    {'3','9'},{'x','x'},{'1','7'},
    {'2','6'},{'1','3'},{'2','4'}
};

// i is a pointer to where to start on a string

bool L(char * i)
{
    char c = 0;

    // move if not \0 and (not-first-char or is a valid move)

    while((*i) && (!c || (*i)==n[c-'1'][0] || (*i)==n[c-'1'][1]))
    {
        c = (*i++);
    }

    return !(*i); // success if it's \0
}

quelle tabelle di ricerca sono enormi. Puoi migliorare molto il tuo punteggio se ti sbarazzi di tutti i delimitatori {,}[]e invece lo codifichi come una char*stringa. Inoltre, tieni presente che il tuo #definenon è conveniente quando lo usi solo due volte: rimuoverlo ti risparmierebbe 4 byte.
Tucuxi,

@tucuxi grazie per i suggerimenti, sono riuscito a portarlo a 92, avendo \0all'interno l'array causato comportamenti indefiniti, quindi l'ho sostituito conx
Khaled.K

Bello - inoltre, non dimenticare di utilizzare <s>oldscore</s> newscoredurante la modifica per riflettere i miglioramenti del punteggio e <!-- language-all: lang-c -->prima che il codice inizi a correggere l'evidenziazione della sintassi. Sono anche riuscito a ridurre un po 'il mio conteggio di byte facendo cadere del tutto il loop
tucuxi,

Il tuo "dettagliato" sembra molto diverso da una semplice espansione del codice golf (dov'è nnella versione breve?). Inoltre, probabilmente dovresti menzionare che stai assumendo la codifica ASCII: otterrai numeri diversi su macchine EBCDIC.
Toby Speight,

@TobySpeight la versione dettagliata dovrebbe mostrare come è stata sostanzialmente costruita, sì, suppongo ASCII che è il caso comune in C.
Khaled.K

3

Julia, 51 49 byte

n->diff(["@1634@8725"...][digits(n)+1]).^2%48⊆1

Verifica

julia> f=n->diff(["@1634@8725"...][digits(n)+1]).^2%48⊆1
(anonymous function)

julia> all(map(f,(1,2,3,4,5,6,7,8,9,16,18,38,61,81,294,349,381,383,729,767,38183,38383,18349276,183492761,618349276)))
true

julia> any(map(f,(10,11,50,53,55,65,95,100,180,182,184,185,186,187,188,189,209,305,2009,5030,3838384,4838383,183492760)))
false

3

In realtà, 30 byte

;#pXZdX`Σ"67294381";'1+R+íu`Mπ

Accetta l'input come stringa. Emette un numero intero positivo per true e 0 per false.

Provalo online!

Spiegazione:

;#pXZdX`Σ"67294381";'1+R+íu`Mπ
                                 (implicit) push input
;#pXZdx                         push zip(n[:-1], n[1;]) (pairs of digits)
       `Σ"67294381";'1+R+íu`M   map:
        Σ                         join digits
         "67294381";'1+R+         push "16729438183492761" (the magic string used in many other solutions)
                         íu       0-based index (-1 if not found), increment so 0 is not found and >=1 is the 1-based index
                             π  product

3

PowerShell v2 +, 105 96 byte

param($a)((1..$a.length|%{'27618349294381672'.IndexOf($a[$_-1]+$a[$_])+1})-join'*'|iex)-or$a-eq5

Scorre l'input (che deve essere incapsulato con "") verificando che l'indice di qualsiasi coppia sequenziale di caratteri sia nella stringa di ricerca valida. Vedo che Kevin Lau aveva qualcosa di simile , ma l'ho inventato in modo indipendente. Ognuno di quegli indici viene aggiunto con +1, poiché la .IndexOf()funzione tornerà -1se la stringa non viene trovata. Questo trasformerà "non trovato" in 0.

Abbiamo quindi -jointutti i valori interi risultanti con *e pipe a iex(simile a eval). Ciò significa che se non viene trovato nessuno degli indici, si otterrà l'intera espressione 0. Ciò è incapsulato in parentesi e -orcon $a-eq5il caso speciale dell'input "5"per ottenere il risultato risultante.

Esecuzioni di test

PS C:\Tools\Scripts\golfing> 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 18, 38, 61, 81, 294, 349, 381, 383, 729, 767, 38183, 38383, 18349276, 183492761, 618349276 | %{.\numpad-knight-numbers.ps1 "$_"}
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True

PS C:\Tools\Scripts\golfing> 10, 11, 50, 53, 55, 65, 95, 100, 180, 182, 184, 185, 186, 187, 188, 189, 209, 305, 2009, 5030, 3838384, 4838383, 183492760 | %{.\numpad-knight-numbers.ps1 "$_"}
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False

2

C, 78 byte

char*a="9614397052";f(x){int b=x/10;return!b||abs(a[x%10]-a[b%10])%6==1&f(b);}

Dato che tutti gli altri hanno preso l'input come una stringa, ho provato a farlo in numeri interi. Funziona in modo ricorsivo dalla cifra meno significativa ( a%10); se è l'unica cifra, restituisce true. Altrimenti, restituisce vero solo se la cifra delle decine ( b%10) non può essere raggiunta dalla cifra delle unità e (ricorsivamente), il resto dell'input soddisfa lo stesso test.

Il test di raggiungibilità funziona codificando linearmente il tour del cavaliere e convertendo ogni cifra nella sua posizione (da zero a sette) nel tour. Per le cifre 0e 5, assegniamo la posizione nove, che è disconnessa dalle altre posizioni. Quindi, i numeri reciprocamente raggiungibili differiscono di uno (mod otto); cioè a[x%10]-a[b%10]è ± 1 o ± 7. Quindi testiamo la differenza assoluta (mod 6) rispetto a 1.

Questa soluzione funziona per qualsiasi codifica di caratteri valida per C (ovvero le cifre hanno codici contigui da 0 a 9).


1

Java 8, 179 167 byte

Posiziona i tastierino numerico (meno 5 e 0) in un cerchio. lcontiene l'indice del cerchio di questi ints. Se la differenza di due indici è +/- 3 mod 8, allora c'è un movimento dei cavalieri tra gli ints corrispondenti a quegli indici. Si noti che xè un int[].

x->{if(x.length<2)return 1;int[] l={0,0,1,2,7,0,3,6,5,4};int o=l[x[1]];for(int i:x){int n=l[i];if(i%5==0||(Math.abs(n-o)!=3&&Math.abs(n-o)!=5))return 0;o=n;}return 1;}

Aggiornare

  • -11 [16-12-10] Passato a un lambda
  • -1 [16-12-10] Usa <2invece di==1
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.