Zdefiniuj funkcję f (n) dla dodatniej liczby całkowitej n w następujący sposób:
- n / 2 , jeśli n jest parzyste
- 3 * n + 1 , jeśli n jest nieparzyste
Jeśli wielokrotnie zastosujesz tę funkcję do dowolnego n większego niż 0, wynik zawsze wydaje się zbieżny do 1 (chociaż nikt nie był jeszcze w stanie tego udowodnić). Ta właściwość jest znana jako hipoteza Collatza .
Zdefiniuj czas zatrzymania liczby całkowitej jako liczbę przypadków, w których musisz przejść przez funkcję Collatz f, zanim osiągnie 1. Oto czasy zatrzymania pierwszych 15 liczb całkowitych:
1 0
2 1
3 7
4 2
5 5
6 8
7 16
8 3
9 19
10 6
11 14
12 9
13 9
14 17
15 17
Zadzwońmy do dowolnego zestawu numerów o tym samym czasie zatrzymania kuzyni Collatz . Na przykład 5 i 32 są kuzynami Collatz, z czasem zatrzymania wynoszącym 5.
Twoje zadanie: napisanie programu lub funkcji, która przyjmuje nieujemną liczbę całkowitą i generuje zestaw kuzynów Collatz, których czas zatrzymania jest równy tej liczbie całkowitej.
Wkład
Nieujemna liczba całkowita S, podana przez STDIN, ARGV lub argument funkcji.
Wydajność
Lista wszystkich liczb, których czas zatrzymania wynosi S, posortowanych w porządku rosnącym . Lista może być wyprowadzana przez twój program lub zwracana lub wyprowadzana przez twoją funkcję. Format wyjściowy jest elastyczny: separacja spacji, separacja nowego wiersza lub dowolny standardowy format listy twojego języka jest w porządku, pod warunkiem, że liczby są łatwe do odróżnienia od siebie.
Wymagania
Twoje zgłoszenie musi dawać prawidłowe wyniki dla dowolnego S ≤ 30. Powinno ono zakończyć się w ciągu sekund lub minut, a nie godzin lub dni.
Przykłady
0 -> 1
1 -> 2
5 -> 5, 32
9 -> 12, 13, 80, 84, 85, 512
15 -> 22, 23, 136, 138, 140, 141, 150, 151, 768, 832, 848, 852, 853, 904, 906, 908, 909, 5120, 5376, 5440, 5456, 5460, 5461, 32768
Oto streszczenie wyniku dla S = 30 .
To jest golf-golf : wygrywa najkrótszy program w bajtach. Powodzenia!
Odpowiedzi:
Pyth,
262421 bajtówTen kod uruchamia się natychmiast dla
S=30
. Wypróbuj sam: demonstracjaDzięki @isaacg za zapisanie 5 bajtów.
Wyjaśnienie
Mój kod zaczyna się od
1
i cofam funkcję Collatz. Mapy to wszystkie numeryd
zS-1
krokiem do2*d
i(d-1)/3
. Ten ostatni nie zawsze jest ważny.źródło
-F
.- ... 1
około sumy w środku redukcji, nie potrzebujesz redukcji.u
, ani na-F
zewnątrz. Zapisuje 2 znaki.q4%d6
jest równoważne!%hhd6
, ale o 1 znak krótszy.Mathematica,
989289 bajtówTo rozwiązanie rozwiązuje
S = 30
natychmiast:Jest to funkcja bez nazwy, która przyjmuje
S
za swój jedyny parametr i zwraca listę kuzynów Collatz.Algorytm jest prostym, szerokim wyszukiwaniem. Kuzyni Collatz dla danej
S
są wszystkie liczby całkowite, które można dojechać z kuzynów Collatz zaS-1
pośrednictwem2*n
lub liczb nieparzystych, które mogą być osiągnięte poprzez(n-1)/3
. Musimy również upewnić się, że produkujemy tylko te liczby całkowite, które zostały osiągnięte po raz pierwszy poS
krokach, więc śledzimy wszystkich poprzednich kuzynówp
i usuwamy je z wyniku. Ponieważ i tak to robimy, możemy zaoszczędzić kilka bajtów, obliczając kroki wszystkich poprzednich kuzynów (nie tylko tych zS-1
), aby zaoszczędzić kilka bajtów (co czyni to nieco wolniejszym, ale nie zauważalnie wymaganymS
).Oto nieco bardziej czytelna wersja:
źródło
Python 2,
8683757371 bajtówZadzwoń jak
f(30)
.n = 30
jest prawie natychmiastowy.(Dzięki @DLosc za pomysł rekurencji,
k
ponieważ jest liczbą, a nie listą kuzynów i kilkoma bajtami. Dziękuję @isaacg za upuszczenie~-
.)Ten wariant jest znacznie krótszy, ale niestety trwa zbyt długo z powodu wykładniczego rozgałęzienia:
źródło
f=lambda d,n=1:d and sorted(sum((c(d-1,x)for x in[n*2]+[~-n/3][:n>4==n%6]),[]))or[n]
. Jest mniej wydajny z wywołaniami funkcji, ale nadal działan = 30
w niecałą sekundę.f=lambda n,k=1:sorted([k][n:]or(k>4==k%6and f(n-1,~-k/3)or[])+f(n-1,k*2))
~-
jest to konieczne, ponieważ używasz podziału na liczby całkowite.CJam,
2926 bajtówPodziękowania dla @isaacg za pomysł usunięcia 1 po każdej iteracji, co pozwoliło mi zaoszczędzić dwa bajty bezpośrednio, a drugi pośrednio.
Wypróbuj online w interpretatorze CJam (powinien zakończyć się w niecałą sekundę).
Jak to działa
źródło
CJam, 35 bajtów
Wyjaśnienie już wkrótce. Jest to wersja znacznie szybsza niż podejście „dość proste” (zobacz w historii edycji).
Wypróbuj online tutaj, ponieważ
N = 30
działa w kilka sekund w wersji online i natychmiast w kompilatorze Javaźródło
It should finish in seconds or minutes, not hours or days.
S=15
nie działa.Java 8, 123
Gdy
x
jest 30, program trwa 15 minut i 29 sekund.Rozszerzony
źródło
javac 1.7.0_79
z Ubuntu dało mi wiele błędów składniowych.i > 1 && ++n <= x
(możeszn++
też upuścić ) wydaje się jeszcze szybsze o zaledwie 5 dodatkowych znaków ... dla mnie około 3 minut dla S = 30. To zostaje ogolone do bezpiecznego poniżej minuty, jeśli uwzględnię.parallel()
również, ale ponieważ jest to kod-golf ...Python 2, 118 bajtów
Pomyślałem, że nie osiągnęłbym najlepszego wyniku w Pythonie po obejrzeniu rozwiązania @ Sp3000. Ale wyglądało to na zabawny mały problem, więc i tak chciałem wypróbować niezależne rozwiązanie:
To samo przed usunięciem białych znaków:
Jest to bardzo bezpośrednia implementacja szerokiego pierwszego wyszukiwania. Na każdym kroku mamy zestaw z czasem zatrzymania
k
, i uzyskujemy zestaw z czasem zatrzymaniak + 1
, dodając możliwych poprzedników każdej wartościt
w zestawie z krokuk
:2 * t
jest zawsze możliwym poprzednikiem.t
można zapisać jako3 * u + 1
, gdzieu
jest liczbą nieparzystą, która nie jest1
, tou
jest również poprzednikiem.Uruchomienie
N = 30
mojego MacBooka Pro zajmuje około 0,02 sekundy .źródło
s.add(x)
jest konieczne w golfie, ponieważ zwykle można to zrobićs|={x}
zamiast tego. Ponadto,~-x
zamiast(x+1)
zapisywać w nawiasach. Ale poza tym dobra robota :)s.add()
ponieważ staje się zadaniem i nie może już być częścią wyrażenia. Działa dla pierwszego. Tefor
pętle oparte na liczniki są zawsze rodzaju gadatliwy jak również. Myślałem, że mogę go skrócić za pomocąwhile
pętli, ale okazało się, że ma dokładnie taką samą długość.for
pętli, ponieważ nie używasz danych w inny sposób, prawdopodobnie możesz to zrobićexec"..."*input()
:)PHP 5.4+, 178 bajtów
Funkcja
Test i wyjście
S (30) działa w 0,24 sekundy * , zwraca 732 elementy. Kilka jest
* Aby zaoszczędzić na bajtach, musiałem dodawać
ksort
iarray_keys
na każdym kroku. Jedynym innym wyborem, jaki miałem, było wykonanie małej funkcji otoki, która wywołuje,c()
a następnie wywołujearray_keys
iksort
raz wynik. Ale ponieważ czas wciąż był przyzwoity, postanowiłem wziąć hit za niską liczbę bajtów. Bez właściwego sortowania i przetwarzania dla S (30) czas wynosi średnio 0,07 sekundy .Jeśli ktoś ma jakieś sprytne sposoby uzyskania poprawnego przetwarzania tylko raz bez zbyt wielu dodatkowych bajtów, daj mi znać! (Przechowuję moje liczby jako klucze tablicy, stąd użycie
array_keys
iksort
)źródło
Język C.
źródło
{}
przycisk, aby sformatować kod, co dla ciebie zrobiłem. Ale jak mówi Alex, dodaj nazwę języka (C?) I spróbuj zagrać w golfa :) Ale witaj!f
nie działa poprawnie. Dziękis=5
otrzymuję kilka niepoprawnych wyników.if (r == s)return true;
powinno byćreturn (r==s)
, ponieważf
nie zwróci niczego znaczącego, kiedy(r < s)
. Także myślę, że należy zadeklarowaći
wf
taklong
, ponieważ będzie przelewać dość szybko dla niektórych wartości.return (r==s);