My robot has short circuited somehow and randomly run off somewhere from my lab!

Luckily, whenever he does this, his shut-down sequence initiates, giving him enough time to randomly turn and run in the direction its facing for five rounds before he switches off. His gyro and accelerometer functions are still relaying the data back to the lab while he is still on.

The data will always come in the form of five sets of two numbers, for example.


Your mission, golfers is to a) simulate the robot's frantic run and turn sequence by displaying five sets of numbers in the form of a1:d1,a2:d2,a3:d3,a4:d4,a5:d5 where a(n) is the clockwise angle (in degrees) such that -179<=a<=+180 that the robot will turn from its current heading (initially it is at zero heading before it runs amok and turns for the first time), and d(n) is the distance in feet it has run before the next heading change which is such that 0<=d<=500 feet; and b) A calculated heading from the lab (which is also facing a heading of zero), distance in feet (accuracy up to 3 decimal places is strongly encouraged, -5 bytes if you do), and the orientation heading (in degrees) of where my robot it is facing when it has switched off.

Easy example:

Data: 0:1,45:1,90:1,90:1,90:1
Heading: 0
Distance: 1
Orientation: -45

The random turns and distances are just that, random. No set values are to be hard coded, we must see the randomness in action within the code.

Restrictions to randomness: No clock or date based references, we need to see a native random reference within the code. Whenever you run this code, the randomness must present itself with a possibility of showing 1 of 360 possible angles of turning with each turn-run round. So the robot may turn -36 degrees at one turn and may turn +157 degrees the next, followed by another turn of +2 degrees by another turn of -116 degrees and a final turn of +42 degrees on the final turn. At least 360 distinct values must be possible (between -179 to +180 degrees inclusive) with each random angle generation.

Restrictions to distance run: Similarly set, there are 501 possible distances the robot can run, (between 0 and 500 feet inclusive), so I expect the randomness to also be available when determining the robot's running distance. The robot could theoretically run 45, 117, 364, 27 and 6 feet with each of its respective rounds...

The data fed to you will always be in integer values... the robot will turn in integer ranges of degrees, and will run in integer ranges of distance. The output values however, will be floats...

This is code-golf. Shortest code wins... Now go find my robot!

PS: In reference to my "Accuracy up to 3 decimal places", if you can provide the heading (in degrees, to a MINIMUM of 3 decimal places) and a distance in feet (also accurate also to a MINIMUM 3 decimal places) you will get a -5 byte bonus).

  • 1
    \$\begingroup\$ @IsmaelMiguel and @OP - I'm probably going to get shot for this, but couldnt you use -180 < a <= +180 as the < sign on its own means less than but not including AFAIK... \$\endgroup\$
    – George
    Commented Mar 11, 2014 at 21:54
  • 1
    \$\begingroup\$ @GeorgeH You are correct, but what WallyWest is saying is wrong. "-179 <= a <= 180 results in all 360 possible integer headings" -> this is wrong because there are 361 headings. Or the robot isn't allowed to go to -180º? \$\endgroup\$ Commented Mar 11, 2014 at 22:06
  • 1
    \$\begingroup\$ @IsmaelMiguel It is allowed to go -180 degrees, because that's exactly the same as 180. \$\endgroup\$
    – Doorknob
    Commented Mar 11, 2014 at 22:39
  • 1
    \$\begingroup\$ That is wrong. +180º means an half-turn clockwise. -180º means half-turn anti-clockwise (or counterclockwise, as you prefer). if the range is -179<=a<=+180, the robot can't turn 180º anti-clockwise. Why? He will be stuck at -179º! Maybe that is why he had short circuit... \$\endgroup\$ Commented Mar 12, 2014 at 9:34
  • 1
    \$\begingroup\$ @WallyWest I'm not stupid and I understand what you mean. I'm just saying that the range should be fixed. \$\endgroup\$ Commented Mar 12, 2014 at 16:32

6 Answers 6


Ruby, 274 252 249 245 214 211 207 204 202 characters (-5 = 197)

How did PHP beat Ruby in char count?! >:O Must find some way to golf more...

Edit: I beat the PHP answer, but the user who wrote it helped me do it! Go upvote him; he deserves it :-P

Another edit: Gah! He passed me again! You are a very worthy opponent, @MathieuRodic; congratulations, I have to let you win ;-)

puts"Data: #{([x=y=a=0]*5).map{a+=o=rand -179..e=180;x+=M.sin(b=a*P/e)*d=rand 500;y+=d*M.cos b;"#{o}:#{d}"}*?,}
Heading: #{M.atan(y/x)/P*-e+90}
Distance: #{M.hypot x,y}
Orientation: #{a}"

Ungolfed code (and slightly much older version):

data = Array.new(5) { [rand(-179..180), rand(0..500)] }
puts "Data: #{data.map{|x|"#{x[0]}:#{x[1]}"}.join ?,}"
x, y, a = [0] * 3
data.each do |o, d|
    a += o
    x += Math.sin(a * Math::PI / 180) * d
    y += Math.cos(a * Math::PI / 180) * d
puts "Heading: #{Math.atan(y / x) / Math::PI * -180 + 90}
Distance: #{Math.sqrt(x * x + y * y)}
Orientation: #{a}"

Sample output:

Data: 94:26,175:332,14:390,159:448,-45:20
Heading: 124.52305879195005
Distance: 279.5742334385328
Orientation: 397
  • \$\begingroup\$ How is the robot facing due north after having turned five random angles? \$\endgroup\$ Commented Mar 11, 2014 at 19:56
  • \$\begingroup\$ @WallyWest I was under the impression that the orientation marks the starting angle of the robot, correct? I could make it mark the ending angle for only 3 extra chars. \$\endgroup\$
    – Doorknob
    Commented Mar 11, 2014 at 20:54
  • \$\begingroup\$ No, it is always facing due north (heading 0) at the code's execution... Then it turns, runs, turns, runs, turns, runs, turns, runs, turns and then runs... before it shuts down. It will need to have the final angle it is facing inthe Orientation section. \$\endgroup\$ Commented Mar 11, 2014 at 21:07
  • \$\begingroup\$ @WallyWest Ah, okay, edited. Is it okay if the orientation is not in 0...360, or do we have to do a % 360 on it? \$\endgroup\$
    – Doorknob
    Commented Mar 11, 2014 at 21:08
  • \$\begingroup\$ You can save 11 characters by declaring M=Math and P=M::PI and replacing the code accordingly - and one more character by getting rid of the space after the second puts. \$\endgroup\$ Commented Mar 11, 2014 at 22:35

PHP - 238 232 221 212 203 199 characters

for(;$i<5;$h+=$a=rand(-179,181),$x+=cos($b=$a*$k=M_PI/180)*$l=rand(0,501),$y+=$l*sin($b),$d.=($i++?",":"")."$a:$l");echo"Data: $d
Heading: $h
Distance: ".hypot($x,$y)."
Orientation: ".atan2($y,$x)/$k

(test it here: http://ideone.com/dNZnKX)

Non-golfed version:

$k = M_PI / 180;
$h = $x = $y = 0;
$d = "";

for ($i=5; $i--;){
    $h += $a = rand(-179,181);
    $x += ($l = rand(0, 501)) * cos($b = $k * $a);
    $y += $l * sin($b);
    $d .= ($d ? "," : "") . "$a:$l";

echo "Data: $d\nHeading: $h\nDistance: " . sqrt($x*$x + $y*$y) ."\nOrientation: " . atan2($y, $x)/$k . "\n";

(test it here: http://ideone.com/1HzWH7)

  • \$\begingroup\$ Looks like Perl just narrowly beat us both at the last minute. :-O \$\endgroup\$
    – Doorknob
    Commented Mar 24, 2014 at 11:47
  • \$\begingroup\$ @Doorknob Yup, sorry :) \$\endgroup\$
    – Mouq
    Commented Mar 24, 2014 at 22:02
  • \$\begingroup\$ Definitely. Mouq, you kind of wiped out all our efforts with only 188... \$\endgroup\$ Commented Mar 24, 2014 at 22:06

Python - 264 259 256 258 - 5 = 253 characters

from math import*;import random as R;r,k,d=R.randint,pi/180,[];h=x=y=0;exec"a,l=r(-179,180),r(0,500);d+=[`a`+':'+`l`];h+=a;x+=l*cos(k*a);y+=l*sin(k*a);"*5;print('Data: %s\nHeading: %d\nDistance: %.3f\nOrientation: %d'%(','.join(d),h,hypot(x,y),atan2(y,x)/k))

(test it at http://ideone.com/FicW6e)

Ungolfed version:

from math import *
from random import randrange as r

k = pi / 180
h = x = y = 0
d = []
for i in range(5):
    a = r(-179,181)
    l = r(501)
    d += ['%d:%d' % (a, l)]
    h += a
    x += l * cos(k * a)
    y += l * sin(k * a)

print('Data: %s\nHeading: %d\nDistance: %.3f\nOrientation: %f' % (','.join(d), h, sqrt(x*x+y*y), atan2(y,x)/k))

(test it at http://ideone.com/O3PP7T)

NB: many answers include -5 in their title, while their program does not represent the distance with accuracy up to 3 decimal places...


Perl 6: 188 184 characters - 5 = 180 points

$_=((-179..180).pick=>(^501).pick)xx 5;my$o;$/=([+] .map:{unpolar .value,$o+=.key/($!=180/pi)}).polar;say "Data: {.fmt("%d:%d",",")}
Heading: {$1*$!}
Distance: $0
Orientation: {$o*$!}"

Golf with whitespace:

$_ = ((-179..180).pick => (^501).pick) xx 5;
my $o;
$/ = ([+] .map: {
    unpolar .value, $o += .key / ($!=180/pi)
say "Data: {.fmt("%d:%d", ",")}
Heading: {$1*$!}
Distance: $0
Orientation: {$o*$!}"


my &postfix:<°>  = */180*pi; # Deg → Rad
my &postfix:<㎭> = */pi*180; # Rad → Deg

my @data = ((-179..180).pick => (0..500).pick) xx 5;
say "Data: @data.fmt("%d:%d", ",")";

my $cum-angle = 0;
my $complex = [+] @data.map: {unpolar .value, $cum-angle += .key°}
my ($dist, $ang) = $complex.polar;

say "Heading: ",     $ang.㎭;
say "Distance: ",    $dist;
say "Orientation: ", $cum-angle.㎭;

This turns the data into complex numbers with unpolar, puts the sum of them into $complex, and then gets the polar coordinates as $dist, $ang.

The cumulative angle, $cum-angle is collected because the angles are relative to the robot as it moves through the lab and because we need the final angle of the robot in our output.

Sample output:

Data: -73:230,-144:453,-151:274,-52:232,88:322
Heading: -5.33408558001246
Distance: 378.74631610127
Orientation: -332

The only real trick the golf uses is that it (mis)uses all 3 of Perl 6's special variables to good effect:

  • $! is used for radians ↔ degrees
  • $_ holds the data, and anything that looks like a lonely .method() actually means $_.method() (except inside the map {…} block, where $_ actually takes on the value of the number pairs that make up the data)
  • $/ holds what is in the ungolfed version ($dist, $ang). $0 and $1 actually mean $/[0], i.e., $dist, and $/[1], i.e., $ang
  • \$\begingroup\$ Nice! You can still go down from 188 to 184 like this: $_=((-179..180).pick=>(^501).pick)xx 5;my$o;$/=([+] .map:{unpolar .value,$o+=.key/($!=180/pi)}).polar;say "Data: {.fmt("%d:%d",",")} Heading: {$1*$!} Distance: $0 Orientation: {$o*$!}" \$\endgroup\$ Commented Mar 24, 2014 at 13:13
  • \$\begingroup\$ @MathieuRodic Oh, nice find! Thanks! Unfortunately, the space after .map: is mandatory \$\endgroup\$
    – Mouq
    Commented Mar 24, 2014 at 22:00
  • \$\begingroup\$ Oh, I was wrong about the space, cool :) \$\endgroup\$
    – Mouq
    Commented Mar 24, 2014 at 22:10

Python 301-5=296

from math import*
for i in[0]*5:a=r(-179,180);d=r(0,500);o+=a;o+=180*((o<-179)-(o>180));n=pi*o/180;x+=d*cos(n);y+=d*sin(n);s+=["%d:%d"%(a,d)]
print"Data: "+",".join(s)+"\nHeading: %d"%degrees(atan(y/x))+"\nDistance: %f"%sqrt(x**2+y**2)+"\nOrientation: %d"%o

Nothing too fancy here, rather verbose. This is one problem for which I am not happy that python's trig functions work in radians.

> python robot.py
Data: 17:469,110:383,-146:240,-78:493,62:1
Heading: -17
Distance: 405.435748
Orientation: -35
> python robot.py
Data: -119:363,89:217,129:321,10:159,-56:109
Heading: -79
Distance: 130.754395
Orientation: 53

Python 2 = 376 319 characters (-5 for distance=314)

import random,math
for i in range(5):
    print '%d:%d,'%(a,d),
    if h>180:
print 'Heading: %d\nDistance: %3f\nOrientation: %d' % (h,t,o)

sample output

-141:245, 56:355, 145:223, -10:80, -38:253,
Heading: 12
Distance: 559.031404
Orientation: -2
  • \$\begingroup\$ Python does trigonometry calculations with radians, not with degrees. Hence, your calculations are probably wrong... \$\endgroup\$ Commented Mar 19, 2014 at 10:07

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.