我的条形码有效吗?


33

EAN-8条码包括的信息和第八校验和数字7位数字。

通过将数字分别乘以3和1,将结果相加,然后从下一个10的倍数中减去,来计算校验和。

例如,给定数字2103498

Digit:        2   1   0   3   4   9   8
Multiplier:   3   1   3   1   3   1   3
Result:       6   1   0   3  12   9  24

这些结果数字的总和为55,所以校验和数字为60-55 = 5


挑战

给定一个8位条形码,您的任务是验证它是否有效-如果校验和有效,则返回真实值,否则返回false。

  • 您可以采用以下任何形式的输入:
    • 长度为8个字符的字符串,代表条形码数字
    • 8个整数的列表,条形码的数字
    • 一个非负整数(您可以假设前导零而不给出任何前导零,即1= 00000001,或请求输入中给出零)
  • 禁止计算EAN-8校验和的内置函数(即,使用前7位数字并计算最后7位数字)。
  • 这是,因此最短的程序(以字节为单位)获胜!

测试用例

20378240 -> True
33765129 -> True
77234575 -> True
00000000 -> True

21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False

Luhn算法有关,用于验证信用卡号(可能是重复)。
xnor

1
这个问题实际上与条形码(黑白条纹的东西)无关,而是与条形码编码的数字有关。该数字可以不带条形码而存在,并且条形码可以编码EAN以外的其他内容。也许只是“ 我的EAN-8有效 ”是一个更好的标题?
圣保罗Ebermann

2
@PaŭloEbermann并不完全相同……
FlipTack

7
在阅读条形码时,我希望阅读一些图像(或至少是一个位串),而不验证校验和。
圣保罗Ebermann

紧密相关,因为ISBN-13是EAN。
OlivierGrégoire17年

Answers:


5

果冻,7个字节

s2Sḅ3⁵ḍ

在线尝试!

怎么运行的

s2Sḅ3⁵ḍ  Main link. Argument: [a,b,c,d,e,f,g,h] (digit array)

s2       Split into chunks of length 2, yielding [[a,b], [c,d], [e,f], [g,h]].
  S      Take the sum of the pairs, yielding [a+c+e+g, b+d+f+h].
   ḅ3    Convert from ternary to integer, yielding 3(a+c+e+g) + (b+d+f+h).
     ⁵ḍ  Test if the result is divisible by 10.

13

JavaScript(ES6),41 40 38字节

@ETHProductions节省了2个字节,@ Craig Ayre节省了1个字节。

s=>s.map(e=>t+=e*(i^=2),t=i=1)|t%10==1

将输入作为数字列表。

确定所有数字的总和,包括校验和。

如果总和是10的倍数,则它是有效的条形码。

测试用例


我要说,你可以通过节省3个字节从前期递归切换到后递归g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1,但你可能已经找到了一个更好的办法...
ETHproductions

谢谢@ETHproductions,我已更改为map,我认为它会更好,因为输入可以是数字列表而不是字符串。
瑞克·希区柯克

也许另存一个字节s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1
ETHproductions

是的,很棒,谢谢
:)

很好的解决方案!你能不能代替&&|自truthy输出1/0 / falsy被允许?
Craig Ayre


8

果冻,8字节

m2Ḥ+µS⁵ḍ

尝试测试套件。

果冻,9 个字节

JḂḤ‘×µS⁵ḍ

在线尝试尝试测试套件。

如何运作

m2Ḥ+ µS⁵ḍ〜完整程序。

m2〜模块化2。返回输入的第二个元素。
  Ḥ〜每个加倍。
   + µ〜追加输入并开始新的单子链。
     S〜总和
      ⁵ḍ〜被10整除吗?
JḂḤ'×µS⁵ḍ〜完整程序(单声道)。

J〜1分度长度范围。
 Ḃ〜位;将上述范围内的每个数字乘以2。
  Ḥ〜每个加倍。
   '〜每个递增。
    ×〜与输入成对相乘。
     µ〜开始一个新的单子链。
      S〜总和
       ⁵ḍ〜总和可以除以10吗?

条形码的前7位数字和校验和数字的结果必须10的倍数才有效。因此,如果应用于整个列表的算法可被10整除,则校验和有效。


仍为9个字节,但具有一致的值:JḂḤ‘×µS⁵ḍ
HyperNeutrino

@HyperNeutrino谢谢,我知道这是一个原子!
Xcoder先生17年

也有9个字节::JḂaḤ+µS⁵ḍP
HyperNeutrino

@HyperNeutrino好吧,有很多选择:P
Xcoder先生,2017年

1
8个字节还是8个字符?m2Ḥ+µS⁵ḍ在UTF-8中为15个字节,除非我计算错误。
ta.speot。是

7

MATL,10字节

感谢@Zgarb指出了一个错误,现在已更正。

IlhY"s10\~

在线尝试!验证所有测试用例

说明

Ilh     % Push [1 3]
Y"      % Implicit input. Run-length decoding. For each entry in the
        % first input, this produces as many copies as indicated by
        % the corresponding entry of the second input. Entries of
        % the second input are reused cyclically
s       % Sum of array
10\     % Modulo 10
~       % Logical negate. Implicit display

7

Befunge-98(PyFunge)16 14字节

通过使用j代替;s 跳过第二部分,以及在第一部分交换a ~+在第二部分中摆脱a +,从而节省了2个字节。

~3*+~+6jq!%a+2

输入为8位数字(如果适用,前导数字为0)。

通过退出代码输出(在TIO上打开调试下拉列表),其中1为true,0为false。

在线尝试!

说明

该程序使用各种技巧。

首先,它通过ASCII值将数字一一对应。通常,这需要从我们从输入中读取的每个值中减去48。但是,如果不进行修改,我们的总和将剩下16个(3 + 1 + 3 + 1 + 3 + 1 + 3 + 1)额外的48个副本,这意味着我们的总数将比768大它应该是什么。由于我们只关心总和mod 10,因此我们可以稍后再将2加和。因此,我们可以采用原始ASCII值,节省6个字节左右。

其次,此代码仅检查是否每个其他字符都是EOF,因为保证输入的长度仅为8个字符。

第三,该#行末尾的不会跳过第一个字符,但是会;从另一方向跳过。这比#;在前面放一个更好。

因为程序的第二部分仅运行一次,所以我们不必对其进行设置,以便在向后运行时跳过第一部分。这使我们可以使用jump命令跳过后半部分,因为我们在执行向后执行之前退出。

一步步

注意:“奇数”和“偶数”字符基于0索引系统。第一个字符是偶数,索引为0。

~3*+~+      Main loop - sum the digits (with multiplication)
~           If we've reached EOF, reverse; otherwise take char input. This will always
                be evenly indexed values, as we take in 2 characters every loop.
 3*+        Multiply the even character by 3 and add it to the sum.
    ~       Then, take an odd digit - we don't have to worry about EOF because
                the input is always 8 characters.
     +      And add it to the sum.
      6j    Jump over the second part - We only want to run it going backwards.

        q!%a+2    The aftermath (get it? after-MATH?)
            +2    Add 2 to the sum to make up for the offset due to reading ASCII
          %a      Mods the result by 10 - only 0 if the bar code is valid
         !        Logical not the result, turning 0s into 1s and anything else into 0s
        q         Prints the top via exit code and exits

6

C, 78  77字节

i,s,c,d=10;f(b){for(i=s=0,c=b%d;b/=d;)s+=b%d*(3-i++%2*2);return(d-s%d)%d==c;}

在线尝试!

C(gcc),72个字节

i,s,c,d=10;f(b){for(i=s=0,c=b%d;b/=d;)s+=b%d*(i++%2?:3);b=(d-s%d)%d==c;}

在线尝试!


6

Wolfram语言(Mathematica)26 21字节

10∣(2-9^Range@8).#&

在线尝试!

将输入作为8位数字的列表。

怎么运行的

2-9^Range@8是10的模全同2-(-1)^Range@8,即{3,1,3,1,3,1,3,1}。我们将这个列表的点积与输入进行比较,并检查结果是否可被10整除。

Wolfram语言(Mathematica),33字节,不竞争

Check[#~BarcodeImage~"EAN8";1,0]&

在线尝试!

将输入作为字符串。返回1有效条形码和0无效条形码。

怎么运行的

我可以通过内置方式找到最好的东西(因为Mathematica就是关于这些的)。

内部位#~BarcodeImage~"EAN8";1生成EAN8条形码的图像,然后将其完全忽略并评估为1。但是,如果条形码无效,则会BarcodeImage生成一条警告,Check捕获该警告,在这种情况下返回0。


3
您是在手工计算,是因为它更短,还是因为Wolfram在其标准库中的某个地方还没有ValidateEAN8BarCode()函数?
标记

1
@Mark Mathematica无法直接验证条形码,但我刚刚发现BarcodeImage,它会生成条形码的图像,并在此过程中验证条形码。这样Check[#~BarcodeImage~"EAN8";0,1]<1&就可以了(但是会更长)。
Misha Lavrov

5

Java 8,58 56 55字节

a->{int r=0,m=1;for(int i:a)r+=(m^=2)*i;return r%10<1;}

通过@RickHitchcock间接感谢-2个字节,方法是使用(m=4-m)*i而不是m++%2*2*i+i在他的JavaScript答案中看到它。通过使用代替,
间接感谢@ETHProductions(和@RickHitchcock)-1个字节。(m^=2)*i(m=4-m)*i

说明:

在这里尝试。

a->{              // Method with integer-array parameter and boolean return-type
  int r=0,        //  Result-sum
      m=1;        //  Multiplier
  for(int i:a)    //  Loop over the input-array
    r+=           //   Add to the result-sum:
       (m^=2)     //    Either 3 or 1,
       *i;        //    multiplied by the digit
                  //  End of loop (implicit / single-line body)
  return r%10<1;  //  Return if the trailing digit is a 0
}                 // End of method

1
您可以使用另一个技巧来保存另一个字节,@ ETHProductions向我展示了:更改m=4-mm^=2
里克·希区柯克

@RickHitchcock当然,啊。^=1当我想在0和之间切换时,我经常在答案中使用1^=2在这种情况下可以在1和之间切换3。不错的技巧,感谢您提出的评论。:)
Kevin Cruijssen

4

05AB1E,14个字节

θ¹¨3X‚7∍*O(T%Q

在线尝试!

需要前导0s,需要数字列表。


似乎失败了3100004(应该是事实)。
Zgarb

@Zgarb你想念0那里。
Erik the Outgolfer

哦,需要一个琴弦吗?好吧,我的坏。
Zgarb

@Zgarb好吧,您可以省略引号,但是是的,您确实需要引号0。此答案实际上是在字符串上使用数字函数,这是05AB1E的功能之一。
暴民埃里克(Erik the Outgolfer)'17年

@ Mr.Xcoder这个问题不是很清楚,我将在下面添加另一个处理该问题的代码。
Erik the Outgolfer

4

Pyth,8个字节

!es+*2%2

验证所有测试用例!

Pyth,13个字节

如果我们可以假设输入总是正好有8位数字:

!es.e*bhy%hk2

验证所有测试用例!


这是如何运作的?

!es + * 2%2〜完整程序。

      %2〜输入[:: 2]。输入的第二个元素。
    * 2〜双(重复列表两次)。
   +〜追加输入。
  s〜总和。
 e〜最后一位。
!〜逻辑非。
!es.e * sbhy%hk2〜完整程序。

               〜将输入转换为字符串。
   .e〜枚举映射,将当前值存储在b中,将索引存储在k中。
          %hk2〜索引的奇偶校验。(k +1)%2。
        hy〜两倍,递增。这会将奇数整数映射为1,将偶数整数映射为3。
      b〜当前数字。
     *〜相乘。
  s〜总和。
 e〜最后一位。
!〜逻辑否定。

如果应用算法后的前7位数字之和从10中减去,然后与最后一位数字进行比较,则等效于在应用算法后检查所有数字之和是否为10的倍数。


似乎失败了3100004(应该是事实)。
Zgarb

@Zgarb等待我们应该做的3*3+1*1+0*3+...还是0*3+3*1+1*0..?我以为我们应该做前者
Xcoder先生,2017年

在新规范中,添加了前导数字以确保精确到8(如果我理解正确的话)。
Zgarb

@Zgarb好的,已修复。
Xcoder先生17年


4

视网膜23 22字节

-1字节感谢Martin Ender

(.).
$1$1$&
.
$*
M`
1$

在线尝试!

说明

输入示例: 20378240

(.).
$1$1$&

用重复两次的第一个数字替换每个数字对,然后是数字对本身。我们得到2220333788824440

.
$*

将每个数字转换为一元。为了清楚起见加上括号,我们得到(11)(11)(11)()(111)(111)...

M`

计算空字符串的匹配数目,该数目比字符串中的匹配数目大一。(在最后两个步骤中,我们基本上对每个数字+1求和)结果:60

1$

1在字符串末尾匹配a 。我们将数字分别乘以3和1并相加,对于有效的条形码,该数字应被10整除(最后一位为0);但我们在最后一步中也添加了1,因此我们希望最后一位为1。最终结果:1


2
我认为您可以.在比赛阶段放弃比赛,并1$在比赛结束时进行比赛。
Martin Ender's

@MartinEnder非常好,我会做到的,谢谢!
Leo

3

PowerShell,85字节

param($a)(10-(("$a"[0..6]|%{+"$_"*(3,1)[$i++%2]})-join'+'|iex)%10)%10-eq+"$("$a"[7])"

在线尝试!验证所有测试用例

实现定义的算法。接受输入$a,用拉出每个数字,"$a"[0..6]然后用循环遍历它们|%{...}。每次迭代时,我们将数字取为数字,将其转换为字符串,"$_"然后将其转换为int,+然后再乘以3or或1(通过增加$imodulo 选择2)。

这些结果全部收集起来并加总-join'+'|iex。我们采用该结果mod 10,从中减去该值10,然后再次采用结果mod 10(这第二个mod是考虑00000000测试用例所必需的)。然后,我们检查-eq该数字是否与最后一位数字相同。该布尔结果留在管道上,并且输出是隐式的。


似乎失败了3100004(应该是事实)。
Zgarb

@Zgarb对我有用吗?在线尝试!
AdmBorkBork

好的,我没有引号就对它进行了测试。
Zgarb

@Zgarb啊,是的。如果不带引号,PowerShell将隐式转换为整数,去除前导零。
AdmBorkBork

3

果冻,16字节

ż3,1ṁ$P€SN%⁵
Ṫ=Ç

在线尝试!

将输入作为数字列表


Nitpick:您的TIO超时。另外,16个字节
暴民埃里克(Erik the Outgolfer)'17

@EriktheOutgolfer等待什么。当我将D页脚放入页脚时,它会起作用。是的,谢谢!:D
HyperNeutrino

@EriktheOutgolfer我做错了吗?您的16个字元似乎无效?
HyperNeutrino

也许它的工作方式有所不同,但您的似乎也有点无效...特别是我认为最后一行应该是DµṪ=Ç
Erik the Outgolfer

1
似乎失败了3100004(应该是事实)。
Zgarb

3

APL(Dyalog),14个字节

等同于流浪汉的解决方案

完整的程序主体。提示输入来自STDIN的数字列表。

0=10|+/⎕×83 1

在线尝试!

是...

0= 零等于

10| 的mod-10

+/ 总数是

⎕× 输入时间

8⍴3 1 周期取自八个元素 [3,1]


1
您是说APL不能用古代苏美尔文或线性B之类的文字来做一个角色吗?
标记

火车:0 = 10 |-/ + 2×+ /
ngn

3

05AB1E,9个字节

3X‚7∍*OTÖ

在线尝试!

3X‚7∍*OTÖ    # Argument a
3X‚          # Push [3, 1]
   7∍        # Extend to length 7
     *       # Multiply elements with elements at same index in a
      O      # Total sum
       TÖ    # Divisible by 10

真好!当我看到此内容时,我想到的第一件事是“扩展长度”,还没有使用过。
魔术章鱼缸

31×S*OTÖ8个字节 ×只需按31 n次。当您相乘时,它会自动删除多余的31。
魔术章鱼缸

@MagicOctopusUrn在第6个测试用例上似乎失败了69165430 -> 1
kalsowerus

3

J,17个字节

-10个字节,感谢科尔

0=10|1#.(8$3 1)*]

在线尝试!

这使用大小相等的列表的乘法来避免原始解决方案的zip / multiply组合,以及1#.将产品加在一起的“ base 1技巧” 。高级方法类似于原始解释。

原始的27字节

0=10|{:+[:+/[:*/(7$3 1),:}:

在线尝试!

解释

0 =                                        is 0 equal to... 
    10 |                                   the remainder when 10 divides...
         {: +                              the last input item plus...
              [: +/                        the sum of...
                    [: */                  the pairwise product of...
                          7$(3 1) ,:       3 1 3 1 3 1 3 zipped with...
                                     }:    all but the last item of the input

0=10|1#.(8$3 1)*]应该工作17个字节(也执行相同的算法)。我确定在Beta中您可以在钩子的右侧用一个名词结束,因此0=10|1#.]*8$3 1可以用15来代替(我会检查tio但它似乎掉下来了?)
cole

@科尔,我喜欢这个改进。我已经了解并忘记了1#.2到3次技巧,谢谢您的提醒。哦,顺便说一句,15字节版本在TIO中不起作用。
约拿(Jonah)

3

C(gcc),84 82 72 61 54字节

c;i;f(x){for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;c=c%10<1;}

来自Neil的 -21个字节

Nahuel Fouilleul的 -7个字节

在线尝试!

独立于Steadybox的答案而开发

'f'是将条形码作为int,然后返回1True和0False 的函数。

  • f存储的最后一位数字xss=x%10

  • 然后计算cfor(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)中的总和

    • c是总和,i是一个计数器

    • 对于每个数字(包括第一个1+2*i%4数字x%10),将数字()乘以校验和并递增ii++in 3-2*i++%4

      • 1+2*i%4i偶数时为1,在i奇数时为0
  • 然后返回总和是否为10的倍数,并且由于我们添加了最后一位数字(乘以1),因此如果条形码有效,则总和将为10的倍数。(使用依赖于GCC的未定义行为来忽略return)。


我想(x%10)可能只是xc%10以后要服用时。我也认为您可以使用i<8,然后只测试最后是否c%10为零。
尼尔,2017年

@尼尔谢谢!那有-10个字节。
pizzapant184 '17

实际上,我认为这s是不必要的:c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;}
Neil

在TiO链接是61个字节,但答案是72,也不知道是什么原因x=c%10<1c=c%10<1代替return c%10<1仍然有效
纳乌艾尔乌Fouilleul

i<8可以由x
Nahuel Fouilleul

3

C,63字节

i;s=0;c(int*v){for(i=0;i<8;i++){s+=v[i]*3+v[++i];}return s%10;}

假设0是,true并且其他任何值为false

+3个字节以获得更好的返回值

i;s=0;c(int*v){for(i=0;i<8;i++){s+=v[i]*3+v[++i];}return s%10==0;}

添加==0return语句。

不打高尔夫球

int check(int* values)
{
    int result = 0;
    for (int index = 0; index < 8; index++)
    {
        result += v[i] * 3 + v[++i]; // adds this digit times 3 plus the next digit times 1 to the result
    }
    return result % 10 == 0; // returns true if the result is a multiple of 10
}

这使用了EAN校验和的替代定义,在该定义中选择了校验位,以使包括校验位在内的整个条形码的校验和为10的倍数。从数学上讲,这是相同的,但编写起来要简单得多。

根据Steadybox的建议,在循环内初始化变量,共63个字节

i;s;c(int*v){for(i=s=0;i<8;i++){s+=v[i]*3+v[++i];}return s%10;}

根据Steadybox的建议删除大括号,61字节

i;s;c(int*v){for(i=s=0;i<8;i++)s+=v[i]*3+v[++i];return s%10;}

使用<1而不是==0更好的返回值由凯文Cruijssen的建议

i;s=0;c(int*v){for(i=0;i<8;i++){s+=v[i]*3+v[++i];}return s%10<1;}

添加<1return语句中,这只会添加2个字节,而不是添加==0会添加3个字节。


您可以通过删除后面的来节省两个字节。另外,函数提交必须是可重用的,因此您需要在函数内部进行初始化(只需更改为和即可)。{}forsi;s=0;i,s;i=0;i=s=0;
Steadybox '17

@Steadybox如何删除大括号?
米歇尔·约翰逊

他们里面只有一个陈述。如果后面没有大括号for,则循环主体将成为下一个语句。for(i=0;i<8;i++){s+=v[i]*3+v[++i];}与相同for(i=0;i<8;i++)s+=v[i]*3+v[++i];
Steadybox '17

@Steadybox当然哦。这是我通常会忘记的C语法的怪癖之一,因为在编写普通代码时,即使不必要,我也会始终使用大括号,因为它使代码更具可读性。
米歇尔·约翰逊

在正确/错误答案中,通过添加而不是+3,==0可以使用+2 <1。:)
Kevin Cruijssen

2

JavaScript(Node.js),47字节

e=>eval(e.map((a,i)=>(3-i%2*2)*a).join`+`)%10<1

尽管答案还短得多,但这是我第一次尝试使用JavaScript打高尔夫球,因此我想听听打高尔夫球的建议:-)

测试中

或者,您可以在线尝试!


2

Perl 5 5,37 32 +1(-p)字节

s/./$-+=$&*(--$|*2+1)/ge;$_=/0$/

-5字节,感谢Dom Hastings。原为37 +1字节

$s+=$_*(++$i%2*2+1)for/./g;$_=!!$s%10

在线尝试


1
稍微玩了一下,以为我会分享一个有用的技巧:--$|1和之间切换,0因此您可以使用它代替++$i%2交替的布尔值!此外,所有重要的事情是total($s)matchs /0$/,设法将33个字节的更改与结合起来s///在线尝试!(-l仅供参考)
Dom Hastings

是的,我虽然要s/./(something with $&)/ge和要/0$/匹配,但不能将两者结合起来。
Nahuel Fouilleul

2

Brainfuck,228字节

>>>>++++[<++>-]<[[>],>>++++++[<++++++++>-]<--[<->-]+[<]>-]>[->]<<<<[[<+>->+<]<[>+>+<<-]>>[<+>-]<<<<<]>>>>[>>[<<[>>+<<-]]>>]<<<++++[<---->-]+++++[<++<+++>>-]<<[<[>>[<<->>-]]>[>>]++[<+++++>-]<<-]<[[+]-<]<++++++[>++[>++++<-]<-]>>+.

大概可以改善一点。输入一次取1位数,输出1为真,0为假。

怎么运行的:

>>>>++++[<++>-]<

将8放在位置3。

[[>],>>++++++[<++++++++>-]<--[<->-]+[<]>-]

输入8次,每次将其从ascii值更改为实际值+2。输入之间用一个空格隔开,这些编号将被删除,以便以后更容易乘法。

>[->]

从每个项目中减去一个。我们的磁带现在看起来像

0 0 0 0 4 0 4 0 8 0 7 0 6 0 2 0 3 0 10 0 0
                                         ^

每个值大于应有的1。这是因为零会弄乱我们的乘法过程。

现在我们准备开始乘法。

<<<<

转到倒数第二个项目。

[[<+>->+<]<[>+>+<<-]>>[<+>-]<<<<<]

当为零时,将其处的项目乘以3,然后向左移动两个项目。现在,我们将所需的所有内容乘以三,并且我们在磁带上的第一个位置。

>>>>[>>[<<[>>+<<-]]>>]

对整个列表求和。

<<<++++[<---->-]

我们的值比实际值大16。减去16即可解决此问题。

+++++[<++<+++>>-]

我们需要测试总和是否为10的倍数。最大总和为所有9s,即144。由于没有总和大于10 * 15,因此按15和10的顺序将其放在磁带上总和的权利。

<<[<[>>[<<->>-]]>[>>]++[<+++++>-]<<-]

移至15。当它不为零时,请检查总和是否为非零。如果是,则减去10。现在,我们要么处于(空)和位置,要么处于(也空)十个位置。向右移动。如果我们处于总和位置,那么我们现在处于非零15位置。如果是这样,请向右移动两次。现在我们在两种情况下都处于同一位置。将十个位置加十,然后从十五个位置减一。

其余的用于输出:

<[[+]-<]<++++++[>++[>++++<-]<-]>>+.

移至求和位置。如果非零(负),则条形码无效;否则,条形码无效。将位置设置为-1。现在添加49以获取正确的ascii值:如果有效,则为1;如果无效,则为0。


2

Java 8,53字节

打高尔夫球:

b->(3*(b[0]+b[2]+b[4]+b[6])+b[1]+b[3]+b[5]+b[7])%10<1

在lambda中直接计算似乎是最短的解决方案。它适合单个表达式,最大程度地减少了lambda开销,并删除了无关的变量声明和分号。

public class IsMyBarcodeValid {

  public static void main(String[] args) {
    int[][] barcodes = new int[][] { //
        { 2, 0, 3, 7, 8, 2, 4, 0 }, //
        { 3, 3, 7, 6, 5, 1, 2, 9 }, //
        { 7, 7, 2, 3, 4, 5, 7, 5 }, //
        { 0, 0, 0, 0, 0, 0, 0, 0 }, //
        { 2, 1, 0, 3, 4, 9, 8, 4 }, //
        { 6, 9, 1, 6, 5, 4, 3, 0 }, //
        { 1, 1, 9, 6, 5, 4, 2, 1 }, //
        { 1, 2, 3, 4, 5, 6, 7, 8 } };
    for (int[] barcode : barcodes) {
      boolean result = f(b -> (3 * (b[0] + b[2] + b[4] + b[6]) + b[1] + b[3] + b[5] + b[7]) % 10 < 1, barcode);
      System.out.println(java.util.Arrays.toString(barcode) + " = " + result);
    }
  }

  private static boolean f(java.util.function.Function<int[], Boolean> f, int[] n) {
    return f.apply(n);
  }
}

输出:

[2, 0, 3, 7, 8, 2, 4, 0] = true
[3, 3, 7, 6, 5, 1, 2, 9] = true
[7, 7, 2, 3, 4, 5, 7, 5] = true
[0, 0, 0, 0, 0, 0, 0, 0] = true
[2, 1, 0, 3, 4, 9, 8, 4] = false
[6, 9, 1, 6, 5, 4, 3, 0] = false
[1, 1, 9, 6, 5, 4, 2, 1] = false
[1, 2, 3, 4, 5, 6, 7, 8] = false

2

QBasic,54 52字节

gh,无聊的回答竟然是最短的:

INPUT a,b,c,d,e,f,g,h
?(3*a+b+3*c+d+3*e+f+3*g+h)MOD 10=0

这将输入逗号分隔的数字。我最初的54字节解决方案(一次输入一位数字)使用一种“更精细”的方法:

m=3
FOR i=1TO 8
INPUT d
s=s+d*m
m=4-m
NEXT
?s MOD 10=0

2

C#(.NET Core)65 62字节

b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;}

在线尝试!

致谢

由于@KevinCruijssen和使用“异或”运算符的巧妙技巧,-3个字节。

去高尔夫

b=>{
    int s=0,i=0,t=1;

    while(i<8)
        s+=b[i++]*(t^=2); // exclusive-or operator alternates t between 3 and 1.

    return s%10<1;
}

C#(.NET Core),53字节

b=>(3*(b[0]+b[2]+b[4]+b[6])+b[1]+b[3]+b[5]+b[7])%10<1

在线尝试!

@Snowman的答案的直接端口。


为了您的第一个答案:b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;}62个字节),或在foreach,也是62个字节或者:b=>{int s=0,t=1;foreach(int i in b)s+=i*(t^=2);return s%10<1;}(这是一个端口我的Java 8回答)。
凯文·克鲁伊森

1

MATLAB / 八度,32字节

@(x)~mod(sum([2*x(1:2:7),x]),10)

在线尝试!

尽管我开发了其他Octave答案,但我将在发布此代码和方法时发布它,而无需查看其他答案。

这里我们有一个匿名函数,它将输入作为8个值的数组,如果有效的条形码返回true,否则返回false。

计算结果如下。

              2*x(1:2:7)
             [          ,x]
         sum(              )
     mod(                   ,10)
@(x)~
  1. 奇数(一个索引)乘以2。
  2. 结果被放在输入数组的前面,给出一个数组,其总和将包含三次奇数位,一次包含偶数位。
  3. 我们进行总和,该总和还将包括提供的校验和。
  4. 接下来执行模10。如果提供的校验和有效,那么包括校验和值在内的所有乘法数字的总和将为10的倍数。因此,只有有效的条形码会返回0。
  5. 如果有效,则将结果取反以获得逻辑输出true。

1

Excel,37个字节

将“ 8个整数的列表”解释为允许在Excel中使用8个单独的单元格:

=MOD(SUM(A1:H1)+2*(A1+C1+E1+G1),10)=0

= MOD(SUM(((A1:H1)+ 2 *(A1 + C1 + E1 + G1)),10)= 0这个公式在Excel中存在吗?
RosLuP

@RosLuP,未预定义,否。但是Modulo,Sum,+等会做;-)
Wernisch

我只想说,似乎在APL中,先执行y =(A1:H1)+ 2 *(A1 + C1 + E1 + G1),然后进行总和和mod运算就很好了;在APL中,首先进行sum(A1:H1)等操作并不顺利,例如(1,2,3)+ 4 =(5,6,7)而不是sum(5,6,7)= 18; 请注意,sum(1,2,3)= 6和6 + 4 = 10与18不同。但是可能我在某些
地方

抱歉,@ RosLuP,()您的评论中缺少更改的。
Wernisch '17

问题是Excel的解释方式=(A1:H1):这不是作为数组处理的。如果放在不在A-H范围内的任何列中,则无效。如果放在AH的列中,则仅返回该列的值。(以%表示的公式以%表示:C2-> C1 H999-> H1 K1-> #VALUE!)
Wernisch

1

Ruby,41字节

接受一个整数数组。-6字节感谢乔丹。

->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}

真好!不需要的FWIWmap在这里都:zip需要一个块。您可以通过使用$.而不是初始化来节省更多的字节s->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
乔丹

1

TI-Basic(83系列),18字节

not(fPart(.1sum(2Ans-Ans9^cumSum(binomcdf(7,0

在中将输入作为列表Ans。返回1有效的条形码和0无效。

我的Mathematica答案的一部分。包括屏幕截图代替在线测试环境:

条码截图

显着特征:binomcdf(7,0用于生成列表{1,1,1,1,1,1,1,1}(从7个成功概率为0的试验中得出的概率列表,对于N = 0,1,...,7,最多将有N个成功)。然后,cumSum(把它变成{1,2,3,4,5,6,7,8}

这比使用该seq(命令要短一个字节,尽管从历史上看,它的使用速度也要快得多。

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.