Czy mój kod kreskowy jest prawidłowy?

33

EAN-8 kodów kreskowych zawiera 7 cyfr informacji i 8 cyfra kontrolna.

Suma kontrolna jest obliczana przez pomnożenie cyfr przez 3 i 1 na przemian, dodanie wyników i odjęcie od następnej wielokrotności 10.

Na przykład, biorąc pod uwagę cyfry 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

Suma tych wynikowych cyfr wynosi 55 , więc cyfra sumy kontrolnej wynosi 60–55 = 5


Wyzwanie

Twoim zadaniem jest, biorąc pod uwagę 8-cyfrowy kod kreskowy, sprawdzenie, czy jest poprawny - zwrócenie prawdziwej wartości, jeśli suma kontrolna jest ważna, i fałszowanie w przeciwnym razie.

  • Możesz przyjmować dane wejściowe w dowolnej z następujących form:
    • Łańcuch o długości 8 znaków reprezentujący cyfry kodu kreskowego
    • Lista 8 liczb całkowitych, cyfr kodu kreskowego
    • Nieujemna liczba całkowita (możesz albo założyć zera na początku, gdzie nie podano żadnego, tj. 1= 00000001, Albo zażądać wprowadzenia z podanymi zerami)
  • Wbudowane, które obliczają sumę kontrolną EAN-8 (tj. Pobierają pierwsze 7 cyfr i obliczają ostatnie) są zakazane.
  • To jest , więc wygrywa najkrótszy program (w bajtach)!

Przypadki testowe

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

21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False
FlipTack
źródło
Powiązany z algorytmem Luhna do weryfikacji numerów kart kredytowych , prawdopodobnie duplikatu.
xnor
1
To pytanie w rzeczywistości nie dotyczy kodu kreskowego (który jest czarno-białym paskiem), ale liczby zakodowanej kodem kreskowym. Liczba może istnieć bez kodu kreskowego, a kod kreskowy może kodować inne rzeczy niż EAN. Może po prostu „ Czy mój EAN-8 jest ważny ” to lepszy tytuł?
Paŭlo Ebermann
2
@ PaŭloEbermann nie ma tego samego pierścienia ...
FlipTack,
7
Czytając o kodach kreskowych, spodziewam się odczytu obrazu (lub przynajmniej ciągu bitów), nie weryfikującego sumy kontrolnej.
Paŭlo Ebermann
Silnie powiązane , ponieważ ISBN-13 to EAN.
Olivier Grégoire,

Odpowiedzi:

5

Galaretka , 7 bajtów

s2Sḅ3⁵ḍ

Wypróbuj online!

Jak to działa

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
źródło
13

JavaScript (ES6), 41 40 38 bajtów

Zaoszczędzono 2 bajty dzięki @ETHProductions i 1 bajt dzięki @Craig Ayre.

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

Pobiera dane wejściowe jako listę cyfr.

Określa sumę wszystkich cyfr, w tym sumę kontrolną.

Jeśli suma jest wielokrotnością 10, to jest to prawidłowy kod kreskowy.

Przypadki testowe

Rick Hitchcock
źródło
Miałem zamiar powiedzieć można zaoszczędzić 3 bajty przez przejście z pre-post-rekursji do rekursji z g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1, ale można znaleźć lepszego sposobu ...
ETHproductions
Dzięki, @ETHproductions, zmieniłem się na map, który moim zdaniem działa lepiej, ponieważ wejściem może być lista cyfr zamiast łańcucha.
Rick Hitchcock
Być może zapisać kolejny bajt s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1?
ETHprodukcje
Tak, genialne, dzięki
:)
Świetne rozwiązanie! Mogłyby zastąpić &&z |do wyjścia 1/0 od truthy / falsy jest dozwolone?
Craig Ayre
10

Python 2 , 64 48 35 29 bajtów

mypetlion zapisał 19 bajtów

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

Wypróbuj online!

Halvard Hummel
źródło
lambda x:sum(x[::2]*3+x[1::2])%10<1Dla 35 bajtów.
mypetlion
2
lambda x:sum(x[::2]*2+x)%10<1Dla 29 bajtów.
mypetlion
8

Galaretka , 8 bajtów

m2Ḥ+µS⁵ḍ

Wypróbuj zestaw testowy.

Galaretka , 9 bajtów

JḂḤ‘×µS⁵ḍ

Wypróbuj online lub Wypróbuj pakiet testowy.

Jak to działa

m2Ḥ + µS⁵ḍ ~ Pełny program.

m2 ~ Modułowy 2. Zwraca co drugi element wejścia.
  Ḥ ~ Podwoić każdy.
   + µ ~ Dołącz dane wejściowe i rozpocznij nowy łańcuch monadyczny.
     S ~ Sum.
      ⁵ḍ ~ Czy można podzielić przez 10?
JḂḤ '× µS⁵ḍ ~ Pełny program (monadyczny).

J ~ 1 indeksowany zakres długości.
 Ḃ ~ Bit; Modulo każdą liczbę w powyższym zakresie o 2.
  Ḥ ~ Podwoić każdy.
   '~ Zwiększ każdy.
    × ~ Mnożenie parami z wejściem.
     µ ~ Rozpoczyna nowy łańcuch monadyczny.
      S ~ Sum.
       ⁵ḍ ~ Czy suma jest podzielna przez 10?

Wynik dla pierwszych 7 cyfr kodu kreskowego i cyfry sumy kontrolnej musi być dodany do wielokrotności 10 , aby był ważny. Tak więc suma kontrolna jest ważna, jeśli algorytm zastosowany do całej listy można podzielić przez 10 .

Pan Xcoder
źródło
Wciąż 9 bajtów, ale ze spójnymi wartościami:JḂḤ‘×µS⁵ḍ
HyperNeutrino,
@HyperNeutrino Dzięki, wiedziałem, że jest do tego atom!
Pan Xcoder,
Również 9 bajtów:: JḂaḤ+µS⁵ḍP
HyperNeutrino,
@HyperNeutrino Cóż, istnieje wiele alternatyw: P
Mr. Xcoder
1
8 bajtów lub 8 znaków? m2Ḥ+µS⁵ḍma 15 bajtów w UTF-8, chyba że źle to obliczyłem.
ta.speot.is
7

MATL , 10 bajtów

Dzięki @Zgarb za wskazanie błędu, teraz poprawionego.

IlhY"s10\~

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

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
źródło
7

Befunge-98 (PyFunge) , 16 14 bajtów

Zaoszczędzono 2 bajty, pomijając drugą część za pomocą jzamiast ;s, a także zamieniając a ~iw +pierwszej części, aby pozbyć się +w drugiej.

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

Dane wejściowe składają się z 8 cyfr (w razie potrzeby z zerami) i nic więcej.

Dane wyjściowe za pośrednictwem kodu wyjścia (otwórz menu debugowania w TIO), gdzie 1 to prawda, a 0 to fałsz.

Wypróbuj online!

Wyjaśnienie

Ten program wykorzystuje różne sztuczki.

Po pierwsze, cyfry po kolei przechodzą przez ich wartości ASCII. Zwykle wymagałoby to odjęcia 48 od każdej wartości podczas odczytywania jej z danych wejściowych. Jeśli jednak go nie zmodyfikujemy, pozostanie nam 16 (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1) dodatkowych 48 kopii, co oznacza, że ​​nasza suma będzie o 768 większa niż co to powinno być. Ponieważ zajmujemy się tylko modem sumowania 10, możemy po prostu dodać 2 do sumy później. Możemy zatem przyjąć surowe wartości ASCII, oszczędzając około 6 bajtów.

Po drugie, ten kod sprawdza tylko, czy co drugi znak jest EOF, ponieważ gwarantowana długość danych wejściowych wynosi tylko 8 znaków.

Po trzecie, #koniec linii nie przeskakuje pierwszego znaku, ale przeskakuje, ;jeśli nadchodzi z innego kierunku. Jest to lepsze niż umieszczanie #;z przodu.

Ponieważ druga część naszego programu jest uruchamiana tylko raz, nie musimy go konfigurować, aby pomijała pierwszą połowę podczas uruchamiania wstecz. To pozwala nam użyć polecenia skoku, aby przeskoczyć drugą połowę, gdy wychodzimy przed wykonaniem jej cofania.

Krok po kroku

Uwaga: Znaki „nieparzyste” i „parzyste” oparte są na systemie 0-indeksowanym. Pierwszy znak jest parzysty, z indeksem 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
Łagodnie Milquetoast
źródło
6

C,  78  77 bajtów

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

Wypróbuj online!

C (gcc), 72 bajty

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

Wypróbuj online!

Steadybox
źródło
6

Wolfram Language (Mathematica) , 26 21 bajtów

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

Wypróbuj online!

Pobiera dane wejściowe jako listę 8 cyfr.

Jak to działa

2-9^Range@8jest przystający modulo 10 to 2-(-1)^Range@8, co jest {3,1,3,1,3,1,3,1}. Bierzemy iloczyn iloczynu z tej listy z danymi wejściowymi i sprawdzamy, czy wynik można podzielić przez 10.

Wolfram Language (Mathematica) , 33 bajty i niekonkurujące

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

Wypróbuj online!

Pobiera dane wejściowe jako ciąg. Zwraca 1prawidłowe i 0niepoprawne kody kreskowe .

Jak to działa

Najlepsza rzecz, jaką mogłem znaleźć na drodze do wbudowania (ponieważ Mathematica o to chodzi).

Bit wewnętrzny #~BarcodeImage~"EAN8";1, generuje obraz kodu kreskowego EAN8, a następnie całkowicie go ignoruje i ocenia na 1. Jednak jeśli kod kreskowy jest nieprawidłowy, BarcodeImagegeneruje ostrzeżenie, które Checkwyłapuje, zwracając w tym przypadku 0.

Misza Ławrow
źródło
3
Czy wykonujesz obliczenia ręcznie, ponieważ jest on krótszy lub ponieważ Wolfram nie ma jeszcze funkcji ValidateEAN8BarCode () gdzieś w swojej standardowej bibliotece?
Mark
1
@ Mark Mathematica nie może bezpośrednio zweryfikować kodu kreskowego, ale właśnie znalazłem BarcodeImage, który generuje obraz kodu kreskowego i weryfikuje kod kreskowy w trakcie procesu. Tak Check[#~BarcodeImage~"EAN8";0,1]<1&by działało (ale jest dłuższe).
Misza Ławrow
5

Java 8, 58 56 55 bajtów

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

-2 bajty pośrednio dzięki @RickHitchcock , używając (m=4-m)*izamiast m++%2*2*i+ipo zobaczeniu go w odpowiedzi na JavaScript .
-1 bajt pośrednio dzięki @ETHProductions (i @RickHitchcock ), używając (m^=2)*izamiast (m=4-m)*i.

Wyjaśnienie:

Wypróbuj tutaj.

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
źródło
1
Możesz zapisać kolejny bajt za pomocą lewy @ETHProductions pokazało mi: zmień m=4-mna m^=2.
Rick Hitchcock
@ RickHitchcock Ach, oczywiście .. Używam ^=1dość często w odpowiedziach, kiedy chcę zmieniać pomiędzy 0i 1. ^=2działa w tym przypadku, aby zmieniać pomiędzy 1i 3. Niezła sztuczka i dziękuję za komentarz, aby wspomnieć o tym. :)
Kevin Cruijssen
4

05AB1E , 14 bajtów

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

Wypróbuj online!

Potrzebuje wiodących 0s, bierze listę cyfr.

Erik the Outgolfer
źródło
Wygląda na to, że zawiedzie 3100004(powinno być prawdą).
Zgarb
@Zgarb Tęsknisz za 0nią.
Erik the Outgolfer
Och, to wymaga sznurka? Dobrze więc, mój zły.
Zgarb
@Zgarb Cóż, możesz pominąć cytaty, ale tak, potrzebujesz wiodących 0. Ta odpowiedź używa funkcji liczbowych na ciągach znaków, co jest jedną z cech 05AB1E.
Erik the Outgolfer
@ Mr.Xcoder Pytanie nie jest do końca jasne, dodam poniżej inny kod, który sobie z tym poradzi.
Erik the Outgolfer
4

Pyth , 8 bajtów

!es+*2%2

Sprawdź wszystkie przypadki testowe!

Pyth , 13 bajtów

Jeśli możemy założyć, że dane wejściowe mają zawsze dokładnie 8 cyfr:

!es.e*bhy%hk2

Sprawdź wszystkie przypadki testowe!


Jak to działa?

! es + * 2% 2 ~ Pełny program.

      % 2 ~ Wejście [:: 2]. Co drugi element danych wejściowych.
    * 2 ~ Double (powtórz listę dwa razy).
   + ~ Dołącz dane wejściowe.
  s ~ Sum.
 e ~ Ostatnia cyfra.
! ~ Logiczne NIE.
! es.e * sbhy% hk2 ~ Pełny program.

               ~ Konwertuj dane wejściowe na ciąg znaków.
   .e ~ Wyliczona mapa, przechowująca aktualną wartość wb oraz indeks wk.
          % hk2 ~ Odwrócona parzystość indeksu. (k + 1)% 2.
        hy ~ Double, przyrost. To odwzorowuje nieparzyste liczby całkowite na 1, a parzyste na 3.
      b ~ Aktualna cyfra.
     * ~ Pomnóż.
  s ~ Sum.
 e ~ Ostatnia cyfra.
! ~ Logiczna negacja.

Jeśli suma pierwszych 7 cyfr po zastosowaniu algorytmu jest odejmowana od 10, a następnie porównywana z ostatnią cyfrą, jest to równoważne ze sprawdzaniem, czy suma wszystkich cyfr po zastosowaniu algorytmu jest wielokrotnością 10 .

Pan Xcoder
źródło
Wygląda na to, że zawiedzie 3100004(powinno być prawdą).
Zgarb
@Zgarb Wait powinniśmy zrobić 3*3+1*1+0*3+...lub 0*3+3*1+1*0..? Myślałem, że powinniśmy zrobić to pierwsze
Mr. Xcoder
W nowej specyfikacji dodano cyfry wiodące, aby upewnić się, że jest ich dokładnie 8 (jeśli dobrze rozumiem).
Zgarb
@Zgarb Ok, naprawione.
Pan Xcoder,
4

Haskell , 40 38 bajtów

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

Wypróbuj online!

Pobiera dane wejściowe jako listę 8 liczb całkowitych. Praktyczny przykład użycia nieskończonych list.

Edycja: Zapisano 2 bajty dzięki GolfWolf

Maślanki
źródło
2
Używanie definicji rekurencyjnej zamiast cycle oszczędzania 2 bajtów .
Cristian Lupascu
4

Siatkówka , 23 22 bajtów

-1 bajt dzięki Martin Ender !

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

Wypróbuj online!

Wyjaśnienie

Przykładowe dane wejściowe: 20378240

(.).
$1$1$&

Zastąp każdą parę cyfr pierwszą dwukrotnie powtórzoną cyfrą, a następnie samą parą. Rozumiemy2220333788824440

.
$*

Konwertuj każdą cyfrę na unarną. Po dodaniu nawiasów dla uzyskania przejrzystości(11)(11)(11)()(111)(111)...

M`

Policz liczbę dopasowań pustego ciągu, która jest o jeden większa niż liczba dopasowań w ciągu. (W dwóch ostatnich krokach w zasadzie wzięliśmy sumę każdej cyfry +1) Wynik:60

1$

Dopasuj a 1na końcu ciągu. Pomnożymy cyfry przez 3 i 1 na przemian i zsumujemy je, dla prawidłowego kodu kreskowego powinien on być podzielny przez 10 (ostatnia cyfra 0); ale również dodać 1 w ostatnim etapie, więc chcemy być ostatnia cyfra 1. Wynik końcowy: 1.

Lew
źródło
2
Myślę, że możesz upuścić .scenę na mecz i 1$zakończyć mecz na końcu.
Martin Ender
@MartinEnder bardzo miło, zrobię to, dzięki!
Lew
3

PowerShell , 85 bajtów

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

Wypróbuj online! lub Zweryfikuj wszystkie przypadki testowe

Implementuje algorytm zgodnie z definicją. Pobiera dane wejściowe $a, wyciąga każdą cyfrę za pomocą "$a"[0..6]i zapętla je za pomocą |%{...}. Każdej iteracji bierzemy cyfrę, rzutujemy ją jako ciąg, "$_"a następnie rzutujemy jako liczbę całkowitą +przed pomnożeniem przez jeden 3lub 1(wybrany przez inkrementację$i modulo 2).

Wszystkie wyniki są zebrane razem i zsumowane -join'+'|iex. Bierzemy ten mod wyniku 10, odejmujemy go 10i ponownie bierzemy mod wyniku 10(ten drugi mod jest konieczny, aby uwzględnić 00000000przypadek testowy). Następnie sprawdzamy, czy jest to liczba -eqcałkowita do ostatniej cyfry. Ten wynik logiczny jest pozostawiany w potoku, a dane wyjściowe są niejawne.

AdmBorkBork
źródło
Wygląda na to, że zawiedzie 3100004(powinno być prawdą).
Zgarb
@Zgarb Pracuje dla mnie? Wypróbuj online!
AdmBorkBork,
Ach, ok, przetestowałem to bez cytatów.
Zgarb
@Zgarb Ah, tak. Bez cudzysłowów PowerShell domyślnie wyrzuci jako liczbę całkowitą, usuwając wiodące zero.
AdmBorkBork,
3

Galaretka , 16 bajtów

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

Wypróbuj online!

przyjmuje dane wejściowe jako listę cyfr

HyperNeutrino
źródło
Nitpick: limity czasu TIO. Również 16 bajtów .
Erik the Outgolfer
@EriktheOutgolfer Poczekaj co. Działa, gdy Dwstawiam stopkę. I dziękuję! : D
HyperNeutrino,
@EriktheOutgolfer Czy robię coś złego? Twój 16-bajter wydaje się być nieprawidłowy?
HyperNeutrino,
Może działa to trochę inaczej, ale twoje wydaje się również trochę nieważne ... konkretnie myślę, że ostatnia linia powinna być DµṪ=Ç.
Erik the Outgolfer
1
Wygląda na to, że zawiedzie 3100004(powinno być prawdą).
Zgarb
3

APL (Dyalog) , 14 bajtów

Odpowiednik z rozwiązania streetster .

Pełna treść programu. Monity o listę numerów z STDIN.

0=10|+/⎕×83 1

Wypróbuj online!

Jest…

0= zero równe

10| mod-10 z

+/ suma

⎕× czasy wejściowe

8⍴3 1 osiem elementów zaczerpniętych cyklicznie z [3,1]

?

Adám
źródło
1
Masz na myśli, że APL nie może tego zrobić w jednej postaci z czegoś takiego jak Ancient Sumerian lub Linear B?
Mark
pociąg: 0 = 10 | - / + 2 × + /
ngn
3

05AB1E , 9 bajtów

3X‚7∍*OTÖ

Wypróbuj 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
źródło
Miły! Pierwszą rzeczą, o której pomyślałem, że „przedłużyłem”, kiedy to zobaczyłem, jeszcze jej nie użyłem.
Magic Octopus Urn
31×S*OTÖdla 8 bajtów. ×popycha 31 nrazy. Po pomnożeniu automatycznie spada dodatkowe 31.
Magic Octopus Urn
@MagicOctopusUrn That wydaje się zawieść na 6. testcase69165430 -> 1
kalsowerus
3

J, 17 bajtów

-10 bajtów dzięki Cole

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

Wypróbuj online!

Wykorzystuje to mnożenie list o jednakowych rozmiarach, aby uniknąć kombinacji zip / multiply oryginalnego rozwiązania, a także „trick 1 base” 1#. aby dodać produkty razem. Podejście na wysokim poziomie jest podobne do pierwotnego wyjaśnienia.

oryginał, 27 bajtów

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

Wypróbuj online!

wyjaśnił

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
Jonasz
źródło
0=10|1#.(8$3 1)*]powinien działać dla 17 bajtów (robi ten sam algorytm). Jestem prawie pewien, że w wersji beta możesz mieć haczyk zakończony po prawej stronie rzeczownikiem, więc 0=10|1#.]*8$3 1może działać dla 15 (sprawdziłbym tio, ale wydaje się, że nie działa?)
cole,
@cole, uwielbiam to ulepszenie. Nauczyłem się tej 1#.sztuczki i zapomniałem ją 2 lub 3 razy ... dzięki za przypomnienie. Oh btw 15 bajtowa wersja nie działała w TIO.
Jonasz
3

C (gcc), 84 82 72 61 54 bajtów

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

-21 bajtów od Neila

-7 bajtów od Nahuela Fouilleula

Wypróbuj online!

Opracowany niezależnie od odpowiedzi Steadyboksa

„f” to funkcja, która przyjmuje kod kreskowy jako inti zwraca wartości 1True i 0False.

  • fprzechowuje ostatnią cyfrę xin s( s=x%10),

  • Następnie oblicza sumę w c( for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)

    • c jest sumą i jest licznikiem

    • dla każdej cyfry, w tym pierwszej, dodaj 1+2*i%4liczbę cyfry ( x%10) do sumy kontrolnej i przyrostu i( i++in 3-2*i++%4)

      • 1+2*i%4wynosi 1, gdy ijest parzysty, a 0, gdy ijest nieparzysty
  • Następnie zwraca, czy suma jest wielokrotnością dziesięciu, a ponieważ dodaliśmy ostatnią cyfrę (pomnożoną przez 1), suma będzie wielokrotnością dziesięciu, jeśli kod kreskowy jest prawidłowy. (wykorzystuje niezdefiniowane zachowanie zależne od GCC return).

pizzapanty184
źródło
Myślę, że (x%10)i tak może być xtak jak c%10później. Myślę też, że możesz użyć, i<8a następnie po prostu przetestować, czy c%10na końcu jest zero.
Neil,
@Neil Thanks! To ma -10 bajtów.
pizzapants184
W rzeczywistości uważam, że nie sjest to konieczne:c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;}
Neil
Łącze tio ma 61 bajtów, ale w odpowiedzi 72, również nie wiem, dlaczego x=c%10<1lub c=c%10<1zamiast tego return c%10<1nadal działa
Nahuel Fouilleul
również i<8może zostać zastąpiony przezx
Nahuel Fouilleul
3

C, 63 bajty

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

Zakłada się, że 0jest truei każda inna wartość jestfalse .

+3 bajty dla lepszej wartości zwracanej

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

Dodaj ==0doreturn wyciągu.

Bez golfa

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
}

Wykorzystuje to alternatywną definicję sum kontrolnych EAN, w których cyfra kontrolna jest wybierana w taki sposób, że suma kontrolna całego kodu kreskowego, w tym cyfra kontrolna, jest wielokrotnością 10. Matematycznie to działa tak samo, ale jest o wiele łatwiejsze do napisania.

Inicjalizacja zmiennych wewnątrz pętli, jak sugeruje Steadybox, 63 bajty

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

Usuwanie nawiasów klamrowych zgodnie z sugestią Steadybox, 61 bajtów

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

Używanie <1zamiast ==0lepszej wartości zwrotu, jak sugerował Kevin Cruijssen

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

Dodaj <1do returninstrukcji, to dodaje tylko 2 bajty zamiast dodawać, ==0która dodaje 3 bajty.

Micheal Johnson
źródło
Możesz zapisać dwa bajty , usuwając {}po for. Ponadto przesłane funkcje muszą być wielokrotnego użytku , więc musisz zainicjować swewnątrz funkcji (po prostu zmień i;s=0;na i,s;i i=0;na i=s=0;).
Steadybox
@ Steadybox Jak mogę usunąć nawiasy klamrowe?
Micheal Johnson
Jest w nich tylko jedno stwierdzenie. Gdy po nawiasie nie ma nawiasów klamrowych for, treść pętli będzie następną instrukcją. for(i=0;i<8;i++){s+=v[i]*3+v[++i];}jest taki sam jak for(i=0;i<8;i++)s+=v[i]*3+v[++i];.
Steadybox
@ Steadybox Och, oczywiście. Jest to jeden z dziwactw składni C, o którym zwykle zapominam, ponieważ podczas pisania normalnego kodu zawsze dołączam nawiasy klamrowe, nawet jeśli są niepotrzebne, ponieważ dzięki temu kod jest bardziej czytelny.
Micheal Johnson
W twojej prawdziwej / fałszywej odpowiedzi zamiast +3, dodając ==0, możesz być +2, używając <1zamiast tego. :)
Kevin Cruijssen
2

JavaScript (Node.js) , 47 bajtów

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

Chociaż odpowiedź jest już znacznie krótsza, jest to moja pierwsza gra w golfa w JavaScript, więc chciałbym usłyszeć zalecenia dotyczące gry w golfa :-)

Testowanie

Alternatywnie możesz wypróbować online!

Mr. Xcoder
źródło
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
źródło
1
Miał trochę zabawę z tym i pomyślałem, że podzielę się użyteczną sztuczkę: --$|przełączanie między 1a 0więc można używać, zamiast ++$i%2za logiczną zmiennego! Liczy się tylko to, że total ( $s) pasuje /0$/, udało się uzyskać 33 bajty łącząc te zmiany z s///: Wypróbuj online! ( -ljest tylko dla widoczności)
Dom Hastings
tak, myślałem do s/./(something with $&)/gei /0$/pasuję, ale nie razem.
Nahuel Fouilleul
2

Brainfuck, 228 bajtów

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

Prawdopodobnie można go nieco poprawić. Wejście jest pobierane 1 cyfra na raz, wyjścia 1 dla true, 0 dla false.

Jak to działa:

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

Umieść 8 w pozycji 3.

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

Pobiera dane 8 razy, za każdym razem zmieniając je z wartości ascii na wartość rzeczywistą +2. Wejścia są oddzielone od nich, które zostaną usunięte, aby umożliwić późniejsze pomnożenie.

>[->]

Odejmij jeden od każdego elementu. Nasza taśma wygląda teraz jakoś

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

Z każdą wartością o 1 więcej niż powinno być. Wynika to z faktu, że zera zaburzą nasz proces mnożenia.

Teraz jesteśmy gotowi do rozpoczęcia mnożenia.

<<<<

Przejdź do ostatniego do ostatniego elementu.

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

Przy zerowym pomnóż element, na którym jest, przez trzy, a następnie przesuń dwa elementy w lewo. Teraz pomnożyliśmy wszystko, czego potrzebowaliśmy, przez trzy i jesteśmy na pierwszym miejscu na taśmie.

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

Zsumuj całą listę.

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

Wartość, którą mamy, jest o 16 większa niż wartość rzeczywista. Napraw to, odejmując 16.

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

Musimy sprawdzić, czy suma jest wielokrotnością 10. Maksymalna suma to wszystkie 9, czyli 144. Ponieważ żadna suma nie będzie większa niż 10 * 15, umieść 15 i 10 na taśmie, w tej kolejności i prawo do prawo do sumy.

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

Przejdź tam, gdzie jest 15. Chociaż jest niezerowa, sprawdź, czy suma jest niezerowa. Jeśli tak, odejmij od niego 10. Teraz jesteśmy albo na (pustej) pozycji sumy, albo na (również pustej) pozycji dziesięciu. Przesuń jeden w prawo. Gdybyśmy byli na pozycji sumy, jesteśmy teraz na niezerowej pozycji 15. Jeśli tak, przesuń dwukrotnie w prawo. Teraz jesteśmy w tej samej pozycji w obu przypadkach. Dodaj dziesięć do dziesięciu pozycji i odejmij jedną z 15 pozycji.

Reszta dotyczy danych wyjściowych:

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

Przejdź do pozycji sumy. Jeśli jest niezerowy (ujemny), kod kreskowy jest nieprawidłowy; ustaw pozycję na -1. Teraz dodaj 49, aby uzyskać poprawną wartość ascii: 1 jeśli jest poprawna, 0 jeśli jest niepoprawna.

Bolce Bussiere
źródło
2

Java 8, 53 bajty

Gra w golfa:

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

Bezpośrednie obliczenia w lambda wydają się najkrótszym rozwiązaniem. Pasuje do pojedynczego wyrażenia, minimalizując narzut lambda i usuwając zewnętrzne deklaracje zmiennych i średniki.

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

Wydajność:

[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

źródło
2

QBasic, 54 52 bajtów

Nudna odpowiedź okazała się najkrótsza:

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

Wprowadza cyfry oddzielone przecinkami. Moje oryginalne 54-bajtowe rozwiązanie, które wprowadza jedną cyfrę na raz, wykorzystuje „ładniejsze” podejście:

m=3
FOR i=1TO 8
INPUT d
s=s+d*m
m=4-m
NEXT
?s MOD 10=0
DLosc
źródło
2

C # (.NET Core) , 65 62 bajtów

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

Wypróbuj online!

Podziękowanie

-3 bajty dzięki @KevinCruijssen i zgrabnej sztuczce przy użyciu operatora exclusive-or.

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 bajty

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

Wypróbuj online!

Bezpośredni port odpowiedzi @ Snowman .

Ayb4btu
źródło
Dla twojej pierwszej odpowiedzi: b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;}( 62 bajty ), lub alternatywnie z foreach, również 62 bajty: b=>{int s=0,t=1;foreach(int i in b)s+=i*(t^=2);return s%10<1;}(która jest portem mojej odpowiedzi Java 8 ).
Kevin Cruijssen
1

MATLAB / oktawa , 32 bajty

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

Wypróbuj online!

Zamierzam to opublikować pomimo drugiej odpowiedzi Octave, gdy opracowałem ten kod i podchodziłem do niego bez patrzenia na inne odpowiedzi.

Tutaj mamy anonimową funkcję, która przyjmuje dane wejściowe jako tablicę 8 wartości i zwraca true, jeśli poprawny kod kreskowy, false w przeciwnym razie ..

Wynik oblicza się w następujący sposób.

              2*x(1:2:7)
             [          ,x]
         sum(              )
     mod(                   ,10)
@(x)~
  1. Liczby nieparzyste (jedna indeksowana) są mnożone przez 2.
  2. Wynik jest dodawany do tablicy wejściowej, dając tablicę, której suma będzie zawierała cyfry nieparzyste trzy razy, a cyfry parzyste jeden raz.
  3. Robimy sumę, która obejmuje również dostarczoną sumę kontrolną w ramach naszej sumy.
  4. Następnie wykonywany jest moduł 10. Jeśli podana suma kontrolna była poprawna, suma wszystkich pomnożonych cyfr, w tym wartość sumy kontrolnej, byłaby wielokrotnością 10. Dlatego tylko poprawny kod kreskowy zwróciłby 0.
  5. Wynik jest odwracany, aby uzyskać logiczne wyjście true, jeśli jest poprawne.
Tom Carpenter
źródło
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
źródło
=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}
displayname
źródło
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.

Misha Lavrov
źródło