三角ウラムスパイラル


21

ウラムのスパイラルについて、いくつか課題がありました。しかし、それだけでは十分ではありません。

この課題では、三角形のウラムスパイラルをプロットします(通常の正方形のウラムスパイラルとは対照的に)。スパイラルがどのように見えるかのスケッチを次に示します。

ここに画像の説明を入力してください

私たちが知っているように、ウラムの螺旋はすべての自然数を外側の螺旋に配置し、素数のみをマークします。したがって、上記のスケッチでは、黒で表示される数字(素数)のみが表示されます。

チャレンジ

入力として数値Nを受け入れ、その数値まで三角形のUlamスパイラルを表示します。

  • 入力は、stdinまたは関数の引数にすることができます。
  • 上の図のように、螺旋は正の方向(つまり、反時計回り)に回転するはずです。
  • 上記の図の120度の回転はいずれも有効であり、入力ごとに回転が異なる場合があります。ただし、許可されるターンは120度(の倍数)のみであるため、暗黙の三角形の最下部は水平になります。
  • コードは、デフォルトのデータ型を使用して行う中間計算で許可されているNまで、理論的に(十分な時間とメモリを与えて)実行する必要があります。double十分です; 大きな整数型は必要ありません。
  • すべての組み込み関数が許可されています。
  • 私は自分の答えを受け入れません(それがとにかく最短になるとは思いませんが...)。

出力形式

次のいずれかを選択します。

  1. 素数ではマーカー(点、円、十字など)を使用してグラフ表示し、非素数では何も表示しません。スケールは2つの軸で同じである必要はありません。つまり、暗黙の三角形は正三角形である必要はありません。軸、グリッド線、軸ラベルはオプションです。素数のマーカーのみが必要です。

    N = 12の出力例は次のとおりです(上記のスケッチと比較してください)。2番目のプロットは、N = 10000に対応する、より興味深い例です。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

  1. 生成画像ファイル(例えば、PNG、TIFF、BMPなど)任意のよく知られた画像形式で、上記と。
  2. スパイラルをASCIIアートとして表示します。プライムには選択した単一の文字を使用し、非プライムには空白スペースを使用し、同じ行の数字の位置を区切る空白スペースを使用します。先頭または末尾のスペースまたは改行を使用できます。たとえば、as文字として使用するN = 12の場合oは、

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

    もちろん、o実際には素数のマークのみが表示されます。·非素数ではあくまで参考のためにここに示されています。

勝利基準

実際の報酬は、コードゴルフ、最短コード勝利という驚くべきパターンを見ることです


2
将来的には、[グラフィック出力]と[アスキーアート]のいずれか1つのみを選択することをお勧めします。これにより、提出物の比較が難しくなります。とにかくいい挑戦です。:)
アレックスA.

@AlexA。ありがとう!それを考慮します。だから...ジュリアの答えがありますか?;-)
ルイスメンドー

うわー、賞金に感謝しますが、あなたはあなた自身の答えを受け入れるべきです。それはです最短。:)
マーティンエンダー

それは当然です!回答を受け入れることに関して、チャレンジルールの1つは「自分の回答を受け入れません」でした。私はこの挑戦を考えたとき、それは少し:-)不正行為のようなものだったので、私は必然的に、その複素数とグラフィカル機能を、念頭に置いてMATLを持っていた
ルイス・Mendo

回答:


13

CJam、49 42バイト

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

STDINに単一の整数として入力します。0素数付きのASCIIグリッドとして出力します。スパイラルの回転には一貫性がありません。スパイラルの最大数は常に最下行にあります。

ここでテストしてください。

説明

基本的な考え方は、計算中に三角形を不規則な2D配列として表すことです。行を逆にしてすべての行を左に揃えることで、この配列を取得します。

   4
  5 3
 6 1 2
7 8 9 A

として表されます

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

ラインをミラーリングしたので、スパイラルを時計回りに巻き上げたいと思います。三角形を反時計回りに回転させ、次のサブリストを順番に追加するだけなので、便利です。すべての行を反転して転置することにより、不規則配列を回転できます。

                                                           [[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]]

これがコードです。注目したい詳細の1つは、三角形のレイアウトを作成する最後の部分です。それはかなり気の利いたものだと思います。:)

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
私はあなたが最初になることを知っていました!
ルイスメンドー

@LuisMendoグリッドインデックスの計算は面倒だと思ったので、実際にはこれをスキップしましたが、線を追加しながら三角形全体を回転させることができることに気付きました。
マーティンエンダー

1
CJamプログラムの説明を理解できるので、私はいつもあなたのCJamプログラムの説明が大好きです。そして、これらのプログラムがどれほど複雑でありながら短いのか、とても驚いています。
ETHproductions

10

MATL48 36バイト

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

現在のリリース(9.3.0)を使用します。

オンラインでお試しください! オンラインコンパイラがグラフィック出力をASCIIに変換する方法はわかりませんが、オンラインコンパイラでサポートされている Octave機能により、おおよそのASCIIプロットが生成されます!

編集(2016年4月4日):この関数Y[k、リリース13.0.0以降に名前が変更されました。オンラインコンパイラへのリンクにはこの変更が組み込まれているため、コードをテストできます。

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

グラフィカル出力を生成します(MATLABバージョンを表示):

ここに画像の説明を入力してください

説明

コードは複素数を使用して、スパイラルが続くパスをトレースします。課題の最初の図からわかるように、スパイラルの各直線脚は、長さが1、2、3、4 ...増加し、方向が120度、240度、0度減少、120度減少する周期的に増加するセグメントです。 ..

コードはまず、各整数から次への個々の複素変位を生成します。これらの複雑な変位は大きさ1と角度持ち2*pi/34*pi/3あるいは0(ラジアン)を。したがって、それらは虚指数として簡単に生成できます。そのために、整数シーケンス0,1,2,2,3,3,3,4,4,4,4 ...が最初に使用されます。

この整数シーケンスは、「n回n回出現する」シーケンス(OEIS A002024)とほぼ同じであり、floor(sqrt(2*n)+.5)where nは0,1,2,3、... として取得できます。を乗算する2j*pi/3と、jは虚数単位であり、目的の複素変位を生成します。

変位は、スパイラル内の整数に対応する位置を計算するために累積されます。スパイラルの最初の整数であるは11複素平面の位置に任意に配置されます。

最後に、非素数に対応する位置は破棄され、残りは複素平面にプロットされます。

: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 '.'

これをさらに読む必要があること
Brain Guider

オンラインで試してみてください!MATLのグラフィカル出力をサポートしていますか?
アレックスA.

TIOはグラフィック出力をサポートしていないと思いましたか?もしそうなら、簡単にMATLに画像を.pngファイルに自動的にダンプさせることができ、ウェブページ@AlexAに表示されるようになります
ルイスメンドー

おい!私は簡単なテスト(plot(1:5))を行いましたが、テキストグラフィック出力を生成します!! matl.tryitonline.net/#code=NTpYRw&input= @AlexA。これはどう?
ルイスメンドー

4
わあ!すごい!
アレックスA.

8

描画は

LaTeX / PGF、527 594バイト

\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バイトは完全なドキュメントです。つまり、プリアンブルとパラメーターを含みます(ここでは4000なので、パラメーターなしで〜523)。PDFファイルを作成します。

基本的なアイデア:まあ、ただ描く。三角グリッドにマトリックス変換を使用ます。唯一の問題は、変換によってドットが影響を受ける(引き伸ばされる)ことです。だから、楕円マーカーを選択します:) 2番目の画像(n = 250、5pt)でそれが意味することは明らかです。

もう1つの注意点:TeXの最大スタックサイズのため、5000未満のビットしか処理できません。最初の画像は、n = 4000用です。どうやらスタックサイズを増やすことができるようです、私はそれを試しませんでした。

PGFを使用しisprime()ます。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ゴルフをしていない:

\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
ワオ。乳液でこれを行うために私に起こったことがないだろう
ルイスMendo

lualatex対応するコメントを正しく理解していれば、その他の動的に割り当てるコンパイラを使用すると、スタックサイズをバイパスできます。したがって、答えを制限するのではなく、実行するほとんどの実装の制限ではありません。
アンドラスDeak

申し訳ありませんが、入力スタックサイズの制限は以前のコメントで対処したメモリ割り当てとは無関係です。(
Andras Deak

@AndrasDeak大丈夫、調べてくれてありがとう。明らかにスタックサイズを増やす方法を見つけましが、自分で(まだ)試しませんでした。

@CamilStapsありがとう、他の同様の投稿を見つけましたが、試してみませんでした。とにかく、私はキリスト教のFeuersängerの投稿をキヤノンと見なします:)
アンドラスディーク

2

Mathematica、94バイト

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

結果

%[10000]

ここに画像の説明を入力してください


2

Python、263バイト

Pythonは初めてなので、改善の余地は確かにあります:)

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()

例:

f(100000)

ここに画像の説明を入力してください


あなたは短縮することができますs=[];X=[];Y=[];i=1;x=0;y=0s=X=Y=[];i=1;x=y=0;
rp.beltran

最後の余分なセミコロンは無視してください。8バイトの余裕が必要です。
rp.beltran

@ rp.beltran。これは動作しません。オブジェクトが同じ値を共有しているという事実に関係していると思います。のみ追加できましたx=y=0
ランブルスコアシド

私の悪い、あなたは正しい。Pythonがリストを参照渡しすることを忘れていました。数値は不変であるため、整数を使用しても安全です。
rp.beltran

1

R、137バイト

素数であっても組み込み関数のみを使用します。反復ではなくベクトル化されたアプローチを考えると、高速ですが、膨大な数を処理できません。

ゴルフ:

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])}

ゴルフをしていない:

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
}

例:

g(10000)

ここに画像の説明を入力してください


結果の例を追加できますか?
ルイスメンドー

@LuisMendo。確かに。プロットを追加する方法を理解するだけでした。
ランブルスコアシド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.