12
\$\begingroup\$

TL;DR: Given an array of chars and a robot in a starting position of the array, write an algorithm than can read a string with movements (F for "go forward", R for "rotate 90 degrees right" and L for "rotate 90 degrees left") and calculate the ending position of the robot. More details in the complete text.

We have at home a very simple programmable device for kids: a small vehicle with buttons to make the vehicle go forward, turn 90 degrees left or turn 90 degrees right. Something similar to this:

Mouse vehicle

We also have a foam mat with letters like this:

Playing mat

The purpose of all this is to teach the kids both the alphabet and the rudiments of programming, all at once.

The challenge

Suppose we have randomly arranged our foam mat like this:

+---+---+---+---+---+---+---+
| E | R | L | B | I | X | N |
+---+---+---+---+---+---+---+
| O | A | Q | Y | C | T | G |
+---+---+---+---+---+---+---+
| F | W | H | P | D | Z | S |
+---+---+---+---+---+---+---+
    | K | V | U | M | J |   
    +---+---+---+---+---+
            |   |
            +---+

Suppose also we have modified the vehicle so that when we program a "go forward" command, the vehicle goes forward exactly size of one square in the mat. So, if the vehicle is in the U square and goes north, it stops exactly in the P square.

The instructions are all given to the vehicle before it starts to move, and those are:

  • F: The vehicle goes forward into the next square.
  • R: The vehicle turns 90 degrees right in its place (no further movement).
  • L: The vehicle turns 90 degrees left in its place (no further movement).

Once the instructions are given, you can press the "GO" button and send the vehicle to a given position as it will follow every instruction in the given order. So, you can tell the kid to insert the needed instructions for the vehicle to go to a given letter.

You must write the shortest program/function that processes a string (input parameter) with a set of instructions and calculates the letter the vehicle stops over (output string).

Details:

  • The vehicle always starts at the blank square at the bottom, and facing north (towards the U square).
  • The input string will contain only the letters F, R, L and G (for the "go" button). You can use lowercase letters for the mat and the instructions, if you prefer so.
  • The algorithm must obey every instruction in the string before the first G (every instruction after that is ignored as the vehicle has started moving).
  • If the vehicle goes out of the mat at any given moment (even if the input string has not been completely processed), the algorithm must return the string Out of mat.
  • If not, the algorithm must return the letter the vehicle has stopped over. The starting point counts as a char (or an empty string).

Examples:

Input: FFG
Output: P

Input: FRFRFG
Output: Out of mat

Input: RRFFG
Output: Out of mat

Input: FFFRFFLFG
Output: X

Input: FFFRFFLF
Output:      <-- Nothing or a whitespace (the robot has not started moving)

Input: FFFRRFFFG
Output:      <-- Nothing or a whitespace (the robot has returned to the starting point)

Input: RRRRRLFFFLFFRFRFGFFRRGRFF
Output: L    (Everything after the first G is ignored)

This is , so may the shortest program for each language win!

\$\endgroup\$
  • 1
    \$\begingroup\$ Next up: same thing, but with the mat configuration as string input, with @ being the starting position and spaces being off the mat, so this config would be ERLBIXN\nOAQYCTG\nFWHPDZS\n KVUMJ \n @ (with different spacing, SE messed it up) \$\endgroup\$ – Stephen Jun 28 '17 at 14:58
3
\$\begingroup\$

JavaScript (ES6), 194 176 169 163 bytes

Saved some bytes thanks to @Luke and @Arnauld.

s=>(p=35,d=3,t='ERLBIXN1OAQYCTG1FWHPDZS11KVUMJ11111 11',[...s].every(i=>i=='L'?d--:i>'Q'?d++:i<'G'?+t[p+=[1,8,-1,-8][d%4]]||!t[p]?p=1/0:p:0)?'':t[p]||'Out of mat')

Ungolfed:

s=>(
  p=35,
  d=3,
  t='ERLBIXN1OAQYCTG1FWHPDZS11KVUMJ11111 11',
  [...s].every(i=>i=='L'?d--:
                  i<'Q'?d++:
                  i<'G'?+t[p+=[1,8,-1,-8][d%4]]||!t[p]?p=1/0:p:
                  0
              )?'':
               t[p]||'Out of mat'
)

f=
s=>(p=35,d=3,t='ERLBIXN1OAQYCTG1FWHPDZS11KVUMJ11111 11',[...s].every(i=>i=='L'?d--:i>'Q'?d++:i<'G'?+t[p+=[1,8,-1,-8][d%4]]||!t[p]?p=1/0:p:0)?'':t[p]||'Out of mat')

console.log(f('FFG')); //P
console.log(f('FRFRFG')); //Out of mat
console.log(f('RRFFG')); //Out of mat
console.log(f('FFFRFFLFG')); //X
console.log(f('FFFRFFLF')); //(space)
console.log(f('FFFRRFFFG')); //(space)
console.log(f('RRRRRLFFFLFFRFRFGFFRRGRFF')); //L
console.log(f('FFFFFRRFG')); //Out of mat

\$\endgroup\$
  • 1
    \$\begingroup\$ You can save 3 bytes by replacing false with !1 \$\endgroup\$ – Luke Jun 28 '17 at 15:11
  • \$\begingroup\$ Thanks, @Luke. I can actually save a bunch of bytes by removing the "G" test altogether. If it's not "L", "R", or "F" it can be assumed to be "G" (unless "G" is missing). Either way, the every method handles it. \$\endgroup\$ – Rick Hitchcock Jun 28 '17 at 15:16
  • \$\begingroup\$ Here's a solution for 165 bytes: (s,p=35,d=3,t='ERLBIXN1OAQYCTG1FWHPDZS11KVUMJ11111 11')=>[...s].every(i=>i=='L'?d--:i=='R'?d++:i=='F'?+t[p+=[1,8,-1,-8][d%4]]||!t[p]?p=1/0:1:0)?'':t[p]||'Out of mat' \$\endgroup\$ – Luke Jun 28 '17 at 15:34
  • \$\begingroup\$ Not sure how that gets me to 165 bytes(?) But I certainly don't need a separate variable for the [1,8,-1,-8] array, thanks! \$\endgroup\$ – Rick Hitchcock Jun 28 '17 at 15:39
  • \$\begingroup\$ Oops, must have miscounted, it's 171. I also removed a space you don't need, which still is in the current answer (it's the last space). \$\endgroup\$ – Luke Jun 28 '17 at 15:40
2
\$\begingroup\$

Python 2, 235 bytes

x=0;y=1;a=4;b=3
p='ERLBIXN','OAQYCTG','FWHPDZS','aKVUMJ','aaa '
r=''
for i in input():
 if'G'==i:r=p[a][b];break
 elif'G'>i:
  b+=x;a-=y;
  if(-1<a<5)-1or(''<p[a][b:]<'a')-1:r='Out of mat';break
 else:x,y=[[y,-x],[-y,x]][i<'R']
print r

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3, 226 231 241 bytes

Second edit; should work now. Again, plenty of optimization to be done.

n=input();s="0ERLBIXN00OAQYCTG00FWHPDZS000KVUMJ000000 00000";d=1;c=40;i=0;w=[-1,-9,1,9]
while n[i]!="G"and c>=0:
 if n[i]=="F":c+=w[d]
 else:d=[d+[-1,3][d<0],-~d%4][n[i]=="R"]
 i+=1
print(["Out of mat",s[c]][c in range(len(s))and s[c]!="0"])

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Wolfram Language/Mathematica, 300 Bytes

p=Re[(1-7I)#[[1]]]&;d=Drop;t=Throw;s=Switch;s[#,0,"Out of mat",_,StringPart["000 0000KVUMJ0FWHPDZSOAQYCTGERLBIXN",p@#]]&@Catch@Fold[If[MemberQ[d[d[Range[4,35],{2,5}],{7}],p@#],#,t@0]&@(s[#2,"F",#+{#[[2]],0},"R",#{1,-I},"L",#{1,I},_,t[#]]&)[#1,#2]&,{4,I},If[StringFreeQ["G"]@#,{"G"},Characters@#]&@#]&

Ungolfed:

p = Re[(1 - 7 I) #[[1]]] &;
d = Drop;
t = Throw;
s = Switch;
s[#,
    0, "Out of mat",
    _, StringPart["000 0000KVUMJ0FWHPDZSOAQYCTGERLBIXN", p@#]] &@
  Catch@
  Fold[
    If[MemberQ[d[d[Range[4, 35], {2, 5}], {7}], p@#], #, 
        t@0] &@(s[#2, "F", # + {#[[2]], 0}, "R", # {1, -I}, 
          "L", # {1, I}, _, t[#]] &)[#1, #2] &,
    {4, I},
    If[StringFreeQ["G"]@#, {"G"}, Characters@#] &@#] &
\$\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.