Meu código de barras é válido?

33

Um código de barras EAN-8 inclui sete dígitos de informações e um oitavo dígito de soma de verificação.

A soma de verificação é calculada multiplicando os dígitos por 3 e 1 alternadamente, adicionando os resultados e subtraindo o próximo múltiplo de 10.

Por exemplo, dados os dígitos 2103498:

Digit:        2   1   0   3   4   9   8
Multiplier:   3   1   3   1   3   1   3
Result:       6   1   0   3  12   9  24

A soma desses dígitos resultantes é 55 , portanto, o dígito da soma de verificação é 60 - 55 = 5


O desafio

Sua tarefa é, com um código de barras de 8 dígitos, verificar se é válido - retornando um valor verdadeiro se a soma de verificação for válida e, caso contrário, falsificar.

  • Você pode receber informações de qualquer uma das seguintes formas:
    • Uma cadeia de caracteres com 8 caracteres, representando os dígitos do código de barras
    • Uma lista de 8 números inteiros, os dígitos do código de barras
    • Um número inteiro não negativo (você pode assumir zeros à esquerda onde nenhum é dado, ou seja , 1= 00000001, ou solicitar entrada com os zeros dados)
  • Os componentes internos que calculam a soma de verificação EAN-8 (ou seja, pegam os 7 primeiros dígitos e calculam os últimos) são banidos.
  • Isso é , então o programa mais curto (em bytes) vence!

Casos de teste

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

21034984 -> False
69165430 -> False
11965421 -> False
12345678 -> False
FlipTack
fonte
Relacionado ao algoritmo Luhn para verificação de números de cartão de crédito , possivelmente um idiota.
Xnor
1
Esta questão não é realmente sobre um código de barras (que é a coisa listrada em preto e branco), mas sobre o número codificado por um código de barras. O número pode existir sem um código de barras e pode codificar outras coisas além de EANs. Talvez apenas " Meu EAN-8 seja válido " seja um título melhor?
Paŭlo Ebermann 15/11
2
@ PaŭloEbermann não consegue ter o mesmo anel para ele ...
FlipTack
7
Ao ler sobre códigos de barras, espero que alguma leitura de imagem (ou pelo menos uma sequência de bits) não verifique uma soma de verificação.
Pa Elo Ebermann 15/11
Fortemente relacionado , uma vez que um ISBN-13 é um EAN.
Olivier Grégoire

Respostas:

5

Geléia , 7 bytes

s2Sḅ3⁵ḍ

Experimente online!

Como funciona

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

JavaScript (ES6), 41 40 38 bytes

Economizou 2 bytes graças a @ETHProductions e 1 byte graças a @Craig Ayre.

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

Recebe a entrada como uma lista de dígitos.

Determina a soma de todos os dígitos, incluindo a soma de verificação.

Se a soma é um múltiplo de 10, é um código de barras válido.

Casos de teste

Rick Hitchcock
fonte
Eu ia dizer que você poderia economizar 3 bytes por mudar de pré-recursão para pós-recursão com g=([n,...s],i=3,t=0)=>n?g(s,4-i,t+n*i):t%10<1, mas você pode ter encontrado uma maneira melhor ...
ETHproductions
Obrigado, @ETHproductions, mudei para map, o que acho que funciona melhor, pois a entrada pode ser uma lista de dígitos em vez de uma string.
Rick Hitchcock
Talvez salvar outro byte com s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1?
ETHproductions
Sim, brilhante, graças:)
Rick Hitchcock
Ótima solução! Você poderia substituir &&com |a saída 1/0, pois a verdade / falsidade é permitida?
Craig Ayre
10

Python 2 , 64 48 35 29 bytes

mypetlion salvou 19 bytes

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

Experimente online!

Halvard Hummel
fonte
lambda x:sum(x[::2]*3+x[1::2])%10<1Para 35 bytes.
mypetlion
2
lambda x:sum(x[::2]*2+x)%10<1Para 29 bytes.
mypetlion
8

Geléia , 8 bytes

m2Ḥ+µS⁵ḍ

Experimente a suíte de testes.

Geléia , 9 bytes

JḂḤ‘×µS⁵ḍ

Experimente online ou Experimente a suíte de testes.

Como isso funciona

m2Ḥ + µS⁵ḍ ~ Programa completo.

m2 ~ Modular 2. Retorne cada segundo elemento da entrada.
  Double ~ Dobro cada.
   + µ ~ Anexe a entrada e inicie uma nova cadeia monádica.
     S ~ Sum.
      Div ~ Divisível por 10?
JḂḤ '× µS⁵ḍ ~ Programa completo (monádico).

Faixa de comprimento indexada J ~ 1.
 Bit ~ Bit; Module cada número no intervalo acima por 2.
  Double ~ Dobro cada.
   '~ Incremente cada um.
    × ~ Multiplicação pareada com a entrada.
     Inicia uma nova cadeia monádica.
      S ~ Sum.
       The ~ A soma é divisível por 10?

O resultado dos 7 primeiros dígitos do código de barras e do dígito da soma de verificação deve ser adicionado a um múltiplo de 10 para que seja válido. Portanto, a soma de verificação é válida se o algoritmo aplicado a toda a lista for divisível por 10 .

Mr. Xcoder
fonte
Ainda 9 bytes, mas com valores consistentes:JḂḤ‘×µS⁵ḍ
HyperNeutrino 15/17
@HyperNeutrino Obrigado, eu sabia que havia um átomo para isso!
Sr. Xcoder 15/11
Também 9 bytes:: JḂaḤ+µS⁵ḍP
HyperNeutrino 15/11
@HyperNeutrino Bem, existem muitas alternativas: P
Sr. Xcoder 15/11
1
8 bytes ou 8 caracteres? m2Ḥ+µS⁵ḍtem 15 bytes em UTF-8, a menos que eu tenha calculado errado.
ta.speot.is
7

MATL , 10 bytes

Obrigado a @ Zgarb por apontar um erro, agora corrigido.

IlhY"s10\~

Experimente online! Ou verifique todos os casos de teste .

Explicação

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

Befunge-98 (PyFunge) , 16 14 bytes

Gravadas 2 bytes por pular a segunda parte usando jem vez de ;s, bem como a troca de um ~e +na primeira parte para se livrar de um +no segundo.

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

A entrada está em 8 dígitos (com 0s iniciais, se aplicável) e nada mais.

Saídas via código de saída (abra o menu suspenso de depuração no TIO), onde 1 é verdadeiro e 0 é falso.

Experimente online!

Explicação

Este programa usa uma variedade de truques.

Primeiro de tudo, ele leva os dígitos um por um através de seus valores ASCII. Normalmente, isso exigiria subtrair 48 de cada valor à medida que o lemos da entrada. No entanto, se não o modificarmos, ficaremos com 16 (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1) cópias extras de 48 em nossa soma, o que significa que nosso total será 768 maior que o que "deveria" ser. Como estamos preocupados apenas com a soma mod 10, podemos adicionar 2 à soma posteriormente. Assim, podemos obter valores ASCII brutos, economizando 6 bytes ou mais.

Em segundo lugar, esse código verifica apenas se todos os outros caracteres são EOF, porque a entrada é garantida para ter apenas 8 caracteres.

Em terceiro lugar, o #final da linha não pula o primeiro caractere, mas pula o ;que vem da outra direção. É melhor do que colocar um #;na frente.

Como a segunda parte do nosso programa é executada apenas uma vez, não precisamos configurá-lo para que ele pule a primeira metade ao retroceder. Isso nos permite usar o comando jump para pular a segunda metade, quando saímos antes de executá-lo para trás.

Passo a passo

Nota: Os caracteres "Ímpar" e "Par" são baseados em um sistema indexado em 0. O primeiro caractere é par, com o índice 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
fonte
6

C,  78  bytes

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

Experimente online!

C (gcc), 72 bytes

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

Experimente online!

Steadybox
fonte
6

Wolfram Language (Mathematica) , 26 21 bytes

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

Experimente online!

Recebe a entrada como uma lista de 8 dígitos.

Como funciona

2-9^Range@8é o módulo 10 congruente para 2-(-1)^Range@8, que é {3,1,3,1,3,1,3,1}. Pegamos o produto escalar desta lista com a entrada e verificamos se o resultado é divisível por 10.

Wolfram Language (Mathematica) , 33 bytes e não concorrentes

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

Experimente online!

Recebe a entrada como uma sequência. Retorna 1códigos de barras válidos e 0inválidos.

Como funciona

A melhor coisa que eu poderia encontrar no caminho de um built-in (já que o Mathematica é sobre isso).

O bit interno #~BarcodeImage~"EAN8";1, gera uma imagem do código de barras EAN8, depois a ignora completamente e avalia como 1. No entanto, se o código de barras for inválido, BarcodeImagegera um aviso que é Checkcapturado, retornando 0 nesse caso.

Misha Lavrov
fonte
3
Você está fazendo o cálculo manualmente porque é mais curto ou porque o Wolfram ainda não tem uma função ValidateEAN8BarCode () em algum lugar de sua biblioteca padrão?
Mark
1
O @Mark Mathematica não pode validar o código de barras diretamente, mas acabei de encontrar BarcodeImage, que gera a imagem do código de barras e valida o código de barras no processo. Então Check[#~BarcodeImage~"EAN8";0,1]<1&funcionaria (mas é mais longo).
Misha Lavrov
5

Java 8, 58 56 55 bytes

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

-2 bytes indiretamente, graças a @RickHitchcock , usando em (m=4-m)*ivez de m++%2*2*i+idepois de vê-lo em sua resposta JavaScript .
-1 byte indiretamente, graças a @ETHProductions (e @RickHitchcock ), usando em (m^=2)*ivez de (m=4-m)*i.

Explicação:

Experimente aqui.

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
fonte
1
Você pode salvar outro byte com um truque que @ETHProductions me mostrou: mude m=4-mpara m^=2.
21717 Ricky Hitchcock #
@ RickHitchcock Ah, é claro. Eu uso ^=1bastante as respostas quando quero alterar entre 0e 1. ^=2funciona neste caso para alterar entre 1e 3. Bom truque, e obrigado pelo comentário para mencioná-lo. :)
Kevin Cruijssen
4

05AB1E , 14 bytes

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

Experimente online!

Precisa de 0s iniciais , pega a lista de dígitos.

Erik, o Outgolfer
fonte
Parece falhar 3100004(deve ser verdade).
Zgarb
@ Zgarb Está faltando um 0lá.
Erik the Outgolfer
Oh, é preciso uma corda? Ok, então, meu mal.
Zgarb
@ Zgarb Bem, você pode omitir as aspas, mas sim, você precisa da liderança 0. Esta resposta realmente usa funções numéricas em strings, um dos recursos do 05AB1E.
Erik the Outgolfer
@ Mr.Xcoder A questão não é muito clara, acrescentarei outro código que lida com isso abaixo.
Erik the Outgolfer
4

Pitão , 8 bytes

!es+*2%2

Verifique todos os casos de teste!

Pitão , 13 bytes

Se pudermos supor que a entrada sempre tenha exatamente 8 dígitos:

!es.e*bhy%hk2

Verifique todos os casos de teste!


Como é que isso funciona?

! es + * 2% 2 ~ Programa completo.

      % 2 ~ Entrada [:: 2]. Cada segundo elemento da entrada.
    * 2 ~ Duplo (repita a lista duas vezes).
   + ~ Anexe a entrada.
  s ~ Sum.
 e ~ Último dígito.
! ~ Lógico NÃO.
! es.e * sbhy% hk2 ~ Programa completo.

               ~ Converta a entrada em uma String.
   .e ~ Mapa enumerado, armazenando o valor atual em be o índice em k.
          % hk2 ~ Paridade invertida do índice. (k + 1)% 2.
        hy ~ Duplo, incremento. Mapeia números inteiros ímpares para 1 e pares pares para 3.
      b ~ O dígito atual.
     * ~ Multiplique.
  s ~ Sum.
 e ~ Último dígito.
! Negação lógica.

Se a soma dos 7 primeiros dígitos após a aplicação, o algoritmo for subtraído de 10 e depois comparado ao último dígito, isso equivale a verificar se a soma de todos os dígitos após a aplicação do algoritmo é um múltiplo de 10 .

Mr. Xcoder
fonte
Parece falhar 3100004(deve ser verdade).
Zgarb
@ Zgarb Espere devemos fazer 3*3+1*1+0*3+...ou 0*3+3*1+1*0..? Eu pensei que nós deveríamos fazer o primeiro.
Sr. Xcoder 15/11
Na nova especificação, os dígitos iniciais são adicionados para garantir que haja exatamente 8 (se bem entendi).
Zgarb
@ Zgarb Ok, corrigido.
Mr. Xcoder
4

Haskell , 40 38 bytes

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

Experimente online!

Leva a entrada como uma lista de 8 números inteiros. Um exemplo prático de uso de listas infinitas.

Editar: salvou 2 bytes graças ao GolfWolf

butterdogs
fonte
2
Usar uma definição recursiva em vez de cycle salvar 2 bytes .
Cristian Lupascu
4

Retina , 23 22 bytes

-1 byte graças a Martin Ender !

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

Experimente online!

Explicação

Exemplo de entrada: 20378240

(.).
$1$1$&

Substitua cada par de dígitos pelo primeiro dígito repetido duas vezes, seguido pelo próprio par. Nós temos2220333788824440

.
$*

Converta cada dígito em unário. Com parênteses adicionados para maior clareza, obtemos(11)(11)(11)()(111)(111)...

M`

Conte o número de correspondências da cadeia vazia, que é uma a mais que o número de unidades na cadeia. (Com as duas últimas etapas, basicamente tomamos a soma de cada dígito +1) Resultado:60

1$

Combine a 1no final da sequência. Nós multiplicamos os dígitos por 3 e 1 alternadamente e os somamos; para um código de barras válido, este deve ser divisível por 10 (último dígito 0); mas também adicionou 1 na última etapa, por isso queremos o último dígito para ser 1. Resultado final: 1.

Leo
fonte
2
Eu acho que você pode jogar .no estádio e 1$no final.
Martin Ender
@ Martinart muito bom, eu vou fazer isso, obrigado!
Leo
3

PowerShell , 85 bytes

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

Experimente online! ou Verifique todos os casos de teste

Implementa o algoritmo conforme definido. Pega entrada $a, puxa cada dígito com "$a"[0..6]e passa por eles com |%{...}. A cada iteração, pegamos o dígito, convertemos como string e, em "$_"seguida, como int +antes de multiplicá-lo por um 3ou 1(escolhido pelo incremento do $imódulo 2).

Esses resultados são todos reunidos e resumidos -join'+'|iex. Nós pegamos esse mod de resultado 10, subtraímos isso de 10e, novamente, pegamos o mod de resultado 10(este segundo mod é necessário para explicar o 00000000caso de teste). Em seguida, verificamos se esse é -eqo último dígito. Esse resultado booleano é deixado no pipeline e a saída é implícita.

AdmBorkBork
fonte
Parece falhar 3100004(deve ser verdade).
Zgarb
@Zgarb Funciona para mim? Experimente online!
AdmBorkBork
Ah ok, eu testei sem as aspas.
Zgarb
@ Zgarb Ah, sim. Sem as aspas, o PowerShell converterá implicitamente como um número inteiro, eliminando o (s) zero (s) inicial (is).
AdmBorkBork
3

Gelatina , 16 bytes

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

Experimente online!

recebe entrada como uma lista de dígitos

HyperNeutrino
fonte
Nitpick: seus tempos limite de TIO. Além disso, 16 bytes .
Erik o Outgolfer
@EriktheOutgolfer Espere como. Funciona quando coloco o Dno rodapé. E sim obrigado! : D
HyperNeutrino
@EriktheOutgolfer Estou fazendo algo errado? Seu 16-byter parece ser inválido?
HyperNeutrino
Talvez, funcione de maneira diferente, mas a sua também parece um pouco inválida ... especificamente, acho que a última linha deve ser DµṪ=Ç.
Erik o Outgolfer
1
Parece falhar 3100004(deve ser verdade).
Zgarb
3

APL (Dyalog) , 14 bytes

Equivalente à solução de ruas .

Corpo do programa completo. Solicita a lista de números do STDIN.

0=10|+/⎕×83 1

Experimente online!

É…

0= zero igual a

10| o mod-10 de

+/ a soma de

⎕× os tempos de entrada

8⍴3 1 oito elementos retirados ciclicamente [3,1]

?

Adão
fonte
1
Você quer dizer que o APL não pode fazê-lo em um personagem de algo como Sumério Antigo ou Linear B?
Mark
train: 0 = 10 | - / + 2 × + /
ngn
3

05AB1E , 9 bytes

3X‚7∍*OTÖ

Experimente 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
fonte
Agradável! A primeira coisa que pensei foi "estender ao comprimento" quando vi isso, ainda não o usei.
Magic Octopus Urn
31×S*OTÖpor 8 bytes. ×apenas empurra 31 nvezes. Quando você multiplica, diminui automaticamente os 31 extras.
Magic Octopus Urn
@MagicOctopusUrn Isso parece falhar no sexto teste #69165430 -> 1
kalsowerus 17/17/17
3

J, 17 bytes

-10 bytes graças a cole

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

Experimente online!

Isso usa a multiplicação de listas de tamanhos iguais para evitar a combinação de zip / multiplicar da solução original, bem como o "truque base 1" 1#.para adicionar os produtos. A abordagem de alto nível é semelhante à explicação original.

original, 27 bytes

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

Experimente online!

explicado

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
fonte
0=10|1#.(8$3 1)*]deve funcionar com 17 bytes (também funciona com o mesmo algoritmo). Estou bastante certo de que no beta você pode ter um gancho terminou no lado direito com um substantivo, por isso 0=10|1#.]*8$3 1pode funcionar para 15 (eu verificar tio, mas ele parece estar em baixo?)
cole
@ Cole, eu amo essa melhoria. Eu aprendi e esqueci o 1#.truque duas ou três vezes ... obrigado por me lembrar. Oh, a versão de 15 bytes não funcionou no 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 de Neil

-7 bytes de Nahuel Fouilleul

Experimente online!

Desenvolvido independentemente de resposta Steadybox

'f' é uma função que usa o código de barras como um inte retorna 1para True e 0para False.

  • farmazena o último dígito de xem s( s=x%10),

  • Em seguida, calcula a soma em c( for(i=c=0;x;x/=10)c+=(1+2*i++%4)*x;)

    • cé a soma, ié um contador

    • para cada dígito incluindo o primeiro, adicione 1+2*i%4vezes o dígito ( x%10) para a soma de verificação e incremento i(o i++no 3-2*i++%4)

      • 1+2*i%4é 1 quando ié par e 0 quando ié ímpar
  • Em seguida, retorna se a soma é um múltiplo de dez e, como adicionamos o último dígito (multiplicado por 1), a soma será um múltiplo de dez se o código de barras for válido. (usa o comportamento indefinido dependente do GCC para omitir return).

pizzapants184
fonte
Eu acho que (x%10)pode ser xcomo você está tomando c%10depois de qualquer maneira. Também acho que você pode usar i<8e depois testar se c%10é zero no final.
Neil
@ Neil Thanks! Isso tem -10 bytes.
pizzapants184
Na verdade eu acho que sé desnecessário:c;i;f(x){for(i=c=0;i<8;x/=10)c+=(1+2*i++%4)*x;return c%10<1;}
Neil
a ligação tio é de 61 bytes, mas a resposta é 72, também não sei por que x=c%10<1ou c=c%10<1em vez de return c%10<1ainda funciona
Nahuel FOUILLEUL
também i<8pode ser substituído porx
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;}

Assume que 0étrue e qualquer outro valor é false.

+3 bytes para melhor valor de retorno

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

Adicionar ==0 à returndeclaração.

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
}

Isso usa a definição alternativa de somas de verificação EAN, onde o dígito de verificação é escolhido de forma que a soma de verificação de todo o código de barras, incluindo o dígito de verificação, seja um múltiplo de 10. Matematicamente, isso funciona da mesma maneira, mas é muito mais simples de escrever.

Inicializando variáveis ​​dentro do loop, conforme sugerido pelo Steadybox, 63 bytes

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

Removendo colchetes como sugerido por Steadybox, 61 bytes

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

Usando em <1vez de ==0obter um melhor valor de retorno, conforme sugerido por Kevin Cruijssen

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

Adicione <1à returninstrução, isso adiciona apenas 2 bytes em vez de adicionar, o ==0que adiciona 3 bytes.

Micheal Johnson
fonte
Você pode salvar dois bytes removendo o {}depois do for. Além disso, os envios de funções precisam ser reutilizáveis ; portanto, você precisa inicializar sdentro da função (basta alterar i;s=0;para i,s;e i=0;para i=s=0;).
Steadybox
@Steadybox Como posso remover os colchetes?
precisa
Há apenas uma declaração dentro deles. Quando não houver colchetes depois for, o corpo do loop será a próxima instrução. for(i=0;i<8;i++){s+=v[i]*3+v[++i];}é o mesmo que for(i=0;i<8;i++)s+=v[i]*3+v[++i];.
Steadybox
@Steadybox Oh, claro. Essa é uma das peculiaridades da sintaxe C que eu geralmente esqueço, porque ao escrever o código normal, sempre incluo os colchetes, mesmo que desnecessários, porque isso torna o código mais legível.
precisa
Na sua resposta verdadeira / falsa, em vez de adicionar +3 ==0, pode ser +2 usando <1. :)
Kevin Cruijssen
2

JavaScript (Node.js) , 47 bytes

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

Embora já exista uma resposta muito mais curta, esta é a minha primeira tentativa de jogar golfe em JavaScript, então eu gostaria de ouvir as recomendações de golfe :-)

Teste

Como alternativa, você pode experimentá-lo online!

Mr. Xcoder
fonte
2

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

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

-5 bytes graças a Dom Hastings. 37 bytes +1 eram

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

experimente online

Nahuel Fouilleul
fonte
1
Brinquei um pouco com isso e pensei em compartilhar um truque útil: --$|alterna entre 1e 0para que você possa usá-lo em vez de usar ++$i%2um booleano alternado! Além disso, tudo o que importa é que o total ( $s) corresponda /0$/, conseguiu obter 33 bytes combinando essas alterações com s///: Experimente online! ( -lé apenas para visibilidade)
Dom Hastings
Sim, eu pensei em combinar s/./(something with $&)/gee /0$/combinar, mas não os dois.
Nahuel FOUILLEUL
2

Brainfuck, 228 bytes

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

Provavelmente pode ser melhorado um pouco. A entrada é obtida 1 dígito de cada vez, gera 1 para verdadeiro, 0 para falso.

Como funciona:

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

Coloque 8 na posição 3.

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

Leva 8 vezes a entrada, alterando-o do valor ascii para o valor real +2 a cada vez. As entradas são espaçadas por outras que serão removidas, para facilitar a multiplicação mais tarde.

>[->]

Subtraia um de cada item. Nossa fita agora parece algo como

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

Com cada valor 1 mais do que deveria. Isso ocorre porque os zeros atrapalham nosso processo de multiplicação.

Agora estamos prontos para começar a multiplicar.

<<<<

Vá para o penúltimo item.

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

Enquanto zero, multiplique o item em três e mova dois itens para a esquerda. Agora multiplicamos tudo o que precisávamos por três e estamos na primeira posição na fita.

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

Soma a lista inteira.

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

O valor que temos é 16 a mais que o valor real. Corrija isso subtraindo 16.

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

Precisamos testar se a soma é um múltiplo de 10. A soma máxima é de todos os 9s, que é 144. Como nenhuma soma será maior que 10 * 15, coloque 15 e 10 na fita, nessa ordem e no direito de o direito da soma.

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

Vá para onde 15 é. Embora seja diferente de zero, teste se a soma é diferente de zero. Se for, subtraia 10 dele. Agora estamos na posição de soma (vazia) ou na posição (também vazia) de dez. Mova um para a direita. Se estivéssemos na posição de soma, agora estamos na posição 15 diferente de zero. Nesse caso, mova para a direita duas vezes. Agora estamos na mesma posição nos dois casos. Adicione dez à posição dez e subtraia um da posição 15.

O restante é para saída:

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

Mover para a posição da soma. Se for diferente de zero (negativo), o código de barras é inválido; defina a posição para -1. Agora adicione 49 para obter o valor ASCII correto: 1 se for válido, 0 se for inválido.

Bolce Bussiere
fonte
2

Java 8, 53 bytes

Golfe:

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

O cálculo direto no lambda parece ser a solução mais curta. Ele se encaixa em uma única expressão, minimizando a sobrecarga lambda e removendo declarações de variáveis ​​estranhas e ponto e vírgula.

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

Saída:

[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

fonte
2

QBasic, 54 52 bytes

Ugh, a resposta chata acabou sendo a mais curta:

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

Isso insere os dígitos separados por vírgula. Minha solução original de 54 bytes, que insere um dígito de cada vez, usa uma abordagem "melhor":

m=3
FOR i=1TO 8
INPUT d
s=s+d*m
m=4-m
NEXT
?s MOD 10=0
DLosc
fonte
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;}

Experimente online!

Agradecimentos

-3 bytes graças a @KevinCruijssen e o truque interessante usando o operador exclusivo-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 bytes

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

Experimente online!

Uma porta direta da resposta de @ Snowman .

Ayb4btu
fonte
Para sua primeira resposta: b=>{int s=0,i=0,t=1;while(i<8)s+=b[i++]*(t^=2);return s%10<1;}( 62 bytes ), ou alternativamente com um foreach, também 62 bytes: b=>{int s=0,t=1;foreach(int i in b)s+=i*(t^=2);return s%10<1;}(que é uma porta da minha resposta Java 8 ).
Kevin Cruijssen
1

MATLAB / oitava , 32 bytes

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

Experimente online!

Vou postar isso, apesar da outra resposta da Oitava, à medida que desenvolvi esse código e abordagem, sem olhar para as outras respostas.

Aqui temos uma função anônima que recebe a entrada como uma matriz de 8 valores e retorna true se um código de barras válido, caso contrário, false.

O resultado é calculado da seguinte maneira.

              2*x(1:2:7)
             [          ,x]
         sum(              )
     mod(                   ,10)
@(x)~
  1. Dígitos ímpares (um indexado) são multiplicados por 2.
  2. O resultado é anexado à matriz de entrada, fornecendo uma matriz cuja soma conterá os dígitos ímpares três vezes e os dígitos pares uma vez.
  3. Fazemos a soma que também incluirá a soma de verificação fornecida em nossa soma.
  4. Em seguida, o módulo 10 é realizado. Se a soma de verificação fornecida fosse válida, a soma de todos os dígitos multiplicados, incluindo o valor da soma de verificação, acabaria sendo um múltiplo de 10. Portanto, apenas um código de barras válido retornaria 0.
  5. O resultado é invertido para obter uma saída lógica de true se válido.
Tom Carpenter
fonte
1

Excel, 37 bytes

Interpretando "Uma lista de 8 números inteiros" como permitindo 8 células separadas no Excel:

=MOD(SUM(A1:H1)+2*(A1+C1+E1+G1),10)=0
Wernisch
fonte
= MOD (SOMA ((A1: H1) + 2 * (A1 + C1 + E1 + G1))), 10) = 0 esta fórmula existe no Excel?
RosLuP
@RosLuP, não predefinido, não. Mas Modulo, Sum, + etc fazer ;-)
Wernisch
Quero apenas dizer que parece que no APL vai bem fazendo primeiro y = (A1: H1) + 2 * (A1 + C1 + E1 + G1), e depois da soma e do mod; em APL não vai bem primeira soma (A1: H1) etc algo como (1,2,3) + 4 = (5,6,7) e que soma (5,6,7) = 18; nota que soma (1,2,3) = 6 e 6 + 4 = 10 diferente de 18. Mas possível erro I make em alguma coisa
RosLuP
O @RosLuP, desculpas, perdeu as alterações ()no seu comentário.
Wernisch
O problema é como o Excel interpreta =(A1:H1): Isso não é tratado como uma matriz. É inválido se colocado em qualquer coluna fora do A-Hintervalo. Se colocado em uma coluna no AH, retorna o valor apenas para essa coluna. (A fórmula em% resulta em%: C2 -> C1 H999 -> H1 K1 -> #VALUE!)
Wernisch 24/11
1

Ruby, 41 bytes

Toma uma matriz de números inteiros. -6 bytes graças à Jordânia.

->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
Mostrar nome
fonte
Agradável! FWIW você não precisa mapaqui: zipleva um bloco. Você pode salvar mais alguns bytes usando, em $.vez de inicializar s:->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
Jordan
1

TI-Basic (série 83), 18 bytes

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

Leva a entrada como uma lista em Ans. Retorna 1códigos de barras válidos e 0inválidos.

Um porto do meu resposta do Mathematica . Inclui captura de tela, em vez de um ambiente de teste on-line:

barcode screenshot

Recurso notável: binomcdf(7,0é usado para gerar a lista {1,1,1,1,1,1,1,1}(a lista de probabilidades de que, em 7 tentativas com probabilidade de sucesso 0, haverá no máximo N sucessos, para N = 0,1, ..., 7). Então, cumSum(transforma isso em {1,2,3,4,5,6,7,8}.

Este é um byte menor que o seq(comando, embora historicamente o ponto seja que também seja significativamente mais rápido.

Misha Lavrov
fonte