L'algorithme de Luhn pour la vérification des numéros de carte de crédit, etc.

50

Défi

Écrivez le programme ou la fonction le plus court pour calculer l' algorithme de Luhn permettant de vérifier les numéros (de carte de crédit).

Algorithme de Luhn expliqué

À partir de RosettaCode , cet algorithme est spécifié en tant que tel, avec l'exemple de l'entrée suivante 49927398716:

Reverse the digits, make an array:
    6, 1, 7, 8, 9, 3, 7, 2, 9, 9, 4
Double the numbers in odd indexes:
    6, 2, 7, 16, 9, 6, 7, 4, 9, 18, 4
Sum the digits in each number:
    6, 2, 7, 7, 9, 6, 7, 4, 9, 9, 4
Sum all of the numbers:
    6 + 2 + 7 + 7 + 9 + 6 + 7 + 4 + 9 + 9 + 4 = 70
If the sum modulo 10 is 0, then the number is valid:
    70 % 10 = 0 => valid

Règles IO

Entrée : une chaîne ou un nombre (votre choix), dans le format d'entrée / sortie de votre langue

Sortie : une valeur de vérité ou de fausseté , respectivement, indiquant si l'entrée est valide ou non selon le test ci-dessus.

Notes / Conseils

  • Essayez de ne pas poster accidentellement vos propres numéros de carte de crédit ou de compte si vous les utilisez pour tester :)

  • Si l'entrée est invalide et impossible à traiter avec l'algorithme spécifié (c'est-à-dire trop courte pour fonctionner), vous pouvez faire ce que vous voulez, y compris faire exploser mon ordinateur.

  • Cependant , la balle précédente ne signifie pas que votre langue peut faire ce qu'il veut avec des chiffres qui sont trop grands pour lui à gérer. Si votre langue n'est pas capable de gérer un scénario de test, envisagez de prendre une chaîne en tant qu'entrée.

Exemples

Les exemples suivants ont été validés avec ce script Python ; si vous pensez que vous avez tort ou si vous avez une question, envoyez simplement une requête ping à @cat.

49927398716      True
49927398717      False
1234567812345670 True    
1234567812345678 False
79927398710      False
79927398711      False
79927398712      False
79927398713      True
79927398714      False
79927398715      False
79927398716      False
79927398717      False
79927398718      False
79927398719      False
374652346956782346957823694857692364857368475368 True
374652346956782346957823694857692364857387456834 False
8 False **
0 True  **

** selon l'implémentation Python, mais vous pouvez faire n'importe quoi car elles sont trop courtes pour être éligibles par un strict respect de la spécification.


Si l'une des réponses ci-dessus invalide les réponses existantes (bien que j'estime que cela ne devrait pas être possible), ces réponses sont toujours valables. Cependant, les nouvelles réponses, pour être valables, devraient suivre la spécification ci-dessus.

Classement

Chris Laplante
la source

Réponses:

21

Golfscript - 24 caractères

-1%{2+0!:0)*109%+}*10%8=

Explication:

  1. -1% inverse la chaîne
  2. {commence un bloc (que nous utilisons comme une boucle). Chaque caractère dans les chaînes est poussé comme valeur ascii.
    1. 2+ ajoute 2. (la valeur ascii d'un chiffre est 48 + n, nous avons donc 50 + n maintenant et le dernier chiffre est n)
    2. 0!:0 inverse la valeur de 0 et la stocke (tout est une variable), nous avons donc 1 à la première itération, 0 à la seconde, etc.
    3. )* ajoute un à cette valeur et la multiplie, donc on multiplie par 2, puis 1, puis 2, etc.
    4. 109% reste modulo 109. Ceci n'affecte que les valeurs 5-9 qui ont été doublées et les réduit à la valeur correcte.
    5. + ajoute cette valeur à la somme courante
  3. }*termine le bloc et fait une opération de "pli". D'abord, le premier caractère est poussé (puisque nous avons inversé, c'est le chiffre de contrôle). Ensuite, alternez pousser et exécuter le bloc. Ainsi, nous utilisons la valeur ascii du premier caractère comme valeur de départ pour la somme en cours d'exécution.
  4. 10% prend le reste modulo 10.
  5. 8= retournera 1 si la valeur est 8. Nous l'utilisons parce que nous n'avons pas normalisé le premier caractère poussé (le chiffre de contrôle).

On pourrait penser que nous pourrions utiliser 8-au lieu de 2+sauvegarder un caractère en changeant 109%à 89%, sauf que nous aurions besoin d'ajouter un espace pour que la -soustraction soit (au lieu de -0).

Nabb
la source
11

GolfScript, 44 caractères

-1%{16%}%2/1,\+{(\.{0=2*.9>9*-+}{;}if+}*10%!

Commentaire sélectionné

Fait intéressant, les deux premiers éléments ci-dessous illustrent trois utilisations complètement différentes de l' %opérateur: sélection de tableau, carte et mod. La plupart des opérateurs GolfScript sont "sensibles au contexte", ce qui leur confère des comportements extrêmement divergents en fonction du type d'argument.

  1. -1%inverse la chaîne. Ceci est important car les paires de chiffres sont comptées à partir de la droite.
  2. {16%}% convertit tous les chiffres ASCII en nombres, en les modifiant avec 16.
  3. 2/ divise le tableau en groupes de 2.
  4. 1,est un moyen peu coûteux de faire [0].
  5. \+ajoute effectivement le 0 au tableau de chiffres. Il le fait en permutant puis en concaténant.

Le 0 est ajouté avant le pli qui vient ensuite. Plutôt que de prendre une valeur initiale explicite, le pli de GolfScript utilise le premier élément du tableau comme valeur initiale.

Maintenant, regardons la fonction de pliage réelle. Cette fonction prend deux arguments: la valeur repliée et l'élément en cours sur le tableau (qui dans ce cas sera un tableau de 2 ou (inhabituellement) 1, en raison de la valeur 2/antérieure). Supposons que les arguments sont 1 [2 3].

  1. (\.divise l'élément de tableau le plus à gauche, déplace le tableau restant au premier plan, puis le copie. Stack maintenant ressemble à : 1 2 [3] [3].
  2. Le ifvérifie si le tableau est vide (ce qui est le cas pour le dernier groupe lorsqu'il s'agit d'un numéro de compte impair). Si tel est le cas, aucun traitement spécial n'est effectué (il suffit de supprimer le tableau vide).
  3. Pour un groupe pair:
    1. 0= récupère le premier (seul, dans ce cas) élément du tableau. 1 2 3
    2. 2* double le nombre. 1 2 6
    3. .9>9*- soustrait 9 du nombre s'il est supérieur à 9. Implémenté sous la forme: copiez le nombre, comparez-le à 9, multipliez le résultat (qui est 0 ou 1) par 9, puis soustrayez. 1 2 6
    4. + ajoute enfin cela au premier numéro. 1 8
  4. +(after the if) ajoute le résultat de ifà la valeur d'origine, donnant ainsi la nouvelle valeur pliée.

Une fois le pliage terminé, modifiez simplement avec 10 ( 10%) et annulez le résultat ( !). Vous renvoyez donc 1 ssi la somme est un multiple de 10.

Chris Jester-Young
la source
Cela semble renvoyer 0 pour le numéro d'exemple sur wikipedia (49927398716)
gnibbler
nm. J'ai oublié d'utiliserecho -n
gnibbler
1
@gnibbler: Haha, échoue. :-P (Sérieusement, je me suis aussi fait piquer par celui-là, lors de mes premiers tests.)
Chris Jester-Young
1
Quelques endroits pour enregistrer quelques personnages faciles ici. -1% 2/peut être combiné dans -2/. 1,peut être remplacé par 0(0 est forcé dans un tableau, puis +est concaténé). 9>9*-peut être remplacé par 9>+(puisque nous ne nous intéressons qu'au dernier chiffre). En outre, la vérification des longueurs impaires est un peu longue, l'utilisation .,2%,\+est plus courte. Après cela, nous pouvons aussi changer {16%}%et (\0=en {16}/(à l'intérieur de la boucle). Une fois que vous avez fait tout ça, ça va ressembler à quelque chose comme ceci: .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb
@Nabb: Merci! Je les intégrerai dans ma solution, même s'il semble que vous en ayez déjà une qui donne un sérieux coup de pied au cul. :-)
Chris Jester-Young le
11

Python, 73 69 caractères

def P(x):D=map(int,x);return sum(D+[d-d/5*9for d in D[-2::-2]])%10==0
Keith Randall
la source
4
Vous pouvez enregistrer deux autres caractères en évitant de revenir en arrière: D[-2::-2]-> D[1::2]l'ordre des sommes n'a pas d'importance :)
ThinkChaos
==0peut être raccourci à<1
Black Owl Kai
10

Python 3, 77 octets

c=lambda a:sum(sum(divmod(int(a[-e-1])<<e%2,10))for e in range(len(a)))%10==0
Alexandru
la source
9

Caractères C # 119:

bool l(string n){return(String.Join("",n.Reverse().Select((x,i)=>(x-48)*(i%2<1?1:2)+"").ToArray()).Sum(x=>x-48))%10<1;}

Pas trop mal pour un code golf n00b dans un langage typé statiquement, j'espère.

Cela peut être réduit à 100 :

bool l(string n){return String.Join("",n.Reverse().Select((x,i)=>(x-48)*(i%2+1))).Sum(x=>x+2)%10<1;}
mootinator
la source
C'est une bonne idée et une approche intéressante, mais cela ne semble pas fonctionner. Du moins pas avec mes quelques tests. Il semble que le "i" de votre premier lambda soit censé être l'index du caractère de la chaîne. Est-ce que ça marche comme il se doit? Si tel est le cas, pourquoi inversez-vous la chaîne uniquement pour la modifier en fonction de la position de l'index? Semble un peu redondant, non?
Nellius
J'ai seulement testé une de mes cartes de crédit et quelques-unes de ses erreurs TBH. (Utilisation du débogueur de VS 2008) L’algorithme est censé doubler tous les deux chiffres en commençant par le dernier. Si je n'inversais pas la chaîne, ce serait incorrect pour les chaînes de longueurs impaires.
Mootinator
Il s'avère que j'ai eu le résultat de i%2<1?1:2revenir en arrière. Merci.
Mootinator
8

Golfscript - 34 caractères

{15&}%.-2%\);-2%{.+(9%)}%+{+}*10%!

Exemple numéro de la page wikipedia 4992739871

{15&}%  does a bitwise and of each ascii digit with 00001111
        now I have a list of digits 
        [4 9 9 2 7 3 9 8 7 1 6]
.       makes a copy of the list, now I have two identical lists
        [4 9 9 2 7 3 9 8 7 1 6] [4 9 9 2 7 3 9 8 7 1 6]
-2%     like [::-2] in python takes every second element in reverse
        [4 9 9 2 7 3 9 8 7 1 6] [6 7 9 7 9 4]
\       swap the two lists around
        [6 7 9 7 9 4] [4 9 9 2 7 3 9 8 7 1 6]
);      drop the last digit off the list
        [6 7 9 7 9 4] [4 9 9 2 7 3 9 8 7 1]
-2%     same as before
        [6 7 9 7 9 4] [1 8 3 2 9]
{       for each item in the list ...
.+      ... double it ...
(       ... subtract 1 ...
9%      ... mod 9 ...
)}%     ... add 1 ...
        [6 7 9 7 9 4] [2 7 6 4 9]
+       join the two lists
        [6 7 9 7 9 4 2 7 6 4 9]
{+}*    add the elements up
        70
10%     mod 10
        0
!       invert the result
        1
gnibbler
la source
Le .+(9%)est très innovant (pour moi en tout cas). J'aime! +1
Chris Jester-Young
Cependant, GolfScript a besoin d’un opérateur de partitionnement, vous n’avez donc pas besoin de faire ceci: "Laisser tomber l’élément final et répéter" un non-sens. :-)
Chris Jester-Young
1
@Chris, j'ai entendu parler de cela il y a plusieurs années, appelé "casting out nines". C’est un bon moyen de vérifier deux fois les additions et les multiplications
faites à la main
3
Cela ne fonctionnera pas si la valeur 0 est doublée ( 0(9%)vaut 9 et non 0).
Nabb
8

PHP, 108 octets

<?function v($s,$t=0){for($i=strlen($s);$i>=0;$i--,$c=$s[$i])$t+=$c+$i%2*(($c>4)*-4+$c%5);return!($t % 10);}
Juan
la source
7

Ruby - 85 caractères

def f s
l=s.size
s.chars.map{|k|(i=k.to_i*((l-=1)%2+1))%10+i/10}.inject(:+)%10==0
end
Nemo157
la source
Vous êtes probablement au courant, mais vous pouvez utiliser .sum au lieu de .inject (: +) pour sauvegarder 7 octets.
Håvard Nygård
7

Haskell, 96 octets

Il doit y avoir un moyen meilleur / plus court, mais voici ma solution Haskell en 96 caractères :

l=(==0).(`mod`10).sum.zipWith($)(cycle[id,\x->x`mod`5*2+x`div`5]).reverse.map((+(-48)).fromEnum)

Malheureusement, la digitToIntfonction ne peut être utilisée que si vous en êtes le import Data.Charpremier. Sinon, je pourrais passer à 88 caractères en remplaçant ((+(-48)).fromEnum)par digitToInt.

sepp2k
la source
6

Windows PowerShell, 82

filter f{!((''+($_[($_.length)..0]|%{+"$_"*($i++%2+1)})-replace'.','+$&'|iex)%10)}

Histoire:

  • 2011-02-13 03:08 (84) Première tentative.
  • 2011-02-13 12:13 (82) Je n'ai pas besoin de participer, les espaces ne font pas mal. +1 + +3peut encore être évalué.
Joey
la source
5

Q, 63

{0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}

usage

q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398711"
0b
q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398712"
0b
q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398713"
1b
tmartin
la source
47 octets avec {0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)une manière différente de doubler les index impairs.
streetster
5

D, 144 octets

bool f(S)(S s){int t(C)(C c){return to!int(c)-'0';}int n,v;foreach(i,c;array(retro(s))){v=i&1?t(c)*2:t(c);n+=v>=10?v%10+v/10:v;}return n%10==0;}

Plus lisiblement:

bool f(S)(S s)
{
    int t(C)(C c)
    {
        return to!int(c) - '0';
    }

    int n, v;

    foreach(i, c; array(retro(s)))
    {
        v = i & 1 ? t(c) * 2 : t(c);

        n += v >= 10 ? v % 10 + v / 10 : v;
    }

    return n % 10 == 0;
}
Jonathan M Davis
la source
5

APL, 28 octets

{0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵}

Vue éclatée

{                     v←⍎¨⍵}  ⍝ turn the string into a numeric vector of its digits, v
                2-2|⍳⍴v       ⍝ make a vector of the same length, with 2 in every 2nd place
             v×⌽              ⍝ multiply it with v, starting from the right
          ∊⍕¨                 ⍝ turn each component into a string and collect all the digits
      +/⍎¨                    ⍝ turn each digit again into a number and sum them
 0=10|                        ⍝ check whether the sum is a multiple of 10

Exemples

      {0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '79927398713'
1
      {0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '123456789'
0
Tobia
la source
1
-2:{0=10|+/⍎¨∊⍕¨⍵×⌽2-2|⍳⍴⍵}⍎¨
Adám
4

PowerShell 123

filter L($x){$l=$x.Length-1;$l..0|%{$d=$x[$_]-48;if($_%2-eq$l%2){$s+=$d}elseif($d-le4){$s+=$d*2}else{$s+=$d*2-9}};!($s%10)}
Ty Auvil
la source
4

Perl, 46 42 41 octets

Inclut +1 pour -p

Donnez votre avis sur STDIN:

luhn.pl <<< 79927398713

luhn.pl:

#!/usr/bin/perl -p
s%.%$=-=-$&-$&*1.2*/\G(..)+$/%eg;$_=/0$/
Ton Hospel
la source
Pouvez-vous s'il vous plaît expliquer comment cela fonctionne? Vous semblez être décrémenté par le match et ensuite aussi par les temps du match 1.2 mais seulement dans les bonnes positions. Pourquoi 1.2? Ça ne devrait pas être ça $=-=-$&-$&*/\G(..)+$/?
msh210
3
@ msh210: Il code l'effet de la multiplication par 2. 0..4* 2 donne 0, 2, 4, 6, 8mais 5..9donne 10,12,14,16,18quelle somme 1 3 5 7 9a les mêmes derniers chiffres que 11 13 15 17 19les mêmes valeurs que 0..9 * 2.2si vous tronquiez en entier. Le premier $&contribue déjà à un facteur 1, de sorte qu'une correction par 1.2est toujours nécessaire. $=ne peut contenir que des entiers et commence par une valeur qui se termine par 0, donc se charge de la troncature. Les valeurs négatives sont nécessaires car les /\G/expressions rationnelles modifient toutes les notes $&restant sur la pile d'évaluation, elles doivent donc être modifiées
Ton Hospel
Oh. Brillant! Et merci pour l'explication.
msh210
3

JavaScript (ES6), 61 octets

Non-concurrence, car JavaScript était très différent en 2011.

Somme des chiffres de 2*nis 2*nsi n in 0..4, 2*n-9si n in 5..9. Cela dit, toute la somme peut être calculée en une étape.

s=>!([...s].reduceRight((t,d)=>t-d-i++%2*(d>4?d-9:d),i=0)%10)
edc65
la source
3

Gelée , 12 à 11 octets

ṚḤJḤ$¦DFS⁵ḍ

Essayez-le en ligne! (avec tous les cas de test)

Comment ça fonctionne

ṚḤJḤ$¦DFSḍ⁵  - Main link. Argument: n (integer) e.g. 49927398716
Ṛ            - Reverse. Casts a number to digits     [6, 1, 7, 8, 9, 3, 7, 2, 9, 9, 4]
     ¦       - Sparse application. Apply the next command to the given indicies
 Ḥ           -   Command: Double
    $        -   Indicies:
  J          -     range(length)...                  [1, 2 , 3, 4, 5, 6, 7, 8, 9, 10, 11]
   Ḥ         -     doubled.                          [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
             - Doubles elements at odd indicies      [6, 2, 7, 16, 9, 6, 7, 4, 9, 18, 4]
      D      - Split each into digits                [6, 2, 7, [1, 6], 9, 6, 7, 4, 9, [1, 8], 4]
       F     - Flatten                               [6, 2, 7, 1, 6, 9, 6, 7, 4, 9, 1, 8, 4]
        S    - Sum                                   70
          ḍ  - Divisible by... 
         ⁵   -   10?                                 1

Alternativement, pour 12 octets:

ṚḤJḤ$¦DFSḍ@⁵
caird coinheringaahing
la source
3

ASM x86-16 , IBM PC DOS, 23 octets

03 F1       ADD  SI, CX         ; start at end of input string 
FD          STD                 ; set LODSB direction to decrement 
    DIGIT_LOOP:
AC          LODSB               ; load next digit into AL, decrement SI
2C 30       SUB  AL, '0'        ; convert ASCII char to binary value 
F7 DA       NEG  DX             ; flip DX to alternate odd/even index
78 06       JS   EVEN           ; if even index, do not double and sum digits 
D0 E0       SHL  AL, 1          ; double the value 
D4 0A       AAM                 ; BCD convert to split digits (ex: 18 = 12H --> 0108H) 
02 DC       ADD  BL, AH         ; add tens digit to running sum 
    EVEN:
02 D8       ADD  BL, AL         ; add ones digit to running sum 
E2 ED       LOOP DIGIT_LOOP 
93          XCHG BX, AX         ; sum is in BL, move to AL for conversion
D4 0A       AAM                 ; BCD convert AL, set ZF=1 if low digit is 0

Utilise (abuse) l'instruction BCD-to-binary du x86 AAMpour gérer le fractionnement et la modulo 10vérification de chiffres individuels .

Pointeur de la chaîne de saisie de la carte d'entrée SI, longueur de CX. Sortie: ZFsi valide.

Exemple de sortie du programme de test:

entrez la description de l'image ici

Téléchargez le programme de test LUHN.COM IBM PC DOS.

640 Ko
la source
2

Scala: 132

def q(x:Int)=x%10+x/10
def c(i:String)={val s=i.reverse
(s(0)-48)==10-(s.tail.sliding(2,2).map(n=>(q((n(0)-48)*2)+n(1)-48)).sum%10)}

invocation:

c("79927398713")
  • reverse ("79927398713") = 31789372997
  • s (0), s.tail: (3) (1789372997)
  • glissant (2,2) = (17 89 37 29 97)
  • map (q ((n (0) -48 * 2 + n (1) -48)) => q (('1' - '0') * 2) + '7' - '0') = 1 * 2 + 7
Utilisateur inconnu
la source
2

JavaScript 1.8: 106 caractères

C’est une solution originale que j’ai imaginée avant de trouver ce post:

function(n){return!(n.split('').reverse().reduce(function(p,c,i){return(+c&&((c*(1+i%2)%9)||9))+p},0)%10)}

Forme lisible:

function luhnCheck(ccNum) {
    return !(                                  // True if the result is zero.
             ccNum.split('').
               reverse().                      // Iterate over the string from rtl.
               reduce(function(prev, cur, idx) {
                 return prev +                 // Sum the results of each character.
                        (+cur &&               // If the current digit is 0, move on.
                         ((cur * (1 + idx % 2) // Double cur at even indices.
                           % 9) || 9));        // Sum the digits of the result.
               }, 0)
            % 10);                             // Is the sum evenly divisible by 10?
}
kojiro
la source
2

K4, 35 octets

{~.*|$+/.:',/$x*1+1{y;~x}\|x:|.:'x}
Aaron Davies
la source
2

Retina , 43 42 bytes

La rétine est (beaucoup) plus récente que ce défi.


;
r`(.);.
$1$&
\d
$*
1+
$.&
.
$*
$
$._
0$

La ligne vide principale est significative.

Imprime 0pour les résultats de fausseté et 1de vérité.

Essayez-le en ligne! (Légèrement modifié pour exécuter tous les tests en même temps.)

Explication


;

Insérer ;dans chaque position pour séparer les chiffres.

r`(.);.
$1$&

Dès le rdébut, nous cherchons deux chiffres et doublons le chiffre de gauche. De cette façon, nous évitons un renversement coûteux de la liste.

\d
$*

Nous comparons chaque chiffre et le convertissons en autant de 1s (c’est-à-dire que nous convertissons chaque chiffre en unaire).

1+
$.&

Cela correspond à chaque nombre unaire et le reconvertit en décimal en le remplaçant par sa longueur. Avec l'étape précédente, cela ajoute les chiffres doublés.

.
$*

Encore une fois, nous correspondons à chaque personnage et le transformons en autant de 1s. C'est-à-dire que nous convertissons chaque chiffre individuellement en unaire. Cela correspond également aux ;séparateurs, qui sont traités comme des zéros lors de la conversion, ce qui signifie qu'ils sont simplement supprimés. Puisque tous les nombres unaires sont maintenant regroupés, nous avons automatiquement ajouté les représentations unaires de tous les chiffres.

$
$._

À la fin, nous insérons la longueur de la chaîne entière, c'est-à-dire la représentation décimale de la somme de contrôle unaire.

0$

Enfin, nous comptons le nombre de correspondances de cette expression rationnelle, c’est-à-dire que nous vérifions si la représentation décimale se termine par 0, en imprimant 0ou en 1conséquence.

Martin Ender
la source
2

Powershell, 74 octets

param($s)$s[$s.Length..0]|%{(1+$i++%2)*"$_"}|%{$r+=$_-9*($_-gt9)}
!($r%10)

Explication

  1. pour chaque caractère d'une chaîne d'argument, dans l'ordre inverse
  2. obtenir un chiffre de double valeur d'un chiffre
  3. une valeur double d'un chiffre ne peut pas être supérieure à 18. Par conséquent, nous accumulons une valeur moins 9 si la valeur> 9
  4. retourne vrai si le reste de la division par 10 est 0

Script de test

$f = {

param($s)$s[$s.Length..0]|%{(1+$i++%2)*"$_"}|%{$r+=$_-9*($_-gt9)}
!($r%10)

}

@(
    ,("49927398716"      , $True)
    ,("49927398717"      , $False)
    ,("1234567812345670" , $True)
    ,("1234567812345678" , $False)
    ,("79927398710"      , $False)
    ,("79927398711"      , $False)
    ,("79927398712"      , $False)
    ,("79927398713"      , $True)
    ,("79927398714"      , $False)
    ,("79927398715"      , $False)
    ,("79927398716"      , $False)
    ,("79927398717"      , $False)
    ,("79927398718"      , $False)
    ,("79927398719"      , $False)
    ,("374652346956782346957823694857692364857368475368" , $True)
    ,("374652346956782346957823694857692364857387456834" , $False)
    ,("8" , $False)
    ,("0" , $True)
) | % {
    $s, $expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result : $s"
}

Sortie

True: True : 49927398716
True: False : 49927398717
True: True : 1234567812345670
True: False : 1234567812345678
True: False : 79927398710
True: False : 79927398711
True: False : 79927398712
True: True : 79927398713
True: False : 79927398714
True: False : 79927398715
True: False : 79927398716
True: False : 79927398717
True: False : 79927398718
True: False : 79927398719
True: True : 374652346956782346957823694857692364857368475368
True: False : 374652346956782346957823694857692364857387456834
True: False : 8
True: True : 0
mazzy
la source
2

05AB1E , 12 à 10 octets

RSāÈ>*SOTÖ

Essayez-le en ligne! ou en tant que suite de tests

Explication

R             # reverse input
 S            # split to list of digits
  ā           # push range[1 ... len(input)]
   È          # map isEven on each
    >         # increment
     *        # multiply doubling every other item
      SO      # sum digits
        TÖ    # mod 10 == 0
Emigna
la source
1

Haskell: 97

Pour une raison quelconque, cela ne fonctionne pas pour moi , alors voici ma version

l=(\x->(==0)$(`mod`10).sum$zipWith($)(cycle[id,sum.map(read.(:"")).show.(*2)])(map(read.(:""))x))
utilisateur701072
la source
1

GNU sed, 140 octets

(y compris +1 pour le -rdrapeau)

s/^(..)*.$/0&/
s/(.)./\1x&/g
s/x[5-9]/1&/g
s/[0x]//g
s/[789]/&6/g
s/[456]/&3/g
s/[369]/&11/g
s/[258]/&1/g
s/.{10}//g
s/.+/false/
s/^$/true/

Sed n’est presque jamais le langage le plus naturel pour l’arithmétique, mais on y va:

#!/bin/sed -rf

# zero-pad to even length
s/^(..)*.$/0&/
# double every other digit
s/(.)./\1x&/g
# add carry (converts mod-9 to mod-10)
s/x[5-9]/1&/g
# convert sum to unary
s/[0x]//g
s/[789]/&6/g
s/[456]/&3/g
s/[369]/&11/g
s/[258]/&1/g
# remove whole tens
s/.{10}//g
# output 'true' or false
s/.+/false/
s/^$/true/
Toby Speight
la source
1

APL, 38 octets

d←10∘⊥⍣¯1⋄{0=10|+/+/d x×1+~2|⍳⍴x←⌽d ⍵}

attend le nombre sous forme de nombre, pas de chaîne, mais c'est uniquement parce que tryAPL (de manière compréhensible) ne met pas en œuvre

plus réductible, je suis sûr…

Aaron Davies
la source
1

PHP - 136 caractères

function t($c){foreach($a=str_split(strrev($c)) as $k=>&$v){$v=array_sum(str_split(($k % 2)!==0?2*$v:$v));}return !(array_sum($a)% 10);}
Flamme
la source
1

MATL , 23 20 octets (non en compétition)

P!Utn:2X\!*t9>+s10\~

Essayez-le en ligne!

Affiche 1 pour un nombre valide, 0 sinon.

Économisé trois octets grâce aux suggestions de Luis Mendo.

Explication

P       % flip the order of elements
!       % transpose into column vector
U       % convert char matrix to numeric
t       % duplicate the vector
n       % find the length
:       % create a new vector length n (1, 2, 3, ... n)
2       % number literal
X\      % take it mod 2, to make the new vector (1, 2, 1, ..., (n-1) mod 2 +1)
!       % transpose
*       % element-wise product
t       % duplicate
9       % push 9
>       % 1 if it is greater than 9
+       % add the vectors, this makes the last digit of each the same as the sum of the digits
s       % add them
10      % number literal
\       % mod 10
~       % logical 'not' (element-wise)
        % (implicit) convert to string and display
B. Mehta
la source
1

Gelée , 14 octets

DUḤJḤ$¦DS$€S⁵ḍ

Essayez-le en ligne!

Explication:

D              get digits
 U             reverse array
   JḤ$         for every other index,
  Ḥ   ¦        double the value
          €    for each value,
       D $     get the digits
        S$     and sum them
           S   sum the list
            ⁵ḍ check if it's divisible by 10
Ellie
la source
Pourquoi est-ce non-concurrent?
mudkip201
@ mudkip201 Corrigez-moi si je me trompe, mais cette version de Jelly n'existait pas lorsque la question a été posée, elle n'est donc pas valide pour la question.
ellie
3
Je suis presque sûr qu'il y avait un méta-consensus qui disait que les langues qui ont été
créées