Les numéros du chevalier d'un pavé numérique


33

Pour les chiffres non nuls sur un pavé numérique standard

789
456
123

Pensez à placer un chevalier d'échecs à n'importe quel chiffre et à le déplacer avec un nombre quelconque de sauts en L normaux, en traçant un entier décimal positif. Quels entiers positifs peuvent être exprimés de cette manière?

L’un d’eux est 38, puisque le chevalier pourrait commencer sur le 3et aller à gauche et jusqu’à 8. 381et 383sont également possibles.

3lui-même est possible si aucun saut n'est effectué (ce qui est autorisé). Cela est 5également le cas, mais aucun autre chiffre ne peut être atteint à partir de la 5, c'est donc le seul numéro où le chiffre 5apparaît.

Ecrivez un programme ou une fonction qui prend un entier décimal positif (vous pouvez le prendre comme une chaîne si vous le souhaitez) et affiche ou renvoie une valeur de vérité si le nombre peut être exprimé par un chevalier sur un pavé numérique de la manière décrite, mais renvoie sinon une valeur de fausseté .

Le code le plus court en octets gagne. Tiebreaker est une réponse plus tôt

Exemples

Vérité

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

Fausseté:

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

2
Qu'en est-il des chevaliers d'échecs aujourd'hui ? :-D
Luis Mendo

1
Astuce: Si vous écrivez les numéros comme une ligne d’emballage, le chevalier saute toujours quatre cases dans le sens des aiguilles d’une montre ou quatre. Je ne sais pas si cela est utile.
Fonds de la poursuite de Monica

3
@LuisMendo Wrapping. Comme dans, si vous traitez est une liste interminable de 78963214, répétée encore et encore. Comptez les distances - c'est toujours quatre, d'une manière ou d'une autre. J'aurais dû être plus clair et avoir explicitement dit qu'il fallait l'écrire dans l'ordre des cercles.
Le procès de Monica

@QPaysTaxes Oh, je pensais que tu voulais dire cercle mais 123...9. Désolé
Luis Mendo

@ LuisMendo Pas de soucis. Comme je l'ai dit, j'aurais dû être plus clair sur ce que je voulais dire.
Le procès de Monica

Réponses:


16

Jelly, 19 15 14 octets

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

Essayez-le en ligne! ou vérifier tous les cas de test .

Comment ça marche

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 octets

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

Vérifie que deux chiffres consécutifs sont dans la chaîne '18349276167294381'. Pour obtenir des chiffres consécutifs, plutôt que de le faire zip(`n`,`n`[1:]), la fonction vérifie à plusieurs reprises les deux derniers chiffres et supprime le dernier chiffre.


13

Retina , 58 à 40 octets

Merci à Sp3000 pour avoir suggéré cette idée:

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

Essayez-le en ligne! (Légèrement modifié pour exécuter la suite de tests complète en une fois.)

Imprime 1pour la vérité et 0pour les résultats faux.

Explication

M&!`..

Recherchez toutes les correspondances superposées de .., c'est-à-dire toutes les paires de chiffres consécutives, et joignez-les à des sauts de ligne.

O%`.

Triez les chiffres dans chaque ligne, de sorte que nous n’ayons à vérifier que deux fois moins de paires.

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

Supprimez toutes les lignes qui correspondent à un mouvement valide.

^$

Comptez les correspondances de cette regex. C'est-à-dire que si toutes les lignes ont été supprimées, cela correspond à la chaîne vide résultante une fois, sinon elle ne correspond pas et donne la valeur zéro.



7

Ruby, 57 octets

Fonction anonyme. L'argument est une chaîne.

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

Programme avec la suite de tests:

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

Je viens de coder tous les mouvements possibles de chevaliers dans une chaîne et de vérifier si tous les 2 chiffres de l'entrée existaient dans cette chaîne.


Oh, cette chaîne de recherche me permettrait également de gagner 17 octets. Est-ce que ça vous dérange si j'utilise ça pour ma réponse à la rétine?
Martin Ender

Fonce! Donnez juste le crédit, je suppose.
Valeur d'encre

Merci, mais je me suis retrouvé avec une solution encore plus courte basée sur une suggestion de Sp3000 :)
Martin Ender

6

grep 58 octets

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

Parce que vraiment, si vous ne pouvez pas battre Grep ...


2
Ni 5ni 185émettre 1avec votre ligne de commande, tandis que 5est dans la vérité, et 185dans la liste de fausseté.
Guntram Blohm soutient Monica

1
@GuntramBlohm corrigé - s'est perdu dans la négation régulière
Yakk

6

Haskell 46 octets

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

Exemple d'utilisation: all(`elem`q"16729438183492761").q $ "183492761"->True

Comment cela fonctionne: Il utilise la chaîne de recherche trouvée dans la réponse de @Kevin Lau . qfait une liste de paires de caractères adjacents d'une chaîne, par exemple q "1672" -> [('1','6'),('6','7'),('7','2')]. La fonction renvoie true si toutes les paires de l'entrée apparaissent dans les paires de la chaîne de recherche. qtransforme les entrées à un chiffre en liste vide, donc elemréussit toujours.


Pourquoi zip<*>tailfonctionne comme une version retournée de zip=<<tail? Je pense que je ne comprends pas ce que les applications généralisent.
xnor

@xnor: je viens de l'utiliser. <*> est défini comme (<*>) f g x = f x (g x) .
Nimi

6

JavaScript (ES6), 65 62 octets

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

Renvoie vrai ou faux. J'avais déjà essayé une solution récursive, qui prend 63 octets, mapet même, reducemais ils m'ont pris 73 octets.

Edit: 3 octets sauvegardés grâce à @ user81655.


Je ne pouvais pas faire mieux, mon meilleur essai était à 88 octets. Bravo!
Naouak

@ user81655 Vous voulez dire matchtravaux au lieu de ~search(mais de toute façon, c'est vraiment sournois) et |peut remplacer ||(mais pas dans la version récursive, malheureusement.)
Neil

@ user81655 Je faisais référence à la façon dont cela !i|...matchfonctionne car le résultat de la correspondance, en cas de succès, est un tableau d'une seule chaîne de deux chiffres, que l' |opérateur finit par forcer à former un entier valide.
Neil

@ Neil Ah, c'est vrai.
user81655

6

C, 85 81 octets

Golfé:

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

Ancienne version non récursive (85 octets):

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

Ancien code avec espace et programme principal:

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

Ceci accepte les nombres délimités par des espaces via l'entrée standard et les sorties 0, sinon numpad-knight, ou 1 sinon.

La nouvelle version récursive de 81 octets supprime 4 octets.


5

MATL , 38 37 29 octets

Ceci utilise l' idée de @QPaysTaxes .

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

La sortie est un tableau 2D, complexe et non vide. C'est la vérité si toutes ses valeurs ont une partie réelle non nulle, et la fausseté autrement.

Essayez-le en ligne!


1
Est-ce même permis ??
CalculatriceFeline

La question demande une truthy ou une valeur falsy, pas un tableau entier.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2
@CatsAreFluffy C'est notre définition de la vérité / de la fausseté. Comme dans MATLAB / Octave, les tableaux sont la vérité dans MATL si tous ses éléments sont la vérité. ( exemple )
Dennis

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


4

MATL, 25 24 33 26 octets

Rasé 1 octet grâce à @LuisMendo!
@Dennis a trouvé un bogue, puis l'a corrigé! Merci!

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

Prend un entier en entrée. Sorties 1/0.

Essayez-le en ligne!


@LuisMendo Bien sur les deux points, merci!
Bécher

@Dennis Mis à jour et, espérons-le, correct. Merci de votre aide.
Bécher

Je ne pense pas que tu aies besoin de ça Aà la fin. Les vecteurs de MATL sont à vérifier si et seulement s'ils ne contiennent pas de 0.
Dennis

4

C, 140 92 octets

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

En supposant ASCII

Détaillé Essayez-le ici

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

ces tables de consultation sont énormes. Vous pouvez améliorer beaucoup votre score si vous vous débarrassez de tous les délimiteurs {,}[]et que vous le codez sous forme de char*chaîne. Notez également que votre utilisation #definen'est pas rentable lorsque vous ne l'utilisez que deux fois: sa suppression vous permettrait d'économiser 4 octets.
Tucuxi

@tucuxi merci pour les conseils, j'ai réussi à le ramener à 92, \0le tableau ayant provoqué un comportement indéfini, je l'ai donc remplacé parx
Khaled.K

Sympa - n'oubliez pas non plus de l'utiliser <s>oldscore</s> newscorelors de l'édition pour refléter les améliorations apportées au score et <!-- language-all: lang-c -->avant que votre code ne commence à corriger la mise en surbrillance de la syntaxe. J'ai également réussi à réduire un peu le nombre d'octets en abandonnant complètement la boucle.
tucuxi

Votre "détail" est très différent d'une simple extension du code de jeu (où est nla version courte?). En outre, vous devriez probablement mentionner que vous supposez le codage ASCII - vous obtiendrez des numéros différents sur les ordinateurs EBCDIC.
Toby Speight

@TobySpeight la version détaillée est censée montrer comment elle a été construite. Oui, je suppose que l'ASCII est le cas habituel en C.
Khaled.K

3

Julia, 51 49 octets

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

Vérification

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

En fait, 30 octets

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

Prend l'entrée sous forme de chaîne. Affiche un entier positif pour vrai et 0 pour faux.

Essayez-le en ligne!

Explication:

;#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 octets

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

Parcourt l'entrée (qui doit être encapsulée avec "") en vérifiant que l'index de toute paire de caractères séquentielle se trouve dans la chaîne de recherche valide. Je vois que Kevin Lau avait quelque chose de similaire , mais je l'ai inventé de manière indépendante. Chacun de ces index est ajouté avec +1, comme la .IndexOf()fonction retournera -1si la chaîne n'est pas trouvée. Cela transformera les "non trouvés" en 0.

Nous avons ensuite -jointoutes les valeurs entières résultantes avec *et conduisent à iex(similaire à eval). Cela signifie que si l’un des index n’est pas trouvé, l’expression entière en résulte 0. Cela est encapsulé entre parenthèses et -oravec $a-eq5le cas particulier d’entrée "5"pour obtenir notre sortie résultante.

Essais

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 octets

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

Comme tout le monde a pris l’entrée sous forme de chaîne, j’ai essayé de le faire en nombres entiers. Cela fonctionne de manière récursive à partir du chiffre le moins significatif ( a%10); si c'est le seul chiffre, alors retourne vrai. Sinon, ne retourne vrai que si le chiffre des dizaines ( b%10) ne peut pas être atteint à partir du chiffre des unités et que (de manière récurrente), le reste de l'entrée satisfait au même test.

Le test d'accessibilité fonctionne en encodant le tour du chevalier de manière linéaire et en convertissant chaque chiffre en sa position (zéro à sept) sur le tour. Pour les chiffres 0et 5, nous affectons la position neuf, qui est déconnectée des autres positions. Ensuite, les nombres mutuellement joignables diffèrent de un (mod huit); c'est à direa[x%10]-a[b%10] - soit ± 1 ou ± 7. Nous testons donc la différence absolue (mod 6) contre 1.

Cette solution fonctionne pour tout codage de caractères valable pour C (c'est-à-dire que les chiffres ont des codes contigus de 0 à 9).


1

Java 8, 179 167 octets

Place les touches numériques (moins 5 et 0) dans un cercle. ldétient l'index de cercle de ces ints. Si la différence de deux indices est de +/- 3 mod 8, il y a un mouvement de chevalier entre les ints correspondant à ces indices. Notez que xc'est 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;}

Mise à jour

  • -11 [16-12-10] Basculé sur un lambda
  • -1 [16-12-10] Utiliser <2au lieu de==1
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.