[Algorytmy][ProjectEuler] Problem Collatza

MichalProg
Użytkownik
Użytkownik
Posty: 411
Rejestracja: 28 cze 2011, o 21:11
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 62 razy
Pomógł: 1 raz

[Algorytmy][ProjectEuler] Problem Collatza

Post autor: MichalProg »

Dzień dobry.

Próbuję rozwiązać problem z tej strony (projecteuler.net). Należy znaleźć najdłuższy ciąg wyrazów, o wyrazie początkowym \(\displaystyle{ a _{1} < 10 ^{6}}\), liczony wg wzoru Collatza. Nie wiem jednak, jakich sprytnych algorytmów/właściwości użyć, aby to szybko policzyć. Bruteforce chyba odpada, poza tym chciałbym się tu czegoś nauczyć, a nie tylko wklepać siłowy kod.

Proszę o wskazówki.
Link do zadania:

Kod: Zaznacz cały

https://projecteuler.net/problem=14


Dzięki.
Michał
Ostatnio zmieniony 8 kwie 2017, o 13:37 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Kaf
Użytkownik
Użytkownik
Posty: 826
Rejestracja: 8 wrz 2013, o 11:31
Płeć: Mężczyzna
Lokalizacja: Wrocław
Pomógł: 187 razy

[Algorytmy][ProjectEuler] Problem Collatza

Post autor: Kaf »

Ja bym liczył po kolei te "ciągi Collatza" dla kolejnych liczb naturalnych z zastrzeżeniem, że jeśli jakąś liczba już wystąpiła w którymś ze wcześniejszych ciągów, to dla niej nie liczymy tego ciągu.
Awatar użytkownika
mortan517
Użytkownik
Użytkownik
Posty: 3359
Rejestracja: 6 lis 2011, o 15:38
Płeć: Mężczyzna
Lokalizacja: Krk
Podziękował: 112 razy
Pomógł: 662 razy

[Algorytmy][ProjectEuler] Problem Collatza

Post autor: mortan517 »

Do miliona to nie aż tak dużo, kiedyś pisałem to zadanie.
Awatar użytkownika
Slup
Użytkownik
Użytkownik
Posty: 793
Rejestracja: 27 maja 2016, o 20:49
Płeć: Kobieta
Lokalizacja: Warszawa
Podziękował: 23 razy
Pomógł: 156 razy

[Algorytmy][ProjectEuler] Problem Collatza

Post autor: Slup »

Tu nie ma w ogóle matematyki i jest dosyć częste na PE, a szczególnie przy początkowych problemach. Napisałem algorytm, który używał programowania dynamicznego(tak jak sugerował Kaf). Dowiedziałem się, że to było niepotrzebne, bo najdłuższy ciąg Collatza dla wyrazów początkowych od \(\displaystyle{ 1}\) do \(\displaystyle{ 10^6}\) ma \(\displaystyle{ 525}\) wyrazów. Oznacza to, że jest spora szansa, że algorytm typu bruteforce będzie działał. Podejrzewam, że średnia złożoność obliczeniowa algorytmu bruteforce jest wcale niezła. Zresztą na forum PE niektórzy deklarowali, że użyli bruteforce i wynik wyszedł im w kilka sekund.

Jeśli wolisz programowanie dynamiczne(w ramach ćwiczenia), to zdefiniuj tablicę \(\displaystyle{ A}\) typów Int o długości \(\displaystyle{ 10^6+1}\), której \(\displaystyle{ i}\) te miejsce będzie długością ciągu Collatza, który zaczyna się od \(\displaystyle{ i}\). Następnie skonstruuj ją rekurencyjnie w ten sposób, że \(\displaystyle{ A[0]=0}\), \(\displaystyle{ A[1]=1}\) i jeśli masz już wartości tablicy dla \(\displaystyle{ 0,1,...,i}\) to wartość w \(\displaystyle{ i+1}\) znajdujesz w ten sposób, że uruchamiasz ciąg Collatza dla \(\displaystyle{ i+1}\), liczysz liczbę jego wyrazów zmienną \(\displaystyle{ k}\), ale jednocześnie sprawdzasz na bieżąco, czy obliczony w danym momencie wyraz \(\displaystyle{ m}\) tego ciągu nie jest przypadkiem mniejszy od \(\displaystyle{ i+1}\). Jeśli jest mniejszy, to definiujesz \(\displaystyle{ A[i+1]=k+A[m]}\). W przeciwnym przypadku liczysz dalej aż \(\displaystyle{ m}\) będzie mniejszy od \(\displaystyle{ i+1}\).
Można to jeszcze ulepszyć i dodatkowo sprawdzać za każdym razem czy \(\displaystyle{ m<10^6+1}\). Wtedy można przy okazji znaleźć od razu \(\displaystyle{ A[m]}\), ale to chyba sprawia, że kod będzie nieprzejrzysty.

Poprawna odpowiedź to:
Ukryta treść:    
Przynajmniej taką mi przyjęli w PE.

Uwaga. Do przechowywania wyrazów ciągu Collatza używaj zmiennej typu Long, bo dla wyrazów początkowych w okolicach \(\displaystyle{ 120000}\) ciąg Collatza wychodzi poza \(\displaystyle{ 2^{32}}\).
ODPOWIEDZ