Biorąc pod uwagę liczbę n> 77 , napisz program lub funkcję, która znajdzie zestaw różnych dodatnich liczb całkowitych, tak że suma zbioru jest równa n , a suma odwrotności zbioru wynosi 1.
Przykład dla 80:
80 = 2 + 4 + 10 + 15 + 21 + 28 ⟶ 1/2 + 1/4 + 1/10 + 1/15 + 1/21 + 1/28 = 1
Twój program lub funkcja musi (teoretycznie) działać dla dowolnego n <2 32 i nie jest usprawiedliwiony dla błędów zaokrąglania zmiennoprzecinkowego. Zauważ, że istnieją rozwiązania dla wszystkich n> 77 .
Najkrótszy kod w bajtach wygrywa.
Istnieje dodatkowa zachęta: przyznam nagrodę za najmniejsze rozwiązanie, które działa dla dowolnego n i uruchamia log (n) . Dla małych n musi być szybki (ustalony według własnego uznania). Tak, jest to możliwe.
O(log n)
algorytm.Odpowiedzi:
Mathematica, 54 bajty
Jest tak mało wydajny, jak to możliwe, ale rozwiązuje się
n = 78
w około 9 sekund.Wynik jest zwracany jako lista zawinięta w listę singletonów, np .:
źródło
Python 3,
73061995 BytesTo rozwiązanie działa w złożoności log (n) (o ile mogę powiedzieć).
Możesz przetestować, że
f(2**32 - 1)
działa prawie natychmiastUżyłem tego artykułu do metody jego obliczania. Dzięki tej metodzie istnieje ogromna porcja danych dla wstępnie ustalonych wartości dla n od 78 do 334 bez liczb parzystych po 168. Chciałem przekształcić te dane w coś małego i nie znałem żadnych dobrych algorytmów kompresji, więc zrobiłem własny.
Sposób, w jaki to skompresowałem, polegał na tym, że lista reguł zastępujących ciąg znaków. Stworzyłem metodę, która znalazła regułę zamiany ciągu, która ograniczyłaby najwięcej treści, biorąc pod uwagę jej zdefiniowanie. Następnie zastosowałem to rekurencyjnie, dopóki nie mogłem utworzyć więcej reguł (użyłem znaków gz i AZ). Ciąg, który utworzyłem w celu zastąpienia, był oddzieloną przecinkami listą wartości szesnastkowych dla każdej z liczb. Patrząc wstecz, konwersja ich na wartości szesnastkowe może nie była najmądrzejszym wyborem, prawdopodobnie pozostawienie ich w liczbach dziesiętnych byłoby krótsze, ponieważ zapisanie szesnastkowe zachowałoby tylko liczby 3-cyfrowe, ale dodałoby 0 dla liczb jednocyfrowych.
Linia, w której ustawiam c, zawiera listę reguł zastępowania i tekst, na którym jest uruchamiany. Reguły należy stosować również w odwrotnej kolejności, ponieważ niektóre reguły obejmują postacie utworzone na podstawie innych reguł.
Istnieje również wiele miejsc w tym kodzie, w których prawdopodobnie mógłbym ograniczyć składnię, na przykład zmieniając listę list w jedną listę, a następnie używając innej metody dostępu do reguł w celu zastąpienia tekstu
źródło
n=218
wyniki[2]
są takie, jakich się spodziewasz?Haskell, 93 bajty
Strasznie wolne 1, ale działa w stałej pamięci. Trywialne rozwiązanie: sprawdź wszystkie podsekwencje
[2..n]
dla sumy i sumy wzajemności.Zwrócenie wszystkich rozwiązań zamiast jednego jest o 3 bajty krótsze: po prostu usuń
!!0
(uwaga: czas działania zawsze będzie poza harmonogramem).1 Czas działania zależy od tego, jak wcześnie wynik pojawia się na liście podsekwencji. Leniwość Haskella zatrzymuje wyszukiwanie, jeśli zostanie znalezione pierwsze dopasowanie. Po skompilowaniu
p 89
(wynik[3,4,6,9,18,21,28]
:) działa na moim (4-letnim) laptopie w wieku 35 lat. Inne wartości, nawet te mniejsze, mogą trwać kilka godzin.źródło
Julia, 77 bajtów
Jest to nieefektywna funkcja lambda, która przyjmuje liczbę całkowitą i zwraca tablicę liczb całkowitych. Aby go wywołać, przypisz go do zmiennej.
Otrzymujemy partycje liczby całkowitej za pomocą
partitions
. Następnie filtrujemy zestaw partycji tylko do tych z unikalnymi elementami, których wzajemności sumują się do 1. Aby upewnić się, że nie wystąpi błąd zaokrągleń, używamy typu JuliiRational
do konstruowania wzajemności.filter
zwraca iterator, więc musimy tocollect
zrobić w tablicy. To daje nam tablicę tablic (z tylko jednym elementem), dzięki czemu możemy uzyskać pierwsze użycie[1]
.Kiedy mówię „nieefektywny”, mam na myśli to. Uruchomienie tego dla n = 80 zajmuje 39,113 sekundy na moim komputerze i przydziela 13,759 GB pamięci.
źródło