Code Golf:您自己的宠物ASCII蛇


34

因此,我给自己写了一条单线纸,在控制台上打印了一条蛇。有点有趣,我想知道如何压缩我的代码...

这是一个(简短的)示例输出:

                +
                 +
                  +
                   +
                   +
                   +
                  +
                   +
                    +
                    +
                    +
                     +
                     +
                      +
                      +
                       +
                      +
                     +
                     +
                    +

规格如下:

  • 在每行中,一个非空白字符(随您喜欢)将被打印到控制台,最初在其左侧填充29至31个空格。
  • 每次迭代,都会在这三个动作之间做出随机决定
    • 填充量减少1
    • 填充量保持不变
    • 填充量增加1

这样做30次,以在控制台上打印一条30段长的蛇。

以字节为单位的最短答案将获胜。


我们可以返回行数组吗?是否允许前导/尾随空格或换行符?
毛茸茸的

1
我假设每行上都可以有尾随空格,对吗?
Luis Mendo '18

1
“随机”是什么意思?均匀随机?是否从任何分布中随机抽取三个结果中的每个?来自任何分布的随机数?程序每次运行的结果都必须不同吗?
纳撒尼尔

1
请注意,默认情况下,随机并不总是表示。例如,尽管现在大多数时候它会产生一条直线,但我的脑力激荡答案的第二部分(到目前为止)是完全有效的。
Jo King

1
目前,有两点尚不清楚:1)随机是否意味着均匀随机?(影响此答案)和2)每次输出是否必须不同?(即,是否可以不使用随机数生成器?影响此答案
DJMcMayhem

Answers:


14

05AB1E15 14字节

30DF2Ý<+ΩD0sú,

在线尝试!

用途0

说明

30DF2Ý<+ΩD0sú,
30D            # Push 30 to the stack (One for the amount of iterations we are going to perform and one for the initial padding)
   F           # Pop one of the 30s and perform the following that many times...
    2Ý          # Push [0,1,2] ...
      <         # and create [-1,0,1] from that
       +        # Add the last padding to every entry (e.g. 30 in the beginning resulting in [29,30,31]
        Ω       # Pick one of the results at random ...
         D      # and push it to the stack twice
          0     # Push 0 (Any character will work fine here) ...
           sú   # and pad it with the randomly chosen amount of spaces in the front
             ,  # Finally print the result with a trailing newline

38
05AB1E:0字节,在线尝试!...等等,几乎没有。
魔术章鱼缸

14

随机Brainfuck123个122 121字节

+[--[<]>>+<-]>+[->+>+>+<<<]++++++++++>>++<[>>[->+<<.>]>[-<+>]>?>+++<[>->+<[>]>[<+>-]<<[<]>-]>-->,<[-<<<+>>>]<<<<+.-<<.>-]

在线尝试!

随机Brainfuck是Brainfuck的扩展,增加了?命令的有用功能,该命令将当前单元格设置为随机字节。这打印出一条蛇! s,看起来比蛇更有趣的是脚步声。

怎么运行的:

+[--[<]>>+<-]>+ Create the value 30
[->+>+>+<<<]    Copy it three times
++++++++++      Create a newline cell
>>++<            Adds 2 to the second copy to make it a space and move to the counter
[ While counter
  >>[->+<<.>]>[-<+>] Print out the padding cell number of spaces
  ?>+++<[>->+<[>]>[<+>-]<<[<]>-] Get 3-(random byte%3)
  >-->,<[-<<<+>>>]   Add (result-2) to the padding cell
  <<<<+.-<           Print an exclamation mark
  <<.                Print a newline
  >-                 Decrement counter
] end loop

另一种解决方案是刺到的问题,而不是精神。

87字节

+[--[<]>>+<-]>+[->+>+>+<<<]++++++++++>++>[>[->+<<<.>>]>[-<+>]?[,<+>]?[,<->]<<<+.-<.>>-]

在线尝试!

强烈偏向于不使用填充,但是增加或减少填充都同样可能。每个人发生的机会少于256分之一。


非常好!我不知道?命令。+1
Grant Miller

@GrantMiller ?仅在随机Brainfuck中可用,而不在经典Brainfuck中可用
Jo King


7

视网膜,24字节


30* +
-29{¶<`^
 
S,2@1`

在线尝试!

说明


30* +

将工作字符串初始化为第一行,即30个空格和一个+

-29{¶<`^
 

第二行上有一个空格。-29{将程序的其余部分包装在一个循环中,该循环将运行29次。¶<在每个循环迭代的开始以末尾的换行符打印工作字符串。原子级本身在字符串的开头插入一个空格(基本思想是先插入一个空格,然后随机删除0–2个空格,因为这比在删除,插入和无操作之间随机选择要短一个字节)。

S,2@1`

这使空的正则表达式与输入匹配,从而为我们提供了字符之间(以及字符串的开头和结尾)之间的每个位置。然后,2仅保留前三个匹配项,即零个,一个和两个空格后的匹配项。@从这三个匹配中选择一个随机。然后,分割阶段(S)在该匹配项附近分割输入。并且1告诉它仅保留拆分的第二部分。换句话说,我们将丢弃所有随机匹配的内容。

最终循环迭代的结果,第30行隐式打印在程序的末尾。


您知道什么比删除0--2空格还要短吗?改组周围的空间!。顺便说一句,新的Retina很棒:D
Leo

7

VBA,60 59 49字节

For l=1To 30:?Spc(30+i)"+":i=i+Sgn(Rnd()-.5):Next

将其粘贴到“立即”窗口中,然后按Enter。(确保已关闭显式声明!)

更有可能比留在移动线(即动作不相同的权重),但不是规定的要求(幸运的!)

{编辑} 通过之间去除空间保存1个字节=1To

{EDIT2} 由于remoel的评论节省了10个字节

旧版本:

'V1
i=30:For l=1 To 30:?String(i," ")&"+":i=i+Sgn(Rnd()-.5):Next
'V2
i=30:For l=1To 30:?String(i," ")&"+":i=i+Sgn(Rnd()-.5):Next

5
欢迎来到PPCG!
Martin Ender '18

2
您可以通过更换节省几个字节String(i," ")Spc(30+i)然后取出i=30:。或通过删除-1个字节&。:)
取消删除

7

C#(.NET核心),112 110 106 100 99 98个字节

v=>{var r="";for(int t=30,i=t;i-->0;r+="+\n".PadLeft(t+=new System.Random().Next(3)-1));return r;}

-1个字节感谢@raznagul
-1个字节感谢@auhmaan

说明:

在线尝试。

v=>{                      // Method with empty unused parameter and no return-type
  var r="";               //  Result-string, starting empty
  for(int t=30,           //  Temp-integer, starting at 30
      i=t;i-->0;          //  Loop 30 times
    r+=                   //   Append the result-String with:
       "+\n"              //    The character and a new-line,
            .PadLeft(     //    left-padded with `t` spaces,
                     t+=new System.Random().Next(3)-1));
                          //    after `t` first has been changed with -1, 0, or 1 randomly
  return r;}              //  Return the result-string

一件奇怪的事:如果我new Random().Next()在本地多次调用(.net Framework版本4.6.1),我总是得到相同的结果。我需要Thread.Sleep(10)在调用之间添加一个,以可靠地获得不同的结果。睡眠时间少于10毫秒时,我有时仍会得到相同的结果。因此,.net-Framework和TIO(.net-Core)具有不同的PRNG或至少使用不同的种子。如果将TIO中的程序切换为C#-mono,则将获得与.net-Framework中本地相同的行为。
raznagul

@raznagul Hmm,使用C#(Mono C#编译器)的输出确实很奇怪
。–

3
@raznagul new Random()使用时间作为种子,因此在紧密循环中,时间是相同的,因此结果是相同的。
TheLethalCoder

@TheLethalCoder:是的,这就是我(或多或少)期望的。奇怪的是1).net-Core(至少在TIO上)表现不同。2)我需要Thread.Sleep(10)可靠地获得不同的结果,Thread.Sleep(1)甚至9ms还不够。
raznagul

@raznagul睡眠时间为1、9或10毫秒的睡眠时间应该全部相同,这取决于运行的其他进程……确实很奇怪。
TheLethalCoder

7

C,56个字节

n;f(p){n>29?n=0:f(printf("%*d\n",n++?p-rand()%3:31,0));}

在线尝试!

说明:

n; // As a global variable, n is initialized to zero.
f(p)
{
    // Call the function recursively until n > 29.
    n > 29

        // At the end, set n back to zero.
        ? n=0

        // On the first iteration, n == 0 and p has an indeterminate value.
        // 'n++ ? p-rand()%3 : 31' returns 31 (without reading p), and thus
        // 30 spaces get printed. printf() returns the number of characters
        // printed, 32 (30 spaces + '0' + '\n').
        //    On subsequent iterations, p has the value the previous printf
        // call returned, which is the padding on last iteration + 2. Also,
        // n > 0, so the same expression now returns p-rand()%3, and thus
        // the padding changes either by -1, 0, or 1 spaces. The function
        // is again called with the value of the current line's padding + 2.
        : f(printf("%*d\n", n++ ? p-rand()%3 : 31, 0));
}

C(gcc),55个字节

n;f(p){n=n<30&&f(printf("%*d\n",n++?p-rand()%3:31,0));}

取决于f “返回”在函数中分配给n的值,这是未定义的行为,但是在未启用优化的情况下与gcc一致。

在线尝试!


6

JavaScript(ES8),63 62 60字节

包括结尾的换行符。*2-1可以用-.5节省1个字节的方式替换,但是每行与前一行相同长度的机会将大大增加。当然,由于挑战中未定义“随机”,因此可以new Date%3-1总字节数55代替RNG 。

f=(x=y=30)=>x?``.padEnd(y+=Math.random()*2-1)+`+
`+f(--x):``

多亏了有人删除了我的评论,才节省了一个字节。我实际上已经用这种方法尝试过了repeatpadStart但是没有想到尝试padEnd-不知道为什么!


奖金

对于相同数量的字节,这是一个以起始空格和迭代次数为输入的版本。

f=(x,y=x)=>x?``.padEnd(y)+`+
`+f(--x,y+Math.random()*2-1):``


f=(x=y=30)=>x?`+\n`.padStart(y+=Math.random()*2-1)+f(--x):``短一个字节。(注意:由于SO不允许在注释中使用换行符,因此我不得不键入\ n而不是实际使用换行符。)
Stefnotch

谢谢,@ Stefnotch。不幸的是,即使初始值为y=31,第一行也可能太短。tio.run/##BcFLDsIgEADQvSeZkUCs7kzQE7hyqSYzKfRjKBCYGHp6fO/…–
毛茸茸的

1
如果我错了,请纠正我,但是您当前的解决方案也不会遇到该问题吗?
Stefnotch

1
根据挑战,第一行应该恰好有 30个空格。
Nit

1
@ Nit,OP确认第一行可能包含29-31个空格,但是尽管屡次要求这样做,但尚未将该事实编辑为挑战。
毛茸茸的

6

Java 8,89 87字节

第一次打高尔夫球,我敢肯定会更好。

编辑:修复了第一行,感谢Steadybox

l->{for(int a=31,b=a;--a>0;){System.out.printf("%"+b+"c\n",'+');b+=2-Math.random()*3;}}

在线尝试!

 l->{                                           //Begin lambda
    for(int a=31,b=a;--a>0;)                  //Initialise vars, loop through 30 lines
    {
        System.out.printf("%"+b+"c\n",'+');     //Print result
        b+=2-Math.random()*3;                   //Change padding by -1, 0, or 1
    }

5
欢迎来到PPCG!:)
Shaggy


6

Python 2中83个 65 64字节

简单的方法:

import os
k=30
exec"print' '*k+'+';k+=ord(os.urandom(1))%3-1;"*k

在线尝试!

感谢@Rod节省了一些字节!感谢@ovs -1字节!

编辑:更改变量名称并将输出字符串更改为字母“ s”

88字节的更多类似蛇的输出:

from random import*
s=[30,0]
exec"print' '*sum(s)+'(S)'[s[-1]+1];s+=[randint(-1,1)];"*30

1
我喜欢这个。真正整洁的解决方案。
linemade


5

木炭,14字节

× ³⁰F³⁰«↙+M‽³→

在线尝试!链接是详细版本的代码。说明:

× ³⁰            Print 30 spaces (forces the desired indentation)
    F³⁰«        Repeat 30 times
        ↙+      Print a `+` and move down and left one square
          M‽³→  Move right a random number of squares from 0 to 2

如果没有初始缩进要求,则只有10个字节。


@KevinCruijssen嗯,这很尴尬,因为木炭喜欢默认修剪。
尼尔,

5

PHP,61字节

for($p=32;$i<30;$i++)echo str_pad("+
",$p+=rand(-1,1),' ',0);

在线尝试!


8
$i<30;$i++ can be $i++<30; to save 2 bytes.
Kevin Cruijssen

2
55 bytes: for($p=30;$i++<30;$p+=rand(-1,1))printf("%{$p}s\n",'+'); (the \n is counted as 1 char, and should be replaced by a real newline)
Ismael Miguel

2
Alternative 55-byte long, without warnings: for($i=$p=30;$i--;$p+=rand(-1,1))printf("%{$p}s\n",'+');
Ismael Miguel

5

Java 8, 131 129 127 126 119 108 101 bytes

v->{String r="";for(int i=30,j,t=i;i-->0;r+="+\n")for(j=t+=Math.random()*3-1;j-->0;r+=" ");return r;}

Explanation:

Try it online.

v->{                     // Method with empty unused parameter and String return-type
  String r="";           //  Result-String, starting empty
  for(int i=30,j,t=i;    //  Two index integers, and a temp integer (starting at 30)
      i-->0;             //  Loop 30 times:
      r+="+\n")          //    After every iteration: Append the character and a new-line
    for(j=t+=Math.random()*3-1;
                         //   Change `t` with -1, 0, or 1 randomly
        j-->0;r+=" ");   //    And append that many spaces to the result-String
  return r;}             //  Return the result-String

Old 119 byte answer:

v->{String s="",r=s;int i=90,t=30;for(;i-->t;s+=" ");for(;i-->0;t+=Math.random()*3-1)r+=s.substring(t)+"+\n";return r;}

Explanation:

Try it online.

v->{                      // Method with empty unused parameter and String return-type
  String s="",            //  Temp-String, starting empty
         r=s;             //  Result-String, starting empty
  int i=90,t=30;          //  Temp integer, starting at 30
  for(;i-->t;s+=" ");     //  Fill the temp String with 60 spaces
  for(;i-->0;             //  Loop 30 times:
      t+=Math.random()*3-1//    After every iteration: Change `t` with -1, 0, or 1 randomly
    r+=s.substring(t)     //   Append the result with `60-t` amount of spaces
       +"+\n";            //   + the character and a new-line
  return r;}              //  Return the result-String

4

R, 72 69 67 bytes

cat(sprintf(paste0("% ",cumsum(c(30,sample(3,29,T)-2)),"s"),"+\n"))

Thanks to Zahiro Mor for 2 extra bytes!

Try it online!


Switching from sample(3,29,T)-2 to runif(29,-1,1) will reduce byte count by 2 but moves are not equally likely anymore. And could you also switch to paste("%" instead of paste0("% " or am I missing something here?
Rift

@Rift if i was using paste the resulting strings would be of the form % 30 s instead of % 30s. As you said runif would mess up the probabiities.
plannapus

Locally sprintf("%30s"), sprintf("% 30s") and sprintf("% 30 s") return the same results for me. But on TIO only the first two have identical results, so paste0("%" should save a byte. And there is no requirement that every move has the same probability.
Rift

4

Japt, 13 bytes

Returns an array of lines.

30ÆQù1nH±1n3ö

Test it


Explanation

30Æ               :Create the range [0,30) and pass each through a function
   Q              :  The " character
    ù             :  Pad start to length...
           3ö     :    Random element from the range [0,3)
         1n       :    Subtract 1
       H±         :    Add the result of that to H (inititally 32)
     1n           :    Subtract 1 to avoid the possibility of the first line being 33 characters long in total

Bonus

For 2 bytes less, here's a version that takes the number of starting spaces & iterations as input.

U°ÆQùU±1n3ö

Try it


Alternative RNGs

The last 4 bytes can be replaced with any of the following:

MrJ1     :A random float between -1 and 1
Jõ ö     :Generate the range [-1,1] and return a random element
3ö É     :An alternative way of writing the method used above
½nMr     :0.5 subtracted from a random float between 0 and 1

1
Wow, can't believe we're winning at the moment! I think you can save a byte with this (on mobile so I can't really verify)
ETHproductions

@ETHproductions: Ha! That's identical to what I started out with. The problem is, though, if -1 is returned by the RNG on the first iteration, we'll end up with a total line length of 29 when it should be 30, 31 or 32.
Shaggy

Hmm, I'm confused about how your version gets around that then... Also, I believe OP has clarified in the comments that they don't care if an extra space is removed or added in the initial iteration.
ETHproductions

Actually I'm confused by "when it should be 30, 31, or 32"—where is that required?
ETHproductions

@ETHproductions: We start with 30 and then add -1, 0 or 1 giving us 29, 30 or 31 - add the " and that gives us a total length of 30, 31 or 32 for the first line.
Shaggy

4

Swift, 101 bytes

import UIKit
var g=29;for _ in 0...g{print((0..<g).map{_ in" "}.joined(),0);g+=Int(arc4random()%3)-1}

Explanation

A full program. This uses a rather odd trick: arc4random() is a member of the Darwin module, but UIKit also comes with this function installed, so it saves a byte :) Also uses one of my Swift golfing tips for repeating strings an arbitrary number of times.

import UIKit        // Imports the UIKit module, necessary for the RNG.
var g=29;           // Declares an integer variable g by assigning it to 30.
for _ in 0 ... g {  // Execute the code block 30 times (for each integer in [0; g]):
 print(             // Output the following:
  (0..<g).map       // For each integer in [0; g)...
   {_ in" "}        // ... return a literal space character. 
    .joined()       // ... And join the result to a single string.
             ,0     // Also print a "0" preceded by a single space (g starts from 29).
 );
g+=                 // Increment the variable g by...
   arc4random()%3   // ... A random integer, modulo 3...
   Int(...)-1       // ... Casted to an integer (yes, this is needed!) and decremented.
}

Doesn't for _ in 0 ... g execute the code block 29 times now instead of 30 (loop from 0 to 29 (exclusive))?
Kevin Cruijssen

@KevinCruijssen No, 0...g generates all the integers in [0; g]. My bad, fixed the explanation. 0..<g would generate the integers in [0; g) :P
Mr. Xcoder

Ah, the [0; g) you've edited to [0; g] indeed confused me. :) Hmm, but isn't it possible to start at g=30 and loop [1; g] in that case?
Kevin Cruijssen

@KevinCruijssen Looping over either [0; g) or [1; g] would definitely be possible if I choose g=30 instead, but then print(...,0) needs to be changed to print(...+"0"), because an additional (extraneous) space would be prepended before the 0 otherwise. Either way, the byte count remains the same.
Mr. Xcoder

4

Perl, 36 bytes

perl -E '$#a=29;map{$#a+=rand(3)-say"@a -"}@a'

So good. I always forget you can set an array length like that... and using say for subtraction. Am I right in thinking it doesn't change the number of runs when $#a is incremented because it's not a reference?
Dom Hastings

@DomHastings: It's because I use map which seems to first lay out the elements on the stack. for does not and would have had an unpredictable loop length
Ton Hospel

That's really useful to know. Thanks!
Dom Hastings

Nice golfing. I tried to shave off another byte with perl -E 'map{$#a+=rand(3)-say"@a -"}@a=1..30', but that sometimes (not every time) resulted in segmentation fault. Could it be a bug in perl v5.22.1 and v5.16.3?
Kjetil S.

@Kjetil Yes, that is a well known problem that probably will never be fixed. When looping an array the entries don't get an extra refcount, so if you delete them they are freed by the time the loop reaches them and you hit freed memory. Fortunately you never do this in real programs.
Ton Hospel

4

R, 54 53 bytes

cat(sprintf('
%*s',cumsum(c(30,sample(3,29,T)-2)),0))

Similar idea as above, but with shortened sprintf code and a shorter character string literal. Instead of \n (two bytes) I’m using a literal line break (one byte).

Try it online!


A field width or precision (but not both) may be indicated by an asterisk *: in this case an argument specifies the desired number. I've been using sprintf for years and somehow always missed that part... Thanks for the reminder!
plannapus

1
The second line is sometimes indented two spaces instead of one.
Scott Milner

@ScottMilner Found some time to fix it.
Konrad Rudolph

4

Ruby, 45 39 bytes

x=30
x.times{puts' '*(x+=rand(3)-1)+?S}

Try it online!

Modifying x during the loop does not affect the loop counter. I chose S as a particularly snakelike output character.

-6 bytes: Use rand(3)-1 instead of [-1,0,1].sample. Thanks, Eric Duminil!


You can save two bytes with x.map instead of x.times (equivalent since you don't use the return value)
RJHunter

1
Oops, you're right, ignore me!
RJHunter

1
OK I've got a better one: rand -1..1 is five bytes shorter than [-1,0,1].sample
RJHunter

1
@RJHunter: Or rand(3)-1 for 6 bytes less.
Eric Duminil

1
(x=30).times{puts' '*x+?+;x+=rand(3)-1} (same size) will print exactly 30 spaces for the head of the snake as requested by the challenge
Asone Tuhid

4

SenseTalk, 237 198 Bytes

This is a language that I came to know and love about a decade ago. It's the scripting language that drives the automated testing tool Eggplant Functional. I was an avid user of the tool for many years before joining the company for a while. It's not the most golf-capable language, but I find it very enjoyable to write in. Golfing in it is actually quite challenging as the language is meant to be verbose and English-like... took me quite a while to get it down to 237 bytes.

set s to "                              +"&lf
set p to s
repeat 30
set a to random(0,2)
if a equals 0
delete first char of p
else if a equals 1
put " " before p
end if
put p after s
end repeat
put s

Ungolfed/Explanation

set the_snake to "                              +"&lf #assign the first line of the snake
set previous_line to the_snake                        #set up for the loop

repeat 30 times                                       #loop 30x
    set action to random(0,2)                         #random add/subtract/stay the same

    if action equals 0
        delete the first character of previous_line   #SenseTalk really shines at string manipulation
    else if action equals 1
        put " " before previous_line                  #insert a character at the beginning
    end if

    put previous_line after the_snake                 #plop the new segment into the string
end repeat                                            #close the loop

put the_snake                                         #print to standard out

Edit: Saved 36 bytes thanks to @mustachemoses


1
Is the whitespace necessary?
MustacheMoses

I've a lot of respect for this. Particularly against the background of 'golfing languages' which seem to exist to be utterly unreadable, but short. It's nice to have an example that's just showing what you can do with your language.
AJFaraday

1
Good call @MustacheMoses! Updated.
Allen Fisher

I count 198 bytes (well, the userscript counts that many)
HyperNeutrino

@AllenFisher Do you have a standalone interpreter or compiler for this language that I can use without getting a Eggplant demo?
MustacheMoses


3

PowerShell, 42 bytes

1..($l=30)|%{" "*$l+"x";$l+=-1,0,1|Random}

Try it online!

Loops from 1 to $l=30. Each iteration we put $l spaces plus an x onto the pipeline as a string, then += either of -1, 0, 1 based on Get-Random into $l for the next loop. Those strings are gathered from the pipeline and an implicit Write-Output gives us a newline-separated list for free.



3

Jelly, 18 bytes

1ŒRX+
30ǒС⁶ẋ;€0Y

Try it online!

The chosen character is 0. If returning a list of list of characters is allowed, then the Y can be dropped and the submission can be turned into a niladic chain for 17 bytes. Alternative.

How it works

30ǒС⁶ẋ;€0Y | Niladic main link.
30           | Starting from 30...
  ǒС       | ... Repeat the helper link 29 times and collect the results in a list.
             | (This list includes the first 30, so there are actually 30 numbers).
      ⁶ẋ     | Repeat a space that many times, for each item in the list.
        ;€0  | Append a 0 to each.
           Y | And join by newlines.
-------------+
1ŒRX+        | Monadic helper link. Alternatively, you can use µ1ŒRX+µ instead of the Ç.
1            | The literal one.
 ŒR          | Symmetric range from –1 to 1.
   X+        | Choose a random number therein and add it to the argument.

Jelly, 16 bytes

Combining mine, Erik’s and Jonathan’s solutions, we can golf this down to 16 bytes. The chosen character is 1.

’r‘X
30ǒСṬ€o⁶Y

Try it online!

Thanks to Jonathan Allan for the heads-up (on Ṭ€o⁶).


You could use Ṭ€o⁶ in place of ⁶ẋ;€0 like my 18 byter does and get to down to 17.
Jonathan Allan

@JonathanAllan Thank you! Combining the three Jelly answers, I actually ended up having 16 bytes. But I posted that as a secondary solution because it is not entirely mine. :-)
Mr. Xcoder

3

Octave, 53 51 50 49 bytes

printf('%*d\n',[a=31+cumsum(randi(3,1,30)-2);~a])

Try it online!

Saved 1 byte by no longer doing any looping. Saved another as Octave has printf as well as fprintf.

This new code creates an array of 30 random integers in the range -1:1. It then cumulatively sums the array and adds 30, which gives the desired sequence.

The result is printed using fprintf with a format that says "A decimal number, padded to a specified width, followed by a new line. The width will be the first value input, and the decimal number will be the second value input. If the number of values input is more than this, Octave will keep repeating the print automatically to get the desired output.

To achieve the looping then, we need only interleave zeros between the sequence array so the fprintf function uses each value in the sequence as a width, and each zero as the digit to be printed.

Prints an output like:

                              0
                             0
                              0
                             0
                              0
                               0
                              0
                               0
                              0
                              0
                             0
                            0
                           0
                           0
                           0
                          0
                           0
                            0
                             0
                              0
                              0
                             0
                             0
                              0
                               0
                              0
                              0
                               0
                               0
                                0

The above code doesn't always print exactly 30 spaces on the first line. It will be either 29, 30, or 31. To correct that, you would use this 53 byte version:

x=31;for i=2:x;fprintf('%*d\n',x,0);x+=randi(3)-2;end

You can save two bytes: x=31;for i=2:x;fprintf('%*d\n',x+=randi(3)-2,0);end
Kevin Cruijssen

@KevinCruijssen I thought about that, but it doesn't work the same. It would result in the first line starting with either 29, 30, or 31 spaces.
Tom Carpenter

1
@KevinCruijssen in fact, never mind. I've just noticed the OPs comments saying that is allowed.
Tom Carpenter

Yep. It's a bit annoying a rule is in the comment (especially since it contradicts with the current challenge description..). I've asked OP to edit the challenge to reflect you can start with 29, 30 or 31, since he seems to allow it in the comments.
Kevin Cruijssen

3

Lua, 81 75 bytes

n=30;for i=1,n do print(("%-"..n.."s+"):format(" "))n=n-2+math.random(3)end

In for i=1,n ... the to_exp n is evaluated only once before entering the loop, saving one byte.

-6 thanks to @user202729

Try it online!


1
Welcome to PPCG! You may want to add a TIO link to your post so people can test your program more easily.
user202729

You can golf your answer down to 76 bytes. Besides the page Tips for golfing in Lua may be useful.
user202729


3

Python 3.6, 84 73 69 bytes

from random import*
x=30
exec("print(' '*x+'+');x+=randint(-1,1);"*x)

Thanks to @WheatWizard for -11 bytes. Thanks to @JoKing for -4 bytes.


Since you don't end up using i you can use for i in[1]*30 instead to save bytes.
Wheat Wizard

You can also from random import* so that you don't need the random. later on. And you can remove the newline space after your :.
Wheat Wizard

And if you change 30 to 29 the "+".rjust(x) can be replaced with " "*x+"+".
Wheat Wizard

Actually regarding my last comment it should be 30 spaces not 29. Your current answer only puts 29 spaces and thus fails to meet the spec. This can be fixed by changing 30 to 31.
Wheat Wizard

1
@WheatWizard Thanks! I've added your changes and credited you as well. I changed [1]*30 to [1]*x because it's one byte shorter.
MustacheMoses

3

ES5, 97 95 81 bytes

for(p=i=30;i--;)console.log(Array(p).join(" ",r=Math.random()*3|0,p+=r>1?-1:r)+0)

ES5, 112 98 bytes if function format is needed:

function a(){for(p=i=30;i--;)console.log(Array(p).join(" ",r=Math.random()*3|0,p+=r>1?-1:r)+0)}a()


2
Welcome to PPCG! I think your variables have to be declared inside of a function - _=>{p=30;for(i=0;i<p;i++){console.log(Array(p).join(" ")+"+\n");r=~~(Math.random()*3);p+=r==2?-1:r}}
Oliver

That'll kill the bytes, I'll tell you that. ES5 doesn't include the arrow functions by default. I'll update
Kyle Fairns

@Oliver, function format added :)
Kyle Fairns

Nice! I'm not sure when it was introduced, but I think you can replace join(" ") with join` `
Oliver

@Oliver I'm not sure you could do that in ES5, could you? I thought that was a template literal added in ES6?
Kyle Fairns

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.