Üçgen Ulam spiral


21

Biz yaşadım birkaç ait zorlukları Ulam spiral hakkında. Ama bu yeterli değil.

Bu mücadelede üçgen Ulam spirali (normal kare Ulam spirali yerine) çizeceğiz. İşte spiralin neye benzediğinin bir taslağı.

görüntü tanımını buraya girin

Bildiğimiz gibi, Ulam sarmal tüm doğal sayıları dışa sarmalda düzenler ve yalnızca asal olanları işaretler. Dolayısıyla yukarıdaki çizimde sadece siyah görünen sayılar (primerler) gösterilecektir.

Meydan okuma

Giriş olarak N sayısını kabul edin ve bu sayıya kadar üçgen Ulam spiralini görüntüleyin.

  • Giriş, stdin veya fonksiyon argümanı olabilir.
  • Spiral, yukarıdaki şekilde olduğu gibi pozitif yönde (yani saatin tersi yönünde) dönmelidir.
  • Yukarıdaki şeklin 120 derecelik dönüşlerinden herhangi biri geçerli olacaktır ve dönüş farklı girişler için farklı olabilir. Ancak, zımni üçgenlerin en alçak tarafı, izin verilen dönüşlerin (katların 120 derece) olduğu gibi yatay olmalıdır.
  • Kod , varsayılan veri türünüzle yaptığınız herhangi bir ara hesaplamada izin verilene kadar herhangi bir N için teorik olarak (yeterli zaman ve hafıza verilir) çalışmalıdır . doubleyeterlidir; Büyük tamsayı türleri için gerek yok.
  • Tüm yerleşik işlevlere izin verilir.
  • Kendi cevabımı kabul etmeyeceğim (bunun en kısa olacağını düşünüyorum sanmıyorum ...).

Çıkış biçimleri

Aşağıdakilerden herhangi birini seçin.

  1. Asal sayılarda bir işaretleyici (nokta, daire, çapraz, ne istersen) ve asal olmayan sayılarda hiçbir şey içermeyen bir grafik görüntüleyin . Ölçek iki eksen için aynı olması gerekmez. Yani, zımni üçgenlerin eşkenar olması gerekmez. Eksenler, ızgara çizgileri ve eksen etiketleri isteğe bağlıdır. Yalnızca asal sayılardaki işaretçiler gereklidir.

    N = 12 için örnek bir çıktı aşağıdaki gibi olacaktır (yukarıdaki çizim ile karşılaştırınız). İkinci çizim, N = 10000'e karşılık gelen daha ilginç bir örnektir .

görüntü tanımını buraya girin

görüntü tanımını buraya girin

  1. İyi bilinen herhangi bir görüntü biçiminde (png, tiff, bmp gibi), yukarıdakilerle bir görüntü dosyası oluşturun.
  2. Spiralleri ASCII resmi olarak gösterin , asal sayılar için seçtiğiniz tek bir karakter ve asal olmayanlar için boş alan kullanın, aynı satırdaki sayı konumlarını ayırmak için boş bir alan kullanın. Öncü veya sondaki boşluklara veya yeni satırlara izin verilir. Örneğin, N = 12 okarakter olarak kullanılan durum

                 o
                · ·
               · o ·
                o · ·
               · o · o
    

    Tabii ki sadece oasallardaki işaret gerçekte görüntülenecektir. ·Olmayan asal de yalnızca başvuru amacıyla gösterilmiştir.

Kazanma kriteri

Asıl ödül, kendin için bu muhteşem kalıpları görmektir. Kod golf, en kısa kod kazanır.


2
Gelecekte, gönderimleri daha az karşılaştırılabilir kıldığından, [grafiksel çıktı] ve [ascii-sanat] 'dan sadece birini seçmenizi tavsiye ederim. Ama yine de güzel bir meydan okuma. :)
Alex A.

@AlexA. Teşekkürler! Bunu dikkate alacağım. Demek ... bir Julia cevabı olacak mı? ;-)
Luis Mendo,

Vay, ödül için teşekkürler, ama kendi cevabını kabul etmelisin. Bu ise en kısa. :)
Martin Ender

Hak ediyor! Bir cevabı kabul etmek için, meydan okuma kurallarından biri “Kendi cevabımı kabul etmiyorum” idi. Bu meydan okumayı düşündüğümde, kaçınılmaz olarak MATL'yi, karmaşık sayı ve grafik işlevleriyle aklımdaydı, bu yüzden biraz hile yapmak üzereydim :-)
Luis Mendo,

Yanıtlar:


13

CJam, 49 42 bayt

Lri{)mp0S?}%{1$,)/(a@Wf%z+\L*}h;eeSff*W%N*

STDIN'de tek bir tam sayı olarak giriş yapın. 0Asal sayılarla ASCII ızgarası olarak çıktı . Spiralin dönüşü tutarlı değildir: Spiralin en büyük sayısı her zaman en alt satırda olacaktır.

Burada test et.

açıklama

Temel fikir, hesaplama yaparken üçgeni düzensiz bir 2D dizi olarak temsil etmektir. Çizgileri tersine çevirerek ve tüm satırları sola hizalayarak bu diziyi elde edersiniz:

   4
  5 3
 6 1 2
7 8 9 A

Olarak temsil edilir

[[7 8 9 A]
 [6 1 2]
 [5 3]
 [4]]

Çizgiyi yansıtdığımızdan beri, spirali saat yönünde sarmak istiyoruz . Bu uygun, çünkü tek yapmamız gereken üçgeni saat yönünün tersine döndürmek ve sırayla bir sonraki alt listeyi hazırlamak. Tüm satırları tersine çevirerek ve kopyalayarak düzensiz diziyi döndürebiliriz:

                                                           [[B C D E F]
[[7 8 9 A]         [[A 9 8 7]           [[A 2 3 4]          [A 2 3 4]
 [6 1 2]   reverse  [2 1 6]   transpose  [9 1 5]   prepend  [9 1 5]
 [5 3]      ---->   [3 5]      ------>   [8 6]      ---->   [8 6]
 [4]]               [4]]                 [7]]               [7]]

Demek kod burada. Dikkat çekmek istediğim bir detay, üçgen düzeni oluşturan son kısım. Bence oldukça şık. :)

L     e# Push an empty array. This will become the spiral.
ri    e# Read input and convert to integer N.
{     e# Map this block over 0 to N-1...
  )   e#   Increment to get 1 to N.
  mp  e#   Test for primality.
  0S? e#   Select 0 or a space correspondingly.
}%
{     e# While the list we just created is not empty yet...
  1$  e#   Copy the spiral so far.
  ,)  e#   Get the number of lines and increment.
  /   e#   Split the list into chunks of that size.
  (a@ e#   Pull off the first chunk, wrap it in an array, pull up the spiral.
  Wf% e#   Reverse the lines of the spiral.
  z   e#   Transpose the spiral.
  +   e#   Prepend the new line.
  \L* e#   Swap with the remaining chunks and join them back together into a single list.
}h
;     e# Discard the empty list that's left on the stack.
ee    e# Enumerate the spiral. This turns each line into a pair of 0-based index
      e# and the line itself.
Sff*  e# Multiply each element of each pair with a space. For the enumeration index i,
      e# this produces a string of i spaces - the required indentation (keeping in
      e# mind that our spiral is still upside down). For the line itself, this
      e# riffles the cells with spaces, creating the required gaps between the cells.
      e# All of this works because we always end the spiral on the bottom edge.
      e# This ensures that the left edge is always complete, so we don't need
      e# different indentation such as in the N=12 example in the challenge.
W%    e# Reverse the lines to make the spiral point upwards.
N*    e# Join the lines with linefeeds.

1
İlk olacağını biliyordum!
Luis Mendo,

@LuisMendo Aslında bunu atlayacaktım çünkü ızgara endekslerinin hesaplanmasının sıkıcı olacağını düşündüm, ama sonra satırları eklerken tüm üçgeni döndürebileceğimi fark ettim.
Martin Ender,

1
CJam programlarının açıklamalarını her zaman seviyorum, çünkü onları anlayabiliyorum ve bu programların ne kadar karmaşık, ama kısa olabileceğine hayret ediyorum.
ETHProductions

10

MATL , 48 36 bayt

:1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG

Mevcut sürümü kullanır (9.3.0) .

Çevrimiçi deneyin! Çevrimiçi derleyicinin grafik çıktısını ASCII'ye çevirmeyi nasıl yönettiği hakkında hiçbir fikrim yok, ancak bunu yapıyor Bu, çevrimiçi derleyici tarafından desteklenenbir Octave özelliği sayesinde yaklaşık bir ASCII grafiği oluşturur!

Düzenleme (4 Nisan 2016): 13.0.0 yayımından bu yana işlev Y[yeniden adlandırıldı k. Çevrimiçi derleyiciye olan bağlantı bu değişikliği içerir; böylece kod test edilebilir.

Örnek

>> matl
 > :1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG
 > 
> 20000

grafiksel çıktı üretir (gösterilen MATLAB sürümü):

görüntü tanımını buraya girin

açıklama

Kod, spirali takip eden yolu izlemek için karmaşık sayılar kullanır. Yarışmadaki ilk şekilden görülebileceği gibi, sarmalın her bir düz ayağı, uzunluğu 1, 2, 3, 4 ... ve döngüsel olarak artan yönelimin 120 derece, 240 derece, 0 derece, 120 derece olduğu bir parçadır. ..

Kod ilk önce her bir tam sayıdan diğerine bireysel karmaşık yer değiştirmeleri oluşturur. Bu kompleks değiştirmeler büyüklüğü 1 ve açısına sahiptir 2*pi/3, 4*pi/3ya da 0(radyan cinsinden). Böylece kolayca hayali üsteller olarak oluşturulabilirler. Bunun için, önce 0,1,2,2,3,3,3,4,4,4,4,4 ... tamsayı dizisi kullanılır.

Bu tamsayı dizisi neredeyse "n n kez görünür" dizisi gibidir ( OEIS A002024 ) ve 0,1,2,3, ... floor(sqrt(2*n)+.5)olduğu gibi elde edilebilir n. İle çarpılması 2j*pi/3, burada j, sanal birim, arzulanan kompleks değiştirmeler üretir.

Yer değiştirmeler, spiral içindeki tam sayılara karşılık gelen konumları hesaplamak için birikir. Spiraldeki ilk tam sayı, yani karmaşık düzlemde 1keyfi bir şekilde konumlandırılmıştır 1.

Son olarak, asal olmayan sayılara karşılık gelen pozisyonlar atılır ve geri kalanı karmaşık düzlemde çizilir.

:1-H*X^.5+Y[     % floor(sqrt(2*n)+.5) for n from 0 to N-1, where N is implicit input
2j3/*YP*Ze       % exp(2j*pi/3* ... )
Ys               % cumulative sum. Produces complex positions
G:               % vector 1,2...,N, where N is previous input
Zp               % logical index to select only prime numbers
)                % use that index to keep only complex positions of primes
'.'2$XG          % plot using marker '.'

Bunu daha fazla okumam için
gerekenler

Çevrimiçi Deneyin mi! MATL için grafiksel çıktı desteği
Alex A.

TIO’nun grafik çıktısını desteklemediğini sanıyordum? Eğer varsa, ben kolayca Matl otomatik olarak görüntüleri dökümü olabilir .pngweb sayfası @AlexA tarafından gösterilmeye dosyanın
Luis Mendo

Hey! Basit test ( plot(1:5)) yaptım ve metin-grafik çıktı üretti !! matl.tryitonline.net/#code=NTpYRw&input= @AlexA. Bu nasıl??
Luis Mendo,

4
VAY! Bu harika!
Alex A.

8

Çizim yapılmalı

LaTeX / PGF, 527 594 bayt

\documentclass{standalone}\usepackage{pgf}\let\z\let\z\e\advance\z\f\ifnum\z\h\the\z\a\newcount\a\i\a\j\a\l\a\x\a\y\a\p\a\q\a\n\i=1\l=1\p=-1\q=1\def\m#1{\e\i by1\e\j by1\e\x by\h\p\e\y by\h\q\pgfmathparse{isprime(\h\i)}\f\pgfmathresult=1\pgfpathcircle{\pgfpoint{\h\x cm}{\h\y cm}}3pt\fi\f\j=\l\e\l by1\j=0\f\p=1\p=-1\q=1\else\f\p=-1\p=0\q=-1\else\p=1\q=0\fi\fi\fi\f#1>0\e#1by-1\m#1\fi}\begin{document}\begin{pgfpicture}\pgftransformcm10{cos(60)}{sin(60)}\pgfpointorigin\n=4000\m\n\pgfusepath{fill}\end{pgfpicture}\end{document}

527 bayt yukarıdaki gibi tam belgedir, yani başlangıç ​​ve parametre dahil (burada 4000, yani ~ 523 parametresiz). Bir PDF dosyası üretir.

Temel fikir: iyi, sadece çizin. Üçgen bir ızgara için matris dönüşümü kullanır . Tek sorun, noktaların dönüşümden etkilenmesi (ve gerilmesi). Bu yüzden elips belirteçleri seçiyorum :) ikinci görüntüde neyi kastediyorum (n = 250, 5pt).

Başka bir uyarı: TeX'in maksimum yığın boyutu nedeniyle yalnızca 5000'den az bir miktarla başa çıkabilir. İlk görüntü n = 4000 içindir. Görünüşe göre yığın boyutunu artırmak mümkün , denemedim.

PGF's kullanır isprime().

görüntü tanımını buraya girin

görüntü tanımını buraya girin

Ungolfed:

\documentclass[border=10cm]{standalone}

\usepackage{pgf}

\newcount\ulami
\newcount\ulamj
\newcount\ulamlen

\newcount\ulamx
\newcount\ulamy
\newcount\ulamdx
\newcount\ulamdy

\ulami=1 %
\ulamj=0 %
\ulamlen=1 %
\ulamdx=-1 %
\ulamdy=1 %
\ulamx=0 %
\ulamy=0 %

\def\ulamplot#1{%
  \advance\ulami by 1 %
  \advance\ulamj by 1 %

  \advance\ulamx by \the\ulamdx %
  \advance\ulamy by \the\ulamdy %

  \pgfpathmoveto{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}

  \pgfmathparse{isprime(\the\ulami)}
  \let\r=\pgfmathresult
  \ifnum\r=1
    \pgfpathcircle{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}{5pt}
  \fi

  \ifnum\ulamj=\the\ulamlen %
    \advance\ulamlen by 1 %
    \ulamj=0 %
    \ifnum\ulamdx=1 %
      \ulamdx=-1 %
      \ulamdy=1 %
    \else%
      \ifnum\ulamdx=-1 %
        \ulamdx=0 %
        \ulamdy=-1 %
      \else%
        \ulamdx=1 %
        \ulamdy=0 %
      \fi
    \fi
  \fi

  \ifnum#1>0 %
    \advance#1 by -1 %
    \ulamplot{#1}%
  \fi
}

\begin{document}

\begin{pgfpicture}
  \pgfmathsetmacro{\x}{cos(60)}
  \pgfmathsetmacro{\y}{sin(60)}
  \pgftransformcm{1}{0}{\x}{\y}{\pgfpointorigin}

  \pgfpathmoveto{\pgfpointorigin}
  \color{blue}
  \newcount\ulamn
  \ulamn=400
  \ulamplot{\ulamn}
  \pgfusepath{stroke,fill}
\end{pgfpicture}

\end{document}

1
Vay. Bunu LaTeX'te yapmak hiç aklıma gelmezdi
Luis Mendo,

lualatexDinamik olarak tahsis eden bir derleyicinin veya başka bir kısmının kullanılması , ilgili yorumunuzu doğru anlıyorsam yığın boyutunu atlamanıza izin vermelidir. Bu yüzden cevabınızın bir kısıtlaması değil, sadece onu uygulayacağınız uygulamaların çoğu için bir sınırlama değil.
Andras Deak

Üzgünüm, kontrol ettim ve giriş yığını boyut sınırı önceki
yorumumda

@AndrasDeak tamam, aradığınız için teşekkürler. Görünüşe göre yığın boyutunu artıran bir yöntem buldum , ancak kendim denemedim.

@CamilStaps teşekkürler, başka benzer mesajlar buldum, ancak onları da denemedim. Neyse, Christian Feuersänger'in mesajlarını canon olarak kabul ediyorum :)
Andras Deak

2

Mathematica, 94 bayt

ListPlot@Accumulate[Join@@Table[ReIm@Exp[2i Pi/3I],{i,2#^.5},{i}]][[Prime@Range@PrimePi@#-1]]&

Sonuç

%[10000]

görüntü tanımını buraya girin


2

Python, 263 bayt

Python'a yeniyse, kesinlikle gelişime açık bir yer var :)

from matplotlib.pyplot import*
from math import*
def f(m):
 s=[];X=[];Y=[];i=x=y=0
 while len(s)<m:i+=1;s+=[i%3*pi*2/3]*i
 for i in range(m):
  x+=cos(s[i]);y+=sin(s[i]);j=i+2
  if all(map(lambda a:j%a>=1,range(2,int(j**.5+1)))):X+=[x];Y+=[y]
 scatter(X,Y);show()

Örnek:

f(100000)

görüntü tanımını buraya girin


Sen kısaltabilir s=[];X=[];Y=[];i=1;x=0;y=0içins=X=Y=[];i=1;x=y=0;
rp.beltran

Sonunda bu fazla noktalı virgül yoksay. Sana 8 byte vermeli.
rp.beltran

@ rp.beltran. Bu çalışmıyor. Bence nesnelerin aynı değerleri paylaşması gerçeğiyle ilgili. Sadece ekleyebildim x=y=0.
lambruscoAcido

Benim hatam sen haklısın. Python'un referans olarak listeleri geçtiğini unuttum. Sayılar değişmezdir ve bu nedenle tam sayılarla yapmak güvenlidir.
rp.beltran

1

R, 137 bayt

Asal sayılar için bile, yalnızca yerleşik işlevleri kullanır. İteratif yerine vectorized yaklaşımı göz önüne alındığında, hızlı, ancak büyük sayıları idare edemez.

golfed:

g=function(m){M=1:m;s=rep(M,M)[M]%%3*pi*2/3;k=cumsum;j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1));plot(k(cos(s))[j],k(sin(s))[j])}

Ungolfed:

g=function(m) {
  M = 1:m
  s = rep(M,M)[M] %% 3 * pi * 2/3
  k=cumsum
  j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1)) # primes
  plot(k(cos(s))[j],k(sin(s))[j])    # cumulated coordinates
}

Örnek:

g(10000)

görüntü tanımını buraya girin


Örnek bir sonuç ekleyebilir misiniz?
Luis Mendo

@LuisMendo. Emin. Sadece nasıl bir arsa ekleyeceğimi bulmak zorunda kaldım.
lambruscoAcido
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.