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

4 Answers 4

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\$
9
  • \$\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\$ Aug 2, 2017 at 21:42
  • \$\begingroup\$ @JonathanAllan Nice tricks! Thanks! \$\endgroup\$
    – hyper-neutrino
    Aug 3, 2017 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\$ Aug 3, 2017 at 1:25
  • \$\begingroup\$ @JonathanAllan Hey cool, thanks! \$\endgroup\$
    – hyper-neutrino
    Aug 3, 2017 at 1:35
  • \$\begingroup\$ Tried my own hand at a Python answer, couldn't get below 179 bytes. Bravo. \$\endgroup\$
    – Quelklef
    Aug 3, 2017 at 1:49
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\$
2
  • \$\begingroup\$ What's "(Go)Ruby"? \$\endgroup\$ Aug 3, 2017 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, 2017 at 8:28
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\$
7
  • \$\begingroup\$ We're getting different answers for the second-to-last test. \$\endgroup\$
    – Quelklef
    Aug 2, 2017 at 18:14
  • \$\begingroup\$ @Quelklef Fixed. \$\endgroup\$
    – darrylyeo
    Aug 2, 2017 at 18:18
  • \$\begingroup\$ Can you save a couple of bytes using search instead of indexOf? \$\endgroup\$
    – Shaggy
    Aug 2, 2017 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, 2017 at 18:40
  • \$\begingroup\$ @Shaggy Awesome, thanks! \$\endgroup\$
    – darrylyeo
    Aug 2, 2017 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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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