24
\$\begingroup\$

Draw a program or function that will write to STDOUT n times (each for one step) a string that contains a dot . at the location of the walker. The program also needs to write a line every s seconds (or wait s seconds after each line).

A random walk is a mathematical formalization of a path that consists of a succession of random steps (wiki), such that every new step will be the last step plus a new value, so any tstep value is just the sum of all the random values before ir plus the initial value.

The program should take 2 inputs and will use only spaces " " and dots "." on the output. The start value of the walker will be 20 such that the output should be a dot after 19 spaces.

                  . #19 spaces then a dot

Every new step the value will be the last value of the walker plus one of these[-2-1,0,1,2](20% chance each). After the new position is printed the program should wait s seconds and the go to the next step. If the step takes the walker outsite the range 1 to 40 it should be just ignored and the walker position stays the same. The number of spaces will always be a number from 0 to 39.

Example

#input
Mywalk(s = 0.1, n = 30)

#output
                     .
                    .
                      .
                        .
                          .
                           .
                            .
                          .
                         .
                          .
                           .
                            .
                           .
                          .
                           .
                           .
                         .
                         .
                          .
                            .
                           .
                          .
                           .
                           .
                           .
                         .
                          .
                         .
                          .
                          .

Considerations

  • You may take the input as any reasonable format

  • The shortest code wins

  • It's okay if your program only accept the seconds as integers

\$\endgroup\$
  • 2
    \$\begingroup\$ I assume n is the number of steps? \$\endgroup\$ – ASCIIThenANSI Dec 18 '15 at 17:27
  • \$\begingroup\$ Yeah, I've clarified that, thanks. \$\endgroup\$ – Mutador Dec 18 '15 at 17:33
  • \$\begingroup\$ I think you should say that the range is 1 to 40, because the number of spaces is always position-1. \$\endgroup\$ – geokavel Dec 18 '15 at 18:09
  • \$\begingroup\$ @geokavel that seems better, fixed ! \$\endgroup\$ – Mutador Dec 18 '15 at 18:29
  • 10
    \$\begingroup\$ Draw a program??? ;-) \$\endgroup\$ – Digital Trauma Dec 18 '15 at 20:13

15 Answers 15

6
\$\begingroup\$

Pyth, 39

J19VEK+.d0QW<.d0K)+*d=JhtS[Z39-+O5J2)\.

Takes s as the first line of input and n as the second. Works on the command line but not with the online interpreter. My first Pyth program ever! Golfing tips are appreciated.

\$\endgroup\$
  • \$\begingroup\$ Welcome to Pyth! The only golfing tip I can see is that you can use Q and E for the two inputs instead fo hQ and eQ, if you newline separate the inputs. \$\endgroup\$ – isaacg Dec 18 '15 at 23:58
13
\$\begingroup\$

Matlab, 112

The core idea is generating a list of possible next positions and then uniformly drawing one of them. If we are e.g. at position $l=1$ the possible steps would be [-1,0,1,2,3] Of course if we would chose -1 that would be invalid and we would have to stay at the same position. Thats why we replace the invalid positions with the current position, [1,0,1,2,3], and then randomly chose an element from this updated list.

The OP asked us tho draw the program, so here we go:

enter image description here

The transcription:

function c(n,s);
l=19;                             %initialize position
for k=1:n;                          
    disp([ones(1,l)*32,'.']);     %print the line
    z=(-2:2)+l;                   %get vector of possible next steps (for l=1 we get [-1,0,1,2,3])
    z(z<0)=l;                     %prune invalids: here we just replace the the invalid positions with the current position
    z(z>39)=l;                    %   this ensures the same behaivour as staying in the same spot when going outside of the range
    l=z(randi(5));                %draw random sample of those
    pause(s);
end
\$\endgroup\$
  • 1
    \$\begingroup\$ -1 uses MathJax in a non-MathJax environment ;) \$\endgroup\$ – Conor O'Brien Dec 18 '15 at 19:16
  • 2
    \$\begingroup\$ O.o You know, equations that are not written in latex are just not quite as trustable, they might even be not true! Better be on the safe side. \$\endgroup\$ – flawr Dec 18 '15 at 21:05
  • 3
    \$\begingroup\$ Drawn programs should be measured in volume of ink, rather than bytes... \$\endgroup\$ – Darrel Hoffman Dec 20 '15 at 15:45
8
\$\begingroup\$

Perl, 136 128 116 106 101 90 86

$p=19;map{say$"x$p.".";sleep $ARGV[0];$x=rand(5)+$p-2;$p=$x>0&&$x<40?$x:$p}1..$ARGV[1]

Requires the seconds to be an integer.

Run with perl <filename> <second delay> <number of steps>.

There may be more golfing potential here, although honestly, I'm surprised it got this far. (Come on, only 6 more bytes to beat the bash answer...)

Changes

  • Saved 8 bytes by removing unneeded parentheses and spelling out ARGV (it's actually shorter that way)
  • Saved 12 more bytes by removing $s and $n and just using the plain $ARGV[0] and $ARGV[1]
  • Saved another 10 bytes when I realized I could use $" and didn't need to specifically define $u as $undef.
  • Saved 5 more bytes by rearranging the ternary and how $x is used and by using map instead of for.
  • Saved 11 bytes by no longer accepting the seconds as decimals (challenge spec says it's OK.)
  • Saved another 5 bytes by using say instead of print.
\$\endgroup\$
6
\$\begingroup\$

Python 2, 124 119 bytes

@janrn and @Steve Eckert: I don't have enough reputation to comment your answer but here's essentially your version shortened down. The task is to draw a program or a function, so by using f(s,x) you can save quite some bits, as well you can use max(0,min(x,39)) to avoid an extra if clause. Got it down to:

import time,random as r
def f(s,x):
 n=19
 while x:print' '*n+'.';time.sleep(s);n=max(0,min(n+r.randint(-2,2),39));x-=1
\$\endgroup\$
5
\$\begingroup\$

Bash, 81

for((s=20;i++<$1;t=s,s+=RANDOM%5-2,s=s<0|s>39?t:s)){
printf %${s}s.\\n
sleep $2
}

Edit: If the step takes the walker outsite the range 1 to 40 it should be just ignored and the walker position stays the same handled correctly.

Input from command-line options. E.g.:

$ ./randwalk.sh 5 0.5
                    .
                     .
                    .
                  .
                 .
$ 
\$\endgroup\$
4
\$\begingroup\$

Ruby, 84

def w(s,n)q=19;n.times{puts ' '*q+'.';sleep s;q+=rand(5)-2;q=[[q,0].max,39].min};end
\$\endgroup\$
4
\$\begingroup\$

Python 2.7, 198 162 143 133

import time,random as r;p=20;s=0;d=input();w=input()
while s<d:
 print' '*p+'.';s+=1;p=max(1,min(p+r.randint(-2,2),40));time.sleep(w)

When calling the script with python script.py, the first input is the amount of steps, second input the time between steps (accepts float or int). Any suggestions for improving?

Edits

  • saved 36 bytes due to now using print ' '*p+'.', thanks to @corsiKlause Ho Ho Ho
  • down another 19 bytes by removing tab indents, replaced them with one space or ; where possible
  • 10 bytes less thanks to @Bruce_Forte idea with p=max(1,min(p+r.randint(-2,2),40)) (I can't comment on your answer as well, but thanks; don't want to copy it completely)
\$\endgroup\$
  • \$\begingroup\$ In Python, can't you just go ' '*p to repeat the string? \$\endgroup\$ – corsiKa Dec 18 '15 at 23:35
  • \$\begingroup\$ Actually yes, didn't know that. Editing now, thanks \$\endgroup\$ – janrn Dec 18 '15 at 23:42
4
\$\begingroup\$

Processing, 150 147

void w(int n,int s){int x=20,i,y,c=0;for(;c<n;c++){x+=y=int(random(5)-2);if(x>40||x<0)x-=y;for(i=1;i<x;i++)print(" ");println(".");delay(s*1000);}}

Usage:

void setup() {
    w(10,1);
}

Note: 1000 can't be changed to 1e3 for type reasons.

\$\endgroup\$
3
\$\begingroup\$

Lua, 140 Bytes

Note: This program requires the LuaSocket package.

require"socket"p=19 for i=1,arg[2]+0 do print((" "):rep(p)..".")p=p+math.random(-2,2)p=p<0 and 0 or p>39 and 39 or p socket.sleep(arg[1])end
\$\endgroup\$
3
\$\begingroup\$

Perl 6, 92 bytes

my (\n,\s)=@*ARGS;$/=19;for (-2..2).roll(n) {put ' 'x($/+=(40>$/+$_>=0??$_!!0)),'.';sleep s} # 92
my (\n,\s)=@*ARGS;
$/=19;
for (-2..2).roll(n) {
  put ' 'x($/+=(40>$/+$_>=0??$_!!0)),'.';
  sleep s
}

Usage:

$ perl6 -e 'my (\n,\s)=@*ARGS;$/=19;for (-2..2).roll(n) {put " "x($/+=(40>$/+$_>=0??$_!!0)),".",;sleep s}' 10 0.001
                  .
                .
               .
              .
               .
                .
               .
                .
                  .
                 .
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 125 bytes

(s,n)=>(t=setTimeout)(c=`console.log(" ".repeat(p)+".");p+=m=Math.random()*5|0;p-=p>41|p<2?m:2;--i&&t(c,d)`,d=s*1e3,p=19,i=n)

Explanation

(s,n)=>
  (t=setTimeout)(                     // set inital timeout
    c=`                               // c = code for timeout to execute
      console.log(" ".repeat(p)+"."); // print the current line
      p+=m=Math.random()*5|0;         // move walker 0 - 4 positions to the right
      p-=p>41|p<2?                    // if walker was moved out of bounds (2 - 41 instead
                                      //     of 0 - 39 because the random move of 0 - 4 to
                                      //     the right has not had the 2 subtracted yet)
        m:                            // undo the move
        2;                            // else subtract 2 to make the move -2 to 2
      --i&&t(c,d)                     // while we have steps remaining schedule next one
    `,
    d=s*1e3,                          // d = milliseconds to wait between steps
    p=19,                             // p = position of walker (0 indexed)
    i=n                               // i = steps remaining (needed to make n global)
  )

Test

console.log = s => result.textContent += s + "\n";
var solution = (s,n)=>(t=setTimeout)(c=`console.log(" ".repeat(p)+".");p+=m=Math.random()*5|0;p-=p>41|p<2?m:2;--i&&t(c,d)`,d=s*1e3,p=19,i=n)
<input type="number" id="seconds" value="0.1" /><br />
<input type="number" id="steps" value="30" /><br />
<button onclick="solution(+seconds.value,+steps.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
3
\$\begingroup\$

k4, 61 characters

f:{y{-1((y:1|40&y+-2+*1?5)#" "),".";."\\sleep ",$x;y}[x]\20;}

sample run:

  f[.1]30
                      .
                    .
                    .
                   .
                   .
                  .
                  .
                   .
                   .
                     .
                    .
                  .
                  .
                    .
                   .
                   .
                 .
                .
               .
               .
              .
            .
          .
         .
         .
          .
            .
              .
              .
                .
\$\endgroup\$
3
\$\begingroup\$

Mathematica, 122 117 bytes

$RecursionLimit=∞;If[#2>0,Print[Indent[a=Min[#3+RandomInteger@{-2,2},39]~Max~0],"."];Pause@#;#0[#,#2-1,a]]&[##,19]&

Recursive anonymous function, takes input in the order specified. Could probably be golfed further.

\$\endgroup\$
2
\$\begingroup\$

Python 3, 154 bytes

import time
from random import*
w=int(input())
z=int(input())
g=19
c=6
s=" "
while c:
    c-=1
    s+=s
while z:
    z-=1
    if -1<g<40:
        print(s[:g]+'.')
    time.sleep(w)
    g+=randint(-2,2)

Generate a string of spaces greater than the maximum required length, then print that string ONLY up to the char at index 'g', then print a '.'. Finish by incrementing g by a random value in the range [-2:2], and repeat.

If anyone could help me golf down that horrific input block, I'd appreciate it.

\$\endgroup\$
  • \$\begingroup\$ To golf the input, why not use sys.argv? \$\endgroup\$ – ASCIIThenANSI Dec 18 '15 at 19:06
  • 1
    \$\begingroup\$ Also, instead of while z:, why not use for i in range(1,z)? \$\endgroup\$ – ASCIIThenANSI Dec 19 '15 at 1:44
  • \$\begingroup\$ I'm curious, how did you get that this is 154 bytes? bytesizematters.com gives a different count (even if you disable counting whitespace) \$\endgroup\$ – p1xel Dec 20 '15 at 22:37
  • \$\begingroup\$ @ASCIIThenANSI: Hmm...by the time I add in the initial call to sys.argv and the import, I can't see how I can save any bytes doing that. And even with the extra lines to declare c then decrement c and z, it's still cheaper to do it this way, by my count. \$\endgroup\$ – Steve Eckert Dec 21 '15 at 16:47
  • \$\begingroup\$ @p1xel: I counted whitespaces internal to the line, just not leading or trailing whitespaces. Is there a different scoring standard that I'm unaware of? \$\endgroup\$ – Steve Eckert Dec 21 '15 at 16:50
1
\$\begingroup\$

C funtion, 114

s=20,i,t;w(int n,float f){for(;i++<n;t=s,s+=rand()%5-2,s=s<0||s>39?t:s,usleep((int)(f*1e6)))printf("%*c.\n",s,0);}

Pretty much a direct translation of my bash answer.

Full test program:

s=20,i,t;w(int n,float f){for(;i++<n;t=s,s+=rand()%5-2,s=s<0||s>39?t:s,usleep((int)(f*1e6)))printf("%*c.\n",s,0);}

int main (int argc, char **argv) {
  w(10, 0.2);
  return 0;
}
\$\endgroup\$

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.