コードゴルフ:独自の水平ペットASCIIスネーク


29

この挑戦に非常に強く触発されたCode Golf:あなた自身のペットのASCIIスネーク -水平にすると複雑さが増すと思いました。

水平のヘビの例:

            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   

ルールは次のとおりです。

  1. 正確に5行の文字が印刷されます
  2. 各行は正確に30文字の長さで、スペースとヘビを描くために選択した文字の組み合わせで構成されます
  3. あなたの蛇は3行目から始まります
  4. スネークの描画に使用する次の行は、現在の行、1行上(まだ1行目でない場合)、または1行下(5行目でない場合)からランダムに選択する必要があります。
    • これらの選択肢は、等しく重み付けする必要があります。したがって、ライン1にいる場合は、ライン1にとどまる可能性が50%、ライン2に移動する可能性が50%あります。ライン2にある場合、ライン1に移動する可能性は33%です。ライン2にとどまる確率33%またはライン3に移動する確率33%
  5. あなたのヘビすべての行を訪れる必要ありません

5
PPCGへようこそ!これは良い最初の挑戦です。
ジュゼッペ

明確にするために、私たちが端にいる場合、均一に選択する必要がありますか(同じ行にとどまります)、(別の​​行に移動します)、または不均一な重みを持つことができますか?
ジュゼッペ

そして、端から離れて、私たちは均一に上/下/同じ線を選ぶ必要がありますか?
ジュゼッペ

2
うーん...少なくとも5行の制限は、人々が転置を追加して他の人から答えを盗むのを防ぎます。
魔法のタコ

9
モニターを物理的に90°回転させると、1バイトとしてカウントされますか?:D
エリックドゥミニル

回答:


11

JavaScript(ES6)、98バイト

@KevinCruijssenのおかげで7バイト節約

5つの文字列の配列を返します。

f=(y=2,a=[...'  0  '])=>a[0][29]?a:f(y+=(Math.random()*(y%4?3:2)|0)-!!y,a.map((v,i)=>v+=i-y&&' '))

オンラインでお試しください!

コメント済み

f = (                       // given:
  y = 2,                    //   y = current line (0-indexed)
  a = [...'  0  ']          //   a[] = array of 5 lines
) =>                        //
  a[0][29] ?                // if all columns have been processed:
    a                       //   stop recursion and return a[]
  :                         // else:
    f(                      //   do a recursive call with:
      y += (                //     the updated value of y, to which we add -1, 0 or 1:
        Math.random() *     //       pick a random value in [0,1)
        (y % 4 ?            //         if y is neither 0 or 4:
          3                 //             multiply it by 3
        :                   //           else:
          2                 //             multiply it by 2
        ) | 0               //       force an integer value
      ) - !!y,              //     subtract either 0 or 1
      a.map((v, i) =>       //     for each value v at position i in a[]:
        v += i - y && ' '   //       append either '0' if i = y or a space otherwise
      )                     //     end of map()
    )                       //   end of recursive call

ドロップしてd((y%4?3:2)|0)-(y>0)-6バイトに使用できます。オンラインでお試しください。
ケビンCruijssen

修正:-7バイト。1中には、new Random(...)もちろん、デフォルトで暗黙的です。.. オンラインそれを試してみてください。
ケビンCruijssen

@KevinCruijssenありがとう!(2バイト!!y(y>0)節約する代わりに。)
アーナルド

7

、28バイト

P|   F³⁰«0≡ⅉ²M‽²↑±²M‽²↓M⊖‽³↓

オンラインでお試しください!リンクは、コードの詳細バージョンです。説明:

P|   

いくつかのパディングを印刷して、5行の出力を強制します。

F³⁰«

30回繰り返します。

0

ゼロを印刷します(そして水平に移動します)。

≡ⅉ²M‽²↑

Y座標が2の場合、0または1だけランダムに移動します。

±²M‽²↓

-2の場合、0または1だけランダムに下に移動します。

M⊖‽³↓

それ以外の場合は、-1、0、または1ずつランダムに下に移動します。


6

Perl、68バイト

perl -E '$%=2;s:$:$n++%5-$%&&$":emg,$%-=!!$%+rand!($%%4)-3for($_=$/x4)x30;say'

これはまったく最適とは言えません。


5

ゼリー、24バイト

3µ’o1r‘«5¥$Xµ30СṬ€o⁶z⁶Y

オンラインでお試しください!

説明

3µ'o1r '«5¥$ Xµ30СṬ€o⁶z⁶Y|| Niladicフルプログラム。
                         ||
3 || 3から始まる...
 µ µ30 || ... 30回実行...
               |¡|| ...結果をリストに収集します。
  'o1r'«5¥$ X ||-| モナドの「ヘルパー」関数。
  'o1 ||-| 現在の整数、デクリメントされたOR 1。
     r X ||-| ^から...までの範囲からランダムなアイテムをつかみます
      '«5 ||-| ...増分され、5に制限されます(最大値を使用)。
         ¥$ ||-| 構文要素。リンクのグループ化に使用されます。
                 Ṭ€|| それぞれの真実。
                   o⁶|| 単一のスペースを持つ論理OR。
                     z⁶|| フィラースペースで転置します。
                       Y || 改行で参加します。


5

Python 3、144バイト

@ Ruts、@ Turksarama、および@mypetlionは、バイト数の削減に非常に役立ちました

import random
m=[list(' '*30)for y in range(5)]
l=2
for i in range(1,30):
 m[l][i]=0
 l+=random.randint(~-(l<1),l<4)
for j in m:
  print(*j)

これを改善しようとします。楽しいチャレンジ!


3
に変更l+=random.randint(-1,1) l=0 if l<0 else l l=4 if l>4 else ll+=random.randint(~-(l<1),l<4)て31バイトを保存します。
-mypetlion

1
多くのスペースと改行を削除できるはずです。
ミスターXcoder

1
に変更m=[[' 'for x in R(w)]for y in R(h)]m=[list(' '*w)for y in R(h)]て、7バイトを保存します。
-mypetlion

2
Pythonではboolean、のサブクラスint。だから、Falseの代わりに使用することができる0True置き換えることができます1~ビット単位のための単項演算子であるnot-オペレータが(乗算によって符号を反転-1)。その~-(False)ため-1~-(True)0に評価され、評価されます。
mypetlion

1
ループ内で最初の0を割り当て、割り当て後にlを設定します。これにより、1行(m[2][0]=0行方不明)とforループの2バイト(にfor i in R(1,30):なります)が節約されますfor i in R(30):。また、0を設定した後、lを再計​​算する必要があります。これにより、144バイトになります。
タークサラマ

4

R120 114バイト

m=matrix
r=m(" ",30,5)
x=3
for(i in 1:30){r[i,x]=0;x=x+sample(-1:1,1,,m(c(0,rep(1,13)),3)[,x])}
write(r,"",30,,"")

6バイトを追加してくれた@Giuseppeに感謝します!

次のように確率の表を使用します。

> matrix(c(0,rep(1,13)),3)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    1
[2,]    1    1    1    1    1
[3,]    1    1    1    1    0
Warning message:
In m(c(0, rep(1, 13)), 3) :
  data length [14] is not a sub-multiple or multiple of the number of rows [3]

ここで、各列はケースに対応します。つまり、ヘビが行1にある場合は列1が選択され、それぞれ0、1 / 2、および1/2が選択され、-1 [下降]、0 [静止]、1 [ go up](sample確率を自動的に1に正規化します)、行2の列2は確率1 / 3、1 / 3、1 / 3などを与えます...

オンラインでお試しください!



@ジュゼッペありがとう!そこ別名それをする理由は確かではなかった、と私は、余分な0のためのベクトルのリサイクルを使用することを忘れてしまった
plannapus

3

SOGL V0.1222の 21 バイト

3ā'∑∫⁵╗ž⁴H1ΧGI5χ⁴-ψ+;

ここで試してみてください!

説明:

3                      push 3
 ā                     push an empty array - the canvas
  '∑∫                  30 times do, pushing counter            | stack = 3, [], 1
     ⁵                   duplicate the Y coordinate            | stack = 3, [], 1, 3
      ╗ž                 at those coordinates insert "+"       | stack = 3, ["","","+"]
        ⁴                duplicate from below                  | stack = 3, ["","","+"], 3
         H               decrease                              | stack = 3, [...], 2
          1Χ             maximum of that and 1                 | stack = 3, [...], 2
            G            get the item 3rd from top             | stack = [...], 2, 3
             I           increase it                           | stack = [...], 2, 4
              5χ         minimum of that and 5                 | stack = [...], 2, 4
                ⁴-       subtract from the larger a copy of the smaller value | stack = [...], 2, 2
                  ψ      random number from 0 to pop inclusive | stack = [...], 2, 2
                   +     add those                             | stack = [...], 4
                    ;    and get the array back ontop          | stack = 4, ["","","+"]

                         implicitly output the top item - the array, joined on newlines






2

SmileBASIC、107 105 103 89バイト

FOR I=0TO 29FOR J=0TO 5LOCATE I,J?" 0"[Y+2==J]NEXT
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
NEXT

(リテラル)エッジケースがあるため、この回答は垂直回答よりも興味深いものです。

64バイト、印刷スペースなし:

FOR I=0TO 29LOCATE,Y+2?0;
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT

また、同じ長さの2行目のいくつかのバリエーションを見つけました。

Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
Y=Y+RND(3)-1D%=Y/3Y=Y-D%-D%*RND(2)NEXT
Y=Y+RND(3)-1Y=Y-Y DIV 3*(RND(2)+1)NEXT
Y=Y+RND(3)-1Y=Y/3OR.Y=Y-D-D*RND(2)NEXT

Y / 3の整数除算を使用して、Yが有効な範囲外にあるかどうかを確認し、符号を取得します。


2

Java 8、177 170バイト

v->{int a[][]=new int[5][30],c=0,r=2;for(;c<30;r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))a[r][c++]=1;String R="";for(int[]y:a){for(int x:y)R+=x<1?" ":"~";R+="\n";}return R;}

@OlivierGrégoireのおかげで-7バイト。

説明:

オンラインでお試しください。

v->{                // Method with empty unused parameter and String return-type
  int a[][]=new int[5][30],
                    //  Integer-matrix of size 5x30
      c=0,          //  Column, starting at index 0
      r=2;          //  Row, starting at index 2
  for(;c<30;        //  Loop `c` 30 times
      r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))
                    //    After every iteration: change `r` with -1,0,1 randomly
                    //     If `r` is 0: random [0;2)-0 → 0,1
                    //     If `r` is 4: random [0;2)-1 → -1,0
                    //     If `r` is 1,2,3: random [0:3)-1 → -1,0,1
    a[r][c++]=1;    //   Fill the cell at indices `r,c` from 0 to 1
  String R="";      //  Result-String, starting empty
  for(int[]y:a){    //  Loop over the rows of the matrix
    for(int x:y)    //   Inner loop over the individual column-cells of the matrix
      R+=x<1?       //    If the value of the cell is still 0:
          " "       //     Append a space
         :          //    Else (it's 1):
          "~";      //     Append the character
    R+="\n";}       //   After every row, Append a new-line
  return R;}        //  Return the result-String

1
r+=Math.random()*(r%4>0?3:2)-(r>0?1:0)数バイトを節約します。
オリビエグレゴワール

@OlivierGrégoire私はすでにそれをやったと思っていたが、明らかにそうではなかった。たぶん私は最近別の答えでそれをやったのかもしれません。
ケビンクルーッセン


1

Python 3、123バイト

from random import*
i,*a=2,
exec("a+=i,;i+=randint(-(i>0),i<4);"*30)
for x in range(5):print(''.join(' 0'[x==i]for i in a))

オンラインでお試しください!

整数の配列を生成し、それを各行に変換します。

Python 2、120バイト

from random import*
i=2;a=[]
exec"a+=i,;i+=randint(-(i>0),i<4);"*30
for x in range(5):print''.join(' 0'[x==i]for i in a)

オンラインでお試しください!

PY2のために、のための冗長括弧execとはprint取り外すことができますが、2行目で構文が無効です。

RodよるPy2提出linemadeによるPy3提出の両方をアウトゴルフします。


1

ルビー98 77バイト

->{a=(0..4).map{" "*30}
x=2
30.times{|i|a[x][i]=?@
x+=rand(3-17[x])-30[x]}
a}

オンラインでお試しください!

文字列の配列を返すラムダ。

私の最初の衝動は、列を生成して転置することでしたが、そのステップを避ける方がはるかに簡単です。

私はで初期化するのが好きでしたa[" "*30]*5、それは文字列の浅いコピーを作成し、非常に太くてスリザリのない蛇になります。

D(同じバイト数の)インクリメントのような定数を使用することもできましたが、Rubyが割り当てるたびに文句を言うでしょう。私はi、無視するデバッグ警告の束を持つよりも、ミッドループを再利用することで読みやすさを減らすことを好むことにしました。

また、でいくつかのバイトを節約したいと思っていましたがloop{x+=rand(3)-1;(0..4)===x&&break}、それはエッジにバイアスを引き起こしていました:内側に戻る1/3のチャンス、とどまる1/3のチャンス、境界の外に出る1/3のチャンスやがてランダムウォークバック(つまり、「滞在」)するしばらく前。

-20バイト: Rubyを使用Integer#[]して小さな条件を作成し、5つの位置すべてに対して正しい移動の重み付けを保証します。これにより、ループブレークパターン(ゼロ以外の確率で停止できない)が置き換えられ、大幅に節約されます。ありがとう、エリック・ダミニル

-1バイト:初期化a(0..4).mapはなく、5.times再度のおかげエリックDuminil

->{
  a = (0..4).map{ " " * 30 }      # a is the return array: 5 strings of 30 spaces
  x = 2                           # x is the snake position
  30.times{ |i|                   # For i from 0 to 29
    a[x][i] = ?@                  #   The ith position of the xth row is modified
    x += rand(3 - 17[x]) - 30[x]  #   Using bit logic, add rand(2 or 3) - (0 or 1)
  }
  a                               # Return the array of strings
}

いいスタートです。インナーは不要ですlooprand(2+14[x])-30[x]またはで増分を計算できますrand -(30[x])..15[x]。おそらくより短いバージョンがあります。それでも、-20バイトは悪くありません!オンラインでお試しください!
エリックドゥミニル

で1バイト少ないx,a=2,(0..4).map{" "*30}オンラインでお試しください!
エリックドゥミニル

1
うわー、30[x]素晴らしいトリックです!ありがとう!
benj2240

1

Perl 6、85バイト

.join.say for [Z] ((' ',' ',0,' ',' '),{.rotate(set(0,+?.[0],-?.[4]).pick)}...*)[^30]

オンラインでお試しください!

長い括弧で囲まれた式は(' ', ' ', 0, ' ', ' ')、出力の最初の垂直ストリップである初期要素から生成された遅延シーケンスです。連続する各ストリップ/リストは、(最初の要素がゼロでない場合)、および(5番目の要素がゼロでない場合)rotateを含むセットからランダムに選択されたメソッドを呼び出すことにより、前のストリップ/リストから生成されます。01-1

水平ストリップのマトリックスは[Z]演算子で転置され、垂直ストリップのリストにjoin変換されsayます。各ストリップは単一の文字列に変換され、で出力されます。


1

Scala、207バイト

val b=Array.fill(150)('.')
def s(y:Int,x:Int)={val r=Random.nextInt(6)
val z=y+(if(y>3)-r%2
else if(y<1)r%2
else r/2-1)
b(z*30+x)='$'
z}
(3/:(0 to 28))(s(_,_))
b.mkString("").sliding(30,30).foreach(println)

サンプル:

...................$$$...$.$$.
.$$$..............$...$.$.$...
$...$$$..$...$$.$$.....$......
.......$$.$.$..$..............
...........$..................

デゴルフ:

val buf = List.fill(150)('.').toBuffer
def setRowCol (y:Int, x:Int): Int = {
  val r = Random.nextInt(6)
  val z = y + (
    if (y>3) 
        -(r%2)
    else if (y<1) 
        (r%2)
    else 
        r/2-1
  )
  buf (z * 30 + x) = '$'
  z
}
(3 /: (0 to 28)(setRowCol (_, _))
println 
buf.mkString ("").sliding(30,30).foreach(println)

私のユニークな発明-さて、これまで他の解決策を読んでいませんが、暗黙的に2つのRandom(2 * 3)であるRandom(6)を生成することです。境界から離れている場合は、r / 2(0,1,2)と→(-1,0,1)の値を使用して、上下に移動します。境界にいる場合、別のランダムの高価な呼び出しを避けることができ、モジュロ(2)を取るだけで、私は滞在するべきか行くべきかを決定できます。

他のソリューションを見てみましょう。:)


はい、間違ったサンプル画像。します。:)
ユーザー不明

スカラ岩!ああ..コードゴルフ..間違ったユースケースが表示されjavaます。
javadba

@javadba:try itリンクをクリックしましたか?Kevin Cruijssenには、このコードをコンパイルしたりJShellで実行したりするために必要なボイラープレートは含まれていませんでしたが、ガイドラインに従っていると思います-メタディスカッションがあるかもしれません。必要に応じて、2次元配列も使用して、このコードを減らすことができます。2番目のアイデアは、最終的にスライドコードを減らすことです。printlnはKevinによって隠されています。-はい、アレイは8で改善を与える
ユーザー不明

scalaに戻り型intを推測させます:さらに4文字を保存します。
ユーザー不明

だから、今はJavaの球場に
入る-javadba

1

Perl、83 101バイト

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l-=1-int 3*rand;$l=~y/60/51/}1..30;say for@s'

新規:国境での確率問題なし:

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l=int($l<2?1+2*rand:$l>4?6-2*rand:$l-1+3*rand)}1..30;say for@s'

ゴルフをしていない:

$l=3;                             #start line
map{
  map $s[$_-1].=/$l/?0:" ",1..5;  #0 at current char and line, space elsewhere
  $l-=1-int 3*rand;               #up, down or stay
  $l=int( $l<2 ? 1+2*rand
        : $l>4 ? 6-2*rand
        :        $l-1+3*rand )    #border patrol
}
1..30;                            #position
say for@s                         #output result strings/lines in @s

2
あなたの国境パトロールは、エッジにとどまるための50%の正しい確率を与えません。
トンホスペル

0

PowerShell、133バイト

$a=(,' '*30),(,' '*30),(,' '*30),(,' '*30),(,' '*30);$l=2;0..29|%{$a[$l][$_]=0;$l+=0,(1,($x=1,-1),$x,$x,-1)[$l]|Random};$a|%{-join$_}

オンラインでお試しください!

幅30スペース、高さ5行の2D配列を作成します。(注-誰かがこの配列を初期化するためのより効果的な方法を思いつくことができれば、私は永遠に3未満になります。)ヘルパー変数$lを設定します2(これは前のスネークセグメントがあった行に使用されます)。次にから0にループし29ます。

反復ごとに、snake要素をに設定します0。次に、複雑な配列にインデックスを付けて、Get-Random上下するか、そのままにするかを選択します。それはに再び追加されました$l

最後に、の5つの要素$a-joinその内部要素をループして、それぞれ1つの文字列にします。これらの5つの文字列はパイプラインに残されており、暗黙のうちにWrite-Output改行が無料で提供されます。


0

Clojure、123バイト

ここに括弧があります:

(let[l(take 30(iterate #(max(min(+(-(rand-int 3)1)%)4)0)3))](doseq[y(range 5)](doseq[x l](print(if(= y x)0" ")))(println)))

ゴルフされていないバージョン:

(let [l (take
       30
       (iterate
        #(max
          (min
           (+ (- (rand-int 3) 1) %)
           4)
          0)
        3))]
(doseq [y (range 5)]
  (doseq [x l]
    (print (if (= y x) 0 " ")))
  (println)))

ヘビの体の異なる高さのリストを作成し、0から4まで繰り返します。高さが現在の行に一致する場合は常に0を出力し、そうでない場合は空白を出力します。高さが境界を超えないようにすると、実際にバイトがかかります。また、新しい行が正しい順序にある​​ことを認識することは、本来よりもバイト集約的です。1つを簡単に記述してdoseq、xとyのデカルト積を作成できますが、新しい行をいつ印刷するかはわかりません。


0

Python3 + numpy、 137 132バイト

最短のpython提出でも、最長でも、間違いなく最速でもありません。

from pylab import*
j=r_[2,:29]
while any(abs(diff(j))>1):j[1:]=randint(0,5,29)
for i in r_[:5]:print(''.join(' #'[c] for c in j==i))

updatenumpyのdiffコマンドを使用すると、スネークが有効なパターンであるかどうかをテストするために5バイトを節約できましたj[1:]-j[:-1]



0

R、95バイト

x=3;l=1:5
write(t(replicate(30,{y=ifelse(x-l,' ',0);x<<-sample(l[abs(x-l)<2],1);y})),'',30,,'')

次の行xは常に、現在の行(l[abs(x-l)<2])から1を超えない行から選択されます。サイクルのreplicate代わりに使用すると、forマトリックスの初期化と操作に必要ないくつかのバイトが節約さ<<-れ、グローバル変数に割り当てるときに演算子を使用する必要がありますx

オンラインでお試しください!


0

05AB1E、25バイト

Y30F©ð5×0®ǝs<DÌŸ4ÝÃΩ}\)ζ»

オンラインでお試しください!

説明

Y                           # push the initial value 2
 30F                        # 30 times do
    ©                       # store a copy of the current value in register
     ð5×                    # push 5 spaces: "     "
        0®ǝ                 # insert 0 at the position of the current value
           s<DÌŸ            # push the range [current-1 ... current-1+2]
                4ÝÃ         # keep only numbers in [0 ... 4]
                    Ω       # pick one at random
                     }\     # end loop and discard the final value
                       )ζ   # transpose the list
                         »  # join by newlines
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.