アスキーアートオブザデイ#2-フロースネーク


32

A もGosper曲線として知られているフロースネークは、単純なプロセスの各注文/反復してサイズが指数関数的に増殖する、フラクタル曲線です。以下は、建設の詳細とさまざまな注文のいくつかの例です。

Order 1 Flow Snake

____
\__ \
__/

注文2フロースネーク

      ____
 ____ \__ \
 \__ \__/ / __
 __/ ____ \ \ \
/ __ \__ \ \/
\ \ \__/ / __
 \/ ____ \/ /
    \__ \__/
    __/

Order 3 Flow Snake

                 ____
            ____ \__ \
            \__ \__/ / __
            __/ ____ \ \ \    ____
           / __ \__ \ \/ / __ \__ \
      ____ \ \ \__/ / __ \/ / __/ / __
 ____ \__ \ \/ ____ \/ / __/ / __ \ \ \
 \__ \__/ / __ \__ \__/ / __ \ \ \ \/
 __/ ____ \ \ \__/ ____ \ \ \ \/ / __
/ __ \__ \ \/ ____ \__ \ \/ / __ \/ /
\ \ \__/ / __ \__ \__/ / __ \ \ \__/
 \/ ____ \/ / __/ ____ \ \ \ \/ ____
    \__ \__/ / __ \__ \ \/ / __ \__ \
    __/ ____ \ \ \__/ / __ \/ / __/ / __
   / __ \__ \ \/ ____ \/ / __/ / __ \/ /
   \/ / __/ / __ \__ \__/ / __ \/ / __/
   __/ / __ \ \ \__/ ____ \ \ \__/ / __
  / __ \ \ \ \/ ____ \__ \ \/ ____ \/ /
  \ \ \ \/ / __ \__ \__/ / __ \__ \__/
   \/ / __ \/ / __/ ____ \ \ \__/
      \ \ \__/ / __ \__ \ \/
       \/      \ \ \__/ / __
                \/ ____ \/ /
                   \__ \__/
                   __/

建設

7個のエッジと8個の頂点を含むパスで構成される順序1 Flow Snakeを考えてみましょう(以下にラベルを付けます。実行可能性のために拡大します)。

4____5____6
 \         \
 3\____2   7\
       /
0____1/

次に、次の注文ごとに、エッジをこの元の注文1パターンの回転バージョンに置き換えるだけです。次の3つのルールを使用して、エッジを置き換えます。

1水平エッジの場合、元の形状にそのまま置き換えます。

________
\       \
 \____   \
     /
____/

2について/(エッジ12上記構成で)、次の回転バージョンに置き換えます。

 /
/   ____
\  /   /
 \/   /
     /
____/

3について\エッジ(34及び67上記)、次の回転バージョンに置き換えます。

 /
/   ____ 
\   \   \
 \   \   \
  \  /
   \/

したがって、たとえば、順序1の頂点がラベル付けされた順序2は次のようになります。

            ________
            \       \
  ________   \____   \6
  \       \      /   /
   \____   \5___/   /   ____
       /            \   \   \
  4___/   ________   \   \   \7
 /        \       \   \  /
/   ____   \____   \2  \/
\   \   \      /   /
 \   \   \3___/   /   ____
  \  /            \  /   /
   \/   ________   \/   /
        \       \      /
         \____   \1___/
             /
        0___/

ここで、高次の場合は、現在のレベルを長さ/1、1 \または2のエッジに分割し_、プロセスを繰り返します。置き換えた後でも、連続する2つのエッジ間の共通の頂点は一致していることに注意してください。

チャレンジ

  • NSTDIN / ARGV / function引数または最も近い同等物を介して単一の整数を受け取り、NSTDOUTにFlow Snake の順序を出力する完全なプログラムの関数を作成する必要があります。
  • 入力整数は常により大きいです0
  • パターンの一部ではない先頭スペースはありません。
  • 末尾のスペースがないか、パターンを埋めて最小の境界矩形を完全に埋めるのに十分な末尾のスペースがありません。
  • 末尾の改行はオプションです。

おもしろ情報

  • Flow SnakesはSnow Flakesの言葉遊びであり、このパターンは注文2以上に似ています
  • パターンは全体に流れる単一のパスで構成されるため、フローとスネークは実際にパターンの一部を果たします。
  • 慎重に気付くと、次数2(およびそれ以上)のパターンは、現在のエッジと前のエッジの共通の頂点を中心に回転した次数1のパターンで構成されます。
  • Flow Snakesの非ASCIIバリアントは、ここと他のいくつかの場所にあります。

これはので、バイト単位の最短コードが勝ちです!


リーダーボード

シリーズの最初の投稿はリーダーボードを生成します。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、すべての回答を見出しで開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

# Ruby, <s>104</s> <s>101</s> 96 bytes

正しく理解すれば、形状1、2、3は2倍に拡大されるため、2の下の行は3ではなく4つの下線で構成する必要があります。
edc6515年

@ edc65例の形状は完全なサイズです。建設部分については、はい、それは拡大されており、3つのアンダースコアがあるので、エッジ番号は4位になります
オプティマイザー

ただし、形状2にはエッジ番号はありません(構成部分にはあります)。形状2の下部は形状1の下部と等しくなければなりません。
edc6515年

@ edc65ああ、そこに!! 一定!
オプティマイザー

3
タイトルを「Snow Flakes」と読みましたが、違いに注意を向けるまで実際のタイトルに気付くことすらありませんでした。
mbomb007

回答:


4

CJam、144バイト

0_]0a{{_[0X3Y0_5]f+W@#%~}%}ri*{_[YXW0WW]3/If=WI6%2>#f*.+}fI]2ew{$_0=\1f=~-
"__1a /L \2,"S/=(@\+\~.+}%_2f<_:.e>\:.e<:M.-:)~S*a*\{M.-~3$3$=\tt}/zN*

スクロールを避けるために改行が追加されました。オンラインで試す

プログラムはいくつかのステップで機能します:

  1. 初期フラクタル(1次)は、移動方向を表す7つの角度(概念的には60°の倍数)のシーケンスとしてエンコードされます。
  2. フラクタルは、水平セグメント(0次フラクタル)にN回「適用」され、N次フラクタルのすべての「動き」が生成されます。
  3. [0 0]から開始し、動きは[xy]座標を持つ一連のポイントに変換されます。
  4. 各セグメント(ポイントのペア)は1または2 [xyc]トリプレットに変換され、座標x、yの文字cを表します
  5. 境界矩形が決定され、座標が調整され、スペースのマトリックスが生成されます
  6. 各トリプレットについて、文字cはマトリックスの位置x、yに配置され、最終マトリックスは出力用に調整されます。

この答えは、バイトエンコーディングの恩恵を受けるのに十分な長さです:goo.gl/D1tMoc-
デニス

@デニスゴルフをやったかどうかわかりません...そしてなぜあなたはそれをブロックに入れたのですか?
-aditsu

よくわからない...あなたの答えはとても印象的です。私はこれを正しくしようとして丸一日を過ごしました。
デニス

@デニスありがとう。ところで、印刷できない文字や制御文字を使用しても大丈夫だと思いますか?私は通常それらを避けようとします
aditsu

バイト数を増やすことなくそれらを回避できる場合は、そうします。しかし、短いほど短くなります。:P文字列や配列ではなくコード自体を圧縮するこのような場合、通常は両方のバージョンを回答に含めます。
デニス

16

Python 2、428 411 388バイト

これはかなりトリッキーでした。パターンは、各ステップの後に比率を保持しません。つまり、その前身から手順的にイメージを生成することは非常に困難です。このコードが行うことは、いくつかの激しい数学のゴルフの後はかなり読みにくいですが、実際には再帰的に定義されたD関数を使用して、最初から最後まで線を引きます。

サイズも問題でした5*3**n。サイズを計算するより良い方法を考えることができるなら、それを変更するかもしれませんが、私は、角張った正方形の真ん中で始めて、その後、物を切り取りました。

n=input();s=5*3**n
r=[s*[" "]for i in[0]*s]
def D(n,x,y,t=0):
 if n<1:
    x-=t%2<1;y+=t%3>1;r[y][x]='_/\\'[t/2]
    if t<2:r[y][x+2*t-1]='_'
    return[-1,2,0,1,0,1][t]+x,y-(2<t<5)
 for c in[int(i)^t%2for i in"424050035512124224003"[t/2::3]][::(t^1)-t]:x,y=D(n-1,x,y,c)
 return x,y
D(n,s/2,s/2)
S=[''.join(c).rstrip()for c in r]
for l in[c[min(c.find('\\')%s for c in S):]for c in S if c]:print l

うわー、これは素晴らしいです。AAoD#1でショットをしたいですか?
オプティマイザー

r=[s*[" "]for i in range(s)]-> r=[[" "]*s]*s]数バイト削る
サーパーシバル

1
残念ながら@sirpercival は、可変オブジェクトを繰り返す方法の*ために機能しません。
-grc

ああ、そう、忘れてしまった
サーパーシバル

インライン化lprint'\n'.join()forループ内での印刷への切り替え、の使用return[...][t]+x,、からの括弧の削除により、いくつかのバイトを節約できます(t%2)。また、min(c.find('\\')%s for c in S)リストの名前を変更してS、の初期値を上書きしないようにする場合にも使用できますs
-grc

12

JavaScriptの(ES6)、356 362 370

それは難しいものです...

各形状はパスとして保存されます。6つの基本的なビルディングブロックがあります(3 + 3後方)

  • 0左上から右下への斜め(4後方)
  • 1対角線左下から右上(5後方)
  • 2水平左から右(6後方)

それぞれについて、順序を増やすときに適用される置換手順があります。

  • 0-> 0645001(後方4-> 5441024
  • 1-> 2116501(後方5-> 5412556
  • 2-> 2160224(後方6-> 0664256

h要素4..6が0..2から取得できる場合でも、配列に事前入力された値

;[...h[n]].reverse().map(x=>x^4).join('')

指定された順序の形状を取得するために、置換が繰り返し適用されるp変数にパスが構築されます。次に、メインループはp変数を反復処理し、各要素が行であるg []配列内に形状を描画します。
位置(0,0)から開始して、各インデックスは負になる場合があります(高次でyインデックス)。負のy値を見つけるたびに、負のyインデックスがすべてのg配列をシフトするのを避けます。JSネガティブインデックスでは許可されているため、xインデックスがネガティブになるかどうかは気にしませんが、管理が少し難しくなります。
最後の手順では、.mapを使用してメイン配列をスキャンしますが、行ごとに、b到達した最小xインデックスを保持する変数(<0)を使用して明示的なfor(;;)ループを使用する必要があります。
の中にconsole.log バージョンには、便利な先頭の改行があり、スニペットバージョンのように、2行をスワップする末尾の改行を簡単に作成できます。

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    o+='\n';
    for(x=b;x<r.length;)o+=r[x++]||' '
  },o='');
  console.log(o)
}

テストに便利なスニペット(Firefoxの場合):

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    for(x=b;x<r.length;)o+=r[x++]||' ';
    o+='\n'
  },o='');
  return o
}

// TEST

fs=9;
O.style.fontSize=fs+'px'

function zoom(d) { 
  d += fs;
  if (d > 1 && d < 40)
    fs=d, O.style.fontSize=d+'px'
}
#O {
  font-size: 9px;
  line-height: 1em;
}
<input id=I value=3><button onclick='O.innerHTML=f(I.value)'>-></button>
<button onclick="zoom(2)">Zoom +</button><button onclick="zoom(-2)">Zoom -</button>
<br>
<pre id=O></pre>


6

Haskell、265バイト

(?)=div
(%)=mod
t[a,b]=[3*a+b,2*b-a]
_#[0,0]=0
0#_=3
n#p=[352,6497,2466,-1]!!((n-1)#t[(s+3)?7|s<-p])?(4^p!!0%7)%4
0&_=0
n&p=(n-1)&t p+maximum(abs<$>sum p:p)
n!b=n&[1,-b]
f n=putStr$unlines[["__ \\/   "!!(2*n#t[a?2,-b]+a%2)|a<-[b-n!2+1..b+n!2+0^n?3]]|b<-[-n!0..n!0]]

(注:7.10の前にGHCに、あなたが追加する必要がありますimport Control.Applicativeか、交換abs<$>してmap abs$。)

Ideone.comでオンラインで実行

f n :: Int -> IO ()レベルnflowsnakeを描画します。描画は、曲線に沿ってではなくビットマップの順序で計算されます。これにより、アルゴリズムをO(n)空間で実行できます(つまり、描画サイズの対数)。私のバイトのほぼ半分が、どの長方形を描くかを計算するのに費やされています!


私はログインしましたが、今は動作します!いいね!
オプティマイザー

64ビットのIntを想定していたため、これは以前Ideone.comで実行されていませんでした。修正されました(2バイトを犠牲にします)。
アンデルスカセオルグ

...のみ確認のための私の電子メールIDを必要とするログインものとしてその大丈夫
オプティマイザ

5

Perl、334 316 309

$_=2;eval's/./(map{($_,"\1"x7^reverse)}2003140,2034225,4351440)[$&]/ge;'x($s=<>);
s/2|3/$&$&/g;$x=$y=3**$s-1;s!.!'$r{'.qw($y--,$x++ ++$y,--$x $y,$x++ $y,--$x
$y--,--$x ++$y,$x++)[$&]."}=$&+1"!eeg;y!1-6!//__\\!,s/^$x//,s/ *$/
/,print for
grep{/^ */;$x&=$&;$'}map{/^/;$x=join'',map$r{$',$_}||$",@f}@f=0..3**$s*2

標準入力で取得されるパラメーター。私をテストしてください


5

ハスケル、469の 419 390 385 365バイト

関数f :: Int-> IO()は入力として整数を取り、フロースネークを出力します

e 0=[0,0];e 5=[5,5];e x=[x]
f n=putStr.t$e=<<g n[0]
k=map$(53-).fromEnum
g 0=id
g n=g(n-1).(=<<)(k.(words"5402553 5440124 1334253 2031224 1345110 2003510"!!))
x=s$k"444666555666"
y=s$k"564645554545"
r l=[minimum l..maximum l]
s _[]=[];s w(x:y)=w!!(x+6):map(+w!!x)(s w y)
t w=unlines[["_/\\\\/_ "!!(last$6:[z|(c,d,z)<-zip3(x w)(y w)w,c==i&&d==j])|i<-r.x$w]|j<-r.y$w]

これにより、2倍の拡大図が生成されます。質問は上部の小さい数字を求めていると思います。2倍に拡大した数字だけを使用して、flowsnakeの構築方法を説明しています。
アンデルスカセオルグ

あなたが正しいです。私はそれを修正しました
ダミアン

あなたは使用することができます$の定義でk、そして置き換える(!!)a(a!!)、いくつかの括弧から取り除くことができました。それ以外に、あなたは自分で多くのトリックを知っているようです。ニース
誇り高いハスケラー

4

C、479 474 468 427バイト

PerlやHaskellを倒すことはないと思いますが、ここにはまだCのサブミットがありません。

#define C char
C *q="053400121154012150223433102343124450553245";X,Y,K,L,M,N,i,c,x,y,o;F(C*p,
int l,C d){if(d){l*=7;C s[l];for(i=0;i<l;i++)s[i]=q[(p[i/7]%8)*7+i%7];return F
(s,l,d-1);}x=0;y=0;o=32;while(l--){c=*p++%8;for(i=!(c%3)+1;i--;) {K=x<K?x:K;L=
y<L?y:L;M=x>M?x:M;N=y>N?y:N;y+=c&&c<3;x-=c%5>1;if(x==X&y==Y)o="_\\/"[c%3];y-=c
>3;x+=c%5<2;}}return X<M?o:10;}main(l){F(q,7,l);for(Y=L;Y<N;Y++)for(X=K;X<=M;X
++)putchar(F(q,7,l));}

atoi()呼び出しのスペースを節約するために、プログラムに渡される引数のがレベルに使用されます。

プログラムはO(n ^ 3)以下で実行されます。最初にパスが1回計算されて最小/最大座標が検出され、次に各(x、y)ペアに対して1回計算されてその特定の場所の文字が検出されます。ひどく遅いが、メモリ管理を節約します。

http://codepad.org/ZGc648Xiでの実行例


使用X,Y,K,L,M,N,i,j,c;の代わりint X,Y,K,L,M,N,i,j,c;main(l)代わりにvoid main(int l)
Spikatrix

ええ、ありがとう、私はすでにそれらを剃り、もう少し、新しいバージョンを作成します。
-Zevv

最新バージョンの出力はトリミングされ、両端が少しオフになっているようです。
オプティマイザー

間違ったブロブをアップロードしました。これは問題ないはずです。
Zevv

4

Python 2、523 502 475 473 467 450 437バイト

l=[0]
for _ in l*input():l=sum([map(int,'004545112323312312531204045045050445212331'[t::6])for t in l],[])
p=[]
x=y=q=w=Q=W=0
for t in l:T=t|4==5;c=t in{2,4};C=t<3;q=min(q,x);Q=max(Q,x+C);w=min(w,y);W=max(W,y);a=C*2-1;a*=2-(t%3!=0);b=(1-T&c,-1)[T&1-c];x+=(a,0)[C];y+=(0,b)[c];p+=[(x,y)];x+=(0,a)[C];y+=(b,0)[c]
s=[[' ']*(Q-q)for _ in[0]*(W-w+1)]
for t,(x,y)in zip(l,p):x-=q;s[y-w][x:x+1+(t%3<1)]='_/\_'[t%3::3]
for S in s:print''.join(S)

Pffft、3時間ほどかかりましたが、楽しかったです!

アイデアは、タスクを複数のステップに分割することです:

  1. すべてのエッジ(0〜5としてエンコード)を出現順に計算します(そのため、蛇の最初から最後まで)。
  2. 各エッジの位置を計算します(そしてxとyの最小値と最大値を保存します)
  3. 構成する文字列を作成します(そして、負のインデックスを取得しないように、最小値を使用してオフセットします)
  4. 文字列を印刷する

以下に、コード化されていない形式のコードを示します。

# The input
n = int(input())

# The idea:
# Use a series of types (_, /, \, %), and positions (x, y)
# Forwards:   0: __  1: /  2: \
# Backwards:  3: __  4: /  5: \

# The parts
pieces = [
    "0135002",
    "0113451",
    "4221502",
    "5332043",
    "4210443",
    "5324551"
]
# The final types list
types = [0]
for _ in range(n):
    old = types
    types = []
    for t in old:
        types.extend(map(int,pieces[t]))

# Calculate the list of positions (and store the mins and max')
pos = []
top = False
x = 0
y = 0
minX = 0
minY = 0
maxX = 0
maxY = 0
for t in types:
    # Calculate dx
    dx = 1 if t < 3 else -1
    if t%3==0:
        dx *= 2         # If it's an underscore, double the horizontal size
    # Calculate dy
    top = t in {1, 5}
    dy = 0
    if top and t in {0, 3, 1, 5}:
        dy = -1
    if not top and t in {2, 4}:
        dy = 1
    # If backwards, add dx before adding the position to the list
    if t>2:
        x += dx
    # If top to bottom, add dy before adding the position to the list
    if t in {2,4}:
        y += dy
    # Add the current position to the list
    pos += [(x, y)]
    # In the normal cases (going forward and up) modify the x and y after changing the position
    if t<3:
        x += dx
    if t not in {2, 4}:
        y += dy
    # Store the max and min vars
    minX = min(minX, x)
    maxX = max(maxX, x + (t<3)) # For forward chars, add one to the length (we never end with __'s)
    minY = min(minY, y)
    maxY = max(maxY, y)

# Create the string (a grid of charachters)
s = [[' '] * (maxX - minX) for _ in range(maxY - minY + 1)]
for k, (x, y) in enumerate(pos):
    x -= minX
    y -= minY
    t = types[k]
    char = '/'
    if t % 3 == 0:
        char = '__'
    if t % 3 == 2:
        char = '\\'
    s[y][x : x + len(char)] = char

# Print the string
for printString in s:
    print("".join(printString))

編集:言語をPython 2に変更して、#3の答えと互換性があります(さらに6バイト節約します)


良くやった; あなたが作ることができる1点の単純な改善が変更されるだろうl.extend(x)l+=x。また、おそらく使用する代わりにcodegolf.stackexchange.com/questions/54 / ....split()を使用できます(回答で同様のことを行いました)
-KSab

@KSabありがとう、私は今使用するために本当に愚かだと思うextend
マティ

0

パリ/ GP、395

X、Yの文字位置をループし、印刷する文字を計算します。最小限に抑えるための適度な試行。空白とコメントを削除してスコアを付けます。

k=3;
{
  S = quadgen(-12);  \\ sqrt(-3)
  w = (1 + S)/2;     \\ sixth root of unity
  b = 2 + w;         \\ base

  \\ base b low digit position under 2*Re+4*Im mod 7 index
  P = [0, w^2, 1, w, w^4, w^3, w^5];
  \\ rotation state table
  T = 7*[0,0,1,0,0,1,2, 1,2,1,0,1,1,2, 2,2,2,0,0,1,2];
  C = ["_","_",  " ","\\",  "/"," "];

  \\ extents
  X = 2*sum(i=0,k-1, vecmax(real(b^i*P)));
  Y = 2*sum(i=0,k-1, vecmax(imag(b^i*P)));

  for(y = -Y, Y,
     for(x = -X+!!k, X+(k<3),  \\ adjusted when endpoint is X limit
        z = (x- (o = (x+y)%2) - y*S)/2;
        v = vector(k,i,
                   z = (z - P[ d = (2*real(z) + 4*imag(z)) % 7 + 1 ])/b;
                   d);
        print1( C[if(z,3,
                     r = 0;
                     forstep(i=#v,1, -1, r = T[r+v[i]];);
                     r%5 + o + 1)]) );  \\ r=0,7,14 mod 5 is 0,2,4
     print())
}

各charは、六角形セルの最初または2番目のセルです。セルの位置は、0、1、w ^ 2、...、w ^ 5の数字で底b = 2 + wに分割された複素数zです。ここで、w = e ^(2pi / 6)の6番目の単位根。これらの数字は、1〜7を区別するために保持され、ネットローテーションの状態テーブルを介して高から低になります。これは、Ed Shoutenによるflowsnakeコードのスタイルです(xytoi)ただし、パスに沿って数字を「N」インデックスに変換するのではなく、ネットローテーションのみ。範囲は、形状の中心にある原点0を基準にしています。制限がエンドポイントでない限り、これらは2文字の六角形の真ん中にあり、必要な文字は1つだけです。ただし、ヘビの開始および/または終了がX制限の場合、2文字が必要です。これは、k = 0開始およびk <3終了です。Pariにはsqrt(-3)組み込みのような「クワッド」がありますが、実数部と虚数部を別々に使用して同じことができます。


1
これは、先頭および末尾の空白に関する規則を完全に満たしていません。
アンデルスカセオルグ

おかげで、私は修正しました。あなたのhaskellが私を1時間倒し、X、Yループでそれをやった。さらにインスピレーションが来るかどうかを確認する前に投稿する必要があります:-)。
ケビンライド

今、ヘビの端はk = 0、1、2で切り取られます(数学はそのように刺激的です-私もそれを処理しなければなりませんでした。)
Anders Kaseorg

エンドポイントが最大のxであるとき、ああ。うーん
ケビンライド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.