Desafio
Escreva o programa ou a função mais curta para calcular o algoritmo Luhn para verificar os números (cartão de crédito).
Algoritmo de Luhn explicado
No RosettaCode , esse algoritmo para os objetivos deste desafio é especificado como tal, com a entrada de exemplo de 49927398716
:
Reverse the digits, make an array:
6, 1, 7, 8, 9, 3, 7, 2, 9, 9, 4
Double the numbers in odd indexes:
6, 2, 7, 16, 9, 6, 7, 4, 9, 18, 4
Sum the digits in each number:
6, 2, 7, 7, 9, 6, 7, 4, 9, 9, 4
Sum all of the numbers:
6 + 2 + 7 + 7 + 9 + 6 + 7 + 4 + 9 + 9 + 4 = 70
If the sum modulo 10 is 0, then the number is valid:
70 % 10 = 0 => valid
Regras de IO
Entrada : uma sequência ou número (sua escolha), no formato de entrada / saída de seu idioma preferido
Saída : Um valor verdadeiro ou falso , respectivamente, indicando se a entrada é válida ou não, de acordo com o teste acima.
Notas / Dicas
Tente não lançar acidentalmente seu próprio cartão de crédito ou números de conta, se você os usar para testar :)
Se a entrada for inválida e impossível de processar com o algoritmo especificado (ou seja, muito curto para trabalhar), você poderá fazer o que quiser, incluindo desligar meu computador.
No entanto , o marcador anterior não significa que seu idioma possa fazer o que quiser com números grandes demais para serem manipulados. Se seu idioma não for capaz de lidar com um caso de teste, considere usar uma string como entrada.
Exemplos
Os exemplos a seguir foram validados com este script Python ; se você acha que alguém está errado ou tem uma pergunta, basta executar ping @cat.
49927398716 True
49927398717 False
1234567812345670 True
1234567812345678 False
79927398710 False
79927398711 False
79927398712 False
79927398713 True
79927398714 False
79927398715 False
79927398716 False
79927398717 False
79927398718 False
79927398719 False
374652346956782346957823694857692364857368475368 True
374652346956782346957823694857692364857387456834 False
8 False **
0 True **
** de acordo com a implementação do Python, mas você pode fazer qualquer coisa, porque estas são muito curtas para serem elegíveis por uma aderência estrita à especificação.
Se qualquer uma das opções acima invalida as respostas existentes (embora eu acredite que isso não seja possível), essas respostas ainda são válidas. No entanto, novas respostas, para serem válidas, devem seguir a especificação acima.
Entre os melhores
var QUESTION_ID=22,OVERRIDE_USER=73772;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
echo -n
-1% 2/
pode ser combinado em-2/
.1,
pode ser substituído por0
(0 é coagido a uma matriz e+
concatenado).9>9*-
pode ser substituído por9>+
(já que estamos preocupados apenas com o último dígito). Além disso, a verificação de comprimentos ímpares é um pouco longa, o uso.,2%,\+
é mais curto. Depois de fazer isso, também podemos mudar{16%}%
e(\0=
em{16}/
(dentro do loop). Depois de ter feito tudo isso, ele vai ser algo como isto:.,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!
.Python,
7369 caracteresfonte
D[-2::-2]
->D[1::2]
como o fim de uma soma não é importante :)==0
pode ser reduzido para<1
Python 3, 77 bytes
fonte
Caracteres C # 119:
Não é tão ruim para um código de golfe n00b em uma linguagem estaticamente tipada, espero.
Isso pode ser reduzido para 100 :
fonte
i%2<1?1:2
trás para a frente. Obrigado.Golfscript - 34 caracteres
Número de exemplo da página da wikipedia 4992739871
fonte
.+(9%)
é muito inovador (para mim, pelo menos). Eu gosto! +10(9%)
é 9 e não 0).PHP, 108 bytes
fonte
Ruby - 85 caracteres
fonte
Haskell, 96 bytes
Deve haver uma maneira melhor / mais curta, mas eis a minha solução Haskell em 96 caracteres :
Infelizmente, a
digitToInt
função só pode ser usada se vocêimport Data.Char
primeiro. Caso contrário, eu poderia diminuir para 88 caracteres substituindo((+(-48)).fromEnum)
pordigitToInt
.fonte
Windows PowerShell, 82
História:
+1 + +3
ainda pode ser avaliado.fonte
Q, 63
uso
fonte
{0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)
uma maneira diferente de duplicar os índices ímpares.D, 144 bytes
Mais legível:
fonte
APL, 28 bytes
Vista expandida
Exemplos
fonte
{0=10|+/⍎¨∊⍕¨⍵×⌽2-2|⍳⍴⍵}⍎¨
PowerShell 123
fonte
Perl,
464241 bytesInclui +1 para
-p
Dê entrada no STDIN:
luhn.pl
:fonte
$=-=-$&-$&*/\G(..)+$/
?0..4
* 2 fornece0, 2, 4, 6, 8
mas5..9
fornece10,12,14,16,18
qual soma1 3 5 7 9
possui os mesmos últimos dígitos e11 13 15 17 19
quais são os mesmos valores como0..9 * 2.2
se você truncar para inteiro. O primeiro$&
já contribui com um fator1
, portanto1.2
ainda é necessária uma correção por .$=
só pode conter números inteiros e começa com um valor que termina em 0, para cuidar do truncamento. Os valores negativos são necessários uma vez que a/\G/
regex altera qualquer$&
ainda na pilha de avaliação para que eles precisam de ser alteradasJavaScript (ES6), 61 bytes
Não concorrente, pois o JavaScript foi muito diferente em 2011.
A soma dos dígitos de
2*n
é2*n
sen in 0..4
,2*n-9
sen in 5..9
. Dito isto, toda a soma pode ser calculada em uma única etapa.fonte
Geléia ,
1211 bytesExperimente online! (com todos os casos de teste)
Como funciona
Como alternativa, para 12 bytes:
fonte
x86-16 ASM , IBM PC DOS, 23 bytes
Utiliza (abusa) a instrução BCD para binário do x86
AAM
para lidar com a divisão emodulo 10
verificação de dígitos individuais .Numero do cartão de entrada em ponteiro
SI
, comprimento emCX
. Saída:ZF
se válido.Exemplo de saída do programa de teste:
Faça o download do programa de teste LUHN.COM IBM PC DOS.
fonte
Scala: 132
invocação:
fonte
JavaScript 1.8: 106 caracteres
Esta é uma solução original que eu criei antes de encontrar este post:
Formulário legível:
fonte
K4, 35 bytes
fonte
Retina ,
4342 bytesA retina é (muito) mais nova que esse desafio.
A linha vazia principal é significativa.
Imprime
0
para obter1
resultados falsos e verdadeiros .Experimente online! (Ligeiramente modificado para executar todos os casos de teste de uma vez.)
Explicação
Insira
;
em todas as posições para separar dígitos.Desde a
r
noite, combinamos repetidamente dois dígitos e dobramos o esquerdo. Dessa forma, evitamos uma inversão cara da lista.Combinamos cada dígito e o convertemos em muitos
1
s (ou seja, convertemos cada dígito em unário).Isso corresponde a cada número unário e o converte novamente em decimal, substituindo-o pelo seu comprimento. Juntamente com o estágio anterior, isso adiciona os dígitos dobrados.
Novamente, combinamos todos os personagens e transformamos em muitos
1
s. Ou seja, convertemos cada dígito individualmente novamente em unário. Isso também corresponde aos;
separadores, que são tratados como zeros na conversão, o que significa que eles são simplesmente removidos. Como todos os números unários agora estão compactados, adicionamos automaticamente as representações unárias de todos os dígitos.No final, inserimos o comprimento de toda a cadeia, ou seja, a representação decimal da soma de verificação unária.
Finalmente, contamos o número de correspondências desse regex, ou seja, verificamos se a representação decimal termina em
0
, imprimindo0
ou em1
conformidade.fonte
Powershell, 74 bytes
Explicação
Script de teste
Resultado
fonte
05AB1E ,
1210 bytesExperimente online! ou como um conjunto de testes
Explicação
fonte
Haskell: 97
Por alguma razão, isso não está funcionando para mim , então aqui está minha versão
fonte
GNU sed, 140 bytes
(incluindo +1 para a
-r
bandeira)Sed quase nunca é a linguagem mais natural para a aritmética, mas aqui vamos nós:
fonte
APL, 38 bytes
espera o número como um número, não como uma string, mas é apenas porque o tryAPL (compreensivelmente) não implementa
⍎
mais redutível, tenho certeza ...
fonte
PHP - 136 caracteres
fonte
MATL ,
2320 bytes (não concorrente)Experimente online!
Saídas 1 para um número válido, 0 caso contrário.
Economizou três bytes graças às sugestões de Luis Mendo.
Explicação
fonte
Gelatina , 14 bytes
Experimente online!
Explicação:
fonte