Un código de barras EAN-8 incluye 7 dígitos de información y un octavo dígito de suma de verificación.
La suma de verificación se calcula multiplicando los dígitos por 3 y 1 alternativamente, sumando los resultados y restando del siguiente múltiplo de 10.
Por ejemplo, dados los dígitos 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
La suma de estos dígitos resultantes es 55 , por lo que el dígito de suma de comprobación es 60 - 55 = 5
El reto
Su tarea es, dado un código de barras de 8 dígitos, verificar si es válida, devolviendo un valor verdadero si la suma de verificación es válida y falsa de lo contrario.
- Puede tomar información en cualquiera de las siguientes formas:
- Una cadena, de 8 caracteres de longitud, que representa los dígitos del código de barras
- Una lista de 8 enteros, los dígitos del código de barras
- Un entero no negativo (puede suponer ceros iniciales donde no se proporciona ninguno, es decir ,
1=00000001o solicitar una entrada con los ceros dados)
- Las unidades integradas que calculan la suma de verificación EAN-8 (es decir, toman los primeros 7 dígitos y calculan el último) están prohibidas.
- Este es el código de golf , por lo que gana el programa más corto (en bytes).
Casos de prueba
20378240 -> True
33765129 -> True
77234575 -> True
00000000 -> True
21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False
code-golf
arithmetic
decision-problem
integer
checksum
FlipTack
fuente
fuente

Respuestas:
Jalea , 7 bytes
Pruébalo en línea!
Cómo funciona
fuente
JavaScript (ES6),
414038 bytesSaved 2 bytes thanks to @ETHProductions and 1 byte thanks to @Craig Ayre.
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
Show code snippet
fuente
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...map, which I think works better since input can be a list of digits instead of a string.s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1?&&with|to output 1/0 since truthy/falsy is allowed?Python 2,
64483529 bytesmypetlion saved 19 bytes
Try it online!
fuente
lambda x:sum(x[::2]*3+x[1::2])%10<1For 35 bytes.lambda x:sum(x[::2]*2+x)%10<1For 29 bytes.Jelly, 8 bytes
Try the test suite.
Jelly, 9 bytes
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.
fuente
JḂḤ‘×µS⁵ḍJḂaḤ+µS⁵ḍ:Pm2Ḥ+µS⁵ḍis 15 bytes in UTF-8, unless I've calculated it wrong.MATL, 10 bytes
Thanks to @Zgarb for pointing out a mistake, now corrected.
Try it online! Or verify all test cases.
Explanation
fuente
Befunge-98 (PyFunge),
1614 bytesSaved 2 bytes by skipping the second part using
jinstead of;s, as well as swapping a~and+in the first part to get rid of a+in the second.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.
fuente
C,
7877 bytesTry it online!
C (gcc), 72 bytes
Try it online!
fuente
Wolfram Language (Mathematica),
2621 bytesTry it online!
Takes input as a list of 8 digits.
How it works
2-9^Range@8is congruent modulo 10 to2-(-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
Try it online!
Takes input as a string. Returns
1for valid barcodes and0for 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, thenBarcodeImagegenerates a warning, whichCheckcatches, returning 0 in that case.fuente
BarcodeImage, which generates the image of the barcode, and validates the barcode in the process. SoCheck[#~BarcodeImage~"EAN8";0,1]<1&would work (but it's longer).Java 8,
585655 bytes-2 bytes indirectly thanks to @RickHitchcock, by using
(m=4-m)*iinstead ofm++%2*2*i+iafter seeing it in his JavaScript answer.-1 byte indirectly thanks to @ETHProductions (and @RickHitchcock), by using
(m^=2)*iinstead of(m=4-m)*i.Explanation:
Try it here.
fuente
m=4-mtom^=2.^=1pretty often in answers when I want to alter between0and1.^=2works in this case to alter between1and3. Nice trick, and thanks for the comment to mention it. :)05AB1E, 14 bytes
Try it online!
Needs leading
0s, takes list of digits.fuente
3100004(should be truthy).0there.0. This answer actually uses number functions on strings, one of the features of 05AB1E.Pyth, 8 bytes
Verify all the test cases!
Pyth, 13 bytes
If we can assume the input always has exactly 8 digits:
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.
fuente
3100004(should be truthy).3*3+1*1+0*3+...or0*3+3*1+1*0..? I thought we are supposed to do the formerHaskell,
4038 bytesTry it online!
Takes input as a list of 8 integers. A practical example of using infinite lists.
Edit: Saved 2 bytes thanks to GolfWolf
fuente
cyclesaves 2 bytes.Retina,
2322 bytes-1 byte thanks to Martin Ender!
Try it online!
Explanation
Example input:
20378240Replace each couple of digits with the first digit repeated twice followed by the couple itself. We get
2220333788824440Convert each digit to unary. With parentheses added for clarity, we get
(11)(11)(11)()(111)(111)...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:
60Match a
1at 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.fuente
.on the match stage and match1$at the end.PowerShell, 85 bytes
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 either3or1(chosen by incrementing$imodulo2).Those results are all gathered together and summed
-join'+'|iex. We take that result mod10, subtract that from10, and again take the result mod10(this second mod is necessary to account for the00000000test case). We then check whether that's-equal to the last digit. That Boolean result is left on the pipeline and output is implicit.fuente
3100004(should be truthy).Jelly, 16 bytes
Try it online!
takes input as a list of digits
fuente
Din the footer. And yay thanks! :DDµṪ=Ç.3100004(should be truthy).APL (Dyalog), 14 bytes
Equivalent with streetster's solution.
Full program body. Prompts for list of numbers from STDIN.
Try it online!
Is…
0=zero equal to10|the mod-10 of+/the sum of⎕×the input times8⍴3 1eight elements cyclically taken from[3,1]?
fuente
05AB1E, 9 bytes
Try it online!
fuente
31×S*OTÖfor 8 bytes.×just pushes 31nnumber of times. When you multiply, it automatically drops the extra 31's.69165430 -> 1J, 17 bytes
-10 bytes thanks to cole
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
Try it online!
explained
fuente
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, so0=10|1#.]*8$3 1may work for 15 (I'd check on tio but it seems to be down?)1#.trick like 2 or 3 times... thanks for reminding me. Oh btw the 15 byte version did not work in TIO.C (gcc),
8482726154 bytes-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 returns1for True and0for False.fstores the last digit ofxins(s=x%10),Then calculates the sum in
c(for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)cis the sum,iis a counterfor each digit including the first, add
1+2*i%4times the digit (x%10) to the checksum and incrementi(thei++in3-2*i++%4)1+2*i%4is 1 wheniis even and 0 wheniis oddThen 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).fuente
(x%10)can just bexas you're takingc%10later anyway. Also I think you can usei<8and then just test whetherc%10is zero at the end.sis unnecessary:c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;}x=c%10<1orc=c%10<1instead ofreturn c%10<1still worksi<8can be replaced byxC, 63 bytes
Assumes that
0istrueand any other value isfalse.+3 bytes for better return value
Add
==0to thereturnstatement.Ungolfed
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
Removing curly brackets as suggested by Steadybox, 61 bytes
Using
<1rather than==0for better return value as suggested by Kevin CruijssenAdd
<1to thereturnstatement, this adds only 2 bytes rather than adding==0which adds 3 bytes.fuente
{}after thefor. Also, function submissions have to be reusable, so you need to initializesinside the function (just changei;s=0;toi,s;andi=0;toi=s=0;).for, the loop body will be the next statement.for(i=0;i<8;i++){s+=v[i]*3+v[++i];}is the same asfor(i=0;i<8;i++)s+=v[i]*3+v[++i];.==0it can be +2 by using<1instead. :)JavaScript (Node.js), 47 bytes
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
Show code snippet
Alternatively, you can Try it online!
fuente
Perl 5,
3732 + 1 (-p) bytes-5 bytes thanks to Dom Hastings. 37 +1 bytes was
try it online
fuente
--$|toggles between1and0so you can use that instead of++$i%2for an alternating boolean! Also, all that matters is that the total ($s) matches/0$/, managed to get 33 bytes combining those changes withs///: Try it online! (-lis just for visibility)s/./(something with $&)/geand to/0$/match but not the two combined.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
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.
fuente
Java 8, 53 bytes
Golfed:
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.
Output:
fuente
QBasic,
5452 bytesUgh, the boring answer turned out to be the shortest:
This inputs the digits comma-separated. My original 54-byte solution, which inputs one digit at a time, uses a "nicer" approach:
fuente
C# (.NET Core),
6562 bytesTry it online!
Acknowledgements
-3 bytes thanks to @KevinCruijssen and the neat trick using the exclusive-or operator.
DeGolfed
C# (.NET Core), 53 bytes
Try it online!
A direct port of @Snowman's answer.
fuente
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).MATLAB/Octave, 32 bytes
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.
fuente
Excel, 37 bytes
Interpreting "A list of 8 integers" as allowing 8 separate cells in Excel:
fuente
()s in your comment.=(A1:H1): This is not handled as an array. Is invalid if placed in any column not inA-Hrange. 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!)Ruby, 41 Bytes
Takes an array of integers. -6 bytes thanks to Jordan.
fuente
maphere at all:ziptakes a block. You can save a couple more bytes by using$.instead of initializings:->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}TI-Basic (83 series), 18 bytes
Takes input as a list in
Ans. Returns1for valid barcodes and0for invalid ones.A port of my Mathematica answer. Includes screenshot, in lieu of an online testing environment:
Notable feature:
binomcdf(7,0is 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.fuente