14
\$\begingroup\$

My dog is barking at me, but I'm too lazy to take him for a walk. I have an idea! I'll get the people at Code Golf to do it for me!

Your challenge is to simulate a dog's walk. Here are the rules for walking the dog:

  • The human (H) will start at 0,0 on a (Cartesian) coordinate plane, and will randomly go one space either up, left, right, or down every second.
  • The dog (D) will start at the same location, and will go either zero, one, two, or three spaces either up, left, right, or down every second (randomly, of course). The dog is less predictable and will sometimes run faster or stop completely.
  • The dog will never get more than a certain amount of units away from the human (in Euclidean distance), which is the length of the leash (L). For example, if L is 6, a valid position would be H(0,0) D(4,4) (since the distance is about 5.65 units), but not H(0,0) D(5,4) (about 6.4 units).
    • If, when the dog moves, it would violate the leash distance requirement, it must go the farthest it can in its determined direction that does not violate the distance requirement. For example, if the position is H(0,0) D(3,4) and the dog is randomly decided to move 3 spaces to the right, it will go to D(4,4), since that's the farthest it can go without getting more than 6 units away. (Note that this might result in a movement of 0 spaces, i.e. no movement at all!)
  • Miscellaneous rules: the human moves first. The human must not exceed the leash length on its move. If it does, it must choose another direction. "Random" means "with an even distribution and with no patterns."

The input will be given in this format (can be STDIN, function parameter, file, etc.):

"<amount of seconds the walk will last> <leash length>"

For example:

300 6 // a 5 minute walk with a 6 yard leash

You must give output in this format (can be STDOUT, function return value, file, etc.):

H(0,0) D(0,0)
H(0,1) D(2,0)
H(1,1) D(2,1)
H(1,0) D(2,-1)
...

(The amount of lines output will be seconds + 1, since the H(0,0) D(0,0) line doesn't count.)

This is , so the shortest code in bytes will win!

\$\endgroup\$
7
  • 4
    \$\begingroup\$ Things you obviously meant, but it's probably good to state them explicitly anyway: 1. Distance means Euclidean distance, 2. The coordinate plane is Cartesian, not polar (or Boeing 777); Things that aren't clear: 3. What does human do if their move would exceed the leash length? 4. On each turn, who moves first, dog or human? \$\endgroup\$ Commented Mar 19, 2014 at 21:22
  • \$\begingroup\$ In case the chosen direction does not allow a valid move: Should no move be done or another direction be chosen? \$\endgroup\$
    – TimWolla
    Commented Mar 19, 2014 at 21:36
  • \$\begingroup\$ How should input be gotten? STDIN? Is a function parameter fine too? \$\endgroup\$
    – TimWolla
    Commented Mar 19, 2014 at 21:37
  • 1
    \$\begingroup\$ My dog only barks at me if I'm about to take him for a walk. \$\endgroup\$
    – TheDoctor
    Commented Mar 19, 2014 at 21:39
  • \$\begingroup\$ @Tim Edited for clarity; thanks. \$\endgroup\$
    – Doorknob
    Commented Mar 19, 2014 at 21:40

4 Answers 4

6
\$\begingroup\$

CoffeeScript - 324 + function call

Demo (Using Leash 10):

H(0,0) D(0,0)
H(0,-1) D(0,3)
H(-1,-1) D(0,3)
H(-1,-2) D(-1,3)
H(-1,-3) D(-4,3)
H(-1,-2) D(-4,4)
H(-1,-3) D(-5,4)
H(-1,-2) D(-2,4)
H(-1,-3) D(-2,5)
H(-1,-4) D(-2,5)
H(-1,-3) D(-3,5)
H(0,-3) D(-4,5)
H(-1,-3) D(-4,6)
H(-1,-4) D(-2,6)
H(-2,-4) D(-2,6)
H(-3,-4) D(-5,6)
H(-4,-4) D(-5,6)
H(-4,-3) D(-5,8)
H(-5,-3) D(-2,8)
H(-5,-2) D(-2,8)
H(-5,-3) D(-2,5)

Code:

w=(i)->
    [s,l]=i.split ' ';m=Math;h=[0,0];d=[0,0];r=->(4*m.random())|0
    a=->m.abs(h[0]-d[0])**2+m.abs(h[1]-d[1])**2<=l**2
    b=(x)->if x%2 then 1else-1
    for i in[0..s]
        console.log "H(#{h}) D(#{d})"
        loop
            H=h.slice();x=r();h[(x/2)|0]+=b x;break if a();h=H
        D=r();x=r();(d[(x/2)|0]+=b x;d[(x/2)|0]-=b x if!a())while D-->0

Long Code:

human = [ 0, 0 ]
doge = [ 0, 0 ]
randomDirection = -> [ 'u', 'd', 'l', 'r' ][(4*Math.random())|0]
allowed = -> Math.abs(human[0] - doge[0]) ** 2 + Math.abs(human[1] - doge[1]) ** 2 <= leash**2
leash = 0
walk = (input) ->
    [ seconds, leash ] = input.split ' '
    for i in [0..seconds]
        console.log "H(#{human}) D(#{doge}) #{Math.sqrt Math.abs(human[0] - doge[0]) ** 2 + Math.abs(human[1] - doge[1]) ** 2}"
        valid = no
        loop
            oldHuman = human.slice()
            switch randomDirection()
                when 'u'
                    human[0]--
                when 'd'
                    human[0]++
                when 'l'
                    human[1]--
                when 'r'
                    human[1]++

            if allowed()
                break
            else
                human = oldHuman

        dogeDistance = (Math.random() * 4)|0
        switch randomDirection()
            when 'u'
                while dogeDistance-- > 0
                    doge[0]--
                    doge[0]++ if !allowed() 
            when 'd'
                while dogeDistance-- > 0
                    doge[0]++
                    doge[0]-- if !allowed() 
            when 'l'
                while dogeDistance-- > 0
                    doge[1]--
                    doge[1]++ if !allowed() 
            when 'r'
                while dogeDistance-- > 0
                    doge[1]++
                    doge[1]-- if !allowed() 
walk "10 2"
\$\endgroup\$
0
4
\$\begingroup\$

Ruby, 189 177

I can possibly drop this a bit. I don't love j.

h=d=0;e,l=$*
def j;[1,-1,?i,'-i'].sample.to_c end
0.upto(e.to_i){puts'H(%d,%d) D(%d,%d)'%(h.rect+d.rect)
1 while((g=h+j)-d).abs>l.to_i
h,s=g,j
3.times{d+=s if(d+s-h).abs<=l.to_i}}

Ungolfed:

h=d=0 # use complex numbers since it has distance built in
time,leash=$*

def randomDirection
  [1,-1,'i','-i'].sample.to_c 
end

0.upto(time.to_i) { # (1 + time) times
  puts"H(%d,%d) D(%d,%d)"%(h.rect+d.rect) # that's [h.real, h.imag, d.real, d.imag]
  
  # find a newH that doesn't violate the leash
  newH = h + randomDirection
  while((g-d).abs > leash.to_i) 
    newH = h + randomDirection
  end
  
  h = newH
  
  newD = randomDirection
  3.times{
    # keep adding newD until you hit the leash
    d += newD if(d + newD - h).abs <= leash.to_i
  }
}
\$\endgroup\$
2
\$\begingroup\$

GolfScript, 140 characters

~.*:L;)[0.].@{['H('1$','*') D('4$','*')'n]@@{[@~]}+[{)}{(}{\(\}{\)\}]:^%{{~2$~@-.*@@-.*+L>!},}:F~.,{rand}:R~=\[.;{.[~}^4R=+{]}+4R*]F-1=\}*;;

Example run (try online):

> 10 3
H(0,0) D(0,0)
H(0,1) D(0,0)
H(0,0) D(0,2)
H(0,1) D(-1,2)
H(1,1) D(-1,2)
H(1,2) D(-1,4)
H(1,3) D(-1,5)
H(0,3) D(-1,5)
H(-1,3) D(1,5)
H(-1,4) D(1,5)
H(0,4) D(-1,5)
\$\endgroup\$
2
\$\begingroup\$

Mathematica 285

Golfed

r=RandomChoice;k=False;
s:=r[{{0,1},{-1,0},{1,0},{0,-1}}]
w:=r[{0,1,2,3,4}]
f[{-1,___}]:="";
f[{n_,l_,{h_,d_}}]:=
(Print["H(",h,")\t","D(",d,")"];
m[i_,u_,v_]:=EuclideanDistance[u+i,v]<l;
z=k;While[z==k,t=s;z=m[t,h,d]];
y=h+t;t=w*s;z=k;While[z==k,t=t-Sign@t;z=m[t,d,y]];
dp=d+t;f[{n-1,l,{y, dp}}])

Example

f[{17,7,{{0,0},{0,0}}}]

H({0,0}) D({0,0})
H({1,0}) D({0,0})
H({2,0}) D({0,2})
H({2,-1}) D({0,-1})
H({1,-1}) D({-3,-1})
H({1,0}) D({-3,1})
H({1,1}) D({0,1})
H({1,2}) D({0,2})
H({1,1}) D({0,2})
H({1,0}) D({-2,2})
H({2,0}) D({1,2})
H({2,-1}) D({-2,2})
H({2,0}) D({-2,3})
H({2,1}) D({-2,0})
H({1,1}) D({-2,3})
H({2,1}) D({-2,6})
H({1,1}) D({-3,6})
H({0,1}) D({-4,6})


UnGolfed

There are some comments in the text below. I've also included a printout which makes it possible to follow some of the calculations.

step:=RandomChoice[{{0,1},{-1,0},{1,0},{0,-1}}]
dogWander:=RandomChoice[{0,1,2,3,4}]

f[{-1,___}]:="";

f[{n_,l_,{humanPos_,dogPos_}}]:=
Module[{tempStep,moveOK,hp,hp1,dp,p,test},

(* human imagines step, checks with leash, chooses another step if would choke the dog *)
moveOK[intendedStep_,pos1_,pos2_]:=EuclideanDistance[pos1+intendedStep,pos2]<l;
test=False;While[test==False,tempStep=step;test=moveOK[tempStep,humanPos,dogPos]];
hp=humanPos+tempStep;
Print["humanPos before: ", humanPos,"\t","human step: ",tempStep,"\thumanPos after: ",hp,"\tdistance from dog: ",N@EuclideanDistance[hp,dogPos]];

(*move closer to human if needed *)
tempStep=dogWander*step;
test=False;While[test==False,tempStep=tempStep-Sign[tempStep];test=moveOK[tempStep,dogPos,hp]];
dp=dogPos+tempStep;
Print["dog's intended step: ",tempStep,"\tdogPos before: ",dogPos,"\t","dog actual step: ",tempStep, "\t","dogPos after: ",dp,"\tdistance: ",N@EuclideanDistance[hp,dp],"\n"];
f[{n-1,l,{hp, dp}}]]

Example

f[{17,5,{{0,0},{0,0}}}]

[Part of the printout is shown to give a sense of how the code works. ]

printout

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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