Is my barcode valid?

33

1

An EAN-8 barcode includes 7 digits of information and an 8th checksum digit.

The checksum is calculated by multiplying the digits by 3 and 1 alternately, adding the results, and subtracting from the next multiple of 10.

For example, given the digits 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

The sum of these resulting digits is 55, so the checksum digit is 60 - 55 = 5


The Challenge

Your task is to, given an 8 digit barcode, verify if it is valid - returning a truthy value if the checksum is valid, and falsy otherwise.

  • You may take input in any of the following forms:
    • A string, 8 characters in length, representing the barcode digits
    • A list of 8 integers, the barcode's digits
    • A non-negative integer (you can either assume leading zeroes where none are given, i.e. 1 = 00000001, or request input with the zeroes given)
  • Builtins that compute the EAN-8 checksum (i.e, take the first 7 digits and calculate the last) are banned.
  • This is , so the shortest program (in bytes) wins!

Test Cases

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

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

FlipTack

Posted 2017-11-15T15:19:41.803

Reputation: 13 242

Related to Luhn algorithm for verifying credit card numbers, possibly a dupe.

– xnor – 2017-11-15T17:58:44.490

1This question is not actually about a bar code (which is the black-white striped thing), but about the number encoded by a barcode. The number can exist without a bar code, and the bar code can encode other things than EANs. Maybe just "Is my EAN-8 valid" is a better title? – Paŭlo Ebermann – 2017-11-15T19:49:22.687

2@PaŭloEbermann doesn't quite have the same ring to it... – FlipTack – 2017-11-15T20:17:02.160

7When reading about barcodes, I expect some image reading (or at least a bit-string), not verifying a checksum. – Paŭlo Ebermann – 2017-11-15T20:19:40.747

Strongly related, since an ISBN-13 is an EAN. – Olivier Grégoire – 2017-11-16T14:55:56.637

Answers

5

Jelly, 7 bytes

s2Sḅ3⁵ḍ

Try it online!

How it works

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.

Dennis

Posted 2017-11-15T15:19:41.803

Reputation: 196 637

13

JavaScript (ES6), 41 40 38 bytes

Saved 2 bytes thanks to @ETHProductions and 1 byte thanks to @Craig Ayre.

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

Takes input as a list of digits.

Determines the sum of all digits, including the checksum.

If the sum is a multiple of 10, then it's a valid barcode.

Test Cases

let f=

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

console.log(f([2,0,3,7,8,2,4,0]));
console.log(f([3,3,7,6,5,1,2,9]));
console.log(f([7,7,2,3,4,5,7,5]));
console.log(f([0,0,0,0,0,0,0,0]));

console.log(f([2,1,0,3,4,9,8,4]));
console.log(f([6,9,1,6,5,4,3,0]));
console.log(f([1,1,9,6,5,4,2,1]));
console.log(f([1,2,3,4,5,6,7,8]));

Rick Hitchcock

Posted 2017-11-15T15:19:41.803

Reputation: 2 461

I was going to say you could save 3 bytes by switching from pre-recursion to post-recursion with g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1, but you may have found a better way...

– ETHproductions – 2017-11-15T16:45:14.933

Thanks, @ETHproductions, I've changed to map, which I think works better since input can be a list of digits instead of a string. – Rick Hitchcock – 2017-11-15T16:48:22.143

Perhaps save another byte with s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1? – ETHproductions – 2017-11-15T16:48:32.430

Yes, brilliant, thanks : ) – Rick Hitchcock – 2017-11-15T16:50:14.290

Great solution! Could you replace && with | to output 1/0 since truthy/falsy is allowed? – Craig Ayre – 2017-11-15T17:22:12.157

One more byte with i^=2? – ETHproductions – 2017-11-16T18:08:37.900

Sweet, thanks @ETHproductions! – Rick Hitchcock – 2017-11-16T18:15:18.310

10

Python 2, 64 48 35 29 bytes

mypetlion saved 19 bytes

lambda x:sum(x[::2]*2+x)%10<1

Try it online!

Halvard Hummel

Posted 2017-11-15T15:19:41.803

Reputation: 3 131

lambda x:sum(x[::2]*3+x[1::2])%10<1 For 35 bytes. – mypetlion – 2017-11-15T17:37:54.997

2lambda x:sum(x[::2]*2+x)%10<1 For 29 bytes. – mypetlion – 2017-11-15T18:51:18.273

8

Jelly, 8 bytes

m2Ḥ+µS⁵ḍ

Try the test suite.

Jelly, 9 bytes

JḂḤ‘×µS⁵ḍ

Try it online or Try the test suite.

How this works

m2Ḥ+µS⁵ḍ ~ Full program.

m2       ~ Modular 2. Return every second element of the input.
  Ḥ      ~ Double each.
   +µ    ~ Append the input and start a new monadic chain.
     S   ~ Sum.
      ⁵ḍ ~ Is divisible by 10?
JḂḤ‘×µS⁵ḍ  ~ Full program (monadic).

J          ~ 1-indexed length range.
 Ḃ         ~ Bit; Modulo each number in the range above by 2.
  Ḥ        ~ Double each.
   ‘       ~ Increment each.
    ×      ~ Pairwise multiplication with the input.
     µ     ~ Starts a new monadic chain.
      S    ~ Sum.
       ⁵ḍ  ~ Is the sum divisible by 10?

The result for the first 7 digits of the barcode and the checksum digit must add to a multiple of 10 for it to be valid. Thus, the checksum is valid iff the algorithm applied to the whole list is divisible by 10.

Mr. Xcoder

Posted 2017-11-15T15:19:41.803

Reputation: 39 774

Still 9 bytes but with consistent values: JḂḤ‘×µS⁵ḍ – HyperNeutrino – 2017-11-15T16:59:47.497

@HyperNeutrino Thanks, I knew there was an atom for this! – Mr. Xcoder – 2017-11-15T17:00:33.747

Also 9 bytes: JḂaḤ+µS⁵ḍ :P – HyperNeutrino – 2017-11-15T17:04:41.917

@HyperNeutrino Well there are a lot of alternatives :P – Mr. Xcoder – 2017-11-15T17:05:35.407

18 bytes or 8 characters? m2Ḥ+µS⁵ḍ is 15 bytes in UTF-8, unless I've calculated it wrong. – ta.speot.is – 2017-11-18T08:31:48.067

@ta.speot.is 8 bytes, Jelly has its own codepage

– Mr. Xcoder – 2017-11-18T10:54:51.750

7

MATL, 10 bytes

Thanks to @Zgarb for pointing out a mistake, now corrected.

IlhY"s10\~

Try it online! Or verify all test cases.

Explanation

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

Luis Mendo

Posted 2017-11-15T15:19:41.803

Reputation: 87 464

7

Befunge-98 (PyFunge), 16 14 bytes

Saved 2 bytes by skipping the second part using j instead of ;s, as well as swapping a ~ and + in the first part to get rid of a + in the second.

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

Input is in 8 digits (with leading 0s if applicable) and nothing else.

Outputs via exit code (open the debug dropdown on TIO), where 1 is true and 0 is false.

Try it online!

Explanation

This program uses a variety of tricks.

First of all, it takes the digits in one by one through their ASCII values. Normally, this would require subtracting 48 from each value as we read it from the input. However, if we don't modify it, we are left with 16 (3+1+3+1+3+1+3+1) extra copies of 48 in our sum, meaning our total is going to be 768 greater than what it "should" be. Since we are only concerned with the sum mod 10, we can just add 2 to the sum later. Thus, we can take in raw ASCII values, saving 6 bytes or so.

Secondly, this code only checks if every other character is an EOF, because the input is guaranteed to be only 8 characters long.

Thirdly, the # at the end of the line doesn't skip the first character, but will skip the ; if coming from the other direction. This is better than putting a #; at the front instead.

Because the second part of our program is only run once, we don't have to set it up so that it would skip the first half when running backwards. This lets us use the jump command to jump over the second half, as we exit before executing it going backwards.

Step by step

Note: "Odd" and "Even" characters are based on a 0-indexed system. The first character is an even one, with index 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

MildlyMilquetoast

Posted 2017-11-15T15:19:41.803

Reputation: 2 907

6

C,  78  77 bytes

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

Try it online!

C (gcc), 72 bytes

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

Try it online!

Steadybox

Posted 2017-11-15T15:19:41.803

Reputation: 15 798

6

Wolfram Language (Mathematica), 26 21 bytes

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

Try it online!

Takes input as a list of 8 digits.

How it works

2-9^Range@8 is congruent modulo 10 to 2-(-1)^Range@8, which is {3,1,3,1,3,1,3,1}. We take the dot product of this list with the input, and check if the result is divisible by 10.

Wolfram Language (Mathematica), 33 bytes and non-competing

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

Try it online!

Takes input as a string. Returns 1 for valid barcodes and 0 for invalid ones.

How it works

The best thing I could find in the way of a built-in (since Mathematica is all about those).

The inside bit, #~BarcodeImage~"EAN8";1, generates an image of the EAN8 barcode, then ignores it entirely and evaluates to 1. However, if the barcode is invalid, then BarcodeImage generates a warning, which Check catches, returning 0 in that case.

Misha Lavrov

Posted 2017-11-15T15:19:41.803

Reputation: 4 846

3Are you doing the calculation by hand because it's shorter, or because Wolfram doesn't yet have a ValidateEAN8BarCode() function somewhere in its standard library? – Mark – 2017-11-16T00:44:52.493

1@Mark Mathematica can't validate the barcode directly, but I just found BarcodeImage, which generates the image of the barcode, and validates the barcode in the process. So Check[#~BarcodeImage~"EAN8";0,1]<1& would work (but it's longer). – Misha Lavrov – 2017-11-16T00:50:45.043

5

Java 8, 58 56 55 bytes

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

-2 bytes indirectly thanks to @RickHitchcock, by using (m=4-m)*i instead of m++%2*2*i+i after seeing it in his JavaScript answer.
-1 byte indirectly thanks to @ETHProductions (and @RickHitchcock), by using (m^=2)*i instead of (m=4-m)*i.

Explanation:

Try it here.

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

Kevin Cruijssen

Posted 2017-11-15T15:19:41.803

Reputation: 67 575

1You can save another byte with a trick @ETHProductions showed me: change m=4-m to m^=2. – Rick Hitchcock – 2017-11-16T18:39:39.823

@RickHitchcock Ah, of course.. I use ^=1 pretty often in answers when I want to alter between 0 and 1. ^=2 works in this case to alter between 1 and 3. Nice trick, and thanks for the comment to mention it. :) – Kevin Cruijssen – 2017-11-16T18:49:01.177

4

05AB1E, 14 bytes

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

Try it online!

Needs leading 0s, takes list of digits.

Erik the Outgolfer

Posted 2017-11-15T15:19:41.803

Reputation: 38 134

Seems to fail on 3100004 (should be truthy). – Zgarb – 2017-11-15T16:15:24.983

@Zgarb You're missing a 0 there. – Erik the Outgolfer – 2017-11-15T16:15:51.790

Oh, it takes a string? Okay then, my bad. – Zgarb – 2017-11-15T16:17:20.437

@Zgarb Well, you can omit the quotes, but yes, you do need the leading 0. This answer actually uses number functions on strings, one of the features of 05AB1E. – Erik the Outgolfer – 2017-11-15T16:20:36.320

@Mr.Xcoder The question isn't very clear on that, I'll add another code which does handle for that below. – Erik the Outgolfer – 2017-11-15T16:23:39.187

4

Pyth, 8 bytes

!es+*2%2

Verify all the test cases!

Pyth, 13 bytes

If we can assume the input always has exactly 8 digits:

!es.e*bhy%hk2

Verify all the test cases!


How does this work?

!es+*2%2 ~ Full program.

      %2 ~ Input[::2]. Every second element of the input.
    *2   ~ Double (repeat list twice).
   +     ~ Append the input.
  s      ~ Sum.
 e       ~ Last digit.
!        ~ Logical NOT.
!es.e*sbhy%hk2 ~ Full program.

               ~ Convert the input to a String.
   .e          ~ Enumerated map, storing the current value in b and the index in k.
          %hk2 ~ Inverted parity of the index. (k + 1) % 2.
        hy     ~ Double, increment. This maps odd integers to 1 and even ones to 3.
      b        ~ The current digit.
     *         ~ Multiply.
  s            ~ Sum.
 e             ~ Last digit.
!              ~ Logical negation.

If the sum of the first 7 digit after being applied the algorithm is subtracted from 10 and then compared to the last digit, this is equivalent to checking whether the sum of all the digits, after the algorithm is applied is a multiple of 10.

Mr. Xcoder

Posted 2017-11-15T15:19:41.803

Reputation: 39 774

Seems to fail on 3100004 (should be truthy). – Zgarb – 2017-11-15T16:13:15.593

@Zgarb Wait should we do 3*3+1*1+0*3+... or 0*3+3*1+1*0..? I thought we are supposed to do the former – Mr. Xcoder – 2017-11-15T16:14:56.413

In the new spec, leading digits are added to ensure there are exactly 8 (if I understand correctly). – Zgarb – 2017-11-15T16:16:17.717

@Zgarb Ok, fixed. – Mr. Xcoder – 2017-11-15T16:18:36.373

4

Haskell, 40 38 bytes

a=3:1:a
f x=mod(sum$zipWith(*)a x)10<1

Try it online!

Takes input as a list of 8 integers. A practical example of using infinite lists.

Edit: Saved 2 bytes thanks to GolfWolf

butterdogs

Posted 2017-11-15T15:19:41.803

Reputation: 101

2

Using a recursive definition instead of cycle saves 2 bytes.

– Cristian Lupascu – 2017-11-16T07:50:58.093

4

Retina, 23 22 bytes

-1 byte thanks to Martin Ender!

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

Try it online!

Explanation

Example input: 20378240

(.).
$1$1$&

Replace each couple of digits with the first digit repeated twice followed by the couple itself. We get 2220333788824440

.
$*

Convert each digit to unary. With parentheses added for clarity, we get (11)(11)(11)()(111)(111)...

M`

Count the number of matches of the empty string, which is one more than the number of ones in the string. (With the last two steps we have basically taken the sum of each digit +1) Result: 60

1$

Match a 1 at the end of the string. We have multiplied digits by 3 and 1 alternately and summed them, for a valid barcode this should be divisible by 10 (last digit 0); but we also added 1 in the last step, so we want the last digit to be 1. Final result: 1.

Leo

Posted 2017-11-15T15:19:41.803

Reputation: 8 482

2I think you can drop the . on the match stage and match 1$ at the end. – Martin Ender – 2017-11-16T10:46:30.430

@MartinEnder very nice, I'll do that, thanks! – Leo – 2017-11-16T21:32:26.077

3

Jelly, 16 bytes

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

Try it online!

takes input as a list of digits

HyperNeutrino

Posted 2017-11-15T15:19:41.803

Reputation: 26 575

Nitpick: your TIO timeouts. Also, 16 bytes.

– Erik the Outgolfer – 2017-11-15T15:37:28.343

@EriktheOutgolfer Wait what how. It works when I put the D in the footer. And yay thanks! :D – HyperNeutrino – 2017-11-15T15:39:54.417

@EriktheOutgolfer Am I doing something wrong? Your 16-byter appears to be invalid? – HyperNeutrino – 2017-11-15T15:41:04.957

Maybe, it works kinda differently, but yours seems a bit invalid too...specifically I think the last line should be DµṪ=Ç. – Erik the Outgolfer – 2017-11-15T15:42:49.247

@EriktheOutgolfer Oh that would make sense. Yeah fixed that for +1 and I'll see what I'm doing wrong with your golf – HyperNeutrino – 2017-11-15T15:50:01.570

Looks like the 00000000 case has issues with mine. Since D returns [0], gets 0 and Ç gets [] and trying to multiply with [3, 1, 3, 1, 3, 1, 3] returns [3, 1, 3, 1, 3, 1, 3] then sum returns 15 negate returns -15 and mod 10 then returns 5 which is unequal to 0. – Erik the Outgolfer – 2017-11-15T15:51:56.963

1Seems to fail on 3100004 (should be truthy). – Zgarb – 2017-11-15T16:15:04.267

@Zgarb How is 3 * 3 + 1 * 1 = 4? – HyperNeutrino – 2017-11-15T16:20:14.550

@HyperNeutrino You need to do 0*3+3*1+1*3 = 4 (if I understand correctly). – Mr. Xcoder – 2017-11-15T16:23:40.393

@HyperNeutrino In the spec, leading zeros are added to ensure the input has exactly 8 digits, if you take it as an integer. – Zgarb – 2017-11-15T16:26:45.137

@Zgarb Oh I didn't see the spec change. In that case I'll just take it as digits – HyperNeutrino – 2017-11-15T16:32:55.010

I managed to abuse Jelly's 1-indexing to get 10 bytes.

– Mr. Xcoder – 2017-11-15T16:46:45.457

@Mr.Xcoder Oh wow nice +1 – HyperNeutrino – 2017-11-15T16:51:33.737

3

PowerShell, 85 bytes

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

Try it online! or Verify all test cases

Implements the algorithm as defined. Takes input $a, pulls out each digit with "$a"[0..6] and loops through them with |%{...}. Each iteration, we take the digit, cast it as a string "$_" then cast it as an int + before multiplying it by either 3 or 1 (chosen by incrementing $i modulo 2).

Those results are all gathered together and summed -join'+'|iex. We take that result mod 10, subtract that from 10, and again take the result mod 10 (this second mod is necessary to account for the 00000000 test case). We then check whether that's -equal to the last digit. That Boolean result is left on the pipeline and output is implicit.

AdmBorkBork

Posted 2017-11-15T15:19:41.803

Reputation: 41 581

Seems to fail on 3100004 (should be truthy). – Zgarb – 2017-11-15T16:14:31.030

@Zgarb Works for me? Try it online!

– AdmBorkBork – 2017-11-15T16:31:11.910

Ah ok, I tested it without the quotes. – Zgarb – 2017-11-15T16:33:25.187

@Zgarb Ah, yeah. Without the quotes, PowerShell will implicitly cast as an integer, stripping the leading zero(s). – AdmBorkBork – 2017-11-15T16:36:16.243

3

J, 17 bytes

-10 bytes thanks to cole

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

Try it online!

This uses multiplication of equal sized lists to avoid the zip/multiply combo of the original solution, as well as the "base 1 trick" 1#. to add the products together. The high level approach is similar to the original explanation.

original, 27 bytes

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

Try it online!

explained

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

Jonah

Posted 2017-11-15T15:19:41.803

Reputation: 8 729

0=10|1#.(8$3 1)*] should work for 17 bytes (does the same algorithm, too). I'm pretty sure that in the beta you can have a hook ended on the right side with a noun, so 0=10|1#.]*8$3 1 may work for 15 (I'd check on tio but it seems to be down?) – cole – 2017-11-16T08:06:51.260

@cole, I love this improvement. I've learned about and forgotten the 1#. trick like 2 or 3 times... thanks for reminding me. Oh btw the 15 byte version did not work in TIO. – Jonah – 2017-11-16T14:06:01.353

3

C (gcc), 84 82 72 61 54 bytes

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

-21 bytes from Neil

-7 bytes from Nahuel Fouilleul

Try it online!

Developed independently of Steadybox's answer

'f' is a function that takes the barcode as an int, and returns 1 for True and 0 for False.

  • f stores the last digit of x in s (s=x%10),

  • Then calculates the sum in c (for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)

    • c is the sum, i is a counter

    • for each digit including the first, add 1+2*i%4 times the digit (x%10) to the checksum and increment i (the i++ in 3-2*i++%4)

      • 1+2*i%4 is 1 when i is even and 0 when i is odd
  • Then returns whether the sum is a multiple of ten, and since we added the last digit (multiplied by 1), the sum will be a multiple of ten iff the barcode is valid. (uses GCC-dependent undefined behavior to omit return).

pizzapants184

Posted 2017-11-15T15:19:41.803

Reputation: 3 174

I think (x%10) can just be x as you're taking c%10 later anyway. Also I think you can use i<8 and then just test whether c%10 is zero at the end. – Neil – 2017-11-15T16:30:43.010

@Neil Thanks! That got -10 bytes. – pizzapants184 – 2017-11-15T16:49:03.720

In fact I think s is unnecessary: c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;} – Neil – 2017-11-15T16:59:57.453

the tio link is 61 bytes but in the answer it's 72, also don't know why x=c%10<1 or c=c%10<1 instead of return c%10<1 still works – Nahuel Fouilleul – 2017-11-16T13:03:37.627

also i<8 can be replaced by x – Nahuel Fouilleul – 2017-11-16T13:07:27.193

3

APL (Dyalog), 14 bytes

Equivalent with streetster's solution.

Full program body. Prompts for list of numbers from STDIN.

0=10|+/⎕×8⍴3 1

Try it online!

Is…

0= zero equal to

10| the mod-10 of

+/ the sum of

⎕× the input times

8⍴3 1 eight elements cyclically taken from [3,1]

?

Adám

Posted 2017-11-15T15:19:41.803

Reputation: 37 779

1You mean APL can't do it in one character from something like Ancient Sumerian or Linear B? – Mark – 2017-11-17T00:20:52.607

train: 0=10|-/+2×+/ – ngn – 2017-11-18T18:44:14.750

3

05AB1E, 9 bytes

3X‚7∍*OTÖ

Try it online!

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

kalsowerus

Posted 2017-11-15T15:19:41.803

Reputation: 1 894

Nice! First thing I thought was "extend to length" when I saw this, haven't used that one yet. – Magic Octopus Urn – 2017-11-17T22:17:07.650

31×S*OTÖ for 8 bytes. × just pushes 31 n number of times. When you multiply, it automatically drops the extra 31's. – Magic Octopus Urn – 2017-11-17T22:21:39.807

@MagicOctopusUrn That seems to fail on the 6th testcase 69165430 -> 1 – kalsowerus – 2017-11-17T23:25:42.310

3

C, 63 bytes

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

Assumes that 0 is true and any other value is false.

+3 bytes for better return value

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

Add ==0 to the return statement.

Ungolfed

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
}

This uses the alternative definition of EAN checksums where the check digit is chosen such that the checksum of the entire barcode including the check digit is a multiple of 10. Mathematically this works out the same but it's a lot simpler to write.

Initialising variables inside loop as suggested by Steadybox, 63 bytes

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

Removing curly brackets as suggested by Steadybox, 61 bytes

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

Using <1 rather than ==0 for better return value as suggested by Kevin Cruijssen

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

Add <1 to the return statement, this adds only 2 bytes rather than adding ==0 which adds 3 bytes.

Micheal Johnson

Posted 2017-11-15T15:19:41.803

Reputation: 131

You can save two bytes by removing the {} after the for. Also, function submissions have to be reusable, so you need to initialize s inside the function (just change i;s=0; to i,s; and i=0; to i=s=0;).

– Steadybox – 2017-11-16T20:44:41.573

@Steadybox How can I remove the curly brackets? – Micheal Johnson – 2017-11-16T21:01:59.680

There's only one statement inside them. When there are no curly brackets after for, the loop body will be the next statement. for(i=0;i<8;i++){s+=v[i]*3+v[++i];} is the same as for(i=0;i<8;i++)s+=v[i]*3+v[++i];. – Steadybox – 2017-11-16T22:32:43.977

@Steadybox Oh of course. That's one of the quirks of C syntax that I usually forget about, because when writing normal code I always include the curly brackets even if they're unnecessary, because it makes the code more readable. – Micheal Johnson – 2017-11-16T22:51:10.923

In your true/false answer, instead of +3 by adding ==0 it can be +2 by using <1 instead. :) – Kevin Cruijssen – 2017-11-17T09:05:10.973

@KevinCruijssen Good catch! – Micheal Johnson – 2017-11-17T12:48:12.730

2

JavaScript (Node.js), 47 bytes

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

Although there is a much shorter answer already, this is my first attempt of golfing in JavaScript so I'd like to hear golfing recommendations :-)

Testing

let f=

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

console.log(f([2,0,3,7,8,2,4,0]));
console.log(f([3,3,7,6,5,1,2,9]));
console.log(f([7,7,2,3,4,5,7,5]));
console.log(f([0,0,0,0,0,0,0,0]));

console.log(f([2,1,0,3,4,9,8,4]));
console.log(f([6,9,1,6,5,4,3,0]));
console.log(f([1,1,9,6,5,4,2,1]));
console.log(f([1,2,3,4,5,6,7,8]));

Alternatively, you can Try it online!

Mr. Xcoder

Posted 2017-11-15T15:19:41.803

Reputation: 39 774

2

Perl 5, 37 32 + 1 (-p) bytes

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

-5 bytes thanks to Dom Hastings. 37 +1 bytes was

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

try it online

Nahuel Fouilleul

Posted 2017-11-15T15:19:41.803

Reputation: 5 582

1

Had a little play with this and thought I'd share a useful trick: --$| toggles between 1 and 0 so you can use that instead of ++$i%2 for an alternating boolean! Also, all that matters is that the total ($s) matches /0$/, managed to get 33 bytes combining those changes with s///: Try it online! (-l is just for visibility)

– Dom Hastings – 2017-11-16T12:01:49.977

yes i though to s/./(something with $&)/ge and to /0$/ match but not the two combined. – Nahuel Fouilleul – 2017-11-16T12:36:25.233

2

Brainfuck, 228 Bytes

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

Can probably be improved a fair bit. Input is taken 1 digit at a time, outputs 1 for true, 0 for false.

How it works:

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

Put 8 at position 3.

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

Takes input 8 times, changing it from the ascii value to the actual value +2 each time. Inputs are spaced out by ones, which will be removed, to allow for easier multiplication later.

>[->]

Subtract one from each item. Our tape now looks something like

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

With each value 1 more than it should be. This is because zeros will mess up our multiplication process.

Now we're ready to start multiplying.

<<<<

Go to the second to last item.

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

While zero, multiply the item it's at by three, then move two items to the left. Now we've multiplied everything we needed to by three, and we're at the very first position on the tape.

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

Sum the entire list.

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

The value we have is 16 more than the actual value. Fix this by subtracting 16.

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

We need to test whether the sum is a multiple of 10. The maximum sum is with all 9s, which is 144. Since no sum will be greater than 10*15, put 15 and 10 on the tape, in that order and right to the right of the sum.

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

Move to where 15 is. While it's non-zero, test if the sum is non-zero. If it is, subtract 10 from it. Now we're either on the (empty) sum position, or on the (also empty) ten position. Move one right. If we were on the sum position, we're now on the non-zero 15 position. If so, move right twice. Now we're in the same position in both cases. Add ten to the ten position, and subtract one from the 15 position.

The rest is for output:

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

Move to the sum position. If it is non-zero (negative), the barcode is invalid; set the position to -1. Now add 49 to get the correct ascii value: 1 if it's valid, 0 if it's invalid.

Bolce Bussiere

Posted 2017-11-15T15:19:41.803

Reputation: 970

2

Java 8, 53 bytes

Golfed:

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

Direct calculation in the lambda appears to the shortest solution. It fits in a single expression, minimizing the lambda overhead and removing extraneous variable declarations and semicolons.

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

Output:

[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

user18932

Posted 2017-11-15T15:19:41.803

Reputation:

2

C# (.NET Core), 65 62 bytes

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

Try it online!

Acknowledgements

-3 bytes thanks to @KevinCruijssen and the neat trick using the exclusive-or operator.

DeGolfed

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 bytes

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

Try it online!

A direct port of @Snowman's answer.

Ayb4btu

Posted 2017-11-15T15:19:41.803

Reputation: 541

For your first answer: b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;} (62 bytes), or alternatively with a foreach, also 62 bytes: b=>{int s=0,t=1;foreach(int i in b)s+=i*(t^=2);return s%10<1;} (which is a port of my Java 8 answer).

– Kevin Cruijssen – 2017-11-17T08:58:21.930

2

QBasic, 54 52 bytes

Ugh, the boring answer turned out to be the shortest:

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

This inputs the digits comma-separated. My original 54-byte solution, which inputs one digit at a time, uses a "nicer" approach:

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

DLosc

Posted 2017-11-15T15:19:41.803

Reputation: 21 213

1

Ruby, 41 Bytes

Takes an array of integers. -6 bytes thanks to Jordan.

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

displayname

Posted 2017-11-15T15:19:41.803

Reputation: 151

Nice! FWIW you don’t need map here at all: zip takes a block. You can save a couple more bytes by using $. instead of initializing s: ->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1} – Jordan – 2017-11-16T06:44:49.303

1

K (oK), 16 15 bytes

Solution:

{~10!+/x*8#3 1}

Try it online!

Examples:

{~10!+/x*8#3 1}2 1 0 3 4 9 8 5
1
{~10!+/x*8#3 1}2 1 0 3 4 9 8 4
0
{~10!+/x*8#3 1}2 0 3 7 8 2 4 0
1

Explanation:

K is interpreted right-to-left:

{~10!+/x*8#3 1} / the solution
{             } / lambda with x as implicit input
           3 1  / the list [3,1]
         8#     / 8 take this list = [3,1,3,1,3,1,3,1]
       x*       / multiply input by this
     +/         / sum over the list
  10!           / 10 mod this sum
 ~              / not, 0 => 1, anything else => 0

streetster

Posted 2017-11-15T15:19:41.803

Reputation: 3 635

1

MATLAB/Octave, 32 bytes

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

Try it online!

I'm going to post this despite the other Octave answer as I developed this code and approach without looking at the other answers.

Here we have an anonymous function which takes the input as an array of 8 values, and return true if a valid barcode, false otherwise..

The result is calculated as follows.

              2*x(1:2:7)
             [          ,x]
         sum(              )
     mod(                   ,10)
@(x)~
  1. Odd digits (one indexed) are multiplied by 2.
  2. The result is prepended to the input array, giving an array whose sum will contain the odd digits three times, and the even digits once.
  3. We do the sum which will also include the supplied checksum within our sum.
  4. Next the modulo 10 is performed. If the checksum supplied was valid, the sum of all multiplied digits including the checksum value would end up being a multiple of 10. Therefore only a valid barcode would return 0.
  5. The result is inverted to get a logical output of true if valid.

Tom Carpenter

Posted 2017-11-15T15:19:41.803

Reputation: 3 990

1

Japt, 12 11 bytes

Takes input as an array of digits, outputs 1 or 0.

xÈ*31sgYÃvA

Try it

Shaggy

Posted 2017-11-15T15:19:41.803

Reputation: 24 623

1

Excel, 37 bytes

Interpreting "A list of 8 integers" as allowing 8 separate cells in Excel:

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

Wernisch

Posted 2017-11-15T15:19:41.803

Reputation: 2 534

=MOD(SUM((A1:H1)+2*(A1+C1+E1+G1)),10)=0 this formula exist in Excel? – RosLuP – 2017-11-23T21:40:33.383

@RosLuP, not predefined, no. But Modulo, Sum, + etc do ;-) – Wernisch – 2017-11-24T10:15:01.440

I want only to say that seems that in APL goes well doing first y= (A1:H1)+2*(A1+C1+E1+G1), and after the sum and the mod; in APL not goes well first sum(A1:H1) etc something as (1,2,3)+4=(5,6,7) and than sum(5,6,7)=18; note that sum(1,2,3)=6 and 6+4=10 different from 18. But possible I make error in something – RosLuP – 2017-11-24T16:37:02.213

@RosLuP, Apologies, missed the changed ()s in your comment. – Wernisch – 2017-11-24T16:43:49.117

Problem is how Excel interprets =(A1:H1): This is not handled as an array. Is invalid if placed in any column not in A-H range. If placed in a column in A-H, returns the value for that column only. (Formula in % results in %: C2 --> C1 H999 --> H1 K1 --> #VALUE!) – Wernisch – 2017-11-24T16:59:04.313

1

TI-Basic (83 series), 18 bytes

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

Takes input as a list in Ans. Returns 1 for valid barcodes and 0 for invalid ones.

A port of my Mathematica answer. Includes screenshot, in lieu of an online testing environment:

barcode screenshot

Notable feature: binomcdf(7,0 is used to generate the list {1,1,1,1,1,1,1,1} (the list of probabilities that from 7 trials with success probability 0, there will be at most N successes, for N=0,1,...,7). Then, cumSum( turns this into {1,2,3,4,5,6,7,8}.

This is one byte shorter than using the seq( command, though historically the point was that it's also significantly faster.

Misha Lavrov

Posted 2017-11-15T15:19:41.803

Reputation: 4 846

1

><>, 89 84 Bytes

8>i$1\
/\?:-/
\8+  \
/1-:?v~r3*+\
\ } \$>3*+v<
/++-/f}   l
\+3ff/\?-4/
/a+++/
\%0=n;

Can probably certainly be improved (this is my second ><> program)

How it works:

8>i$1\
 \?:-/

Gets user input, 8 times. Note that since i pushes -1 if the input stack is empty, this may not always return false for inputs shorter than 8 digits.

/
\8+  \
/1-:?v
\ } \$
/++-/f
\+3ff/

Converts the ascii values to their actual values.

      ~r3*+\
      >3*+v<
      }   l
      \?-4/

Remove the counter, and reverse the stack. Then, while the stack is longer than 4, multiply the top value by three, add it to the digit below it, and move the result to the bottom of the stack.

     /
/a+++/
\%0=n;

Sum the values on the stack. If the answer is divisible by 10, the code is valid. If so, print 1, otherwise, 0.

Bolce Bussiere

Posted 2017-11-15T15:19:41.803

Reputation: 970

1

Nice work! Here are a couple of suggestions to help get the bytes down. You can use the fish's wrapping behaviour to cut down on direction commands — it's often possible to fit a loop on a single line, with clever use of / and ?. The register (accessed with &) is a good place to store a counting variable, like you use to count how many times to go through a loop. Here's what your code might look like after applying these ideas (and a couple of others): Try it online!

– Not a tree – 2017-11-28T23:37:38.513

1

Julia 29 bytes

~x=[3,1,3,1,3,1,3,1]⋅x%10<1

golfing away that long literal array would be nice.

⋅ is a 3 byte character. But it is shorter than calling dot(...,x). and shorter that anything that handles everything as arrays and then grabs the only element.

Lyndon White

Posted 2017-11-15T15:19:41.803

Reputation: 1 021

1!x=~2(1:8)%4⋅x%10==0 saves a few bytes. Try it online! – Dennis – 2017-11-18T17:32:19.653

1

Acc!!, 60 45 bytes

3*N+N+3*N+N+3*N+N+3*N+N-8
Write 1/(1+_%10)+48

Try it online!

Explanation

We read eight digits, multiplying the appropriate ones by 3, and add. It's not quite that simple, because what we're actually reading is ASCII codes, and so each digit has 48 added to it. Thus, the resulting sum is too big by 3*48*4 + 48*4 = 768. We only care about the 1's digit, so subtracting 8 is sufficient to get the correct result.

We want to print 1 if the accumulator mod 10 is 0, and 0 otherwise. Acc!! doesn't have comparison operators, so we have to use integer division:

_%10        0  1  9
1+_%10      1  2  10
1/(1+_%10)  1  0  0

Then we add 48 to get an ASCII value and Write it.


Original 60-byte solution with a loop:

Count i while 8-i {
_+(N-48)*(3-i%2*2)
}
Write 1/(1+_%10)+48

DLosc

Posted 2017-11-15T15:19:41.803

Reputation: 21 213

1

C 98, 118 bytes

Ive edited this now to instead of echoing F or T it will return 0 or 1 to the pipe.

int i,j,k;int main(int,char**v){for(;i<7;(j+=(v[1][i]-48)*(i++%2?1:3)));for(;(k+=10)<j;);return v[1][7]-48==(k-j)%10;}

usage:

./a.out XXXXXXXX

where XXXXXXXX is a zero padded string, it will return either a 0 or a 1 as an exit code

this is 118 chars long in total. and the the compiled program is

   text    data     bss     dec     hex filename
   1307     544      16    1867     74b a.out

Peter Li

Posted 2017-11-15T15:19:41.803

Reputation: 11

Welcome to the site! I don't think that C requires newlines after semi-colons, so I think you can shave off a newline while retaining your functionality. – Post Rock Garf Hunter – 2017-11-20T07:02:27.920

Oh yeah for sure could've totally done that and bring it down to a 154 char solution. Though I don't think I could ever hit some of those 9 byte solutions with c. – Peter Li – 2017-11-20T07:34:56.280

It's best not to try to compare cross languages, the languages with the small solutions are designed to get short answers in the first place. (I've been here a while and I've never had the shortest answer yet) C answers can be impressive in their own right. I don't golf in C but I do know C a little bit and this seems like a pretty good answer to me. It's all about how cleverly you use the tools. – Post Rock Garf Hunter – 2017-11-20T07:40:02.487

1

Husk, 10 bytes

¬→dB3mΣTC2

Try it online!

Husk, 10 bytes

¦10B3mΣTC2

Try it online!

Mr. Xcoder

Posted 2017-11-15T15:19:41.803

Reputation: 39 774

0

Batch, 88 bytes

@set/as=0,n=%1
@for %%i in (1 2 3 4)do @set/as+=n+n/10*3,n/=100
@if %s:~-1%==0 echo 1

N.B. Leading zeros are not acceptable as they will cause the input to be treated as octal. As the numbers are always 8 digits the loop size can be hardcoded which saves 2 bytes.

Neil

Posted 2017-11-15T15:19:41.803

Reputation: 95 035

0

Java (OpenJDK 8), 104 99 bytes

s->{int y=0,i=0;for(;i<7;y+=(3-i%2*2)*(s.charAt(i++)-48));return 58-(y%10<1?10:y%10)==s.charAt(7);}

Try it online!

Roberto Graham

Posted 2017-11-15T15:19:41.803

Reputation: 1 305

Suggest return(y%10<1?10:y%10)+s.charAt(7)==58; instead of return 58-(y%10<1?10:y%10)==s.charAt(7); – ceilingcat – 2019-11-13T08:12:15.067

0

Pyke, 14 13 12 9 bytes

2%2*+sT%!

Try it here!

2%        -      input[::2]
  2*      -     ^ * 2
    +     -    input + ^
     s    -   sum(^)
      T%  -  ^ % 10
        ! - not ^

Thanks Mr. Xcoder for saving 3 bytes!

Blue

Posted 2017-11-15T15:19:41.803

Reputation: 26 661

10 bytes: 2%2*+s10%! – Mr. Xcoder – 2017-11-15T19:53:31.290

0

Octave, 40 bytes

@(a)9-mod(a*("31313130"'-48)-1,10)==a(8)

Accepts an array of integers as input and returns true/false.

Try it online!

rahnema1

Posted 2017-11-15T15:19:41.803

Reputation: 5 435

0

QBIC, 23 bytes

[4|_!_!p=p+b*3+c]?p%z=0

Explanation

[4|          DO four times
_!           Ask the user for a digit, save as 'b' ('a' is taken by [4| )
_!           Ask the user for a digit, save as 'c'
p=p          Add to running total p 
+b*3         the first digit times 3
+c           and the second digit
]            NEXT
?p%z=0       PRINT -1 if the seven digits + checksum MOD 10 == 0

steenbergh

Posted 2017-11-15T15:19:41.803

Reputation: 7 772

0

Perl 5, 54 + 1 (-F) = 55bytes

$r=pop@F;map$s+=$_*(($.+=2)%4),@F;say$r==(10-$s%10)%10

Try it online!

Xcali

Posted 2017-11-15T15:19:41.803

Reputation: 7 671

0

PHP, 82 bytes

<?for(;$i<strlen($p=$argv[1])-1;)$t+=($i%2?1:3)*$p[$i++];echo(10-$t%10)%10==$p[7];

Try it online!

Input as a string; prints 1 for valid, nothing for invalid.

Jo.

Posted 2017-11-15T15:19:41.803

Reputation: 974

0

Clojure, 41 bytes

#(=(mod(apply +(map *(cycle[3 1])%))10)0)

NikoNyrh

Posted 2017-11-15T15:19:41.803

Reputation: 2 361

0

GolfScript - 54 52 bytes

1/[{~}/][):a;[3 1]3*[3]+]zip 0\{{*}*+}/10%10\- 10%a=
  • Input: 33765129
  • Output: 1

If the input is an array the code can be modified to:

~[):a;[3 1]3*[3]+]zip 0\{{*}*+}/10%10\- 10%a=     # 45 bytes
  • Input: [3 3 7 6 5 1 2 9]
  • Output: 1

Explanation

1/[{~}/]     # Parse input
[):a;        # Gets last digit
[3 1]3*[3]+  # Generates the vector [3 1 3 1 3 1 3]
]zip         # Transposes the vector [[input] [3 1s]]
0\{{*}*+}/   # Vector dot product
10%10\- 10%  # (10-ans mod10)mod10
a=           # Compare

FedeWar

Posted 2017-11-15T15:19:41.803

Reputation: 271

0

C (gcc), 54 by pizzapants184 51 bytes

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

Try it online!

This answer heavily builds upon the answer of pizzapants184, but improves the bytecount by 3. i would have commented, but rep is below 50. The 3 bytes are removed, by replacing i=0 (...) (1+2*i++%4) with i=3 (...) (i^=2).

PlatinTato

Posted 2017-11-15T15:19:41.803

Reputation: 89

0

R, 45 bytes 42 bytes

x=scan();(140-sum(x[-8]*c(3,1)))%%10==x[8]

Try it online!

Explanation:

140-         #the largest value possible is 135 (all 9's)
sum( 
  x[-8]      #drop last value from input vector
     *c(3,1) #multiply by a automatically replicating vector of 3,1
)
  %%10       #modulo 10
== x[8]      #compare to the checksum

Mark

Posted 2017-11-15T15:19:41.803

Reputation: 411

0

GolfScript, 16 bytes

0\~{\3*++}4*10%!

Try it online!

Example Input

2 0 3 7 8 2 4 0

Output:

1

How it Works

Takes a string of 8 digits separated by spaces. For convenience I have included a header which automatically adds spaces to the input.

0\                          - Add zero to stack and place under input
  ~                         - Dump digits in input string onto stack
   {     }4*                - Loop 4 times.
    \                       - Swap top two indices of stack
     3*                     - Multiply by three
       ++                   - Add twice
            10%             - Modulo 10
               !            - Logical(?) not

Marcos

Posted 2017-11-15T15:19:41.803

Reputation: 171

0

PHP, 50 bytes

while($c++<8)$s+=$argv[$c]*($c&1?3:1);echo$s%10<1;

Run with -nr, provide digits as separate command line arguments or try it online.

Titus

Posted 2017-11-15T15:19:41.803

Reputation: 13 814

0

Z80 Assembly, 22 bytes

; INPUT:
;   HL = a memory location storing barcode as a sequence of integers
; OUTPUT:
;   flag Z signals that barcode is valid, NZ signals invalid barcode

CheckBarcode:
        xor a : ld bc,7*256+%10101010       ; B is the number of loop iterations
                                            ; bits of C say when factor 3 is to be used
AddLoop:
        sub (hl) : rl c : jr nc,Times1      ; negative checksum computation
Times3: sub (hl) : sub (hl)
Times1: inc hl : djnz AddLoop

        jr z,Check                          ; the ugly line to deal with 00000000

Rem:    add 10 : jr nc,Rem                  ; add 10s until the answer is non-negative...

Check:  cp (hl) : ret                       ; ...and compare it with 8th digit!

This task fits into 8-bit assembly quite well.

introspec

Posted 2017-11-15T15:19:41.803

Reputation: 121

0

APL (Dyalog Unicode), 36 bytes

f←{0=10∣+/⍵+2×+/⍵×8⍴0 1}

Try it online!

I just copy and modify (because that formula it seems wrong) the above Excel solution....

RosLuP

Posted 2017-11-15T15:19:41.803

Reputation: 3 036

0

Tcl, 89 bytes

proc C L {lmap c $L {incr t [expr [incr i]%8?$i%2?3*$c:$c:0]}
expr [lindex $L 7]==-$t%10}

Try it online!

sergiol

Posted 2017-11-15T15:19:41.803

Reputation: 3 055

0

Tcl, 93 bytes

proc C s {expr ([regsub -all (.)(.) [string repl $s 7 7 0] {-3*\1-\2}])%10==[string in $s 7]}

Try it online!

Will golf it more later!

sergiol

Posted 2017-11-15T15:19:41.803

Reputation: 3 055

0

Jelly, 17 bytes

Ṗµ3,1ṁ×⁸S⁵a%⁵⁼³Ṫ¤

Try it online!

Explanation:

Ṗµ                 take off the last element
  3,1ṁ             repeat [3, 1] to the same length as the input without the last element
      ×⁸           multiply together
        S          sum
         ⁵a        abs(10 - sum)
           %⁵      mod 10
              ³Ṫ¤  the last element of the original input
             ⁼     are they equal?

ellie

Posted 2017-11-15T15:19:41.803

Reputation: 131

0

Perl 6, 23 bytes

{:1[$_ «*»(3,1)]%%10}

Try it online!

Takes a list of digits.

nwellnhof

Posted 2017-11-15T15:19:41.803

Reputation: 10 037

0

Ruby, 37 bytes

->n{(n+n.scan(/.(.)/)*''*2).sum%10<1}

Try it online!

G B

Posted 2017-11-15T15:19:41.803

Reputation: 11 099