To jest wersja ostatniego wyzwania. Czy ta liczba jest potęgą całkowitą -2? z innym zestawem kryteriów zaprojektowanych w celu podkreślenia interesującej natury problemu i utrudnienia wyzwania. Zastanowiłem się nad tym tutaj .
Wyzwanie, jak wspaniale stwierdził Toby w powiązanym pytaniu, to:
Istnieją sprytne sposoby określania, czy liczba całkowita jest dokładną potęgą 2. To już nie jest interesujący problem, więc ustalmy, czy dana liczba całkowita jest dokładną potęgą -2 . Na przykład:
-2 => yes: (-2)¹ -1 => no 0 => no 1 => yes: (-2)⁰ 2 => no 3 => no 4 => yes: (-2)²
Zasady:
- Liczba całkowita to 64 bity, ze znakiem, uzupełnienie dwóch. To jedyny typ danych, z którym możesz pracować.
- Możesz używać tylko następujących operacji. Każda z nich liczy się jako jedna operacja.
n << k
,n >> k
: Przesunięcie w lewo / prawon
ok
bity. Bit znaku jest przedłużany przy przesunięciu w prawo.n >>> k
: Przesunięcie w prawo, ale nie przedłużaj bitu znakowego. Zera są przesunięte.a & b
,a | b
,a ^ b
: Bitowe AND, OR, XOR.a + b
,a - b
,a * b
: Dodawanie, odejmowanie, mnożenie.~b
: Odwrócenie bitowe.-b
: Negacja dopełniacza Two.a / b
,a % b
: Podziel (iloraz liczby całkowitej, zaokrągla w kierunku 0) i modulo.- Modulo liczb ujemnych wykorzystuje reguły określone w C99 :
(a/b) * b + a%b
powinno być równea
. Tak5 % -3
jest2
i-5 % 3
jest-2
: 5 / 3
jest1
,5 % 3
jest2
, ponieważ 1 * 3 + 2 = 5.-5 / 3
jest-1
,-5 % 3
jest-2
, ponieważ -1 * 3 + -2 = -5.5 / -3
jest-1
,5 % -3
jest2
, ponieważ -1 * -3 + 2 = 5.-5 / -3
jest1
,-5 % -3
jest-2
, ponieważ 1 * -3 + -2 = -5.- Zauważ, że
//
operator podziału podłogi w Pythonie nie spełnia tutaj właściwości podziału zaokrąglenie do zera, a%
operator języka Python również nie spełnia wymagań.
- Modulo liczb ujemnych wykorzystuje reguły określone w C99 :
- Przydziały nie są liczone jako operacja. Podobnie jak w C, przypisania oceniają wartość po lewej stronie po przypisaniu:
a = (b = a + 5)
ustawia sięb
naa + 5
, następnie ustawia sięa
nab
i liczy się jako jedna operacja. - Przypisania złożone mogą być użyte jako
a += b
środkia = a + b
i można je liczyć jako jedną operację.
- Możesz użyć stałych całkowitych, nie liczą się jako nic.
- Dopuszczalne są nawiasy określające kolejność operacji.
- Możesz zadeklarować funkcje. Deklaracje funkcji mogą mieć dowolny dogodny styl, ale należy pamiętać, że 64-bitowe liczby całkowite są jedynym prawidłowym typem danych. Deklaracje funkcji nie liczą się jako operacje, ale wywołanie funkcji liczy się jako jedna. Dla jasności: funkcje mogą zawierać wiele
return
instrukcjireturn
is z dowolnego punktu są dozwolone.return
Sama nie liczy się jako operacji. - Możesz zadeklarować zmienne bez żadnych kosztów.
- Możesz używać
while
pętli, ale nie możesz używaćif
lubfor
. Operatory użyte w tymwhile
stanie liczą się do twojego wyniku.while
pętle działają, dopóki ich stan nie jest zerowy („prawda” 0 w językach, które mają tę koncepcję, nie jest poprawnym wynikiem). Od wczesnego powrotu jest dozwolone, są dopuszczone do wykorzystaniabreak
, jak również - Przepełnienie / niedopełnienie jest dozwolone i nie zostanie wykonane żadne ustalanie wartości. Traktuje się to tak, jakby operacja faktycznie przebiegła poprawnie, a następnie została obcięta do 64 bitów.
Kryteria punktacji / wygranej:
Twój kod musi generować wartość niezerową, jeśli dane wejściowe mają potęgę -2, a w przeciwnym razie zero.
To jest golf atomowy . Twój wynik to całkowita liczba operacji obecnych w kodzie (jak zdefiniowano powyżej), a nie całkowita liczba operacji wykonanych w czasie wykonywania. Następujący kod:
function example (a, b) {
return a + ~b;
}
function ispowerofnegtwo (input) {
y = example(input, 9);
y = example(y, 42);
y = example(y, 98);
return y;
}
Zawiera 5 operacji: dwie w funkcji i trzy wywołania funkcji.
Nie ma znaczenia, w jaki sposób prezentujesz swój wynik, używasz wszystkiego, co jest wygodne w twoim języku, czy to ostatecznie przechowuje wynik w zmiennej, zwraca go z funkcji, czy cokolwiek innego.
Zwycięzcą jest post, który jest w sposób oczywisty poprawny (w razie potrzeby należy przedstawić zwykły lub formalny dowód) i ma najniższą ocenę, jak opisano powyżej.
Bonus Very Hard Mode wyzwanie!
Aby uzyskać szansę na wygranie absolutnie nic oprócz potencjalnej zdolności do zaimponowania ludziom na przyjęciach, prześlij odpowiedź bez użycia while
pętli! Jeśli zostanie dostarczonych wystarczająca ich liczba, mogę nawet rozważyć podzielenie zwycięskich grup na dwie kategorie (z pętlami i bez).
Uwaga: jeśli chcesz podać rozwiązanie w języku, który obsługuje tylko 32-bitowe liczby całkowite, możesz to zrobić, pod warunkiem, że wystarczająco uzasadnisz, że będzie to nadal poprawne dla 64-bitowych liczb całkowitych w wyjaśnieniu.
Ponadto: Niektóre funkcje specyficzne dla języka mogą być dozwolone bez ponoszenia kosztów, jeśli nie omijają zasad, ale są niezbędne do zmuszenia języka do zachowywania się zgodnie z powyższymi zasadami . Na przykład (wymyślony), zezwalam na bezpłatne porównanie z równością 0 w while
pętlach, gdy zostanie zastosowane do warunku jako całości, jako obejście dla języka, który ma „prawdziwe” zera. Wyraźne próby wykorzystania tego rodzaju rzeczy są niedozwolone - np. Koncepcja „prawdy” 0 lub „niezdefiniowanych” wartości nie istnieje w powyższym zestawie reguł, więc nie można na nich polegać.
źródło
m ^= s
imponujące, i myślę, że byłoby całkowicie OK, aby dokonać zmiany, aby ją jeszcze bardziej ulepszyć.while
ibreak
jednak nieif
?if (x) { ... }
jest równoważne zwhile (x) { ... break; }
.break
a wczesne zwroty są częścią godną pożałowania) i jest długą historią i lekcją wyciągniętą z zasad dotyczących przyszłych wyzwań. Zawsze dostępna jest wersja „bonusowa”! :)if
ifor
są niedozwolone?int x=condition; while (x) { ... x=0; }
jest darmowy, tylko więcej kodu. To samo z c-stylufor
.Odpowiedzi:
C ++, 15 operacji
Nie mam pojęcia, dlaczego
while
pętle są dozwolone, ponieważ niszczą całe wyzwanie. Oto odpowiedź bez żadnej:źródło
while
pętle niszczą całe wyzwanie ?while
pod każdym względem jest przeciwne.n
lub czegoś takiego.uint64_t
ponieważ jest to jedyny sposób, aby uzyskać właściwą zmianę bez rozszerzenia znaku).Operacje w języku Python 2 , 3
Wypróbuj online!
Operacje są
>>
,&
,/
.Chodzi o wielokrotne dzielenie przez -2. Uprawnienia -2 łańcucha do 1:
-8 -> 4 -> -2 -> 1
. Jeśli trafimy a1
, zaakceptuj. Jeśli trafimy nieparzystą liczbę przed uderzeniem1
, odrzuć. Musimy także odrzucić0
, co na zawsze idzie w parze.while n>>1:
Pętli ażn
wynosi 0 lub 1. W przypadku przerwy w pętli,n
zwracana jest, i1
ma wyjście Truthy i0
jeden Falsey. Wewnątrz pętli wielokrotnie odrzucamy stosowanien -> n/-2
i odrzucamy wszelkie nieparzysten
.Ponieważ
/
zawsze stosuje się go w parzystych wartościach, jego zaokrąglanie nigdy nie wchodzi w grę. Więc nie ma znaczenia, że Python zaokrągla inaczej niż w specyfikacji.źródło
while n&1
zamiastif n&1
?if
.Rdza,
1412 operacji (bez pętli)Wymaga optymalizacji (
-O
) lub-C overflow-checks=no
włączenia przepełnienia odejmowania zamiast paniki.(Aby wyjaśnić:
!x
jest bitowe-NIE tutaj, nie logiczne-NIE)Przypadki testowe:
Wypróbuj online!
Chodzi o sprawdzenie, czy | x | jest potęgą 2 (używając
(y & (y - 1)) == 0
jak zwykle). Jeśli x jest potęgą 2, to dalej sprawdzamy (1) kiedyx >= 0
, powinna to być również parzysta potęga 2, lub (2) kiedyx < 0
, powinna to być nieparzysta potęga 2. Sprawdzamy to poprzez&
„bad_power_of_two
"maska 0x… aaaa kiedyx >= 0
(produkuje 0 tylko wtedy, gdy jest parzystą potęgą) lub 0x… 5555 kiedyx < 0
.źródło
~((r | -r) >> 63)
sztuczkę, by dokończyć naprawianie mojej odpowiedzi.Haskell,
23 operacjeDefiniuje funkcję rekurencyjną
f(n)
. Stosowane operacje to wywołanie funkcji (f
), dzielenie (div
) oraz bitowe i (.&.
).Nie zawiera żadnych pętli, ponieważ Haskell nie ma instrukcji pętli :-)
źródło
f 0
,f 1
,f n ...
tutaj, ponieważ są one w istocieif
„s w przebraniu, chociaż z drugiej strony, ja nie pozwalająwhile
+break
i wczesnereturn
s, więc wydaje się targi. Chociaż wydaje się, że korzysta z mojego zestawu reguł, który został przypadkowo pozostawiony otwarty na interpretację, jest to miłe rozwiązanie.|
są w powietrzu. To powiedziawszy, narusza to jedną konkretną zasadę w mniej dyskusyjny sposób: Porównanie==
nie jest dozwolone. Zauważ jednak, że jeśli moja interpretacja tego kodu jest prawidłowa, użycie booleanów tutaj wydaje się akceptowalne, ponieważ zastępowanie dowolnych wartości całkowitych w ich miejscu nie wydaje się zmieniać wyników, a są one bardziej ostateczną formą prezentacji.==
, ponieważ nie ma innego sposobu, aby z obsadąInt
doBool
lub „Truthy” w Haskell. To, czy dopasowanie wzorca i strażnicy naruszająif
zasadę „no s”, jest twoim wezwaniem ;-)Operacje w Pythonie 3,
10 lub 119Zwraca
5
za moce-2
,0
inaczejźródło
C, 5 operacji
C, 10 operacji, bez pętli
C, 1 operacja
źródło
Montaż, 1 operacja
Używa ogromnej tabeli odnośników, aby sprawdzić, czy liczba jest potęgą 2. Możesz ją rozszerzyć do 64 bitów, ale znalezienie komputera do przechowywania takiej ilości danych pozostało ćwiczeniu dla czytelnika :-P
źródło
C, 31 operacji
Demo na żywo
Mój pomysł jest prosty, jeśli jest potęgą dwóch, to jeśli jego log jest nawet wtedy, musi być dodatni, w przeciwnym razie jego log musi być nieparzysty.
źródło
C, 7 operacji
lub:
C, 13 operacji bez pętli jako warunków
Wyjaśnienie:
n&-n
daje najniższy ustawiony bitn
.a
jest zanegowaną wartością bezwzględnąn/2
, koniecznie ujemną, ponieważ/2
wyklucza przepełnienie negacji.a/x
wynosi zero tylko wtedy, gdya
jest dokładną siłą dwóch; w przeciwnym razie ustawiony jest co najmniej jeden inny bit i jest on wyższy niżx
najniższy bit, co daje wynik ujemny.~(a/x >> 63)
następnie zwraca maskę bitową, która jest jednością, jeślin
lub-n
jest potęgą dwóch, w przeciwnym razie zerami.^s
jest nakładany na maskę, aby sprawdzić znak,n
aby zobaczyć, czy jest to moc-2
.źródło
PHP, 3 operacje
trójskładnikowe i
if
są niedozwolone; więc nadużyciewhile
:$n>>1
: jeśli liczba to 0 lub 1, zwróć liczbę$n&1
: jeśli liczba jest nieparzysta, zwróć 0$n/-2
(+ rzut na int)źródło
JavaScript ES6, 7 operacji
Wypróbuj online!
Wyjaśnienie
Podczas X! = 0 i X% 2 == 0 4 OPS
/ x jest równe 1, tak długo jak nie ma wartości 0 x (0/0 daje NaN które oceniano jako FAŁSZ)
-bitowe i
X 1 ^ 1 jest równe 1 jeśli x jest parzyste (x i 1) x lub 1
Jest to forma podziału zdefiniowana w pytaniu 1 op
Podczas gdy x! = 1 i x! = 0 1 operacja
Warunek konieczny do wyjścia, gdy x == 0 lub x == 1, ponieważ te dwie wartości zwracają i wejście w nieskończoną pętlę nie byłoby produktywne. Można to teoretycznie rozszerzyć dla większych wartości poprzez zwiększenie liczby szesnastkowej. Obecnie działa do ± 2 ^ 32-1
Ustaw x na 0 1 op.
Chociaż mógłbym użyć return 0 dla 0 operacji, czułem, że pętla while, która jest przerwana przez inną instrukcję, wydaje się zbyt podobna do oszustwa.
zwraca x (1 jeśli moc -2, 0 w przeciwnym razie)
źródło