| Bytes | Lang | Time | Link |
|---|---|---|---|
| 038 | Jelly | 250410T233954Z | Jonathan |
| 102 | Ruby | 250405T201606Z | Level Ri |
| 057 | Charcoal | 250404T115314Z | Neil |
| 104 | JavaScript Node.js | 250404T065416Z | l4m2 |
Jelly, 38 bytes
“¢ṭ⁴×tṭ‘Ä©⁸ịðiị⁽BgDݤṃ“FRB”ṄȧƲị®œ?⁸ðƒ®
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).
How?
Permute some permutation indices :)
“¢ṭ⁴×tṭ‘Ä©⁸ịðiị⁽BgDݤṃ“FRB”ṄȧƲị®œ?⁸ðƒ® - 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
⁸ị - 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
œ?⁸ - permutation of {Current} at {that} index -> Next
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}}
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}}
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.)
Charcoal, 57 bytes
≔⭆⁶⊕ιηFS«§⪪”&↓⎇\`ï≧ξ,⁸” ⌕ηι→≔⭆§⪪”←⧴◨¡C·κ<B✂9S!ⅈ¿” ⌕ηι§ηIκη
Try it online! Link is to verbose version of code. Explanation:
≔⭆⁶⊕ιη
Start with the six digits.
FS«
Loop over the input.
§⪪”&↓⎇\`ï≧ξ,⁸” ⌕ηι→
Output the move that will bring the ant to the desired digit.
≔⭆§⪪”←⧴◨¡C·κ<B✂9S!ⅈ¿” ⌕ηι§η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⭆⁶⊕ιω⟧FυFEE∧¬ⅈFBR⟦§ι⁰⭆§⪪”)⊟}↓&≕G*”⁶λ§§ι¹Iμ⁺§ι²κ⟧⎇⌕§ι⁰§§κ¹¦⁰κEκ§⟦Φμπμ⁺μ ⟧ν¿⌊κ⊞υκ⊟κ
Try it online! Link is to verbose version of code. Outputs a trailing space. Explanation:
⊞υ⟦S⭆⁶⊕ιω⟧Fυ
Start a breadth-first search with the input as the faces left to visit, the current die position, and the moves taken.
FEE∧¬ⅈFBR⟦§ι⁰⭆§⪪”)⊟}↓&≕G*”⁶λ§§ι¹Iμ⁺§ι²κ⟧⎇⌕§ι⁰§§κ¹¦⁰κ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.
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)
Never turn left. It's useless.