Taking the dog for a walk

14

3

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!

Doorknob

Posted 2014-03-19T21:06:45.347

Reputation: 68 138

4Things 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? – Jonathan Van Matre – 2014-03-19T21:22:41.670

In case the chosen direction does not allow a valid move: Should no move be done or another direction be chosen? – TimWolla – 2014-03-19T21:36:57.523

How should input be gotten? STDIN? Is a function parameter fine too? – TimWolla – 2014-03-19T21:37:46.580

1My dog only barks at me if I'm about to take him for a walk. – TheDoctor – 2014-03-19T21:39:03.777

@Tim Edited for clarity; thanks. – Doorknob – 2014-03-19T21:40:53.123

@TheDoc My dog seems to bark for an endless amount of reasons ;-) – Doorknob – 2014-03-19T21:41:36.227

Nice challenge. Much more demanding than it first appears to be. – DavidC – 2014-03-20T08:42:17.467

Answers

2

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)

Howard

Posted 2014-03-19T21:06:45.347

Reputation: 23 109

6

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"

TimWolla

Posted 2014-03-19T21:06:45.347

Reputation: 1 878

4

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

Not that Charles

Posted 2014-03-19T21:06:45.347

Reputation: 1 905

2

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

DavidC

Posted 2014-03-19T21:06:45.347

Reputation: 24 524