El algoritmo de Luhn para verificar números de tarjetas de crédito, etc.


50

Desafío

Escriba el programa o función más corto para calcular el algoritmo de Luhn para verificar los números (tarjeta de crédito).

Algoritmo de Luhn explicado

Desde RosettaCode , este algoritmo para los propósitos de este desafío se especifica como tal, con la entrada de ejemplo de 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

Reglas IO

Entrada : una cadena o número (su elección), en el formato de entrada / salida de su idioma de elección

Salida : Un valor verdadero o falso , respectivamente, que indica si la entrada es válida o no de acuerdo con la prueba anterior.

Notas / Consejos

  • Intente no publicar accidentalmente su propia tarjeta de crédito o números de cuenta, si los usa para probar :)

  • Si la entrada es inválida e imposible de procesar con el algoritmo especificado (es decir, demasiado corto para trabajar), puede hacer lo que quiera, incluso hacer estallar mi computadora.

  • Sin embargo , la viñeta anterior no significa que su idioma pueda hacer lo que quiera con Números que son demasiado grandes para manejarlos. Si su idioma no es capaz de manejar un caso de prueba, considere tomar una cadena como entrada.

Ejemplos

Los siguientes ejemplos fueron validados con este script Python ; Si cree que uno está equivocado o tiene una pregunta, simplemente haga ping a @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  **

** según la implementación de Python, pero puede hacer cualquier cosa porque estos son demasiado cortos para ser elegibles por un estricto cumplimiento de la especificación.


Si alguno de los anteriores invalida las respuestas existentes (aunque creo que eso no debería ser posible), esas respuestas aún son válidas. Sin embargo, las nuevas respuestas, para ser válidas, deben seguir la especificación anterior.

Tabla de clasificación

Respuestas:


21

Golfscript - 24 caracteres

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

Explicación:

  1. -1% invierte la cuerda
  2. {comienza un bloque (que usamos como un bucle). Cada carácter en las cadenas se empuja ya que es un valor ascii.
    1. 2+ suma 2. (el valor ascii de un dígito es 48 + n, entonces tenemos 50 + n ahora y el último dígito es n)
    2. 0!:0 invierte el valor de 0 y lo almacena (todo es una variable), por lo que tenemos 1 en la primera iteración, 0 en la segunda, etc.
    3. )* agrega uno a este valor y lo multiplica, por lo que multiplicamos por 2, luego 1, luego 2, etc.
    4. 109% es el módulo 109 restante. Esto afecta solo a los valores 5-9 que se han duplicado y los reduce al valor correcto.
    5. + agrega este valor a la suma acumulada
  3. }*finaliza el bloque y realiza una operación de "plegado". Primero, se empuja el primer carácter (dado que hemos invertido, este es el dígito de verificación). Luego, alterna empujando y ejecutando el bloqueo. Por lo tanto, estamos utilizando el valor ascii del primer personaje como valor inicial para la suma acumulada.
  4. 10% toma el resto módulo 10.
  5. 8= devolverá 1 si el valor es 8. Usamos esto porque no normalizamos el primer carácter empujado (el dígito de verificación).

Uno podría pensar que podríamos usar en 8-lugar de 2+guardar un personaje cambiando 109%a 89%, excepto que tendríamos que agregar un espacio para que la -resta sea (en lugar de -0).


11

GolfScript, 44 caracteres

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

Comentario seleccionado

Curiosamente, los primeros dos elementos a continuación demuestran tres usos completamente diferentes del %operador: selección de matriz, mapa y mod. La mayoría de los operadores de GolfScript son "sensibles al contexto", lo que les da comportamientos muy divergentes según los tipos de argumentos.

  1. -1%invierte la cadena. Esto es importante ya que los pares de dígitos se cuentan desde la derecha.
  2. {16%}% Convierte todos los dígitos ASCII en números, modificándolos con 16.
  3. 2/ divide la matriz en grupos de 2.
  4. 1,Es una forma barata de hacerlo [0].
  5. \+efectivamente antepone el 0 a la matriz de dígitos. Lo hace intercambiando y luego concatenando.

El 0 se antepone en preparación para el pliegue que viene a continuación. En lugar de tomar un valor inicial explícito, el pliegue de GolfScript usa el primer elemento de la matriz como valor inicial.

Ahora, veamos la función de plegado real. Esta función toma dos argumentos: el valor plegado y el elemento actual en la matriz (que en este caso será una matriz de 2 o (poco frecuente) 1, debido a lo 2/anterior). Asumamos que los argumentos son 1 [2 3].

  1. (\.divide el elemento de matriz más a la izquierda, mueve la matriz restante al frente y luego la copia. Apilar ahora se ve así: 1 2 [3] [3].
  2. Los ifcomprueba si la matriz está vacía (que es el caso para el último grupo cuando se trata de un número de cuenta de tamaño impar). Si es así, entonces no ocurre un procesamiento especial (simplemente salga de la matriz vacía).
  3. Para un grupo par:
    1. 0= agarra el primer elemento (solo, en este caso) de la matriz. 1 2 3
    2. 2* duplica el número 1 2 6
    3. .9>9*- resta 9 del número si es mayor que 9. Implementado como: copie el número, compare con 9, multiplique el resultado (que es 0 o 1) con 9, luego reste. 1 2 6
    4. + finalmente agrega eso al primer número. 1 8
  4. +(después de if) agrega el resultado de ifal valor original, lo que da como resultado el nuevo valor plegado.

Una vez que se completa el plegado, simplemente modificamos con 10 ( 10%) y negamos el resultado ( !), de modo que devolvemos 1 si la suma es un múltiplo de 10.


Esto parece devolver 0 para el número de ejemplo en wikipedia (49927398716)
gnibbler

Nuevo Méjico. Olvidé usarecho -n
gnibbler

1
@gnibbler: Jaja, falla. :-P (En serio, ese también me picó en mi prueba inicial).
Chris Jester-Young

1
Algunos lugares para guardar algunos personajes fáciles aquí. -1% 2/se puede combinar en -2/. 1,se puede reemplazar con 0(0 se coacciona a una matriz, luego +se concatena). 9>9*-se puede reemplazar con 9>+(ya que solo nos preocupa el último dígito). Además, la comprobación de longitudes impares es un poco larga, el uso .,2%,\+es más corto. Después de hacer esto, también podemos cambiar {16%}%y (\0=entrar {16}/(dentro del bucle). Una vez hecho todo esto, que se verá algo como esto: .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb

@Nabb: ¡Gracias! Los incorporaré en mi solución, aunque parece que ya tienes uno que está pateando traseros serios. :-)
Chris Jester-Young

11

Python, 73 69 caracteres

def P(x):D=map(int,x);return sum(D+[d-d/5*9for d in D[-2::-2]])%10==0

44
Puede guardar dos caracteres más si no realiza un bucle hacia atrás: D[-2::-2]-> D[1::2]ya que el orden de una suma no es importante :)
ThinkChaos

==0se puede acortar a<1
Black Owl Kai

10

Python 3, 77 bytes

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

9

C # 119 caracteres:

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

No es demasiado malo para un n00b código de golf en un lenguaje de tipos estáticos, espero.

Esto se puede reducir a 100 :

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

Es una buena idea y un enfoque interesante, pero no parece funcionar. Al menos no con mis pocas pruebas. Parece que se supone que la "i" en su primer lambda es el índice del carácter en la cadena. ¿Funciona como debería? Si es así, ¿por qué invierte la cadena solo para luego modificarla según la posición del índice? Parece un poco redundante, ¿no?
Nellius

Solo probé una de mis tarjetas de crédito y algunas de ellas con errores de TBH. (Usando el depurador VS 2008) Se supone que el algoritmo duplica cada segundo dígito comenzando con el ÚLTIMO dígito. Si no invirtiera la cadena, sería incorrecto para cadenas con longitudes impares.
Mootinator

Resulta que tuve el resultado de al i%2<1?1:2revés. Gracias.
Mootinator

8

Golfscript - 34 caracteres

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

Número de ejemplo de la página de 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

El .+(9%)es muy innovador (para mí, de todos modos). ¡Me gusta! +1
Chris Jester-Young

Sin embargo, a primera vista, GolfScript necesita un operador de particionamiento, por lo que no necesita hacer esta tontería de "descartar el elemento final y repetir". :-)
Chris Jester-Young

1
@ Chris, aprendí sobre eso hace muchos años llamado "echar nueves". Es una forma ordenada de verificar dos veces las sumas y multiplicaciones a mano
gnibbler

3
Esto no funcionará para un valor de 0 duplicado ( 0(9%)es 9 y no 0).
Nabb

8

PHP, 108 bytes

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

7

Ruby - 85 caracteres

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

Probablemente lo sepas, pero podrías hacer .sum en lugar de .inject (: +) para guardar 7 bytes
Håvard Nygård

7

Haskell, 96 bytes

Debe haber una forma mejor / más corta, pero aquí está mi solución de Haskell en 96 caracteres :

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

Lamentablemente, la digitToIntfunción solo se puede usar si usted import Data.Charprimero. De lo contrario, podría bajar a 88 caracteres reemplazando ((+(-48)).fromEnum)con digitToInt.


6

Windows PowerShell, 82

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

Historia:

  • 2011-02-13 03:08 (84) Primer intento.
  • 2011-02-13 12:13 (82) No necesito unirme, ya que los espacios no duelen. +1 + +3Todavía se puede evaluar.

5

Q, 63

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

uso

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

47 bytes con {0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)una forma diferente de duplicar los índices impares.
Callejero

5

D, 144 bytes

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

Más legible:

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

5

APL, 28 bytes

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

Vista en despiece ordenado

{                     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

Ejemplos

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

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

4

Perl, 46 42 41 bytes

Incluye +1 para -p

Dar entrada en STDIN:

luhn.pl <<< 79927398713

luhn.pl:

#!/usr/bin/perl -p
s%.%$=-=-$&-$&*1.2*/\G(..)+$/%eg;$_=/0$/

¿Puedes explicar cómo funciona esto? Parece que estás disminuyendo por el partido y luego también por los tiempos del partido 1.2 pero solo en las posiciones correctas. ¿Por qué 1.2? ¿No debería ser $=-=-$&-$&*/\G(..)+$/?
msh210

3
@ msh210: codifica el efecto de la multiplicación por 2. 0..4* 2 da 0, 2, 4, 6, 8pero 5..9da a 10,12,14,16,18qué suma 1 3 5 7 9tienen los mismos últimos dígitos 11 13 15 17 19que los mismos valores que 0..9 * 2.2si truncara a entero. El primero $&ya aporta un factor 1, por 1.2lo que aún se necesita una corrección por . $=solo puede contener enteros y comienza con un valor que termina en 0, por lo que se encarga del truncamiento. Los valores negativos son necesarios ya que la /\G/expresión regular cambia cualquier $&todavía en la pila de evaluación, por lo que deben cambiarse
Ton Hospel

Oh. ¡Brillante! Y gracias por la explicación.
msh210

3

JavaScript (ES6), 61 bytes

No competidor, ya que JavaScript fue muy diferente en 2011.

Suma de dígitos de 2*nes 2*nif n in 0..4, 2*n-9if n in 5..9. Dicho esto, toda la suma se puede calcular en un solo paso.

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

3

Jalea , 12 11 bytes

ṚḤJḤ$¦DFS⁵ḍ

Pruébalo en línea!(con todos los casos de prueba)

Cómo funciona

ṚḤ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

Alternativamente, para 12 bytes:

ṚḤJḤ$¦DFSḍ@⁵

3

x86-16 ASM , IBM PC DOS, 23 bytes

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

Utiliza (abusa) la instrucción BCD a binario del x86 AAMpara manejar la división y modulo 10verificación de dígitos individuales .

Tarjeta de entrada número puntero cadena SI, longitud en CX. Salida: ZFsi es válida.

Ejemplo de salida del programa de prueba:

ingrese la descripción de la imagen aquí

Descargue el programa de prueba LUHN.COM IBM PC DOS.


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

invocación:

c("79927398713")
  • reverso ("79927398713") = 31789372997
  • s (0), s.tail: (3) (1789372997)
  • deslizante (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

2

JavaScript 1.8: 106 caracteres

Esta es una solución original que se me ocurrió antes de encontrar esta publicación:

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

Forma legible:

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


2

Retina , 43 42 bytes

La retina es (mucho) más nueva que este desafío.


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

La línea vacía principal es significativa.

Impresiones 0para falsedad y1 verdaderos.

Pruébalo en línea!(Ligeramente modificado para ejecutar todos los casos de prueba a la vez).

Explicación


;

Insertar ;en cada posición para separar los dígitos.

r`(.);.
$1$&

Desde el right, repetidamente emparejamos dos dígitos y duplicamos el izquierdo. De esta manera evitamos una inversión costosa de la lista.

\d
$*

Emparejamos cada dígito y lo convertimos a esa cantidad de 1s (es decir, convertimos cada dígito a unario).

1+
$.&

Esto coincide con cada número unario y lo convierte de nuevo a decimal reemplazándolo por su longitud. Junto con la etapa anterior, esto agrega los dígitos duplicados.

.
$*

Una vez más, combinamos cada personaje y lo convertimos en tantos 1s. Es decir, convertimos cada dígito individualmente de nuevo a unario. Esto también coincide con el; separadores, que se tratan como ceros en la conversión, lo que significa que simplemente se eliminan. Dado que todos los números unarios están ahora juntos, hemos agregado automáticamente las representaciones unarias de todos los dígitos juntos.

$
$._

Al final, insertamos la longitud de toda la cadena, es decir, la representación decimal de la suma de comprobación unaria.

0$

Finalmente contamos el número de coincidencias de esta expresión regular, es decir, verificamos si la representación decimal termina 0, imprimiendo 0o en 1consecuencia.


2

Powershell, 74 bytes

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

Explicación

  1. para cada carácter de una cadena de argumento, en orden inverso
  2. obtener un dígito de doble valor de un dígito
  3. un valor doble de un dígito no puede ser mayor que 18. Por lo tanto, acumulamos un valor menos 9 si el valor es> 9
  4. devuelve verdadero si el resto de la división por 10 es 0

Script de prueba

$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"
}

Salida

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

2

05AB1E , 12 10 bytes

RSāÈ>*SOTÖ

Pruébalo en línea! o como un conjunto de pruebas

Explicación

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


1

GNU sed, 140 bytes

(incluido +1 para la -rbandera)

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 casi nunca es el lenguaje más natural para la aritmética, pero aquí vamos:

#!/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/

1

APL, 38 bytes

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

espera el número como un número, no como una cadena, pero eso es solo porque tryAPL (comprensiblemente) no se implementa

más reducible, estoy seguro ...


1

PHP - 136 caracteres

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

1

MATL , 23 20 bytes (no competidor)

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

Pruébalo en línea!

Salidas 1 para un número válido, 0 de lo contrario.

Ahorré tres bytes gracias a las sugerencias de Luis Mendo.

Explicación

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

1

Jalea , 14 bytes

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

Pruébalo en línea!

Explicación:

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

¿Por qué esto no es competitivo?
mudkip201

@ mudkip201 Corrígeme si me equivoco, pero esta versión de Jelly no existía cuando se hizo la pregunta, por lo que no es válida para la pregunta.
ellie

3
Estoy bastante seguro de que hubo un meta consenso que decía que los idiomas que se hicieron después del desafío ya no son 'no competitivos'
mudkip201
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.