Calcule un dígito de verificación utilizando el algoritmo Damm

17

Existen algoritmos de verificación de dígitos populares como Luhn y luego hay otros buenos , por ejemplo, el algoritmo Damm. La única razón posible detrás de la popularidad de algoritmos como Luhn es que existen implementaciones de código de golf de ellos. Esto significa que nosotros como comunidad tenemos el poder de cambiar el mundo al proporcionar implementaciones de mejores algoritmos.

Entonces, este desafío es cambiar el mundo escribiendo una función o un programa completo en el idioma de su elección que calcule un dígito de verificación utilizando el algoritmo Damm . La respuesta con el menor número de caracteres (no bytes) será elegida como ganadora en unas pocas semanas. Tenga en cuenta que todas las funciones de ayuda y la declaración de la tabla de operaciones deben incluirse en el recuento de caracteres. En caso de empate se elegirá la respuesta más popular.

Este algoritmo gira en torno a una tabla de operaciones que debe ser un cuasigrupo de orden débilmente totalmente antisimétrico 10. La tabla de operaciones que se puede encontrar en el artículo de Wikipedia sobre el algoritmo Damm es la que se utilizará en este desafío. Para completar, lo reproduciré a continuación:

    |   0   1   2   3   4   5   6   7   8   9
----+----------------------------------------
0   |   0   3   1   7   5   9   8   6   4   2
1   |   7   0   9   2   1   5   4   8   6   3
2   |   4   2   0   6   8   7   1   3   5   9
3   |   1   7   5   0   9   8   3   4   2   6
4   |   6   1   2   3   0   4   5   9   7   8
5   |   3   6   7   4   2   0   9   5   8   1
6   |   5   8   6   9   7   2   0   1   3   4
7   |   8   9   4   5   3   6   2   0   1   7
8   |   9   4   3   8   6   1   7   2   0   5
9   |   2   5   8   1   4   3   6   7   9   0

En resumen (para más detalles ver el artículo de Wikipedia ) el algoritmo funciona de la siguiente manera:

  1. Comienza con una lista de dígitos para procesar y un dígito provisional que se establece en 0.
  2. Para cada dígito de la lista, calcula un nuevo dígito intermedio utilizando el dígito como índice de columna y el dígito intermedio anterior como índice de fila.
  3. El último dígito provisional es el dígito de verificación. Si está validando un número que ya tiene un dígito de verificación agregado, el dígito intermedio final es 0 si el número es válido.

Su programa o función debe aceptar una cadena que pueda contener cualquier carácter excepto nulo, pero solo debe ocuparse de los dígitos de la cadena. Debe imprimir (si es un programa) o devolver (si es una función) la cadena original con el dígito de verificación calculado agregado. Si elige escribir un programa, el programa puede aceptar la entrada como argumento o como entrada estándar. Si la cadena de entrada está vacía o no contiene ningún dígito, debe devolver o agregar un cero.

Algunos ejemplos:

Input       |   Output
------------+-------------
42          |   427
427         |   4270
2 to 2      |   2 to 29
23 42 76-   |   23 42 76-5
-           |   -0
Fors
fuente
Espero ver las entradas de Piet reclamando la victoria.
Alchymist

Respuestas:

3

Pyth, 49 caracteres

+z`u@sm>+0jCdT_6"Ľ򒉲򭉟񶯆𐱩򐞆󰆂򕟐򑽌򵋏󇋽򯴆󚙈𱑂񞑼쵥񪨶"+*TGvH:z"\D"k0

Contiene dios sabe qué caracteres, así que aquí hay un programa Python3 para generar el programa anterior con precisión en su máquina:

N = 317598642709215486342068713591750983426612304597836742095815869720134894536201794386172052581436790
M = 1000000
l = []
while N:
    l.insert(0, N % M)
    N //= M

n = "".join(chr(c) for c in l)

s = '+z`u@sm>+0jCdT_6"' + n + '"+*TGvH:z"\D"k0'

with open("golf.pyth", "wb") as f:
    f.write(s.encode("utf-8"))

print("Program length is {} characters.".format(len(s)))

Explicación:

+z`                                     Output the input followed by a
                                        stringified...
   u                         :z"\D"k0   Reduction starting with 0 of digits
                                        in input...
    @                  +*TGvH           Indexing ... by 10*prev + int(next).
     sm         "ZALGO"                 Sum all digits created by ... over the
                                        unicode garbage.
       >+0     6                        Prepend 0 if needed to...
          jCdT_                         Codepoint converted to sequence of
                                        digits.
orlp
fuente
3

CJam, 54 caracteres

q_o{A,s&},{~0"끼´慜䪝膞䝮芜㮜ꡞ靓渏縰蒆㣉倔쵶"2G#bAb+A/T==:T;}/T

Hay un carácter no imprimible allí, por lo que es posible que desee utilizar el enlace permanente a continuación.

Pruébalo aquí.

Explicación

El dígito interino se está rastreando en T , que CJam inicializa a 0.

q_o                                  "Read STDIN, duplicate it and print it.";
   {A,s&},                           "Filter out all non-digit characters.";
          {                     }/   "For each digit character.";
           ~                         "Eval to get the digit itself.";
            0                        "Push a zero.";
             "..."2G#b               "Push that long string and interpret the character
                                      codes as the digits of a base-2^16 number.";
                      Ab+            "Get base-10 digits and prepend the 0.";
                         A/          "Split into rows of 10.";
                           T=        "Select row based on interim digit.";
                             =       "Select column based on current digit.";
                              :T;    "Store in T and discard.";
                                   T "Push the interim digit to be printed.";
Martin Ender
fuente
3

Pitón 3, 149141 caracteres

import re
l=""
for c in"ĽᝢႮ⏿ዿၮ∉᜝Ꮺൢ៫Njẜ᳼╭᛭ᰡඡᆸߡⓞ᠜ȍ῏᪆":l+="%04d"%ord(c)
def D(b):
 a="0"
 for i in re.sub("\D","",b):a=l[int(a+i)]
 return b+a

Ejemplos:

 Input | Output
-------+--------
    42 | 427
   427 | 4270
2 to 2 | 2 to 29
   123 | 1234
  1234 | 12340
     - | -0

Gracias a @MegaTom y @Sieg por ayudar a eliminar un total de 11 caracteres.

monopolo
fuente
2
10 * int (a) + int (i) es int (a + i), ¿no es así?
MegaTom
¡Buen punto! Gracias, eso ahorra 5 caracteres.
monopolo
1
Para seguido de una sola declaración no necesita una nueva línea en el medio. (-3)
seequ
2

Ruby, 149 caracteres

i="0";t="0#{'2uleblnnz0nbpv3kqkaufbjqebm57jdj6ubaba1mc2fyucqff69tbllrcvw393li'.to_i 36}";puts(gets.chomp.each_char{|c|i=(c=~/\d/?t[(i+c).to_i]:i)}+i)

Probado en repl.it

MegaTom
fuente
2

J, 117 bytes

Contiene solo ascii imprimible. (Tuve dificultades con J y Unicode). Genera la tabla de transición a partir de los índices de permutación de las filas.

3 :'y,":(((_4(87)&#:inv\40-~a.i.''(3/3+wGf*Dl:(zaW+Hhw*(1p+;~.,y>m-<MZ)JCs'')A.i.10){~<@,~)/|.0,(#~10>])(1":i.10)i.y'

Uso:

   damm=.3 :'y,":(((_4(87)&#:inv\40-~a.i.''(3/3+wGf*Dl:(zaW+Hhw*(1p+;~.,y>m-<MZ)JCs'')A.i.10){~<@,~)/|.0,(#~10>])(1":i.10)i.y'

   damm '23 42 76-'
23 42 76-5

   damm ''
0

Pruébelo en línea aquí.

randomra
fuente
2

Haskell, 131 personajes

import Data.Char
f n=n++(show$foldl(\x y->read[('0':(show.ord=<<"౧⚈ક×ዿၮ∉ɏᵕₖ᧔İɕSʢ凞㷽ᰡ衎텴䘗↩倭῏᪆"))!!(x*10+y)])0[read[i]|i<-n,isDigit i])

Prueba de funcionamiento:

> mapM_ (putStrLn.f) ["42", "427", "2 to 2", "23 42 76-", "-"]
427
4270
2 to 29
23 42 76-5
-0
nimi
fuente
0

k, 36 caracteres

/ declare quasi-group  
M:"H"$'"0317598642709215486342068713591750983426612304597836742095815869720134894536201794386172052581436790"

/ declare function
  f:{x,$0{M y+10*x}/"H"$'x@&x in .Q.n}

/ get length of function
  #$f
36

/ execute function against test input
  .q.show f@'{x!x}("42";"427";"2 to 2";"23 42 76-";,"-")
"42"       | "427"
"427"      | "4270"
"2 to 2"   | "2 to 29"
"23 42 76-"| "23 42 76-5"
,"-"       | "-0"

q, 40 caracteres (implementación equivalente a k)

 f:{x,string 0{M y+10*x}/"H"$'x inter .Q.n}
usuario38879
fuente
1
Debo decir que admiro el uso de un bucle cuestionable en las reglas, pero realmente debo aclarar las reglas para hacer cumplir la inclusión de la declaración del cuasi-grupo y la declaración de cualquier tipo de función de ayuda en el recuento de caracteres. .
Fors