Rozważ funkcję, Remove(n, startIndex, count)
która usuwa count
cyfry z numeru n
rozpoczynającego się od cyfry na pozycji startIndex
. Przykłady:
Remove(1234, 1, 1) = 234
Remove(123456, 2, 3) = 156
Remove(1507, 1, 2) = 07 = 7
Remove(1234, 1, 4) = 0
Będziemy nazywać liczbę pierwszą X kruchą, jeśli każda możliwa Remove
operacja spowoduje, że będzie ona niepierwszorzędna. Na przykład 80651 jest kruchą liczbą pierwszą, ponieważ wszystkie następujące liczby nie są liczbami pierwszymi:
651, 51, 1, 0, 8651, 851, 81, 8, 8051, 801, 80, 8061, 806, 8065
Cel
Napisz program, który znajdzie największą kruchą liczbę pierwszą. Edycja: usunięto limit czasu, ponieważ istniał względnie sprawiedliwy sposób na obejście go.
Wynik to krucha liczba pierwsza znaleziona przez twój program. W przypadku remisu wygrywa wcześniejsze zgłoszenie.
Zasady
- Możesz używać dowolnego języka i dowolnych bibliotek stron trzecich.
- Program uruchamiasz na własnym sprzęcie.
- Możesz użyć probabilistycznych testów pierwszeństwa.
- Wszystko jest w bazie 10.
Wiodące wpisy
- 6629 cyfr według Qualtagh (Java)
- 5048 cyfr według Emila (Python 2)
- 2268 cyfr według Jakube (Python 2)
Edycja: Dodałem własną odpowiedź.
- 28164 cyfry według Suboptimus Prime, oparte na algorytmie Qualtagha (C #)
code-challenge
primes
Suboptimus Prime
źródło
źródło
Odpowiedzi:
Java -
314433226629 cyfr6 0{3314} 8969999
To rozwiązanie jest oparte na odpowiedzi FryAmTheEggman .
Co jeśli będziemy kopać głębiej?
Staje się strukturą drzewa:
Nazwijmy R prawy złożony, jeśli R i wszystkie jego zakończenia są złożone.
Będziemy iterować po wszystkich liczbach zespolonych w pierwszej kolejności: 1, 9, 01, 81, 91, 09, 49, 69, 99, 001, 801, 901 itd.
Liczby zaczynające się od zera nie są sprawdzane pod kątem pierwszeństwa, ale są potrzebne do budowania kolejnych liczb.
Poszukamy liczby docelowej N w postaci X00 ... 00R, gdzie X jest jednym z 4, 6, 8 lub 9, a R jest prawym kompozytu. X nie może być liczbą pierwszą. X nie może być 0. A X nie może wynosić 1, ponieważ jeśli R kończy się na 1 lub 9, wówczas N będzie zawierać 11 lub 19.
Jeśli XR zawiera liczby pierwsze po operacji „usuń”, to XYR będzie je również zawierał dla dowolnego Y. Nie powinniśmy więc przechodzić przez gałęzie zaczynające się od R.
Niech X będzie stałą, powiedzmy 6.
Pseudo kod:
Powinniśmy ograniczyć liczbę zer, ponieważ znalezienie liczby pierwszej w postaci X + zera + R może zająć zbyt długo (lub na zawsze, jeśli wszystkie są złożone).
Prawdziwy kod jest dość szczegółowy i można go znaleźć tutaj .
Badanie pierwotności liczb w długim zakresie int jest wykonywane przez deterministyczny wariant testu Millera. W przypadku liczb BigInteger najpierw wykonywany jest podział próbny, a następnie test BailliePSW. Jest to probabilistyczne, ale całkiem pewne. I jest szybszy niż test Millera-Rabina (powinniśmy zrobić wiele iteracji dla tak dużych liczb w Millerze-Rabinie, aby uzyskać wystarczającą dokładność).
Edycja: pierwsza próba była niepoprawna. Powinniśmy również zignorować gałęzie zaczynające się na R, jeśli X0 ... 0R jest liczbą pierwszą. Wtedy X0 ... 0YR nie byłby kruchą liczbą pierwszą. Dodano więc dodatkową kontrolę. To rozwiązanie wydaje się poprawne.
Edycja 2: dodano optymalizację. Jeśli (X + R) można podzielić przez 3, to (X + zera + R) jest również podzielne przez 3. Więc (X + zera + R) nie może być w tym przypadku liczbą pierwszą i takie R mogą zostać pominięte.
Edycja 3: nie było konieczne pomijanie cyfr pierwszych, jeśli nie znajdują się one na ostatniej lub pierwszej pozycji. Zakończenia takie jak 21 lub 51 są w porządku. Ale to niewiele zmienia.
Wnioski:
źródło
Python 2 -
1261221133717192268 cyfrIstnieje około len (n) ^ 2 wynikowych liczb Remove (n, startIndex, count). Próbowałem zminimalizować te liczby. Jeśli wiele cyfr obok siebie jest takich samych, wiele z tych liczb wynikowych można zignorować, ponieważ pojawiają się wiele razy.
Podszedłem więc do skrajności, tylko 9s i trochę pierwsza w środku. Spojrzałem również na kruchą liczbę pierwszą poniżej 1 miliona i zobaczyłem, że są takie kruche pierwsze. Wyszukiwanie liczb z 2 9 na końcu działa naprawdę dobrze, nie wiem, dlaczego. 1 liczba, 3 lub 4 9 na końcu daje mniejsze kruche liczby pierwsze.
Wykorzystuje moduł pyprimes . Nie jestem pewien, czy to jest dobre. Wykorzystuje test miller_rabin, więc jest probabilistyczny.
Program znajduje tę 126-cyfrową kruchą liczbę pierwszą w około 1 minutę, a przez resztę czasu szuka bez powodzenia.
edytować:
Właśnie zobaczyłem, że usunąłeś limit czasu. Uruchomię program przez noc, może pojawią się naprawdę duże, delikatne liczby pierwsze.
edycja 2:
Przyspieszyłem mój oryginalny program, więc nadal nie ma rozwiązania z więcej niż 126 cyframi. Wskoczyłem więc do pociągu i szukałem x 9s + 1 cyfra + y 9s. Zaletą jest to, że musisz sprawdzić liczby O (n) pod kątem pierwszeństwa, jeśli naprawisz to. Szybko odnajduje 1221.
edycja 3:
W przypadku liczby 2268 cyfr używam tego samego programu, dzieliłem tylko pracę na wiele rdzeni.
źródło
Python 2.7 - 429623069
99993799Jak dotąd żadnych optymalizacji. Wystarczy użyć kilku trywialnych spostrzeżeń na temat delikatnych liczb pierwszych (dzięki Rainbolt na czacie):
Próbuję tylko uruchomić piłkę :)
To technicznie trwa nieco ponad 15 minut, ale sprawdza tylko jeden numer w dogrywce.
is_prime
jest wzięty stąd (użył go tutaj isaacg ) i jest probabilistyczny.Tylko uwaga, kiedy zacznę to z
n=429623069
wstaję do482704669
. Dodatkowa cyfra naprawdę zabija tę strategię ...źródło
Python 2,
828 cyfr5048 cyfrJak wskazał @Jakube, pierwsza liczba przesłana przeze mnie nie była tak naprawdę krucha z powodu błędu w moim kodzie. Naprawienie błędu było łatwe, ale znacznie spowolniło algorytm.
Ograniczyłem się do łatwo przeszukiwalnego podzbioru delikatnych liczb pierwszych, a mianowicie tych, które składają się tylko z cyfry 9 i dokładnie jednej cyfry 7.
Użyłem tej samej
is_prime
funkcji ( stąd ) jak @FryAmTheEggman.Edytować:
Wprowadziłem dwie zmiany, aby przyspieszyć algorytm:
Staram się pomijać jak najwięcej kontroli pierwotności, jak to możliwe, i cofam się tylko wtedy, gdy zostanie znaleziona potencjalna krucha liczba pierwsza, aby upewnić się, że jest naprawdę krucha. Istnieje niewielka liczba zduplikowanych kontroli, więc z grubsza zapamiętałem funkcję sprawdzania liczby pierwszych.
Dla liczb formularza
b*'9' + '7' + c*'9'
ograniczyłem rozmiarb
. Im niższy limit, tym mniej liczb trzeba sprawdzić, ale szanse rosną, aby w ogóle nie znaleźć dużej kruchej liczby pierwszej. Jakoś arbitralnie wybrałem 222 jako limit.Przy kilku tysiącach cyfr pojedynczy test wstępny może już zająć mojemu programowi kilka sekund. Tak więc prawdopodobnie nie mogę nic lepszego z tym podejściem.
Sprawdź poprawność mojego zgłoszenia. Ze względu na probabilistyczną kontrolę pierwotności mój numer teoretycznie nie może być liczbą pierwszą, ale jeśli tak, to powinien być kruchy. Albo zrobiłem coś złego. :-)
źródło
C #,
1003928164 cyfryEdycja: Stworzyłem inny program oparty na algorytmie Qualtagha z niewielkimi modyfikacjami:
Stara odpowiedź:
Istnieje kilka godnych uwagi wzorów na kruche liczby pierwsze:
gdzie X może wynosić 1, 2, 4, 5, 7 lub 8.
W przypadku takich liczb musimy jedynie wziąć pod uwagę (długość - 1) możliwe
Remove
operacje. InneRemove
operacje generują albo duplikaty, albo oczywiście liczby zespolone. Próbowałem wyszukać wszystkie takie liczby z maksymalnie 800 cyframi i zauważyłem, że 4 wzorce pojawiają się częściej niż pozostałe: 8007001, 8004001, 9997999 i 6004009. Ponieważ Emil i Jakube używają wzoru 999X999, postanowiłem użyć 8004001 tylko dodać trochę urozmaicenia.Do algorytmu dodałem następujące optymalizacje:
źródło
Haskell -
naprawiono12201277 cyfr dla prawdziwych realiLepiej jeden - 1277 cyfr
Kod Haskell
źródło