使用Damm算法计算校验位


17

流行的校验数字算法,例如Luhn,然后有很好的的,例如Damm算法。诸如Luhn之类的算法流行背后的唯一可能原因是,存在着代码实现它们的实现。这意味着我们作为一个社区有能力通过提供更好算法的高尔夫实现来改变世界。

因此,这个挑战就是通过使用您选择的语言编写一个函数或完整程序来改变世界,该函数或完整程序使用Damm算法来计算校验位。字符数最少(不是字节)的答案将在几周内被选为优胜者。请注意,所有帮助功能和操作表的声明都必须包括在字符计数中。如果是平局,将选择最流行的答案。

该算法围绕一个运算表,该运算表必须是10阶的弱完全反对称准群。可以在Wikipedia中有关Damm算法的文章中找到该运算表,该运算表将用于此挑战中。为了完整起见,我将在下面复制它:

    |   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

简而言之(有关详细信息,请参阅Wikipedia文章),该算法的工作方式如下:

  1. 您从要处理的数字列表和设置为0的中间数字开始。
  2. 对于列表中的每个数字,您可以通过使用该数字作为列索引并使用前一个中间数字作为行索引来计算一个新的中间数字。
  3. 最后的中间数字是校验数字。如果您要验证的数字中已经添加了校验位,则该数字有效时,最终的中间数字为0。

您的程序或函数必须接受可以包含除null以外的任何字符的字符串,但它仅应与字符串中的数字有关。它必须打印(如果是程序)或返回(如果是函数)原始字符串,并附加计算出的校验位。如果选择编写程序,则该程序可以接受输入作为参数或标准输入。如果输入字符串为空或不包含任何数字,则必须返回或附加零。

一些例子:

Input       |   Output
------------+-------------
42          |   427
427         |   4270
2 to 2      |   2 to 29
23 42 76-   |   23 42 76-5
-           |   -0

我期待看到Piet参赛者夺冠。
Alchymist 2015年

Answers:


3

Pyth,49个字符

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

包含上帝知道什么字符,因此这是一个Python3程序,可在您的计算机上准确生成上述程序:

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

说明:

+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.

3

CJam,54个字符

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

那里有一个无法打印的字符,因此您可能要使用下面的永久链接。

在这里测试。

说明

在中T,将跟踪中间数字 ,CJam初始化为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.";

3

Python 3中,149个141 138字符

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

例子:

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

感谢@MegaTom和@Sieg帮助删除了总共11个字符


2
10 * int(a)+ int(i)是int(a + i),不是吗?
MegaTom

好点子!谢谢,这样可以节省5个字符。
单极

1
对于后跟一个语句,不需要在两者之间使用换行符。(-3)
Seequ

2

Ruby,149个字符

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

经过测试 经过repl.it


2

J,117字节

仅包含可打印的ascii。(我在使用J和unicode时遇到了麻烦。)根据行的排列索引生成转换表。

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=.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

在这里在线尝试。


2

Haskell,131个字符

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

测试运行:

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

0

k,36个字符

/ 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个字符(与k等效)

 f:{x,string 0{M y+10*x}/"H"$'x inter .Q.n}

1
我必须说我很欣赏规则中存在可疑的漏洞,但是我确实必须澄清规则以强制在字符计数中包括准组声明和任何类型的帮助功能的声明。 。
Fors 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.