Qualquer um que esteja moderadamente otimizado para o código de baixo nível conhece os perigos da ramificação, seja ela implementada como instruções if, loops ou instruções select, a possibilidade de uma previsão incorreta de ramificação é uma terrível perda de tempo.
Problemas simples podem ser resolvidos muito melhor com aritmética simples, então vamos fazer isso.
Para os seguintes problemas, todas as variáveis são números inteiros não assinados de 32 bits e o único código permitido são instruções de conjunto simples que envolvem apenas os seguintes operadores:
+ addition
- subtraction
* multiplication
/ integer division, rounds down, division by 0 not allowed
% modulo
& binary and
| binary or
^ binary exclusive or
>> bitshift right
<< bitshift left
Logic operators, return 1 if the expression is true and 0 if it is false.
== equal
!= not equal
< less than
<= less than or equal
> greater than
>= greater than or equal
Set operator
=
Cada linha deve consistir em um identificador de variável seguido por um operador set, seguido por uma expressão.
Uma expressão pode não conter operadores de conjunto adicionais, mas pode conter identificadores de variáveis, números literais e parênteses.
A pontuação do golfe deve contar apenas o número de operadores.
Exemplo:
myvar = ( ( ( foo + 5 ) * bar ) % 7 ) == 3
Tem uma pontuação de 5 operadores.
Uma solução pode incluir tantas variáveis quanto o autor entender.
Variáveis que não foram definidas têm valor 0
.
Estouro positivo e negativo é permitido, todos os números negativos estouro negativo, então 3 - 5
é 4294967294
, como parte de uma instrução maior.
Tarefa 1: Máx.
Dois valores A
e B
existem no escopo fazem com que a RESULT
variável contenha o maior desses valores quando o programa termina.
Tarefa 2: mediana
Três valores, A
, B
e C
, existem no escopo, fazer a RESULT
variável conter a mediana desses valores quando o termina do programa.
Tarefa 3: Raiz quadrada
Um valor, A
existe no escopo, faz com que a RESULT
variável contenha a raiz quadrada de A
, arredondada para baixo, quando o programa termina.
Não há problema em postar uma resposta para apenas uma ou duas das perguntas; para alguns de vocês, encontrar soluções válidas será um desafio.
fonte
-
mas~
poderia ser legal (mesmo que eu não saiba para quê).0xFFFF_FFFF_FFFF_FFFF ^ x
e0 - x
. Como eu pude esquecer?!
é também bastante trivial:x == 0
.Boole[a-b]
?Respostas:
Tarefa 3, 23 ops
Usando o método de Newton, como as outras soluções, com uma semente escolhida com mais tato. O primeiro bit
A >> 16
mantém o topo da faixa feliz, o segundo bitA / ((A >> 13) + 511)
mantém o meio da faixa feliz e o último bit15
o inferior, além de impedir a divisão por erros zero (15 é o maior valor possível que permite0
convergir corretamente - pela metade correção três vezes menos igual a zero). Para os valores de entrada225, 275625, 82137969, 2908768489
(e valores próximos), a semente inicial é exata. Todos os casos de borda (quadrados perfeitos, quadrados perfeitos + 1 e quadrados perfeitos - 1) na faixa0 .. 2**32-1
foram testados e estão corretos.Alguns comentários sobre as regras: O
estouro e o estouro são permitidos, todos os números negativos estão vazios; portanto, 3 - 5 é 4294967294, mesmo como parte de uma declaração maior .
Essa última parte acaba sendo uma espécie de matadora de inovação. Inicialmente, tentei uma solução usando uma forma generalizada do método de Halley , mas percebi que era inválida, dada a restrição acima. A iteração (aplicada às raízes quadradas) é a seguinte:
Essa iteração possui boas qualidades que a de Newton não possui. Ele converge cubicamente (em vez de quadraticamente), converge de cima ou de baixo (e não apenas de cima), e não é tão sensível a uma semente mal escolhida (se a iteração de Newton fornecer uma semente que é muito baixa, será ultrapassar bastante o ponto de convergência e, em seguida, precisar voltar ao trabalho).
O método de Newton também tem o problema (pelo menos quando se lida com números inteiros) que muitas vezes atinge um x tal que A / x - x = 2 - nesse caso, converge para um valor um maior que a raiz inteira adequada, que precisa ser corrigido; O método de Halley não precisa dessa correção. Infelizmente, porém, o valor de
3*A + x*x
geralmente será maior que o espaço inteiro permitido de 32 bits.Existem vários outros algoritmos de enésima raiz generalizados , mas todos compartilham essa mesma característica:
etc. A maioria deles exibe convergência cúbica ou quadrática. Os quatro últimos fazem parte de uma série de iterações que convergem na convergência quártica. Mas, na prática, o método de Newton fornece o que você precisa com menos operações, a menos que você precise calcular muitas centenas de dígitos.
fonte
log(3)/log(2) ~= 1.585
iterações de Newton.A = 0
- então isso é de fato mais curto. Cerca de 4294967295 , que foi uma supervisão: como 65536² ≡ 0 , a iteração da correção falha ao corrigir. Vou ver se consigo encontrar uma alternativa.65 (61) operações (5 + 13 + 47 (43))
Tarefa 1 - Máx. (A, B)
Esta é a solução óbvia. Você precisa da atribuição, precisa de comparação, precisa multiplicar a comparação por algo, o multiplicando não pode ser uma das variáveis e o produto não pode ser o resultado.
Tarefa 2 - Média (A, B, C)
Essa é uma melhoria em relação à minha solução anterior de 15 operações, que condicionou todas as três variáveis - isso salvou duas subtrações, mas introduziu outro teste de centralidade. O teste em si é simples: um elemento está no meio, se exatamente um dos outros estiver acima.
Tarefa 3 - sqrt (A)
Onze rodadas de aproximação de Newton. A constante mágica de 1024 já é superada pelo WolframW (e 512 causa divisão por zero para a = 0 antes de a = 2 ** 32 convergir), mas se pudermos definir 0/0 como zero, dez iterações funcionarão com o valor inicial de 512. Eu admito que minha reivindicação de dez iterações não é totalmente clara, mas ainda as reivindico entre parênteses.
Vou ter que investigar se nove é possível, no entanto.A solução do WolframH são nove iterações.fonte
(1024 + A/1024)/2 == (512 + A/2048)
(que é comoX0 = 1024
, e depois iniciar Newton).MOV RESULT, A; CMP A,B; CMOVA RESULT, B
;-)1: 5 operadores
2: 13 operadores
3: 27 operadores
fonte
Tarefa 3, 39 Operações
EDIT: última linha alterada; Ver comentários.
Esta é uma implementação do método Newthon. Testado com todos os quadrados positivos, e também com os quadrados positivos menos um e também um milhão de números aleatórios no intervalo de 0 a 2 ^ 32-1. O valor aparentemente engraçado começando é curto para
(1022 + A/1022) / 2
que precisa do mínimo número de iterações (eu acho), e também faz oRESULT
paraA=0
a direita (o que não seria o caso de1024
, em vez de1022
).fonte