12
\$\begingroup\$

An ant needs help moving around specific faces on a 6 sided die in order. Write a program or function which, given a series of numbers between 1 and 6, outputs the shortest set of instructions to travel to those faces around the die.

The face with the 1 is towards you, the 2 is on top, and the 3 is to your right. (This is a left-handed die.) Faces 1 and 6, 2 and 5, and 3 and 4 are opposite. The faces are laid out like this:

 5
 6
 2
413

The ant always begins on the 1 face, facing up, towards the 2.

To get to the 2 face, it needs to go Forward. To get to the 5 face from there, it would need to go Forward twice. To get to the 3 face from there, it would need to turn Right, then Forward. To get back to the 5, it would need to move Backward. (Moving backward is shorter than turning twice then moving forward).

Thus, given an input of 2,5,3,5 the instructions required are F,FF,RF,B. Notice how the instructions are grouped for each destination. (F,BB,RF,B is another correct solution, as are F,FF,LB,F and F,BB,LB,F. The sample data prefers F over B when both are possible.)

Input

A series of 1 or more integers in the range 1-6, in any format you like. You can use 0-5 if you prefer. Each face will be different from the previous, and the first input face is not 1 (since the ant starts at 1). (If you want, you can have the input always include an extra 1 at the start, as the starting face.)

Output

A series of delimited sets of instructions, where each instruction is one of R (right), L (left), F (forward), B (backward). You can output these in any format you like, so long as there is a clear grouping. So [['F'], ['F','F'],['R','F']] would be acceptable, as well as F;F F;R F or f\nff\nrf. Lowercase is fine. Extra whitespace is fine. Using characters other than /[FRLBfrlb]/ to indicate directions is not allowed.

Challenge

This is code golf. Standard rules apply.

Sample data

  • 2535 => F FF RF B
  • 616 => FF FF FF
  • 35421 => RF RF F F RF
  • 654321 => FF F LF FF B LF
  • 2131415161 => F B RF B B F RF B FF FF

Related questions involving ants and cubes

asked Apr 3 at 23:43
\$\endgroup\$
12
  • 1
    \$\begingroup\$ Btw, for anyone considering this: I'm finding this deceptively difficult. It sounds straightforward, but I can't even figure out a data structure to solve this, even without golfing. \$\endgroup\$ Commented Apr 4 at 0:17
  • \$\begingroup\$ Dice problem to Steve: youtu.be/t-tRErs5UcI?si=cpeA9ghCn6I-g3_S&t=22 \$\endgroup\$ Commented Apr 4 at 3:54
  • 1
    \$\begingroup\$ Your last test case is missing the final instruction (either FF or BB). \$\endgroup\$ Commented Apr 4 at 11:17
  • 2
    \$\begingroup\$ @KevinCruijssen I specified you were facing right \$\endgroup\$ Commented Apr 4 at 16:32
  • 1
    \$\begingroup\$ @Jonah Ah, Indeed you did. My bad.. \$\endgroup\$ Commented Apr 5 at 11:13

4 Answers 4

9
\$\begingroup\$

JavaScript (Node.js), 104 bytes

x=>x.map(g=t=>t-H?([H,F]=t-F?t+R-7&&t-R?[7-F,H,'B']:[H,R,'R',R=7-F]:[F,7-H,'F'])[2]+g(t):'',H=1,F=2,R=3)

Try it online!

Never turn left. It's useless.

answered Apr 4 at 6:54
\$\endgroup\$
1
  • \$\begingroup\$ Wow, very impressive! \$\endgroup\$ Commented Apr 4 at 7:34
4
\$\begingroup\$

Charcoal, 57 bytes

≔⭆6⊕ιηFS«§⪪"&↓⎇\`ï≧ξ,8" ⌕ηι→≔⭆§⪪"←⧴◨¡C·κ<B✂9S!i¿" ⌕ηι§ηIκη

Try it online! Link is to verbose version of code. Explanation:

≔⭆6⊕ιη

Start with the six digits.

FS«

Loop over the input.

§⪪"&↓⎇\`ï≧ξ,8" ⌕ηι→

Output the move that will bring the ant to the desired digit.

≔⭆§⪪"←⧴◨¡C·κ<B✂9S!i¿" ⌕ηι§ηIκη

Update the ant's position and direction.

As far as I can tell, local optimal is also global optimal. In any given position, F and B can only allow you to visit four of the six digits; you'll need to turn to reach the other two, which you might as well do immediately as the best that taking an extra F or B can do is to save you a single turn later on. For example, 32 might as well be RF LF as FRF B is the same length. But just in case you aren't convinced, I wrote a program that definitively finds the globally optimal solution, although it is 50% longer, and a lot slower of course:

⊞υ⟦S⭆6⊕ιω⟧FυFEE∧¬iFBR⟦§ι0⭆§⪪")⊟}↓&≕G*"6λ§§ι1Iμ+§ι2κ⟧⎇⌕§ι0§§κ1¦0κEκ§⟦Φμπμ+μ ⟧ν¿⌊κ⊞υκ⊟κ

Try it online! Link is to verbose version of code. Outputs a trailing space. Explanation:

⊞υ⟦S⭆6⊕ιω⟧Fυ

Start a breadth-first search with the input as the faces left to visit, the current die position, and the moves taken.

FEE∧¬iFBR⟦§ι0⭆§⪪")⊟}↓&≕G*"6λ§§ι1Iμ+§ι2κ⟧⎇⌕§ι0§§κ1¦0κEκ§⟦Φμπμ+μ ⟧ν

If no solution has been found, then for each of the moves FBR (L isn't needed, as you can just flip all of the letters starting at that L, e.g. FF F LF can be FF F RB), calculate the new die position, and then remove the next face if possible.

¿⌊κ⊞υκ⊟κ

If this is not a solution then add it to the search list otherwise print the moves taken.

answered Apr 4 at 11:53
\$\endgroup\$
2
  • \$\begingroup\$ Hmm... I don't follow the logic in the closing paragraph. 32 are neighboring faces, so one move should be enough. Did you mean an implicit 1 as in 132? For 32, the routes for the four orientations would seem to be F, B, RF and LF|RB. I cannot see how RF LF and F RF B would be the same length? \$\endgroup\$ Commented Apr 4 at 13:07
  • \$\begingroup\$ @doubleunary I meant 32 as an input, so yes, the 1 is implicit. \$\endgroup\$ Commented Apr 4 at 14:59
4
\$\begingroup\$

Ruby, 102 bytes

->i{x,y,z=1,2,3
i.map{|j|k=s="";(x,y=y,7-x;k+=?F;k[3]&&(y,z,s,k=z,7-y,?R,""))while x!=j;s+=k[2]??B:k}}

Try it online!

6 bytes saved with help from l4m2.

Ruby, 108 bytes

->i{x,y,z=1,2,3
i.map{|j|j-=j/4*7;k=s="";z*z==j*j&&(y,z,s=z,-y,?R);(x,y=y,-x;k+=?F)while x!=j;s+=k[2]??B:k}}

Try it online!

A function taking an array of face numbers and returning an array of strings. Will also handle repeat numbers in the input - If the current face is in the input, an empty string is returned.

The dice is represented by the vector x,y,z which initially contains 1,2,3 containing the top, front and right sides. If the desired face is to the left or right, we rotate about the x axis y,z=z,-y (always to the right.) Then we rotate forward about the z axis x,y=y,-x until the desired face is on top. If the number of rotations is more than 2 we output B otherwise we output the relevant number of Fs.

Faces j other than 1,2,3 are represented by j-7 and are therefore -3,-2,-1 for 4,5,6. A vector with x=-1 means that the 1 face is on the bottom so the 6 face represented by -1 is on top.

There are some similarities between l4m2 's code and mine but I'm not sure if they are using the same approach.

commented code

->i{x,y,z=1,2,3 #set up vector x,y,z with start position
i.map{|j| #iterate j through elements in input array i 
j-=j/4*7 #if j=4,5,6 subtract 7 to convert to -3,-2,-1
k=s="" #setup 2 empty strings: s for right turns, k for forward
z*z==j*j&&(y,z,s=z,-y,?R) #if desired face is right or left (magnitude of j and z is equal) rotate right and s="R"
(x,y=y,-x;k+=?F)while x!=j #rotate forward until desired face on top. Add "F" to k each time
s+=k[2]??B:k} #final value is s (either "R" or "") with k appended. If k has more than 2 F's append "B" instead.
} #return with the value returned by .map (the final values of each iteration.)
answered Apr 5 at 20:16
\$\endgroup\$
2
  • \$\begingroup\$ Is cost of j-=j/4*7 lower than treating them as 4-6? \$\endgroup\$ Commented Apr 7 at 0:33
  • \$\begingroup\$ @l4m2 Thanks, your comment is timely, because I was thinking about losing the initial check to see if the desired cell was on the side and simply go forward 4 times (and if that fails rotate right.) Doing that alone would have increased my code by 1 byte. I'm not sure how I would have done that initial check without j-=j/4, but making both changes together saves 6 bytes. On another note, your answer is impressive but I'm still not sure exactly how your code works. \$\endgroup\$ Commented Apr 7 at 18:57
1
\$\begingroup\$

Jelly, 38 bytes

×ばつtṭ‘Ä©8ịðiị(BgDݤṃ"FRB"ṄȧƲị®œ?8ðƒ®

A monadic Link that accepts a list of face numbers (not starting with 1 and without any equal neighbours) and prints to stdout as a side effect (and yields a list of numbers, which may be ignored).

Try it online!

How?

Permute some permutation indices :)

×ばつtṭ‘Ä©8ịðiị(BgDݤṃ"FRB"ṄȧƲị®œ?8ðƒ® - Link: list of integers, Faces×ばつtṭ‘ - code page indices -> [1,224,132,17,116,224]
 Ä - cumulative sums -> [1,225,357,374,490,714]
 = the permutation indices of:
 [no-op, F, RF, RB, B, FF] from [1,2,3,4,5,6]
 © - ...and copy that to the register
 8ị - Faces indexed into {that} -> P
 ð ðƒ® - starting with the register, reduce P by - f(Current, PValue):
 i - 1-index of {PValue} in {Current}
 Ʋ - last four links as a monad - SideEffect(X=that):
 ị - 1-index {X} into:
 ¤ - nilad followed by links as a nilad
 (Bg - 17604
 D - to decimal -> [1,7,6,0,4]
 Ż - prefix with a zero -> [0,1,7,6,0,4]
 ṃ"FRB" - convert to base three with digits 120 as FRB
 Ṅ - print {that} to stdout and yield {that}
 ȧ - {that} logical AND {X} -> X
 ị® - 1-index {X} into the register
 œ?8 - permutation of {Current} at {that} index -> Next
answered Apr 10 at 23:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.