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 é código-golfe , 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
code-golf
arithmetic
decision-problem
integer
checksum
FlipTack
fonte
fonte
Respostas:
Geléia , 7 bytes
Experimente online!
Como funciona
fonte
JavaScript (ES6),
414038 bytesEconomizou 2 bytes graças a @ETHProductions e 1 byte graças a @Craig Ayre.
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
Mostrar snippet de código
fonte
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 ...map
, o que acho que funciona melhor, pois a entrada pode ser uma lista de dígitos em vez de uma string.s=>s.map(e=>t+=e*(i=4-i),t=i=1)&&t%10==1
?&&
com|
a saída 1/0, pois a verdade / falsidade é permitida?Python 2 ,
64483529 bytesmypetlion salvou 19 bytes
Experimente online!
fonte
lambda x:sum(x[::2]*3+x[1::2])%10<1
Para 35 bytes.lambda x:sum(x[::2]*2+x)%10<1
Para 29 bytes.Geléia , 8 bytes
Experimente a suíte de testes.
Geléia , 9 bytes
Experimente online ou Experimente a suíte de testes.
Como isso funciona
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 .
fonte
JḂḤ‘×µS⁵ḍ
JḂaḤ+µS⁵ḍ
Pm2Ḥ+µS⁵ḍ
tem 15 bytes em UTF-8, a menos que eu tenha calculado errado.MATL , 10 bytes
Obrigado a @ Zgarb por apontar um erro, agora corrigido.
Experimente online! Ou verifique todos os casos de teste .
Explicação
fonte
Befunge-98 (PyFunge) ,
1614 bytesGravadas 2 bytes por pular a segunda parte usando
j
em vez de;
s, bem como a troca de um~
e+
na primeira parte para se livrar de um+
no segundo.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.
fonte
C,
78bytesExperimente online!
C (gcc), 72 bytes
Experimente online!
fonte
Wolfram Language (Mathematica) ,
2621 bytesExperimente online!
Recebe a entrada como uma lista de 8 dígitos.
Como funciona
2-9^Range@8
é o módulo 10 congruente para2-(-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
Experimente online!
Recebe a entrada como uma sequência. Retorna
1
códigos de barras válidos e0
invá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,BarcodeImage
gera um aviso que éCheck
capturado, retornando 0 nesse caso.fonte
BarcodeImage
, que gera a imagem do código de barras e valida o código de barras no processo. EntãoCheck[#~BarcodeImage~"EAN8";0,1]<1&
funcionaria (mas é mais longo).Java 8,
585655 bytes-2 bytes indiretamente, graças a @RickHitchcock , usando em
(m=4-m)*i
vez dem++%2*2*i+i
depois de vê-lo em sua resposta JavaScript .-1 byte indiretamente, graças a @ETHProductions (e @RickHitchcock ), usando em
(m^=2)*i
vez de(m=4-m)*i
.Explicação:
Experimente aqui.
fonte
m=4-m
param^=2
.^=1
bastante as respostas quando quero alterar entre0
e1
.^=2
funciona neste caso para alterar entre1
e3
. Bom truque, e obrigado pelo comentário para mencioná-lo. :)05AB1E , 14 bytes
Experimente online!
Precisa de
0
s iniciais , pega a lista de dígitos.fonte
3100004
(deve ser verdade).0
lá.0
. Esta resposta realmente usa funções numéricas em strings, um dos recursos do 05AB1E.Pitão , 8 bytes
Verifique todos os casos de teste!
Pitão , 13 bytes
Se pudermos supor que a entrada sempre tenha exatamente 8 dígitos:
Verifique todos os casos de teste!
Como é que isso funciona?
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 .
fonte
3100004
(deve ser verdade).3*3+1*1+0*3+...
ou0*3+3*1+1*0..
? Eu pensei que nós deveríamos fazer o primeiro.Haskell ,
4038 bytesExperimente 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
fonte
cycle
salvar 2 bytes .Retina ,
2322 bytes-1 byte graças a Martin Ender !
Experimente online!
Explicação
Exemplo de entrada:
20378240
Substitua cada par de dígitos pelo primeiro dígito repetido duas vezes, seguido pelo próprio par. Nós temos
2220333788824440
Converta cada dígito em unário. Com parênteses adicionados para maior clareza, obtemos
(11)(11)(11)()(111)(111)...
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
Combine a
1
no 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
.fonte
.
no estádio e1$
no final.PowerShell , 85 bytes
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 um3
ou1
(escolhido pelo incremento do$i
módulo2
).Esses resultados são todos reunidos e resumidos
-join'+'|iex
. Nós pegamos esse mod de resultado10
, subtraímos isso de10
e, novamente, pegamos o mod de resultado10
(este segundo mod é necessário para explicar o00000000
caso de teste). Em seguida, verificamos se esse é-eq
o último dígito. Esse resultado booleano é deixado no pipeline e a saída é implícita.fonte
3100004
(deve ser verdade).Gelatina , 16 bytes
Experimente online!
recebe entrada como uma lista de dígitos
fonte
D
no rodapé. E sim obrigado! : DDµṪ=Ç
.3100004
(deve ser verdade).APL (Dyalog) , 14 bytes
Equivalente à solução de ruas .
Corpo do programa completo. Solicita a lista de números do STDIN.
Experimente online!
É…
0=
zero igual a10|
o mod-10 de+/
a soma de⎕×
os tempos de entrada8⍴3 1
oito elementos retirados ciclicamente[3,1]
?
fonte
05AB1E , 9 bytes
Experimente online!
fonte
31×S*OTÖ
por 8 bytes.×
apenas empurra 31n
vezes. Quando você multiplica, diminui automaticamente os 31 extras.69165430 -> 1
J, 17 bytes
-10 bytes graças a cole
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
Experimente online!
explicado
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 isso0=10|1#.]*8$3 1
pode funcionar para 15 (eu verificar tio, mas ele parece estar em baixo?)1#.
truque duas ou três vezes ... obrigado por me lembrar. Oh, a versão de 15 bytes não funcionou no TIO.C (gcc),
8482726154 bytes-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
int
e retorna1
para True e0
para False.f
armazena o último dígito dex
ems
(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 contadorpara cada dígito incluindo o primeiro, adicione
1+2*i%4
vezes o dígito (x%10
) para a soma de verificação e incrementoi
(oi++
no3-2*i++%4
)1+2*i%4
é 1 quandoi
é par e 0 quandoi
é ímparEm 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
).fonte
(x%10)
pode serx
como você está tomandoc%10
depois de qualquer maneira. Também acho que você pode usari<8
e depois testar sec%10
é zero no final.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;}
x=c%10<1
ouc=c%10<1
em vez dereturn c%10<1
ainda funcionai<8
pode ser substituído porx
C, 63 bytes
Assume que
0
étrue
e qualquer outro valor éfalse
.+3 bytes para melhor valor de retorno
Adicionar
==0
àreturn
declaração.Ungolfed
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
Removendo colchetes como sugerido por Steadybox, 61 bytes
Usando em
<1
vez de==0
obter um melhor valor de retorno, conforme sugerido por Kevin CruijssenAdicione
<1
àreturn
instrução, isso adiciona apenas 2 bytes em vez de adicionar, o==0
que adiciona 3 bytes.fonte
{}
depois dofor
. Além disso, os envios de funções precisam ser reutilizáveis ; portanto, você precisa inicializars
dentro da função (basta alterari;s=0;
parai,s;
ei=0;
parai=s=0;
).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 quefor(i=0;i<8;i++)s+=v[i]*3+v[++i];
.==0
, pode ser +2 usando<1
. :)JavaScript (Node.js) , 47 bytes
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
Mostrar snippet de código
Como alternativa, você pode experimentá-lo online!
fonte
Perl 5,
3732 + 1 (-p) bytes-5 bytes graças a Dom Hastings. 37 bytes +1 eram
experimente online
fonte
--$|
alterna entre1
e0
para que você possa usá-lo em vez de usar++$i%2
um booleano alternado! Além disso, tudo o que importa é que o total ($s
) corresponda/0$/
, conseguiu obter 33 bytes combinando essas alterações coms///
: Experimente online! (-l
é apenas para visibilidade)s/./(something with $&)/ge
e/0$/
combinar, mas não os dois.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
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.
fonte
Java 8, 53 bytes
Golfe:
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.
Saída:
fonte
QBasic,
5452 bytesUgh, a resposta chata acabou sendo a mais curta:
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":
fonte
C # (.NET Core) ,
6562 bytesExperimente online!
Agradecimentos
-3 bytes graças a @KevinCruijssen e o truque interessante usando o operador exclusivo-or.
DeGolfed
C # (.NET Core) , 53 bytes
Experimente online!
Uma porta direta da resposta de @ Snowman .
fonte
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 ).MATLAB / oitava , 32 bytes
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.
fonte
Excel, 37 bytes
Interpretando "Uma lista de 8 números inteiros" como permitindo 8 células separadas no Excel:
fonte
()
no seu comentário.=(A1:H1)
: Isso não é tratado como uma matriz. É inválido se colocado em qualquer coluna fora doA-H
intervalo. 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!)Ruby, 41 bytes
Toma uma matriz de números inteiros. -6 bytes graças à Jordânia.
fonte
map
aqui:zip
leva um bloco. Você pode salvar mais alguns bytes usando, em$.
vez de inicializars
:->n{n.zip([3,1]*4){|x,y|$.+=x*y};$.%10<1}
TI-Basic (série 83), 18 bytes
Leva a entrada como uma lista em
Ans
. Retorna1
códigos de barras válidos e0
inválidos.Um porto do meu resposta do Mathematica . Inclui captura de tela, em vez de um ambiente de teste on-line:
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.fonte