8
\$\begingroup\$

Oh no, I am lost on the way to finding the great treasures of Marakov! And all I have are these useless instructions that look like S10R10D30... I have no idea what they mean! Can you help me?

Challenge

Given directions consisting of N E S W U D L R 1 2 3 4 5 6 7 8 9 0, output how far I will be from where I started when I follow those directions (i.e. Euclidean Distance).

N E S W refer to me turning North, East, South, and West;

U D L R refer to me turning Up, Down, Left, and Right (So NR is the same as E, and so is SL; SLL is the same as N). Up means keep going forward; Down means turn around.

After each letter direction will be a number, which is how far I will go in that direction. N10E20 means go North 10 units, then turn East, and go East 20 units.

Input Details

  • Input will always start with one of NESW (so blank input need not be accounted for).
  • Two letter instructions in a row are allowed. NE should be interpreted, "Turn North, then immediately turn East". It's the same as just E. SLL is "Turn South, then immediately turn Left twice". It's the same as N.
  • All numbers will be integers (note how . isn't in the character set)
  • Input will only consist of NESWUDLR1234567890 (If it needs something else, like '\0' in C; or if your language's input functions has a trailing newline, or something, that's fine.)

Output

  • The norm.
  • If using a function, should output a numeric datatype or a string.
  • Must be accurate to 3 decimal places.

Test Cases

  • N10: 10
  • N10E10: 14.1421
  • N10S10: 0
  • NSEWUDLR10: 10
  • N100RR20E300D40L12: 268.7452
  • ERR10LL20UN30D100: 70.71067

The unimaginative Python program I used to make these.

Winning

This is codegolf, so lowest bytes after a week wins!

\$\endgroup\$
  • \$\begingroup\$ @AdmBorkBork Right. Lemme edit. \$\endgroup\$ – Quelklef Aug 2 '17 at 17:51
  • \$\begingroup\$ Related \$\endgroup\$ – AdmBorkBork Aug 2 '17 at 17:54
  • \$\begingroup\$ @AdmBorkBork Also this, but all are slightly different. \$\endgroup\$ – Quelklef Aug 2 '17 at 17:55
  • \$\begingroup\$ Can we assume the input consists only of NESWUDLR1234567890? \$\endgroup\$ – darrylyeo Aug 2 '17 at 17:57
  • \$\begingroup\$ @darrylyeo Sure, let me edit. \$\endgroup\$ – Quelklef Aug 2 '17 at 17:59
2
\$\begingroup\$

(Go)Ruby, 111 bytes

x=0
c=1,1i,-1,-1i
gs.sc(/(\w)(\d*)/){|o,a|x+=c.ro!('URDL'.ix(o)||'NESW'.ix(o)+c.ix(1)).fs*a.toi}
p Mh::hy *x.rc

Try it online!

Takes input on STDIN, outputs it on STDOUT.

Basically, this approach uses complex numbers to store the current position, as well as a stack (c), containing offsets for each direction. If a direction is in URDL, the stack is rotated by the index of the direction in that string; if the direction is in NESW, it's rotated by the index of the direction in that string, plus the index of 1 in the stack. This transforms a rotation relative to the current position into a rotation relative to the position of 1. In any event, the top of the stack is multiplied by the number of steps in the direction and added to the current position.

\$\endgroup\$
  • \$\begingroup\$ What's "(Go)Ruby"? \$\endgroup\$ – Carcigenicate Aug 3 '17 at 3:51
  • \$\begingroup\$ @Carcigenicate It's Ruby, where the interpreter has been compiled with a special flag that makes it more suitable for golfing. Among other changes, it allows you to abbreviate method names, and changes the behavior of certain built-ins. If you visit my TiO link, you'll see the code in the header, which is the majority of changes that are made. \$\endgroup\$ – Tutleman Aug 3 '17 at 8:28
4
\$\begingroup\$

Python 3, 137 bytes

v=n=0
d=1
for i in input()+'U':x="NUERSDW0123456789".find(i);c=x<7;v+=d*n*c;n=[n*10+x-7,0][c];d=[d,d**(x%2)*1j**(~-x/2)][c]
print(abs(v))

Try it online!

-9 bytes thanks to Jonathan Allan

\$\endgroup\$
  • \$\begingroup\$ You can save six bytes with the else clause: else:v+=d*n;n=0;h='NUERSDW'.find(i);d=d**(h%2)*1j**(~-h/2)- note that L can be lopped off the end of the find string here because -1%2 equals 7%2 and 1j**(-1) equals 1j**3. \$\endgroup\$ – Jonathan Allan Aug 2 '17 at 21:42
  • \$\begingroup\$ @JonathanAllan Nice tricks! Thanks! \$\endgroup\$ – HyperNeutrino Aug 3 '17 at 0:29
  • \$\begingroup\$ Save another three by inlining the for: for i in input()+'U':x="NUERSDW0123456789".find(i);c=x<7;v+=d*n*c;n=[n*10+x-7,0][c];d=[d,d**(x%2)*1j**(~-x/2)][c] \$\endgroup\$ – Jonathan Allan Aug 3 '17 at 1:25
  • \$\begingroup\$ @JonathanAllan Hey cool, thanks! \$\endgroup\$ – HyperNeutrino Aug 3 '17 at 1:35
  • \$\begingroup\$ Tried my own hand at a Python answer, couldn't get below 179 bytes. Bravo. \$\endgroup\$ – Quelklef Aug 3 '17 at 1:49
2
\$\begingroup\$

JavaScript (ES6), 148 142 140 138 137 134 bytes

s=>s.replace(/\d+|./g,_=>~(i='NESW'.search(_))?d=i:~(i='URDL'.search(_))?d+=i:a[d&3]+=+_,a=[0,0,0,0])&&Math.hypot(a[1]-a[3],a[0]-a[2])

f=

s=>s.replace(/\d+|./g,_=>~(i='NESW'.search(_))?d=i:~(i='URDL'.search(_))?d+=i:a[d&3]+=+_,a=[0,0,0,0])&&Math.hypot(a[1]-a[3],a[0]-a[2])

for(test of [
  'N10',
  'N10E10',
  'N10S10',
  'NSEWUDLR10',
  'N100RR20E300D40L12',
  'ERR10LL20UN30D100',
]) console.log(f(test))

-2 bytes: Use .search() instead of .indexOf() (@Shaggy)

-1 byte: Rearrange program to remove enclosing parentheses (@Shaggy)

-3 bytes: Use .replace() instead of .match().map() (@ThePirateBay)

\$\endgroup\$
  • \$\begingroup\$ We're getting different answers for the second-to-last test. \$\endgroup\$ – Quelklef Aug 2 '17 at 18:14
  • \$\begingroup\$ @Quelklef Fixed. \$\endgroup\$ – darrylyeo Aug 2 '17 at 18:18
  • \$\begingroup\$ Can you save a couple of bytes using search instead of indexOf? \$\endgroup\$ – Shaggy Aug 2 '17 at 18:36
  • \$\begingroup\$ I think you can also save a byte by moving a into the map, replacing the , before Math with && and removing the enclosing parentheses. \$\endgroup\$ – Shaggy Aug 2 '17 at 18:40
  • \$\begingroup\$ @Shaggy Awesome, thanks! \$\endgroup\$ – darrylyeo Aug 2 '17 at 18:45
0
\$\begingroup\$

Perl 5, 149 + 1 (-p) = 150 bytes

while(s/(\D+)(\d+)//){$p=/N/?0:/E/?1:/S/?2:/W/?3:/L/?$p-1:/R/?$p+1:/D/?$p+2:$p for split//,$1;$m[$p%4]+=$2}$_=sqrt(($m[0]-$m[2])**2+($m[1]-$m[3])**2)

Try it online!

Explained:

# Each direction is assigned a number:
#
#     0     North
#     1     East
#     2     South
#     3     West
#
# Variables:
#     $p     present direction
#     @m     total movement in each direction
# Inside loop:
#     $1     a set of direction instructions
#     $2     distance

while(s/(\D+)(\d+)//)    # Remove and preserve the first direction set and distance
   for split//,$1        # Loop through individual letters to set new direction
      $p=/N/?0:          # North
         /E/?1:          # South
         /S/?2:          # East
         /W/?3:          # West
         /L/?$p-1:       # Turn left
         /R/?$p+1:       # Turn right
         /D/?$p+2:       # Turn around
         $p              # Do not change direction
   $m[$p%4]+=$2          # Add the directional movement to previous movements

   $_=sqrt(              # Calculate distance
       ($m[0]-$m[2])**2  # Net North/South movement
      +($m[1]-$m[3])**2  # Net East/West movement
      )
\$\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.