Controlla se un numero intero è una potenza di 2 senza usare +, - operazioni [chiuso]


30

Scrivi un programma che controlla se l'intero è una potenza di 2.


Input di esempio:

8

Uscita campione:

Yes

Input di esempio:

10

Uscita campione:

No

Regole:

  • Non usare +, -operazioni.

  • Utilizzare una sorta di flusso di input per ottenere il numero. L'input non dovrebbe essere inizialmente memorizzato in una variabile.

  • Vince il codice più breve (in byte).

È possibile utilizzare qualsiasi risposta di verità / falsa (ad esempio, true/ false). Si può presumere che il numero di input sia maggiore di 0.


1
È anche consentito l'output "true" anziché "yes" e "false" anziché "no"?
Programma FOX il

2
Sì, puoi usare qualsiasi risposta positiva / negativa. La domanda è stata aggiornata
gthacoder

1
La predfunzione, quando applicata a un numero intero n, restituisce n - 1. Sono vietate anche funzioni come questa, che sono sottili travestimenti intorno all'operatore proibito?
Wayne Conrad,

1
@Wayne proprio come golfscript ), o la maggior parte delle lingue basate su c ' --.
Maniglia della porta

2
So che ci sono 3 anni nel futuro, ma "+/- operatori" non sono osservabili, o per lo meno definiti in modo debole.
ATaco,

Risposte:


13

GolfScript, 6 caratteri, nessun decremento

~.3/&!

Ecco una soluzione che non utilizza il x & (x-1)metodo in nessuna forma. Usa x & (x/3)invece. ;-) Emette 0se falso, 1se vero.

Spiegazione:

  • ~ elimina la stringa di input per trasformarla in un numero,
  • .lo duplica (per il successivo &),
  • 3/ lo divide per tre (troncando verso il basso),
  • & calcola il AND bit per bit del valore diviso con l'originale, che sarà zero se e solo se l'ingresso è zero o una potenza di due (cioè ha al massimo un bit impostato), e
  • ! nega logicamente questo, mappando zero su uno e tutti gli altri valori su zero.

Gli appunti:

  • Secondo le regole chiarite, zero non è un input valido , quindi questo codice è OK, anche se viene emesso 1se l'input è zero.

  • Se l'operatore di decremento GolfScript (è consentito, è sufficiente la soluzione a 5 caratteri ~.(&! pubblicata da aditsu . Tuttavia, sembra andare contro lo spirito delle regole , se non la lettera.

  • Ho inventato il x & (x/3)trucco anni fa sulla mailing list di Fun With Perl. (Sono sicuro di non essere il primo a scoprirlo, ma l'ho (ri) inventato in modo indipendente.) Ecco un link al post originale , inclusa una prova che funziona davvero.


Penso che sia davvero un po 'sciocco, golfscript permette di scrivere la soluzione esatta che l'OP voleva escludere senza infrangere le regole.
Tim Seguine,

1
@Tim: OK, eccone uno senza decrementi, quindi. ;)
Ilmari Karonen il

come può funzionare? Ad esempio 7/3 = 2 (0010), quindi 7 & 2 = 0111 & 0010 = 0010che chiaramente l'ultimo bit non è 1
phuclv

@ LưuVĩnhPhúc: No, ma il secondo bit è. Prova a fare una lunga divisione per 3 in binario ed è abbastanza ovvio perché ciò accade sempre se il dividendo ha più di un bit impostato.
Ilmari Karonen,

ah ho letto male questo con "divisibile per 2"
phuclv,

15

APL (7)

Sì, sono 7 byte . Supponiamo per il momento che sto usando la tabella codici IBM 907 anziché Unicode e quindi ogni carattere è un byte :)

0=1|2⍟⎕

vale a dire 0 = mod(log(input(),2),1)


Mi chiedo, cosa succede se gli dai 0 o un numero negativo?
aditsu,

@aditsu Non so cosa sia l'infinity mod 1, ma sicuramente non dovrebbe essere zero.
Tim Seguine,

1
@TimSeguine Mathematica mi dà Indeterminatequando lo provo.
LegionMammal978,

7

GolfScript, 11 (per 1 (vero) e 0 (falso))

.,{2\?}%?0>

Metti il ​​numero in pila e poi esegui.

GolfScript, 22 (per Sì / No)

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

Adoro il modo in cui la conversione 1/ 0in Yes/ Noaccetta tanto codice quanto la sfida stessa: D

Avvertenza: ESTREMAMENTE inefficiente;) Funziona bene per numeri fino a 10000, ma una volta che si arriva così in alto si inizia a notare un leggero ritardo.

Spiegazione:

  • .,: si trasforma nin n 0..n( .duplicato, ,intervallo 0..n)
  • {2\?}: alla potenza di 2
  • %: mappa "potenza di 2" su "0..n" in modo che diventi n [1 2 4 8 16 ...]
  • ?0>: verifica se l'array contiene il numero (0 è maggiore dell'indice)

1
1 byte più corto per Sì / No .,{2\?}%?0<'YesNo'3/=:; inoltre penso che stai barando chiedendo di "Metti il ​​numero in pila", dovresti iniziare con un ~.
aditsu,

1
Non riesce il 1, che è 2 ^ 0
Joachim Isaksson il

6

Mathematica 28

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

Per potenze intere pari a 2, il numeratore del registro di base 2 sarà 1 (il che significa che il registro è una frazione di unità).

Qui modifichiamo leggermente la funzione per visualizzare l'ingresso presunto. Usiamo #al posto di Input[]e aggiungiamo &per definire una funzione pura. Restituisce la stessa risposta che verrebbe restituita se l'utente inserisse il numero nella funzione sopra.

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

Vero
Falso

Test di più numeri alla volta.

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

{Vero, Vero, Falso, Falso}


4

Perl 6 (17 caratteri)

say get.log(2)%%1

Questo programma ottiene una linea dalla getfunzione STDIN , calcola il logaritmo con la base 2 su di esso ( log(2)) e controlla se il risultato si divide per 1 ( %%1, dove %%si divide per operatore). Non è breve come la soluzione GolfScript, ma lo trovo accettabile (GolfScript vince comunque tutto), ma molto più veloce (anche considerando che Perl 6 è lento in questo momento).

~ $ perl6 -e 'say get.log(2)%%1'
256
True
~ $ perl6 -e 'say get.log(2)%%1'
255
False

2
Il motivo per cui +e -sono proibiti per questa sfida, è perché se x & (x - 1)è uguale a 0, allora xè una potenza di 2.
ProgramFOX

@ProgramFOX: capisco. Trucco interessante.
Konrad Borowski il

1
@ProgramFOX Ma x&~(~0*x)funziona ancora. Sono solo 2 caratteri in più.
orlp,

4

Ottava ( 15 23)

EDIT: aggiornato a causa dei requisiti di input dell'utente;

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

Consente all'utente di immettere un valore e di 1 per true, 0 per false.

Testato in Octave, dovrebbe funzionare anche in Matlab.


Funziona anche in Matlab :)
jub0bs

4

R, 13 11

Basato sulla soluzione Perl. Restituisce FALSEo TRUE.

!log2(i)%%1

Il parametro irappresenta la variabile di input.

Una versione alternativa con input dell'utente:

!log2(scan())%%1

4

GolfScript, 5

Emette 1 per vero, 0 per falso. Basato sull'idea di user3142747:

~.(&!

Nota: (è un decremento, si spera non contenga come -:)
Se lo fa (e i commenti del PO suggeriscono che potrebbe), si prega di fare riferimento invece alla soluzione di Ilmari Karonen .
Per l'output Y / N, aggiungere 'NY'1/=alla fine (altri 7 byte).


4

Python, 31

print 3>bin(input()).rfind('1')

31 se lo faibin(input()).rfind('1')<3
Blender

@Blender Ben individuato. L'avevo usato 2==perché immaginavo che dovesse funzionare anche con numeri non positivi. Ciò non è esplicitamente richiesto dalle regole, quindi ...
stand dal

1
+1. Avrei pubblicato print bin(input()).count('1')<2un totale di 31 personaggi, ma è troppo simile al tuo.
Steven Rumbalski il

4

C, 48

main(x){scanf("%i",&x);puts(x&~(x*~0)?"F":"T");}

Può essere più breve se è consentito negare unario, è più lungo se non sono consentite costanti negative. Suppone il complemento a due.
orlp

*ha una precedenza maggiore rispetto al binario &, non hai bisogno delle parentesi. E se il valore di ritorno viene accettato (appena richiesto) exit(x&x*-1)sarebbe molto più breve.
Kevin,

V'è una -: x*-1.
klingt.net,

@ klingt.net sì, ma fa parte di una costante numerica. Tecnicamente, come è scritto ora, -è vietato solo all'operatore .
Kevin,

1
@ klingt.net È stato sostituito con una versione che non utilizza segni.
orlp,

4

Ho deciso di utilizzare un altro approccio, basato sul conteggio della popolazione o sulla somma laterale del numero (il numero di 1 bit). L'idea è che tutti i poteri di due hanno esattamente un 1bit, e nessun altro numero lo ha. Ho aggiunto una versione JavaScript perché l'ho trovata divertente, anche se sicuramente non vincerà alcuna competizione di golf.

J, 14 15 caratteri (uscite 0 o 1)

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

JavaScript, 76 caratteri (output vero o falso)

alert((~~prompt()).toString(2).split("").map(Number).filter(Boolean).length)

Questo utilizza l'aggiunta, che è preclusa dalla sfida.
FUZxxl,

Huh. Non ho idea di cosa stavo pensando quando ho scritto questo ... L'ho risolto ora in modo che segua effettivamente le regole.
FireFly

4

Clip , 9 8 7

!%lnxWO

Legge un numero dallo stdin.

Spiegazione:

Per cominciare, Z= 0, W= 2e O= 1. Ciò consente di collocare We Ouno accanto all'altro, mentre l'uso 2e 1verrebbe interpretato come il numero 21 senza uno spazio di separazione (un carattere aggiuntivo indesiderato). In Clip, la funzione modulo ( %) funziona su numeri non interi, quindi, per capire se un valore vè un numero intero, controlli se vmod 1 = 0. Usando la sintassi Clip, questo è scritto come =0%v1. Tuttavia, poiché i booleani vengono archiviati come 1(o qualsiasi altra cosa) e 0, controllare se qualcosa è uguale non 0significa semplicemente "non farlo". Per questo, Clip ha l' !operatore. Nel mio codice, vè lnx2. xè un input di stdin,nconverte una stringa in un numero ed labè la base bdi log di a. Il programma pertanto si traduce (più facilmente) in 0 = ((log base 2 of parseInt(readLine)) mod 1).

Esempi:

8

uscite

1

e

10

uscite

0

Modifica 1: sostituito 0, 1e 2con Z, Oe W.

Modifica 2: sostituito =Zcon !.

Anche:

Pyth , 5

Comprime ulteriormente la versione Clip, poiché Pyth ha Q per l'input già valutato e una funzione log2 (a) anziché solo log generale (a, b).

!%lQ1

3

Javascript (37)

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

Script semplice che si divide semplicemente per 2 ripetutamente e controlla il resto.


1
stessa idea con un forloop (anche 37 caratteri)for(i=prompt();i>1;i/=2){}alert(i==1)
Math chiller

3

Mathematica (21)

IntegerQ@Log2@Input[]

Senza input è un po 'più breve

IntegerQ@Log2[8]

Vero

IntegerQ@Log2[7]

falso


⌊#⌋==#&@Log2@Input[]
alephalpha,

1
@alephalpha Questo finisce per usare 24 byte per i caratteri UTF-8. Un altro programma a 21 byte è Log2@Input[]~Mod~1==0.
LegionMammal978,

2

JavaScript, 41 40 caratteri

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

Come funziona: prendi il logaritmo in base 2 usando l(prompt()) / l(2) , e se quel risultato modulo 1 è uguale a zero, allora è una potenza di 2.

Ad esempio: dopo aver preso il logaritmo di 8 su base 2, ottieni 3.3 modulo 1è uguale a 0, quindi questo restituisce vero.

Dopo aver preso il logaritmo di 7 sulla base 2, ottieni 2.807354922057604. 2.807354922057604 modulo 1è uguale a 0.807354922057604, quindi questo restituisce false.


Non è necessario trasmettere l'input a un numero; Math.loglo farà già : "Ognuna delle seguenti funzioni dell'oggetto Math applica l'operatore astratto ToNumber a ciascuno dei suoi argomenti ..."
apsillers

Non soffre di inesattezze numeriche?
Mark Jeronimus l'

@MarkJeronimus: in realtà non lo so. Potrebbe essere, ma non ho ancora riscontrato un risultato errato.
Programma FOX l'

2

JavaScript, 35

Funziona per i byte.

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

Versione a 46 caratteri , funziona per numeri a 16 bit.

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

Il trucco funziona nelle lingue più dinamiche.

Spiegazione: Convertire il numero in base 2, interpretare quella stringa come base 10, fare modulo 9 per ottenere la somma delle cifre, che deve essere 1.


Che dire 0x2ff, quale è nella base 2 1111111111?
Peter Taylor,

@PeterTaylor Hai ragione, risolto
copia il

quindi la cosa reale che stai facendo è controllare modulo 10 senza resto, ma hai usato 9 per radere un carattere del tuo codice +1,!
Chiller matematico

Questo è un po 'un imbroglio ma un altro metodo:alert(!(Number.MAX_VALUE%prompt()))
Plutone il


2

python 3, 38

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

pitone, 32

Tuttavia, il codice non funziona in tutte le versioni.

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

Si noti che la soluzione funziona anche per 0 (stampa Falso).


È stato votato perché questa era anche la mia soluzione.
Josh Caswell

1
Cosa succede se si sostituisce ==con &?
SimonT

@SimonT Questo non è vero. Sostituendo '==' con '&' verrà stampato 1 per ogni numero che ha un numero dispari di '1' nella sua rappresentazione binaria. Controllare ad esempio 7 = 111. Ce ne sono 3 = 11. Restituirà 11 & 1 = 1.
Gari BN

2

Rubino - 17 personaggi (quarto tentativo)

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

Il mio attuale migliore è una fusione della risposta di @ steenslag con la mia. Di seguito sono riportati i miei precedenti tentativi.

Ruby - 19 personaggi (terzo tentativo)

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

Rubino - 22 caratteri (secondo tentativo)

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

Ruby - 24 caratteri (primo tentativo)

p !!('%b'%gets=~/^10*$/)

c'è ancora un "+" nel tuo programma
phuclv

Lo so. : - / Ho chiesto chiarimenti se "+" e "-" sono severamente vietati o se possono essere utilizzati in altri contesti oltre all'addizione e alla sottrazione. Sono in procinto di riscrivere a prescindere.
OI

Grande miglioramento. Sembra che sia il miglior risultato di Ruby finora. Ho aggiornato la tabella dei leader nel testo della domanda.
gthacoder,

@gthacoder Ho appena combinato il regex di steenslag con la mia formattazione binaria. Sicuramente non posso prendermi tutto il merito.
OI

2

K / Kona ( 24 17)

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

Restituisce 1 se vero e 0 se falso. Qualsiasi potenza di 2 ha un singolo bit uguale 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)

(questo stampa tutti i poteri di 2 (da 0 a 9) in binario)

Quindi riassumo tutti i componenti dell'espressione binaria di xe vedo se è uguale a 1; se sì allora x=2^n, altrimenti no .

... sapevo che avrei potuto ridurlo


@gthacoder: ho ridotto il codice, spero che tu possa aggiornare il tuo post principale per riflettere questo!
Kyle Kanos,

Questo non usa l'aggiunta? E la domanda, errare, non lo proibisce?
zgrep,

2

C # (54 caratteri)

 Math.Log(int.Parse(Console.ReadLine()),2)%1==0?"Y":"N"

Il compito afferma chiaramente che l'input non è memorizzato in una variabile, dovrebbe essere ottenuto da un flusso di input di qualche tipo (come stdin), inoltre, questo è code-golf , prova ad accorciare un po 'il codice, almeno rimuovendo gli spazi bianchi
mniip,

Penso che intendi solo Int32, non ToInt32...
Chris,

Ya ya Grazie per aver segnalato Chris. Prima era Convert.ToInt32 e volevo cambiarlo in Int32.Parse per accorciarlo. : D
Merin Nakarmi,

2
utilizzare intinvece di Int322 caratteri in meno.
Rik

2

Rebmu (9 caratteri)

z?MOl2A 1

Test

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

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

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

Rebmu è un dialetto ristretto di Rebol. Il codice è essenzialmente:

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

Alternativa

14 caratteri: Rebmu non ha un bit a bit e AND ~

z?AND~aTIddA 3

In Rebol:

zero? a & to-integer a / 3

1

GTB , 46 byte

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

1

Python, 35

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

Non utilizza non solo le operazioni +/-, ma qualsiasi operazione matematica oltre alla conversione in forma binaria.

Altre cose (interessanti, ma non per la concorrenza):

Ho anche una versione di regexp (61) :

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

(Adoro l'idea, ma la funzione di importazione e abbinamento la rende troppo lunga)

E bella, ma noiosa versione operazioni bit per bit (31) :

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

(sì, è più breve, ma usa ~ -x per il decremento che comporta - operazione)


Le risposte di boothby usano la stessa idea della mia prima, ma è più breve :(
Ivan Anishchuk

1

Python 2.7 ( 30 29 39 37)

EDIT: aggiornato a causa dei requisiti di input dell'utente;

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

Forza bruta, prova a dividere fino a = 1 (successo) o <1 (fallimento)


1
not a%2può essere scritto come a%2==0. Certo, questo sarebbe più lungo in molte lingue, ma non in Python.
Konrad Borowski il

@xfix Grazie, testato e aggiornato.
Joachim Isaksson,

1
o meglio ancora, a%2<1.
stand dal

hai uno spazio dopo la 2.rimozione che salverebbe un byte!
Keerthana Prabhakaran,

1

Python (33)

print int(bin(input())[3:]or 0)<1

int(bin(input()*2)[3:])<1funziona anche dalla shell Python con solo 25 caratteri.
martedì


1

APL (12 per 0/1, 27 per sì / no)

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

oppure, se dobbiamo produrre testo:

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

Leggi in A. Forma un vettore 0..A, quindi un vettore 2 0 ..2 A (sì, è molto più del necessario), quindi un vettore che confronta A con ognuno di questi (risultante in un vettore di 0 e al massimo uno 1), quindi xo quello (non c'è un operatore xor in APL, ma ≠ applicato ai booleani agirà come uno.) Ora abbiamo 0 o 1.

Per ottenere SÌ o NO: moltiplicare 0 o 1 per 3, eliminare questo numero di caratteri da "YESNO", quindi prendere i primi 3 caratteri di questo.


1

C, 65 byte

main(k){scanf("%i",&k);while(k&&!(k%2))k/=2;puts(k==1?"T":"F");}

Puoi tagliare 5 caratteri usando main(k){..., facendo affidamento sulla intdigitazione implicita . Potrebbe essere UB, ma questo è il golf del codice. MAI usare qualcosa del genere in produzione, ovviamente.
Kevin,

1

Haskell ( 52 50)

k n=elem n$map(2^)[1..n]
main=interact$show.k.read
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.