Python, 89 86 85 bajtów
f=lambda n,k=0:126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))and f(n+k,k%2*2+~k)or n
Algorytm jest na początku O (przerażający), a rekurencja tak naprawdę nie pomaga, ale działa dobrze, dopóki n jest wystarczająco zbliżone do liczby 7DP.
Dzięki @xnor za grę w golfa z 3 bajtów!
Przetestować go na repl.it .
Jak to działa
Python nie ma wbudowanych funkcji pierwszeństwa ani faktoryzacji, ale możemy zidentyfikować liczby 7DP według ilości i charakteru ich dzielników.
Zgodnie z zasadą mnożenia liczbę dzielników liczby całkowitej można obliczyć jako iloczyn przyrostowych wykładników jej pierwszej faktoryzacji. Zatem σ 0 (n) ( funkcja dzielnika ) wynosi 2 m za każdym razem, gdy n jest liczbą mDP.
σ 0 (n) = 128 jest zatem warunkiem koniecznym, ale niewystarczającym; na przykład σ 0 (2 127 ) = 128 , ale 2 127 wyraźnie nie jest liczbą 7DP. Jeśli jednak zarówno σ 0 (n) = 128, jak i żaden idealny kwadrat nie dzieli równomiernie n , to n jest liczbą 7DP.
Dla wejścia n algorytm polega na sprawdzeniu liczb całkowitych n , n - 1 , n + 1 , n - 2 , n + 2 itd. I zwróceniu pierwszego, który jest liczbą 7DP.
Gdy f jest wywoływane z argumentem n , dzieje się tak:
Kod
126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))
sprawdza, czy brak jest nie wiele 7DP następująco.
Dla wszystkich liczb całkowitych i takie, że 1 <i <n , 1>>n%i<<7*(n/i%i<1)
jest obliczany.
Jeśli n jest podzielne przez i, ale nie przez i 2 , to 1>>n%i
daje 1 i (n/i%i<1)
daje 0 , co daje
1,2 × 0,0 = 1 .
Jeśli n jest podzielne przez i 2 , 1>>n%i
i (n/i%i<1)
obie dają 1 , co daje 1,2 × 7 = 128 .
Jeśli n nie jest podzielne przez i , 1>>n%i
daje 0 , co daje 0,2 7 · x = 0 .
Suma liczb wynikających będzie 2 m - 2 , gdy n jest liczbą MDP (produkt 2 m dzielnikami, z wyłączeniem 1 i n ), a większa ilość niż 127. Jeśli brak jest kwadratem czynnik. Tak więc suma wyniesie 126 wtedy i tylko wtedy, gdy n jest liczbą 7DP.
Dla liczb 7DP suma wynosi 126 , więc XOR z 126 daje 0 , co jest fałszem. W ten sposób, czy część lambda jest wykonany i f zwraca bieżące wartości n .
Jeśli n nie jest liczbą 7DP, XOR zwróci niezerową, prawdziwą wartość. W ten sposób, a część lambda jest wykonywany.
f(n+k,k%2*2+~k)
rekurencyjnie wywołuje f ze zaktualizowanymi wartościami n (następny potencjalny numer 7DP) i k (różnica między nowym kandydatem a kolejnym).
Jeśli k jest liczbą całkowitą nieujemną, k%2*2
daje 0 i ~k
daje - (k + 1) . Suma obu wyników to - (k + 1) , która jest nieparzystą, ujemną liczbą całkowitą, która jest o 1 większa w wartości bezwzględnej niż k .
Jeśli k jest nieparzystą, ujemną liczbą całkowitą, k%2*2
daje 2, a ~k
daje - (k + 1) . Suma obu wyników wynosi 2 - (k + 1) = - (k - 1) , co jest parzystą, nieujemną liczbą całkowitą, która jest o 1 jednostkę większa w wartości bezwzględnej niż k .
Oznacza to, że k przyjmuje wartości 0, -1, 2, -3, 4, ⋯ .
Po dodaniu narastająco do n 0 (wartość początkowa n ), wynikowe liczby całkowite to
- n 0 + 0
- ( N 0 + 0) - 1 n = 0 - 1
- ( n 0-1 ) + 2 = n 0 + 1
- ( n 0 + 1) - 3 = n 0 - 2
- ( n 0–2 ) + 4 = n 0 + 2
- itp.
upewniając się, że pierwsza liczba 7DP spotykamy jest tak blisko n 0 , jak to możliwe.
k
bezpośrednio jakof(n+k,k%2*2+~k)
, zaczynając odk=0
.Brachylog ,
444016 bajtówPrzekreślone 44 jest nadal regularne 44; (
Przykład:
Czy to możliwe, że ten język nie zawsze jest do kitu? Pokonałem Jelly i MATL!
Przypadek testowy z
5
jest najdłuższy i zajmuje około 10 sekund na moim komputerze.Byłoby to 12 bajtów, gdyby
$p
nie było błędu (nie potrzebowalibyśmy>0,.
części)Wyjaśnienie
Brachylog domyślnie używa programowania logiki ograniczeń dla całej arytmetyki liczb całkowitych. Co więcej, wbudowane etykietowanie
=
działa na prawdopodobnie nieskończonych domenach.Że kolejno łączy zmienną bez ograniczeń (Tj
(-inf, inf)
) w następujący sposób:0, 1, -1, 2, -2, 3, …
.Dlatego możemy uzyskać najbliższy numer 7DP, szukając pierwszego
I
zunifikowanego numeru(-inf, inf)
(używając automatycznego cofania), dla któregoInput + I
jest to numer 7DP.źródło
$p
. Teoretycznie nie potrzebuję>0,
, ale moja implementacja jestInput+1, Input-1, Input+2, Input-2, Input+3, ...
dlatego pierwsze 7DP znalezione tą metodą będzie najbliższe.>0,.
niepotrzebne)Galaretka, 17 bajtów
Działa teoretycznie, ale jego ukończenie zajmuje wiele lat.
Oto wersja, która faktycznie działa dla danych wejściowych, ale teoretycznie nie działa w przypadku dużych danych wejściowych:
Wypróbuj tutaj. To generuje wszystkie liczby pierwsze do 50, a następnie znajduje wszystkie 7 kombinacji liczb pierwszych na tej liście, a następnie wszystkie ich produkty. Wreszcie, po prostu znajduje najbliższy element z tej listy do podanego argumentu.
Oczywiście, gdy nasze 7DP zawierają liczby pierwsze większe niż 50, to się nie powiedzie. Wersja teoretyczna generuje wszystkie liczby pierwsze do 256n dla wejścia n , ale poza tym działa w ten sam sposób.
Dowód
Niech
p(x)
oznaczymy następną liczbę pierwszą pox
. (Bardzo luźna) górna granica dla najbliższego produktu 7DP do x to:Musimy tylko sprawdzić liczby pierwsze w [2… p (p (p (p (p (p (p (p (x))))))] . Postulat Bertranda mówi, że p (x) ≤ 2x , więc wystarczy sprawdzić wszystkie liczby pierwsze do 128x .
źródło
×⁹ÆRœc7P€µạ³ỤḢị
lub×⁹ÆRœc7P€µạ³NMị
(wydrukowanie tablicy wszystkich rozwiązań) oszczędza kilka bajtów. Ponadto,×⁹
można zmienić+⁴
, aby poprawić wydajność.MATL ,
2117161413 bajtówPodziękowania dla Dennisa za sugestię usunięcia 4 bajtów i kolejną, która pozwoliła zaoszczędzić jeszcze 1 bajt!
Działa to teoretycznie, ale zabraknie pamięci dla powyższych danych wejściowych
6
(kompilator online).Bardziej wydajna wersja wykorzystuje 21 bajtów i oblicza wszystkie przypadki testowe w ciągu około jednej sekundy:
Wypróbuj online!
Wyjaśnienie
Wersja wydajna pod względem pamięci
Weź przykład N =
860782
. Wystarczy pod liczb pierwszych do M =29
, która jest najpierw pierwsza, że pomnożony przez2*3*5*7*11*13
przekracza N . W tym przykładzie2*3*5*7*11*13*29 = 870870
. Następna liczba pierwsza to31
. Jakikolwiek produkt obejmujący tę pierwszą lub większą będzie co najmniej2*3*5*7*11*13*31 = 930930
, a więc na pewno nie będzie rozwiązaniem, ponieważ przekracza to,870870
co przekracza N .M jest obliczane jako pierwsza liczba pierwsza większa niż
max(N/(2*3*5*7*11*13), 16)
.max
Funkcja jest stosowana w celu zapewnienia, że co najmniej17
jest zrywane. Aby zaoszczędzić kilka bajtów, zostaje zastąpiony przez kod2*3*5*7*11*13 = 30030
użytkownika30000
i funkcjimax
przez dodanie. Te zmiany są ważne, ponieważ dają większą wartość.Wersja nieefektywna pamięci
Aby jeszcze bardziej zmniejszyć liczbę bajtów, podział można usunąć; w rzeczywistości wystarczy pomnożyć przez
17
(dzięki, @Dennis). Zapewnia to uwzględnienie kolejnej liczby pierwszej (zgodnie z postulatem Bertranda ) i co najmniej wynik17
. Działa to teoretycznie, ale zabraknie pamięci dla danych wejściowych większych niż około6
.W kodzie sekcja
zastępuje się przez
źródło
Pyke, 32 bajty
Wypróbuj tutaj!
Pamiętaj, że to nie działa online - limit czasu. Ta wersja sprawdza tylko 2 różne liczby pierwsze i powinna działać szybciej. Gdy dwie liczby w tej samej odległości znajdują się od celu, wybiera niższą.
Przechodzi przez wszystkie liczby, aż znajdzie taki, który jest większy niż wejście i ma wartość 7DP. Dla każdego numeru pozbywa się go, jeśli nie jest to 7DP. Następnie ma listę 7DP aż do wejścia z większym. Następnie wybiera ten, który jest najbliżej wejścia.
źródło
Julia, 59 bajtów
To jest bardzo nieefektywne, ale działa w przypadku pierwszego przypadku testowego w praktyce, a dla pozostałych w teorii.
Kosztem kolejnych 5 bajtów - w sumie 64 bajtów - można znacznie poprawić wydajność.
Wypróbuj online!
tło
Jak wspomniano w odpowiedzi @ LuisMendo , zestaw liczb pierwszych, które musimy wziąć pod uwagę dla najbliższej liczby 7DP, jest dość mały. Wystarczy, aby zestaw zawierał liczbę 7DP większą niż wartość wejściowa n , co będzie prawdą wtedy i tylko wtedy, gdy zawiera liczbę pierwszą p ≥ 17 taką, że 30300p = 2 · 3 · 5 · 7 · 11 · 13 · p ≥ n .
In On przedział zawierający co najmniej jedną liczbę pierwszą dowodzi, że przedział [x, 1,5x) zawiera co najmniej jedną liczbę pierwszą, ilekroć x ≥ 8 . Od 30030/16384 ≈ 1,83 , to znaczy, że musi być głównym P w (n / 30030 N / 16384) gdy n> 8 · 30300 = 242.400 .
Wreszcie, gdy n <510510 , p = 17 jest wyraźnie wystarczające, więc musimy wziąć pod uwagę liczby pierwsze do n / 16384 + 17 .
Kosztem wydajności możemy zamiast tego rozważyć liczby pierwsze do 17n . Działa to, gdy n = 1 i jest znacznie większe niż n / 16384 + 17 dla większych wartości n .
Jak to działa
17n|>primes
orazn>>14+17|>primes
(przesunięcie bitów jest równoważne podzieleniu przez 2 14 = 16384 ) oblicza przedziały liczb pierwszych wspomniane w poprzednim akapicie. Następniecombinations(...,7)
oblicza wszystkie tablice siedmiu różnych liczb pierwszych w tym zakresie, a odwzorowanieprod
na nich oblicza ich produkty, tj. Liczby 7DP, z których wybieramy odpowiedź.Następnie
-n
odejmuje n prom dla każdej liczby 7DP, a następniesort(...,by=abs)
sortuje te różnice według ich wartości bezwzględnych. Na koniec wybieramy pierwszą różnicę za pomocą[]
i obliczamy odpowiedni numer 7DP, dodając n za pomocą+n
.źródło
Pyth, 30 bajtów
Wypróbuj online!
Zestaw testowy.
(5 trwa zbyt długo)
Wyjaśnienie
źródło
Mathematica
136 8075 bajtówJest to proste podejście, działające na zewnątrz
n
.n
jest 7-odrębnym produktem głównym, jeśli liczba czynników pierwszych wynosi 7 (PrimeNu@#==7
) i żaden z tych czynników nie pojawia się więcej niż jeden raz (SquareFreeQ@#&
).Moje wcześniejsze zgłoszenie (136 bajtów) znalazło zarówno pierwszy 7-odrębny główny produkt powyżej,
n
a jeśli istnieje, pierwszy 7-odrębny główny wynik poniżejn
. Następnie po prostu określił, który był bliżejn
. Jeśli produkty były w równej odległości, zwracane były oba.Obecna wersja sprawdza n-1, n + 1, n-2, n + 2 ... aż osiągnie pierwszy 7-odrębny produkt główny. Ta bardziej wydajna wersja przyjmuje podejście Dennisa.
Kluczowym postępem było użycie
⌊k/2](-1)^k⌋
do zwrócenia serii, 0, 1, -1, 2, -2 ... Zero służy do sprawdzenia, czyn
sam jest produktem 7-odrębnym-pierwszym. Z tego powoduFloor
(to znaczy⌊...⌋
) jest używane zamiastCeiling
.510510
870870
1438710
źródło
05AB1E , 10 bajtów
Wypróbuj online!
Próbuje wszystkich kombinacji 7 z pierwszych 10 ** liczb pierwszych wejściowych. Skończy się pamięć dla wejść większych niż 1.
Znacznie bardziej wydajna 14-bajtowa wersja:
Wypróbuj online!
Wykorzystuje pierwsze liczby (wejściowe / 100000 + 7).
źródło