Apakah barcode saya valid?

33

Sebuah EAN-8 barcode meliputi 7 digit informasi dan checksum digit ke-8.

Checksum dihitung dengan mengalikan digit dengan 3 dan 1 secara bergantian, menambahkan hasilnya, dan mengurangi dari kelipatan 10 berikutnya.

Misalnya, diberi angka 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

Jumlah digit yang dihasilkan ini adalah 55 , sehingga digit checksum adalah 60 - 55 = 5


Tantangan

Tugas Anda adalah, diberi barcode 8 digit, memverifikasi apakah valid - mengembalikan nilai kebenaran jika checksum valid, dan sebaliknya palsu.

  • Anda dapat mengambil input dalam formulir berikut:
    • String, panjang 8 karakter, mewakili digit kode batang
    • Daftar 8 bilangan bulat, digit barcode
    • Integer non-negatif (Anda dapat mengasumsikan nol terkemuka di mana tidak ada yang diberikan, yaitu 1= 00000001, atau meminta input dengan nol yang diberikan)
  • Builtin yang menghitung checksum EAN-8 (yaitu, ambil 7 digit pertama dan hitung yang terakhir) dilarang.
  • Ini adalah , jadi program terpendek (dalam byte) menang!

Uji Kasus

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

21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False
FlipTack
sumber
Terkait dengan algoritma Luhn untuk memverifikasi nomor kartu kredit , mungkin penipuan.
xnor
1
Pertanyaan ini sebenarnya bukan tentang kode batang (yang merupakan garis hitam-putih), tetapi tentang nomor yang dikodekan oleh barcode. Angka tersebut dapat ada tanpa kode batang, dan kode batang dapat menyandikan hal lain selain EAN. Mungkin hanya " Apakah EAN-8 saya valid " adalah judul yang lebih baik?
Paŭlo Ebermann
2
@ PaŭloEbermann tidak memiliki cincin yang sama untuk itu ...
FlipTack
7
Saat membaca tentang barcode, saya mengharapkan beberapa pembacaan gambar (atau setidaknya sedikit-string), tidak memverifikasi checksum.
Paŭlo Ebermann
Sangat terkait , karena ISBN-13 adalah EAN.
Olivier Grégoire

Jawaban:

5

Jelly , 7 byte

s2Sḅ3⁵ḍ

Cobalah online!

Bagaimana itu bekerja

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
sumber
13

JavaScript (ES6), 41 40 38 byte

Disimpan 2 byte berkat @ETHProductions dan 1 byte terima kasih ke @Craig Ayre.

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

Mengambil input sebagai daftar digit.

Menentukan jumlah semua digit, termasuk checksum.

Jika jumlahnya adalah kelipatan 10, maka itu adalah barcode yang valid.

Uji Kasus

Rick Hitchcock
sumber
Saya akan mengatakan Anda dapat menghemat 3 byte dengan beralih dari pra-rekursi ke pasca-rekursi dengan g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1, tetapi Anda mungkin telah menemukan cara yang lebih baik ...
ETHproduksi
Terima kasih, @ ETHproductions, saya telah mengubah map, yang menurut saya berfungsi lebih baik karena input dapat berupa daftar digit, bukan string.
Rick Hitchcock
Mungkin menyimpan byte lain dengan s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1?
ETHproduksi
Ya, brilian, terima kasih
:)
Solusi hebat! Bisakah Anda ganti &&dengan |dengan output 1/0 karena kebenaran / kepalsuan diizinkan?
Craig Ayre
10

Python 2 , 64 48 35 29 byte

mypetlion menyimpan 19 byte

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

Cobalah online!

Halvard Hummel
sumber
lambda x:sum(x[::2]*3+x[1::2])%10<1Selama 35 byte.
mypetlion
2
lambda x:sum(x[::2]*2+x)%10<1Selama 29 byte.
mypetlion
8

Jelly , 8 byte

m2Ḥ+µS⁵ḍ

Coba test suite.

Jelly , 9 byte

JḂḤ‘×µS⁵ḍ

Cobalah online atau Coba test suite.

Bagaimana ini bekerja?

m2Ḥ + µS⁵ḍ ~ Program lengkap.

m2 ~ Modular 2. Kembalikan setiap elemen input yang kedua.
  Ḥ ~ Gandakan masing-masing.
   + µ ~ Tambahkan input dan mulai rantai monadik baru.
     S ~ Jumlah.
      ⁵ḍ ~ Apakah habis dibagi 10?
JḂḤ '× µS⁵ḍ ~ Program lengkap (monadik).

J ~ 1 rentang panjang diindeks.
 Ḃ ~ Sedikit; Modulo masing-masing angka dalam kisaran di atas oleh 2.
  Ḥ ~ Gandakan masing-masing.
   '~ Setiap kenaikan.
    × ~ Perkalian berpasangan dengan input.
     μ ~ Memulai rantai monadik baru.
      S ~ Jumlah.
       ⁵ḍ ~ Apakah jumlahnya dapat dibagi 10?

Hasil untuk 7 digit pertama dari barcode dan digit checksum harus ditambahkan kelipatan 10 agar valid. Dengan demikian, checksum valid jika algoritma yang diterapkan pada seluruh daftar dapat dibagi 10 .

Tuan Xcoder
sumber
Masih 9 byte tetapi dengan nilai yang konsisten:JḂḤ‘×µS⁵ḍ
HyperNeutrino
@HyperNeutrino Terima kasih, saya tahu ada atom untuk ini!
Tn. Xcoder
Juga 9 byte:: JḂaḤ+µS⁵ḍP
HyperNeutrino
@HyperNeutrino Yah ada banyak alternatif: P
Mr. Xcoder
1
8 byte atau 8 karakter? m2Ḥ+µS⁵ḍadalah 15 byte di UTF-8, kecuali saya sudah salah menghitungnya.
ta.speot.is
7

MATL , 10 byte

Terima kasih kepada @Zgarb karena menunjukkan kesalahan, sekarang diperbaiki.

IlhY"s10\~

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

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
sumber
7

Befunge-98 (PyFunge) , 16 14 byte

Disimpan 2 byte dengan melewatkan bagian kedua menggunakan jbukan ;s, serta menukar a ~dan +di bagian pertama untuk menyingkirkan a +di bagian kedua.

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

Input dalam 8 digit (dengan awalan 0s jika berlaku) dan tidak ada yang lain.

Output melalui kode keluar (buka dropdown debug pada TIO), di mana 1 benar dan 0 salah.

Cobalah online!

Penjelasan

Program ini menggunakan berbagai trik.

Pertama-tama, dibutuhkan digit satu per satu melalui nilai ASCII mereka. Biasanya, ini membutuhkan pengurangan 48 dari setiap nilai saat kita membacanya dari input. Namun, jika kami tidak memodifikasinya, kami memiliki 16 (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1) salinan tambahan dari 48 jumlah kami, yang berarti total kami akan menjadi 768 lebih besar dari apa itu "seharusnya". Karena kita hanya peduli dengan jumlah mod 10, kita bisa menambahkan 2 ke jumlah kemudian. Dengan demikian, kita dapat mengambil nilai ASCII mentah, menghemat 6 byte atau lebih.

Kedua, kode ini hanya memeriksa apakah setiap karakter lain adalah EOF, karena inputnya dijamin hanya 8 karakter.

Ketiga, #pada akhir baris tidak melewatkan karakter pertama, tetapi akan melewatkan ;jika datang dari arah lain. Ini lebih baik daripada meletakkan #;di depan saja.

Karena bagian kedua dari program kami hanya berjalan sekali, kami tidak perlu mengaturnya sehingga akan melewati babak pertama ketika berjalan mundur. Ini memungkinkan kita menggunakan perintah lompat untuk melompati babak kedua, saat kita keluar sebelum mengeksekusinya mundur.

Selangkah demi selangkah

Catatan: Karakter "Ganjil" dan "Genap" didasarkan pada sistem yang diindeks 0. Karakter pertama adalah karakter genap, dengan indeks 0.

~3*+~+      Main loop - sum the digits (with multiplication)
~           If we've reached EOF, reverse; otherwise take char input. This will always
                be evenly indexed values, as we take in 2 characters every loop.
 3*+        Multiply the even character by 3 and add it to the sum.
    ~       Then, take an odd digit - we don't have to worry about EOF because
                the input is always 8 characters.
     +      And add it to the sum.
      6j    Jump over the second part - We only want to run it going backwards.

        q!%a+2    The aftermath (get it? after-MATH?)
            +2    Add 2 to the sum to make up for the offset due to reading ASCII
          %a      Mods the result by 10 - only 0 if the bar code is valid
         !        Logical not the result, turning 0s into 1s and anything else into 0s
        q         Prints the top via exit code and exits
MildlyMilquetoast
sumber
6

C,  78  77 byte

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

Cobalah online!

C (gcc), 72 byte

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

Cobalah online!

Steadybox
sumber
6

Bahasa Wolfram (Mathematica) , 26 21 byte

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

Cobalah online!

Mengambil input sebagai daftar 8 digit.

Bagaimana itu bekerja

2-9^Range@8adalah modulo 10 kongruen 2-(-1)^Range@8, yaitu {3,1,3,1,3,1,3,1}. Kami mengambil produk titik dari daftar ini dengan input, dan memeriksa apakah hasilnya dapat dibagi 10.

Bahasa Wolfram (Mathematica) , 33 byte dan tidak bersaing

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

Cobalah online!

Mengambil input sebagai string. Pengembalian 1untuk barcode yang valid dan 0untuk yang tidak valid.

Bagaimana itu bekerja

Hal terbaik yang bisa saya temukan di jalan bawaan (karena Mathematica adalah soal itu).

Bit bagian dalam #~BarcodeImage~"EAN8";1,, menghasilkan gambar dari barcode EAN8, kemudian mengabaikannya sepenuhnya dan mengevaluasi ke 1. Namun, jika barcode tidak valid, kemudian BarcodeImagemenghasilkan peringatan, yang Checkmenangkap, mengembalikan 0 dalam kasus itu.

Misha Lavrov
sumber
3
Apakah Anda melakukan perhitungan dengan tangan karena lebih pendek, atau karena Wolfram belum memiliki fungsi ValidateEAN8BarCode () di suatu tempat di perpustakaan standarnya?
Tandai
1
@ Markus Mathematica tidak dapat memvalidasi barcode secara langsung, tetapi saya baru saja menemukan BarcodeImage, yang menghasilkan gambar barcode, dan memvalidasi barcode dalam proses. Begitu Check[#~BarcodeImage~"EAN8";0,1]<1&juga bekerja (tapi lebih lama).
Misha Lavrov
5

Java 8, 58 56 55 byte

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

-2 byte secara tidak langsung berkat @RickHitchcock , dengan menggunakan (m=4-m)*ialih-alih m++%2*2*i+isetelah melihatnya dalam jawaban JavaScript- nya .
-1 byte secara tidak langsung berkat @ETHProductions (dan @RickHitchcock ), dengan menggunakan (m^=2)*ialih-alih (m=4-m)*i.

Penjelasan:

Coba di sini.

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
sumber
1
Anda dapat menyimpan byte lain dengan trik @ETHProductions menunjukkan kepada saya: ubah m=4-mke m^=2.
Rick Hitchcock
@RickHitchcock Ah, tentu saja .. Saya ^=1cukup sering menggunakan jawaban ketika saya ingin mengubah antara 0dan 1. ^=2berfungsi dalam hal ini untuk mengubah antara 1dan 3. Trik yang bagus, dan terima kasih atas komentarnya. :)
Kevin Cruijssen
4

05AB1E , 14 byte

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

Cobalah online!

Membutuhkan terkemuka 0, mengambil daftar digit.

Erik the Outgolfer
sumber
Tampaknya gagal 3100004(harus jujur).
Zgarb
@ Zgarb Anda melewatkan satu di 0sana.
Erik the Outgolfer
Oh, ini butuh string? Baiklah kalau begitu, salahku.
Zgarb
@ Zgarb Yah, Anda bisa menghilangkan tanda kutip, tapi ya, Anda memang perlu yang memimpin 0. Jawaban ini sebenarnya menggunakan fungsi angka pada string, salah satu fitur 05AB1E.
Erik the Outgolfer
@ Mr.Xcoder Pertanyaannya tidak terlalu jelas tentang itu, saya akan menambahkan kode lain yang menangani untuk itu di bawah ini.
Erik the Outgolfer
4

Pyth , 8 byte

!es+*2%2

Verifikasi semua kasus uji!

Pyth , 13 byte

Jika kita dapat berasumsi bahwa input selalu memiliki tepat 8 digit:

!es.e*bhy%hk2

Verifikasi semua kasus uji!


Bagaimana cara kerjanya?

! es + * 2% 2 ~ Program lengkap.

      % 2 ~ Input [:: 2]. Setiap elemen input kedua.
    * 2 ~ Ganda (daftar ulangi dua kali).
   + ~ Tambahkan input.
  s ~ Jumlah.
 e ~ Digit terakhir.
! ~ TIDAK logis.
! es.e * sbhy% hk2 ~ Program lengkap.

               ~ Konversikan input ke String.
   .e ~ Enumerated map, menyimpan nilai saat ini di b dan indeks di k.
          % hk2 ~ Paritas terbalik dari indeks. (k + 1)% 2.
        hy ~ Gandakan, increment. Ini memetakan bilangan bulat ganjil ke 1 dan bahkan yang ke 3.
      b ~ Digit saat ini.
     * ~ Multiply.
  s ~ Jumlah.
 e ~ Digit terakhir.
! ~ Negasi logis.

Jika jumlah dari 7 digit pertama setelah diterapkan algoritma dikurangi dari 10 dan kemudian dibandingkan dengan digit terakhir, ini sama dengan memeriksa apakah jumlah semua digit, setelah algoritma diterapkan adalah kelipatan dari 10 .

Tuan Xcoder
sumber
Tampaknya gagal 3100004(harus jujur).
Zgarb
@ Zgarb Tunggu, haruskah kita lakukan 3*3+1*1+0*3+...atau tidak 0*3+3*1+1*0..? Saya pikir kita harus melakukan yang pertama
Tn. Xcoder
Dalam spec baru, digit terdepan ditambahkan untuk memastikan ada 8 angka (jika saya mengerti dengan benar).
Zgarb
@ Zgarb Ok, sudah diperbaiki.
Tn. Xcoder
4

Haskell , 40 38 byte

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

Cobalah online!

Mengambil input sebagai daftar 8 bilangan bulat. Contoh praktis menggunakan daftar tak terbatas.

Sunting: Disimpan 2 byte berkat GolfWolf

anjing kampung
sumber
2
Menggunakan definisi rekursif alih-alih cycle menghemat 2 byte .
Cristian Lupascu
4

Retina , 23 22 byte

-1 byte terima kasih kepada Martin Ender !

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

Cobalah online!

Penjelasan

Input contoh: 20378240

(.).
$1$1$&

Ganti setiap pasangan angka dengan digit pertama diulang dua kali diikuti oleh pasangan itu sendiri. Kita mendapatkan2220333788824440

.
$*

Ubah setiap digit menjadi unary. Dengan tanda kurung ditambahkan untuk kejelasan, kita dapatkan(11)(11)(11)()(111)(111)...

M`

Hitung jumlah kecocokan string kosong, yang satu lebih banyak dari jumlah yang ada dalam string. (Dengan dua langkah terakhir pada dasarnya kami telah mengambil jumlah setiap digit +1) Hasil:60

1$

Cocokkan 1di akhir string. Kami telah mengalikan digit dengan 3 dan 1 secara bergantian dan menjumlahkannya, untuk barcode yang valid ini harus dapat dibagi dengan 10 (digit terakhir 0); tapi kami juga menambahkan 1 di langkah terakhir, jadi kami ingin angka terakhir menjadi 1. Hasil akhir: 1.

Leo
sumber
2
Saya pikir Anda bisa menjatuhkan .pertandingan dan pertandingan 1$di akhir.
Martin Ender
@ MartinEnder sangat baik, saya akan melakukannya, terima kasih!
Leo
3

PowerShell , 85 byte

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

Cobalah online! atau Verifikasi semua kasus uji

Menerapkan algoritma seperti yang didefinisikan. Mengambil input $a, menarik setiap digit dengan "$a"[0..6]dan loop melalui mereka |%{...}. Setiap iterasi, kami mengambil digit, melemparkannya sebagai string "$_"kemudian melemparkannya sebagai int +sebelum mengalikannya dengan salah satu 3atau 1(dipilih dengan menambah $imodulo 2).

Semua hasil itu dikumpulkan dan dijumlahkan -join'+'|iex. Kami mengambil mod hasil itu 10, kurangi dari 10, dan kembali mengambil mod hasil 10(mod kedua ini diperlukan untuk menjelaskan 00000000kasus uji). Kami kemudian memeriksa apakah itu -equal ke digit terakhir. Hasil Boolean ditinggalkan di jalur pipa dan hasilnya tersirat.

AdmBorkBork
sumber
Tampaknya gagal 3100004(harus jujur).
Zgarb
@Zgarb Bekerja untuk saya? Cobalah online!
AdmBorkBork
Ah ok, saya mengujinya tanpa tanda kutip.
Zgarb
@ Zgarb Ah, ya. Tanpa tanda kutip, PowerShell secara implisit akan dilemparkan sebagai integer, menghilangkan nol di muka.
AdmBorkBork
3

Jelly , 16 byte

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

Cobalah online!

menerima input sebagai daftar digit

HyperNeutrino
sumber
Nitpick: batas waktu TIO Anda. Juga, 16 byte .
Erik the Outgolfer
@EriktheOutgolfer Tunggu, bagaimana caranya. Ini bekerja ketika saya memasukkan Dfooter. Dan terima kasih! : D
HyperNeutrino
@EriktheOutgolfer Apakah saya melakukan sesuatu yang salah? 16-byter Anda tampaknya tidak valid?
HyperNeutrino
Mungkin, ini bekerja agak berbeda, tetapi milik Anda tampaknya agak tidak valid juga ... khususnya saya pikir baris terakhir seharusnya DµṪ=Ç.
Erik the Outgolfer
1
Tampaknya gagal 3100004(harus jujur).
Zgarb
3

APL (Dyalog) , 14 byte

Setara dengan solusi streetster .

Tubuh program penuh. Meminta daftar nomor dari STDIN.

0=10|+/⎕×83 1

Cobalah online!

Aku s…

0= nol sama dengan

10| mod-10 dari

+/ jumlah dari

⎕× waktu input

8⍴3 1 delapan elemen diambil secara siklis [3,1]

?

Adm
sumber
1
Maksud Anda APL tidak dapat melakukannya dalam satu karakter dari sesuatu seperti Sumeria Kuno atau Linear B?
Tandai
kereta: 0 = 10 | - / + 2 × + /
ngn
3

05AB1E , 9 byte

3X‚7∍*OTÖ

Cobalah 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
sumber
Bagus! Hal pertama yang saya pikir adalah "memperpanjang ke panjang" ketika saya melihat ini, belum pernah menggunakannya.
Magic Octopus Mm
31×S*OTÖuntuk 8 byte. ×hanya mendorong 31 nkali. Ketika Anda mengalikan, secara otomatis akan menjatuhkan 31 ekstra.
Magic Gurita Guci
@MagicOctopusUrn Tampaknya gagal pada testcase ke-669165430 -> 1
kalsowerus
3

J, 17 byte

-10 byte berkat cole

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

Cobalah online!

Ini menggunakan penggandaan daftar berukuran sama untuk menghindari kombo zip / gandakan solusi asli, serta "trik dasar 1" 1#.untuk menambahkan produk bersama. Pendekatan tingkat tinggi mirip dengan penjelasan asli.

asli, 27 byte

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

Cobalah online!

dijelaskan

0 =                                        is 0 equal to... 
    10 |                                   the remainder when 10 divides...
         {: +                              the last input item plus...
              [: +/                        the sum of...
                    [: */                  the pairwise product of...
                          7$(3 1) ,:       3 1 3 1 3 1 3 zipped with...
                                     }:    all but the last item of the input
Jonah
sumber
0=10|1#.(8$3 1)*]harus bekerja selama 17 byte (melakukan algoritma yang sama juga). Saya cukup yakin bahwa dalam versi beta Anda dapat memiliki kait berakhir di sisi kanan dengan kata benda, jadi 0=10|1#.]*8$3 1mungkin bekerja untuk 15 (saya akan memeriksa tio tetapi tampaknya turun?)
cole
@cole, saya suka peningkatan ini. Saya telah belajar tentang dan melupakan 1#.trik seperti 2 atau 3 kali ... terima kasih telah mengingatkan saya. Oh, btw versi 15 byte tidak berfungsi di TIO.
Jonah
3

C (gcc), 84 82 72 61 54 byte

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

-21 byte dari Neil

-7 byte dari Nahuel Fouilleul

Cobalah online!

Dikembangkan secara independen dari jawaban Steadybox

'f' adalah fungsi yang mengambil barcode sebagai int, dan mengembalikan 1untuk True dan 0False.

  • fmenyimpan digit terakhir dari xdalam s( s=x%10),

  • Kemudian hitung jumlah dalam c( for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)

    • cadalah jumlah, iadalah penghitung

    • untuk setiap digit termasuk yang pertama, tambahkan 1+2*i%4kali digit ( x%10) ke checksum dan kenaikan i( i++dalam 3-2*i++%4)

      • 1+2*i%4adalah 1 saat igenap dan 0 bila iganjil
  • Kemudian mengembalikan apakah jumlahnya merupakan kelipatan dari sepuluh, dan karena kami menambahkan digit terakhir (dikalikan dengan 1), jumlahnya akan menjadi kelipatan dari sepuluh jika barcode itu valid. (menggunakan perilaku tidak terdefinisi tergantung GCC untuk menghilangkan return).

pizzapants184
sumber
Saya pikir (x%10)bisa saja xseperti yang Anda lakukan c%10nanti. Juga saya pikir Anda dapat menggunakan i<8dan kemudian hanya menguji apakah c%10nol pada akhirnya.
Neil
@Neil Terima kasih! Itu mendapat -10 byte.
pizzapants184
Sebenarnya saya pikir stidak perlu:c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;}
Neil
tautan tio adalah 61 byte tetapi dalam jawabannya 72, juga tidak tahu mengapa x=c%10<1atau c=c%10<1bukannya return c%10<1masih berfungsi
Nahuel Fouilleul
juga i<8dapat digantikan olehx
Nahuel Fouilleul
3

C, 63 byte

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

Mengasumsikan bahwa 0adalah truedan nilai lain adalah false.

+3 byte untuk nilai pengembalian yang lebih baik

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

Tambahkan ==0ke returnpernyataan.

Tidak disatukan

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
}

Ini menggunakan definisi alternatif checksum EAN di mana digit cek dipilih sedemikian rupa sehingga checksum dari seluruh barcode termasuk digit periksa adalah kelipatan 10. Secara matematis ini berfungsi sama tetapi jauh lebih mudah untuk menulis.

Menginisialisasi variabel di dalam loop seperti yang disarankan oleh Steadybox, 63 byte

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

Menghapus kurung keriting seperti yang disarankan oleh Steadybox, 61 byte

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

Menggunakan <1daripada ==0untuk nilai pengembalian yang lebih baik seperti yang disarankan oleh Kevin Cruijssen

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

Tambahkan <1ke returnpernyataan, ini hanya menambah 2 byte daripada menambahkan ==0yang menambahkan 3 byte.

Micheal Johnson
sumber
Anda dapat menyimpan dua byte dengan menghapus {}setelah for. Juga, pengiriman fungsi harus dapat digunakan kembali , jadi Anda perlu menginisialisasi sdi dalam fungsi (hanya mengubah i;s=0;ke i,s;dan i=0;ke i=s=0;).
Steadybox
@Steadybox Bagaimana saya bisa menghapus kurung keriting?
Micheal Johnson
Hanya ada satu pernyataan di dalamnya. Ketika tidak ada kurung keriting setelah itu for, tubuh loop akan menjadi pernyataan berikutnya for(i=0;i<8;i++){s+=v[i]*3+v[++i];}sama dengan for(i=0;i<8;i++)s+=v[i]*3+v[++i];.
Steadybox
@Steadybox Oh tentu saja. Itulah salah satu keanehan sintaks C yang biasanya saya lupakan, karena ketika menulis kode normal saya selalu menyertakan kurung keriting bahkan jika itu tidak perlu, karena itu membuat kode lebih mudah dibaca.
Micheal Johnson
Dalam jawaban benar / salah Anda, bukannya +3 dengan menambahkannya ==0bisa +2 dengan menggunakan <1sebagai gantinya. :)
Kevin Cruijssen
2

JavaScript (Node.js) , 47 byte

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

Meskipun sudah ada jawaban yang jauh lebih singkat, ini adalah upaya pertama saya bermain golf di JavaScript sehingga saya ingin mendengar rekomendasi golf :-)

Pengujian

Atau, Anda dapat mencobanya secara online!

Tuan Xcoder
sumber
2

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

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

-5 byte berkat Dom Hastings. 37 +1 byte tadinya

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

coba online

Nahuel Fouilleul
sumber
1
Sudah sedikit bermain dengan ini dan berpikir saya akan berbagi trik yang berguna: --$|beralih antara 1dan 0sehingga Anda dapat menggunakannya daripada ++$i%2untuk boolean bergantian! Selain itu, yang terpenting adalah bahwa total ( $s) yang cocok /0$/, berhasil mendapatkan 33 byte yang menggabungkan perubahan-perubahan itu dengan s///: Coba online! ( -lhanya untuk visibilitas)
Dom Hastings
ya saya ke s/./(something with $&)/gedan untuk /0$/mencocokkan tetapi tidak keduanya digabungkan.
Nahuel Fouilleul
2

Brainfuck, 228 Bytes

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

Mungkin bisa ditingkatkan sedikit adil. Input diambil 1 digit pada satu waktu, output 1 untuk true, 0 untuk false.

Bagaimana itu bekerja:

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

Letakkan 8 di posisi 3.

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

Mengambil input 8 kali, mengubahnya dari nilai ascii ke nilai aktual +2 setiap kali. Input diberi spasi oleh yang, yang akan dihapus, untuk memungkinkan penggandaan yang lebih mudah nanti.

>[->]

Kurangi satu dari setiap item. Rekaman kami sekarang terlihat seperti

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

Dengan setiap nilai 1 lebih dari yang seharusnya. Ini karena nol akan mengacaukan proses perkalian kami.

Sekarang kita siap untuk mulai mengalikan.

<<<<

Pergi ke item kedua ke terakhir.

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

Sementara nol, gandakan item dengan tiga, lalu pindahkan dua item ke kiri. Sekarang kami telah mengalikan semua yang kami butuhkan menjadi tiga, dan kami berada di posisi pertama dalam rekaman itu.

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

Jumlahkan seluruh daftar.

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

Nilai yang kami miliki adalah 16 lebih dari nilai sebenarnya. Perbaiki ini dengan mengurangi 16.

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

Kita perlu menguji apakah jumlahnya adalah kelipatan 10. Jumlah maksimum adalah dengan semua 9s, yaitu 144. Karena tidak ada jumlah yang lebih besar dari 10 * 15, letakkan 15 dan 10 pada pita, dalam urutan itu dan hak untuk hak penjumlahan.

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

Pindah ke tempat 15. Meskipun tidak nol, uji apakah jumlahnya tidak nol. Jika ya, kurangi 10 dari itu. Sekarang kita berada pada posisi jumlah (kosong), atau pada posisi (juga kosong) sepuluh. Bergerak ke kanan. Jika kita berada di posisi penjumlahan, kita sekarang di posisi bukan-nol 15. Jika demikian, gerakkan ke kanan dua kali. Sekarang kami berada di posisi yang sama dalam kedua kasus. Tambahkan sepuluh ke posisi sepuluh, dan kurangi satu dari posisi 15.

Sisanya untuk output:

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

Pindah ke posisi penjumlahan. Jika bukan nol (negatif), barcode tidak valid; atur posisi ke -1. Sekarang tambahkan 49 untuk mendapatkan nilai ascii yang benar: 1 jika valid, 0 jika tidak valid.

Bolce Bussiere
sumber
2

Java 8, 53 byte

Golf:

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

Penghitungan langsung dalam lambda tampaknya merupakan solusi terpendek. Ini cocok dalam satu ekspresi, meminimalkan overhead lambda dan menghapus deklarasi variabel asing dan titik koma.

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

Keluaran:

[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

sumber
2

QBasic, 54 52 byte

Ugh, jawaban yang membosankan ternyata yang terpendek:

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

Ini input digit yang dipisahkan koma. Solusi 54 byte asli saya, yang memasukkan satu digit pada satu waktu, menggunakan pendekatan "lebih baik":

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

C # (.NET Core) , 65 62 byte

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

Cobalah online!

Ucapan Terima Kasih

-3 byte terima kasih kepada @KevinCruijssen dan trik rapi menggunakan operator-atau eksklusif.

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 byte

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

Cobalah online!

Port langsung jawaban @ Snowman .

Ayb4btu
sumber
Untuk jawaban pertama Anda: b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;}( 62 byte ), atau sebagai alternatif dengan foreach, juga 62 byte: b=>{int s=0,t=1;foreach(int i in b)s+=i*(t^=2);return s%10<1;}(yang merupakan port jawaban Java 8 saya ).
Kevin Cruijssen
1

MATLAB / Oktaf , 32 byte

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

Cobalah online!

Saya akan memposting ini terlepas dari jawaban Oktaf lainnya ketika saya mengembangkan kode dan pendekatan ini tanpa melihat jawaban yang lain.

Di sini kita memiliki fungsi anonim yang mengambil input sebagai array dari 8 nilai, dan mengembalikan true jika barcode yang valid, false sebaliknya ..

Hasilnya dihitung sebagai berikut.

              2*x(1:2:7)
             [          ,x]
         sum(              )
     mod(                   ,10)
@(x)~
  1. Digit ganjil (satu diindeks) dikalikan 2.
  2. Hasilnya didahului dengan array input, memberikan array yang jumlahnya akan berisi digit ganjil tiga kali, dan digit genap satu kali.
  3. Kami melakukan jumlah yang juga akan mencakup checksum yang disediakan dalam jumlah kami.
  4. Selanjutnya modulo 10 dilakukan. Jika checksum yang diberikan valid, jumlah semua digit yang dikalikan termasuk nilai checksum akan berakhir kelipatan 10. Oleh karena itu hanya barcode yang valid yang akan mengembalikan 0.
  5. Hasilnya terbalik untuk mendapatkan output logis true jika valid.
Tom Carpenter
sumber
1

Excel, 37 byte

Menafsirkan "Daftar 8 bilangan bulat" sebagai memungkinkan 8 sel terpisah di Excel:

=MOD(SUM(A1:H1)+2*(A1+C1+E1+G1),10)=0
Wernisch
sumber
= MOD (SUM ((A1: H1) + 2 * (A1 + C1 + E1 + G1)), 10) = 0 rumus ini ada di Excel?
RosLuP
@RosLuP, tidak ditentukan sebelumnya, tidak. Tapi Modulo, Sum, + etc do ;-)
Wernisch
Saya hanya ingin mengatakan bahwa dalam APL berjalan baik pertama-tama y = (A1: H1) + 2 * (A1 + C1 + E1 + G1), dan setelah penjumlahan dan mod; dalam APL tidak berjalan dengan baik jumlah pertama (A1: H1) dll sesuatu seperti (1,2,3) + 4 = (5,6,7) dan dari jumlah (5,6,7) = 18; perhatikan bahwa jumlah (1,2,3) = 6 dan 6 + 4 = 10 berbeda dari 18. Tetapi mungkin saya membuat kesalahan dalam sesuatu
RosLuP
@RosLuP, Permintaan Maaf, melewatkan perubahan ()dalam komentar Anda.
Wernisch
Masalahnya adalah bagaimana Excel menginterpretasikan =(A1:H1): Ini tidak ditangani sebagai sebuah array. Tidak valid jika ditempatkan di kolom mana pun yang tidak dalam A-Hjangkauan. Jika ditempatkan dalam kolom di AH, kembalikan nilai untuk kolom itu saja. (Formula dalam% menghasilkan%: C2 -> C1 H999 -> H1 K1 -> #VALUE!)
Wernisch
1

Ruby, 41 Bytes

Mengambil array bilangan bulat. -6 byte berkat Jordan.

->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
nama tampilan
sumber
Bagus! FWIW Anda tidak perlu mapdi sini sama sekali: zipmengambil blok. Anda dapat menyimpan beberapa byte lagi dengan menggunakan $.alih-alih menginisialisasi s:->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
Jordan
1

TI-Basic (83 series), 18 byte

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

Mengambil input sebagai daftar di Ans. Pengembalian 1untuk barcode yang valid dan 0untuk yang tidak valid.

Port jawaban Mathematica saya . Termasuk tangkapan layar, sebagai pengganti lingkungan pengujian online:

tangkapan layar barcode

Fitur penting: binomcdf(7,0digunakan untuk menghasilkan daftar {1,1,1,1,1,1,1,1}(daftar probabilitas yang dari 7 percobaan dengan probabilitas keberhasilan 0, akan ada paling banyak N keberhasilan, untuk N = 0,1, ..., 7). Lalu, cumSum(ubah ini menjadi {1,2,3,4,5,6,7,8}.

Ini satu byte lebih pendek daripada menggunakan seq(perintah, meskipun secara historis intinya adalah bahwa itu juga secara signifikan lebih cepat.

Misha Lavrov
sumber