Verifique se um número inteiro é uma potência de 2 sem usar +, - operações [fechadas]

30

Escreva um programa que verifique se o número inteiro é uma potência de 2.


Entrada de amostra:

8

Saída de amostra:

Yes

Entrada de amostra:

10

Saída de amostra:

No

Regras:

  • Não use +, -operações.

  • Use algum tipo de fluxo de entrada para obter o número. A entrada não deve ser inicialmente armazenada em uma variável.

  • O código mais curto (em bytes) vence.

Você pode usar qualquer resposta de verdade / falsidade (por exemplo, true/ false). Você pode assumir que o número de entrada é maior que 0.

gthacoder
fonte
1
Também é permitido gerar "true" em vez de "yes" e "false" em vez de "no"?
ProgramFOX
2
Sim, você pode usar qualquer resposta positiva / negativa. A pergunta é atualizada.
Gthacoder #
1
A predfunção, quando aplicada a um número inteiro n, retorna n - 1. São também funções como essa, que são disfarces finos em torno do operador proibido?
Wayne Conrad
1
@Wayne, assim como o golfscript ), ou a maioria dos idiomas baseados em c ' --.
Maçaneta
2
Sei que daqui a três anos estamos no futuro, mas "+/- operadores" não são observáveis ​​ou, no mínimo, pouco definidos.
ATaco 12/09

Respostas:

13

GolfScript, 6 caracteres, sem decréscimos

~.3/&!

Aqui está uma solução que não usa o x & (x-1)método de nenhuma forma. Ele usa em seu x & (x/3)lugar. ;-) Saídas 0se false, 1se true.

Explicação:

  • ~ avalia a sequência de entrada para transformá-la em um número,
  • .duplica (para o subsequente &),
  • 3/ divide por três (truncando para baixo),
  • & calcula o AND bit a bit do valor dividido com o original, que será zero se e somente se a entrada for zero ou uma potência de dois (ou seja, tiver no máximo um bit definido), e
  • ! nega isso logicamente, mapeando zero para um e todos os outros valores para zero.

Notas:

  • De acordo com as regras esclarecidas, zero não é uma entrada válida ; portanto, este código está OK, mesmo que seja emitido 1se a entrada for zero.

  • Se o operador de decremento GolfScript (for permitido, a solução de 5 caracteres ~.(&! postada pelo aditsu é suficiente. No entanto, parece ir contra o espírito das regras , se não a letra.

  • Eu inventei o x & (x/3)truque anos atrás na lista de discussão Fun With Perl. (Tenho certeza de que não sou o primeiro a descobri-lo, mas o (re) inventei de forma independente.) Aqui está um link para a postagem original , incluindo uma prova de que ela realmente funciona.

Ilmari Karonen
fonte
Eu acho que é um pouco bobo, realmente, o golfscript permite escrever a solução exata que o OP queria excluir sem realmente violar as regras.
Tim Seguine
1
@ Tim: OK, aqui está um sem decrementos, então. ;)
Ilmari Karonen
como isso pode funcionar? Por exemplo 7/3 = 2 (0010), para 7 & 2 = 0111 & 0010 = 0010que claramente o último bit não seja 1
phuclv
@ LưuVĩnhPhúc: Não, mas o segundo bit é. Tente fazer divisão longa por 3 em binário e é bastante óbvio porque isso sempre acontece se o dividendo tiver mais de um bit definido.
Ilmari Karonen
ah eu interpretei isso errado com "divisível por 2"
phuclv
15

APL (7)

Sim, são 7 bytes . Suponha que eu esteja usando a página de códigos IBM 907 em vez de Unicode e, em seguida, cada caractere seja um byte :)

0=1|2⍟⎕

ie 0 = mod(log(input(),2),1)

marinus
fonte
Apenas imaginando, o que acontece se você der 0 ou um número negativo?
Aditsu
@aditsu Não sei o que é o infinito mod 1, mas certamente não deve ser zero.
Tim Seguine
1
O @TimSeguine Mathematica me fornece Indeterminatequando tento isso.
LegionMammal978
7

GolfScript, 11 (para 1 (verdadeiro) e 0 (falso))

.,{2\?}%?0>

Coloque o número na pilha e depois execute.

GolfScript, 22 (para Sim / Não)

.,{2\?}%?0>'Yes''No'if

Eu amo como converter 1/ 0para Yes/ Noleva tanto código quanto o próprio desafio: D

Aviso: EXTREMAMENTE ineficiente;) Funciona bem para números de até 10000, mas depois que você chega tão alto, começa a notar um ligeiro atraso.

Explicação:

  • .,: transforma n- se em n 0..n( .duplicado, ,intervalo 0..n)
  • {2\?}: ao poder de 2
  • %: mapeie "poder de 2" sobre "0..n" para que se torne n [1 2 4 8 16 ...]
  • ?0>: verifica se a matriz contém o número (0 é maior que o índice)
Maçaneta da porta
fonte
1
1 byte mais curto para Sim / Não .,{2\?}%?0<'YesNo'3/=:; Também acho que você está trapaceando pedindo "Coloque o número na pilha", você deve começar com a ~.
Aditsu
1
Falha no 1, que é 2 ^ 0
Joachim Isaksson
6

Mathematica 28

Numerator[Input[]~Log~2]==1

Para potências inteiras de 2, o numerador do log da base 2 será 1 (o que significa que o log é uma fração da unidade).

Aqui, modificamos ligeiramente a função para exibir a entrada presumida. Usamos #no lugar de Input[]e adicionamos &para definir uma função pura. Retorna a mesma resposta que seria retornada se o usuário digitar o número na função acima.

    Numerator[#~Log~2] == 1 &[1024]
    Numerator[#~Log~2] == 1 &[17]

Verdadeiro
Falso

Testando vários números de cada vez.

    Numerator[#~Log~2] == 1 &&/@{64,8,7,0}

{Verdadeiro, Verdadeiro, Falso, Falso}

DavidC
fonte
4

Perl 6 (17 caracteres)

say get.log(2)%%1

Este programa obtém uma linha da getfunção STDIN , calcula o logaritmo com base 2 nela ( log(2)) e verifica se o resultado é dividido por 1 ( %%1, onde %%é dividido pelo operador). Não tão curto quanto a solução GolfScript, mas acho isso aceitável (o GolfScript ganha tudo de qualquer maneira), mas muito mais rápido (mesmo considerando que o Perl 6 está lento no momento).

~ $ perl6 -e 'say get.log(2)%%1'
256
True
~ $ perl6 -e 'say get.log(2)%%1'
255
False
Konrad Borowski
fonte
2
A razão pela qual +e -são proibidos para esse desafio, é porque se x & (x - 1)é igual a 0, então xé uma potência de 2. #
ProgramFOX
@ProgramFOX: Entendo. Truque interessante.
precisa saber é o seguinte
1
@ProgramFOX Mas x&~(~0*x)ainda funciona. São apenas 2 caracteres a mais.
orlp
4

Oitava ( 15 23)

EDIT: atualizado devido ao requisito de entrada do usuário;

~mod(log2(input('')),1)

Permite que o usuário insira um valor e produz 1 para true, 0 para false.

Testado em oitava, também deve funcionar no Matlab.

Joachim Isaksson
fonte
Funciona em Matlab também :)
jub0bs
4

R, 13 11

Baseado na solução Perl. Retorna FALSEou TRUE.

!log2(i)%%1

O parâmetro irepresenta a variável de entrada.

Uma versão alternativa com entrada do usuário:

!log2(scan())%%1
Sven Hohenstein
fonte
4

GolfScript, 5

Saídas 1 para verdadeiro, 0 para falso. Com base na ideia de user3142747:

~.(&!

Nota: (é decrescente, espero que não conte como -:)
Se sim (e os comentários do OP sugerem que sim), consulte a solução de Ilmari Karonen .
Para saída Y / N, acrescente 'NY'1/=no final (mais 7 bytes).

aditsu
fonte
4

Python, 31

print 3>bin(input()).rfind('1')
boothby
fonte
31 se você fizerbin(input()).rfind('1')<3
Blender
@ Blender Bem manchado. Eu tinha usado 2==porque achei que deveria funcionar para números não positivos também. Que explicitamente não é exigido pelas regras, então ...
Boothby
1
+1. Eu ia postar print bin(input()).count('1')<2um total de 31 caracteres, mas é muito parecido com o seu.
Steven Rumbalski
4

C, 48

main(x){scanf("%i",&x);puts(x&~(x*~0)?"F":"T");}
orlp
fonte
Pode ser menor se a negação unária for permitida, e mais longa se constantes negativas não forem permitidas. Assume o complemento de dois.
orlp
*tem precedência mais alta que binária &, você não precisa dos parênteses. E se o valor de retorno for aceito (apenas solicitado) exit(x&x*-1), será muito menor.
Kevin
Há um -: x*-1.
Klingt.net
@ klingt.net sim, mas isso faz parte de uma constante numérica. Tecnicamente, como está redigido agora, apenas o operador -é proibido.
Kevin
1
@ klingt.net Substituiu por uma versão que não usa sinais.
orlp
4

Decidi usar outra abordagem, com base na contagem da população ou na soma lateral do número (o número de 1 bits). A idéia é que todos os poderes de dois tenham exatamente um 1bit e nenhum outro número. Eu adicionei uma versão JavaScript porque achei divertido, embora certamente não vença nenhuma competição de golfe.

J, 14 15 caracteres (saídas 0 ou 1)

1=##~#:".1!:1]1

JavaScript, 76 caracteres (gera verdadeiro ou falso)

alert((~~prompt()).toString(2).split("").map(Number).filter(Boolean).length)
FireFly
fonte
Isso usa adição, que é impedida pelo desafio.
FUZxxl
Hã. Não faço ideia do que estava pensando quando escrevi isso ... Corrigi-o agora para que ele siga as regras.
FireFly
4

Clipe , 9 8 7

!%lnxWO

Lê um número de stdin.

Explicação:

Para começar, Z= 0, W= 2e O= 1. Isso permite a colocação de We Oao lado do outro, ao passo que utilizando 2e 1seria interpretada como o número 21, sem um espaço de separação (um carácter adicional indesejada). No Clip, a função modulo ( %) funciona em não-inteiros; portanto, para descobrir se algum valor vé um número inteiro, verifique se vmod 1 = 0. Usando a sintaxe do Clip, isso é escrito como =0%v1. No entanto, como os booleanos são armazenados como 1(ou qualquer outra coisa) e 0, verificar se algo é igual 0é apenas 'not'ing'. Para isso, o Clip possui o !operador. No meu código, vé lnx2. xé uma entrada do stdin,nconverte uma string em um número e labé a base bde log de a. O programa traduz, portanto, (mais facilmente) para 0 = ((log base 2 of parseInt(readLine)) mod 1).

Exemplos:

8

saídas

1

e

10

saídas

0

Edit 1: substituído 0, 1e 2com Z, Oe W.

Editar 2: substituído =Zpor !.

Além disso:

Pitão , 5

Compacta a versão do Clip ainda mais, pois Pyth possui Q para a entrada já avaliada e uma função log2 (a) em vez de apenas o log geral (a, b).

!%lQ1
bcsb1001
fonte
3

Javascript (37)

a=prompt();while(a>1)a/=2;alert(a==1)

Script simples que apenas divide por 2 repetidamente e verifica o restante.

Joachim Isaksson
fonte
1
mesma idéia com um forloop (também 37 caracteres)for(i=prompt();i>1;i/=2){}alert(i==1)
chiller de matemática
3

Mathematica (21)

IntegerQ@Log2@Input[]

Sem entrada, é um pouco menor

IntegerQ@Log2[8]

Verdade

IntegerQ@Log2[7]

Falso

ybeltukov
fonte
⌊#⌋==#&@Log2@Input[]
precisa saber é o seguinte
1
@alephalpha Isso acaba usando 24 bytes para os caracteres UTF-8. Outro programa de 21 bytes é Log2@Input[]~Mod~1==0.
LegionMammal978
2

JavaScript, 41 40 caracteres

l=Math.log;alert(l(prompt())/l(2)%1==0);

Como isso funciona: você usa o logaritmo na base 2 usando l(prompt()) / l(2), e se o resultado do módulo 1 for igual a zero, será uma potência de 2.

Por exemplo: depois de pegar o logaritmo de 8 na base 2, você recebe 3. 3 modulo 1é igual a 0, então isso retorna verdadeiro.

Depois de pegar o logaritmo de 7 na base 2, você recebe 2.807354922057604. 2.807354922057604 modulo 1é igual a 0.807354922057604, então isso retorna false.

ProgramFOX
fonte
Você não precisa converter a entrada em um número; Math.logjá fará isso : "Cada uma das seguintes funções de objeto Math aplica o operador abstrato ToNumber a cada um de seus argumentos ..."
apsillers
Não sofre imprecisões numéricas?
Mark Jeronimus
@ MarkJeronimus: Na verdade, eu não sei. Pode ser, mas ainda não encontrei um resultado incorreto.
precisa
2

JavaScript, 35

Funciona para bytes.

alert((+prompt()).toString(2)%9==1)

Versão de 46 caracteres , funciona para números de 16 bits.

x=(+prompt()).toString(2)%99;alert(x==1|x==10)

O truque funciona nas linguagens mais dinâmicas.

Explicação: Converta o número na base 2, interprete essa sequência como base 10, execute o módulo 9 para obter a soma dos dígitos, que deve ser 1.

cópia de
fonte
Que tal 0x2ff, qual é a base 2 1111111111?
Peter Taylor
@PeterTaylor Você está certo, corrigido
copiar
então a coisa real que você está fazendo é verificar o módulo 10 sem deixar resto, mas você usou 9 para raspar um caractere do seu código +1!
Resfriador de matemática
Isso é meio trapaça, mas outro método:alert(!(Number.MAX_VALUE%prompt()))
Plutão
2

python 3, 38

print(1==bin(int(input())).count('1'))

python, 32

No entanto, o código não funciona em todas as versões.

print 1==bin(input()).count('1')

Observe que a solução também funciona para 0 (imprimir False).

Gari BN
fonte
Votado porque esta foi minha solução também.
precisa saber é o seguinte
1
E se você substituir ==com &?
precisa saber é o seguinte
@ SimonT Isso não é verdade. Substituir '==' por '&' imprimirá 1 para cada número que tiver um número ímpar de '1' em sua representação binária. Verifique por exemplo 7 = 111. Existem 3 = 11 uns. Ele irá retornar 11 & 1 = 1.
Gari BN
2

Ruby - 17 caracteres (quarta tentativa)

p /.1/!~'%b'%gets

Meu melhor atual é uma fusão da resposta de @ steenslag com a minha. Abaixo estão minhas tentativas anteriores.

Ruby - 19 caracteres (terceira tentativa)

p /10*1/!~'%b'%gets

Ruby - 22 caracteres (segunda tentativa)

p !('%b'%gets)[/10*1/]

Ruby - 24 caracteres (primeira tentativa)

p !!('%b'%gets=~/^10*$/)
OI
fonte
ainda existe um "+" no seu programa
phuclv 5/01/14
Eu sei. : - / Pedi esclarecimentos sobre se '+' e '-' são estritamente proibidos ou se podem ser usados ​​em outros contextos além de adição e subtração. Estou no processo de reescrever, independentemente.
OI
Grande melhoria. Parece que é o melhor resultado do Ruby até agora. Atualizei a tabela de líderes no texto da pergunta.
Gthacoder
@gthacoder Acabei de combinar o regex do steenslag com a minha formatação binária. Definitivamente não aguento todo o crédito.
OI
2

K / Kona ( 24 17)

d:{(+/(2_vs x))~1

Retorna 1 se verdadeiro e 0 se falso. Qualquer potência de 2 tem um único bit igual a 1:

2_vs'_(2^'(!10))
(,1
1 0
1 0 0
1 0 0 0
1 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0)

(isso imprime todos os poderes de 2 (de 0 a 9) em binário)

Então, resumo todos os componentes da expressão binária de xe vejo se é igual a 1; se sim x=2^n, então , caso contrário não.

... sabia que eu poderia torná-lo menor

Kyle Kanos
fonte
@ gthacoder: fiz o código menor, espero que você possa atualizar seu post principal para refletir isso!
precisa saber é o seguinte
Isso não usa adição? E a pergunta, erre, não proíbe isso?
zgrep 12/09
2

C # (54 caracteres)

 Math.Log(int.Parse(Console.ReadLine()),2)%1==0?"Y":"N"
Merin Nakarmi
fonte
A tarefa afirma claramente que a entrada não é armazenada em uma variável; ela deve ser obtida de um fluxo de entrada de algum tipo (como stdin); também, isso é código-golfe ; tente encurtar um pouco o código, pelo menos removendo o espaço em branco
mniip
Eu acho que você acabou de dizer Int32, não ToInt32...
Chris
Ya ya. Obrigado por apontar Chris. Anteriormente, era Convert.ToInt32 e eu queria alterá-lo para Int32.Parse para reduzi-lo. : D
Merin Nakarmi
2
use em intvez de Int322 caracteres a menos.
Rik
2

Rebmu (9 caracteres)

z?MOl2A 1

Teste

>> rebmu/args [z?MOl2A 1] 7
== false

>> rebmu/args [z?MOl2A 1] 8 
== true

>> rebmu/args [z?MOl2A 1] 9 
== false

Rebmu é um dialeto restrito de Rebol. O código é essencialmente:

z? mo l2 a 1  ; zero? mod log-2 input 1

Alternativo

14 caracteres - Rebmu não tem um 'amassado' AND ~

z?AND~aTIddA 3

Em Rebol:

zero? a & to-integer a / 3
rgchris
fonte
1

GTB , 46 bytes

2→P`N[@N=Pg;1P^2→P@P>1E90g;2]l;2~"NO"&l;1"YES"
Timtech
fonte
1

Python, 35

print bin(input()).strip('0')=='b1'

Não usa não apenas operações +/-, mas qualquer operação matemática, além de converter para a forma binária.

Outras coisas (interessantes, mas não para competição):

Eu também tenho uma versão regexp (61) :

import re;print re.match(r'^0b10+$',bin(input())) is not None

(Adoro a ideia, mas a função de importação e correspondência a torna muito longa)

E agradável, mas chata versão de operações bit a bit (31) :

x=input();print x and not x&~-x

(sim, é mais curto, mas usa ~ -x para diminuir o que inclui - operação)

Ivan Anishchuk
fonte
As respostas de Boothby usa a mesma idéia que o meu primeiro, mas é mais curto :(
Ivan Anishchuk
1

Python 2.7 ( 30 29 39 37)

EDIT: atualizado devido ao requisito de entrada do usuário;

a=input()
while a>1:a/=2.
print a==1

Força bruta, tente dividir até = 1 (sucesso) ou <1 (falha)

Joachim Isaksson
fonte
1
not a%2pode ser escrito como a%2==0. Concedido, isso seria mais longo em muitos idiomas, mas não no Python.
precisa saber é o seguinte
@xfix Obrigado, testado e atualizado.
Joachim Isaksson
1
ou melhor ainda a%2<1.
usar o seguinte comando
você tem um espaço após a 2.remoção que salvaria um byte!
Keerthana Prabhakaran
1

Python (33)

print int(bin(input())[3:]or 0)<1
Liquidificador
fonte
int(bin(input()*2)[3:])<1também funciona a partir do shell python com apenas 25 caracteres.
precisa saber é
1

Ruby, 33 , 28 , 25

p /.1/!~gets.to_i.to_s(2)
steenslag
fonte
1

APL (12 para 0/1, 27 para sim / não)

≠/A=2*0,ιA←⍞ 

ou, se precisarmos gerar texto:

3↑(3x≠/A=2*0,ιA←⍞)↓'YESNO '

Leia em A. Forme um vetor 0..A, depois um vetor 2 0 ..2 A (sim, isso é muito mais do que necessário), depois um vetor comparando A com cada um deles (resultando em um vetor de 0 e no máximo um 1), depois xor que (não há operador xor no APL, mas ≠ aplicado aos booleanos atuará como um). Agora, temos 0 ou 1.

Para obter SIM ou NÃO: multiplique 0 ou 1 por 3, solte esse número de caracteres de 'YESNO' e, em seguida, pegue os 3 primeiros caracteres.

Mark Plotnick
fonte
1

C, 65 bytes

main(k){scanf("%i",&k);while(k&&!(k%2))k/=2;puts(k==1?"T":"F");}
vershov
fonte
Você pode cortar 5 caracteres usando main(k){..., contando com a intdigitação implícita . Pode ser UB, mas isso é código de golfe. NUNCA use algo assim na produção, é claro.
Kevin
1

Haskell ( 52 50)

k n=elem n$map(2^)[1..n]
main=interact$show.k.read
Zeta
fonte