Esta é uma versão do desafio recente. Esse número é uma potência inteira de -2? com um conjunto diferente de critérios projetados para destacar a natureza interessante do problema e dificultar o desafio. Eu coloquei alguma consideração nisso aqui .
O desafio, maravilhosamente declarado por Toby na questão vinculada, é:
Existem maneiras inteligentes de determinar se um número inteiro é uma potência exata de 2. Isso não é mais um problema interessante, então vamos determinar se um número inteiro inteiro é uma potência exata de -2 . Por exemplo:
-2 => yes: (-2)¹ -1 => no 0 => no 1 => yes: (-2)⁰ 2 => no 3 => no 4 => yes: (-2)²
Regras:
- Um número inteiro é de 64 bits, assinado, complemento de dois. Esse é o único tipo de dados com o qual você pode trabalhar.
- Você só pode usar as seguintes operações. Cada um deles conta como uma operação.
n << k
,n >> k
: Deslocamento esquerdo / direiton
emk
bits. O bit de sinal é estendido no turno direito.n >>> k
: Desloque para a direita, mas não estenda o bit de sinal. 0s são trocados.a & b
,a | b
,a ^ b
: Bitwise AND, OR, XOR.a + b
,a - b
,a * b
: Adicionar, subtrair, multiplicar.~b
: Inverter bit a bit.-b
: Negação do complemento de dois.a / b
,a % b
: Divide (quociente inteiro, arredonda para 0) e módulo.- O módulo de números negativos usa as regras especificadas em C99 :
(a/b) * b + a%b
devem ser iguaisa
. Assim5 % -3
é2
e-5 % 3
é-2
: 5 / 3
é1
,5 % 3
é2
, como 1 * 3 + 2 = 5.-5 / 3
é-1
,-5 % 3
é-2
, como -1 * 3 + -2 = -5.5 / -3
é-1
,5 % -3
é2
, como -1 * -3 + 2 = 5.-5 / -3
é1
,-5 % -3
é-2
, como 1 * -3 + -2 = -5.- Observe que o
//
operador de divisão de piso do Python%
não atende à propriedade "round round 0" da divisão aqui, e o operador do Python também não atende aos requisitos.
- O módulo de números negativos usa as regras especificadas em C99 :
- As atribuições não contam como uma operação. Como em C, as atribuições avaliam o valor do lado esquerdo após a atribuição:
a = (b = a + 5)
defineb
paraa + 5
, depois definea
parab
e conta como uma operação. - As atribuições de compostos podem ser usadas como
a += b
médiasa = a + b
e contam como uma operação.
- Você pode usar constantes inteiras, elas não contam como nada.
- Parênteses para especificar a ordem das operações são aceitáveis.
- Você pode declarar funções. As declarações de função podem ter qualquer estilo conveniente para você, mas observe que números inteiros de 64 bits são o único tipo de dados válido. As declarações de função não contam como operações, mas uma chamada de função conta como uma. Além disso, fique claro: as funções podem conter várias
return
instruçõesreturn
es de qualquer ponto são permitidas. Oreturn
próprio não conta como uma operação. - Você pode declarar variáveis sem nenhum custo.
- Você pode usar
while
loops, mas não pode usarif
oufor
. Os operadores usados nawhile
condição contam para sua pontuação.while
os loops são executados desde que sua condição seja avaliada como um valor diferente de zero (um "verdadeiro" 0 em idiomas que possuem esse conceito não é um resultado válido). Desde o início de retorno é permitido, você tem permissão para usarbreak
bem - Estouro / estouro insuficiente é permitido e nenhum valor de fixação será feito. É tratado como se a operação realmente tivesse ocorrido corretamente e foi truncado para 64 bits.
Critérios de pontuação / vencedor:
Seu código deve produzir um valor diferente de zero se a entrada for uma potência de -2 e zero, caso contrário.
Isso é código-atômico-golfe . Sua pontuação é o número total de operações presentes no seu código (conforme definido acima), não o número total de operações que são executadas em tempo de execução. O código a seguir:
function example (a, b) {
return a + ~b;
}
function ispowerofnegtwo (input) {
y = example(input, 9);
y = example(y, 42);
y = example(y, 98);
return y;
}
Contém 5 operações: duas na função e três chamadas de função.
Não importa como você apresenta seu resultado, use o que for conveniente em seu idioma, seja ele armazenando o resultado em uma variável, retornando-o de uma função ou qualquer outra coisa.
O vencedor é o post que está comprovadamente correto (forneça uma prova casual ou formal, se necessário) e tem a menor pontuação, conforme descrito acima.
Desafio de modo muito difícil de bônus !
Para ter a chance de ganhar absolutamente nada, exceto a capacidade potencial de impressionar as pessoas nas festas, envie uma resposta sem usar while
loops! Se um número suficiente deles for submetido, posso até considerar dividir os grupos vencedores em duas categorias (com e sem loops).
Nota: Se você desejar fornecer uma solução em um idioma que suporte apenas números inteiros de 32 bits, faça isso, desde que justifique suficientemente que ainda será correto para números inteiros de 64 bits em uma explicação.
Além disso: certos recursos específicos do idioma podem ser permitidos sem custo, se eles não violarem as regras, mas forem necessários para coagir o seu idioma a se comportar de acordo com as regras acima . Por exemplo (artificial), permitirei uma comparação livre não igual a 0 em while
loops, quando aplicada à condição como um todo, como uma solução alternativa para um idioma que possui 0s "verdadeiros". Não são permitidas tentativas claras de tirar proveito desses tipos de coisas - por exemplo, o conceito de valores "verdadeiros" 0 ou "indefinidos" não existe no conjunto de regras acima e, portanto, eles não podem ser invocados.
fonte
m ^= s
ainda impressionante, e acho que seria totalmente bom fazer a substituição para melhorá-lo ainda mais.while
ebreak
mas nãoif
?if (x) { ... }
é equivalente awhile (x) { ... break; }
.break
e os retornos iniciais são a parte lamentável) e é uma longa história e uma lição aprendida em regras para desafios futuros. Sempre há a versão "bônus"! :)if
efor
não são permitidos?int x=condition; while (x) { ... x=0; }
é gratuito, apenas mais código. A mesma coisa com o estilo cfor
.Respostas:
C ++, 15 operações
Não faço ideia por que os
while
loops são permitidos, pois destroem todo o desafio. Aqui está uma resposta sem nenhuma:fonte
while
loops destroem todo o desafio ?while
vai contra isso de todas as maneiras.n
ou algo assim.uint64_t
porque essa é a única maneira de obter o deslocamento para a direita sem extensão de sinal.)Operações Python 2 , 3
Experimente online!
As operações são
>>
,&
,/
.A idéia é dividir repetidamente por -2. Poderes de -2 cadeia até 1:
-8 -> 4 -> -2 -> 1
. Se acertarmos um1
, aceite. Se acertarmos um número ímpar antes de bater1
, rejeite. Também precisamos rejeitar0
, o que sempre vai para si.Os
while n>>1:
loops atén
são 0 ou 1. Quando o loop quebra,n
ele próprio é retornado e1
é uma saída Truthy e0
uma saída Falsey. Dentro do loop, rejeitamos repetidamente aplicarn -> n/-2
e rejeitar qualquer ímparn
.Como o método
/
é usado apenas em valores pares, seu comportamento de arredondamento nunca entra em jogo. Portanto, não importa que o Python seja diferente das especificações.fonte
while n&1
invés deif n&1
?if
.Ferrugem,
1412 operações (sem loops)Requer otimização (
-O
) ou-C overflow-checks=no
para ativar a subtração transbordante em vez de pânico.(Para esclarecer: NÃO
!x
é bit a bit aqui, não é lógico)Casos de teste:
Experimente online!
A idéia é verificar se | x | é uma potência de 2 (usando
(y & (y - 1)) == 0
como de costume). Se x é uma potência de 2, então verificamos (1) quandox >= 0
, também deve ser uma potência par de 2 ou (2) quandox < 0
, deve ser uma potência ímpar de 2. Verificamos isso&
ao "bad_power_of_two
"mascara 0x… aaaa quandox >= 0
(produz 0 somente quando é uma potência uniforme) ou 0x… 5555 quandox < 0
.fonte
~((r | -r) >> 63)
truque para terminar de corrigir minha resposta.Haskell,
23 operaçõesDefine uma função recursiva
f(n)
. As operações usadas são chamada de função (f
), divisão (div
) e bit a bit e (.&.
).Não contém loops devido ao fato de que Haskell não possui instruções de loop :-)
fonte
f 0
,f 1
,f n ...
aqui, porque eles são, essencialmente,if
é disfarçada, embora, novamente, eu queria permitir quewhile
+break
e inícioreturn
s, por isso, parece justo. Embora pareça tirar proveito do meu conjunto de regras ser inadvertidamente deixado em aberto para interpretação, é uma boa solução.|
s estão especialmente no ar. Dito isto, isso viola uma regra específica de uma maneira menos discutível: a comparação==
não é permitida. Note, no entanto, que se a minha interpretação deste código está correto, o uso de booleans aqui não parece aceitável como substituindo valores inteiros arbitrários em seu lugar não parece alterar os resultados, e eles são mais de uma forma de apresentação final.==
porque não há outra maneira de transmitir de ouInt
paraBool
"Truthy" em Haskell. Se a correspondência de padrão e guardas estão em violação da "nãoif
é" regra é a sua chamada ;-)Operações em Python 3,
10 ou 119Retorna
5
para poderes de-2
,0
caso contráriofonte
C, 5 operações
C, 10 operações, sem loops
C, 1 operação
fonte
Montagem, 1 operação
Usa uma enorme tabela de pesquisa para descobrir se o número é uma potência de 2. Você pode expandir isso para 64 bits, mas encontrar um computador para armazenar esses dados é deixado como exercício para o leitor :-P
fonte
C, 31 operações
Demonstração ao vivo
Minha idéia é simples, se é uma potência de dois, então, se o log for par, deve ser positivo; caso contrário, o log deve ser impar.
fonte
C, 7 operações
ou:
C, 13 operações sem loops como condicionais
Explicação:
n&-n
produz o menor bit definido den
.a
é o valor absoluto negado den/2
, necessariamente negativo, porque/2
impede o excesso de negação.a/x
é zero somente sea
for uma potência exata de dois; caso contrário, pelo menos um outro bit está definido e é maior quex
o bit mais baixo, produzindo um resultado negativo.~(a/x >> 63)
em seguida, produz uma máscara de bits que é todo-queridos sen
ou-n
é uma potência de dois, caso contrário, todos os-zeros.^s
é aplicado à máscara para verificar o sinal den
para ver se é uma potência-2
.fonte
PHP, 3 operações
ternário e
if
não permitido; então vamos abusarwhile
:$n>>1
: se number for 0 ou 1, retorne number$n&1
: se o número for ímpar, retorne 0$n/-2
(+ converter para int)fonte
JavaScript ES6, 7 operações
Experimente online!
Explicação
Enquanto x! = 0 e x% 2 == 0 4 ops
x / x é igual a 1 desde que x não seja 0 (0/0 fornece NaN que é avaliado como falso)
& bit a bit e
x & 1 ^ 1 é igual a 1 se x é par (x e 1) xor 1
Essa é a forma de divisão definida pela pergunta 1
Enquanto x! = 1 e x! = 0 1 op
A condição necessária para sair quando x == 0 ou x == 1, pois esses dois são os valores de retorno e a inserção de um loop infinito não seria produtiva. Teoricamente, isso poderia ser estendido para valores maiores, aumentando o número hexadecimal. Atualmente trabalha para até ± 2 ^ 32-1
Defina x como 0 1 op.
Embora eu pudesse ter usado o retorno 0 para 0 ops, senti que qualquer loop while quebrado por outra instrução parece muito trapaceiro.
retorna x (1 se potência de -2, 0 caso contrário)
fonte