Oblicz cyfrę kontrolną za pomocą algorytmu Damm

17

Istnieją popularne algorytmy kontrolne, takie jak Luhn, a następnie są dobre , na przykład algorytm Damm. Jedynym możliwym powodem popularności algorytmów, takich jak Luhn, jest ich implementacja w golfa. Oznacza to, że jako społeczność możemy zmieniać świat, oferując golfowe implementacje lepszych algorytmów.

Dlatego wyzwaniem jest zmiana świata poprzez napisanie funkcji lub kompletnego programu w wybranym języku, który oblicza cyfrę kontrolną za pomocą algorytmu Damm . Odpowiedź z najmniejszą liczbą znaków (nie bajtów) zostanie wybrana jako zwycięzca za kilka tygodni. Zauważ, że wszystkie funkcje pomocnicze i deklaracja tabeli operacji muszą być uwzględnione w liczbie znaków. W przypadku remisu zostanie wybrana najpopularniejsza odpowiedź.

Ten algorytm obraca się wokół tabeli operacyjnej, która musi być słabo całkowicie antysymetryczną quasiggrupą rzędu 10. Tabela operacyjna, którą można znaleźć w artykule Wikipedii na temat algorytmu Damm, jest tym, którego należy użyć w tym wyzwaniu. Dla kompletności odtworzę go poniżej:

    |   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

W skrócie (szczegóły w artykule na Wikipedii ) algorytm działa w następujący sposób:

  1. Zaczynasz od listy cyfr do przetworzenia i cyfry pośredniej ustawionej na 0.
  2. Dla każdej cyfry na liście obliczasz nową cyfrę pośrednią, używając cyfry jako indeksu kolumny i poprzedniej cyfry pośredniej jako indeksu wiersza.
  3. Ostatnią cyfrą pośrednią jest cyfra kontrolna. Jeśli sprawdzasz poprawność numeru, który ma już dodaną cyfrę kontrolną, ostatnia cyfra tymczasowa wynosi 0, jeśli numer jest prawidłowy.

Twój program lub funkcja musi zaakceptować ciąg znaków, który może zawierać dowolne znaki oprócz null, ale powinien dotyczyć tylko cyfr w ciągu. Musi albo wydrukować (jeśli program) lub zwrócić (jeśli funkcja) oryginalny ciąg z dołączoną obliczoną cyfrą kontrolną. Jeśli zdecydujesz się napisać program, program może zaakceptować dane wejściowe jako argument lub jako dane standardowe. Jeśli ciąg wejściowy jest pusty lub nie zawiera żadnych cyfr, musisz zwrócić lub dołączyć zero.

Kilka przykładów:

Input       |   Output
------------+-------------
42          |   427
427         |   4270
2 to 2      |   2 to 29
23 42 76-   |   23 42 76-5
-           |   -0
Fors
źródło
Z niecierpliwością czekam na zgłoszenia Piet, które twierdzą, że wygrywają.
Alchymist

Odpowiedzi:

3

Pyth, 49 znaków

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

Zawiera bóg wie, jakie znaki, więc oto program Python3 do generowania powyższego programu dokładnie na twoim komputerze:

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

Wyjaśnienie:

+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
źródło
3

CJam, 54 znaki

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

Jest tam jedna postać, której nie można wydrukować, więc możesz skorzystać z bezpośredniego linku poniżej.

Sprawdź to tutaj.

Wyjaśnienie

TŚledzona jest cyfra tymczasowa , którą CJam inicjuje na 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
źródło
3

Python 3, 149 141 138 znaków

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

Przykłady:

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

Dzięki @MegaTom i @Sieg za pomoc w usunięciu łącznie 11 znaków

monopole
źródło
2
10 * int (a) + int (i) jest int (a + i), prawda?
MegaTom
Słuszna uwaga! Dziękuję, to oszczędza 5 znaków.
monopole
1
Po której następuje pojedyncze zdanie, nie potrzebuje nowego wiersza pomiędzy. (-3)
patrz
2

Ruby, 149 znaków

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

Testowane na repl.it

MegaTom
źródło
2

J, 117 bajtów

Zawiera tylko ascii do wydruku. (Trudno mi było pracować z J i Unicode). Generuje tabelę przejścia z indeksów permutacji wierszy.

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'

Stosowanie:

   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

Wypróbuj online tutaj.

randomra
źródło
2

Haskell, 131 znaków

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

Testowe uruchomienie:

> mapM_ (putStrLn.f) ["42", "427", "2 to 2", "23 42 76-", "-"]
427
4270
2 to 29
23 42 76-5
-0
nimi
źródło
0

k, 36 znaków

/ 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 znaków (odpowiednik implementacji k)

 f:{x,string 0{M y+10*x}/"H"$'x inter .Q.n}
użytkownik38879
źródło
1
Muszę powiedzieć, że podziwiam stosowanie wątpliwej pętli w regułach, ale tak naprawdę muszę wyjaśnić zasady, aby wymusić włączenie deklaracji quasi-grupy i deklaracji o jakiejkolwiek funkcji pomocniczej w liczbie znaków .
Fors