Seu objetivo é implementar a operação de multiplicação XOR (sem carga ), definida abaixo, no menor número possível de bytes.
Se pensarmos no XOR bit a bit ( ^
) como adição binária sem carregar
101 5
^ 1001 9
----
1100 12
5^9=12
podemos realizar a multiplicação de XOR @
fazendo uma multiplicação longa binária , mas executando a etapa de adição sem carregar o XOR em bits ^
.
1110 14
@ 1101 13
-----
1110
0
1110
^ 1110
------
1000110 70
14@13=70
(Para matemáticos, isso é multiplicação no anel polinomial F_2[x]
, identificando polinômios com números naturais, avaliando x=2
como um polinômio sobre Z.)
A multiplicação de XOR alterna a@b=b@a
, associa (a@b)@c=a@(b@c)
e distribui em XOR bit a bit a@(b^c)=(a@b)^(a@c)
. Na verdade, ele é o único tal operação que corresponde a multiplicação a@b=a*b
sempre a
e b
são potências de 2
como 1,2,4,8...
.
Exigências
Tome dois números inteiros não negativos como entrada e saída ou imprima seu produto XOR. Devem ser números ou representações de cadeias decimais, não expansões binárias. Menos bytes ganha.
Não se preocupe com estouros de número inteiro.
Aqui estão alguns casos de teste formatados como a b a@b
.
0 1 0
1 2 2
9 0 0
6 1 6
3 3 5
2 5 10
7 9 63
13 11 127
5 17 85
14 13 70
19 1 19
63 63 1365
PCLMULQDQ
da extensão CLMUL. Infelizmente, obtive voto negativo pelo meu conhecimento das instruções x86 definidas anteriormente (relacionadas aPEXT/PDEP
), então vou deixar isso como um comentário aqui.Respostas:
código de máquina x86: 7 bytes
Apenas duas instruções.
pclmulqdq
faz o trabalho pesado, literalmente implementa esse tipo de multiplicação xor.ret
para torná-lo uma função que pode ser chamada, atendendo, esperançosamente, o requisito de "gerar" o resultado (no valor de retornoxmm0
). Colocar argumentos inteiros emxmm
args é um pouco incomum, mas espero que você me perdoe.fonte
Z80, 11 bytes
O código é chamado como uma função.
a
eb
estão dentroD
eE
(a ordem não importa) e a resposta é armazenadaA
quando o código retorna (não há funções de E / S).Produz os resultados corretos para todas as entradas de teste, exceto
63@63
que retornam85
porque todos os registros são de 8 bits e 1365 mod 256 = 85 (excesso de número inteiro).fonte
C,
4438 bytesGraças a nimi, agora usamos recursão para 6 bytes a menos!
Nós definimos uma função
f
que levaa
,b
.Isso pode ser chamado como:
Quais saídas:
13 @ 14 = 70
Experimente os casos de teste online !
fonte
f(a,b)={return(b)?(b&1)*a^f(2*a,b/2):0;}
?(b&1)
porb%2
para salvar mais dois bytes, pois%
possui o mesmo nível de precedência da esquerda para a direita que*
.Pitão,
1312 bytesDemonstração.
Versão antiga, 13 bytes:
Demonstração.
fonte
vz
duas entradas inteiras.CJam,
1413 bytesComo funciona :
Primeiro obtemos os longos resultados de multiplicação e depois avançamos a partir dos dois pares inferiores.
Experimente online aqui
fonte
J, 14 bytes
Uso:
Explicação (lendo principalmente da direita para a esquerda;
u
ev
significa funções arbitrárias):u&.#:
aplicau
- se aos vetores das representações binárias dos números de entrada e, em seguida, retorne o resultado a um número inteiro (u&.v == v_inverse(u(v(input_1), v(input_2)))
)*/
produtos (*
) de entradas no produto Descartes (/
) do vetor binário doisv(u@)
aplicaru
av
(para o produto Descartes)u/.
aplicamu
- se a todas as antiasgonais do produto Descartes (as antiagonais representam os 1º, 2º, ... dígitos na representação binária)~:/
reduzir (/
) uma anti-diagonal com a operação XOR (~:
)Experimente online aqui.
fonte
Python 2, 35 bytes
Ligue como
f(13, 14)
. Eu acho que a maioria das linguagens com uma construção semelhante irá convergir para algo assim.fonte
Java, 62
Expandido
fonte
for(;i<32;)
parawhile(i<32)
? Eles têm o mesmo comprimento, mas o segundo parece ser uma maneira mais natural de escrevê-lo.i++
foi originalmente nofor
loop e foi jogado para a sua posição atual. Comowhile
não é menor, não há razão para alterá-lo.Haskell, 50 bytes
Uma tradução da resposta C do @ BrainSteel. Exemplo de uso:
fonte
Perl - 35 bytes
Contando a opção de linha de comando como uma. A entrada é retirada de
STDIN
, espaço separado.Uso da amostra:
fonte
Julia,
353330 bytesIsso cria uma função recursiva
f
que pega dois números inteiros e retorna o produto XOR das entradas.Ungolfed:
Economizou alguns bytes com o incentivo do Sp3000!
fonte
Python 2,
104917866 bytesTake the bits of
b
in reverse order, ending before you hit the'0b'
at the start of the string. Multiply each one bya
andxor
with the total, then left-shifta
. Then print the total.fonte
Go, 63 bytes
Complete example:
http://play.golang.org/p/-ngNOnJGyM
fonte
GAP, 368 Bytes
Claro, vamos fazer isso! (isso é apenas pouco jogado, o objetivo era passar para F 2 [x] e fazer os cálculos mais do que qualquer tentativa de ser uma entrada vencedora)
Aqui está o código
Aqui está o código não destruído com explicação:
Ok, então, primeiro, criamos o anel polinomial univariado sobre o campo F 2 e o chamamos
R
. Observe queGF(2)
é F 2 no GAP.Em seguida, vamos atribuir a variável GAP
x
ao indeterminado do anelR
. Agora, sempre que eu disserx
no GAP, o sistema saberá que estou falando sobre o indeterminado do anelR
.Next, we have two functions, which are inverse maps of each other. These maps are both onto, but they are not structure preserving, so I couldn't figure out a better way to implement them in GAP. There almost certainly is a better way, if you know it, please comment!
O primeiro mapa,
to_ring
pega um número inteiro e mapeia para o seu elemento de anel correspondente. Isso é feito usando um algoritmo de conversão em binário, onde todo o1
que apareceria em binário é substituído por umx^n
onden
é a potência apropriada que 2 seria necessária se o número fosse realmente binário.A próxima função reverte isso.
to_ints
pega um elemento de anel e mapeia para seu número inteiro correspondente. Faço isso obtendo uma lista dos coeficientes do polinômio e, para cada coeficiente diferente de zero, o resultado é aumentado em 2 ^ n, da mesma forma que converteríamos binário em decimal.Para a etapa final, chamamos essas funções. Pegamos as duas entradas inteiras, as convertemos em elementos no anel
R
, depois multiplicamos esses elementos e enviamos o produto de volta aos números inteiros.fonte
Ruby,
767573 bytesRuby, 60 bytes (somente função, sem E / S)
fonte
Mathematica, 40 bytes
fonte
f@@{a,b,c,d}
=f[a,b,c,d]
. reference.wolfram.com/language/ref/Apply.htmlDart,
3432 bytesStraight-forward recursive implementation.
fonte
gnuplot, 29 bytes
just like in Dart (see above)
fonte
GNU Assembler(x86_64 Mac OS X), 97 bytes
This is a proper function that can be called from C:
& can be tested with this C program:
Note that on Mac OS X, you have to use
clang -x c
to compile it as C & not C++.For linux(if I remember right), the code would be 95 bytes:
Strangely enough, this version is actually longer than defining the function in inline assembly, but that one was longer than the pure C solution we already have, so I decided to try assembly.
edit
If it's counted by the assembled size(excluding any labels &c.), then it's
x86_64 Assembler, 22 bytes:
fonte
golflua 68
Does basically the same bitshifting as Ypnypn's Java answer, but seems to require the divide by 2 at the end to work correctly. Takes in values as stdin, examples below
fonte
Ceylon, 90 bytes
This is just the algorithm as described: multiply
a
by2^i
wherever thei
th bit is set inb
, and add them all together using xor. Iterates over0:64
because Integers are 64-bit in Ceylon when running on JVM (lower when running as Javascript, but thenb.get(i)
just returns false).Formatted:
The alias safes here just a single byte.
fonte
(non-competing) Jelly, 16 bytes
Try it online!
fonte