Un code à barres EAN-8 comprend 7 chiffres d'informations et un 8ème chiffre de somme de contrôle.
La somme de contrôle est calculée en multipliant les chiffres par 3 et 1 alternativement, en additionnant les résultats et en soustrayant du multiple de 10 suivant.
Par exemple, étant donné les chiffres 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 somme de ces chiffres résultants est 55 , le chiffre de la somme de contrôle est donc 60 - 55 = 5
Le défi
Votre tâche consiste à vérifier, à l'aide d'un code à barres de 8 chiffres, si celui-ci est valide - à renvoyer une valeur de vérité si la somme de contrôle est valide.
- Vous pouvez prendre des contributions sous l’une des formes suivantes:
- Une chaîne de 8 caractères représentant les chiffres du code à barres
- Une liste de 8 entiers, les chiffres du code à barres
- Un entier non négatif (vous pouvez soit supposer des zéros en tête où aucun n'est donné, c'est-à-dire
1
=00000001
, soit demander une entrée avec les zéros donnés)
- Les fonctions intégrées qui calculent la somme de contrôle EAN-8 (c.-à-d., Prennent les 7 premiers chiffres et calculent le dernier) sont interdites.
- C'est du code-golf , donc le programme le plus court (en octets) gagne!
Cas de test
20378240 -> True
33765129 -> True
77234575 -> True
00000000 -> True
21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False
Réponses:
Gelée , 7 octets
Essayez-le en ligne!
Comment ça marche
la source
JavaScript (ES6),
414038 octets2 octets sauvés grâce à @ETHProductions et 1 octet grâce à @Craig Ayre.
Prend la saisie sous forme de liste de chiffres.
Détermine la somme de tous les chiffres, y compris la somme de contrôle.
Si la somme est un multiple de 10, il s'agit d'un code à barres valide.
Cas de test
Afficher l'extrait de code
la source
g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1
, mais vous avez peut-être trouvé un meilleur moyen ...map
, ce qui, à mon avis, fonctionne mieux, car l'entrée peut être une liste de chiffres au lieu d'une chaîne.s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1
?&&
par|
pour sortir 1/0 puisque la vérité / la fausseté est permise?Python 2 ,
64483529 octetsmypetlion a enregistré 19 octets
Essayez-le en ligne!
la source
lambda x:sum(x[::2]*3+x[1::2])%10<1
Pour 35 octets.lambda x:sum(x[::2]*2+x)%10<1
Pour 29 octets.Gelée , 8 octets
Essayez la suite de tests.
Gelée , 9 octets
Essayez-le en ligne ou essayez la suite de tests.
Comment ça marche
Le résultat pour les 7 premiers chiffres du code à barres et le chiffre de la somme de contrôle doivent s’ajouter à un multiple de 10 pour que le code soit valide. Ainsi, la somme de contrôle est valide si l’algorithme appliqué à toute la liste est divisible par 10 .
la source
JḂḤ‘×µS⁵ḍ
JḂaḤ+µS⁵ḍ
Pm2Ḥ+µS⁵ḍ
est de 15 octets en UTF-8, sauf si je l’ai mal calculé.MATL , 10 octets
Merci à @Zgarb pour avoir signalé une erreur, maintenant corrigée.
Essayez-le en ligne! Ou vérifiez tous les cas de test .
Explication
la source
Befunge-98 (PyFunge) ,
16 à14 octetsSauvegardé 2 octets en sautant la deuxième partie en utilisant
j
au lieu de;
s, ainsi qu'en échangeant a~
et+
dans la première partie pour se débarrasser de a+
dans la seconde.La saisie est en 8 chiffres (avec le 0 en début si applicable) et rien d’autre.
Les sorties via le code de sortie (ouvrez la liste déroulante de débogage sur TIO), où 1 est vrai et 0 est faux.
Essayez-le en ligne!
Explication
Ce programme utilise une variété de trucs.
Tout d'abord, il prend les chiffres un par un à travers leurs valeurs ASCII. Normalement, cela nécessiterait de soustraire 48 à chaque valeur comme nous le lisons à partir de l'entrée. Cependant, si nous ne le modifions pas, il nous reste 16 (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1) copies supplémentaires de 48 dans notre somme, ce qui signifie que notre total va être 768 supérieur à ce qu'il "devrait" être. Comme nous ne sommes concernés que par la somme mod 10, nous pouvons simplement ajouter 2 à la somme plus tard. Ainsi, nous pouvons prendre en valeurs ASCII brutes, économisant environ 6 octets.
Deuxièmement, ce code vérifie uniquement si tous les autres caractères sont des caractères EOF, car il est garanti que la saisie ne comporte que 8 caractères.
Troisièmement, la#
fin de la ligne ne saute pas le premier caractère, mais saute le;
si venant de l’autre direction. C'est mieux que de mettre un#;
à l'avant à la place.Étant donné que la deuxième partie de notre programme n’est exécutée qu’une fois, nous n’avons pas besoin de le configurer pour qu’il saute la première moitié lorsqu’il fonctionne à l’arrière. Cela nous permet d'utiliser la commande jump pour sauter par-dessus la seconde moitié, avant de l'exécuter en arrière.
Pas à pas
Remarque: les caractères "impairs" et "pairs" sont basés sur un système indexé par 0. Le premier caractère est pair, avec l'index 0.
la source
C,
7877 octetsEssayez-le en ligne!
C (gcc), 72 octets
Essayez-le en ligne!
la source
Wolfram Language (Mathematica) ,
2621 octetsEssayez-le en ligne!
Prend la saisie sous forme de liste de 8 chiffres.
Comment ça marche
2-9^Range@8
est congru modulo 10 à2-(-1)^Range@8
, qui est{3,1,3,1,3,1,3,1}
. Nous prenons le produit scalaire de cette liste avec l'entrée et vérifions si le résultat est divisible par 10.Wolfram Language (Mathematica) , 33 octets et non en concurrence
Essayez-le en ligne!
Prend l'entrée sous forme de chaîne. Renvoie
1
les codes à barres valides et0
ceux non valides.Comment ça marche
La meilleure chose que je puisse trouver dans la manière d'un intégré (puisque Mathematica est tout à propos de ceux-ci).
Le bit intérieur
#~BarcodeImage~"EAN8";1
, génère une image du code à barres EAN8, puis l’ignore complètement et s’évalue à 1. Toutefois, si le code à barres est invalide,BarcodeImage
un avertissement est généré quiCheck
renvoie un 0 dans ce cas.la source
BarcodeImage
ce qui génère l'image du code à barres et valide le code à barres dans le processus. AlorsCheck[#~BarcodeImage~"EAN8";0,1]<1&
, ça marcherait (mais c'est plus long).Java 8,
585655 octets-2 octets indirectement grâce à @RickHitchcock , en utilisant
(m=4-m)*i
au lieu de l'm++%2*2*i+i
avoir vu dans sa réponse JavaScript .-1 octet indirectement grâce à @ETHProductions (et @RickHitchcock ), en utilisant à la
(m^=2)*i
place de(m=4-m)*i
.Explication:
Essayez ici.
la source
m=4-m
àm^=2
.^=1
assez souvent dans les réponses lorsque je veux changer entre0
et1
.^=2
travaille dans ce cas pour changer entre1
et3
. Belle astuce, et merci pour le commentaire de le mentionner. :)05AB1E , 14 octets
Essayez-le en ligne!
A besoin d’être en tête
0
, prend une liste de chiffres.la source
3100004
(devrait être la vérité).0
there.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?
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.
la source
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
la source
cycle
saves 2 bytes.Retina,
2322 bytes-1 byte thanks to Martin Ender!
Try it online!
Explanation
Example input:
20378240
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)...
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
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
.la source
.
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 either3
or1
(chosen by incrementing$i
modulo2
).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 the00000000
test case). We then check whether that's-eq
ual to the last digit. That Boolean result is left on the pipeline and output is implicit.la source
3100004
(should be truthy).Jelly, 16 bytes
Try it online!
takes input as a list of digits
la source
D
in 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 1
eight elements cyclically taken from[3,1]
?
la source
05AB1E, 9 bytes
Try it online!
la source
31×S*OTÖ
for 8 bytes.×
just pushes 31n
number of times. When you multiply, it automatically drops the extra 31's.69165430 -> 1
J, 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
la source
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 1
may 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 returns1
for True and0
for False.f
stores the last digit ofx
ins
(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 counterfor each digit including the first, add
1+2*i%4
times the digit (x%10
) to the checksum and incrementi
(thei++
in3-2*i++%4
)1+2*i%4
is 1 wheni
is even and 0 wheni
is 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
).la source
(x%10)
can just bex
as you're takingc%10
later anyway. Also I think you can usei<8
and then just test whetherc%10
is zero at the end.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;}
x=c%10<1
orc=c%10<1
instead ofreturn c%10<1
still worksi<8
can be replaced byx
C, 63 bytes
Assumes that
0
istrue
and any other value isfalse
.+3 bytes for better return value
Add
==0
to thereturn
statement.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
<1
rather than==0
for better return value as suggested by Kevin CruijssenAdd
<1
to thereturn
statement, this adds only 2 bytes rather than adding==0
which adds 3 bytes.la source
{}
after thefor
. Also, function submissions have to be reusable, so you need to initializes
inside 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];
.==0
it can be +2 by using<1
instead. :)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!
la source
Perl 5,
3732 + 1 (-p) bytes-5 bytes thanks to Dom Hastings. 37 +1 bytes was
try it online
la source
--$|
toggles between1
and0
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 withs///
: Try it online! (-l
is just for visibility)s/./(something with $&)/ge
and 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.
la source
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:
la source
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:
la source
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.
la source
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.
la source
Excel, 37 bytes
Interpreting "A list of 8 integers" as allowing 8 separate cells in Excel:
la source
()
s in your comment.=(A1:H1)
: This is not handled as an array. Is invalid if placed in any column not inA-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!)Ruby, 41 Bytes
Takes an array of integers. -6 bytes thanks to Jordan.
la source
map
here at all:zip
takes 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
. Returns1
for valid barcodes and0
for invalid ones.A port of my Mathematica answer. Includes screenshot, in lieu of an online testing environment:
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.la source