Liczby Fibbinary to takie liczby naturalne, które w zapisie binarnym nie mają dwóch cyfr 1 zapisanych obok siebie.
Liczbą Fibbinary jest przykładowo liczba 10, ponieważ 10 = 10102. Jak można zauważyć, że w zapisie nie ma dwóch cyfr 1 obok siebie. Jednak już dla 11 = 10112 taka sytuacja ma miejsce, więc 11 nie należy do tego zbioru liczb.
Ustawiając liczby Fibbinary w ciąg otrzymujemy: 0, 1, 2, 4, 5, 8, 9, 10, 16, 17, 18, ...
Napisz funkcję, która sprawdzi czy podana liczba całkowita a jest liczbą Fibbinary. Przetestuj działanie napisanej funkcji.
Pierwszy sposób rozwiązania tego zadania polega na sprawdzeniu każdej pary bitów przekazanej liczby w poszukiwaniu wartości 11. Tego typu rozwiązanie jest zależne od ilości bitów z których składa się liczba. Oto przykładowa implementacja funkcji czyFibbinary().
(2.) Dla każdej pary bitów: (3.) pobierz dwa kolejne i sprawdź czy obie wartości są ustawione (112 = 3).
Wbrew pozorom sprawdzenie każdej pary bitów jest procesem czasochłonnym i istnieje bardziej efektywne rozwiązanie. Wiadomo, że między każdą parę cyfr 1 w zapisie musi istnieć wartość 0. Oznacza to, że jeśli wszystkie bity zostałyby przesunięte o 1 w prawo to gwarantowane jest, że w miejsce 1 pojawi się 0. W przypadku, gdy nie jest to liczba Fibbinary to na któreś pozycji zamiast 0 wciąż będzie znajdować się wartość 1. Sprawdzenie czy dwie liczby mają wartość na tej samej pozycji można wykonać wywołując operacje binarną AND na obu wartościach. Cyfry 1 zostaną tylko tam gdzie występują w jednej i drugiej liczbie na tej samej pozycji i wtedy wynik jest niezerowy. (Wszystkie pary 0 i 1 oraz 0 i 0 przyjmą wartość 0).
Rozpatrzmy przykładowo przykład wartości 10 zapisanej na 8 bitach:
10 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
10 >> 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
AND | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Jak można zauważyć wynik operacji AND jest 0, więc jest to liczba Fibbinary. Z kolei dla liczby 11 zostaną otrzymane następujące wartości:
11 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
---|---|---|---|---|---|---|---|---|
11 >> 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
AND | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Tym razem wynik jest niezerowy. Oznacza to, że nie jest to liczba Fibbinary. Tego typu rozwiązanie jest niezależne od długości liczby, ponieważ przyjmuje się, że operacje binarne są operacjami atomowymi. Oto przykładowa implementacja:
Poniższy kod wypisze pierwsze n liczb Fibbinary, gdzie n to liczba wczytana od użytkownika.
Przyjmuje się, że każdą liczbę Fibbinary można zapisać jako sumę dwóch innych liczb Fibbinary. Napisz funkcję podajeSume(), która dla podanej liczby a znajdzie jakich dwóch liczb Fibbinary jest sumą liczba a. Jeśli jest więcej niż jedno unikalne rozwiązanie też je wypisz. Zakładamy, że dodawane liczby nie muszą być różne. Przetestuj działanie napisanej funkcji.
Przykładowo dla liczby 18 będzie to: