Biorąc pod uwagę dodatnią liczbę całkowitą, wypisz liczbę kroków potrzebnych do znalezienia danych wejściowych poprzez wyszukiwanie binarne od 1.
Symulujemy binarne wyszukiwanie liczby całkowitej podanej jako dane wejściowe, w której symulowany wyszukiwarka może wielokrotnie zgadywać liczbę całkowitą i otrzymywać informację, czy jest ona za wysoka, za niska lub poprawna. Strategia znajdowania liczby całkowitej jest następująca:
Niech n będzie liczbą całkowitą podaną jako dane wejściowe, które próbujemy znaleźć.
Zacznij od zgadywania 1. (Dla każdego zgadnięcia zwiększ liczbę kroków (niezależnie od tego, czy było poprawne, czy nie)) i natychmiast zatrzymaj i wyślij całkowitą liczbę kroków, jeśli zgadnięcie było poprawne.)
Dwukrotnie zgadnij, aż zgadnięcie będzie większe niż n (liczba docelowa). (Lub jeśli jest to poprawne, ale jest to już objęte naszą regułą zgadywania, o której mowa powyżej.)
Teraz ustaw górną granicę pierwszej potęgi 2, która jest większa niż n (tj. Właśnie odgadnięta liczba), i ustaw dolną granicę potęgi 2 bezpośrednio pod nią.
Wielokrotnie zgadnij średnią (zaokrągloną w dół) górnej granicy i dolnej granicy. Jeśli jest za wysoko, ustaw go jako górną granicę. Jeśli jest za niski, ustaw go jako dolną granicę. Ta procedura gwarantuje, że ostatecznie spowoduje prawidłowe zgadnięcie.
Oto przykład wprowadzenia n = 21:
1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 24 -> 20 -> 22 -> 21
\__________________________/
repeated doubling \________________________/
repeated averaging
Ponieważ jest to code-golf , wygra najkrótszy kod w bajtach.
Oto wszystkie dane wyjściowe od n = 1 do n = 100:
1
2
4
3
6
5
6
4
8
7
8
6
8
7
8
5
10
9
10
8
10
9
10
7
10
9
10
8
10
9
10
6
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
8
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
7
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
10
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
9
14
13
14
12
A oto kilka większych przypadków testowych:
1234 -> 21
1337 -> 22
3808 -> 19
12345 -> 28
32768 -> 16
32769 -> 32
50000 -> 28
Galaretka,
1815109 bajtówWypróbuj online! lub sprawdź małe przypadki testowe i duże przypadki testowe .
tło
Niech N jest liczbą całkowitą dodatnią, a m najmniejszą moc 2 , która jest równa lub większa niż lub równa n .
Faza podwojenia ma jeden krok dla każdej cyfry w binarnej reprezentacji m .
Weź binarną reprezentację n , usuń pierwszą, najbardziej znaczącą cyfrę (zawsze 1 ) i wszystkie zera końcowe. Faza uśredniania trwa jeden krok dla każdej pozostałej cyfry.
Aby uniknąć obliczenia m , obserwujemy, że jeśli n <m , liczba cyfr binarnych n jest dokładnie o jeden mniejsza niż liczba cyfr binarnych m .
Jeśli zamienimy pierwszą cyfrę binarną n na 0 , odwróć wynik, dołącz oryginalne cyfry binarne i usuń wszystkie początkowe zera, a następnie:
Jeśli n jest potęgą 2 , wszystkie cyfry pierwszej (zmodyfikowanej) połowy są usuwane, pozostawiając tylko cyfry oryginalnej reprezentacji binarnej n = m .
Jeśli n jest nie potęgą liczby 2 , cyfra w pierwszej połowie, która odpowiada najbardziej znaczącej cyfry ma nie zostaną usunięte, kompensując tym, że n ma binarną cyfrę mniej niż m .
Jak to działa
źródło
’B;Bt0L
(7 bajtów) działa w najnowszej wersji Jelly, przy użyciu tego samego podejścia, co w mojej odpowiedzi Julii .ES6, 38 bajtów
Jak wspomniano w innych odpowiedziach, można obliczyć liczbę kroków na podstawie pozycji pierwszego i ostatniego bitu.
Liczba kroków w fazie podwojenia wynosi
n=33-Math.clz32(x-1)
. Chcemy 2ⁿ ≥ x, alen=33-Math.clz32(x)
daje nam 2ⁿ> x, więc odejmujemy 1 od x, aby to zrekompensować.Liczba kroków w fazie uśredniania jest łatwiejsza, po prostu
n=Math.clz32(x&-x)-Math.clz32(x)
.x&-x
jest przydatnym wyrażeniem, które ocenia do najniższego bitux
(jako potęga 2).źródło
x&-x
działa Myślałbym, że oszacuje to wartość bezwzględną x.Pyth,
1513 bajtówOdkryłem, że liczba do obliczenia to
1 + 2*ceil(log_2(x)) - [number of 2s in x's prime factorization, minus 1 if x is a power of 2 greater than 1].
Wypróbuj tutaj .
źródło
Julia,
3735 bajtówDzięki @AlexA. za zapisanie 2 bajtów!
Jest to zgodne z obserwacjami z mojej odpowiedzi Jelly , ale inaczej traktuje przypadki brzegowe.
Jeśli n> 1 , binarna reprezentacja n - 1 ma jedną cyfrę mniejszą niż jedna z następnej potęgi 2 , co jest kompensowane przez nie usuwanie pierwszej cyfry binarnej reprezentacji n .
Usuwając wszystkie zera z obu stron , zajmujemy się również przypadkiem krawędzi 1 .
źródło
Haskell, 82 bajty
Jest to dość prosta implementacja w Haskell:
Mniej golfa:
źródło