Czy kwadratowe słoje mogą być generowane z liczb pierwszych?


33

Najwyraźniej tak! W trzech łatwych krokach.

Krok 1

Niech f ( n ) oznacza funkcję zliczania liczb pierwszych (liczba liczb pierwszych mniejsza lub równa n ).

Zdefiniuj sekwencję całkowitą s ( n ) w następujący sposób. Dla każdej dodatniej liczby całkowitej N ,

  • Zainicjuj t do n .
  • Dopóki t nie jest ani liczbą pierwszą ani 1, zamień t na f ( t ) i iteruj.
  • Liczba iteracji to s ( n ).

Proces iteracyjny gwarantuje zakończenie, ponieważ f ( n ) < n dla wszystkich n .

Rozważmy na przykład n = 25. Inicjalizujemy t = 25. Ponieważ nie jest to liczba pierwsza ani 1, obliczamy f (25), które wynosi 9. To staje się nową wartością dla t . To nie jest liczba pierwsza ani 1, więc kontynuujemy: f (9) wynosi 4. Kontynuujemy ponownie: f (4) wynosi 2. Ponieważ jest to liczba pierwsza, zatrzymujemy się tutaj. Zrobiliśmy 3 iteracje (od 25 do 9, następnie do 4, a następnie do 2). Zatem s (25) wynosi 3.

Pierwsze 40 elementów sekwencji są następujące. Sekwencja nie znajduje się w OEIS.

0 0 0 1 0 1 0 2 2 2 0 1 0 2 2 2 0 1 0 3 3 3 0 3 3 3 3 3 0 3 0 1 1 1 1 1 0 2 2 2

Krok 2

Biorąc pod uwagę nieparzystą dodatnią liczbę całkowitą N , zbuduj tablicę N × N (macierz), nawijając skończoną sekwencję s (1), s (2), ..., s ( N 2 ), aby utworzyć kwadratową spiralę na zewnątrz . Na przykład, biorąc pod uwagę N = 5, spirala jest

s(21)   s(22)   s(23)   s(24)   s(25)
s(20)   s(7)    s(8)    s(9)    s(10)
s(19)   s(6)    s(1)    s(2)    s(11)
s(18)   s(5)    s(4)    s(3)    s(12)
s(17)   s(16)   s(15)   s(14)   s(13)

lub zastępując wartości,

 3       3       0       3       3
 3       0       2       2       2
 0       1       0       0       0
 1       0       1       0       1
 0       2       2       2       0

Krok 3

Przedstaw tablicę N × N jako obraz za pomocą szarej mapy kolorów lub innej mapy kolorów według własnego gustu. Mapa powinna być stopniowa, aby kolejność liczb odpowiadała wizualnie oczywistej kolejności kolorów. Poniższe przypadki testowe pokazują przykładowe mapy kolorów.

Wyzwanie

Biorąc pod uwagę nieparzystą dodatnią liczbę całkowitą N , wykonaj zdjęcie opisane powyżej.

Zasady

  • Spirala musi być skierowana na zewnątrz, ale może być zgodna z ruchem wskazówek zegara lub przeciwna do ruchu wskazówek zegara i może zacząć przesuwać się w prawo (jak w powyższym przykładzie), w lewo, w dół lub w górę.

  • Skale osi poziomej i pionowej nie muszą być takie same. Również etykiety osi, pasek kolorów i podobne elementy są opcjonalne. Dopóki spirala jest wyraźnie widoczna, obraz jest prawidłowy.

  • Obrazy można wyprowadzać dowolnym standardowym sposobem . W szczególności obraz może być wyświetlany na ekranie lub może zostać utworzony plik graficzny lub może zostać wyprowadzony szereg wartości RGB. Jeśli wyprowadzasz plik lub tablicę, zamieść przykład tego, jak to wygląda po wyświetleniu.

  • Środki wprowadzania i format są jak zwykle elastyczne . Program lub funkcja może być zapewnione . Standardowe luki są zabronione .

  • Najkrótszy kod w bajtach wygrywa.

Przypadki testowe

Poniższe zdjęcia (kliknij w pełnej rozdzielczości) odpowiadają kilku wartości N . Zastosowano spiralę, zgodnie z ruchem wskazówek zegara, pierwszą w prawo, jak w powyższym przykładzie. Obrazy ilustrują również kilka prawidłowych map kolorów.

  • N = 301: wprowadź opis zdjęcia tutaj

  • N = 501: wprowadź opis zdjęcia tutaj

  • N = 701: wprowadź opis zdjęcia tutaj


Jeśli tablica wartości s(n)może być wprowadzona do jakiejś funkcji / pakietu kreślącego bez modyfikacji (myślę, że imshoww matplotlib mógłby to na przykład poradzić), czy jest to akceptowalna forma wyjściowa?
dylnan

@dylnan Pewnie, o ile drukuje obraz na ekranie lub tworzy plik, jest prawidłowy. W rzeczywistości wygenerowałem przykłady z czymś podobnym do tego, o czym wspomniałeś. Uważaj tylko na skalowanie wartości. Na przykład niedopuszczalne jest, aby wszystkie wartości powyżej 1 miały ten sam kolor, jak imshowrobi Matlab (i prawdopodobnie Matplotlib)
Luis Mendo

Słuszna uwaga. Nie jestem pewien, czy to imshowrobi.
dylnan

1
@ kamoroso94 Proszę zobaczyć tutaj
Luis Mendo

1
Tak, bardzo jasne
Christopher

Odpowiedzi:


3

Dyalog APL, 94 bajty

'P2'
2⍴n←⎕
9
(⍪0){×≢⍵:(≢⍺)((⍉∘⌽⍺,↑)∇↓)⍵⋄⍺}2↓{⍵⌊1+⍵[+\p]}⍣≡9×~p←1=⊃+/(≠⍨,≠⍨,~⍴⍨(×⍨n)-2×≢)¨,\×⍳n

zakłada ⎕IO=0

wyjście dla n = 701 (przekonwertowane z .pgm na .png):

wprowadź opis zdjęcia tutaj


10

MATLAB - 197 185 178 175 184 163 162 148 142 140 bajtów

Ogoliłem 12 bajtów, dzięki Anderowi i Andrasowi, i wiele podziękowań dla Luisa za połączenie tych dwóch. Ogolono 16 dzięki Remco, 6 dzięki flawr

function F(n)
p=@primes
s=@isprime
for a=2:n^2
c=0
if~s(a)
b=nnz(p(a))
while~s(b)
b=nnz(p(b))
c=c+1
end
end
d(a)=c
end
imagesc(d(spiral(n)))

Wynik dla N=301( F(301)):

wprowadź opis zdjęcia tutaj

Wyjaśnienie:

function F(n)
p=@primes % Handle
s=@isprime % Handle
for a=2:n^2 % Loop over all numbers
    c=0 % Set initial count
    if~s(a) % If not a prime
        b=nnz(p(a)) % Count primes
        while~s(b) % Stop if b is a prime. Since the code starts at 2, it never reaches 1 anyway
            b=nnz(p(b)) % count again
            c=c+1 % increase count
        end
    end
    d(a)=c % store count
end
imagesc(d(spiral(n))) % plot

8

Wolfram Language (Mathematica) , 124 bajty

Dzięki Martin Ender za oszczędność 12 bajtów!

Image[#/Max@#]&[Array[(n=0;Max[4#2#2-Max[+##,3#2-#],4#
#-{+##,3#-#2}]+1//.x_?CompositeQ:>PrimePi[++n;x];n)&,{#,#},(1-#)/2]]&

Wypróbuj online!


Wygenerowany obraz to:

Spirala

Formuła zamkniętej formy wartości spiralnej zaczerpnięta bezpośrednio z tej mojej odpowiedzi .


5
#/2-.5zapisuje bajt.
user202729

8
Haha, sugerujesz to sobie?
Luis Mendo

6
@ user202729 Nie wydaje się działać.
user202729,

18
Nie chciałem przerywać twojego wewnętrznego dialogu:
Luis Mendo

Odłóż definicję, pdopóki jej nie potrzebujesz:...,{y,p=(1-#)/2,-p},{x,p,-p}
Martin Ender

7

MATLAB: 115 114 110 bajtów

Jedna linijka (działająca w R2016b + jako funkcja w skrypcie ) 115 bajtów

I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)));function k=s(n,k);if n>1&~isprime(n);k=s(nnz(primes(n)),k+1);end;end

Umieszczenie funkcji w osobnym pliku, jak sugeruje flawr, i użycie 1 dodatkowego bajtu na regułę dla dodatkowego pliku

W pliku s.m64 + 1 bajtów dla kodu + pliku

function k=s(n,k);if n>1&~isprime(n);k=s(nnz(primes(n)),k+1);end

Okno poleceń do zdefiniowania I, 45 bajtów

I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)))

Łącznie: 110 bajtów


Używa rekurencji zamiast whilezapętlania, podobnie jak inne implementacje MATLAB ( gnovice , Adriaan ). Uruchom go jako skrypt (w wersji R2016b lub nowszej), definiuje to funkcję, Iktórą można uruchomić w podobny sposób I(n).

Wersja strukturalna:

% Anonymous function for use, i.e. I(301)
% Uses arrayfun to avoid for loop, spiral to create spiral!
I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)));

% Function for recursively calculating the s(n) value
function k=s(n,k)
    % Condition for re-iterating. Otherwise return k unchanged
    if n>1 && ~isprime(n)
        % Increment k and re-iterate
        k = s( nnz(primes(n)), k+1 );
    end
end

Przykład:

I(301)

wątek

Uwagi:

  • Próbowałem też uczynić tę sfunkcję anonimową, co oczywiście znacznie zmniejszyłoby liczbę. Istnieją jednak 2 problemy:

    1. Podczas korzystania z anonimowych funkcji trudno jest uniknąć nieskończonej rekurencji, ponieważ MATLAB nie ma potrójnego operatora oferującego warunek przerwania. Powiązanie operatora trójskładnikowego (patrz poniżej) również kosztuje bajty, ponieważ warunek jest potrzebny dwa razy.

    2. Musisz przekazać do siebie anonimową funkcję, jeśli jest rekurencyjna (patrz tutaj ), która dodaje bajty.

    Najbliżej tego doszedłem użyłem następujących linii, być może można to zmienić do pracy:

    % Condition, since we need to use it twice 
    c=@(n)n>1&&~isprime(n);
    % This uses a bodged ternary operator, multiplying the two possible outputs by
    % c(n) and ~c(n) and adding to return effectively only one of them
    % An attempt was made to use &&'s short-circuiting to avoid infinite recursion
    % but this doesn't seem to work!
    S=@(S,n,k)~c(n)*k+c(n)&&S(S,nnz(primes(n)),k+1);

6

MATLAB - 126 121 * bajtów

Spróbowałem bardziej wektoryzowanego podejścia niż Adriaan i udało mi się ogolić więcej bajtów. Oto rozwiązanie jednoliniowe:

function t(n),M=1:n^2;c=0;i=1;s=@isprime;v=cumsum(s(M));while any(i),i=M>1&~s(M);c=c+i;M(i)=v(M(i));end;imagesc(c(spiral(n)))

A oto ładnie sformatowane rozwiązanie:

function t(n),
  M = 1:n^2;
  c = 0;
  i = 1;
  s = @isprime;
  v = cumsum(s(M));
  while any(i),         % *See below
    i = M > 1 & ~s(M);
    c = c+i;
    M(i) = v(M(i));
  end;
  imagesc(c(spiral(n)))

* Uwaga: jeśli chcesz zezwolić na metryczny zbiór niepotrzebnych iteracji, możesz zmienić linię while any(i), na for m=v, i zapisać 5 bajtów.


Miły! Podoba mi się sposób cumsumwektoryzacji i unikaniannz(primes(...)
Luis Mendo

1
Jeśli dobrze rozumiem, iteracja nie zaszkodzi więcej razy, niż to konieczne (kosztem prędkości). Więc można zastąpić while any(i)przez for m=M. Kogo to obchodzi, jeśli uruchomienie kodu zajmuje wiele godzin :-)
Luis Mendo

2
@LuisMendo: Jasne, czemu nie? Już iteruje się jeszcze raz, niż jest to potrzebne, co jeszcze n^2zaszkodzi! ;)
gnovice

1
To jest duch! Możesz także zachować szybszą wersję, ale liczba bajtów jest krótsza
Luis Mendo

2

Python 3, 299 265 bajtów

Zaoszczędzono 5 bajtów dzięki sugestiom formatowania autorstwa Jonathana Frecha i NoOneIsHere. Usunięto dodatkowe 34 bajty, usuwając definicję funkcji, która została wywołana tylko raz.

Jest to trochę dłużej niż niektóre inne, ponieważ python nie ma polecenia określającego prymityw ani spirali tablicy. Działa jednak stosunkowo szybko, około minuty n = 700.

from pylab import*
def S(n):
 q=arange(n*n+1);t=ones_like(q)
 for i in q[2:]:t[2*i::i]=0
 c=lambda i:0 if t[i]else 1+c(sum(t[2:i]));S=[c(x)for x in q]
 t=r_[[[S[1]]]]
 while any(array(t.shape)<n):m=t.shape;i=multiply(*m)+1;t=vstack([S[i:i+m[0]],rot90(t)])
 return t

Przetestuj za pomocą

n = 7
x = S(n)
imshow(x, interpolation='none')
colorbar()
show(block=False)

1
Możliwe 294 bajty (nieprzetestowane).
Jonathan Frech

1
Jedna szybka rzecz: możesz usunąć przestrzeń między importi *.
NoOneIsHere

2

J, 121 bajtów

load 'viewmat'
a=:3 :'viewmat{:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0(,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1'

Definiuje funkcję:

a=:3 :'viewmat{:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0(,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1' | Full fuction
                                                                     (,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1  | Creates the number spiral
              {:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0                                      | Applies S(n) to each element
       viewmat                                                                                             | View the array as an image

2

R, 231 bajtów

function(n){p=function(n)sum(!n%%2:n)<2;M=matrix(0,n,n);M[n^2%/%2+cumsum(c(1,head(rep(rep(c(1,-n,-1,n),l=2*n-1),rev(n-seq(n*2-1)%/%2)),-1)))]=sapply(1:(n^2),function(x){y=0;while(x>2&!p(x)){x=sum(sapply(2:x,p));y=y+1};y});image(M)}

Nieco mniej golfa:

function(n){
    p=function(n)sum(!n%%2:n)<2 #"is.prime" function
    M=matrix(0,n,n)             #empty matrix
    indices=n^2%/%2+cumsum(c(1,head(rep(rep(c(1,-n,-1,n),l=2*n-1),rev(n-seq(n*2-1)%/%2)),-1)))
    values=sapply(1:(n^2),function(x){
        y=0
        while(x>2&!p(x)){
            x=sum(sapply(2:x,p))
            y=y+1
            }
        y})
    M[indices]=values
    image(M) #Plotting
}

Funkcja anonimowa. Dane wyjściowe w oknie graficznym. Skala jest na skali czerwonej, a najciemniejszy odcień równa się 0, a wyraźniejsze odcienie zwiększają wartości.

Wynik dla n = 101:

n = 101

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.