Você recebe como entrada duas seqüências que representam números inteiros positivos na base 10, como "12345"
e "42"
. Sua tarefa é gerar uma string contendo o produto deles, "518490"
neste caso.
A desvantagem é que você não pode usar nenhum tipo numérico no seu código. Não ints
, float
s, unsigned long
s, etc., nenhum tipo de número complexo interno ou números inteiros de precisão arbitrários, ou qualquer coisa nesse sentido. Muitos não usam literais desses tipos, nem qualquer função, método, operador etc. que os retorne.
Você pode usar strings, booleanos, matrizes ou qualquer outra coisa que normalmente não seria usada para representar um número. (Mas observe que nem é provável que seja possível indexar em uma matriz nem obter seu comprimento sem chamar um tipo numérico.) char
S são permitidos, mas você não pode executar operações aritméticas ou bit a bit nelas ou tratá-las como qualquer outra coisa além de um token que representa parte de uma sequência. (A comparação lexicográfica de char
s é permitida.)
Você não pode contornar a restrição. Isso inclui (sem limitação) o uso de tipos numéricos dentro de uma eval
função de tipo, conversões implícitas de tipos em tipos numéricos, uso de operadores numéricos ou bit a bit em tipos não numéricos que os suportam, uso de tipos numéricos armazenados em tipos de contêiner ou funções de chamada ou programas externos que retornam resultados numéricos em forma de sequência. (Eu me reservo o direito de adicionar a esta lista se outras soluções alternativas aparecerem nas respostas.) Você deve implementar a multiplicação por conta própria usando apenas tipos não numéricos.
A entrada e a saída podem ser de qualquer método conveniente, desde que os dados entrem e saiam do seu código na forma de uma string. Você pode assumir que cada um dos dois argumentos de entrada contém apenas os caracteres ASCII [0-9]
e não será iniciado 0
. Sua saída também não deve ter zeros à esquerda.
Só mais uma coisa: o seu código deve lidar corretamente com entradas até , pelo menos, 10 caracteres de comprimento , e deve ser executado em menos de um minuto em um computador moderno para todas as entradas nesse intervalo. Antes de postar, verifique se, ao receber entradas 9999999999
e 9999999999
, seu programa fornece uma saída de 99999999980000000001
, em menos de um minuto. Essa restrição existe especificamente para impedir respostas que funcionem, alocando uma matriz de tamanho a*b
e, em seguida, repetindo-a; portanto, lembre-se de que as respostas desse formulário não serão elegíveis para vitória.
Isso é código-golfe , então a solução válida mais curta (em bytes) vence.
fonte
"12345"
do STDIN em vez de12345
? Ou podemos aceitar os dois números como"12345", "42"
?m
en
e retornando um argumento de comprimentom*n
. Mas como as strings precisam literalmente conter a representação ASCII dos números, acho que isso é contra as regras.a,b="0123456789x".split('0');c=iter(b).next()
if c=='x':
c='0'
a,b="0123456789x".split(x);c,*d=b
if c=='x':
c='0'
d='123456789';I=dict(zip('0'+d,d+'0'))
Respostas:
Haskell - 180
206 214Implementa a multiplicação por adição repetida e todos os tipos de magia de dígitos são manipulados deslocando e filtrando a
['0'..'9']
lista. Define um operador#
do tipoString -> String -> String
:fonte
"0123456789"
é a lista['0'..'9']
. Segundo, em Haskell [a..b] é uma enumeração, os tipos que declararam instâncias daEnum
classe de tipo podem ser enumerados assim, e a declaração descreve como a enumeração funciona.Bool
, o tipo booleano também possui uma instância e, portanto, você também pode fazê-lo[False..True]
. Quase não há números envolvidos.sed,
339338 bytesSei que é antigo, mas estava navegando e isso despertou meu interesse. O suficiente para realmente se registrar como usuário! Eu acho que fiquei impressionado com " eu gostaria de ver uma solução sed completa - Nathaniel " ...
Esse script sed espera dois números decimais como entrada, separados por um espaço
testes:
Você pode reconhecer os dois últimos como RSA-100 (50 x 50 dígitos) e RSA-768 (116 x 116 dígitos).
Usando o GNU sed em um não-moderno (Intel Core 2 da era de 2007), o último deles demora mais de um minuto, mas é mais rápido em um processador mais recente:
A multiplicidade insignificante de 10 dígitos especificada na pergunta leva bem menos de um segundo em qualquer uma delas (apesar de estar cheia de noves patológicos).
Eu acredito que é sed padrão, sem extensões. As garantias POSIX mantêm apenas 8192 bytes de espaço, o que nos limita à multiplicação de números de 400x400 dígitos, mas as implementações podem fornecer mais. O GNU sed é limitado apenas pela memória disponível; portanto, pode gerenciar algo muito maior, se você estiver disposto a esperar.
E estou confiante de que cumpri as regras - isso é quase um dado em um idioma que não tem números. :-)
Explicação
Eu uso um híbrido unário / decimal, convertendo números decimais em uma sequência de unário:
Em decimal unário, a adição é fácil. Nós iteramos do dígito menos significativo para o mais significativo, concatenando os x's:
Em seguida, removemos o espaço em branco e lidamos com carry convertendo 10 x consecutivos em uma das próximas unidades:
Uma vez que tenhamos adição, é possível multiplicar. Multiplicamos x * y considerando o último dígito de y. Adicione x ao acumulador várias vezes, depois vá para o próximo dígito e desloque x uma casa decimal à esquerda. Repita até y ser zero.
Código expandido
fonte
sed, 379 bytes
O crédito por essa resposta brilhante vai para @LuigiTiburzi no Unix e Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Acabei de tropeçar nisso há alguns dias:
Explicação geral
12*3
se torna<1<2*<3
|
caracteres. Assim<1<2*<3
se torna<|<||*<|||
|<
por<||||||||||
para mudar as casas decimais mais altas para a posição das unidades. Assim<|<||*<|||
se torna<||||||||||||*<|||
<
. Assim<||||||||||||*<|||
se torna||||||||||||*|||
|
do RHS do*
. Assim||||||||||||*|||
se torna||||||||||||*||
|
no RHS por todos|
no LHS. Isso tem o efeito de multiplicar o número LHS e RHS de|
para fornecer o número do produto|
Assim,||||||||||||*||
torna-se||||||||||||||||||||||||||||||||||||*
*
. Assim||||||||||||||||||||||||||||||||||||*
se torna||||||||||||||||||||||||||||||||||||
|
volta para decimal pelo inverso das primeiras etapas. Assim||||||||||||||||||||||||||||||||||||
se torna36
.Saída:
Infelizmente, ele falha miseravelmente no requisito de tempo -
200*1000
leva 41 segundos na minha VM do Ubuntu, e o tempo de execução parece empírico com o quadrado do produto final.fonte
length()
que retorna um número. Este usa substituição puramente regex sem tipos numéricos. Acho que sua resposta é potencialmente vencedora, se você puder remover alength()
- talvez você possa fazer uma substituição de regex semelhante em seu lugar?Python -
312286273Se (muitos) zeros à esquerda forem permitidos, os últimos 12 caracteres não serão necessários.
Isso essencialmente executa a multiplicação padrão manualmente. Os dígitos são representados como seqüências de caracteres
I
s repetidos (como números romanos primitivos). Os números são representados como listas de dígitos na ordem inversa. A adição de um dígito é realizada co-codificando cadeias e removendo dezI
segundos, se necessário.Aqui está uma versão não destruída:
fonte
def A(x,y):\n S=[];o=""
->def A(x,y,S=[],o=""):
. Além disso, infelizmente,["","1"][t in i]
não é permitido; está usando um bool para indexar, tratando-o como um número. Eu acho que issot in i and"1"or""
deve funcionar, no entanto.S
como argumento com um padrão não teria funcionado, pois sempre seria a mesma lista mesmo para chamadas diferentes da função e, portanto, não será redefinida para[]
. Você estava certo["","1"][t in i]
, eu consertei isso. Eu também adicionei uma explicação.Ruby:
752698Isso é apenas para obter uma resposta lá fora, apenas por curiosidade. Editado: agora jogou um pouco de golfe.
Uso: Eu tinha isso em um arquivo chamado peasant.rb:
Explicação: é uma multiplicação camponesa, então eu repetidamente reduzi pela metade e dobro. A metade é feita pela metade dos dígitos e marcando os restantes itens da seguinte forma: 1234 -> 0b1a1b2a; encontre e substitua nos b: 06a17a; depois limpando -> 617.
A adição é feita assim ... primeiro, eu ponho as duas cordas no mesmo comprimento e faço pares a partir dos dígitos. Então eu adiciono os dígitos construindo uma string que tem o comprimento de cada dígito e concatenando; Eu removo uma sequência desse comprimento desde o início de '0123456789abcdefghij' e mantenho o primeiro caractere. Então, por exemplo, "9" + "9" -> "i". NB: Evito realmente usar funções de comprimento aqui para evitar tipos de números inteiramente; a remoção do prefixo é feita com um regexp.
Então agora eu tenho uma string contendo uma mistura de dígitos e letras. As letras representam números com um dígito de transporte; Anexo 0 ao número e substituo repetidamente os padrões de letras de dígitos pelo resultado do transporte até que a adição esteja completa.
fonte
Brainfuck (1328 bytes)
Considerações a princípio:
Eu só testei o programa com meu próprio intérprete, você pode encontrá-lo aqui .
A entrada deve ser os dois números separados por um único espaço ASCII.
Golfe:
Ungolfed:
Eu peguei o código para a saída do valor desta resposta , obrigado ao autor por isso!
O programa pode não ser válido, mas de qualquer forma eu queria compartilhar com você ^^
Atualização: Agora você pode testá-lo (apenas para pequenas multiplicações) aqui, graças à resposta do @ Sp3000 a este concurso e aos novos Snippets de pilha do SE!
fonte
Python,
394349340 caracteresExecutar como:
Leva 50 milissegundos.
Usa a multiplicação do camponês russo . Ao adicionar dígitos, os convertemos em unários ('5' => [R, R, R, R, R, R]), concatenamos as listas e depois convertemos de volta.
U
converte para unário, usandoR
como dígito unário. Computamosb/=2
comob=b*5/10
.fonte
def A(a,b):\n r='';c=[]
->def A(a,b,r='',c=[]):
, da mesma forma paradef M
. Você pode mudarfor z in D:d.pop()\n c=['X']
para[d.pop()for z in D];c=['X']
, nesse caso, pode até recolocá-lo no anteriorif
. Além disso, podeif list(b).pop()in'13579'
ser apenasif b[:].pop()in'13579'
?b
é uma sequência, não uma lista.M
e escrever um programa completo;a,b=input()
é permitido.reduce
depararA(b,A(b,A(b,A(b,b))))
com isso, o que permite que você amereduce(A,[b,b,b,b,b])
. Infelizmente, isso não afeta a contagem de caracteres.JavaScript (E6)
375395 411449Edit Golfed
Edit Bug corrigido: falta de limpeza de uma bandeira de transporte
Isso pode ser feito apenas com manipulação de símbolos em quase 0 tempo.
Nesta versão, você pode usar qualquer caractere em vez dos dígitos, desde que o símbolo esteja em ordem crescente.
Notas: usando strings, hashmap com chave de string, matrizes usadas como lista. Sem indexação, as matrizes são percorridas usando 'map' ou giradas usando push & shift.
Todos os '+' são concatenações de strings.
Menos golfe (talvez eu adicione uma explicação amanhã)
Teste no console do FireFox / FireBug
Saída
fonte
9999999999
caso deve ser99999999980000000001
, não #99999999980000000081
Haskell, 231 bytes
Isso define um operador # que multiplica duas representações de string de números naturais. Ele funciona definindo uma operação elementar de incremento / decremento nas strings e, em seguida, utiliza-a para criar adição e multiplicação. Um pouco de mágica extra fornece algumas acelerações exponenciais que tornam tudo isso possível.
Essa abordagem é rápida o suficiente para que, mesmo em um laptop de 2008 no ghci REPL não otimizado, o caso de teste leve apenas uma fração de segundo:
A seguir, verifique se todos os produtos de dois dígitos estão corretos:
fonte
Bash + ImageMagick: 52
Espera que a entrada esteja nas variáveis shell
a
eb
. Não é particularmente inteligente ou eficiente, mas faz o trabalho. Provavelmente já foi feito antes.Observe que
x
denota as dimensões da imagem; não é um operador aritmético neste contexto.Não testei isso, mas estou disposto a supor que, para informações não extremas, ela será concluída em menos de um minuto. Eu posso testar amanhã.
Caso haja algum problema com as versões do ImageMagick, este é o que estou usando:
ImageMagick 6.7.7-10
fonte
9999999999
e9999999999
.dd if=/dev/zero bs=$a count=$b 2>&-|wc -c
.9999999999x9999999999
imagem no formato 8 bits ocupará todo o espaço do disco rígido que existe atualmente na Terra. Obviamente, um png seria muito menor, se você puder criá-lo sem antes criar a imagem bruta. (Embora eu suspeite fortemente que você tenha problemas de excesso de números inteiros com uma imagem desse tamanho.) Mas, ainda assim, esse método quase certamente prejudicaria a brecha de chamar coisas que retornam resultados numéricos como seqüências de caracteres.$b
vez de${b}
.grep -vc g
vez degrep -v g|wc -l
.Python 2 (prova de conceito)
Esta solução funciona usando apenas seqüências de caracteres e listas e um pouco de regex. Acredito que se encaixa totalmente nas especificações, exceto que não há como fazer isso
9999999999x9999999999
em um minuto. Embora tivesse tempo suficiente, iria funcionar. Pode multiplicar números de 4 dígitos rapidamente.Uma vez que é tecnicamente inválido, ainda não me preocupei em jogá-lo completamente. Farei isso se as regras mudarem.
Exemplos:
fonte
Python 2 (555)
Normalmente, eu não responderia ao meu próprio desafio tão rapidamente (ou nada), mas queria provar que isso poderia ser feito. (Felizmente, outras respostas o fizeram antes desta, mas não pude deixar de querer terminá-la.) Há mais golfe a ser feito, mas acho que isso é razoável. Ele lida com o
9999999999x9999999999
caso em menos de 0,03s na minha máquina.Exemplo de uso:
m("12345","42")
Ele funciona multiplicando por muito tempo usando manipulações de string. Às vezes, as variáveis são strings e, às vezes, são iteradores sobre strings, o que torna possível obter o primeiro elemento sem usar um literal inteiro. Tudo é armazenado com os dígitos invertidos, para que o primeiro elemento seja o dígito menos significativo.
Aqui está uma explicação de função por função:
r
es
são funções de contabilidade. (r
é apenas um alias parareversed
, que cria um iterador reverso es
converte iteradores em strings.)i
incrementa o número em uma string em 1, incluindo casos como39+1=40
e99+1=100
.b
adicionax
ey
, masy
deve ter apenas um dígito. Funciona aumentando osx
y
tempos.a
adiciona dois números que podem ter vários dígitos, chamandob
cada dígito emy
.n
multiplicax
ey
, masy
deve ter apenas um dígito. Funciona adicionandox
a si próprioy
tempos.o
multiplicax
ey
, onde ambos os argumentos podem ter vários dígitos. Ele usa multiplicação longa clássicam
apenas converte suas entradas de string em iteradores reversos e as entregao
, depois inverte o resultado e o converte em uma string.fonte
def a(x,y):
->def a(x,y,z=''):
e remova a próxima linha; truques semelhantes para outras funções, indef o(x,y):
, altere ox=s(x)
parax=s(x);l='';z=''
, no loop for, remova similarmente a nova linha + ritmos; em vez disso, use;
. Além disso, acho que oif h!='0':h+=s(x)\nelse:h+=i(x)
pode ser simplesmenteh+=h!='0'and i(x)or s(x)
; talvez atéh+=(h!='0'and i or s)(x)
; caso contrário, simplesmente mude paraif'0'!=h
. Também coisas comodef r(x):return reversed(x)
->r=reversed
s
,m
:s=lambda x:''.join(x)
,m=lambda x,y:s(r(o(r(x),r(y))))
em vez de toda a declaração da função. Com apenas as coisas que eu sei o trabalho, isso traz o byte contagem regressiva para o 521.for
loops:for c in'0'+d:\nif c==y:break\nz=a(iter(z),x)
->for c in'0'+d:\nif c!=y:z=a(iter(z),x)
, embora isso possa alterar significativamente a velocidade do seu programa.JavaScript:
37103604 bytesGolfe:
Sem jogar com testes:
Isso gera:
fonte
Haskell
507496Isso funciona para números inteiros arbitrariamente grandes. Defino representações personalizadas para os números naturais de 0 a 18 (o maior número natural igual à soma de dois dígitos) e defino a multiplicação little-endian em termos de multiplicação de dígitos *, que eu defino em termos de adição de número + número , que eu defino em termos de adição de dígito + dígito. Eu tenho uma função de redução que expande 10-18 valores em sua decomposição digital. Isso, então, apenas lê e inverte as duas strings, converte para as vinculações personalizadas, multiplica e converte de volta, revertendo para obter o resultado certo.
Editar 2
Salvei alguns caracteres criando aliases locais curtos para comandos com vários caracteres que uso mais de uma vez, além de remover espaços e parênteses e substituindo
(
-)
pares por$
quando possível.Para referência, S é o tipo de dados inteiro personalizado,
p
é 'mais' (adição de dígito + dígito),s
é subtraído (para redução),r
é reduzido (expande para decomposição digital),a
é adição (adição de número + número),m
é multiplicar (dígito * multiplicação de números),t
é times (número * multiplicação de números),i
é 'interpretar' (converter string para lista deS
),b
é 'back' (lista de S para string), eg são apenas encurtamentos para o golfe propósitos. Eu não usei números, mesmo implicitamente; o mais próximo que cheguei foi do uso de sucessores e predecessores, que são conceitos matemáticos de nível muito superior ao da adição e multiplicação de números naturais.Editar
Esqueceu de incluir o perfil de horário.
Apenas para uma boa medida:
Vamos enlouquecer!
confirmação
fonte
Python 2 -
1165, 712, 668664Observe que não estou usando indexação lógica como
Z = [X, Y][N == "0"]
, porque isso pode ser interpretado como um booleano convertido em um índice numérico.Ungolfed:
fonte
Scala, 470 caracteres
(a
⇒
escala é padrão, mas pode ser substituída de forma equivalente=>
se contamos bytes)Aqui estamos emulando dígitos usando o comprimento das listas, tomando cuidado para não usar nenhuma operação numérica - apenas dobras, mapas, zíperes e similares. Um número é uma lista desses dígitos (ordem estrategicamente revertida na metade do cálculo); multiplicamos dígitos individuais com
flatMap
e nossas linhas comreduce
.u
lida com a descoberta do carry (correspondendo diretamente a uma lista de> 10 elementos e recorrendo) e convertendo dígitos de volta em caracteres, e usamos a/:
para trabalhar o caminho da pilha com isso. O exemplo necessário é concluído em menos de um segundo.fonte