Oblicz pierwsze luki


19

Znalezienie liczb pierwszych to programowy rytuał przejścia i bardzo często pierwszy poważny program, który ktoś buduje (zwykle z podziałem na próby).

Ale same liczby pierwsze są już zużyte. Kolejną o wiele bardziej interesującą rzeczą jest uzyskanie pierwszych luk: najdłuższych jak dotąd przerw między kolejnymi liczbami pierwszymi. Są to dość rzadkie i „cenne”. Kilka pierwszych par i ich różnice to:

2 3 1
3 5 2
7 11 4
23 29 6
89 97 8
113 127 14
...

Mój ojciec obliczał je ręcznie dla zabawy do 10 tys. Zobaczmy, jak krótki jest kod.

Zasady:

  • brak wbudowanych funkcji do testowania liczb pierwszych, generowania liczb pierwszych i luk podstawowych
  • brak pobierania http://oeis.org/A002386 lub podobnego (z daleka czuję was oszustów :))
  • brak wstępnie obliczonych tablic
  • kontynuuj drukowanie, dopóki wewnętrzny typ liczb całkowitych nie zawiedzie

Wygrywa najniższa liczba postaci. +10 znaków, jeśli drukujesz odstępy bez liczb pierwszych.

Możesz również pochwalić się wersjami z wbudowanymi funkcjami, jeśli są interesujące. Bądź kreatywny.

Wyjaśnienie: przechodzisz przez liczby pierwsze i raportujesz za każdym razem, gdy widzisz lukę, która jest większa niż jakakolwiek luka, którą widziałeś wcześniej. Na przykład między 3 a 5 jest przerwa o szerokości 2 jednostek. Różnica między 5 a 7 wynosi również 2, ale to stare wieści, że już nas to nie obchodzi. Tylko wtedy, gdy zobaczysz nową największą lukę, zgłoś ją. Odzwierciedla to, w jaki sposób liczby pierwsze stają się coraz rzadsze, gdy luki stają się coraz większe.


EDYCJA : Większość odpowiedzi jest genialna i zasługuje na większe uznanie. Jak dotąd wpis w GolfScript z 48 znakami jest najkrótszy.


1
W twoim przykładzie 3 oznacza koniec pary i początek następnej pary, podczas gdy nie dotyczy to innych liczb. Co chcesz?
mmumboss,

Nieważne, mam to teraz.
mmumboss,

Być może zechcesz przepisać swoją regułę jako „brak wbudowanych funkcji do testowania, obliczania liczb głównych lub luk”. W przeciwnym razie oczywistym rozwiązaniem byłoby użycie funkcji, która zwraca n- tą liczbę pierwszą, a następnie zwiększenie n , uruchomienie funkcji ponownie i znalezienie różnicy.
user12205

2
Aww. uwielbiam OEIS
TheDoctor

Mam takie same wątpliwości jak @mmumboss. Czy możesz zadowolić Xplaina?
Clyde Lobo

Odpowiedzi:


3

GolfScript 66 59 57 49 48

[2.0{:d{;\;.{).{(1$1$%}do(}do.2$-.d>!}do].p~.}do

Chociaż mam problem z uruchomieniem go tutaj http://golfscript.apphb.com/ (może ta strona nie lubi nieskończonej pętli?), Ale działa dobrze, gdy uruchomię ją na moim komputerze z golfscript.rb. Jestem całkiem nowy w GolfScript, więc można go jeszcze bardziej pograć w golfa. AKTUALIZACJA: Nie sądzę, że można to znacznie pogorszyć bez zmiany algorytmu.

Wydrukowano kilka pierwszych wierszy (jeśli nie podoba ci się drukowany „”, możesz dodać; na początku skryptu, ale powoduje to wzrost do 49 znaków):

[2 3 1]
["" 3 5 2]
["" 7 11 4]
["" 23 29 6]
["" 89 97 8]
["" 113 127 14]
["" 523 541 18]
["" 887 907 20]
["" 1129 1151 22]
...

Ogólne, czytelne dla człowieka pojęcie o tym, jak to działa (kilka rzeczy nieco się różni, ponieważ nie używam stosu w tej wersji):

cur_prime = 2
next_prime = 2
gap = 0        

do {
    do {
        cur_prime = next_prime
        do {
            next_prime = next_prime + 1
            possible_factor = next_prime
            do {
                possible_factor = possible_factor - 1
            } while (next_prime % possible_factor > 0)
        } while (possible_factor != 1)
    } while (next_prime - cur_prime <= gap)

    gap = next_prime - cur_prime
    print [cur_prime next_prime gap]
} while (true)

11

Python, 121 110 109 108 104 103 znaków

p,n,m=[2],3,0
while 1:
 if all(n%x for x in p):
  c=n-p[0]
  if m<c:m=c;print(p[0],n,c)
  p=[n]+p
 n+=1

Po raz pierwszy próbowałem odpowiedzieć tutaj, mam nadzieję, że zrobiłem to dobrze ... nie jestem pewien, czy poprawnie policzyłem postacie.

Hmmm, mógłbym zapisać inną postać na wydruku, obniżając wersję do Pythona 2.x ...


121 znaków, zmień tytuł na tytuł #, poważnie nie liczysz znaków ręcznie, prawda? javascriptkit.com/script/script2/charcount.shtml
user80551

Nie, nie liczyłem ręcznie :) Ale widziałem inne odpowiedzi Pythona na niektóre pytania spłaszczone do jednej linii w sposób, który zmniejszył białe spacje, i szczerze mówiąc nie jestem pewien, czy nowa linia jest liczona jako 1 czy 2 znaki ...
Tal

1
Nowe znaki liczymy jako 1 znak, chyba że reguły pytania wyraźnie stanowią inaczej. Witamy w PPCG!
Jonathan Van Matre

3
Witamy! Dobra odpowiedź, a także ma miejsce na poprawę. Na przykład if all(n%x>0for x in p):jest nieco krótszy. Możesz także zapisać niektóre znaki, przenosząc instrukcje do tej samej linii (np a=1;b=2;f().).
grc

1
Ostatnia zmiana złamała kod, nie wypychając [n] do przodu, jak podano.
orion

4

JavaScript, 90 85 78 74 znaków

Krótki kod (Kompilator Google Closure - zaawansowane optymalizacje; niektóre zmiany ręczne; więcej zmian przez @ MT0 )

for(a=b=2,c=0;b++;)for(d=b;b%--d;)d<3&&(c<b-a&&console.log(a,b,c=b-a),a=b)

Długi kod

var lastPrime = 2,
    curNumber = lastPrime,
    maxDistance = 0,
    i;

// check all numbers
while( curNumber++ ) {

  // check for primes
  i = curNumber;
  while( curNumber % --i != 0 ) {}

  // if prime, then i should be equal to one here
  if( i == 1 ) {

    // calc distance
    i=curNumber-lastPrime;

    // new hit
    if( maxDistance < i ) {
      maxDistance = i;
      console.log( lastPrime, curNumber, maxDistance );
    }

    // remember prime
    lastPrime = curNumber;
  }
}

Wynik

2 3 1
3 5 2
7 11 4
23 29 6
89 97 8
113 127 14
523 541 18
887 907 20
1129 1151 22
1327 1361 34
9551 9587 36
15683 15727 44
19609 19661 52
31397 31469 72
...

Dość nieefektywny test liczb pierwszych, ale w ten sposób zużywa mniej znaków.

Pierwszy post tutaj, więc proszę wybacz błędy.


78 znaków -for(a=b=2,c=0;b++;){for(d=b;b%--d;);1==d&&(c<b-a&&console.log(a,b,c=b-a),a=b)}
MT0

@ MT0 Dzięki. Nie zauważyłem ich. Edytowane.
Sirko,

Jeszcze bardziej nieefektywne, ale 74 znaki -for(a=b=2,c=0;b++;)for(d=b;b%--d;)d<3&&(c<b-a&&console.log(a,b,c=b-a),a=b)
MT0

3

Mathematica, 114 108

Pozwala na nieskończoną moc wyjściową, chociaż po pewnym momencie sekwencji wentylator włącza się i zaczynasz podejrzewać, że Twój procesor gra Freecell, starając się wyglądać na zajętego.

p@x_:=NestWhile[#+1&,x+1,Divisors@#≠{1,#}&];m=0;q=1;While[1<2,If[p@q-q>m,Print@{q,p@q,p@q-q};m=p@q-q];q=p@q]

Próbka wyjściowa (są to te, które zbiera w pierwszych ~ 30s):

{1,2,1}
{3,5,2}
{7,11,4}
{23,29,6}
{89,97,8}
{113,127,14}
{523,541,18}
{887,907,20}
{1129,1151,22}
{1327,1361,34}
{9551,9587,36}
{15683,15727,44}
{19609,19661,52}
{31397,31469,72}
{155921,156007,86}
{360653,360749,96}
{370261,370373,112}
{492113,492227,114}
{1349533,1349651,118}
{1357201,1357333,132}
{2010733,2010881,148}

Nieskluczony kod:

p@x_ := NestWhile[
   # + 1 &,
   x + 1,
   Divisors@# ≠ {1, #} &];
m = 0;
q = 1;
While[
 1 < 2,
 If[
  p@q - q > m,
  Print@{q, p@q, p@q - q}; m = p@q - q];
 q = p@q]

Czy to rozpoznaje ?
Riking

Tak, po prostu nie eksportuje w ten sposób, ale dobrze go parsuje po wklejeniu kodu do notesu. Już odpowiednio go zdobyłem, ale zmienię, aby uprościć.
Jonathan Van Matre

ile znaków, jeśli zrobić zastosowanie Mathematica wbudowanej funkcji Prime?
Michael Stern

76. Ponieważ cała definicja p @ x_ jest tylko ponownym wdrożeniem NextPrime, można ją zastąpić p = NextPrime;
Jonathan Van Matre

3

Haskell - 122 116 114 112 110

q=[n|n<-[3..],all((>0).rem n)[2..n-1]]
d m((p,q):b)|q-p>m=print(p,q,q-p)>>d(q-p)b|q>p=d m b
main=d 0$zip(2:q)q

(Nieefektywne) wyrażenie listy głównej skradzione Willowi Nessowi .

- edytuj - nigdy nie wiedziałem, x|y=z|w=qże będzie ważny.


2

MATLAB 104 89

Właśnie wdrożyłem podstawową metodę, sprawdzając każdy możliwy podział.

a=2;g=0;for n=3:inf;b=n*(sum(mod(n,1:n)<1)<3);h=b-a;if(h>g)g=h;[a,b,h]
end;a=max(a,b);end

Wynik:

  2     3     1
  3     5     2
  7    11     4
 23    29     6
 89    97     8
113   127    14
523   541    18
887   907    20

Jestem włączony octavei ta inffunkcja nie działa (a drukowanie jest odraczane do momentu zakończenia pętli). Czy Matlab ma ocenę leniwego zasięgu?
Orion

Matlab drukuje w czasie rzeczywistym, przy każdej iteracji pętli. Po uruchomieniu programu pojawia się ostrzeżenie, że maksymalny indeks to 2147483647, a następnie się uruchamia. Alternatywnie mógłbym zamienić inf na intmax, ale to trzy znaki więcej.
mmumboss

2

76 znaków, dogelang

Konwertowane z mojej wersji Python :

g=0
i=l=2
while i+=1=>all$map(i%)(2..i)=>(i-l>g=>(g=i-l),print(l,i,g)),(l=i)

Wynik:

(2, 3, 1)
(3, 5, 2)
(7, 11, 4)
(23, 29, 6)
(89, 97, 8)
(113, 127, 14)
(523, 541, 18)
(887, 907, 20)
(1129, 1151, 22)
...

Powinien zostać wybrany jako zwycięzca!
Sarge Borsch

2

Golfscript, 59 51 50 znaków

Człowiek każdej postaci jest niezwykle trudny do stracenia:

0[2.{).,2>{\.@%!},{.2$-.4$>{].p~\[}{;\;}if..}or}do

Wyjście :

[2 3 1]
[3 5 2]
[7 11 4]
[23 29 6]
[89 97 8]
[113 127 14]
...

Objaśnienie :

Stos jest skonfigurowany, więc każda iteracja zaczyna się od stosu w ten sposób, górna jest po prawej stronie. [Wskazuje aktualny znacznik tablicy, czyli gdy interpreter napotka ], wszystko na stosie od znaku do góry należy umieścić w tablicy.

g [ last | cur

gto maksymalna jak dotąd luka. Z góry na dół:

 command         | explanation
-----------------+----------------------------------------
 0[2.            | initialize vars g=0, last=2, cur=2
 {...}do         | loop forever...

Wewnątrz pętli:

 )               | cur += 1
 .,2>{\.@%!},    | put all divisors of cur into a list
 {...}or         | if the list is empty, cur is prime, so
                 | the block is executed. otherwise,
                 | 'do' consumes the stack, sees it is truthy,
                 | and loops again

Jak umieszcza wszystkie dzielniki na liście? Zróbmy to krok po kroku

 Command         | explanation                                  | stack
-----------------+----------------------------------------------+----------------
                 | initial stack                                | n
 .,              | make list of 0..n-1                          | n [0,1,...,n-1]
 2>              | take elements at index 2 and greater         | n [2,3,...,n-1]
 {...},          | take list off stack, then iterate through    |
                 | the list. on each iteration, put the current |
                 | element on the stack, execute the block, and |
                 | pop the top of the stack. if the top is      |
                 | true then keep the element, else drop it.    |
                 | when done, push list of all true elements    |
                 | So, for each element...                      | n x
   \.            |   Swap & dup                                 | x n n 
   @             |   Bring x around                             | n n x
   %             |   Modulo                                     | n (n%x)
   !             |   Boolean not. 0->1, else->0. Thus this is 1 |
                 |   if x divides n.                            | n (x divides n)
                 | So only the divisors of n are kept           | n [divisors of n]

Co robi, jeśli dzielniki są puste?

 Command         | explanation                                  | stack
-----------------+----------------------------------------------+----------------
                 | initial stack                                | g [ last | cur
  .              | dup                                          | g [ l | c | c
  2$             | copy 3rd down                                | g [ l | c | c | l
  -              | sub. This is the current gap, cur-last       | g [ l | c | c-l
  .              | dup                                          | g [ l | c | c-l | c-l
  4$             | copy 4th down                                | g [ l | c | c-l | c-l | g
  >              | is cur gap > max gap so far?                 | g [ l | c | c-l | c-l>g
  {#1}{#2}if..   | #1 if c-l > g, #2 otherwise, and do ".." in  | ... | g [ c | c | c
                 | either situation                             | 

Dwie ścieżki: tak i nie. Jeśli tak (pamiętaj, że ifzużywa najwyższą wartość na stosie):

 Command         | explanation                                  | stack
-----------------+----------------------------------------------+----------------
                 | initial stack. note that now the old `g` is  | XX [ l | c | g
                 | garbage and `c-l` is the new `g`.            |
 ]               | close the array                              | XX [l, c, g]
 .p              | duplicate it and print it, consuming the dup | XX [l, c, g]
 ~               | pump array back onto the stack. Note now the | XX | l | c | j
                 | array marker [ is gone.                      | 
 \               | swap.                                        | XX | l | g | c                         
 [               | mark the array                               | XX | l | g | c [
 .               | this is the part after the if. dups the top, | XX | l | g [ c | c
                 | but it does this in two steps, first popping | 
                 | c then putting two copies on top, so the     | 
                 | array marker moves                           | 
 .               | dup again                                    | XX | l | g [ c | c | c

Jeśli nie:

 Command         | explanation                                  | stack
-----------------+----------------------------------------------+----------------
                 | initial stack. In this case g is still the   | g [ l | c | c-l
                 | max gap so far                               | 
 ;\;             | dump top of stack, swap, and dump again      | g [ c
 ..              | the part after the if. dup twice             | g [ c | c | c

W obu przypadkach nasz stos jest teraz w formie ... | g [ c | c | c.

Teraz dowyskakuje najwyższa wartość ze stosu - zawsze c- i zapętla się, jeśli jest dodatnia. Ponieważ czawsze rośnie, jest to zawsze prawda, więc zapętlamy na zawsze.

Po wysunięciu górna część stosu oznacza g [ c | c, że ostatnia została zaktualizowana c, znak tablicy znajduje się w tym samym miejscu i gnadal jest tam, gdzie się tego spodziewamy.

Są to zawiłe operacje GolfScript. Mam nadzieję, że podobało Ci się śledzenie!


1
Doskonałe wyjaśnienie!
Jonathan Van Matre

1

Ruby, 110

Tylko dla Ruby 2.0 ze względu na lazymetodę:

(2..1.0/0).lazy.select{|n|!(2...n).any?{|m|n%m==0}}.reduce([2,0]){|(l,t),c|d=c-l;p [l,c,d]if d>t;[c,d>t ?d:t]}

Wynik:

[2, 3, 1]
[3, 5, 2]
[7, 11, 4]
[23, 29, 6]
[89, 97, 8]
[113, 127, 14]
[523, 541, 18]
[887, 907, 20]
[1129, 1151, 22]
[1327, 1361, 34]
[9551, 9587, 36]
[15683, 15727, 44]
[19609, 19661, 52]
[31397, 31469, 72]
[155921, 156007, 86]
[360653, 360749, 96]
[370261, 370373, 112]
[492113, 492227, 114]
...

1

Perl, 105 bajtów

$p=2;$d=0;L:for($i=2;++$i>2;){!($i%$_)&&next L for 2..$i-1;if($i-$p>$d){$d=$i-$p;print"$p $i $d\n"}$p=$i}

Nie golfowany:

$p = 2;
$d = 0;
L: for ($i = 2; ++$i > 2; ){
    !($i % $_) && next L for 2..$i-1;
    if ($i - $p > $d) {
        $d = $i - $p;
        print "$p $i $d\n"
    }
    $p = $i
}  

Algorytm jest prosty, $ppamięta poprzednią liczbę pierwszą. Następnie $iprzechodzi z 3góry do, gdy typ $ i „zawodzi na mnie” lub staje się ujemny z powodu przepełnienia. $ijest testowany w przybliżeniu, sprawdzając wszystkie dzielniki od 2 do $i-1. Linia jest drukowana, jeśli aktualna różnica jest większa niż poprzednia wydrukowana różnica $d.

Przy większej liczbie bajtów czas działania można poprawić:

$p = 2;
$d = 0;
L: for ($i=3; $i > 2; $i += 2){
    for ($j=3; $j <= sqrt($i); $j += 2){
        next L if !($i%$j)
    }
    if ($i - $p > $d) {
        $d = $i - $p;
        print "$p $i $d\n"
    }
    $p = $i
}

The Wynik zaczyna się od:

2 3 1
3 5 2
7 11 4
23 29 6
89 97 8
113 127 14
523 541 18
887 907 20
1129 1151 22
1327 1361 34
9551 9587 36
15683 15727 44
19609 19661 52
31397 31469 72
155921 156007 86
360653 360749 96
370261 370373 112
492113 492227 114
1349533 1349651 118
1357201 1357333 132
2010733 2010881 148
4652353 4652507 154
17051707 17051887 180
20831323 20831533 210
47326693 47326913 220
...

1
To nie jest poprawne, musisz znaleźć szereg rosnących luk. Zobacz na przykład odpowiedź Ruby lub Matlab dla oczekiwanego wyniku.
mmumboss,

1
@mmumboss: Och, przeoczyłem to. Naprawiono teraz.
Heiko Oberdiek

Dobry dla języka, w którym wszystkie zmienne wymagają co najmniej 2 znaków.
Orion

1

Pyton, 93 91 znaków

Naiwne sprawdzanie liczby pierwszej (sprawdź, czy można podzielić przez coś od 2 do n(mniej znaków niż don/2 )):

g=0;i=l=2
while 1:
 i+=1
 if all(i%x for x in range(2,i)):
    if i-l>g:g=i-l;print l,i,g
    l=i

Drugi poziom wcięcia to jeden znak tabulacji.

Wynik:

2 3 1
5 7 2
7 11 4
23 29 6
89 97 8
113 127 14
523 541 18
...

Fajnie, zapomniałem o tym przedziale ntylko do czeków don-1
Claudiu

1

Bash i trochę Perla dla pierwotnego wyrażenia regularnego ( 167 157 143 112 bajtów)

n=2
c=2
while p=$c
do perl -e\(1x$[++n]')=~/^(11+?)\1+$/&&exit 1'&&c=$n
((c-p>g))&&g=$[c-p]&&echo $p $c $g
done

niektóre dane wyjściowe:

$./golfd.sh
2 3 1
3 5 2
7 11 4
23 29 6
89 97 8
113 127 14
523 541 18
887 907 20
1129 1151 22

Korzystanie z cofania NP regexa w celu całkowitego obejścia pętli i struktur kontrolnych jest czystą perfekcją. Jednak testdużo protestuje i to nie działa dla mnie. Można również korzystać z niektórych let n++i let f=c-pi zastąpić testz [. Lub ewentualnie przetestuj, (())gdzie nie potrzebujesz $ani spacji.
orion

test -n $dzwrócił true dla pustego ciągu. test -n "$d"było w porządku, ale dłużej. Jednak strona man mówi, że -n jest opcjonalne i okazuje się, że test $dbyło w porządku. I dlatego [ $d ]też. I trzeba było zainicjować g = 0.
orion

@orion, przepraszam z jakiegoś powodu, że wydawało się, że teraz działa, ale zepsuł się również na moim komputerze, przywróciłem go do 167. Spróbuję dodać kilka innych sugestii
Newbrict

Twoje środowisko może mieć predefiniowane zmienne.
orion

@orion z jakiegoś powodu twoja edycja została odrzucona, czy możesz ponownie edytować?
Newbrict,

1

Perl 95 90 bajtów

for($n=$c=2;$p=$c;$c-$p>$g&&printf"$p $c %d\n",$g=$c-$p){$c=$n if(1x++$n)!~/^(11+?)\1+$/}

stara wersja bez golfa:

$n=$c=2;
while($p=$c){
    $c=$n if (1x++$n)!~/^(11+?)\1+$/;
    if ($c-$p>$g) {$g=$c-$p;print "$p $c $g\n"}
}

Jest to podobne do mojego innego zdania, sans bash.


Nie jestem irytujący, chcę tylko zobaczyć, jak daleko to może zajść. Tutaj:for($n=$c=2;$p=$c;$c-$p>$g&&printf"$p $c %d\n",$g=$c-$p){$c=$n if(1x++$n)!~/^(11+?)\1+$/}
orion

@orion, który jest poważny dla nadużywania pętli haha!
Newbrict

1

C (100)

Mój własny wkład, brak specjalnego algorytmu, po prostu golf:

i,g,r,p=2;main(){for(;r=p;p-r>g?printf("%d %d %d\n",r,p,g=p-r):0)for(i=0;i-p;)for(i=1,++p;p%++i;);}

„+10 znaków, jeśli drukujesz odstępy bez liczb pierwszych”. - jeśli usuniesz drukowanie ri pbędziesz mieć mniej znaków i zdobędziesz bonus :)
CompuChip

Kompletność jest ładna :)
orion

1

Haskell, 134 ° C

Gra w golfa:

c n=null[x|x<-[2..n-1],n`mod`x==0]&&n>1
p=filter c[1..]
g l(m:n:o)
 |(n-m)>l=do print(m,n,n-m);g(n-m)(n:o)
 |True=g l(n:o)
main=g 0 p

Nie golfowany:

-- c function checks if n is a prime number
c n=null[x|x<-[2..n-1],n`mod`x==0]&&n>1

-- p is an infinite list of primes
p=filter c[1..]

-- g function prints a list of primes and differences.
--   l is the maximum difference seen so far
--   (m:n:o) is the list of unprocessed primes
g l(m:n:o)
 |(n-m)>l=do print(m,n,n-m);g(n-m)(n:o)
 |True=g l(n:o)

-- main starts the ball rolling with a default max-seen value of 0
main=g 0 p

Uwielbiam tę leniwą ocenę!
Jonathan Van Matre

1

C: 493 302 272 246

int e(int j){for(int i=2;i<j;i++)if(j%i<1)return 0;return 1;}void f(int a,int b,int c){if(e(a)&e(b))if(c<b-a){printf("%d %d %d\n",a,b,b-a);f(a+1,b+1,b-a);}else f(a+1,b+1,c);if(e(b))f(a+1,b,c);if(e(a))f(a,b+1,c);f(a+1,b+1,c);}int main(){f(2,3,0);}

Użyłem rekurencji, a nie zwykłej pętli forlub while.

int isPrime(int num){
    for( int i=2; i<num; i++ )
        if(num%i < 0) return 0;
    return 1;
}
void fun(int n1, int n2, int gap){
   if( isPrime(n1) & isPrime(n2) ){
        if( gap < n2-n1 ){
           printf("%d %d %d\n", n1, n2, n2-n1);
           fun(n1+1, n2+1, n2-n1);
        }else{
           fun(n1+1, n2+1, gap);
        }
   }
   if( isPrime(n2) ){
       fun(n1+1, n2, gap);
   }
   if( isPrime(n1) ){
       fun(n1, n2+1, gap);
   }
   fun(n1+1, n2+1, gap);
}

int main(){
   fun(2,3,0);
}

Wynik:

2 3 1
3 5 2
7 11 4
23 29 6
89 97 8
113 127 14
523 541 18
887 907 20
1129 1151 22
1327 1361 34
9551 9587 36
15683 15727 44
19609 19661 52

To nie działa prawda / fałsz nie są zdefiniowane, ale nawet jeśli to naprawimy, zgłasza błędne luki. Na przykład, istnieje DUŻO liczb pierwszych między 25219 a 43237. Twoja rekurencja jest leakingna górze, ponieważ nie testujesz isPrime (n2), dopuszczasz liczby pierwsze od n1 do n2. I tak naprawdę nie można tego naprawić, ponieważ nie można zwiększyć n2 bez spełnienia liczb pierwszych.
orion

Masz rację! To jest złe! Moje myślenie było błędne od samego początku.
Loukas

1
Teraz jest lepiej .. :)
Loukas

+1 Teraz, gdy jest naprawiony, podoba mi się - jest całkiem nietypowy (choć nieefektywny). Możesz dużo zagrać w golfa. Pomiń returnw głównej. Pomiń ostatni else. Wymienić &&-> &i num%i==0z num%i<1. A według starożytnych standardów c (pojawią się ostrzeżenia) nie trzeba określać zwracanych wartości funkcji void i int (ich argumenty również domyślnie int).
Orion

Grałem trochę i sprowadziłem go do 151 znaków, z jednym bezwarunkowym wywołaniem rekurencyjnym, tylko jednym specyfikatorem typu ( int) i znacznie zredukowaną funkcją testowania: e(j,i){while(j%++i);return i==j;}f(a,b,c){int A=e(a,1),B=e(b,1);if(A&B&&c<b-a)printf("%d %d %d\n",a,b,c=b-a);f(a+(B|!A),b+(A|!B),c);}main(){f(2,3,0);}
Marion

1

Oracle SQL, 216 202 196 172 + 10 = 182

Właśnie zauważyłem to w pytaniu:

Wygrywa najniższa liczba postaci. +10 znaków, jeśli drukujesz odstępy bez liczb pierwszych.

Ponieważ jest to SQL, a słowa kluczowe są tak długie, właściwie lepiej wziąć karę, podając następujące. To ten sam pomysł, co oryginał.

with c as(select level+1n from dual connect by level<1e124)select lead(n)over(order by n) from(select*from c a where not exists(select*from c where n<a.n and mod(a.n,n)=0))

co upiększa:

with c as ( 
 select level + 1 n 
   from dual 
connect by level < 1e124
        )
select lead(n) over ( order by n ) 
  from ( select *
           from c a 
          where not exists( select * 
                              from c 
                             where n < a.n 
                               and mod(a.n, n) = 0
                                   )
                )

Stara odpowiedź (196)

with c as(select level+1n from dual connect by level<1e124)select n,p,p-n from(select n,lead(n)over(order by n)p from(select*from c a where not exists(select*from c where n<a.n and mod(a.n,n)=0)))

oraz w czytelnym formacie:

with c as ( 
 select level + 1 n 
   from dual 
connect by level < 1e124
        )
select n, p, p-n 
  from ( select n, lead(n) over ( order by n ) p 
           from ( select * 
                    from c a 
                   where not exists (
                                select * 
                                  from c
                                 where n < a.n 
                                   and mod(a.n, n) = 0
                                       )
                         )
                )

To tworzy generator liczb w c , najbardziej wewnętrzny podselekcja tworzy liczby pierwsze za pomocą sita Eratostenesa, zewnętrzny sprawdza poprzednią liczbę pierwszą, a na koniec ostatni wybór odejmuje jeden od drugiego.

To nic nie zwróci, ponieważ wykonuje 1 x 10 124 zapytań rekurencyjnych ... Więc jeśli chcesz, aby działał, obniż tę liczbę do rozsądnego poziomu.


Jeśli chodzi o takie wyzwanie, myślę o SQL nie tyle o ukończeniu Turinga, ile o uparciu Turinga.
Jonathan Van Matre

Ale to jest Turning-complete @Jonathan, chociaż zdobycie go jest czasem „interesujące” :-)?
Ben

Wiedząc, że to kompletny Turing, chciałem żartować. Najwyraźniej przegapił znak. :) W każdym razie w moim profilu jest kilka odpowiedzi T-SQL ... przynieś swoją Oracle i chodźmy na pojedynek!
Jonathan Van Matre

0

D - 153 + 10 = 163

Chętnie biorę tutaj karę +10, ponieważ liczba znaków jest nadal niższa niż byłaby, gdybym również wydrukował liczby pierwsze.

Gra w golfa :

import std.stdio;bool p(int l){int n;foreach(i;1..l+1)n+=l%i==0?1:0;return n==2;}void main(){int g;foreach(l;0..int.max)if(l.p){if(g>0)(l-g).write;g=l;}}

Wersja do odczytu :

import std.stdio;

bool prime( int number )
{
    int divisors;

    foreach( i; 1 .. number + 1 )
        divisors += number % i == 0 ? 1 : 0;

    return divisors == 2;
}

void main()
{
    int lastPrime;

    foreach( number; 0 .. int.max )
        if( number.prime )
        {
            if( lastPrime > 0 )
                ( number - lastPrime ).write;

            lastPrime = number;
        }
}

0

JAVASCRIPT 174 char

var p=[2],l=2,g=0;
for(var n=3;n>0;n+=2){
  var o=0;
  for(var t=0;t<p.length;++t){
    if(n/p[t] == parseInt(n/p[t])){
      o=1;
    }
  }
  if(o==0){
    p.push(n);
    if(n-l>g){
      g=n-l;
      console.log(l,n,g);
    }
    l=n;
  }
}

krótka wersja:

var p=[2],l=2,g=0;for(var n=3;n>0;n+=2){var o=0;for(var t=0;t<p.length;++t){if(n/p[t] == parseInt(n/p[t])){o=1;}}if(o==0){p.push(n);if(n-l>g){g=n-l;console.log(l,n,g);}l=n;}}

0

JavaScript 138

for(var a=2,b=0,c=0;a++;){var d;a:{for(var e=a,f=2;f<e;f++)if(0==e%f){d=!1;break a}d=!0}d&&(0!=b&&a-b>c&&(c=a-b,console.log(b,a,c)),b=a)}

Skopiuj ten kod do konsoli przeglądarki. Tak będzie na zawsze, ponieważ maksymalna liczba jest czymś w pobliżu 1.79*10^308.

Nie golfowany:

var number = 2;
var lastPrime = 0;
var gap = 0;

while(number++)
{
    if (isPrime(number)) {
        if (lastPrime != 0) {            
            if (number - lastPrime > gap)
            {
                gap = number - lastPrime;
                console.log(lastPrime, number, gap);
            }
        }

        lastPrime = number;
    }
}

function isPrime(n){
    for (var i = 2; i < n; i++) {
        if (n % i == 0)
            return false;
    }
    return true;
}

0

C # 162 161 znaków

151 znaków + 10 znaków kary = 161 znaków

Krótka wersja:

using System;class P{static void Main(){int p=2,g=0;for(int i=3;;i++){for(int j=2;j<i;j++)if(i%j==0)goto e;if(i-p>g)Console.WriteLine(g=i-p);p=i;e:;}}}

Długa wersja:

using System;

class PrimeGaps
{
    private static void Main()
    {
        int lastPrime = 2;
        int largestGap = 0;

        for (int i = 3; true; i++)
        {
            // Prime test
            for (int j = 2; j < i; j++)
                if (i%j == 0)
                    goto nextI; // Skip to next iteration of i

            // Largest gap check
            if (i - lastPrime > largestGap)
            {
                largestGap = i - lastPrime;
                Console.WriteLine(largestGap);
            }

            // Remember last prime
            lastPrime = i;

            nextI:
                ; // Do nothing
        }
    }
}

W rzeczywistości lepiej było wziąć 10 znaków kary, ponieważ jest krótszy g(11 znaków z karą) niż p+" "+i+" "+g(13 znaków bez kary).


0

Ruby 90 86 84 83 znaków

r,i,g=2,2,0;while i+=1 do(2...i).all?{|j|i%j>0}&&((i-r<=g||p([r,i,g=i-r]))&&r=i)end

Niektóre zwarcia logiczne, nadużycie oceny ekspresji itp.


0

C 248

Kod porównuje kolejne liczby pierwsze a, b, a następnie sprawdza, czy luki są większe niż g, a następnie znajduje następną parę liczb pierwszych.

#include <cstdio>
void f(int* a, int* b){*a =*b;int t=1;while (*b += 2){t=1;for(int i=3;i<*b;i+=2){if(*b%i==0){t=0; break;}}if(t)break;}}
int main(){int a=2,b=3,g=0;do{(b-a>g)?printf("%d %d %d\n",a,b,(g=b-a)): f(&a,&b);} while(b>=0);return 0;}

To jest C ++, prawda?
Zacharý

0

Haskell, 154 144 137 123

pLiczby pierwsze są generowane za pomocą sita erasthotenów #, a następnie filtrowane i drukowane za pomocą %.

p=2:3#1
n#m|all((>0).mod n)$take m p=n:(n+1)#(m+1)|1<2=(n+1)#m
(l:u@(o:_))%k|o-l>k=print(l,o,o-l)>>u%(o-l)|1<2=u%k
main=p%0

Wygląda jak

(2,3,1)
(3,5,2)
(7,11,4)
(23,29,6)
(89,97,8)

co mam nadzieję jest w porządku.


0

Game Maker Language, 85

Zakładając, że wszystkie niezainicjowane zmienne 0to (jest to domyślne ustawienie w niektórych wersjach Game Maker).

a=2b=2for(d=2;b++;1)for(c<b-a;b mod --d;1)d<3&&(c=b-a&&show_message_ext("",a,b,c)a=b)

0

Game Maker Language, 74 + 55 = 129

Zakładając, że wszystkie niezainicjowane zmienne 0to (jest to domyślne ustawienie w niektórych wersjach Game Maker).

n=2while(n++){if p(n){if l{if n-l>g{g=n-l;show_message_ext("",l,n,g)}}l=n}

Skrypt pznajduje się poniżej:

r=1a=argument0for(i=2i<a;i++){if a mod i=0r=0}return r}

0

Perl, 87 bajtów ( przy użyciu modułu )

use Math::Prime::Util":all";$l=2;forprimes{if($_-$l>$m){say"$l $_ ",$m=$_-$l}$l=$_}1e14

Napisałem moduł, ale musielibyśmy dodać dodatkowe 565,000 znaków do licznika. Przeważnie publikowanie dla zabawy, ale także w celu zapewnienia alternatywnej wydajności, ponieważ do tej pory nie widzę żadnych programów wbudowanych. 4,6s dla przerw do 1e9, 36s dla przerw do 1e10, 6,5 min dla 1e11.

Pari / GP 2.8 można wykonać w zasadzie w ten sam sposób, aczkolwiek ponad dwukrotnie wolniej:

l=2;m=0;forprime(p=2,1e14,if(p-l>m,print(l," ",p," ",m=p-l));l=p)

-1

Perl 153

Krótki kod:

$i=$a=2;while($a=$i++){if(p($i)){if($m<$m2=$i-$a){$m=$m2;print"$a $i $m$/"}}}sub p{$d=2;$s=sqrt$_[0];while(){return 0if!($_[0]%$d);return 1if$d>$s;$d++}}

łatwy do odczytania:

$i=$a=2;
while($a=$i++){
  if(p($i)){
    if($m<$m2=$i-$a){
      $m=$m2;
      print"$a $i $m$/"
    }
  }
}
sub p {
  $d=2;
  $s=sqrt$_[0];
  while(){
    return 0if!($_[0]%$d);
    return 1if$d>$s;
    $d++;
  }
}

To powoduje powstanie wszystkich luk, nie tylko największych jak dotąd.
orion
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.