Code Golf: Your own horizontal pet ASCII snake

29

4

Very heavily inspired by this challenge Code Golf: Your own pet ASCII snake - I thought making it horizontal would add an extra layer of complexity.

An example horizontal snake:

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

And the rules are:

  1. Exactly 5 lines of characters are printed
  2. Each line is exactly 30 characters long, consisting of a combination of spaces and the character you choose to draw your snake with
  3. Your snake starts on line 3
  4. The next line to be used for drawing your snake must be randomly chosen from your current line, one line above (if you're not already on line 1) or one line below (if you're not already on line 5).
    • These choices must be equally weighted. So if you are on line 1, you have a 50% chance to stay on line 1 and a 50% chance to move to line 2. If you are on line 2, you have a 33% chance to move to line 1, a 33% chance to stay on line 2 or a 33% chance to move to line 3
  5. Your snake does not need to visit every single line.

Scoots

Posted 2018-02-21T16:39:47.703

Reputation: 679

5Welcome to PPCG! This is a good first challenge. – Giuseppe – 2018-02-21T16:43:13.060

For clarification, if we're on the edge, do we have to uniformly pick (stay on the same line) and (go to a different line) or can we have non-uniform weights? – Giuseppe – 2018-02-21T16:47:00.747

And off the edges, do we have to uniformly pick up/down/same line? – Giuseppe – 2018-02-21T16:47:32.150

2Mmm... at least the 5-line limitation stops people from stealing answers from the other one with a transpose appended. – Magic Octopus Urn – 2018-02-21T16:48:36.473

Humm, I think it should be an even weight. I will clarify the question rules – Scoots – 2018-02-21T16:49:24.400

Can we output an array of lines? – Shaggy – 2018-02-21T17:58:15.930

Also, must we use 0 for the snake or can we use any non-whitespace character? – Shaggy – 2018-02-21T18:21:50.857

@Shaggy "and the character you choose to draw your snake with" – Giuseppe – 2018-02-21T18:31:33.663

Thanks, @Giuseppe; missed that scanning through it on my phone. – Shaggy – 2018-02-21T18:33:04.137

@Shaggy I feel like allowing that now would be unfair to the other answers – Scoots – 2018-02-21T22:01:26.990

9Does physically rotating the monitor by 90° count as a byte? :D – Eric Duminil – 2018-02-22T11:22:52.720

...this is snek – Grant Miller – 2018-02-27T00:59:54.750

Answers

11

JavaScript (ES6), 98 bytes

Saved 7 bytes thanks to @KevinCruijssen

Returns an array of 5 strings.

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&&' '))

Try it online!

Commented

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

Arnauld

Posted 2018-02-21T16:39:47.703

Reputation: 111 334

You can drop the d and use ((y%4?3:2)|0)-(y>0) for -6 bytes. Try it online.

– Kevin Cruijssen – 2018-02-22T08:27:27.020

Correction: -7 bytes. The 1 in new Random(...) is implicit by default of course.. Try it online.

– Kevin Cruijssen – 2018-02-22T08:56:46.300

@KevinCruijssen Thanks! (!!y instead of (y>0) saves 2 more bytes.) – Arnauld – 2018-02-22T11:33:51.433

7

Charcoal, 28 bytes

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

Try it online! Link is to verbose version of code. Explanation:

P|   

Print some padding to force 5 lines of output.

F³⁰«

Repeat 30 times.

0

Print a zero (and move horizontally).

≡ⅉ²M‽²↑

If the Y-coordinate is 2, move up randomly by 0 or 1.

±²M‽²↓

If it's -2, move down randomly by 0 or 1.

M⊖‽³↓

Otherwise move down randomly by -1, 0 or 1.

Neil

Posted 2018-02-21T16:39:47.703

Reputation: 95 035

6

Perl, 68 bytes

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

This doesn't feel optimal at all.

Ton Hospel

Posted 2018-02-21T16:39:47.703

Reputation: 14 114

5

R, 138 bytes

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,,"")

Try it online!

Handily outgolfed by plannapus

Giuseppe

Posted 2018-02-21T16:39:47.703

Reputation: 21 077

5

Python 3, 144 bytes

@Ruts, @Turksarama, and @mypetlion have been very helpful in reducing bytes

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)

Will try and improve on this. Fun challenge!

linemade

Posted 2018-02-21T16:39:47.703

Reputation: 141

3Change l+=random.randint(-1,1) l=0 if l<0 else l l=4 if l>4 else l to l+=random.randint(~-(l<1),l<4) to save 31 bytes. – mypetlion – 2018-02-21T17:48:12.033

1You should be able to remove a lot of spaces and newlines. – Mr. Xcoder – 2018-02-21T17:51:56.947

1Change m=[[' 'for x in R(w)]for y in R(h)] to m=[list(' '*w)for y in R(h)] to save 7 bytes. – mypetlion – 2018-02-21T17:52:17.970

@mypetlion can you explain how l+=random.randint(~-(l<1),l<4) works? – linemade – 2018-02-21T18:34:34.310

2In python, boolean a subclass of int. So False can be used in place of 0 and True can replace 1. The ~ is a unary operator for bitwise not and the - operator flips the sign (multiply by -1). So ~-(False) evaluates to -1 and ~-(True) evaluates to 0. – mypetlion – 2018-02-21T18:46:15.897

1Assign your initial 0 inside your loop and set l after the assignment. This saves you one whole line (m[2][0]=0 is gone) and 2 bytes on the for loop (for i in R(1,30): becomes for i in R(30):).

You will also need to recalculate l after you set the 0. This should take you to 144 bytes. – Turksarama – 2018-02-21T23:43:02.090

1I'm not very experienced, but I believe you can win 9 bytes by not introducing variables wand h. Remove line w,h=30,5 and change m=[list(' '*w)for y in R(h)] to m=[list(' '*30)for y in R(5)]. I hope I'm right. – Ruts – 2018-02-22T07:30:52.293

1Also tried to remove R=range and used function range twice in your code. This also seems to save 1 byte. – Ruts – 2018-02-22T07:41:20.850

Thanks for the explanation, mypetlion. Also thanks Turksarama and Ruts for saving me some bytes! – linemade – 2018-02-22T14:14:04.867

5

Jelly, 24 bytes

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

Try it online!

Explanation

3µ’o1r‘«5¥$Xµ30СṬ€o⁶z⁶Y || Niladic full program.
                         ||
3                        || Starting from 3...
 µ          µ30          || ... Execute 30 times...
               С        || ... And collect the results in a list.
  ’o1r‘«5¥$X             ||--| Monadic "Helper" function.
  ’o1                    ||--| The current integer, decremented OR 1.
     r     X             ||--| Grab a random item from the range from ^ to...
      ‘«5                ||--| ... The number incremented, capped to 5 (uses maximum).
         ¥$              ||--| Syntax elements. Used for grouping links.
                 Ṭ€      || Untruth each.
                   o⁶    || Logical OR with a single space.
                     z⁶  || Transpose with filler spaces.
                       Y || Join by newlines.

Mr. Xcoder

Posted 2018-02-21T16:39:47.703

Reputation: 39 774

4

R, 120 114 bytes

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,,"")

Thanks to @Giuseppe for the additional 6 bytes!

Uses a table of probabilities as follows:

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

where each columns corresponds to a case, i. e. column 1 is picked if the snake is in row 1, giving probabilities 0, 1/2 and 1/2 to pick respectively -1 [go down], 0 [stay still] and 1 [go up] (sample automatically normalize the probabilities to 1), column 2 for row 2 gives probabilities 1/3, 1/3 and 1/3, etc...

Try it online!

plannapus

Posted 2018-02-21T16:39:47.703

Reputation: 8 610

114 bytes – Giuseppe – 2018-02-22T12:22:56.087

@Giuseppe Thanks! There was indeed no reason to alias it, and I forgot to use vector recycling for that extra 0. – plannapus – 2018-02-22T12:49:50.437

3

SOGL V0.12, 22 21 bytes

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

Try it Here!

Explanation:

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

dzaima

Posted 2018-02-21T16:39:47.703

Reputation: 19 048

3

Japt, 31 29 bytes

Returns an array of lines.

30ÆQùU±[2V=Jõ VVJò]mö i3 gUÃy

Test it

Shaggy

Posted 2018-02-21T16:39:47.703

Reputation: 24 623

3

Japt, 26 bytes

30ÆQùU=U?5õ f_aU <2Ãö :3Ãy

Test it online!

ETHproductions

Posted 2018-02-21T16:39:47.703

Reputation: 47 880

2

SmileBASIC, 107 105 103 89 bytes

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

This answer is more interesting than the vertical one because of the (literal) edge cases.

64 bytes, without printing spaces:

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

I also found a few variations of line 2 with the same length:

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

The integer division of Y/3 is used to check if Y is outside the valid range, as well as getting the sign.

12Me21

Posted 2018-02-21T16:39:47.703

Reputation: 6 110

2

Python 2, 127 bytes

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)

Try it online!

Rod

Posted 2018-02-21T16:39:47.703

Reputation: 17 588

2

Octave with Statistics Package, 99 bytes

It also works in MATLAB with the 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])

Try it online!

Luis Mendo

Posted 2018-02-21T16:39:47.703

Reputation: 87 464

2

Java 8, 177 170 bytes

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 bytes thanks to @OlivierGrégoire.

Explanation:

Try it online.

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

Kevin Cruijssen

Posted 2018-02-21T16:39:47.703

Reputation: 67 575

1r+=Math.random()*(r%4>0?3:2)-(r>0?1:0) to save a few bytes. – Olivier Grégoire – 2018-02-23T13:54:21.673

@OlivierGrégoire I thought I had already done that, but apparently not. Maybe I did it in another answer recently.. :S Thanks! – Kevin Cruijssen – 2018-02-23T15:16:21.503

2

Japt, 28 bytes

Saved 9 bytes thanks to ETHproductions

3k
29Æp5õ f_aUgY)<2Ãö
¡QùXÃy

Try it online!

Oliver

Posted 2018-02-21T16:39:47.703

Reputation: 7 160

2

C (gcc), 134 130 bytes

r,x,y=3,a[31],m;f(){for(x=0;x<31;x++){m?putchar(x==30?10:a[x]-m?32:48):(a[x]=y);r=rand();y+=y==1?r%2:y==5?-r%2:1-r%3;}++m<6&&f();}

Try it online!

MaSi

Posted 2018-02-21T16:39:47.703

Reputation: 21

Welcome to PPCG! – Martin Ender – 2018-02-24T14:42:42.730

Thanks! Using putchar instead of printf saves 4 bytes. – MaSi – 2018-02-24T15:22:34.293

1

Perl, 83 101 bytes

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'

New: Without probability issue at the borders:

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'

Ungolfed:

$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

Kjetil S.

Posted 2018-02-21T16:39:47.703

Reputation: 1 049

2Your border patrol does not give the right probability of 50% for staying on the edge. – Ton Hospel – 2018-02-21T18:40:11.583

1

Scala, 207 Bytes

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)

sample:

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

degolfed:

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)

My unique invention - well, I haven't read the other solutions so far, is, to generate a Random (6) which is implicitly two Randoms, (2*3). If away from the border, I use the values of r/2 (0,1,2) and → (-1,0,1) tell me, to go up or down. If at the border, I can avoid the character costly call of another random, and just take the modulo(2), to decide, should I stay or should I go.

Let's see the other solutions. :)

user unknown

Posted 2018-02-21T16:39:47.703

Reputation: 4 210

Yes, wrong sample image. It does. :) – user unknown – 2018-02-22T01:18:59.730

scala rocks! oh .. code golf .. wrong use case it appears.. How in the heck did it get lapped by java ? – javadba – 2018-02-22T22:28:13.400

@javadba: Have you clicked the try it link? Kevin Cruijssen didn't include some boilerplate, needed to compile this code or to run it in JShell, but I guess that's according to the guidelines - there might be a meta discussion. If you like, you can try to reduce this code, by using a two-dim array too. A second idea is, to reduce the sliding code in the end.Some map method? The println is hidden by Kevin. - Yes, Array gives an improvement by 8. – user unknown – 2018-02-23T03:12:28.050

Let scala infer the return type int: Saved 4 more character. – user unknown – 2018-02-23T03:30:03.083

so it's getting into the ballpark for java now – javadba – 2018-02-23T03:53:43.230

A (0 to 4).map(y=>b(y*30+29)='\n');b foreach print is 2 characters longer than the last line, mkString ... sliding – user unknown – 2018-02-23T03:57:09.187

As I was scrolling down the page, I was thinking about ways to use just one random number, and I thought of using random(6) right as I saw your answer. – 12Me21 – 2018-02-26T21:58:53.647

1

Ruby, 98 77 bytes

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

Try it online!

A lambda returning an array of strings.

My initial impulse was to generate the columns and transpose them, but it's much easier to just avoid that step.

I would have liked to initialize a with [" "*30]*5, but that would make shallow copies of the strings, resulting in a very fat, non-slithery snake.

I could have used a constant like D as the increment (for the same byte count), but Ruby would have complained every time I assigned it. I decided I prefer decreasing readability by reusing i mid-loop to having a bunch of Debug warnings to ignore.

I also would have liked to save a few bytes with loop{x+=rand(3)-1;(0..4)===x&&break}, but that would have caused a bias on the edges: 1/3 chance to turn back inward, 1/3 chance to stay, and 1/3 chance to go out of bounds for a while before eventually random-walking back in (that is, "stay").

-20 bytes: Use Ruby's Integer#[] to create tiny conditionals, ensuring correct movement weightings for all 5 positions. This replaces a loop-break pattern (with a nonzero chance of failing to halt) for a huge savings. Thanks, Eric Duminil!

-1 byte: Initialize a with (0..4).map instead of 5.times, thanks again to 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
}

benj2240

Posted 2018-02-21T16:39:47.703

Reputation: 801

Nice start. No need for an inner loop. You can calculate the increment with rand(2+14[x])-30[x] or rand -(30[x])..15[x]. There's probably a shorter version. Still, -20 bytes isn't bad! Try it online!

– Eric Duminil – 2018-02-22T13:14:33.320

1 byte less with x,a=2,(0..4).map{" "*30}. Try it online!

– Eric Duminil – 2018-02-22T15:20:34.213

1Wow, 30[x] is a great trick! Thanks! – benj2240 – 2018-02-22T19:48:59.280

1

Python 3, 123 bytes

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

Try it online!

Generate an array of integers, then convert it to each row.

Python 2, 120 bytes

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)

Try it online!

For Py2, redundant parens for exec and print can be removed, but the syntax in the 2nd line is invalid.

Outgolfing both Py2 submission by Rod and Py3 submission by linemade.

Bubbler

Posted 2018-02-21T16:39:47.703

Reputation: 16 616

1

Perl 6, 85 bytes

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

Try it online!

The long parenthesized expression is a lazy sequence generated from the initial element (' ', ' ', 0, ' ', ' '), the first vertical strip of the output. Each successive strip/list is generated from the preceding one by calling its rotate method, with the offset randomly chosen from a set containing 0, 1 (if the first element is nonzero), and -1 (if the fifth element is nonzero).

The matrix of horizontal strips is transposed with the [Z] operator, turning it into a list of vertical strips, each of which is then joined into a single string and output with say.

Sean

Posted 2018-02-21T16:39:47.703

Reputation: 4 136

0

PowerShell, 133 bytes

$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$_}

Try it online!

Constructs a 2D array of 30 spaces wide by 5 lines tall. (NB - if someone can come up with a better effective way to initialize this array, I'll <3 you forever.) Sets helper variable $l to 2 (this is used for what line the previous snake segment was on). Then loops from 0 to 29.

Each iteration, we set our snake element to 0. Then we index into a complicated array with Get-Random that selects out whether we go up or down or stay the same. That's added back into $l.

Finally, we loop through the five elements of $a and -join their inner elements into a single string each. Those five strings are left on the pipeline, and the implicit Write-Output gives us newlines for free.

AdmBorkBork

Posted 2018-02-21T16:39:47.703

Reputation: 41 581

0

Clojure, 123 bytes

Here come the parens:

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

Ungolfed version:

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

Builds a list of the different heights of the snake body, then iterates from 0 to 4. Whenever a height matches the current row it prints a 0, otherwise a blank. Not letting the heights exceed the boundary really costs bytes. Also recognizing when a new line is in order is more byte-intensive as it should be. One could easily write a single doseq, making a cartesian product of the x's and y's but then one does not know when to print a new line.

Joshua

Posted 2018-02-21T16:39:47.703

Reputation: 231

0

Python3 +numpy, 137 132 bytes

Not the shortest python submission, not the longest, and definitely not the fastest.

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

update Using numpy's diff command saved 5 bytes for testing if the snake is a valid pattern, compared to calculating the difference manually with j[1:]-j[:-1].

user2699

Posted 2018-02-21T16:39:47.703

Reputation: 538

0

C (gcc), 80 76 72 71 bytes

a[5][30],i,r;f(){for(r=2;i<30;r+=rand()%3-1)a[r=r>4?4:r<0?0:r][i++]=1;}

Try it online!

vazt

Posted 2018-02-21T16:39:47.703

Reputation: 311

Suggest f(r) instead of r;f() – ceilingcat – 2018-12-21T03:14:08.503

0

R, 95 bytes

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

Next line x is always chosen from lines that are no more than 1 away from current line (l[abs(x-l)<2]). Using replicate instead of a for cycle saves some bytes needed for matrix initialization and manipulation and requires the use of the <<- operator when assigning to the global variable x.

Try it online!

Robert Hacken

Posted 2018-02-21T16:39:47.703

Reputation: 371

0

05AB1E, 25 bytes

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

Try it online!

Explanation

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

Emigna

Posted 2018-02-21T16:39:47.703

Reputation: 50 798