34
\$\begingroup\$

So, I wrote myself a one-liner which printed out a snake on the console. It's a bit of fun, and I wondered how I might condense my code...

Here's a (short) example output:

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

Here's the specs:

  • In each line, a single non-whitespace character (whichever you like) is printed to the console, initially with 29 to 31 spaces padding to the left of it.
  • Each iteration, a random decision is made between these three actions
    • The amount of padding decreases by 1
    • The amount of padding remains the same
    • The amount of padding increases by 1

Do this 30 times, to print 30-segment long a snake to the console.

The shortest answer in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Can we return an array of lines? Are leading/trailing spaces or newlines allowed? \$\endgroup\$ – Shaggy Feb 20 '18 at 12:07
  • 1
    \$\begingroup\$ I assume trailing spaces on each line are allowed, right? \$\endgroup\$ – Luis Mendo Feb 20 '18 at 13:20
  • 1
    \$\begingroup\$ What does "random" mean? Uniformly random? Random from any distribution with positive support on each of the three outcomes? Random from any distribution whatsoever? Do the results have to be different on each run of the program? \$\endgroup\$ – Nathaniel Feb 21 '18 at 9:02
  • 1
    \$\begingroup\$ Note that, by default, random does not mean uniformly so. For example, the second part of my brainfuck answer is (as of now) perfectly valid, despite it generating a straight line most of the time. \$\endgroup\$ – Jo King Feb 21 '18 at 15:11
  • 1
    \$\begingroup\$ Right now, there are two points that are unclear: 1) Does random mean uniformly random? (affects this answer) and 2) Must the output be different every time? (i.e., can the random number generator be unseeded? Affects this answer) \$\endgroup\$ – James Mar 2 '18 at 20:41

48 Answers 48

1
2
2
\$\begingroup\$

Python 2, 73 bytes

from random import*
l=c=30
while c>0:l+=randint(-1,1);print' '*l+"+";c-=1

Try it online!

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I really like the idea of creating a snake in Python \$\endgroup\$ – LuudJacobs Feb 21 '18 at 13:56
  • \$\begingroup\$ I must have been half asleep yesterday - I didn't even think about that ;-) \$\endgroup\$ – ElPedro Feb 21 '18 at 14:14
2
\$\begingroup\$

Pyth, 21 19 16 15 bytes

Thanks to Rod for saving 2 bytes and Mr. Xcoder for saving another 3 :)

Uses 0

VK30p*KdZ=+KtO3

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 74 bytes

""<>(" "&~Array~#<>"+
"&)/@Accumulate@Prepend[{-1,1}~RandomInteger~29,30]&

Pure function. Takes no input and returns a string as output.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

K4, 26 bytes

Solution:

-1(-31+\0,-1+29?3)$\:,"$";

Example:

q)k)-1(-31+\0,-1+29?3)$\:,"$";
                              $
                             $
                             $
                            $
                           $
                            $
                             $
                              $
                              $
                              $
                              $
                              $
                               $
                                $
                               $
                              $
                               $
                              $
                              $
                               $
                                $
                                 $
                                 $
                                $
                                 $
                                $
                               $
                                $
                                $
                                 $

Explanation:

Build a list of negative numbers to left-pad "$", perform padding and print to stdout.

-1(-31+\0,-1+29?3)$\:,"*"; / the solution
-1                       ; / print to stdout and swallow return
                     ,"$"  / enlist "$" (e.g. ["$"])
  (              )$\:      / pad right with each-left
             29?3          / 29 choose 3, takes from 0 1 2
          -1+              / subtract 1, so range is -1 0 1
        0,                 / join 0
      +\                   / sums
   -31                     / add to -31

Bonus:

27 byte version in K (oK):

`0:(-31+\0,-1+29?3)$\:,"*";

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ oK 22 bytes: `0:(-31+\1-30?3)$\:$0; \$\endgroup\$ – zgrep Feb 27 '18 at 8:40
  • \$\begingroup\$ @zgrep, probably worth posting as a separate oK solution :) stringing 0 in K4 gives an atom rather than an enlisted char (so you can't pad it) and the above solution always pads the first line with 30 chars - a requirement which was removed as a comment. \$\endgroup\$ – streetster Feb 28 '18 at 22:11
2
\$\begingroup\$

Icon, 51 bytes

-2 bytes thanks to Kevin Cruijssen

n:=30;every 1to 30do{write(repl(" ",n),8);n+:=?3-2}

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Clojure, 88 77 bytes

Always happy to provide a Clojure answer. Always sad, it's quite long.

(loop[x 30 p x](when(> x 0)(printf(str "%"p"d\n")1)(recur(dec x)(+(-(rand-int 3)1)p))))

Ungolfed:

(loop [x 30 p x]
  (when (> x 0) 
    (printf (str "%" p "d\n") 1)
    (recur (dec x) (+ (- (rand-int 3) 1) p))))

Update 1

Managed to shave off 11 bytes by making the code more idiomatic. Who would have thought that making things "more right" would end up being more effective in a Code Golf challenge.

(doseq[p(take 30(iterate #(+ %(-(rand-int 3)1))30))](printf(str "%"p"d\n")1))

Ungolfed:

(doseq [p (take 30
            (iterate
              #(+ % (- (rand-int 3) 1))
              30))]
  (printf (str "%" p "d\n") 1))

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hi, I added a TIO link of your solution to your post. According to TIO, it's 77 bytes long, so I updated this also. \$\endgroup\$ – Galen Ivanov Feb 21 '18 at 11:55
2
\$\begingroup\$

Julia 0.6, 52 49 bytes

Full program, prints a snake with 0. I usually prefer comprehensions to for...end blocks because comprehensions return things. But since I'm printing anyway this is shorter, and you can use newlines at no cost (meaning equal to ;) for a nice readable golf. Saved a byte by using 1:n instead of 1:30 and two bytes with println(" "^n,0) instead of println(" "^n*"+").

n=30
for i=1:n
println(" "^n,0)
n+=rand(-1:1)
end

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

SmileBASIC, 40 bytes

This answer turned out to be pretty boring.

X=30FOR I=1TO 30?" "*X;0X=X+RND(3)-1NEXT
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Pip, 21 bytes

Ln:30{PsXn.0--n+:RR3}

Try it online!

Explanation

                       s is space (implicit)
 n:30                  Set n to 30
L    {              }  Loop that many times:
      P                 Print, with trailing newline:
       sXn               space, repeated n times
          .0             with "0" concatenated
            --n         Decrement n
               +:       and add to it (in-place)
                 RR3    randrange(3), i.e. a random integer between 0 and 2
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

PHP, 58 56 bytes

for($a=$b=30;$a--;)echo str_pad('',$b+=rand(-1,1))."+
";

Try it online!

-2 bytes thanks to @Shaggy

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! :) Seeing as the first line can contain 29-31 spaces, I think you could do this to save 2 bytes. \$\endgroup\$ – Shaggy Feb 23 '18 at 11:59
  • \$\begingroup\$ Thx @Shaggy. Yeah, I only just read the comments on the question saying I could do that xD. Thanks for helping me shave 2 bytes! \$\endgroup\$ – Ethan Feb 23 '18 at 12:01
1
\$\begingroup\$

Jelly, 18 bytes

30µ3ẋX€_2+\+⁸Ṭ€o⁶Y

Uses 1 as the character.

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Your first line does not always start with 30 spaces. \$\endgroup\$ – chocochaos Feb 20 '18 at 12:31
  • \$\begingroup\$ See my comment under the OP \$\endgroup\$ – Jonathan Allan Feb 20 '18 at 12:35
1
\$\begingroup\$

Jelly, 17 bytes

30µ’r‘Xµ’С⁶ẋp”.Y

Try it online!

Full program.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Haskell, 108 bytes

import System.Random
0%_=pure()
n%p=putStrLn(([1..p]>>" ")++"+")>>randomRIO(-1,1::Int)>>=((n-1)%).(p+)
30%30

Try it online! I was surprised to find that this code works in GHCi without the explicit type annotation but not on TIO, until BMO told me about the ExtendedDefaultRules flag which is set by GHCi.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

SOGL V0.12, 14 bytes

'∑:{:@*O2ψH+╗p

Try it Here!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

AWK, 54 bytes

{for(f=30;a++<30;f+=int(4*rand()-2))printf"%"f"s\n",1}

Try it online!

Very straightforward. This requires a 1 line input to run. Could make it a "program" by using a BEGIN label.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

CJam, 31 bytes

{S*TN}:F;30:V{3,{V1-+}%mRz:VF}*

Try it online!

Sort of a port of @Datboi's answer

Explanation

{S*TN}:F                         -The padded string function
{                                -Start block
 S*                              -Multiply space string by argument and push to stack
   T                             -Push integer 0 to stack
    N                            -Push newline string to stack
     }                           -End block
      :F                         -Store top of stack(the block) in variable F
        ;                        -Pop from stack
         30:V                    -Push integer 30 to stack and store in variable V
             {3,{V1-+}%mRz:VF}   -The main loop
              3                  -Push integer 3 to stack
               ,                 -Array range from 0 to n-1
                {V1-+}%          -Map to array
                 V               -Push variable V to stack
                  1              -Push integer 1
                   -+            -subtract values from each other and add to array index
                       mR        -Random choice
                         z       -Absolute value
                          :V     -Store in variable V
                            F    - Execute function in F
                              *  -pop stack and repeat block
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ 21 bytes: Try it online! \$\endgroup\$ – Esolanging Fruit Feb 22 '18 at 7:23
  • \$\begingroup\$ Clearly, I still have a lot of practicing to do. \$\endgroup\$ – Marcos Feb 24 '18 at 12:23
1
\$\begingroup\$

Perl 6, 39 bytes

$_=30;say(" "x($_+=^3 .roll-1)~"x")xx$_

Explanation:

$_=30: Sets the number of spaces to prefix to 30.

say(" "x($_+=^3 .roll-1)~"x"): Outputs that number of spaces and updates it (^3 .roll-1: pick a random integer from 0 to 2 and subtract it by 1), followed by x and a newline.

xx$_: Does this 30 times. Using $_ instead of 30 saves one space before 30.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Go, 123 107 94 bytes

import(."fmt"
."math/rand")
func s(){s:=30
for i:=0;i<30;i++{Printf(`%*d
`,s,4)
s+=Intn(3)-1}}

call function s

Try it online!

| improve this answer | |
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.