Code Golf:您自己的水平宠物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行)或从下方一行(如果您尚未位于第5行)。
    • 这些选择必须同等权重。因此,如果您在1号线,则有50%的机会留在1号线,而50%的机会移至2号线。如果在2号线,则有33%的机会移至1号线,留在2号线的机会为33%或移至3号线的机会为33%
  5. 你的蛇并不需要访问每一行。

5
欢迎来到PPCG!这是一个很好的第一个挑战。
朱塞佩

为了澄清起见,如果我们处于优势地位,我们是否必须统一选择(停留在同一条线上)和(转到另一条线),或者我们的权重不一致?
朱塞佩

而且在边缘,我们是否必须统一拾取/向下/同一条线?
朱塞佩

2
嗯...至少有5行限制,使人们无法从附加了移调的另一人那里窃取答案。
魔术章鱼缸

9
将监视器实际旋转90°是否算作一个字节?:D
埃里克·杜米尼尔

Answers:


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个字节。在线尝试。
凯文·克鲁伊森

校正:-7个字节。该1new Random(...)是当然的默认隐.. 在线试玩。
凯文·克鲁伊森

@KevinCruijssen谢谢!(!!y而不是再(y>0)保存2个字节。)
Arnauld

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ð¡oozzY || Niladic完整程序。
                         ||
3 || 从3开始...
 µ µ30 || ...执行30次...
               С|| ...并将结果收集在列表中。
  'o1r'«5¥$ X ||-| Monadic的“助手”功能。
  'o1 ||-| 当前整数,减1。
     r X ||-| 抓取从^到...之间的随机项目
      '«5 ||-| ...该数字增加,上限为5(最多使用)。
         ¥$ ||-| 语法元素。用于对链接进行分组。
                 |€|| 解开每个。
                   o⁶|| 逻辑或(含单个空格)。
                     z⁶|| 用填充空间转置。
                       Y || 通过换行加入。

5

R,138字节

m=matrix(" ",30,5)
m[1,3]=0
x=3
s=sample
for(i in 2:30)m[i,x<-x+(-1)^(x==5)*s(0:1,1)*x%in%c(1,5)+(s(3,1)-2)*x%in%2:4]=0
write(m,"",30,,"")

在线尝试!

被Plannapus轻易超越


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先生18年

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。这样可以为您节省一整行(m[2][0]=0走了)和for循环上的2个字节(for i in R(1,30):变为for i in R(30):)。设置为0后,您还需要重新计算l。这将使您达到144个字节。
Turksarama

4

[R 120个 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,,"")

感谢@Giuseppe额外的6个字节!

使用如下的概率表:

> 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 [上升](sample将概率自动归一化为1),第2行的第2列给出了概率1 / 3、1 / 3和1/3,依此类推...

在线尝试!



@Giuseppe谢谢!确实没有理由对其进行别名,我忘了使用矢量回收来获得额外的
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

Python 2,127个字节

from random import*
s=['']*5
n=3
r=range(5)
exec"for i in r:s[i]+=' 0'[i==n]\nn=choice(r[n and~-n:n+2])\n"*30
print'\n'.join(s)

在线尝试!


2

带统计数据包的八度,99字节

它也可以在MATLAB中使用Statistics Toolbox。

p=3;for k=1:29
p=[p;p(k)+fix(randsample(setdiff([1 pi 5],p(k)),1)-3)/2];end
disp(['' (p==1:5)'+32])

在线尝试!



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;}

-7个字节,感谢@OlivierGrégoire

说明:

在线尝试。

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我以为我已经做到了,但是显然没有。也许我最近在另一个答案中做到了..:S谢谢!
凯文·克鲁伊森


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,但是第二行中的语法无效。

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}

在线尝试!

返回字符串数组的lambda。

我最初的冲动是生成列并转置它们,但是避免该步骤要容易得多。

我本想使用进行初始化a[" "*30]*5,但这会使字符串的副本变浅,从而导致一条非常肥大,无瑕疵的蛇。

我本可以使用一个常量D作为增量(对于相同的字节数),但是Ruby在每次分配它时都会抱怨。我决定重用i中循环来降低可读性,而不是忽略一堆Debug警告。

我还想用来保存一些字节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,再次感谢Eric 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
}

好的开始。不需要内在的loop。您可以使用rand(2+14[x])-30[x]或来计算增量rand -(30[x])..15[x]。可能是较短的版本。不过,-20个字节还不错!在线尝试!
埃里克·杜米尼尔

少1个字节x,a=2,(0..4).map{" "*30}在线尝试!
埃里克·杜米尼尔

1
哇,30[x]真是个绝招!谢谢!
benj2240 '18

1

Perl 6,85个字节

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

在线尝试!

长括号表达式是从初始元素(' ', ' ', 0, ' ', ' ')(输出的第一个垂直条)生成的惰性序列。每个连续的条带/列表都是通过调用其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)

我的独特发明-到目前为止,我还没有阅读其他解决方案,它是生成一个Random(6)隐式地是两个Random(2 * 3)。如果离开边界,我将使用r / 2(0,1,2)和→(-1,0,1)的值向上或向下移动。如果在边界处,我可以避免另一个随机字符的代价高昂的调用,而只需取modulo(2)来决定我应该留下还是应该走。

让我们看看其他解决方案。:)


是的,样本图像错误。是的 :)
用户未知

斯卡拉岩石!哦..代码高尔夫..它出现了错误的用例..它到底是如何被应用的java
javadba

@javadba:您是否单击了try it链接?凯文·克鲁伊森(Kevin Cruijssen)没有提供一些样板,需要编译此代码或在JShell中运行它,但是我想这是根据指南进行的-可能会进行元讨论。如果愿意,也可以尝试使用二维数组来减少此代码。第二个想法是,最终减少滑动代码。一些map方法?凯文(Kevin)隐藏了println。-是的,阵列能够提供通过8的改进
用户未知的

让scala推断返回类型int:多保存了4个字符。
用户未知

所以它现在进入了Java的
舞台

1

Perl,83101字节

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%的概率留在边缘。
Ton Hospel '18

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。)将 helper变量设置$l2(用于上一条蛇段所在的行)。然后从循环029

每次迭代时,我们将蛇元素设置为0。然后,我们索引到一个复杂的数组中,Get-Random从而选择是向上还是向下还是保持不变。这已添加回$l

最后,通过五行我们循环$a-join自己内心的元素融入到每一个字符串。这五个字符串留在管道上,隐式字符串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,否则显示空白。不让高度超过边界实际上会花费字节。同样,识别换行的时间也应该是字节密集型的。一个人可以很容易地写一个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))

使用numpy手动计算差异相比,使用的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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.