Sprawdź, czy liczba całkowita jest potęgą 2, bez użycia operacji +, - [zamknięte]


30

Napisz program, który sprawdzi, czy liczba całkowita jest potęgą 2.


Przykładowe dane wejściowe:

8

Przykładowe dane wyjściowe:

Yes

Przykładowe dane wejściowe:

10

Przykładowe dane wyjściowe:

No

Zasady:

  • Nie używać +, -operacje.

  • Użyj jakiegoś strumienia wejściowego, aby uzyskać liczbę. Dane wejściowe nie powinny być początkowo przechowywane w zmiennej.

  • Najkrótszy kod (w bajtach) wygrywa.

Możesz użyć dowolnej odpowiedzi typu prawda / fałsz (na przykład true/ false). Możesz założyć, że liczba wejściowa jest większa niż 0.


1
Czy można również wypisywać „prawda” zamiast „tak” i „fałsz” zamiast „nie”?
ProgramFOX

2
Tak, możesz użyć dowolnej pozytywnej / negatywnej odpowiedzi. Pytanie zostało zaktualizowane.
gthacoder

1
predFunkcyjne, gdy stosuje się do liczby całkowitej N, N - 1. powraca to funkcje, takie jak to, które są cienkie, stroje około zakazanego operatora, zakazano?
Wayne Conrad

1
@Wayne, podobnie jak golfscript ), lub większość języków opartych na języku c ” --.
Klamka

2
Wiem, że mamy za 3 lata, ale „+/- operatorów” nie da się zaobserwować, a przynajmniej słabo zdefiniować.
ATaco

Odpowiedzi:


13

GolfScript, 6 znaków, bez dekrecji

~.3/&!

Oto rozwiązanie, które nie wykorzystuje tej x & (x-1)metody w żadnej formie. x & (x/3)Zamiast tego używa . ;-) Wypisuje wartość 0false, 1jeśli true.

Wyjaśnienie:

  • ~ analizuje ciąg wejściowy, aby przekształcić go w liczbę,
  • .powiela to (dla następnych &),
  • 3/ dzieli to przez trzy (obcięcie),
  • & oblicza bitowe ORAZ podzielonej wartości z oryginałem, który będzie wynosił zero wtedy i tylko wtedy, gdy wejście będzie równe zero lub potęgi dwóch (tj. będzie ustawiony najwyżej jeden bit), i
  • ! logicznie to neguje, odwzorowując zero na jedną i wszystkie inne wartości na zero.

Uwagi:

  • Zgodnie z objaśnionymi regułami zero nie jest prawidłowym wejściem , więc ten kod jest OK, nawet jeśli wyprowadza, 1jeśli wejście jest zerowe.

  • Jeśli operator dekrementacji GolfScript (jest dozwolony, wystarczy 5-znakowe rozwiązanie ~.(&! opublikowane przez aditsu . Jednak wydaje się to sprzeczne z duchem zasad , jeśli nie z literą.

  • x & (x/3)Kilka lat temu wpadłem na tę sztuczkę na liście dyskusyjnej Fun With Perl. (Jestem pewien, że nie jestem pierwszym, który to odkrył, ale samodzielnie go wymyśliłem.) Oto link do oryginalnego postu , w tym dowód, że faktycznie działa.


Myślę, że to trochę głupie, golfscript pozwala napisać dokładne rozwiązanie, które OP chciał wykluczyć, nie naruszając przy tym reguł.
Tim Seguine

1
@Tim: OK, oto jeden bez dekrecji. ;)
Ilmari Karonen

jak to może działać Na przykład 7/3 = 2 (0010), więc 7 & 2 = 0111 & 0010 = 0010który wyraźnie ostatni bit nie jest 1
phuclv

@ LưuVĩnhPhúc: Nie, ale drugi bit to. Spróbuj wykonać długi podział przez 3 w systemie binarnym i jest całkiem oczywiste, dlaczego tak się zawsze dzieje, jeśli dywidenda ma ustawiony więcej niż jeden bit.
Ilmari Karonen

ah
Źle

15

APL (7)

Tak, to 7 bajtów . Załóżmy na chwilę, że używam strony kodowej IBM 907 zamiast Unicode, a następnie każdy znak jest bajtem :)

0=1|2⍟⎕

to znaczy 0 = mod(log(input(),2),1)


Zastanawiam się, co się stanie, jeśli podasz 0 lub liczbę ujemną?
aditsu

@aditsu Nie wiem, co to jest nieskończoność mod 1, ale na pewno nie powinno być zero.
Tim Seguine

1
@TimSeguine Mathematica daje mi, Indeterminategdy próbuję tego.
LegionMammal978

7

GolfScript, 11 (dla 1 (prawda) i 0 (fałsz))

.,{2\?}%?0>

Umieść liczbę na stosie, a następnie uruchom.

GolfScript, 22 (dla Tak / Nie)

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

Uwielbiam, jak konwersja 1/ 0do Yes/ Nozajmuje tyle samo kodu, co samo wyzwanie: D

Ostrzeżenie: NIEZWYKLE nieefektywne;) Działa dobrze dla liczb do 10000, ale gdy osiągniesz tak wysoki poziom, zaczniesz zauważać niewielkie opóźnienie.

Wyjaśnienie:

  • .,: zmienia się nw n 0..n( .duplikat, ,zakres 0..n)
  • {2\?}: do potęgi 2
  • %: mapuje „potęgę 2” na „0..n”, więc staje się n [1 2 4 8 16 ...]
  • ?0>: sprawdza, czy tablica zawiera liczbę (0 jest większe niż indeks)

1
1 bajt krótszy dla Tak / Nie .,{2\?}%?0<'YesNo'3/=:; również myślę, że oszukujesz, prosząc o „Umieść liczbę na stosie”, powinieneś zacząć od ~.
aditsu

1
Nie odpowiada 1, czyli 2 ^ 0
Joachim Isaksson

6

Mathematica 28

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

Dla liczb całkowitych 2, licznikiem logarytmu podstawowego 2 będzie 1 (co oznacza, że ​​log jest ułamkiem jednostkowym).

Tutaj nieznacznie modyfikujemy funkcję, aby wyświetlić przypuszczalne wejście. Używamy #zamiast Input[]i dodajemy, &aby zdefiniować czystą funkcję. Zwraca tę samą odpowiedź, która zostałaby zwrócona, gdyby użytkownik wprowadził numer w powyższej funkcji.

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

Prawda
Fałsz

Testowanie kilku liczb jednocześnie.

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

{Prawda, prawda, fałsz, fałsz}


4

Perl 6 (17 znaków)

say get.log(2)%%1

Ten program pobiera wiersz z getfunkcji STDIN , oblicza logarytm z podstawą 2 na nim ( log(2)) i sprawdza, czy wynik dzieli przez 1 ( %%1, gdzie %%jest dzielony przez operatora). Nie tak krótkie jak rozwiązanie GolfScript, ale uważam to za dopuszczalne (GolfScript i tak wygrywa wszystko i tak), ale o wiele szybciej (nawet biorąc pod uwagę, że Perl 6 jest teraz wolny).

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

2
Dlatego, że +i -są zabronione na to wyzwanie, dlatego jeśli x & (x - 1)jest równa 0, to xjest potęgą 2.
ProgramFOX

@ProgramFOX: Rozumiem. Ciekawa sztuczka.
Konrad Borowski

1
@ProgramFOX Ale x&~(~0*x)nadal działa. To tylko 2 znaki dłużej.
orlp

4

Oktawa ( 15 23)

EDYCJA: Zaktualizowano ze względu na wymagania użytkownika;

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

Pozwala użytkownikowi wprowadzić wartość i wyprowadza 1 dla wartości true, 0 dla wartości false.

Testowany w Octave, powinien również działać w Matlabie.


Działa również w Matlabie :)
jub0bs

4

R 13 13

Na podstawie rozwiązania Perla. Zwraca FALSElub TRUE.

!log2(i)%%1

Ten parametr ireprezentuje zmienną wejściową.

Alternatywna wersja z wejściem użytkownika:

!log2(scan())%%1

4

GolfScript, 5

Wyjścia 1 dla wartości true, 0 dla wartości false. Oparty na pomyśle user3142747:

~.(&!

Uwaga: (jest zmniejszeniem, miejmy nadzieję, że nie liczy się jako -:)
Jeśli tak (a komentarze OP sugerują, że może), to zamiast tego zapoznaj się z rozwiązaniem Ilmari Karonen .
W przypadku danych wyjściowych Y / N dołącz 'NY'1/=na końcu (7 kolejnych bajtów).


4

Python, 31

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

31 jeśli to zrobiszbin(input()).rfind('1')<3
Blender

@Blender Dobrze zauważony. Użyłem, 2==ponieważ uznałem, że powinien on również działać dla liczb niepozytywnych. Nie jest to wyraźnie wymagane przez zasady, więc ...
stoisko

1
+1. Zamierzałem napisać print bin(input()).count('1')<2w sumie 31 znaków, ale jest zbyt podobny do twojego.
Steven Rumbalski

4

C, 48

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

Może być krótszy, jeśli dozwolone jest jednostronne negowanie, jest dłuższy, jeśli stałe ujemne nie są dozwolone. Zakłada uzupełnienie dwóch.
orlp

*ma wyższy priorytet niż binarny &, nie potrzebujesz parenów. A jeśli wartość zwrotu zostanie zaakceptowana (tylko zapytana), exit(x&x*-1)byłaby znacznie krótsza.
Kevin

Jest -: x*-1.
klingt.net

@ klingt.net tak, ale to część stałej liczbowej. Technicznie, jak to jest teraz sformułowane, -zabroniony jest tylko operator .
Kevin

1
@ klingt.net Zastąpił go wersją, która nie używa znaków.
orlp

4

Zdecydowałem się zastosować inne podejście, oparte na liczbie ludności lub na bokach sumy liczby (liczby 1-bitów). Chodzi o to, że wszystkie potęgi dwóch mają dokładnie jeden 1bit, a żadna inna liczba nie. Dodałem wersję JavaScript, ponieważ uważam ją za zabawną, choć na pewno nie wygra żadnej gry w golfa.

J, 14 15 znaków (wyjścia 0 lub 1)

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

JavaScript, 76 znaków (wyniki prawda lub fałsz)

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

Wykorzystuje to dodawanie, które jest wykluczone przez wyzwanie.
FUZxxl

Huh Nie mam pojęcia, o czym myślałem, kiedy to napisałem ... Naprawiłem to teraz, aby właściwie postępowało zgodnie z zasadami.
FireFly,

4

Klips , 9 8 7

!%lnxWO

Czyta liczbę ze standardowego wejścia.

Wyjaśnienie:

Na początek, Z= 0, W= 2i O= 1. Pozwala to na umieszczanie Wi Oobok siebie, natomiast użycie 2i 1byłoby interpretowane jako liczba 21 bez spacji (niepożądany dodatkowy znak). W Clip funkcja modulo ( %) działa na liczbach niecałkowitych, więc aby sprawdzić, czy jakaś wartość vjest liczbą całkowitą, sprawdź, czy vmod 1 = 0. Za pomocą składni Clipa zapisuje się to jako =0%v1. Jednakże, ponieważ booleany są przechowywane jako 1(lub cokolwiek innego) i 0sprawdzenie, czy coś jest równe, 0to po prostu „nie” to. W tym celu Clip ma !operatora. W moim kodzie vjest lnx2. xjest wejściem ze stdin,nkonwertuje ciąg znaków na liczbę i labjest podstawa log bz a. Dlatego program tłumaczy (bardziej czytelnie) na 0 = ((log base 2 of parseInt(readLine)) mod 1).

Przykłady:

8

wyjścia

1

i

10

wyjścia

0

Edit 1: zastąpić 0, 1i 2z Z, Oi W.

Edycja 2: zastąpiona =Zprzez !.

Również:

Pyth , 5

Kompresuje wersję Clip jeszcze bardziej, ponieważ Pyth ma Q dla już ocenionego wejścia i funkcję log2 (a) zamiast zwykłego dziennika (a, b).

!%lQ1

3

JavaScript (37)

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

Prosty skrypt, który dzieli tylko kilka razy i sprawdza resztę.


1
ten sam pomysł z forpętlą (także 37 znaków)for(i=prompt();i>1;i/=2){}alert(i==1)
agregat matematyczny

3

Matematyka (21)

IntegerQ@Log2@Input[]

Bez danych wejściowych jest nieco krótszy

IntegerQ@Log2[8]

Prawdziwe

IntegerQ@Log2[7]

Fałszywe


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

1
@alephalpha To kończy się na 24 bajtach dla znaków UTF-8. Kolejny 21-bajtowy program to Log2@Input[]~Mod~1==0.
LegionMammal978

2

JavaScript, 41 40 znaków

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

Jak to działa: bierzesz logarytm z podstawy 2 za pomocą l(prompt()) / l(2), a jeśli ten wynik modulo 1 jest równy zero, to jest to potęga 2.

Na przykład: po przyjęciu logarytmu 8 na podstawie 2dostajesz 3. 3 modulo 1jest równe 0, więc zwraca true.

Po przyjęciu logarytmu 7 na podstawie 2 otrzymujesz 2.807354922057604. 2.807354922057604 modulo 1jest równa 0.807354922057604, więc zwraca false.


Nie musisz rzutować danych wejściowych na liczbę; Math.logzrobi to już : „Każda z następujących funkcji obiektów matematycznych stosuje operator abstrakcyjny ToNumber do każdego z argumentów ...”
apsillers

Czy to nie cierpi na niedokładności liczbowe?
Mark Jeronimus

@MarkJeronimus: Właściwie to nie wiem. Być może, ale nie napotkałem jeszcze niepoprawnego wyniku.
ProgramFOX

2

JavaScript, 35

Działa dla bajtów.

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

Wersja 46 znaków , Działa dla liczb 16-bitowych.

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

Sztuczka działa w najbardziej dynamicznych językach.

Objaśnienie: Konwertuj liczbę na bazę 2, zinterpretuj ten ciąg jako bazę 10, wykonaj modulo 9, aby uzyskać sumę cyfr, która musi wynosić 1.


A 0x2ffco z bazą 2 1111111111?
Peter Taylor

@PeterTaylor Masz rację, naprawiono
skopiuj

więc tak naprawdę to robisz, sprawdzając modulo 10 bez reszty, ale użyłeś 9, aby ogolić znak swojego kodu +1,!
Agregat matematyczny

To trochę oszustwo, ale inna metoda:alert(!(Number.MAX_VALUE%prompt()))
Pluton


2

python 3, 38

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

python, 32

Jednak kod nie działa w każdej wersji.

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

Zauważ, że rozwiązanie działa również dla 0 (drukuj False).


Głosowałem, ponieważ to również było moje rozwiązanie.
Josh Caswell

1
Co zrobić, jeśli zastąpi ==się &?
SimonT

@ SimonT To nie jest prawda. Zastąpienie „==” przez „&” spowoduje wydrukowanie 1 dla każdej liczby, która ma nieparzystą liczbę „1” w swojej reprezentacji binarnej. Sprawdź na przykład 7 = 111. Są 3 = 11. Zwróci 11 i 1 = 1.
Gari BN

2

Ruby - 17 znaków (czwarta próba)

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

Moim obecnym najlepszym jest połączenie odpowiedzi @ steenslag z moją własną. Poniżej znajdują się moje poprzednie próby.

Ruby - 19 znaków (trzecia próba)

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

Rubin - 22 znaków (druga próba)

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

Ruby - 24 znaki (pierwsza próba)

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

W twoim programie jest jeszcze „+”
phuclv

Wiem. : - / Poprosiłem o wyjaśnienie, czy „+” i „-” są surowo zabronione, czy też można ich używać w innych kontekstach oprócz dodawania i odejmowania. Niezależnie od tego jestem w trakcie przepisywania.
OI

Wielka poprawa. Wygląda na to, że jest to najlepszy jak dotąd wynik Ruby. Zaktualizowałem tabelę liderów w tekście pytania.
gthacoder

@gthacoder Właśnie połączyłem wyrażenie regularne steenslag z moim formatowaniem binarnym. Zdecydowanie nie mogę wziąć całego uznania.
OI

2

K / Kona ( 24 17)

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

Zwraca 1, jeśli prawda, i 0, jeśli fałsz. Każda moc 2 ma pojedynczy bit równy 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)

(to wypisuje wszystkie potęgi 2 (od 0 do 9) binarnie)

Podsumowuję więc wszystkie składniki wyrażenia binarnego xi sprawdzam, czy jest ono równe 1; jeśli tak x=2^n, to w przeciwnym razie nie.

... wiedziałem, że mogę to zmniejszyć


@gthacoder: Zmniejszyłem kod, mam nadzieję, że możesz zaktualizować swój główny post, aby to odzwierciedlić!
Kyle Kanos

Czy to nie używa dodatku? I czy to pytanie nie jest zabronione?
zgrep

2

C # (54 znaki)

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

Zadanie wyraźnie stwierdza, że ​​dane wejściowe nie są przechowywane w zmiennej, należy je uzyskać ze strumienia wejściowego pewnego rodzaju (np. Stdin), to także jest golf-golf , spróbuj nieco skrócić swój kod, przynajmniej usuwając białe znaki
mniip

Myślę, że masz na myśli Int32, a nie ToInt32...
Chris

Tak Dzięki za zwrócenie uwagi na Chrisa. Wcześniej był to Convert.ToInt32 i chciałem go zmienić na Int32.Parse, aby go skrócić. : D
Merin Nakarmi

2
użyj intzamiast o Int322 mniej znaków.
Rik

2

Rebmu (9 znaków)

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 jest zwężonym dialektem Rebola. Kod jest zasadniczo:

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

Alternatywny

14 znaków - Rebmu nie ma „mushed” bitowego AND ~

z?AND~aTIddA 3

W Rebol:

zero? a & to-integer a / 3


1

Python, 35

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

Nie używa nie tylko operacji +/-, ale również operacji matematycznych oprócz konwersji do postaci binarnej.

Inne rzeczy (ciekawe, ale nie dla konkurencji):

Mam również wersję wyrażenia regularnego (61) :

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

(Podoba mi się ten pomysł, ale funkcja importu i dopasowania powoduje, że jest za długi)

I ładna, ale nudna wersja operacji bitowych (31) :

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

(tak, jest krótszy, ale używa ~ -x do zmniejszenia, co zawiera - operacja)


Odpowiedzi boothby wykorzystują ten sam pomysł, co mój pierwszy, ale jest krótszy :(
Ivan Anishchuk

1

Python 2.7 ( 30 29 39 37)

EDYCJA: Zaktualizowano ze względu na wymagania użytkownika;

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

Brutalna siła, spróbuj podzielić, aż = 1 (sukces) lub <1 (niepowodzenie)


1
not a%2można zapisać jako a%2==0. To prawda, że ​​byłoby to dłużej w wielu językach, ale nie w Pythonie.
Konrad Borowski

@xfix Dzięki, przetestowane i zaktualizowane.
Joachim Isaksson

1
lub nawet lepiej a%2<1.
stoisko

po 2.usunięciu masz spację , która oszczędziłaby bajt!
Keerthana Prabhakaran

1

Python (33)

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

int(bin(input()*2)[3:])<1działa również z powłoki pytona z tylko 25 znakami.
gmatht


1

APL (12 dla 0/1, 27 dla tak / nie)

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

lub, jeśli musimy wyprowadzić tekst:

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

Wczytaj A. Utwórz wektor 0..A, a następnie wektor 2 0 .2 A. (tak, to bardziej niż to konieczne), a następnie wektorem porównywania każdego z tych (w wyniku tworząc wektor 0 i co najwyżej jeden 1), a następnie xor że (w APL nie ma operatora xor, ale ≠ zastosowane do boolanów będzie działać jak jeden). Mamy teraz 0 lub 1.

Aby uzyskać TAK lub NIE: pomnóż 0 lub 1 przez 3, upuść tę liczbę znaków z „TAK”, a następnie weź pierwsze 3 znaki.


1

C, 65 bajtów

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

Możesz odciąć 5 znaków przy użyciu main(k){..., polegając na niejawnym intpisaniu. Może to być UB, ale to jest golf golfowy. Oczywiście NIGDY nie używaj czegoś takiego w produkcji.
Kevin

1

Haskell ( 52 50)

k n=elem n$map(2^)[1..n]
main=interact$show.k.read
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.