Чи дійсний мій штрих-код?


33

EAN-8 штрих - коду включає в себе 7 цифр інформації та 8 - ї контрольної цифрою.

Контрольна сума обчислюється шляхом множення цифр на 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-значний штрих-код, переконатися, чи він дійсний - повернути триєдне значення, якщо контрольна сума дійсна, і помилково вказати інше.

  • Ви можете взяти інформацію в будь-якій з наступних форм:
    • Рядок, довжиною 8 символів, що представляє цифри штрих-коду
    • Список 8 цілих чисел, цифри штрих-коду
    • Невід’ємне ціле число (ви можете припустити провідні нулі там, де їх не вказано, тобто 1= 00000001, або запитати введення з заданими нулями)
  • Вбудовані, які обчислюють контрольну суму EAN-8 (тобто беруть перші 7 цифр і обчислюють останню), заборонені.
  • Це , тому найкоротша програма (у байтах) виграє!

Випробування

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

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


1
Це питання не насправді про штрих-код (який є чорно-білою смугастою річчю), а про число, закодоване штрих-кодом. Номер може існувати без штрих-коду, а штрих-код може кодувати інші речі, крім EAN. Можливо, просто " Чи дійсний мій EAN-8 ", це кращий заголовок?
Paŭlo Ebermann

2
@ PaŭloEbermann має не одне і те саме дзвінок ...
FlipTack

7
Читаючи про штрих-коди, я очікую деякого читання зображення (або, принаймні, бітового рядка), не підтверджуючи контрольну суму.
Paŭlo Ebermann

Тісно пов'язані , оскільки ISBN-13 є EAN.
Олів'є Грегоар

Відповіді:


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 байт

Збережено 2 байти завдяки @ETHProductions та 1 байт завдяки @Craig Ayre.

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

Так, блискуче, дякую
Рік Хічкок

Чудове рішення! Чи не могли б ви замінити &&з |на виході 1/0 , оскільки truthy / falsy дозволено?
Крейг Ейр


8

Желе , 8 байт

m2Ḥ+µS⁵ḍ

Спробуйте набір тестів.

Желе , 9 байт

JḂḤ‘×µS⁵ḍ

Спробуйте в Інтернеті або Спробуйте тестовий набір.

Як це працює

m2Ḥ + µS⁵ḍ ~ Повна програма.

м2 ~ Модульна 2. Повертайте кожен другий елемент вводу.
  Ḥ ~ Подвійний кожен.
   + µ ~ Додайте вхід і заведіть новий монадичний ланцюг.
     S ~ Сума.
      ⁵ḍ ~ Ділиться на 10?
JḂḤ '× µS⁵ḍ ~ Повна програма (монадійна).

J ~ 1-індексований діапазон довжини.
 Ḃ ~ Біт; Модулюйте кожне число в діапазоні вище на 2.
  Ḥ ~ Подвійний кожен.
   '~ Збільшення кожного.
    × ~ Парне множення з введенням.
     µ ~ Запускає новий монадичний ланцюг.
      S ~ Сума.
       ⁵ḍ ~ Чи ділиться сума на 10?

Результат для перших 7 цифр штрих-коду та цифри контрольної суми повинен додати кратний 10, щоб він був дійсним. Таким чином, контрольна сума дійсна, якщо алгоритм, застосований до всього списку, ділиться на 10 .


Ще 9 байт, але з послідовними значеннями:JḂḤ‘×µS⁵ḍ
HyperNeutrino

@HyperNeutrino Спасибі, я знав, що для цього є атом!
Містер Xcoder

Також 9 байт: JḂaḤ+µS⁵ḍ P
HyperNeutrino

@HyperNeutrino Ну є багато альтернатив: P
Містер Xcoder

1
8 байт чи 8 символів? m2Ḥ+µS⁵ḍце 15 байт у UTF-8, якщо я не обчислив його неправильно.
ta.speot.is

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 байт

Збережено 2 байти, пропустивши другу частину за допомогою jзамість ;s, а також замінивши a ~і+ в першій частині, щоб позбутися а +в другій.

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

Введіть 8 цифр (з провідними 0, якщо це можливо) і нічого іншого.

Виводиться за допомогою коду виходу (відкрийте випадок налагодження на TIO), де 1 відповідає дійсності, а 0 - помилково.

Спробуйте в Інтернеті!

Пояснення

Ця програма використовує різноманітні трюки.

Перш за все, вона бере цифри по черзі через їх значення ASCII. Зазвичай для цього потрібно буде відняти 48 з кожного значення, коли ми читаємо його з вхідних даних. Однак, якщо ми не змінимо його, у нас залишиться 16 (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1) додаткових копій, що становить 48 в нашій сумі, тобто загальна сума буде на 768 більше, ніж що це "повинно бути". Оскільки нас стосується лише сума mod 10, ми можемо просто додати 2 до суми пізніше. Таким чином, ми можемо взяти необроблені значення ASCII, заощадивши 6 байт або близько того.

По-друге, цей код перевіряє, чи будь-який інший символ є EOF, оскільки вхід гарантовано має бути лише 8 символів.

По-третє, #кінець рядка не пропускає перший символ, а пропускає, ;якщо йде з іншого напрямку. Це краще, ніж #;замість цього поставити фронт.

Оскільки друга частина нашої програми запускається лише один раз, нам не потрібно налаштовувати її так, щоб вона пропускала першу половину при запуску назад. Це дозволяє нам скористатися командою стрибок для переходу через другу половину, коли ми виходимо, перш ніж виконувати її, рухаючись назад.

Крок за кроком

Примітка: символи "Непарний" та "Непарний" базуються на системі, що індексується 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

Мова Вольфрама (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.

Мова Вольфрама (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&би працювало (але це довше).
Міша Лавров

5

Java 8, 58 56 55 байт

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

-2 байти опосередковано завдяки @RickHitchcock , використовуючи (m=4-m)*iзамість m++%2*2*i+iтого, щоб побачити це у своїй відповіді на JavaScript .
-1 байт опосередковано завдяки @ETHProductions@ RickHitchcock ), використовуючи (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-mна m^=2.
Рік Хічкок

@ RickHitchcock Ну, звичайно .. Я ^=1досить часто використовую відповіді, коли хочу змінити між 0і 1. ^=2працює в цьому випадку для зміни між 1і 3. Хороший трюк, і дякую за коментар, щоб згадати його. :)
Кевін Круїссен

4

05AB1E , 14 байт

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

Спробуйте в Інтернеті!

Необхідно вести 0s, приймає список цифр.


Здається, що не вдається 3100004(має бути правдою).
Згарб

@Zgarb Ви 0там пропущені .
Ерік Аутгольфер

О, це займає рядок? Добре тоді, моє погано.
Згарб

@ Zgarb Добре, що ви можете пропустити цитати, але так, вам потрібні ведучі 0. Ця відповідь фактично використовує функції числення на рядках, одна з особливостей 05AB1E.
Ерік Атголфер

@ Mr.Xcoder Питання щодо цього не дуже зрозуміле, я додам ще один код, який вирішує для цього нижче.
Ерік Аутгольфер

4

Pyth , 8 байт

!es+*2%2

Перевірте всі тестові випадки!

Піт , 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 Зачекайте, чи ми повинні зробити 3*3+1*1+0*3+...чи 0*3+3*1+1*0..? Я думав, що ми повинні зробити колишнього
містера Xcoder

У новій специфікації додаються провідні цифри, щоб переконатися, що їх точно 8 (якщо я правильно розумію).
Згарб

@ Zgarb Добре, виправлено.
Містер Xcoder

4

Haskell , 40 38 байт

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

Спробуйте в Інтернеті!

Вводиться як список із 8 цілих чисел. Практичний приклад використання нескінченних списків.

Редагувати: Збережено 2 байти завдяки GolfWolf


2
Використання рекурсивного визначення замість cycle економії 2 байтів .
Крістіан Лупаску

4

Сітківка , 23 22 байт

-1 байт завдяки Мартіну Ендеру !

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

Спробуйте в Інтернеті!

Пояснення

Приклад введення: 20378240

(.).
$1$1$&

Замініть кожну пару цифр першою цифрою, повтореною двічі, а потім самою парою. Ми отримуємо2220333788824440

.
$*

Перетворіть кожну цифру в одинакову. З доданими дужками для ясності ми отримуємо(11)(11)(11)()(111)(111)...

M`

Порахуйте кількість збігів порожнього рядка, що на одну більшу кількість, ніж кількість рядків. (За останні два кроки ми в основному взяли суму кожної цифри +1) Результат: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.


2
I think you can drop the . on the match stage and match 1$ at the end.
Martin Ender

@MartinEnder very nice, I'll do that, thanks!
Leo

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.


Seems to fail on 3100004 (should be truthy).
Zgarb

@Zgarb Works for me? Try it online!
AdmBorkBork

Ah ok, I tested it without the quotes.
Zgarb

@Zgarb Ah, yeah. Without the quotes, PowerShell will implicitly cast as an integer, stripping the leading zero(s).
AdmBorkBork

3

Jelly, 16 bytes

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

Try it online!

takes input as a list of digits


Nitpick: your TIO timeouts. Also, 16 bytes.
Erik the Outgolfer

@EriktheOutgolfer Wait what how. It works when I put the D in the footer. And yay thanks! :D
HyperNeutrino

@EriktheOutgolfer Am I doing something wrong? Your 16-byter appears to be invalid?
HyperNeutrino

Maybe, it works kinda differently, but yours seems a bit invalid too...specifically I think the last line should be DµṪ=Ç.
Erik the Outgolfer

1
Seems to fail on 3100004 (should be truthy).
Zgarb

3

APL (Dyalog), 14 bytes

Equivalent with streetster's solution.

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

0=10|+/⎕×83 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]

?


1
You mean APL can't do it in one character from something like Ancient Sumerian or Linear B?
Mark

train: 0=10|-/+2×+/
ngn

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

Nice! First thing I thought was "extend to length" when I saw this, haven't used that one yet.
Magic Octopus Urn

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

@MagicOctopusUrn That seems to fail on the 6th testcase 69165430 -> 1
kalsowerus

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

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

@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

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


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

@Neil Thanks! That got -10 bytes.
pizzapants184

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

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

also i<8 can be replaced by x
Nahuel Fouilleul

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.


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

@Steadybox How can I remove the curly brackets?
Micheal Johnson

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

@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

In your true/false answer, instead of +3 by adding ==0 it can be +2 by using <1 instead. :)
Kevin Cruijssen

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

Alternatively, you can Try it online!


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


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

yes i though to s/./(something with $&)/ge and to /0$/ match but not the two combined.
Nahuel Fouilleul

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.


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

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

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.


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

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.

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

=MOD(SUM((A1:H1)+2*(A1+C1+E1+G1)),10)=0 this formula exist in Excel?
RosLuP

@RosLuP, not predefined, no. But Modulo, Sum, + etc do ;-)
Wernisch

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

@RosLuP, Apologies, missed the changed ()s in your comment.
Wernisch

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

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}

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

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.