Solve a Rubik's cube: Difference between revisions

From Rosetta Code
Content added Content deleted
m (capitalized a word.)
m (→‎{{header|Phix}}: syntax coloured)
Line 1,317: Line 1,317:
Uses brute-force (width/highscore-first) Fridrich-steps (ie cross,f2l,oll,pll).<br>
Uses brute-force (width/highscore-first) Fridrich-steps (ie cross,f2l,oll,pll).<br>
Not the fastest (see THRESHOLD) or shortest results (see thistlethwaite) but the code is pretty easy to follow.<br>
Not the fastest (see THRESHOLD) or shortest results (see thistlethwaite) but the code is pretty easy to follow.<br>
The final stage (pll) would probably benefit the most from being replaced with standard algorithms.
The final stage (pll) would probably benefit the most from being replaced with standard algorithms.<br>
While technically this works under pwa/p2js, you should expect a blank screen for nearly 3 minutes.
<lang Phix>--
<!--<lang Phix>(phixonline)-->
-- demo\rosetta\rubik_cfop.exw
<span style="color: #000080;font-style:italic;">--
--
-- demo\rosetta\rubik_cfop.exw
-- Each stage uses a workspace of moves tried so far, ranked by score.
--
-- We repeatedly take the best scoring so far and try more moves, storing
-- those results in a second/new workspace. The THRESHOLD value below
-- Each stage uses a workspace of moves tried so far, ranked by score.
-- We repeatedly take the best scoring so far and try more moves, storing
-- determines the minimum number we should examine before discarding a
-- those results in a second/new workspace. The THRESHOLD value below
-- workspace and switching to the new (one move longer) one. We only ever
-- determines the minimum number we should examine before discarding a
-- switch on change of score, and obviously the first workspace is empty,
-- workspace and switching to the new (one move longer) one. We only ever
-- and the next new workspace has a maximum of 12 entries (+/-90 by 6),
-- switch on change of score, and obviously the first workspace is empty,
-- both of which will force earlier switches.
-- and the next new workspace has a maximum of 12 entries (+/-90 by 6),
--
-- both of which will force earlier switches.
constant THRESHOLD = 100000 -- 100000 -- very slow (100s), best results
--</span>
-- 10000 -- slow (10s), reasonable results
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
-- 1000 -- fast (1s), fairly poor results
<span style="color: #008080;">constant</span> <span style="color: #000000;">THRESHOLD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100000</span> <span style="color: #000080;font-style:italic;">-- 100000 -- very slow (100s), best results
-- 100 -- (counter-productive/slower)
-- 10000 -- 10000 -- slow (10s), reasonable results

-- 1000 -- fast (1s), fairly poor results
string init ="""
-- 100 -- (counter-productive/slower)</span>
_____________---YYY--------
---YYY--------
<span style="color: #004080;">string</span> <span style="color: #000000;">init</span> <span style="color: #0000FF;">=</span><span style="color: #008000;">"""
---YYY--------
---YYY--------
BBBRRRGGGOOO--
---YYY--------
BBBRRRGGGOOO--
---YYY--------
BBBRRRGGGOOO--
BBBRRRGGGOOO--
------WWW-----
BBBRRRGGGOOO--
------WWW-----
BBBRRRGGGOOO--
------WWW-----
------WWW-----
------WWW-----
"""
------WWW-----
-- numbering:
-- 1..15: ---456--------\n
"""</span>
-- 16..30: ---901--------\n -- U
<span style="color: #000080;font-style:italic;">-- numbering:
-- 31..45: ---456--------\n
-- 46..60: 678901234567--\n
-- 1..15: ---456--------\n
-- 61..75: 123456789012--\n -- LFRB
-- 16..30: ---901--------\n -- U
-- 76..90: 678901234567--\n
-- 31..45: ---456--------\n
-- 91..105: ------789-----\n
-- 46..60: 678901234567--\n
-- 106..120:------234-----\n -- D
-- 61..75: 123456789012--\n -- LFRB
-- 121..136:------789-----\n\n
-- 76..90: 678901234567--\n
-- 91..105: ------789-----\n

-- 106..120:------234-----\n -- D
if length(init)!=136 then ?9/0 end if
-- 121..136:------789-----\n\n</span>

--
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">init</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">136</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- TIP: Wrap a cube with blank paper, and write
-- the numbers on it, to derive these sets.
<span style="color: #000080;font-style:italic;">--
--
-- TIP: Wrap a cube with blank paper, and write
constant centres = {20,62,65,68,71,113}
-- the numbers on it, to derive these sets.

--</span>
constant edges = {{ 4, 5, 6,57,56,55}, -- ie YYY/OOO
<span style="color: #008080;">constant</span> <span style="color: #000000;">centres</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">62</span><span style="color: #0000FF;">,</span><span style="color: #000000;">65</span><span style="color: #0000FF;">,</span><span style="color: #000000;">68</span><span style="color: #0000FF;">,</span><span style="color: #000000;">71</span><span style="color: #0000FF;">,</span><span style="color: #000000;">113</span><span style="color: #0000FF;">}</span>
{ 6, 21, 36,54,53,52}, -- YYY/GGG
{ 34, 35, 36,49,50,51}, -- YYY/RRR
<span style="color: #008080;">constant</span> <span style="color: #000000;">edges</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">57</span><span style="color: #0000FF;">,</span><span style="color: #000000;">56</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- ie YYY/OOO</span>
{ 4, 19, 34,46,47,48}, -- YYY/BBB
<span style="color: #0000FF;">{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">21</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">36</span><span style="color: #0000FF;">,</span><span style="color: #000000;">54</span><span style="color: #0000FF;">,</span><span style="color: #000000;">53</span><span style="color: #0000FF;">,</span><span style="color: #000000;">52</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- YYY/GGG</span>
{ 51, 66, 81,52,67,82}, -- RRR/GGG
<span style="color: #0000FF;">{</span> <span style="color: #000000;">34</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">35</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">36</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">50</span><span style="color: #0000FF;">,</span><span style="color: #000000;">51</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- YYY/RRR</span>
{ 54, 69, 84,55,70,85}, -- GGG/OOO
<span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">34</span><span style="color: #0000FF;">,</span><span style="color: #000000;">46</span><span style="color: #0000FF;">,</span><span style="color: #000000;">47</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- YYY/BBB</span>
{ 57, 72, 87,46,61,76}, -- OOO/BBB
<span style="color: #0000FF;">{</span> <span style="color: #000000;">51</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">66</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">81</span><span style="color: #0000FF;">,</span><span style="color: #000000;">52</span><span style="color: #0000FF;">,</span><span style="color: #000000;">67</span><span style="color: #0000FF;">,</span><span style="color: #000000;">82</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- RRR/GGG</span>
{ 48, 63, 78,49,64,79}, -- BBB/RRR
<span style="color: #0000FF;">{</span> <span style="color: #000000;">54</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">69</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">84</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">,</span><span style="color: #000000;">70</span><span style="color: #0000FF;">,</span><span style="color: #000000;">85</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- GGG/OOO</span>
{ 97, 98, 99,82,83,84}, -- WWW/GGG
<span style="color: #0000FF;">{</span> <span style="color: #000000;">57</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">72</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">87</span><span style="color: #0000FF;">,</span><span style="color: #000000;">46</span><span style="color: #0000FF;">,</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span><span style="color: #000000;">76</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- OOO/BBB</span>
{ 99,114,129,85,86,87}, -- WWW/OOO
<span style="color: #0000FF;">{</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">63</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">78</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">64</span><span style="color: #0000FF;">,</span><span style="color: #000000;">79</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- BBB/RRR</span>
{127,128,129,78,77,76}, -- WWW/BBB
<span style="color: #0000FF;">{</span> <span style="color: #000000;">97</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">98</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">99</span><span style="color: #0000FF;">,</span><span style="color: #000000;">82</span><span style="color: #0000FF;">,</span><span style="color: #000000;">83</span><span style="color: #0000FF;">,</span><span style="color: #000000;">84</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- WWW/GGG</span>
{ 97,112,127,81,80,79}} -- WWW/RRR
<span style="color: #0000FF;">{</span> <span style="color: #000000;">99</span><span style="color: #0000FF;">,</span><span style="color: #000000;">114</span><span style="color: #0000FF;">,</span><span style="color: #000000;">129</span><span style="color: #0000FF;">,</span><span style="color: #000000;">85</span><span style="color: #0000FF;">,</span><span style="color: #000000;">86</span><span style="color: #0000FF;">,</span><span style="color: #000000;">87</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- WWW/OOO</span>

<span style="color: #0000FF;">{</span><span style="color: #000000;">127</span><span style="color: #0000FF;">,</span><span style="color: #000000;">128</span><span style="color: #0000FF;">,</span><span style="color: #000000;">129</span><span style="color: #0000FF;">,</span><span style="color: #000000;">78</span><span style="color: #0000FF;">,</span><span style="color: #000000;">77</span><span style="color: #0000FF;">,</span><span style="color: #000000;">76</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- WWW/BBB</span>
constant corners = {{ 4, 57,46},{34,48, 49},{36,51,52},{ 6,54,55},
<span style="color: #0000FF;">{</span> <span style="color: #000000;">97</span><span style="color: #0000FF;">,</span><span style="color: #000000;">112</span><span style="color: #0000FF;">,</span><span style="color: #000000;">127</span><span style="color: #0000FF;">,</span><span style="color: #000000;">81</span><span style="color: #0000FF;">,</span><span style="color: #000000;">80</span><span style="color: #0000FF;">,</span><span style="color: #000000;">79</span><span style="color: #0000FF;">}}</span> <span style="color: #000080;font-style:italic;">-- WWW/RRR</span>
-- YOB/UBL YBR/UFL YRG/UFR YGO/UBL
{76,129,87},{78,79,127},{81,82,97},{84,85,99}}
<span style="color: #008080;">constant</span> <span style="color: #000000;">corners</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">57</span><span style="color: #0000FF;">,</span><span style="color: #000000;">46</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">34</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">49</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span><span style="color: #000000;">51</span><span style="color: #0000FF;">,</span><span style="color: #000000;">52</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">54</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">},</span>
-- BWO/DBL BRW/DFL RGW/DFR GOW/DFL
<span style="color: #000080;font-style:italic;">-- YOB/UBL YBR/UFL YRG/UFR YGO/UBL</span>

<span style="color: #0000FF;">{</span><span style="color: #000000;">76</span><span style="color: #0000FF;">,</span><span style="color: #000000;">129</span><span style="color: #0000FF;">,</span><span style="color: #000000;">87</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">78</span><span style="color: #0000FF;">,</span><span style="color: #000000;">79</span><span style="color: #0000FF;">,</span><span style="color: #000000;">127</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">81</span><span style="color: #0000FF;">,</span><span style="color: #000000;">82</span><span style="color: #0000FF;">,</span><span style="color: #000000;">97</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">84</span><span style="color: #0000FF;">,</span><span style="color: #000000;">85</span><span style="color: #0000FF;">,</span><span style="color: #000000;">99</span><span style="color: #0000FF;">}}</span>
constant facing_corners = {-16,-14,16,14}, -- (nb not 14,16)
<span style="color: #000080;font-style:italic;">-- BWO/DBL BRW/DFL RGW/DFR GOW/DFL</span>
facing_edges = {-15, 1,15,-1},
fce = facing_corners&facing_edges,
<span style="color: #008080;">constant</span> <span style="color: #000000;">facing_corners</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- (nb not 14,16)</span>
rotations = {
<span style="color: #000000;">facing_edges</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
-- up (clockwise):
<span style="color: #000000;">fce</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">facing_corners</span><span style="color: #0000FF;">&</span><span style="color: #000000;">facing_edges</span><span style="color: #0000FF;">,</span>
{{57,54,51,48}, -- clockwise corners
<span style="color: #000000;">rotations</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
{46,55,52,49}, -- anticlockwise corners
{47,56,53,50}}, -- middle edges
<span style="color: #000080;font-style:italic;">-- up (clockwise):</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">57</span><span style="color: #0000FF;">,</span><span style="color: #000000;">54</span><span style="color: #0000FF;">,</span><span style="color: #000000;">51</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- clockwise corners</span>
-- left
<span style="color: #0000FF;">{</span><span style="color: #000000;">46</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">,</span><span style="color: #000000;">52</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- anticlockwise corners</span>
{{ 4,49,127, 87},
<span style="color: #0000FF;">{</span><span style="color: #000000;">47</span><span style="color: #0000FF;">,</span><span style="color: #000000;">56</span><span style="color: #0000FF;">,</span><span style="color: #000000;">53</span><span style="color: #0000FF;">,</span><span style="color: #000000;">50</span><span style="color: #0000FF;">}},</span> <span style="color: #000080;font-style:italic;">-- middle edges
{57,34, 79,129},
{19,64,128, 72}},
-- left</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">127</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">87</span><span style="color: #0000FF;">},</span>
-- front
<span style="color: #0000FF;">{</span><span style="color: #000000;">57</span><span style="color: #0000FF;">,</span><span style="color: #000000;">34</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">79</span><span style="color: #0000FF;">,</span><span style="color: #000000;">129</span><span style="color: #0000FF;">},</span>
{{34,52, 97, 78},
<span style="color: #0000FF;">{</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">64</span><span style="color: #0000FF;">,</span><span style="color: #000000;">128</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">72</span><span style="color: #0000FF;">}},</span>
{48,36, 82,127},
{35,67,112, 63}},
<span style="color: #000080;font-style:italic;">-- front</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">34</span><span style="color: #0000FF;">,</span><span style="color: #000000;">52</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">97</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">78</span><span style="color: #0000FF;">},</span>
-- right
<span style="color: #0000FF;">{</span><span style="color: #000000;">48</span><span style="color: #0000FF;">,</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">82</span><span style="color: #0000FF;">,</span><span style="color: #000000;">127</span><span style="color: #0000FF;">},</span>
{{36,55,99,81},
<span style="color: #0000FF;">{</span><span style="color: #000000;">35</span><span style="color: #0000FF;">,</span><span style="color: #000000;">67</span><span style="color: #0000FF;">,</span><span style="color: #000000;">112</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">63</span><span style="color: #0000FF;">}},</span>
{51, 6,85,97},
{21,70,98,66}},
<span style="color: #000080;font-style:italic;">-- right</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">,</span><span style="color: #000000;">99</span><span style="color: #0000FF;">,</span><span style="color: #000000;">81</span><span style="color: #0000FF;">},</span>
-- back
<span style="color: #0000FF;">{</span><span style="color: #000000;">51</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">85</span><span style="color: #0000FF;">,</span><span style="color: #000000;">97</span><span style="color: #0000FF;">},</span>
{{ 6,46,129,84},
<span style="color: #0000FF;">{</span><span style="color: #000000;">21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">70</span><span style="color: #0000FF;">,</span><span style="color: #000000;">98</span><span style="color: #0000FF;">,</span><span style="color: #000000;">66</span><span style="color: #0000FF;">}},</span>
{54, 4, 76,99},
{ 5,61,114,69}},
<span style="color: #000080;font-style:italic;">-- back</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">46</span><span style="color: #0000FF;">,</span><span style="color: #000000;">129</span><span style="color: #0000FF;">,</span><span style="color: #000000;">84</span><span style="color: #0000FF;">},</span>
-- down
<span style="color: #0000FF;">{</span><span style="color: #000000;">54</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">76</span><span style="color: #0000FF;">,</span><span style="color: #000000;">99</span><span style="color: #0000FF;">},</span>
{{82,85,76,79},
<span style="color: #0000FF;">{</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span><span style="color: #000000;">114</span><span style="color: #0000FF;">,</span><span style="color: #000000;">69</span><span style="color: #0000FF;">}},</span>
{81,84,87,78},
{83,86,77,80}}}
<span style="color: #000080;font-style:italic;">-- down</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">82</span><span style="color: #0000FF;">,</span><span style="color: #000000;">85</span><span style="color: #0000FF;">,</span><span style="color: #000000;">76</span><span style="color: #0000FF;">,</span><span style="color: #000000;">79</span><span style="color: #0000FF;">},</span>

<span style="color: #0000FF;">{</span><span style="color: #000000;">81</span><span style="color: #0000FF;">,</span><span style="color: #000000;">84</span><span style="color: #0000FF;">,</span><span style="color: #000000;">87</span><span style="color: #0000FF;">,</span><span style="color: #000000;">78</span><span style="color: #0000FF;">},</span>
--Up/Left/Front/Right/Back/Down
<span style="color: #0000FF;">{</span><span style="color: #000000;">83</span><span style="color: #0000FF;">,</span><span style="color: #000000;">86</span><span style="color: #0000FF;">,</span><span style="color: #000000;">77</span><span style="color: #0000FF;">,</span><span style="color: #000000;">80</span><span style="color: #0000FF;">}}}</span>
enum U=1,L=2,F=3,/*R=4,*/B=5,D=6,Dbl=#08,Shift=#10
constant U2 = U+Dbl, F2 = F+Dbl, /*R2 = R+Dbl, B2 = B+Dbl,*/ D2 = D+Dbl,
<span style="color: #000080;font-style:italic;">--Up/Left/Front/Right/Back/Down</span>
Us = U+Shift, Fs = F+Shift, Bs = B+Shift, Rs = R+Shift, Ds = D+Shift
<span style="color: #008080;">enum</span> <span style="color: #000000;">U</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">L</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">F</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">R</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">B</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">D</span><span style="color: #0000FF;">=</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">=</span><span style="color: #000000;">#08</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">=</span><span style="color: #000000;">#10</span>

<span style="color: #008080;">constant</span> <span style="color: #000000;">U2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">U</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">F2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">F</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*R2 = R+Dbl, B2 = B+Dbl,*/</span> <span style="color: #000000;">D2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">D</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">,</span>
enum CROSS,F2L,OLL,PLL
<span style="color: #000000;">Us</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">U</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Fs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">F</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Bs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Rs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">R</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Ds</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">D</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Shift</span>

integer f2l = 0 -- (28==done)
<span style="color: #008080;">enum</span> <span style="color: #000000;">CROSS</span><span style="color: #0000FF;">,</span><span style="color: #000000;">F2L</span><span style="color: #0000FF;">,</span><span style="color: #000000;">OLL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PLL</span>
integer edge_score = 0 -- (0..12 for f2l [as U cleared],
-- 0..24 for oll and pll stages)
<span style="color: #004080;">integer</span> <span style="color: #000000;">f2l</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- (28==done)</span>

<span style="color: #004080;">integer</span> <span style="color: #000000;">edge_score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- (0..12 for f2l [as U cleared],
function score(string cube, integer stage)
-- 0..24 for oll and pll stages)</span>
integer res = 0, c, cc, k
f2l = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">)</span>
for i=1 to length(centres) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span>
c = centres[i]
<span style="color: #000000;">f2l</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
cc = cube[c]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">centres</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for j=1 to length(fce) do -- (the 8 next to c)
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">centres</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
k = c+fce[j]
<span style="color: #000000;">cc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
if cube[k]=cc then
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fce</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (the 8 next to c)</span>
res += 1
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">fce</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
f2l += (stage>CROSS and k>=61)
<span style="color: #008080;">if</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">cc</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #000000;">f2l</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">stage</span><span style="color: #0000FF;">></span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">and</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">61</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- give extra credit for edges paired with corners
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
edge_score = 0 -- += (0|1|2) for the 12 edges:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if stage>CROSS then
<span style="color: #000080;font-style:italic;">-- give extra credit for edges paired with corners</span>
for i=1 to length(edges) do
<span style="color: #000000;">edge_score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- += (0|1|2) for the 12 edges:</span>
sequence ei = edges[i] -- as 123
<span style="color: #008080;">if</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">></span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">then</span>
-- -- 456
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
-- then if {1,4}=={2,5} then edge_score += 1,
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ei</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- as 123
-- plus if {2,5}=={3,6} then edge_score += 1.
-- -- 456
edge_score += (cube[ei[1]]=cube[ei[2]] and
cube[ei[4]]=cube[ei[5]]) +
-- then if {1,4}=={2,5} then edge_score += 1,
(cube[ei[2]]=cube[ei[3]] and
-- plus if {2,5}=={3,6} then edge_score += 1.</span>
<span style="color: #000000;">edge_score</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]]=</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]]</span> <span style="color: #008080;">and</span>
cube[ei[5]]=cube[ei[6]])
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]]=</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]])</span> <span style="color: #0000FF;">+</span>
end for
<span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]]=</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]]</span> <span style="color: #008080;">and</span>
end if
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]]=</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]])</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
function oll_score(string cube)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- (should only be invoked if f2l==28)
integer res = 0 -- (true if res=8)
<span style="color: #008080;">function</span> <span style="color: #000000;">oll_score</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">)</span>
integer cu = centres[U]
<span style="color: #000080;font-style:italic;">-- (should only be invoked if f2l==28)</span>
if cube[cu]!='Y' then ?9/0 end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- (true if res=8)</span>
for i=1 to length(fce) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">cu</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">centres</span><span style="color: #0000FF;">[</span><span style="color: #000000;">U</span><span style="color: #0000FF;">]</span>
integer fcei = fce[i]
<span style="color: #008080;">if</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cu</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'Y'</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res += (cube[cu+fcei]='Y')
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fce</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">fcei</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fce</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
return res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cu</span><span style="color: #0000FF;">+</span><span style="color: #000000;">fcei</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
function rotate_face(string cube, integer face)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
--
-- face is 1..6 for clockwise (ULFRBD),
<span style="color: #008080;">function</span> <span style="color: #000000;">rotate_face</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">face</span><span style="color: #0000FF;">)</span>
-- plus #08(Dbl) for a 180 (clockwise),
<span style="color: #000080;font-style:italic;">--
-- plus #10(Shift) for anti-clockwise.
-- face is 1..6 for clockwise (ULFRBD),
--
-- plus #08(Dbl) for a 180 (clockwise),
integer dbl = 1+(and_bits(face,Dbl)=Dbl)
-- plus #10(Shift) for anti-clockwise.
bool cw = 1-floor(face/Shift)
--</span>
face = remainder(face,Dbl)
<span style="color: #004080;">integer</span> <span style="color: #000000;">dbl</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">+(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">)</span>
integer cf = centres[face]
<span style="color: #004080;">bool</span> <span style="color: #000000;">cw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">/</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">)</span>
sequence rf = {sq_add(facing_corners,cf),
<span style="color: #000000;">face</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">)</span>
sq_add(facing_edges,cf)}
<span style="color: #004080;">integer</span> <span style="color: #000000;">cf</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">centres</span><span style="color: #0000FF;">[</span><span style="color: #000000;">face</span><span style="color: #0000FF;">]</span>
&rotations[face]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rf</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">facing_corners</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cf</span><span style="color: #0000FF;">),</span>
for d=1 to dbl do
<span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">facing_edges</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cf</span><span style="color: #0000FF;">)}</span>
for i=1 to length(rf) do
<span style="color: #0000FF;">&</span><span style="color: #000000;">rotations</span><span style="color: #0000FF;">[</span><span style="color: #000000;">face</span><span style="color: #0000FF;">]</span>
sequence rfi = rf[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">dbl</span> <span style="color: #008080;">do</span>
if cw then rfi = reverse(rfi) end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer rfi1 = cube[rfi[1]]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rfi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
for j=1 to 3 do
<span style="color: #008080;">if</span> <span style="color: #000000;">cw</span> <span style="color: #008080;">then</span> <span style="color: #000000;">rfi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rfi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
cube[rfi[j]] = cube[rfi[j+1]]
<span style="color: #004080;">integer</span> <span style="color: #000000;">rfi1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rfi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]]</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
cube[rfi[4]] = rfi1
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rfi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rfi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]]</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rfi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rfi1</span>
return cube
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">cube</span>
function apply_moves(string cube, sequence moves)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
for i=1 to length(moves) do
cube = rotate_face(cube,moves[i])
<span style="color: #008080;">function</span> <span style="color: #000000;">apply_moves</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
return cube
<span style="color: #000000;">cube</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rotate_face</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">cube</span>
constant ULFRBD = "ULFRBD"
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

function moves_to_string(sequence moves)
<span style="color: #008080;">constant</span> <span style="color: #000000;">ULFRBD</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ULFRBD"</span>
-- convert eg {1,20,11} to "UR'F2"
string res = ""
<span style="color: #008080;">function</span> <span style="color: #000000;">moves_to_string</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
integer l = length(moves)
<span style="color: #000080;font-style:italic;">-- convert eg {1,20,11} to "UR'F2"</span>
for i=1 to l do
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
integer face = moves[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
integer dbl = and_bits(face,Dbl)=Dbl
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
bool anticw = floor(face/Shift)
<span style="color: #004080;">integer</span> <span style="color: #000000;">face</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">moves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
face = remainder(face,Dbl)
<span style="color: #004080;">integer</span> <span style="color: #000000;">dbl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">Dbl</span>
res &= ULFRBD[face]
<span style="color: #004080;">bool</span> <span style="color: #000000;">anticw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">/</span><span style="color: #000000;">Shift</span><span style="color: #0000FF;">)</span>
if dbl then
<span style="color: #000000;">face</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">face</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Dbl</span><span style="color: #0000FF;">)</span>
res &= '2'
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ULFRBD</span><span style="color: #0000FF;">[</span><span style="color: #000000;">face</span><span style="color: #0000FF;">]</span>
elsif anticw then
<span style="color: #008080;">if</span> <span style="color: #000000;">dbl</span> <span style="color: #008080;">then</span>
res &= '\''
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'2'</span>
end if
<span style="color: #008080;">elsif</span> <span style="color: #000000;">anticw</span> <span style="color: #008080;">then</span>
end for
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;"><nowiki>'\''</nowiki></span>
res &=sprintf(" (%d move%s) ",{l,iff(l=1?"":"s")})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" (%d move%s) "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
--
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- The seen dictionary.
-- Without this, since it uses a breadth/highscore-first
<span style="color: #000080;font-style:italic;">--
-- algorithm, after f2l (for instance) it would probably
-- The seen dictionary.
-- just do U and U' as the new high scores, forever.
-- Without this, since it uses a breadth/highscore-first
-- (The THRESHOLD constant mitigates that to some extent)
-- algorithm, after f2l (for instance) it would probably
--
-- just do U and U' as the new high scores, forever.
integer seen = new_dict()
-- (The THRESHOLD constant mitigates that to some extent)

--</span>
function solve_stage(string cube, integer stage)
<span style="color: #004080;">integer</span> <span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
atom t1 = time()+1
string moves = "", moves2
<span style="color: #008080;">function</span> <span style="color: #000000;">solve_stage</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">)</span>
sequence workspace, w2,
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
init
<span style="color: #004080;">string</span> <span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">moves2</span>
integer wslen, high = 1,
<span style="color: #004080;">sequence</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">w2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">init</span>
s, c2c = 0, o = 0
<span style="color: #004080;">integer</span> <span style="color: #000000;">wslen</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
bool done
<span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c2c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">o</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>

<span style="color: #004080;">bool</span> <span style="color: #000000;">done</span>
if stage=CROSS then
--
<span style="color: #008080;">if</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">then</span>
-- first, blank out all corners, and
<span style="color: #000080;font-style:italic;">--
-- all edges without a white on them.
--
-- first, blank out all corners, and
-- all edges without a white on them.
for i=1 to length(rotations) do
for j=1 to 2 do -- (just corners)
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rotations</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for k=1 to 4 do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (just corners)</span>
cube[rotations[i][j][k]]='-'
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rotations</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]]=</span><span style="color: #008000;">'-'</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to length(edges) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer {?,m1,?,?,m2,?} = edges[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if cube[m1]!='W'
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{?,</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">,?,?,</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">,?}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
and cube[m2]!='W' then
<span style="color: #008080;">if</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'W'</span>
cube[m1] = '-'
<span style="color: #008080;">and</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'W'</span> <span style="color: #008080;">then</span>
cube[m2] = '-'
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end if
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
wslen = 8
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
s = score(cube,CROSS)
<span style="color: #000000;">wslen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">8</span>
done = (s=8)
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">CROSS</span><span style="color: #0000FF;">)</span>
elsif stage=F2L then
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
--
<span style="color: #008080;">elsif</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">F2L</span> <span style="color: #008080;">then</span>
-- first, blank out all pieces with a yellow
<span style="color: #000080;font-style:italic;">--
--
-- first, blank out all pieces with a yellow
for i=1 to length(corners) do
integer {c1,c2,c3} = corners[i]
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">corners</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if cube[c1]='Y'
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">corners</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
or cube[c2]='Y'
<span style="color: #008080;">if</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span>
or cube[c3]='Y' then
<span style="color: #008080;">or</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span>
cube[c1] = '-'
<span style="color: #008080;">or</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span> <span style="color: #008080;">then</span>
cube[c2] = '-'
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
cube[c3] = '-'
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end if
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=1 to length(edges) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer {?,m1,?,?,m2,?} = edges[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if cube[m1]='Y'
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{?,</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">,?,?,</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">,?}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
and cube[m2]='Y' then
<span style="color: #008080;">if</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span>
cube[m1] = '-'
<span style="color: #008080;">and</span> <span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'Y'</span> <span style="color: #008080;">then</span>
cube[m2] = '-'
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end if
<span style="color: #000000;">cube</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'-'</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
wslen = 57+12
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
s = score(cube,F2L)
<span style="color: #000000;">wslen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">57</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span>
done = (f2l=28)
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">F2L</span><span style="color: #0000FF;">)</span>
else
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">f2l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">28</span><span style="color: #0000FF;">)</span>
wslen = 77+24
<span style="color: #008080;">else</span>
s = score(cube,stage)
<span style="color: #000000;">wslen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">77</span><span style="color: #0000FF;">+</span><span style="color: #000000;">24</span>
if f2l!=28 then ?9/0 end if
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">stage</span><span style="color: #0000FF;">)</span>
if stage=OLL then
<span style="color: #008080;">if</span> <span style="color: #000000;">f2l</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">28</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
done = (oll_score(cube)=8)
<span style="color: #008080;">if</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">OLL</span> <span style="color: #008080;">then</span>
else -- (stage=PLL)
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">oll_score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
done = (s=48)
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- (stage=PLL)</span>
end if
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">48</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if not done then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
workspace = repeat({},wslen)
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">done</span> <span style="color: #008080;">then</span>
w2 = workspace
<span style="color: #000000;">workspace</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">wslen</span><span style="color: #0000FF;">)</span>
init = cube
<span style="color: #000000;">w2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">workspace</span><span style="color: #0000FF;">)</span>
workspace[high] = {""}
<span style="color: #000000;">init</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cube</span>
destroy_dict(seen,justclear:=1)
<span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}</span>
integer move_count = 1
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">justclear</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
while 1 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">move_count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
if workspace[high]={} then
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
while high and workspace[high]={} do high -= 1 end while
<span style="color: #008080;">if</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">]={}</span> <span style="color: #008080;">then</span>
if high=0 or (stage!=CROSS and c2c>THRESHOLD) then
<span style="color: #008080;">while</span> <span style="color: #000000;">high</span> <span style="color: #008080;">and</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">]={}</span> <span style="color: #008080;">do</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
move_count += 1
<span style="color: #008080;">if</span> <span style="color: #000000;">high</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">stage</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c2c</span><span style="color: #0000FF;">></span><span style="color: #000000;">THRESHOLD</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
workspace = w2
<span style="color: #000000;">move_count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
w2 = repeat({},wslen)
<span style="color: #000000;">workspace</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w2</span>
c2c = 0
<span style="color: #000000;">w2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">wslen</span><span style="color: #0000FF;">)</span>
high = wslen
<span style="color: #000000;">c2c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
while workspace[high]={} do high -= 1 end while
<span style="color: #000000;">high</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">wslen</span>
end if
<span style="color: #008080;">while</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">]={}</span> <span style="color: #008080;">do</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
moves = workspace[high][1]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
workspace[high] = workspace[high][2..$]
<span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
cube = apply_moves(init,moves)
<span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">workspace</span><span style="color: #0000FF;">[</span><span style="color: #000000;">high</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
for face=U to D do
<span style="color: #000000;">cube</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">apply_moves</span><span style="color: #0000FF;">(</span><span style="color: #000000;">init</span><span style="color: #0000FF;">,</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
-- (originally this loop did 180s as well, but that
<span style="color: #008080;">for</span> <span style="color: #000000;">face</span><span style="color: #0000FF;">=</span><span style="color: #000000;">U</span> <span style="color: #008080;">to</span> <span style="color: #000000;">D</span> <span style="color: #008080;">do</span>
-- gave them far too much dominance, esp during pll.
-- instead we now coalese those that survive a 90.)
<span style="color: #000080;font-style:italic;">-- (originally this loop did 180s as well, but that
for m=0 to Shift by Shift do
-- gave them far too much dominance, esp during pll.
integer mi = face+m
-- instead we now coalese those that survive a 90.)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">Shift</span> <span style="color: #008080;">by</span> <span style="color: #000000;">Shift</span> <span style="color: #008080;">do</span>
sequence cube2 = rotate_face(cube,mi)
<span style="color: #004080;">integer</span> <span style="color: #000000;">mi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">face</span><span style="color: #0000FF;">+</span><span style="color: #000000;">m</span>
if getd_index(cube2,seen)=0 then
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cube2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rotate_face</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mi</span><span style="color: #0000FF;">)</span>
putd(cube2,0,seen)
<span style="color: #008080;">if</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
s = score(cube2,stage)
<span style="color: #7060A8;">putd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">)</span>
if stage=CROSS then
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">stage</span><span style="color: #0000FF;">)</span>
done = (s=8)
<span style="color: #008080;">if</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">then</span>
elsif stage=F2L then
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
done = (f2l=28)
<span style="color: #008080;">elsif</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">F2L</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">f2l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">28</span><span style="color: #0000FF;">)</span>
if f2l=28 then
o = oll_score(cube2)
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">f2l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">28</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">o</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">oll_score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube2</span><span style="color: #0000FF;">)</span>
o = 0
end if
<span style="color: #008080;">else</span>
if stage=OLL then
<span style="color: #000000;">o</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
done = (o=8)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">OLL</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">=</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
done = (s=48)
end if
<span style="color: #008080;">else</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">48</span><span style="color: #0000FF;">)</span>
end if
moves2 = moves
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if length(moves2) and moves2[$]=mi then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
moves2[$] = face+Dbl
<span style="color: #000000;">moves2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">moves</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">moves2</span><span style="color: #0000FF;">[$]=</span><span style="color: #000000;">mi</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">moves2</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">face</span><span style="color: #0000FF;">+</span><span style="color: #000000;">Dbl</span>
moves2 &= mi
end if
<span style="color: #008080;">else</span>
<span style="color: #000000;">moves2</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">mi</span>
if done then
destroy_dict(seen,justclear:=1)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">done</span> <span style="color: #008080;">then</span>
return moves2
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">justclear</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
end if
s += 1+edge_score*2+o
<span style="color: #008080;">return</span> <span style="color: #000000;">moves2</span>
w2[s] = append(w2[s],moves2)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">+</span><span style="color: #000000;">edge_score</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">o</span>
c2c += 1
<span style="color: #000000;">w2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">],</span><span style="color: #000000;">moves2</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">c2c</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if time()>t1 then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"working... %d moves, %d positions\r",{move_count,dict_size(seen)})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()></span><span style="color: #000000;">t1</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
t1 = time()+1
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"working... %d moves, %d positions\r"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">move_count</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">dict_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">)})</span>
if get_key()=#1B then exit end if
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
end if
<span style="color: #008080;">if</span> <span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">()=</span><span style="color: #000000;">#1B</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return "" -- (already solved case)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- (already solved case)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant stage_desc = { "make cross",
"solve first two layers",
<span style="color: #008080;">constant</span> <span style="color: #000000;">stage_desc</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #008000;">"make cross"</span><span style="color: #0000FF;">,</span>
"orientate last layer",
"permute last layer" }
<span style="color: #008000;">"solve first two layers"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"orientate last layer"</span><span style="color: #0000FF;">,</span>

<span style="color: #008000;">"permute last layer"</span> <span style="color: #0000FF;">}</span>
procedure main()
string cube
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
sequence moves
<span style="color: #004080;">string</span> <span style="color: #000000;">cube</span>
integer total_moves = 0
<span style="color: #004080;">sequence</span> <span style="color: #000000;">moves</span>
atom t0 = time()
<span style="color: #004080;">integer</span> <span style="color: #000000;">total_moves</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>

<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
-- "hardest case" from http://www.cube20.org
moves = {F, Us, F2, Ds, B, U, Rs, Fs, L, Ds,
<span style="color: #000080;font-style:italic;">-- "hardest case" from http://www.cube20.org</span>
Rs, Us, L, U, Bs, D2, Rs, F, U2, D2}
<span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">F</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Us</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">F2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Ds</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">U</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Rs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Fs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">L</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Ds</span><span style="color: #0000FF;">,</span>
cube = apply_moves(init,moves)
<span style="color: #000000;">Rs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Us</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">L</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">U</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Bs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">D2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Rs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">F</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">U2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">D2</span><span style="color: #0000FF;">}</span>
if length(moves)<=20 then
<span style="color: #000000;">cube</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">apply_moves</span><span style="color: #0000FF;">(</span><span style="color: #000000;">init</span><span style="color: #0000FF;">,</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
printf(1,"scramble: %s\n",{moves_to_string(moves)})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">20</span> <span style="color: #008080;">then</span>
end if
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"scramble: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">moves_to_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)})</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
puts(1,substitute(cube,"-"," "))

<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
for stage=CROSS to PLL do
moves = solve_stage(cube, stage)
<span style="color: #008080;">for</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">=</span><span style="color: #000000;">CROSS</span> <span style="color: #008080;">to</span> <span style="color: #000000;">PLL</span> <span style="color: #008080;">do</span>
total_moves += length(moves)
<span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">solve_stage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">stage</span><span style="color: #0000FF;">)</span>
cube = apply_moves(cube,moves)
<span style="color: #000000;">total_moves</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
printf(1,"%s: %s\n",{stage_desc[stage],moves_to_string(moves)})
<span style="color: #000000;">cube</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">apply_moves</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span>
if length(moves) then
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">stage_desc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">stage</span><span style="color: #0000FF;">],</span><span style="color: #000000;">moves_to_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)})</span>
puts(1,substitute(cube,"-"," "))
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cube</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"\nsolution of %d total moves found in %3.2fs\n",{total_moves,time()-t0})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsolution of %d total moves found in %3.2fs\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">total_moves</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
main()</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
{{Out}}
{{Out}}
The "hardest case" from http://www.cube20.org with a high threshold. You can try this manually.
The "hardest case" from http://www.cube20.org with a high threshold. You can try this manually.
Line 1,771: Line 1,774:
Translation/de-golf(hrumph) of Tomas Sirgedas' winning entry from http://tomas.rokicki.com/cubecontest as held in 2004.<br>
Translation/de-golf(hrumph) of Tomas Sirgedas' winning entry from http://tomas.rokicki.com/cubecontest as held in 2004.<br>
Faster and shorter solutions (in most cases) than cfop, however probably nigh on impossible to debug/enhance...
Faster and shorter solutions (in most cases) than cfop, however probably nigh on impossible to debug/enhance...
<lang Phix>--
<!--<lang Phix>(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\rubik_tomas.exw
-- demo\rosetta\rubik_tomas.exw
--
--</span>
function xor_string(string s)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
return xor_bits(s[1],xor_bits(s[2],iff(length(s)=3?s[3]:'!')))
<span style="color: #008080;">function</span> <span style="color: #000000;">xor_string</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">?</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]:</span><span style="color: #008000;">'!'</span><span style="color: #0000FF;">)))</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function xor_all(sequence s)
for i=1 to length(s) do
<span style="color: #008080;">function</span> <span style="color: #000000;">xor_all</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
s[i] = xor_string(s[i])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xor_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
return s
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant d1 = xor_all(split("UF DF UB DB UR DR UL DL FR FL BR BL UFR DBR UBL DFL DLB ULF DRF URB"))
-- This is Mike Reid's notation, 12 sides then 8 corners, which may be rotated - hence we xor the
<span style="color: #008080;">constant</span> <span style="color: #000000;">d1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xor_all</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"UF DF UB DB UR DR UL DL FR FL BR BL UFR DBR UBL DFL DLB ULF DRF URB"</span><span style="color: #0000FF;">))</span>
-- characters for fast lookup. The above string represents a cube in the solved state.
<span style="color: #000080;font-style:italic;">-- This is Mike Reid's notation, 12 sides then 8 corners, which may be rotated - hence we xor the

-- characters for fast lookup. The above string represents a cube in the solved state.</span>
constant d2 = {18,12,17,15,0, 9,1,8,16,14,19,13,2,10,3,11,12,18,13,19,4,8,5,10,
14,16,15,17,6,11,7,9,17,12,19,14,6, 0,4, 2,18,15,16,13,1,7,3, 5}
<span style="color: #008080;">constant</span> <span style="color: #000000;">d2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span>
--?sort(d2): (0..11 appear twice, 12..19 appear thrice - edges/corners is pretty much all I can say)
<span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">}</span>

<span style="color: #000080;font-style:italic;">--?sort(d2): (0..11 appear twice, 12..19 appear thrice - edges/corners is pretty much all I can say)</span>
constant d3 = {13,16,15,1,3,
19,18,17,4,6}
<span style="color: #008080;">constant</span> <span style="color: #000000;">d3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span>
-- these apppear to be swapped during initialisation, dunno why...
<span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}</span>

<span style="color: #000080;font-style:italic;">-- these apppear to be swapped during initialisation, dunno why...</span>
integer cur_phase, search_mode, history_idx
sequence history_mov = repeat(0,48),
<span style="color: #004080;">integer</span> <span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">search_mode</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">history_idx</span>
history_rpt = repeat(0,48),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">history_mov</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">),</span>
depth_to_go,
<span style="color: #000000;">history_rpt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">),</span>
hash_table = repeat(repeat(6,6912),48)
<span style="color: #000000;">depth_to_go</span><span style="color: #0000FF;">,</span>
-- (hash_table can/should be preserved for different problems)
<span style="color: #000000;">hash_table</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6912</span><span style="color: #0000FF;">),</span><span style="color: #000000;">48</span><span style="color: #0000FF;">)</span>

<span style="color: #000080;font-style:italic;">-- (hash_table can/should be preserved for different problems)</span>
sequence cubelet_pos = repeat(0,48),
cubelet_twi = repeat(0,48)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cubelet_pos</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">),</span>

<span style="color: #000000;">cubelet_twi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">)</span>
procedure rot(integer cur_phase)
if cur_phase<4 then
<span style="color: #008080;">procedure</span> <span style="color: #000000;">rot</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">)</span>
for i=0 to 3 do
<span style="color: #008080;">if</span> <span style="color: #000000;">cur_phase</span><span style="color: #0000FF;"><</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span>
integer di = cur_phase*8+i+1,
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
j = d2[di]+1,
<span style="color: #004080;">integer</span> <span style="color: #000000;">di</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">*</span><span style="color: #000000;">8</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
k = d2[di+4]+1
<span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">di</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
cubelet_twi[j] = mod(cubelet_twi[j]+2-mod(i,2),3)
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">di</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
cubelet_twi[k] = xor_bits(cubelet_twi[k],cur_phase<2)
<span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;"><</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=0 to 6 do
integer di = cur_phase*8+i+1,
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
j = d2[di+(i!=3)]+1,
<span style="color: #004080;">integer</span> <span style="color: #000000;">di</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">*</span><span style="color: #000000;">8</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
k = d2[di]+1
<span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">di</span><span style="color: #0000FF;">+(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
-- swap(cubelet[j]], cubelet[k]);
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">di</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
{cubelet_pos[j],cubelet_pos[k]} = {cubelet_pos[k],cubelet_pos[j]}
<span style="color: #000080;font-style:italic;">-- swap(cubelet[j]], cubelet[k]);</span>
{cubelet_twi[j],cubelet_twi[k]} = {cubelet_twi[k],cubelet_twi[j]}
<span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}</span>
end for
<span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
function hashf()
int ret = 0;
<span style="color: #008080;">function</span> <span style="color: #000000;">hashf</span><span style="color: #0000FF;">()</span>
switch cur_phase do
<span style="color: #004080;">int</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">;</span>
case 0:
<span style="color: #008080;">switch</span> <span style="color: #000000;">cur_phase</span> <span style="color: #008080;">do</span>
for i=0 to 10 do
<span style="color: #008080;">case</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">:</span>
ret += ret + cubelet_twi[i+1]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
return ret;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
case 1:
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span><span style="color: #0000FF;">;</span>
for i=0 to 6 do
<span style="color: #008080;">case</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">:</span>
ret = ret*3 + cubelet_twi[i+12+1]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ret</span><span style="color: #0000FF;">*</span><span style="color: #000000;">3</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for i=0 to 10 do
ret += ret + (cubelet_pos[i+1]>7)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]></span><span style="color: #000000;">7</span><span style="color: #0000FF;">)</span>
return ret-7;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
case 2:
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span><span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">;</span>
sequence inva = repeat(0,48),
<span style="color: #008080;">case</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">:</span>
b = repeat(0,48)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">inva</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">),</span>
for i=0 to 7 do
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">48</span><span style="color: #0000FF;">)</span>
integer ci12p = cubelet_pos[i+12+1],
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">7</span> <span style="color: #008080;">do</span>
ci12p3 = and_bits(ci12p,3)
<span style="color: #004080;">integer</span> <span style="color: #000000;">ci12p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
if ci12p<16 then
<span style="color: #000000;">ci12p3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ci12p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
inva[ci12p3+1] = ret
<span style="color: #008080;">if</span> <span style="color: #000000;">ci12p</span><span style="color: #0000FF;"><</span><span style="color: #000000;">16</span> <span style="color: #008080;">then</span>
ret += 1
<span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ci12p3</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ret</span>
else
b[i-ret+1] = ci12p3
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #008080;">else</span>
<span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ret</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ci12p3</span>
end for
for i=0 to 6 do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ret += ret + (cubelet_pos[i+1]>3);
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]></span><span style="color: #000000;">3</span><span style="color: #0000FF;">);</span>
for i=0 to 6 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
ret += ret + (cubelet_pos[i+12+1]>15);
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]></span><span style="color: #000000;">15</span><span style="color: #0000FF;">);</span>
integer ib2 = xor_bits(inva[b[1]+1],inva[b[2]+1])*2,
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
ib3 = xor_bits(inva[b[1]+1],inva[b[3]+1]),
<span style="color: #004080;">integer</span> <span style="color: #000000;">ib2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
ib4 = xor_bits(inva[b[1]+1],inva[b[4]+1])
<span style="color: #000000;">ib3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span>
return ret*54 + ib2 + (ib3 > ib4) - 3587708
<span style="color: #000000;">ib4</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">inva</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
end switch
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span><span style="color: #0000FF;">*</span><span style="color: #000000;">54</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">ib2</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ib3</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">ib4</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">3587708</span>
for i=0 to 4 do
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
ret *= 24;
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
for cp=0 to 3 do
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">;</span>
for k=0 to cp-1 do
<span style="color: #008080;">for</span> <span style="color: #000000;">cp</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
if cubelet_pos[i*4+cp+1] < cubelet_pos[i*4+k+1] then
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">cp</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
ret += cp + iff(cp=3?cp:0)
<span style="color: #008080;">if</span> <span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">4</span><span style="color: #0000FF;">+</span><span style="color: #000000;">cp</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">4</span><span style="color: #0000FF;">+</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">cp</span> <span style="color: #0000FF;">+</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cp</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">?</span><span style="color: #000000;">cp</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return floor(ret/2)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ret</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function do_search(integer dpt)
integer h = hashf(),
<span style="color: #008080;">function</span> <span style="color: #000000;">do_search</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dpt</span><span style="color: #0000FF;">)</span>
q = (floor(cur_phase/2)*19+8)*power(2,7),
<span style="color: #004080;">integer</span> <span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hashf</span><span style="color: #0000FF;">(),</span>
hmq = mod(h,q)+1,
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">19</span><span style="color: #0000FF;">+</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">),</span>
hfq = floor(h/q)+1,
<span style="color: #000000;">hmq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
d = (dpt < hash_table[cur_phase+1][hmq] or
<span style="color: #000000;">hfq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
dpt < hash_table[cur_phase+4+1][hfq])
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">dpt</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hmq</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">or</span>

<span style="color: #000000;">dpt</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hfq</span><span style="color: #0000FF;">])</span>
if d xor search_mode then
if search_mode then
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span> <span style="color: #008080;">xor</span> <span style="color: #000000;">search_mode</span> <span style="color: #008080;">then</span>
if dpt <= depth_to_go[h+1] then
<span style="color: #008080;">if</span> <span style="color: #000000;">search_mode</span> <span style="color: #008080;">then</span>
return not h;
<span style="color: #008080;">if</span> <span style="color: #000000;">dpt</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">depth_to_go</span><span style="color: #0000FF;">[</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
else
<span style="color: #008080;">return</span> <span style="color: #008080;">not</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">;</span>
depth_to_go[h+1] = dpt;
end if
<span style="color: #008080;">else</span>
<span style="color: #000000;">depth_to_go</span><span style="color: #0000FF;">[</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dpt</span><span style="color: #0000FF;">;</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
hash_table[cur_phase+1][hmq] = min(hash_table[cur_phase+1][hmq],dpt);
hash_table[cur_phase+5][hfq] = min(hash_table[cur_phase+5][hfq],dpt);
<span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hmq</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hmq</span><span style="color: #0000FF;">],</span><span style="color: #000000;">dpt</span><span style="color: #0000FF;">);</span>
<span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hfq</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hash_table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hfq</span><span style="color: #0000FF;">],</span><span style="color: #000000;">dpt</span><span style="color: #0000FF;">);</span>
for k=0 to 5 do
for i=0 to 3 do
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span>
rot(k)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
if (k>=cur_phase*2 or i=1) and i<=2 then
<span style="color: #000000;">rot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
history_idx += 1
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">cur_phase</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
history_mov[history_idx] = k
history_rpt[history_idx] = i
<span style="color: #000000;">history_idx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">history_mov</span><span style="color: #0000FF;">[</span><span style="color: #000000;">history_idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k</span>
if do_search(dpt-search_mode*2+1) then return 1 end if
<span style="color: #000000;">history_rpt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">history_idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
history_idx -= 1
<span style="color: #008080;">if</span> <span style="color: #000000;">do_search</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dpt</span><span style="color: #0000FF;">-</span><span style="color: #000000;">search_mode</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #000000;">history_idx</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return 0
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function pack_moves()
string moves = ""
<span style="color: #008080;">function</span> <span style="color: #000000;">pack_moves</span><span style="color: #0000FF;">()</span>
integer n = 0, this, last, last_rpt
<span style="color: #004080;">string</span> <span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
if history_idx!=0 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">last</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">last_rpt</span>
-- add a dummy move to trigger the last move print:
<span style="color: #008080;">if</span> <span style="color: #000000;">history_idx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
last = xor_bits(history_mov[history_idx],1) -- F<->B, etc
<span style="color: #000080;font-style:italic;">-- add a dummy move to trigger the last move print:</span>
history_idx += 1
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history_mov</span><span style="color: #0000FF;">[</span><span style="color: #000000;">history_idx</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- F&lt;-&gt;B, etc</span>
history_mov[history_idx] = last
<span style="color: #000000;">history_idx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
history_rpt[history_idx] = 0
<span style="color: #000000;">history_mov</span><span style="color: #0000FF;">[</span><span style="color: #000000;">history_idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">last</span>
last = history_mov[1]
<span style="color: #000000;">history_rpt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">history_idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
last_rpt = 0
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">history_mov</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for i=1 to history_idx do
<span style="color: #000000;">last_rpt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
this = history_mov[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">history_idx</span> <span style="color: #008080;">do</span>
if this!=last then
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">history_mov</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
-- coalesce eg F1F2 to F' (unless you wanna fix do_search()!)
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">last</span> <span style="color: #008080;">then</span>
if last_rpt then
<span style="color: #000080;font-style:italic;">-- coalesce eg F1F2 to F' (unless you wanna fix do_search()!)</span>
moves &= "FBRLUD"[last+1] & {"","2","'"}[last_rpt]
<span style="color: #008080;">if</span> <span style="color: #000000;">last_rpt</span> <span style="color: #008080;">then</span>
n += 1
<span style="color: #000000;">moves</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"FBRLUD"</span><span style="color: #0000FF;">[</span><span style="color: #000000;">last</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">last_rpt</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #000000;">n</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
last = this
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
last_rpt = history_rpt[i]+1
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
else
<span style="color: #000000;">last_rpt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">history_rpt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
last_rpt = mod(last_rpt+history_rpt[i]+1,4)
end if
<span style="color: #008080;">else</span>
<span style="color: #000000;">last_rpt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">last_rpt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">history_rpt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return {moves,n,iff(n=1?"":"s")}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">)}</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function tomas(sequence args)
search_mode = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">tomas</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
history_idx = 0
<span style="color: #000000;">search_mode</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
depth_to_go = repeat(0,5*power(2,20))
<span style="color: #000000;">history_idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>

<span style="color: #000000;">depth_to_go</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">))</span>
for i=0 to 19 do
cubelet_pos[i+1] = i
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
for i=0 to 3 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
cur_phase = i
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
{} = do_search(0)
<span style="color: #000000;">cur_phase</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
end for
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">do_search</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
args = split(args)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=0 to 19 do
<span style="color: #000000;">args</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
string s = args[i+1] -- (may be rotated, eg RU or UR)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</span>
integer p = find(xor_string(s),d1)
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">args</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- (may be rotated, eg RU or UR)</span>
if p=0 then ?9/0 end if -- sensible message(bad args)?
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xor_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #000000;">d1</span><span style="color: #0000FF;">)</span>
cubelet_pos[i+1] = p-1
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- sensible message(bad args)?</span>
int x = max(find('U',s), find('D',s));
<span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
cubelet_twi[i+1] = iff(x!=0 ? x-1 : s[1]>'F')
<span style="color: #004080;">int</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'U'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'D'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">));</span>
end for
<span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #0000FF;">?</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]></span><span style="color: #008000;">'F'</span><span style="color: #0000FF;">)</span>
for i=0 to 4 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer j = d3[i+1]+1,
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
k = d3[i+6]+1
<span style="color: #004080;">integer</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
-- swap(cubelet[j], cubelet[k]);
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
{cubelet_pos[j],cubelet_pos[k]} = {cubelet_pos[k],cubelet_pos[j]}
<span style="color: #000080;font-style:italic;">-- swap(cubelet[j], cubelet[k]); </span>
{cubelet_twi[j],cubelet_twi[k]} = {cubelet_twi[k],cubelet_twi[j]}
<span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_pos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}</span>
end for
<span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">cubelet_twi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}</span>
search_mode = 1;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for cp=0 to 3 do
<span style="color: #000000;">search_mode</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span>
cur_phase = cp
<span style="color: #008080;">for</span> <span style="color: #000000;">cp</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
for i=0 to 19 do
<span style="color: #000000;">cur_phase</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cp</span>
if do_search(i) then exit end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">do_search</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return pack_moves()
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">pack_moves</span><span style="color: #0000FF;">()</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
printf(1,"%s (%d move%s)\n",tomas("UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL"))</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s (%d move%s)\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tomas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL"</span><span style="color: #0000FF;">))</span>
<!--</lang>-->
{{out}}
{{out}}
<pre>
<pre>

Revision as of 22:11, 7 April 2022

Solve a Rubik's cube is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Create a program that is capable of solving a   Rubik's Cube   as efficiently as possible.


Other names are:

  •   Magic Cube
  •   Speed Cube
  •   Puzzle Cube
  •   Cube


You may use any sort of input you wish.

Go

As in the case of the Kotlin entry, this is a translation of the C++ competition code by Stefan Pochmann.

On the same machine, typical timings for the 100 line dataset are just over 200 milliseconds which is significantly slower than both the Kotlin and C++ code but still acceptable.

The relative slowness may be partly due to maps in Go not being able to accept reference types (such as slices) as a key because they don't support the '==' operator which tests for structural equality. I've therefore had to copy each slice returned by the 'id' function into a forty element array (a value type in Go) and use that as a key instead.

For the single line example, typical timings are around 240 milliseconds which is much faster than Kotlin due, no doubt, to JVM warm up time. <lang go>/**********************************************************************

*
* A cube 'state' is an int array with 40 entries, the first 20
* are a permutation of {0,...,19} and describe which cubie is at
* a certain position (regarding the input ordering). The first
* twelve are for edges, the last eight for corners.
*
* The last 20 entries are for the orientations, each describing
* how often the cubie at a certain position has been turned
* counterclockwise away from the correct orientation. Again the
* first twelve are edges, the last eight are corners. The values
* are 0 or 1 for edges and 0, 1 or 2 for corners.
*
**********************************************************************/

package main

import (

   "bufio"
   "fmt"
   "log"
   "os"
   "strings"
   "time"

)

type ai = [40]int

var applicableMoves = [5]int{0, 262143, 259263, 74943, 74898}

var phase = 0

var affectedCubies = [6][8]int{

   {0, 1, 2, 3, 0, 1, 2, 3},   // U
   {4, 7, 6, 5, 4, 5, 6, 7},   // D
   {0, 9, 4, 8, 0, 3, 5, 4},   // F
   {2, 10, 6, 11, 2, 1, 7, 6}, // B
   {3, 11, 7, 9, 3, 2, 6, 5},  // L
   {1, 8, 5, 10, 1, 0, 4, 7},  // R

}

func btoi(b bool) int {

   if b {
       return 1
   }
   return 0

}

func sliceToAi(s []int) ai {

   var a ai
   copy(a[:], s)
   for i := len(s); i < 40; i++ {
       a[i] = -1
   }
   return a

}

func applyMove(move int, state ai) ai {

   turns := move%3 + 1
   face := move / 3
   for turns != 0 {
       turns--
       oldState := state
       for i := 0; i < 8; i++ {
           isCorner := btoi(i > 3)
           target := affectedCubies[face][i] + isCorner*12
           temp := i + 1
           if (i & 3) == 3 {
               temp = i - 3
           }
           killer := affectedCubies[face][temp] + isCorner*12
           var orientationDelta int
           switch {
           case i < 4:
               orientationDelta = btoi(face > 1 && face < 4)
           case face < 2:
               orientationDelta = 0
           default:
               orientationDelta = 2 - (i & 1)
           }
           state[target] = oldState[killer]
           state[target+20] = oldState[killer+20] + orientationDelta
           if turns == 0 {
               state[target+20] %= 2 + isCorner
           }
       }
   }
   return state

}

func inverse(move int) int {

   return move + 2 - 2*(move%3)

}

func id(state ai) ai {

   //--- Phase 1: Edge orientations.
   if phase < 2 {
       return sliceToAi(state[20:32])
   }
   //-- Phase 2: Corner orientations, E slice edges.
   if phase < 3 {
       result := state[31:40]
       for e := uint(0); e < 12; e++ {
           result[0] |= (state[e] / 8) << e
       }
       return sliceToAi(result)
   }
   //--- Phase 3: Edge slices M and S, corner tetrads, overall parity.
   if phase < 4 {
       result := []int{0, 0, 0}
       for e := uint(0); e < 12; e++ {
           temp := 2
           if state[e] <= 7 {
               temp = state[e] & 1
           }
           result[0] |= temp << (2 * e)
       }
       for c := uint(0); c < 8; c++ {
           result[1] |= ((state[c+12] - 12) & 5) << (3 * c)
       }
       for i := 12; i < 19; i++ {
           for j := i + 1; j < 20; j++ {
               result[2] ^= btoi(state[i] > state[j])
           }
       }
       return sliceToAi(result)
   }
   //--- Phase 4: The rest.
   return state

}

func main() {

   startTime := time.Now()
   aggregateMoves := 0
   //--- Define the goal.
   goal := [20]string{
       "UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",
       "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR",
   }
   //--- Load dataset (file name should be passed as a command line argument).
   if len(os.Args) != 2 {
       log.Fatal("the file name should be passed as a command line argument") 
   }
   file, err := os.Open(os.Args[1])
   if err != nil {
       log.Fatal(err)       
   }
   defer file.Close()
   var lineCount = 0
   scanner := bufio.NewScanner(file)
   for scanner.Scan() {
       line := scanner.Text()
       inputs := strings.Fields(line)
       lineCount++
       phase = 0
       totalMoves := 0
       //--- Prepare current (start) and goal state.
       var currentState ai
       var goalState ai
       for i := 0; i < 20; i++ {
           //--- Goal state.
           goalState[i] = i
           //--- Current (start) state.
           cubie := inputs[i]
           for {
               idx := -1
               for c := 0; c < len(goal); c++ {
                   if goal[c] == cubie {
                       idx = c
                       break
                   }
               }
               if idx >= 0 {
                   currentState[i] = idx
               } else {
                   currentState[i] = 20
               }
               if currentState[i] != 20 {
                   break
               }
               cubie = cubie[1:] + cubie[:1]
               currentState[i+20]++
           }
       }
       //--- Dance the funky Thistlethwaite..
   nextPhase:
       for phase++; phase < 5; phase++ {
           //--- Compute ids for current and goal state, skip phase if equal.
           currentId := id(currentState)
           goalId := id(goalState)
           if currentId == goalId {
               continue
           }
           //--- Initialize the BFS queue.
           q := []ai{currentState, goalState}
           //--- Initialize the BFS tables.
           predecessor := make(map[ai]ai)
           direction := make(map[ai]int)
           lastMove := make(map[ai]int)
           direction[currentId] = 1
           direction[goalId] = 2
           //--- Dance the funky bidirectional BFS...
           for {
               //--- Get state from queue, compute its ID and get its direction.
               oldState := q[0]
               q = q[1:]
               oldId := id(oldState)
               oldDir := direction[oldId]
               //--- Apply all applicable moves to it and handle the new state.
               for move := 0; move < 18; move++ {
                   if (applicableMoves[phase] & (1 << uint(move))) != 0 {
                       //--- Apply the move.
                       newState := applyMove(move, oldState)
                       newId := id(newState)
                       newDir := direction[newId]
                       //--- Have we seen this state (id) from the other direction already?
                       //--- I.e. have we found a connection?
                       if (newDir != 0) && (newDir != oldDir) {
                           //--- Make oldId represent the forwards
                           //--- and newId the backwards search state.
                           if oldDir > 1 {
                               newId, oldId = oldId, newId
                               move = inverse(move)
                           }
                           //--- Reconstruct the connecting algorithm.
                           algorithm := []int{move}
                           for oldId != currentId {
                               algorithm = append(algorithm, 0)
                               copy(algorithm[1:], algorithm[0:])
                               algorithm[0] = lastMove[oldId]
                               oldId = predecessor[oldId]
                           }
                           for newId != goalId {
                               algorithm = append(algorithm, inverse(lastMove[newId]))
                               newId = predecessor[newId]
                           }
                           //--- Print and apply the algorithm.
                           for i := 0; i < len(algorithm); i++ {
                               fmt.Printf("%c", "UDFBLR"[algorithm[i]/3])
                               fmt.Print(algorithm[i]%3 + 1)
                               fmt.Print(" ")
                               totalMoves++
                               currentState = applyMove(algorithm[i], currentState)
                           }
                           //--- Jump to the next phase.
                           continue nextPhase
                       }
                       //--- If we've never seen this state (id) before, visit it.
                       if newDir == 0 {
                           q = append(q, newState)
                           direction[newId] = oldDir
                           lastMove[newId] = move
                           predecessor[newId] = oldId
                       }
                   }
               }
           }
       }
       fmt.Printf(" (moves %d)\n", totalMoves)
       aggregateMoves += totalMoves
   }
   if err := scanner.Err(); err != nil {
       log.Fatal(err)
   }
   endTime := time.Now()
   elapsedTime := endTime.Sub(startTime).Nanoseconds() / 1000000
   fmt.Println("\nAverage number of moves =", float64(aggregateMoves)/float64(lineCount))
   fmt.Println("\nAverage time =", elapsedTime/int64(lineCount), "milliseconds")

}</lang>

Output:
Same as Kotlin entry apart, of course, from the timings.


Julia

Translation of: Kotlin

<lang julia>#=**********************************************************************

*
* A cube 'state' is a vector<int> with 40 entries, the first 20
* are a permutation of {0,...,19} and describe which cubie is at
* a certain position (regarding the input ordering). The first
* twelve are for edges, the last eight for corners.
*
* The last 20 entries are for the orientations, each describing
* how often the cubie at a certain position has been turned
* counterclockwise away from the correct orientation. Again the
* first twelve are edges, the last eight are corners. The values
* are 0 or 1 for edges and 0, 1 or 2 for corners.
*
*********************************************************************=#

const applicablemoves = [0, 262143, 259263, 74943, 74898]

const affectedcubies = [ 0 1 2 3 0 1 2 3; # U 4 7 6 5 4 5 6 7; # D 0 9 4 8 0 3 5 4; # F 2 10 6 11 2 1 7 6; # B 3 11 7 9 3 2 6 5; # L 1 8 5 10 1 0 4 7] # R

function applymove(move, state)

   state2, oldstate2 = deepcopy(state), zeros(Int, length(state))
   face, turns = divrem(move, 3) .+ 1
   while turns != 0
       turns -= 1
       oldstate2 .= state2
       for i in 1:8
           iscorner = i > 4
           target = affectedcubies[face, i] + iscorner * 12 + 1
           temp = ((i-1) & 3) == 3 ? i - 3 : i + 1
           killer = affectedcubies[face, temp] + iscorner * 12 + 1
           orientationdelta = i < 5 ? Int(face in [3, 4]) : face < 3 ? 0 : 2 - ((i-1) & 1)
           state2[target] = oldstate2[killer]
           state2[target + 20] = oldstate2[killer + 20] + orientationdelta
           (turns == 0) && (state2[target + 20] %= 2 + iscorner)
       end
   end
   return state2

end

inverse(move) = move + 2 - 2 * (move % 3)

function id(state::Vector{Int}, phase::Int)

   #--- Phase 1: Edge orientations.
   if phase < 2
       return state[21:32]
   elseif phase < 3
   #-- Phase 2: Corner orientations, E slice edges.
       result =  state[32:40]
       for e in 0:11
           result[1] |= ((state[e + 1] ÷ 8) << e)
       end
       return result
   elseif phase < 4
   #--- Phase 3: Edge slices M and S, corner tetrads, overall parity.
       result = zeros(Int, 3)
       for e in 0:11
           result[1] |= state[e + 1] > 7 ? 2 : (state[e + 1] & 1) << (2 * e)
       end
       for c in 0:7
           result[2] |= ((state[c + 12 + 1] - 12) & 5) << (3 * c)
       end
       for i in 13:19, j in i+1:20
           result[3] ⊻= Int(state[i] > state[j])
       end
       return result
   end
   #--- Phase 4: The rest.
   return state

end

function pochmann(fname)

   starttime = time_ns() ÷ 1000000
   aggregatemoves = 0
   #--- Define the goal.
   goal = ["UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",
       "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR"]
   #--- Load dataset (file name should be passed as a command line argument).
   file = read(fname, String)
   linecount = 0
   for line in split(strip(file), "\n")
       inputs = split(line)
       linecount += 1
       totalmoves = 0
       #--- Prepare current (start) and goal state.
       state, goalstate, phase = zeros(Int, 40), zeros(Int, 40), 0
       for i in 1:20
           #--- Goal state.
           goalstate[i] = i - 1
           #--- Current (start) state.
           cubie = inputs[i]
           while true
               state[i] = something(findfirst(x -> x .== cubie, goal), 21) - 1
               (state[i] != 20) && break
               cubie = cubie[2:end] * cubie[1]
               state[i + 20] += 1
           end
       end
       #--- Dance the funky Thistlethwaite...
   @label nextphase    # preserves phase value, but restarts while loop
       while (phase += 1) < 5
           #--- Compute ids for current and goal state, skip phase if equal.
           currentid = id(state, phase)
           goalid = id(goalstate, phase)
           currentid == goalid && continue
           #--- Initialize the BFS queue.
           q = [state, goalstate]
           #--- Initialize the BFS tables.
           predecessor = Dict{Vector{Int}, Vector{Int}}()
           direction = Dict{Vector{Int}, Int}()
           lastmove = Dict{Vector{Int}, Int}()
           direction[currentid] = 1
           direction[goalid] = 2
           #--- Dance the funky bidirectional BFS...
           while true
               #--- Get state from queue, compute its ID and get its direction.
               oldstate = popfirst!(q)
               oldid = id(oldstate, phase)
               olddir = get!(direction, oldid, 0)
               #--- Apply all applicable moves to it and handle the new state.
               for move in 0:17
                   if applicablemoves[phase + 1] & (1 << UInt(move)) != 0
                       #--- Apply the move.
                       newstate = applymove(move, oldstate)
                       newid = id(newstate, phase)
                       newdir = get!(direction, newid, 0)
                       #--- Have we seen this state (id) from the other direction already?
                       #--- I.e. have we found a connection?
                       if (newdir != 0) && (newdir != olddir)
                           #--- Make oldid represent the forwards
                           #--- and newid the backwards search state.
                           if olddir > 1
                               newid, oldid = oldid, newid
                               move = inverse(move)
                           end
                           #--- Reconstruct the connecting algorithm.
                           algorithm = [move]
                           while oldid != currentid
                               pushfirst!(algorithm, get(lastmove, oldid, 0))
                               oldid = get!(predecessor, oldid, Int[])
                           end
                           while newid != goalid
                               push!(algorithm, inverse(get!(lastmove, newid, 0)))
                               newid = get!(predecessor, newid, Int[])
                           end
                           #--- Print and apply the algorithm.
                           for i in 1:length(algorithm)
                               print("UDFBLR"[algorithm[i] ÷ 3 + 1])
                               print(algorithm[i] % 3 + 1)
                               print(" ")
                               totalmoves += 1
                               state = applymove(algorithm[i], state)
                           end
                           #--- Jump to the next phase.
                           @goto nextphase
                       end
                       #--- If we've never seen this state (id) before, visit it.
                       if newdir == 0
                           push!(q, newstate)
                           direction[newid] = olddir
                           lastmove[newid] = move
                           predecessor[newid] = oldid
                       end
                   end
                   move += 1
               end
           end
       end
       println(" (moves $totalmoves)")
       aggregatemoves += totalmoves
   end
   elapsedtime = time_ns() ÷ 1000000 - starttime
   println("\nAverage number of moves = $(aggregatemoves / linecount)")
   println("\nAverage time = $(elapsedtime / linecount) milliseconds")

end

pochmann("rubikdata.txt")

</lang>

Output:

Using the 100-line database:

 (moves 0)
U1 U2  (moves 2)
U2  (moves 1)
U1  (moves 1)
F1 F2  (moves 2)
F2  (moves 1)
F1  (moves 1)
R1 R2  (moves 2)
R2  (moves 1)
R1  (moves 1)
D1 D2  (moves 2)
D2  (moves 1)
D1  (moves 1)
B1 B2  (moves 2)
B2  (moves 1)
B1  (moves 1)
L1 L2  (moves 2)
L2  (moves 1)
L1  (moves 1)
U2 B3 B2  (moves 3)
L2 U3  (moves 2)
R1 U1  (moves 2)
D3 L3  (moves 2)
D3 L2  (moves 2)
D2 F3 F2  (moves 3)
R2 F3  (moves 2)
R1 F2 F2 R2 F2  (moves 5)
D1 D2 U2  (moves 3)
L1 B2 F2 L2 R2 B2 F2  (moves 7)
L1 L2 D3  (moves 3)
D1 F2  (moves 2)
U2 R3  (moves 2)
L1 L2 U3  (moves 3)
U1 R2  (moves 2)
U1 R3  (moves 2)
F1 U2  (moves 2)
U2 R3 R2  (moves 3)
F2 D1 F3  (moves 3)
F2 D3 D2 U2  (moves 4)
L3 D2 R3  (moves 3)
D2 R3 R2 D3  (moves 4)
F1 R1 B2 B2 R2 B2  (moves 6)
L1 B2 F2  (moves 3)
U1 R2 B3 B2  (moves 4)
R2 F3 R2  (moves 3)
L2 D3 R3 R2  (moves 4)
L2 F3 L2 L2 F2 L2  (moves 6)
F1 R1 B3 D3 B2 D3 L3 U2 L3 U2 L2 U2 L2 U3 R2 U1 F2 L2 U2 B2 L2 F2 U2 L2 U2 F2 D2 F2 U2  (moves 29)
L1 L2 U3 R2  (moves 4)
L3 B3 B2 R3 R2  (moves 5)
B2 U1 R3 R2  (moves 4)
L3 B3 L2  (moves 3)
D1 B2 L3 L2  (moves 4)
B1 B2 R3 F2 F2 R2 F2  (moves 7)
D1 F3 D1 D2  (moves 4)
R1 B3 D1 R2 F3 L1 U2 F2 D3 B2 D1 L3 U1 F2 R2 U1 L2 U1 F2 U2 R2 U3 F2 U3 F2 D2 F2 L2 F2 L2 F2 U2 F2 D2 L2  (moves 35)
F1 R1 U3 D1 B3 U3 D2 L3 B2 R1 F2 D3 L3 U2 R2 D1 R2 B2 U2 L2 U3 U2 F2 U2 L2 B2 R2 D2 R2 D2 B2 L2 F2 U2  (moves 34)
U1 R1 F3 L1 R2 U3 L1 D2 F2 U3 L3 L2 U1 F2 D3 F2 F2 U2 D2 L2 U2 F2 R2 F2 D2 R2 U2  (moves 27)
R1 D3 R3 F3 R1 D3 F2 U1 R3 D2 U1 R3 F2 U1 L2 U3 F2 U1 B2 D2 L2 D3 F2 F2 U2 F2 D2 L2 U2 L2 F2 L2 U2 R2  (moves 34)
D2 R1 B1 L1 F3 U2 D3 L2 R1 D3 B2 U1 F2 L3 F2 U3 B2 U3 B2 L2 U3 B2 U3 F2 U2 F2 U2 L2 F2 R2 B2 D2 L2 D2 F2  (moves 35)
B3 U2 L1 F3 F2 U1 R3 D1 F2 R3 D3 B2 R3 B2 U1 F2 U3 R2 U1 R2 U3 R2 L2 F2 U2 R2 F2 D2 R2 B2 U2 R2 B2  (moves 33)
L1 F3 L2 D3 U1 F3 L1 B2 R1 U1 D1 B2 R3 U1 L2 U1 B2 U1 F2 U3 L2 D1 F2 U3 F2 U2 D2 R2 U2 L2 F2 R2 U2 F2 R2  (moves 35)
F1 R3 U2 F3 B2 U1 L1 U1 R3 B2 U1 R3 R2 U3 L2 U1 B2 U2 R2 U3 L2 U3 F2 L2 U2 F2 U2 B2 L2 D2 L2 F2 L2 F2 U2  (moves 35)
U2 D3 B3 U1 L2 D1 R1 U3 L3 D2 U1 R3 U3 B2 D3 R2 F2 U3 F2 U3 U2 B2 D2 B2 L2 F2 R2 D2 R2  (moves 29)
D2 L3 U3 F3 B2 U3 L1 U2 R3 D2 L3 U2 L2 U3 R2 B2 D3 F2 R2 U3 U2 L2 U2 F2 U2 D2 R2 F2 U2 B2 D2  (moves 31)
F1 L1 U1 L1 B3 U3 L1 F2 L1 B2 F2 U3 L3 F2 D3 B2 D3 R2 U1 F2 U3 L2 U3 U2 F2 D2 B2 U2 F2 R2 F2 L2  (moves 32)
B1 L1 U3 F3 B2 U1 L3 B2 R3 L3 U3 L3 D2 B2 D3 F2 L2 U2 R2 U3 F2 U3 F2 L2 U2 B2 L2 U2 B2 F2 R2 U2 F2  (moves 33)
F2 L3 F1 D3 B3 B2 U3 R1 D3 U3 L3 L2 R2 U3 B2 D1 B2 U3 R2 U3 F2 L2 F2 L2 U2 F2 B2 R2 B2 L2  (moves 30)
D3 F3 U1 B2 U3 L1 D1 R3 U3 F2 L3 U1 F2 U2 L2 U3 L2 B2 R2 L2 D1 F2 F2 L2 U2 F2 L2 U2 R2 D2 B2 R2 L2  (moves 33)
F2 R3 U2 F3 U2 L2 B2 D1 F2 R3 B2 D1 L3 D2 R2 B2 D1 R2 B2 U1 L2 B2 R2 B2 R2 D2 L2 D2 F2 L2 B2 L2 F2  (moves 33)
U1 R3 F3 D3 R3 B2 L3 D1 F2 U1 R3 L2 U1 B2 D1 L2 U3 R2 U1 L2 U3 F2 U3 F2 U2 B2 L2 D2 L2 U2 R2 F2  (moves 32)
F1 R1 F1 D3 B3 F3 U1 R2 F2 U1 L3 U1 F2 U2 R2 U1 R2 U3 L2 U3 D2 L2 F2 L2 F2 U2 B2 U2 L2 F2  (moves 30)
F3 R3 L2 B3 U1 B2 U1 F2 U2 B2 R3 D2 L3 B2 U1 F2 U3 L2 U1 B2 D3 L2 U1 L2 U2 L2 D2 R2 F2 D2 F2 U2 R2 U2  (moves 34)
D1 B3 D2 L1 F3 U3 F2 D2 L3 F2 L3 D3 L3 D1 L2 B2 U3 R2 U1 R2 U3 L2 U3 L2 D2 R2 D2 F2 R2 F2 L2 D2 U2 F2 U2  (moves 35)
U1 B1 D1 R3 F3 U1 B2 R1 U3 L1 D3 B2 U1 R3 U2 F2 L2 U3 R2 U1 B2 D3 B2 U1 L2 F2 U2 D2 L2 U2 B2 R2 B2 L2 D2 L2  (moves 36)
U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)
U1 B2 L1 B3 F3 U1 F2 B2 R2 D3 R3 U3 L3 B2 U1 F2 U3 F2 U3 L2 U2 F2 R2 B2 R2 U2 F2 U2 F2 U2 F2  (moves 31)
U1 B1 U3 D1 F3 U2 D3 R3 D1 U1 L1 F2 L3 D2 L2 U1 F2 B2 R2 U3 F2 U1 L2 U2 R2 F2 D2 F2 U2 L2 B2 U2 F2  (moves 33)
D1 F3 U2 R1 B3 L1 B2 R1 U3 L2 D3 F2 R3 L2 D2 L2 D3 L2 F2 U3 F2 B2 D2 L2 B2 L2 B2 D2 L2 F2 U2 F2 U2  (moves 33)
R1 B1 D3 F3 D1 R3 D3 B2 L2 B2 U2 L3 L2 U2 B2 L2 U2 F2 U3 U2 F2 L2 D2 L2 B2 U2 R2 F2 L2 B2  (moves 30)
U1 D2 F1 L1 B3 D1 B2 D3 L2 R1 D3 L2 U2 R3 D2 F2 U3 F2 R2 U1 B2 U1 F2 U3 B2 R2 U2 L2 U2 B2 D2 F2 L2 B2 F2 U2  (moves 36)
U1 L1 D1 L1 F3 L1 U1 L3 U3 L1 D1 R3 F2 U2 R2 U1 F2 U2 F2 L2 D1 F2 U3 F2 U2 R2 D2 F2 R2 B2 L2 B2 D2 B2  (moves 34)
L3 D3 U1 F3 U2 F2 D3 R3 B2 D3 U3 L3 R2 U2 L2 D3 R2 U1 L2 U2 F2 U3 F2 U3 U2 L2 U2 R2 B2 R2 B2 U2 F2 U2  (moves 34)
L1 B1 U2 D1 F3 B2 U3 R3 D2 U3 L2 U3 L3 F2 U3 R2 U1 F2 R2 L2 D3 F2 F2 B2 L2 D2 F2 R2 D2 B2 R2 F2 L2  (moves 33)
L1 B1 U3 F3 U1 L2 D3 L1 B2 R1 L3 U3 L3 U3 L2 D3 L2 U1 L2 B2 F2 U3 L2 D2 L2 U2 R2 F2 D2 B2 U2 R2 U2  (moves 33)
F1 U1 B3 F3 B2 U2 D3 L3 U3 L3 U3 R2 D3 B2 D2 L2 U3 R2 U2 F2 U3 F2 L2 D2 L2 R2 F2 L2 U2 L2 D2 U2 F2 U2  (moves 34)
D1 L3 R1 F2 U2 F3 U3 F2 D3 L3 D2 L3 U2 L3 D1 L2 U3 R2 D1 B2 U1 L2 R2 U2 L2 D2 B2 R2 F2 L2 D2 U2 F2 U2  (moves 34)
L2 R3 D1 F3 D3 L1 U3 L3 D2 L3 B2 L2 U1 R2 U2 F2 U3 F2 L2 F2 L2 B2 U2 R2 U2 R2 B2 U2 B2  (moves 29)
L2 U2 R1 B3 F3 U1 L1 D3 F2 U2 R3 U2 L3 L2 U2 L2 D2 L2 F2 U3 F2 U2 L2 U2 B2 U2 R2 D2 R2 B2  (moves 30)
L2 F1 U2 F3 D3 R3 U1 D3 L3 D1 U1 L3 R2 D3 R2 F2 D2 B2 U3 F2 U1 F2 D2 L2 B2 U2 L2 U2 R2 B2 F2 U2  (moves 32)
F3 D2 F3 L2 B2 D3 L2 U3 B2 L3 L2 F2 L2 D3 L2 B2 U3 L2 L2 U2 F2 D2 L2 D2 L2 B2 L2 F2 L2 U2  (moves 30)
F3 R2 U3 F3 U3 R3 D2 R2 D1 F2 U2 L3 D3 L2 D3 R2 U1 F2 U3 L2 U1 F2 L2 B2 D2 B2 L2 F2 U2 L2 F2 D2  (moves 32)
B1 R1 U1 D3 F3 R2 U1 L2 R2 D2 B2 U3 L3 R2 F2 U1 L2 B2 U1 F2 U3 L2 U3 R2 U2 F2 D2 F2 L2 B2 L2 U2 F2  (moves 33)
L3 D3 U1 B3 L2 F2 D3 L3 R1 U1 R3 L2 D3 F2 R2 U3 F2 R2 U3 L2 D2 R2 U2 B2 U2 B2 L2 U2 R2 F2 U2  (moves 31)
L1 F3 L2 R1 B3 L1 U3 L1 R1 D3 F2 D1 R3 B2 R2 U1 F2 L2 D1 R2 F2 D2 L2 R2 B2 R2 B2 U2 L2 U2  (moves 30)
U1 F1 U3 L1 B3 D1 L2 B2 R1 D3 R3 F2 L3 U3 F2 B2 L2 U3 B2 D3 L2 U3 L2 D2 R2 F2 D2 L2 F2 D2 F2  (moves 31)
D2 L3 U1 F3 U1 D3 L1 F2 D3 R3 F2 U3 R3 L2 U1 L2 U3 L2 U1 F2 L2 U1 R2 U3 F2 U2 L2 D2 B2 U2 L2 F2 U2 F2 U2  (moves 35)
F3 L2 F3 U1 L1 U1 D2 L3 U3 L3 B2 U1 F2 U1 F2 D2 R2 U3 L2 U2 F2 U3 R2 F2 D2 L2 D2 R2 F2 U2 F2 U2 F2 U2  (moves 34)
U2 L3 B3 U2 R3 U3 L2 B2 U1 R3 R2 D3 R2 U1 R2 U3 F2 U1 F2 U3 F2 U2 L2 F2 R2 F2 D2 L2 D2 L2 B2  (moves 31)
F1 B1 R3 F3 U3 F3 B2 D1 B2 R1 U3 L1 U2 L3 F2 U3 F2 R2 U1 R2 U2 B2 D3 F2 U3 F2 B2 L2 U2 F2 L2 D2 B2 F2 L2 B2  (moves 36)

Average number of moves = 16.38

Average time = 65.71 milliseconds


Kotlin

This is a translation of Stefan Pochmann's C++ entry in the 2004 competition which was linked to by the author of the Phix entry. This program won the Judge's prize, finished second overall and (as in the case of the winner) is based on Thistlethwaite's algorithm.

I've adjusted the code to accept input from a file whose name is supplied via a command line argument and, as in the case of the original competition, to calculate the average number of moves for each line in the file and the average time to process each one.

To aid readability I've also inserted spaces between each move in the results and added the total moves needed for each line. <lang scala>// version 1.2.21

/**********************************************************************

* 
* A cube 'state' is a vector<int> with 40 entries, the first 20
* are a permutation of {0,...,19} and describe which cubie is at
* a certain position (regarding the input ordering). The first
* twelve are for edges, the last eight for corners.
* 
* The last 20 entries are for the orientations, each describing
* how often the cubie at a certain position has been turned
* counterclockwise away from the correct orientation. Again the
* first twelve are edges, the last eight are corners. The values
* are 0 or 1 for edges and 0, 1 or 2 for corners.
* 
**********************************************************************/

import java.util.ArrayDeque import java.io.File

fun Boolean.toInt() = if (this) 1 else 0

typealias AI = ArrayList<Int>

val applicableMoves = intArrayOf(0, 262143, 259263, 74943, 74898)

val affectedCubies = listOf(

   intArrayOf(0,  1, 2,  3, 0, 1, 2, 3),  // U
   intArrayOf(4,  7, 6,  5, 4, 5, 6, 7),  // D
   intArrayOf(0,  9, 4,  8, 0, 3, 5, 4),  // F
   intArrayOf(2, 10, 6, 11, 2, 1, 7, 6),  // B
   intArrayOf(3, 11, 7,  9, 3, 2, 6, 5),  // L
   intArrayOf(1,  8, 5, 10, 1, 0, 4, 7)   // R

)

fun applyMove(move: Int, state: AI): AI {

   val state2 = AI(state)  // avoids mutating original 'state'.
   var turns = move % 3 + 1
   val face = move / 3
   while (turns-- != 0) {
       val oldState2 = AI(state2)
       for (i in 0..7) {
           val isCorner = (i > 3).toInt()
           val target = affectedCubies[face][i] + isCorner * 12
           val temp = if ((i and 3) == 3) i - 3 else i + 1
           val killer = affectedCubies[face][temp] + isCorner * 12
           val orientationDelta =
               if (i < 4) (face in 2..3).toInt()
               else if (face < 2) 0
               else 2 - (i and 1)
           state2[target] = oldState2[killer]
           state2[target + 20] = oldState2[killer + 20] + orientationDelta
           if (turns == 0) state2[target + 20] %= 2 + isCorner
       }
   }
   return state2

}

fun inverse(move: Int) = move + 2 - 2 * (move % 3)

var phase = 0

fun id(state: AI): AI {

   //--- Phase 1: Edge orientations.
   if (phase < 2) return AI(state.subList(20, 32))
   //-- Phase 2: Corner orientations, E slice edges.
   if (phase < 3) {
       val result =  AI(state.subList(31, 40))
       for (e in 0..11) result[0] = result[0] or ((state[e] / 8) shl e)
       return result
   }
   //--- Phase 3: Edge slices M and S, corner tetrads, overall parity.
   if (phase < 4) {
       val result = AI(3)
       repeat(3) { result.add(0) }
       for (e in 0..11) {
           val temp  = (if (state[e] > 7) 2 else (state[e] and 1)) shl (2 * e)
           result[0] = result[0] or temp
       }
       for (c in 0..7) {
           val temp =  ((state[c + 12] - 12) and 5) shl (3 * c)
           result[1] = result[1] or temp
       }
       for (i in 12..18) {
           for (j in (i + 1)..19) {
               result[2] = result[2] xor (state[i] > state[j]).toInt()
           }
       }
       return result
   }
   //--- Phase 4: The rest.
   return state

}

fun main(args: Array<String>) {

   val startTime = System.currentTimeMillis()
   var aggregateMoves = 0
   //--- Define the goal.
   val goal = listOf(
       "UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",
       "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR"
   )
   //--- Load dataset (file name should be passed as a command line argument).
   val file = File(args[0])
   var lineCount = 0
   file.forEachLine { line ->
       val inputs = line.split(' ')
       lineCount++
       phase = 0
       var totalMoves = 0
       //--- Prepare current (start) and goal state.
       var currentState = AI(40)
       repeat(40) { currentState.add(0) }
       val goalState = AI(40)
       repeat(40) { goalState.add(0) }
       for (i in 0..19) {
           //--- Goal state.
           goalState[i] = i
           //--- Current (start) state.
           var cubie = inputs[i]
           while (true) {
               val idx = goal.indexOf(cubie)
               currentState[i] = if (idx >= 0) idx else 20
               if (currentState[i] != 20) break
               cubie = cubie.substring(1) + cubie[0]
               currentState[i + 20]++
           }
       }
       //--- Dance the funky Thistlethwaite...
       nextPhase@ while (++phase < 5) {
           //--- Compute ids for current and goal state, skip phase if equal.
           val currentId = id(currentState)
           val goalId = id(goalState)
           if (currentId == goalId) continue
           //--- Initialize the BFS queue.
           val q = ArrayDeque<AI>()
           q.addLast(currentState)
           q.addLast(goalState)
           //--- Initialize the BFS tables.
           val predecessor = mutableMapOf<AI, AI>()
           val direction = mutableMapOf<AI, Int>()
           val lastMove = mutableMapOf<AI, Int>()
           direction[currentId] = 1
           direction[goalId] = 2
           //--- Dance the funky bidirectional BFS...
           while (true) {
               //--- Get state from queue, compute its ID and get its direction. 
               val oldState = q.peek()
               q.pop()
               var oldId = id(oldState)
               val oldDir = direction.getOrPut(oldId) { 0 }
               //--- Apply all applicable moves to it and handle the new state.
               var move = 0
               while (move < 18) {
                   if ((applicableMoves[phase] and (1 shl move)) != 0) {
                       //--- Apply the move.
                       val newState = applyMove(move, oldState)
                       var newId = id(newState)
                       var newDir = direction.getOrPut(newId) { 0 }
                       //--- Have we seen this state (id) from the other direction already?
                       //--- I.e. have we found a connection?
                       if ((newDir != 0) && (newDir != oldDir)) {
                           //--- Make oldId represent the forwards
                           //--- and newId the backwards search state.
                           if (oldDir > 1) {
                               val temp = newId
                               newId = oldId
                               oldId = temp
                               move = inverse(move)
                           }
                           //--- Reconstruct the connecting algorithm.
                           val algorithm = AI()
                           algorithm.add(move)
                           while (oldId != currentId) {
                               val tempI = lastMove.getOrPut(oldId) { 0 }
                               algorithm.add(0, tempI)
                               val tempAI = predecessor.getOrPut(oldId) { AI() }
                               oldId = tempAI
                           }
                           while (newId != goalId) {
                               val tempI = lastMove.getOrPut(newId) { 0 }
                               algorithm.add(inverse(tempI))
                               val tempAI = predecessor.getOrPut(newId) { AI() }
                               newId = tempAI
                           }
                           //--- Print and apply the algorithm.
                           for (i in 0 until algorithm.size) {
                               print("UDFBLR"[algorithm[i] / 3])
                               print(algorithm[i] % 3 + 1)
                               print(" ")
                               totalMoves++
                               currentState = applyMove(algorithm[i], currentState)
                           }
                           //--- Jump to the next phase.
                           continue@nextPhase
                       }
                       //--- If we've never seen this state (id) before, visit it.
                       if (newDir == 0) {
                           q.addLast(newState)
                           direction[newId] = oldDir
                           lastMove[newId] = move
                           predecessor[newId] = oldId
                       }
                   }
                   move++
               }
           }
       }
       println(" (moves $totalMoves)")
       aggregateMoves += totalMoves
   }
   val elapsedTime = System.currentTimeMillis() - startTime
   println("\nAverage number of moves = ${aggregateMoves.toDouble() / lineCount}")
   println("\nAverage time = ${elapsedTime / lineCount} milliseconds")

}</lang>

Output:

Using the original dataset of 100 lines, the results were as follows (time doesn't mean much but is typical for my modest machine):

U1 U2  (moves 2)
U2  (moves 1)
U1  (moves 1)
F1 F2  (moves 2)
F2  (moves 1)
F1  (moves 1)
R1 R2  (moves 2)
R2  (moves 1)
R1  (moves 1)
D1 D2  (moves 2)
D2  (moves 1)
D1  (moves 1)
B1 B2  (moves 2)
B2  (moves 1)
B1  (moves 1)
L1 L2  (moves 2)
L2  (moves 1)
L1  (moves 1)
U2 B3 B2  (moves 3)
L2 U3  (moves 2)
R1 U1  (moves 2)
D3 L3  (moves 2)
D3 L2  (moves 2)
D2 F3 F2  (moves 3)
R2 F3  (moves 2)
R1 F2 F2 R2 F2  (moves 5)
D1 D2 U2  (moves 3)
L1 B2 F2 L2 R2 B2 F2  (moves 7)
L1 L2 D3  (moves 3)
D1 F2  (moves 2)
U2 R3  (moves 2)
L1 L2 U3  (moves 3)
U1 R2  (moves 2)
U1 R3  (moves 2)
F1 U2  (moves 2)
U2 R3 R2  (moves 3)
F2 D1 F3  (moves 3)
F2 D3 D2 U2  (moves 4)
L3 D2 R3  (moves 3)
D2 R3 R2 D3  (moves 4)
F1 R1 B2 B2 R2 B2  (moves 6)
L1 B2 F2  (moves 3)
U1 R2 B3 B2  (moves 4)
R2 F3 R2  (moves 3)
L2 D3 R3 R2  (moves 4)
L2 F3 L2 L2 F2 L2  (moves 6)
F1 R1 B3 D3 B2 D3 L3 U2 L3 U2 L2 U2 L2 U3 R2 U1 F2 L2 U2 B2 L2 F2 U2 L2 U2 F2 D2 F2 U2  (moves 29)
L1 L2 U3 R2  (moves 4)
L3 B3 B2 R3 R2  (moves 5)
B2 U1 R3 R2  (moves 4)
L3 B3 L2  (moves 3)
D1 B2 L3 L2  (moves 4)
B1 B2 R3 F2 F2 R2 F2  (moves 7)
D1 F3 D1 D2  (moves 4)
R1 B3 D1 R2 F3 L1 U2 F2 D3 B2 D1 L3 U1 F2 R2 U1 L2 U1 F2 U2 R2 U3 F2 U3 F2 D2 F2 L2 F2 L2 F2 U2 F2 D2 L2  (moves 35)
F1 R1 U3 D1 B3 U3 D2 L3 B2 R1 F2 D3 L3 U2 R2 D1 R2 B2 U2 L2 U3 U2 F2 U2 L2 B2 R2 D2 R2 D2 B2 L2 F2 U2  (moves 34)
U1 R1 F3 L1 R2 U3 L1 D2 F2 U3 L3 L2 U1 F2 D3 F2 F2 U2 D2 L2 U2 F2 R2 F2 D2 R2 U2  (moves 27)
R1 D3 R3 F3 R1 D3 F2 U1 R3 D2 U1 R3 F2 U1 L2 U3 F2 U1 B2 D2 L2 D3 F2 F2 U2 F2 D2 L2 U2 L2 F2 L2 U2 R2  (moves 34)
D2 R1 B1 L1 F3 U2 D3 L2 R1 D3 B2 U1 F2 L3 F2 U3 B2 U3 B2 L2 U3 B2 U3 F2 U2 F2 U2 L2 F2 R2 B2 D2 L2 D2 F2  (moves 35)
B3 U2 L1 F3 F2 U1 R3 D1 F2 R3 D3 B2 R3 B2 U1 F2 U3 R2 U1 R2 U3 R2 L2 F2 U2 R2 F2 D2 R2 B2 U2 R2 B2  (moves 33)
L1 F3 L2 D3 U1 F3 L1 B2 R1 U1 D1 B2 R3 U1 L2 U1 B2 U1 F2 U3 L2 D1 F2 U3 F2 U2 D2 R2 U2 L2 F2 R2 U2 F2 R2  (moves 35)
F1 R3 U2 F3 B2 U1 L1 U1 R3 B2 U1 R3 R2 U3 L2 U1 B2 U2 R2 U3 L2 U3 F2 L2 U2 F2 U2 B2 L2 D2 L2 F2 L2 F2 U2  (moves 35)
U2 D3 B3 U1 L2 D1 R1 U3 L3 D2 U1 R3 U3 B2 D3 R2 F2 U3 F2 U3 U2 B2 D2 B2 L2 F2 R2 D2 R2  (moves 29)
D2 L3 U3 F3 B2 U3 L1 U2 R3 D2 L3 U2 L2 U3 R2 B2 D3 F2 R2 U3 U2 L2 U2 F2 U2 D2 R2 F2 U2 B2 D2  (moves 31)
F1 L1 U1 L1 B3 U3 L1 F2 L1 B2 F2 U3 L3 F2 D3 B2 D3 R2 U1 F2 U3 L2 U3 U2 F2 D2 B2 U2 F2 R2 F2 L2  (moves 32)
B1 L1 U3 F3 B2 U1 L3 B2 R3 L3 U3 L3 D2 B2 D3 F2 L2 U2 R2 U3 F2 U3 F2 L2 U2 B2 L2 U2 B2 F2 R2 U2 F2  (moves 33)
F2 L3 F1 D3 B3 B2 U3 R1 D3 U3 L3 L2 R2 U3 B2 D1 B2 U3 R2 U3 F2 L2 F2 L2 U2 F2 B2 R2 B2 L2  (moves 30)
D3 F3 U1 B2 U3 L1 D1 R3 U3 F2 L3 U1 F2 U2 L2 U3 L2 B2 R2 L2 D1 F2 F2 L2 U2 F2 L2 U2 R2 D2 B2 R2 L2  (moves 33)
F2 R3 U2 F3 U2 L2 B2 D1 F2 R3 B2 D1 L3 D2 R2 B2 D1 R2 B2 U1 L2 B2 R2 B2 R2 D2 L2 D2 F2 L2 B2 L2 F2  (moves 33)
U1 R3 F3 D3 R3 B2 L3 D1 F2 U1 R3 L2 U1 B2 D1 L2 U3 R2 U1 L2 U3 F2 U3 F2 U2 B2 L2 D2 L2 U2 R2 F2  (moves 32)
F1 R1 F1 D3 B3 F3 U1 R2 F2 U1 L3 U1 F2 U2 R2 U1 R2 U3 L2 U3 D2 L2 F2 L2 F2 U2 B2 U2 L2 F2  (moves 30)
F3 R3 L2 B3 U1 B2 U1 F2 U2 B2 R3 D2 L3 B2 U1 F2 U3 L2 U1 B2 D3 L2 U1 L2 U2 L2 D2 R2 F2 D2 F2 U2 R2 U2  (moves 34)
D1 B3 D2 L1 F3 U3 F2 D2 L3 F2 L3 D3 L3 D1 L2 B2 U3 R2 U1 R2 U3 L2 U3 L2 D2 R2 D2 F2 R2 F2 L2 D2 U2 F2 U2  (moves 35)
U1 B1 D1 R3 F3 U1 B2 R1 U3 L1 D3 B2 U1 R3 U2 F2 L2 U3 R2 U1 B2 D3 B2 U1 L2 F2 U2 D2 L2 U2 B2 R2 B2 L2 D2 L2  (moves 36)
U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)
U1 B2 L1 B3 F3 U1 F2 B2 R2 D3 R3 U3 L3 B2 U1 F2 U3 F2 U3 L2 U2 F2 R2 B2 R2 U2 F2 U2 F2 U2 F2  (moves 31)
U1 B1 U3 D1 F3 U2 D3 R3 D1 U1 L1 F2 L3 D2 L2 U1 F2 B2 R2 U3 F2 U1 L2 U2 R2 F2 D2 F2 U2 L2 B2 U2 F2  (moves 33)
D1 F3 U2 R1 B3 L1 B2 R1 U3 L2 D3 F2 R3 L2 D2 L2 D3 L2 F2 U3 F2 B2 D2 L2 B2 L2 B2 D2 L2 F2 U2 F2 U2  (moves 33)
R1 B1 D3 F3 D1 R3 D3 B2 L2 B2 U2 L3 L2 U2 B2 L2 U2 F2 U3 U2 F2 L2 D2 L2 B2 U2 R2 F2 L2 B2  (moves 30)
U1 D2 F1 L1 B3 D1 B2 D3 L2 R1 D3 L2 U2 R3 D2 F2 U3 F2 R2 U1 B2 U1 F2 U3 B2 R2 U2 L2 U2 B2 D2 F2 L2 B2 F2 U2  (moves 36)
U1 L1 D1 L1 F3 L1 U1 L3 U3 L1 D1 R3 F2 U2 R2 U1 F2 U2 F2 L2 D1 F2 U3 F2 U2 R2 D2 F2 R2 B2 L2 B2 D2 B2  (moves 34)
L3 D3 U1 F3 U2 F2 D3 R3 B2 D3 U3 L3 R2 U2 L2 D3 R2 U1 L2 U2 F2 U3 F2 U3 U2 L2 U2 R2 B2 R2 B2 U2 F2 U2  (moves 34)
L1 B1 U2 D1 F3 B2 U3 R3 D2 U3 L2 U3 L3 F2 U3 R2 U1 F2 R2 L2 D3 F2 F2 B2 L2 D2 F2 R2 D2 B2 R2 F2 L2  (moves 33)
L1 B1 U3 F3 U1 L2 D3 L1 B2 R1 L3 U3 L3 U3 L2 D3 L2 U1 L2 B2 F2 U3 L2 D2 L2 U2 R2 F2 D2 B2 U2 R2 U2  (moves 33)
F1 U1 B3 F3 B2 U2 D3 L3 U3 L3 U3 R2 D3 B2 D2 L2 U3 R2 U2 F2 U3 F2 L2 D2 L2 R2 F2 L2 U2 L2 D2 U2 F2 U2  (moves 34)
D1 L3 R1 F2 U2 F3 U3 F2 D3 L3 D2 L3 U2 L3 D1 L2 U3 R2 D1 B2 U1 L2 R2 U2 L2 D2 B2 R2 F2 L2 D2 U2 F2 U2  (moves 34)
L2 R3 D1 F3 D3 L1 U3 L3 D2 L3 B2 L2 U1 R2 U2 F2 U3 F2 L2 F2 L2 B2 U2 R2 U2 R2 B2 U2 B2  (moves 29)
L2 U2 R1 B3 F3 U1 L1 D3 F2 U2 R3 U2 L3 L2 U2 L2 D2 L2 F2 U3 F2 U2 L2 U2 B2 U2 R2 D2 R2 B2  (moves 30)
L2 F1 U2 F3 D3 R3 U1 D3 L3 D1 U1 L3 R2 D3 R2 F2 D2 B2 U3 F2 U1 F2 D2 L2 B2 U2 L2 U2 R2 B2 F2 U2  (moves 32)
F3 D2 F3 L2 B2 D3 L2 U3 B2 L3 L2 F2 L2 D3 L2 B2 U3 L2 L2 U2 F2 D2 L2 D2 L2 B2 L2 F2 L2 U2  (moves 30)
F3 R2 U3 F3 U3 R3 D2 R2 D1 F2 U2 L3 D3 L2 D3 R2 U1 F2 U3 L2 U1 F2 L2 B2 D2 B2 L2 F2 U2 L2 F2 D2  (moves 32)
B1 R1 U1 D3 F3 R2 U1 L2 R2 D2 B2 U3 L3 R2 F2 U1 L2 B2 U1 F2 U3 L2 U3 R2 U2 F2 D2 F2 L2 B2 L2 U2 F2  (moves 33)
L3 D3 U1 B3 L2 F2 D3 L3 R1 U1 R3 L2 D3 F2 R2 U3 F2 R2 U3 L2 D2 R2 U2 B2 U2 B2 L2 U2 R2 F2 U2  (moves 31)
L1 F3 L2 R1 B3 L1 U3 L1 R1 D3 F2 D1 R3 B2 R2 U1 F2 L2 D1 R2 F2 D2 L2 R2 B2 R2 B2 U2 L2 U2  (moves 30)
U1 F1 U3 L1 B3 D1 L2 B2 R1 D3 R3 F2 L3 U3 F2 B2 L2 U3 B2 D3 L2 U3 L2 D2 R2 F2 D2 L2 F2 D2 F2  (moves 31)
D2 L3 U1 F3 U1 D3 L1 F2 D3 R3 F2 U3 R3 L2 U1 L2 U3 L2 U1 F2 L2 U1 R2 U3 F2 U2 L2 D2 B2 U2 L2 F2 U2 F2 U2  (moves 35)
F3 L2 F3 U1 L1 U1 D2 L3 U3 L3 B2 U1 F2 U1 F2 D2 R2 U3 L2 U2 F2 U3 R2 F2 D2 L2 D2 R2 F2 U2 F2 U2 F2 U2  (moves 34)
U2 L3 B3 U2 R3 U3 L2 B2 U1 R3 R2 D3 R2 U1 R2 U3 F2 U1 F2 U3 F2 U2 L2 F2 R2 F2 D2 L2 D2 L2 B2  (moves 31)
F1 B1 R3 F3 U3 F3 B2 D1 B2 R1 U3 L1 U2 L3 F2 U3 F2 R2 U1 R2 U2 B2 D3 F2 U3 F2 B2 L2 U2 F2 L2 D2 B2 F2 L2 B2  (moves 36)
B2 D3 B3 U2 B2 D3 L3 D1 R1 U2 L3 L2 U3 B2 U1 B2 D2 R2 U3 F2 U3 U2 L2 U2 F2 D2 F2 U2 B2 L2 D2 F2 R2 F2  (moves 34)

Average number of moves = 16.72

Average time = 127 milliseconds

When run with a file containing the single line:

UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL

a typical result was:

U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)

Average number of moves = 29.0

Average time = 522 milliseconds

Nim

Translation of: Kotlin

<lang Nim>#[

  • A cube 'state' is a sequence of ints with 40 entries, the first
  • 20 are a permutation of {0,...,19} and describe which cubie is
  • at a certain position (regarding the input ordering). The first
  • twelve are for edges, the last eight for corners.
  • The last 20 entries are for the orientations, each describing
  • how often the cubie at a certain position has been turned
  • counterclockwise away from the correct orientation. Again the
  • first twelve are edges, the last eight are corners. The values
  • are 0 or 1 for edges and 0, 1 or 2 for corners.

]#

import deques, os, strformat, strutils, tables, times

const

 ApplicableMoves = [0, 262143, 259263, 74943, 74898]
 AffectedCubies = [[0,  1, 2,  3, 0, 1, 2, 3],  # U
                   [4,  7, 6,  5, 4, 5, 6, 7],  # D
                   [0,  9, 4,  8, 0, 3, 5, 4],  # F
                   [2, 10, 6, 11, 2, 1, 7, 6],  # B
                   [3, 11, 7,  9, 3, 2, 6, 5],  # L
                   [1,  8, 5, 10, 1, 0, 4, 7]]  # R

type State = seq[int]

func initState(n: Natural = 0): State = newSeq[int](n)


var phase: Natural


proc slicetoState(s: openArray[int]): State =

 result.setLen(40)
 for i, val in s: result[i] = val
 for i in s.len..39: result[i] = -1


proc id(state: State): State =

 case phase
 of 1: # Phase 1: Edge orientations.
   result = sliceToState(state[20..31])
 of 2: # Phase 2: Corner orientations, E slice edges.
   var res = state[31..39]
   for e in 0..11:
     res[0] = res[0] or state[e] shr 3 shl e
   result = sliceToState(res)
 of 3: # Phase 3: Edge slices M and S, corner tetrads, overall parity.
   var res = @[0, 0, 0]
   for e in 0..11:
     let temp = if state[e] > 7: 2 else: (state[e] and 1) shl (2 * e)
     res[0] = res[0] or temp
   for c in 0..7:
     res[1] = res[1] or ((state[c + 12] - 12) and 5) shl (3 * c)
   for i in 12..18:
     for j in (i + 1)..19:
       res[2] = res[2] xor ord(state[i] > state[j])
   result = sliceToState(res)
 else: # Phase 4: The rest.
   result = state


proc applyMove(move: int; state: State): State =

 result = state
 var turns = move mod 3 + 1
 let face = move div 3
 while turns != 0:
   dec turns
   var oldState = result
   for i in 0..7:
     let isCorner = ord(i > 3)
     let target = AffectedCubies[face][i] + isCorner * 12
     let temp = if (i and 3) == 3: i - 3 else: i + 1
     let killer = AffectedCubies[face][temp] + isCorner * 12
     let orientationDelta =
       if i < 4: ord(face in 2..3)
       elif face < 2: 0
       else: 2 - (i and 1)
     result[target] = oldState[killer]
     result[target + 20] = oldState[killer + 20] + orientationDelta
     if turns == 0:
         result[target + 20] = result[target + 20] mod (2 + isCorner)


func inverse(move: int): int = move + 2 - 2 * (move mod 3)


let startTime = cpuTime() var aggregateMoves = 0

  1. Define the goal.

const Goal = ["UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",

             "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR"]
  1. Load dataset (file name should be passed as a command line argument).

if paramCount() == 0: quit "Missing file name", QuitFailure var lineCount = 0 for line in paramStr(1).lines():

 let inputs = line.splitWhitespace()
 inc lineCount
 var totalMoves = 0
 # Prepare current (start) and goal state.
 var currentState, goalState = initState(40)
 for i in 0..19:
   # Goal state.
   goalState[i] = i
   # Current (start) state.
   var cubie = inputs[i]
   while true:
     let idx = Goal.find(cubie)
     currentState[i] = if idx >= 0: idx else: 20
     if currentState[i] != 20: break
     cubie = cubie[1..^1] & cubie[0]
     inc currentState[i + 20]
 # Dance the funky Thistlethwaite...
 phase = 1
 while phase < 5:
   block doPhase:
     # Compute ids for current and goal state, skip phase if equal.
     let currentId = id(currentState)
     let goalId = id(goalState)
     if currentId == goalId: break doPhase
     # Initialize the BFS queue.
     var q = [currentState, goalState].toDeque
     # Initialize the BFS tables.
     var predecessor: Table[State, State]
     var direction, lastMove: Table[State, int]
     direction[currentId] = 1
     direction[goalId] = 2
     # Dance the funky bidirectional BFS.
     while true:
       # Get state from queue, compute its ID and get its direction.
       let oldState = q.popFirst()
       var oldId = id(oldState)
       let oldDir = direction[oldId]
       # Apply all applicable moves to it and handle the new state.
       var move = 0
       while move < 18:
         if (ApplicableMoves[phase] and (1 shl move)) != 0:
           # Apply the move.
           let newState = applyMove(move, oldState)
           var newId = id(newState)
           let newDir = direction.getOrDefault(newId, 0)
           # Have we seen this state (id) from the other direction already?
           # I.e. have we found a connection?
           if newDir != 0 and newDir != oldDir:
             # Make oldId represent the forwards and newId the backwards search state.
             if oldDir > 1:
               swap newId, oldId
               move = inverse(move)
             # Reconstruct the connecting algorithm.
             var algorithm: State = @[move]
             while oldId != currentId:
               algorithm.insert(lastMove.mgetOrPut(oldId, 0), 0)
               oldId = predecessor.mgetOrPut(oldId, initState())
             while newId != goalId:
               algorithm.add inverse(lastMove.mgetOrPut(newId, 0))
               newId = predecessor.mgetOrPut(newId, initState())
             # Print and apply the algorithm.
             for step in algorithm:
               stdout.write "UDFBLR"[step div 3], step mod 3 + 1, ' '
               inc totalMoves
               currentState = applyMove(step, currentState)
             # Jump to the next phase.
             break doPhase
           # If we've never seen this state (id) before, visit it.
           if newdir == 0:
             q.addLast(newState)
             direction[newId] = oldDir
             lastMove[newId] = move
             predecessor[newId] = oldId
         inc move
   inc phase
 echo &" (moves {totalMoves})"
 inc aggregateMoves, totalMoves

let elapsedTime = cpuTime() - startTime echo &"\nAverage number of moves = {aggregateMoves / lineCount}" echo &"\nAverage time = {elapsedTime * 1000 / lineCount.toFloat:.2f} milliseconds"</lang>

Output:

We compiled the program with command nim c -d:danger --gc:arc -d:lto, which means no runtime checks, ARC memory management and link time optimization.

When run with the original dataset of 100 lines, we got:

U1 U2  (moves 2)
U2  (moves 1)
U1  (moves 1)
F1 F2  (moves 2)
F2  (moves 1)
F1  (moves 1)
R1 R2  (moves 2)
R2  (moves 1)
R1  (moves 1)
D1 D2  (moves 2)
D2  (moves 1)
D1  (moves 1)
B1 B2  (moves 2)
B2  (moves 1)
B1  (moves 1)
L1 L2  (moves 2)
L2  (moves 1)
L1  (moves 1)
U2 B3 B2  (moves 3)
L2 U3  (moves 2)
R1 U1  (moves 2)
D3 L3  (moves 2)
D3 L2  (moves 2)
D2 F3 F2  (moves 3)
R2 F3  (moves 2)
R1 F2 F2 R2 F2  (moves 5)
D1 D2 U2  (moves 3)
L1 B2 F2 L2 R2 B2 F2  (moves 7)
L1 L2 D3  (moves 3)
D1 F2  (moves 2)
U2 R3  (moves 2)
L1 L2 U3  (moves 3)
U1 R2  (moves 2)
U1 R3  (moves 2)
F1 U2  (moves 2)
U2 R3 R2  (moves 3)
F2 D1 F3  (moves 3)
F2 D3 D2 U2  (moves 4)
L3 D2 R3  (moves 3)
D2 R3 R2 D3  (moves 4)
F1 R1 B2 B2 R2 B2  (moves 6)
L1 B2 F2  (moves 3)
U1 R2 B3 B2  (moves 4)
R2 F3 R2  (moves 3)
L2 D3 R3 R2  (moves 4)
L2 F3 L2 L2 F2 L2  (moves 6)
F1 R1 B3 D3 B2 D3 L3 U2 L3 U2 L2 U2 L2 U3 R2 U1 F2 L2 U2 B2 L2 F2 U2 L2 U2 F2 D2 F2 U2  (moves 29)
L1 L2 U3 R2  (moves 4)
L3 B3 B2 R3 R2  (moves 5)
B2 U1 R3 R2  (moves 4)
L3 B3 L2  (moves 3)
D1 B2 L3 L2  (moves 4)
B1 B2 R3 F2 F2 R2 F2  (moves 7)
D1 F3 D1 D2  (moves 4)
R1 B3 D1 R2 F3 L1 U2 F2 D3 B2 D1 L3 U1 F2 R2 U1 L2 U1 F2 U2 R2 U3 F2 U3 F2 D2 F2 L2 F2 L2 F2 U2 F2 D2 L2  (moves 35)
F1 R1 U3 D1 B3 U3 D2 L3 B2 R1 F2 D3 L3 U2 R2 D1 R2 B2 U2 L2 U3 U2 F2 U2 L2 B2 R2 D2 R2 D2 B2 L2 F2 U2  (moves 34)
U1 R1 F3 L1 R2 U3 L1 D2 F2 U3 L3 L2 U1 F2 D3 F2 F2 U2 D2 L2 U2 F2 R2 F2 D2 R2 U2  (moves 27)
R1 D3 R3 F3 R1 D3 F2 U1 R3 D2 U1 R3 F2 U1 L2 U3 F2 U1 B2 D2 L2 D3 F2 F2 U2 F2 D2 L2 U2 L2 F2 L2 U2 R2  (moves 34)
D2 R1 B1 L1 F3 U2 D3 L2 R1 D3 B2 U1 F2 L3 F2 U3 B2 U3 B2 L2 U3 B2 U3 F2 U2 F2 U2 L2 F2 R2 B2 D2 L2 D2 F2  (moves 35)
B3 U2 L1 F3 F2 U1 R3 D1 F2 R3 D3 B2 R3 B2 U1 F2 U3 R2 U1 R2 U3 R2 L2 F2 U2 R2 F2 D2 R2 B2 U2 R2 B2  (moves 33)
L1 F3 L2 D3 U1 F3 L1 B2 R1 U1 D1 B2 R3 U1 L2 U1 B2 U1 F2 U3 L2 D1 F2 U3 F2 U2 D2 R2 U2 L2 F2 R2 U2 F2 R2  (moves 35)
F1 R3 U2 F3 B2 U1 L1 U1 R3 B2 U1 R3 R2 U3 L2 U1 B2 U2 R2 U3 L2 U3 F2 L2 U2 F2 U2 B2 L2 D2 L2 F2 L2 F2 U2  (moves 35)
U2 D3 B3 U1 L2 D1 R1 U3 L3 D2 U1 R3 U3 B2 D3 R2 F2 U3 F2 U3 U2 B2 D2 B2 L2 F2 R2 D2 R2  (moves 29)
D2 L3 U3 F3 B2 U3 L1 U2 R3 D2 L3 U2 L2 U3 R2 B2 D3 F2 R2 U3 U2 L2 U2 F2 U2 D2 R2 F2 U2 B2 D2  (moves 31)
F1 L1 U1 L1 B3 U3 L1 F2 L1 B2 F2 U3 L3 F2 D3 B2 D3 R2 U1 F2 U3 L2 U3 U2 F2 D2 B2 U2 F2 R2 F2 L2  (moves 32)
B1 L1 U3 F3 B2 U1 L3 B2 R3 L3 U3 L3 D2 B2 D3 F2 L2 U2 R2 U3 F2 U3 F2 L2 U2 B2 L2 U2 B2 F2 R2 U2 F2  (moves 33)
F2 L3 F1 D3 B3 B2 U3 R1 D3 U3 L3 L2 R2 U3 B2 D1 B2 U3 R2 U3 F2 L2 F2 L2 U2 F2 B2 R2 B2 L2  (moves 30)
D3 F3 U1 B2 U3 L1 D1 R3 U3 F2 L3 U1 F2 U2 L2 U3 L2 B2 R2 L2 D1 F2 F2 L2 U2 F2 L2 U2 R2 D2 B2 R2 L2  (moves 33)
F2 R3 U2 F3 U2 L2 B2 D1 F2 R3 B2 D1 L3 D2 R2 B2 D1 R2 B2 U1 L2 B2 R2 B2 R2 D2 L2 D2 F2 L2 B2 L2 F2  (moves 33)
U1 R3 F3 D3 R3 B2 L3 D1 F2 U1 R3 L2 U1 B2 D1 L2 U3 R2 U1 L2 U3 F2 U3 F2 U2 B2 L2 D2 L2 U2 R2 F2  (moves 32)
F1 R1 F1 D3 B3 F3 U1 R2 F2 U1 L3 U1 F2 U2 R2 U1 R2 U3 L2 U3 D2 L2 F2 L2 F2 U2 B2 U2 L2 F2  (moves 30)
F3 R3 L2 B3 U1 B2 U1 F2 U2 B2 R3 D2 L3 B2 U1 F2 U3 L2 U1 B2 D3 L2 U1 L2 U2 L2 D2 R2 F2 D2 F2 U2 R2 U2  (moves 34)
D1 B3 D2 L1 F3 U3 F2 D2 L3 F2 L3 D3 L3 D1 L2 B2 U3 R2 U1 R2 U3 L2 U3 L2 D2 R2 D2 F2 R2 F2 L2 D2 U2 F2 U2  (moves 35)
U1 B1 D1 R3 F3 U1 B2 R1 U3 L1 D3 B2 U1 R3 U2 F2 L2 U3 R2 U1 B2 D3 B2 U1 L2 F2 U2 D2 L2 U2 B2 R2 B2 L2 D2 L2  (moves 36)
U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)
U1 B2 L1 B3 F3 U1 F2 B2 R2 D3 R3 U3 L3 B2 U1 F2 U3 F2 U3 L2 U2 F2 R2 B2 R2 U2 F2 U2 F2 U2 F2  (moves 31)
U1 B1 U3 D1 F3 U2 D3 R3 D1 U1 L1 F2 L3 D2 L2 U1 F2 B2 R2 U3 F2 U1 L2 U2 R2 F2 D2 F2 U2 L2 B2 U2 F2  (moves 33)
D1 F3 U2 R1 B3 L1 B2 R1 U3 L2 D3 F2 R3 L2 D2 L2 D3 L2 F2 U3 F2 B2 D2 L2 B2 L2 B2 D2 L2 F2 U2 F2 U2  (moves 33)
R1 B1 D3 F3 D1 R3 D3 B2 L2 B2 U2 L3 L2 U2 B2 L2 U2 F2 U3 U2 F2 L2 D2 L2 B2 U2 R2 F2 L2 B2  (moves 30)
U1 D2 F1 L1 B3 D1 B2 D3 L2 R1 D3 L2 U2 R3 D2 F2 U3 F2 R2 U1 B2 U1 F2 U3 B2 R2 U2 L2 U2 B2 D2 F2 L2 B2 F2 U2  (moves 36)
U1 L1 D1 L1 F3 L1 U1 L3 U3 L1 D1 R3 F2 U2 R2 U1 F2 U2 F2 L2 D1 F2 U3 F2 U2 R2 D2 F2 R2 B2 L2 B2 D2 B2  (moves 34)
L3 D3 U1 F3 U2 F2 D3 R3 B2 D3 U3 L3 R2 U2 L2 D3 R2 U1 L2 U2 F2 U3 F2 U3 U2 L2 U2 R2 B2 R2 B2 U2 F2 U2  (moves 34)
L1 B1 U2 D1 F3 B2 U3 R3 D2 U3 L2 U3 L3 F2 U3 R2 U1 F2 R2 L2 D3 F2 F2 B2 L2 D2 F2 R2 D2 B2 R2 F2 L2  (moves 33)
L1 B1 U3 F3 U1 L2 D3 L1 B2 R1 L3 U3 L3 U3 L2 D3 L2 U1 L2 B2 F2 U3 L2 D2 L2 U2 R2 F2 D2 B2 U2 R2 U2  (moves 33)
F1 U1 B3 F3 B2 U2 D3 L3 U3 L3 U3 R2 D3 B2 D2 L2 U3 R2 U2 F2 U3 F2 L2 D2 L2 R2 F2 L2 U2 L2 D2 U2 F2 U2  (moves 34)
D1 L3 R1 F2 U2 F3 U3 F2 D3 L3 D2 L3 U2 L3 D1 L2 U3 R2 D1 B2 U1 L2 R2 U2 L2 D2 B2 R2 F2 L2 D2 U2 F2 U2  (moves 34)
L2 R3 D1 F3 D3 L1 U3 L3 D2 L3 B2 L2 U1 R2 U2 F2 U3 F2 L2 F2 L2 B2 U2 R2 U2 R2 B2 U2 B2  (moves 29)
L2 U2 R1 B3 F3 U1 L1 D3 F2 U2 R3 U2 L3 L2 U2 L2 D2 L2 F2 U3 F2 U2 L2 U2 B2 U2 R2 D2 R2 B2  (moves 30)
L2 F1 U2 F3 D3 R3 U1 D3 L3 D1 U1 L3 R2 D3 R2 F2 D2 B2 U3 F2 U1 F2 D2 L2 B2 U2 L2 U2 R2 B2 F2 U2  (moves 32)
F3 D2 F3 L2 B2 D3 L2 U3 B2 L3 L2 F2 L2 D3 L2 B2 U3 L2 L2 U2 F2 D2 L2 D2 L2 B2 L2 F2 L2 U2  (moves 30)
F3 R2 U3 F3 U3 R3 D2 R2 D1 F2 U2 L3 D3 L2 D3 R2 U1 F2 U3 L2 U1 F2 L2 B2 D2 B2 L2 F2 U2 L2 F2 D2  (moves 32)
B1 R1 U1 D3 F3 R2 U1 L2 R2 D2 B2 U3 L3 R2 F2 U1 L2 B2 U1 F2 U3 L2 U3 R2 U2 F2 D2 F2 L2 B2 L2 U2 F2  (moves 33)
L3 D3 U1 B3 L2 F2 D3 L3 R1 U1 R3 L2 D3 F2 R2 U3 F2 R2 U3 L2 D2 R2 U2 B2 U2 B2 L2 U2 R2 F2 U2  (moves 31)
L1 F3 L2 R1 B3 L1 U3 L1 R1 D3 F2 D1 R3 B2 R2 U1 F2 L2 D1 R2 F2 D2 L2 R2 B2 R2 B2 U2 L2 U2  (moves 30)
U1 F1 U3 L1 B3 D1 L2 B2 R1 D3 R3 F2 L3 U3 F2 B2 L2 U3 B2 D3 L2 U3 L2 D2 R2 F2 D2 L2 F2 D2 F2  (moves 31)
D2 L3 U1 F3 U1 D3 L1 F2 D3 R3 F2 U3 R3 L2 U1 L2 U3 L2 U1 F2 L2 U1 R2 U3 F2 U2 L2 D2 B2 U2 L2 F2 U2 F2 U2  (moves 35)
F3 L2 F3 U1 L1 U1 D2 L3 U3 L3 B2 U1 F2 U1 F2 D2 R2 U3 L2 U2 F2 U3 R2 F2 D2 L2 D2 R2 F2 U2 F2 U2 F2 U2  (moves 34)
U2 L3 B3 U2 R3 U3 L2 B2 U1 R3 R2 D3 R2 U1 R2 U3 F2 U1 F2 U3 F2 U2 L2 F2 R2 F2 D2 L2 D2 L2 B2  (moves 31)
F1 B1 R3 F3 U3 F3 B2 D1 B2 R1 U3 L1 U2 L3 F2 U3 F2 R2 U1 R2 U2 B2 D3 F2 U3 F2 B2 L2 U2 F2 L2 D2 B2 F2 L2 B2  (moves 36)
B2 D3 B3 U2 B2 D3 L3 D1 R1 U2 L3 L2 U3 B2 U1 B2 D2 R2 U3 F2 U3 U2 L2 U2 F2 D2 F2 U2 B2 L2 D2 F2 R2 F2  (moves 34)
Average number of moves = 16.72

Average time = 52.03 milliseconds

When run with a file containing the single line:

UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL

a typical result was:

U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)

Average number of moves = 29.0

Average time = 69.01 milliseconds

Phix

cfop

Uses brute-force (width/highscore-first) Fridrich-steps (ie cross,f2l,oll,pll).
Not the fastest (see THRESHOLD) or shortest results (see thistlethwaite) but the code is pretty easy to follow.
The final stage (pll) would probably benefit the most from being replaced with standard algorithms.
While technically this works under pwa/p2js, you should expect a blank screen for nearly 3 minutes.

--
-- demo\rosetta\rubik_cfop.exw
--
-- Each stage uses a workspace of moves tried so far, ranked by score.
-- We repeatedly take the best scoring so far and try more moves, storing
-- those results in a second/new workspace. The THRESHOLD value below
-- determines the minimum number we should examine before discarding a
-- workspace and switching to the new (one move longer) one. We only ever
-- switch on change of score, and obviously the first workspace is empty,
-- and the next new workspace has a maximum of 12 entries (+/-90 by 6), 
-- both of which will force earlier switches.
--
with javascript_semantics
constant THRESHOLD =   100000 -- 100000 -- very slow (100s), best results
--                      10000 --  10000 -- slow (10s), reasonable results
                              --   1000 -- fast (1s), fairly poor results
                              --    100 -- (counter-productive/slower)
 
string init ="""
---YYY--------
---YYY--------
---YYY--------
BBBRRRGGGOOO--
BBBRRRGGGOOO--
BBBRRRGGGOOO--
------WWW-----
------WWW-----
------WWW-----

"""
-- numbering:
--  1..15:   ---456--------\n
--  16..30:  ---901--------\n   -- U
--  31..45:  ---456--------\n
--  46..60:  678901234567--\n
--  61..75:  123456789012--\n   -- LFRB
--  76..90:  678901234567--\n
--  91..105: ------789-----\n
--  106..120:------234-----\n   -- D
--  121..136:------789-----\n\n
 
if length(init)!=136 then ?9/0 end if
 
--
-- TIP: Wrap a cube with blank paper, and write
--      the numbers on it, to derive these sets.
--
constant centres = {20,62,65,68,71,113}
 
constant edges = {{  4,  5,  6,57,56,55},   -- ie YYY/OOO
                  {  6, 21, 36,54,53,52},   --    YYY/GGG
                  { 34, 35, 36,49,50,51},   --    YYY/RRR
                  {  4, 19, 34,46,47,48},   --    YYY/BBB
                  { 51, 66, 81,52,67,82},   --    RRR/GGG
                  { 54, 69, 84,55,70,85},   --    GGG/OOO
                  { 57, 72, 87,46,61,76},   --    OOO/BBB
                  { 48, 63, 78,49,64,79},   --    BBB/RRR
                  { 97, 98, 99,82,83,84},   --    WWW/GGG
                  { 99,114,129,85,86,87},   --    WWW/OOO
                  {127,128,129,78,77,76},   --    WWW/BBB
                  { 97,112,127,81,80,79}}   --    WWW/RRR
 
constant corners = {{ 4, 57,46},{34,48, 49},{36,51,52},{ 6,54,55},
                --   YOB/UBL     YBR/UFL     YRG/UFR    YGO/UBL
                    {76,129,87},{78,79,127},{81,82,97},{84,85,99}}
                --   BWO/DBL     BRW/DFL     RGW/DFR    GOW/DFL
 
constant facing_corners = {-16,-14,16,14}, -- (nb not 14,16)
         facing_edges   = {-15,  1,15,-1},
         fce = facing_corners&facing_edges,
         rotations = {
                      -- up (clockwise):
                      {{57,54,51,48},   -- clockwise corners
                       {46,55,52,49},   -- anticlockwise corners
                       {47,56,53,50}},  -- middle edges
                      -- left
                      {{ 4,49,127, 87},
                       {57,34, 79,129},
                       {19,64,128, 72}},
                      -- front
                      {{34,52, 97, 78},
                       {48,36, 82,127},
                       {35,67,112, 63}},
                      -- right
                      {{36,55,99,81},
                       {51, 6,85,97},
                       {21,70,98,66}},
                      -- back
                      {{ 6,46,129,84},
                       {54, 4, 76,99},
                       { 5,61,114,69}},
                      -- down
                      {{82,85,76,79},
                       {81,84,87,78},
                       {83,86,77,80}}}
 
--Up/Left/Front/Right/Back/Down
enum U=1,L=2,F=3,R=4,B=5,D=6,Dbl=#08,Shift=#10
constant U2 = U+Dbl, F2 = F+Dbl, /*R2 = R+Dbl, B2 = B+Dbl,*/ D2 = D+Dbl,
         Us = U+Shift, Fs = F+Shift, Bs = B+Shift, Rs = R+Shift, Ds = D+Shift
 
enum CROSS,F2L,OLL,PLL
 
integer f2l = 0         -- (28==done)
integer edge_score = 0  -- (0..12 for f2l [as U cleared],
                        --  0..24 for oll and pll stages)
 
function score(string cube, integer stage)
    integer res = 0, c, cc, k
    f2l = 0
    for i=1 to length(centres) do
        c = centres[i]
        cc = cube[c]
        for j=1 to length(fce) do -- (the 8 next to c)
            k = c+fce[j]
            if cube[k]=cc then
                res += 1
                f2l += (stage>CROSS and k>=61)
            end if
        end for
    end for
    -- give extra credit for edges paired with corners
    edge_score = 0  -- += (0|1|2) for the 12 edges:
    if stage>CROSS then
        for i=1 to length(edges) do
            sequence ei = edges[i]  -- as 123
            --                      --    456
            -- then if {1,4}=={2,5} then edge_score += 1, 
            -- plus if {2,5}=={3,6} then edge_score += 1.
            edge_score += (cube[ei[1]]=cube[ei[2]] and
                           cube[ei[4]]=cube[ei[5]]) +
                          (cube[ei[2]]=cube[ei[3]] and
                           cube[ei[5]]=cube[ei[6]])
        end for
    end if
    return res
end function
 
function oll_score(string cube)
-- (should only be invoked if f2l==28)
    integer res = 0     -- (true if res=8)
    integer cu = centres[U]
    if cube[cu]!='Y' then ?9/0 end if
    for i=1 to length(fce) do
        integer fcei = fce[i]
        res += (cube[cu+fcei]='Y')
    end for
    return res
end function
 
function rotate_face(string cube, integer face)
--
-- face is 1..6 for clockwise (ULFRBD), 
-- plus #08(Dbl) for a 180 (clockwise),
-- plus #10(Shift) for anti-clockwise.
--
    integer dbl = 1+(and_bits(face,Dbl)=Dbl)
    bool cw = 1-floor(face/Shift)
    face = remainder(face,Dbl)
    integer cf = centres[face]
    sequence rf = {sq_add(facing_corners,cf),
                   sq_add(facing_edges,cf)}
                  &rotations[face]
    for d=1 to dbl do
        for i=1 to length(rf) do
            sequence rfi = rf[i]
            if cw then rfi = reverse(rfi) end if
            integer rfi1 = cube[rfi[1]]
            for j=1 to 3 do
                cube[rfi[j]] = cube[rfi[j+1]]
            end for
            cube[rfi[4]] = rfi1
        end for
    end for
    return cube
end function
 
function apply_moves(string cube, sequence moves)
    for i=1 to length(moves) do
        cube = rotate_face(cube,moves[i])
    end for
    return cube
end function
 
constant ULFRBD = "ULFRBD"
 
function moves_to_string(sequence moves)
-- convert eg {1,20,11} to "UR'F2"
    string res = ""
    integer l = length(moves)
    for i=1 to l do
        integer face = moves[i]
        integer dbl = and_bits(face,Dbl)=Dbl
        bool anticw = floor(face/Shift)
        face = remainder(face,Dbl)
        res &= ULFRBD[face]
        if dbl then
            res &= '2'
        elsif anticw then
            res &= '\''
        end if
    end for
    res &=sprintf("  (%d move%s)     ",{l,iff(l=1?"":"s")})
    return res
end function
 
--
-- The seen dictionary.
--  Without this, since it uses a breadth/highscore-first
--  algorithm, after f2l (for instance) it would probably
--  just do U and U' as the new high scores, forever.
--  (The THRESHOLD constant mitigates that to some extent)
--
integer seen = new_dict()
 
function solve_stage(string cube, integer stage)
    atom t1 = time()+1
    string moves = "", moves2
    sequence workspace, w2, init
    integer wslen, high = 1,
            s, c2c = 0, o = 0
    bool done
 
    if stage=CROSS then
        --
        -- first, blank out all corners, and   
        -- all edges without a white on them.
        --
        for i=1 to length(rotations) do
            for j=1 to 2 do -- (just corners)
                for k=1 to 4 do
                    cube[rotations[i][j][k]]='-'
                end for
            end for
        end for
        for i=1 to length(edges) do
            integer {?,m1,?,?,m2,?} = edges[i]
            if cube[m1]!='W'
            and cube[m2]!='W' then
                cube[m1] = '-'
                cube[m2] = '-'
            end if
        end for
        wslen = 8
        s = score(cube,CROSS)
        done = (s=8)
    elsif stage=F2L then
        --
        -- first, blank out all pieces with a yellow
        --
        for i=1 to length(corners) do
            integer {c1,c2,c3} = corners[i]
            if cube[c1]='Y'
            or cube[c2]='Y'
            or cube[c3]='Y' then
                cube[c1] = '-'
                cube[c2] = '-'
                cube[c3] = '-'
            end if
        end for
        for i=1 to length(edges) do
            integer {?,m1,?,?,m2,?} = edges[i]
            if cube[m1]='Y'
            and cube[m2]='Y' then
                cube[m1] = '-'
                cube[m2] = '-'
            end if
        end for
        wslen = 57+12
        s = score(cube,F2L)
        done = (f2l=28)
    else
        wslen = 77+24
        s = score(cube,stage)
        if f2l!=28 then ?9/0 end if
        if stage=OLL then
            done = (oll_score(cube)=8)
        else -- (stage=PLL)
            done = (s=48)
        end if
    end if
    if not done then
        workspace = repeat({},wslen)
        w2 = deep_copy(workspace)
        init = cube
        workspace[high] = {""}
        destroy_dict(seen,justclear:=1)
        integer move_count = 1
        while 1 do
            if workspace[high]={} then
                while high and workspace[high]={} do high -= 1 end while
                if high=0 or (stage!=CROSS and c2c>THRESHOLD) then
                    move_count += 1
                    workspace = w2
                    w2 = repeat({},wslen)
                    c2c = 0
                    high = wslen
                    while workspace[high]={} do high -= 1 end while
                end if
            end if
            moves = workspace[high][1]
            workspace[high] = workspace[high][2..$]
            cube = apply_moves(init,moves)
            for face=U to D do
                -- (originally this loop did 180s as well, but that
                --  gave them far too much dominance, esp during pll.
                --  instead we now coalese those that survive a 90.)
                for m=0 to Shift by Shift do
                    integer mi = face+m
                    sequence cube2 = rotate_face(cube,mi)
                    if getd_index(cube2,seen)=0 then
                        putd(cube2,0,seen)
                        s = score(cube2,stage)
                        if stage=CROSS then
                            done = (s=8)
                        elsif stage=F2L then
                            done = (f2l=28)
                        else
                            if f2l=28 then
                                o = oll_score(cube2)
                            else
                                o = 0
                            end if
                            if stage=OLL then
                                done = (o=8)
                            else
                                done = (s=48)
                            end if
                        end if
                        moves2 = moves
                        if length(moves2) and moves2[$]=mi then
                            moves2[$] = face+Dbl
                        else
                            moves2 &= mi
                        end if
                        if done then
                            destroy_dict(seen,justclear:=1)
                            return moves2
                        end if
                        s += 1+edge_score*2+o
                        w2[s] = append(w2[s],moves2)
                        c2c += 1
                    end if
                end for
            end for
            if time()>t1 and platform()!=JS then
                printf(1,"working... %d moves, %d positions\r",{move_count,dict_size(seen)})
                t1 = time()+1
                if get_key()=#1B then exit end if
            end if
        end while   
    end if
    return ""   -- (already solved case)
end function
 
constant stage_desc = { "make cross",
                        "solve first two layers",
                        "orientate last layer",
                        "permute last layer" }
 
procedure main()
    string cube
    sequence moves
    integer total_moves = 0
    atom t0 = time()
 
    -- "hardest case" from http://www.cube20.org
    moves = {F, Us, F2, Ds, B, U, Rs, Fs, L, Ds, 
             Rs, Us, L, U, Bs, D2, Rs, F, U2, D2}
    cube = apply_moves(init,moves)
    if length(moves)<=20 then
        printf(1,"scramble: %s\n",{moves_to_string(moves)})
    end if
 
    puts(1,substitute(cube,"-"," "))
 
    for stage=CROSS to PLL do
        moves = solve_stage(cube, stage)
        total_moves += length(moves)
        cube = apply_moves(cube,moves)
        printf(1,"%s: %s\n",{stage_desc[stage],moves_to_string(moves)})
        if length(moves) then
            puts(1,substitute(cube,"-"," "))
        end if
    end for
    printf(1,"\nsolution of %d total moves found in %3.2fs\n",{total_moves,time()-t0})
end procedure
main()
Output:

The "hardest case" from http://www.cube20.org with a high threshold. You can try this manually. Disclaimer: the results are not always quite as good as this!

scramble: FU'F2D'BUR'F'LD'R'U'LUB'D2R'FU2D2  (20 moves)
   ROB
   BYG
   GRO
YYOYYBYYRYYG
RBOBRGOGRGOB
WWOWWBWWRWWG
      OGB
      RWO
      GBR

make cross: DLBRFL  (6 moves)
   BRB
   YYG
   YYY
ROBRBRGOYOGW
OBRBRYRGYGOB
RBYORGOGOBOW
      WWW
      WWW
      GWG

solve first two layers: FUL'R'FLRF'LRB'R'U'BU'B'U'B  (18 moves)
   RYG
   OYR
   YYY
BYRGGOBYOYBY
BBBRRRGGGOOO
BBBRRRGGGOOO
      WWW
      WWW
      WWW

orientate last layer: R'F'U'FUR  (6 moves)
   YYY
   YYY
   YYY
GGBRRGOOOBBR
BBBRRRGGGOOO
BBBRRRGGGOOO
      WWW
      WWW
      WWW

permute last layer: RU'L'UR'U2LU'L'U2LU'  (12 moves)
   YYY      
   YYY      
   YYY      
BBBRRRGGGOOO
BBBRRRGGGOOO
BBBRRRGGGOOO
      WWW
      WWW
      WWW


solution of 42 total moves found in 81.33s

thistlethwaite

Translation/de-golf(hrumph) of Tomas Sirgedas' winning entry from http://tomas.rokicki.com/cubecontest as held in 2004.
Faster and shorter solutions (in most cases) than cfop, however probably nigh on impossible to debug/enhance...

--
-- demo\rosetta\rubik_tomas.exw
--
with javascript_semantics
function xor_string(string s)
    return xor_bits(s[1],xor_bits(s[2],iff(length(s)=3?s[3]:'!')))
end function

function xor_all(sequence s)
    for i=1 to length(s) do
        s[i] = xor_string(s[i])
    end for
    return s
end function

constant d1 = xor_all(split("UF DF UB DB UR DR UL DL FR FL BR BL UFR DBR UBL DFL DLB ULF DRF URB"))
-- This is Mike Reid's notation, 12 sides then 8 corners, which may be rotated - hence we xor the
-- characters for fast lookup. The above string represents a cube in the solved state.

constant d2 = {18,12,17,15,0, 9,1,8,16,14,19,13,2,10,3,11,12,18,13,19,4,8,5,10,
               14,16,15,17,6,11,7,9,17,12,19,14,6, 0,4, 2,18,15,16,13,1,7,3, 5}
--?sort(d2): (0..11 appear twice, 12..19 appear thrice - edges/corners is pretty much all I can say)

constant d3 = {13,16,15,1,3,
               19,18,17,4,6}
-- these apppear to be swapped during initialisation, dunno why...

integer cur_phase, search_mode, history_idx
sequence history_mov = repeat(0,48),
         history_rpt = repeat(0,48),
         depth_to_go,
         hash_table = repeat(repeat(6,6912),48)
         -- (hash_table can/should be preserved for different problems)

sequence cubelet_pos = repeat(0,48),
         cubelet_twi = repeat(0,48)

procedure rot(integer cur_phase)
    if cur_phase<4 then
        for i=0 to 3 do
            integer di = cur_phase*8+i+1,
                    j = d2[di]+1,
                    k = d2[di+4]+1
            cubelet_twi[j] = mod(cubelet_twi[j]+2-mod(i,2),3)
            cubelet_twi[k] = xor_bits(cubelet_twi[k],cur_phase<2)
        end for
    end if
    
    for i=0 to 6 do
        integer di = cur_phase*8+i+1,
                j = d2[di+(i!=3)]+1,
                k = d2[di]+1
        -- swap(cubelet[j]], cubelet[k]);
        {cubelet_pos[j],cubelet_pos[k]} = {cubelet_pos[k],cubelet_pos[j]}
        {cubelet_twi[j],cubelet_twi[k]} = {cubelet_twi[k],cubelet_twi[j]}
    end for
end procedure

function hashf()
    int ret = 0;
    switch cur_phase do
        case 0:
                for i=0 to 10 do
                    ret += ret + cubelet_twi[i+1]
                end for
                return ret;
        case 1:
                for i=0 to 6 do
                    ret = ret*3 + cubelet_twi[i+12+1]
                end for
                for i=0 to 10 do
                    ret += ret + (cubelet_pos[i+1]>7)
                end for
                return ret-7;
        case 2:
                sequence inva = repeat(0,48),
                         b = repeat(0,48)
                for i=0 to 7 do
                    integer ci12p = cubelet_pos[i+12+1], 
                            ci12p3 = and_bits(ci12p,3)
                    if ci12p<16 then
                        inva[ci12p3+1] = ret
                        ret += 1
                    else
                        b[i-ret+1] = ci12p3 
                    end if
                end for
                for i=0 to 6 do
                    ret += ret + (cubelet_pos[i+1]>3);
                end for
                for i=0 to 6 do
                    ret += ret + (cubelet_pos[i+12+1]>15);
                end for
                integer ib2 = xor_bits(inva[b[1]+1],inva[b[2]+1])*2,
                        ib3 = xor_bits(inva[b[1]+1],inva[b[3]+1]),
                        ib4 = xor_bits(inva[b[1]+1],inva[b[4]+1])
                return ret*54 + ib2 + (ib3 > ib4) - 3587708
    end switch
    for i=0 to 4 do
        ret *= 24;
        for cp=0 to 3 do
            for k=0 to cp-1 do
                if cubelet_pos[i*4+cp+1] < cubelet_pos[i*4+k+1] then
                    ret += cp + iff(cp=3?cp:0)
                end if
            end for
        end for
    end for
    return floor(ret/2)
end function

function do_search(integer dpt)
    integer h = hashf(), 
            q = (floor(cur_phase/2)*19+8)*power(2,7),
            hmq = mod(h,q)+1,
            hfq = floor(h/q)+1,
            d = (dpt < hash_table[cur_phase+1][hmq] or 
                 dpt < hash_table[cur_phase+4+1][hfq])

    if d xor search_mode then
        if search_mode then
            if dpt <= depth_to_go[h+1] then
                return not h;
            else
                depth_to_go[h+1] = dpt;
            end if
        end if

        hash_table[cur_phase+1][hmq] = min(hash_table[cur_phase+1][hmq],dpt);
        hash_table[cur_phase+5][hfq] = min(hash_table[cur_phase+5][hfq],dpt);
        
        for k=0 to 5 do
            for i=0 to 3 do
                rot(k)
                if (k>=cur_phase*2 or i=1) and i<=2 then
                    history_idx += 1
                    history_mov[history_idx] = k
                    history_rpt[history_idx] = i
                    if do_search(dpt-search_mode*2+1) then return 1 end if
                    history_idx -= 1
                end if
            end for
        end for
    end if
    return 0
end function

function pack_moves()
string moves = ""
integer n = 0, curr, last, last_rpt
    if history_idx!=0 then
        -- add a dummy move to trigger the last move print:
        last = xor_bits(history_mov[history_idx],1) -- F<->B, etc
        history_idx += 1
        history_mov[history_idx] = last
        history_rpt[history_idx] = 0
        last = history_mov[1]
        last_rpt = 0
        for i=1 to history_idx do
            curr = history_mov[i]
            if curr!=last then
                -- coalesce eg F1F2 to F' (unless you wanna fix do_search()!)
                if last_rpt then
                    moves &= "FBRLUD"[last+1] & {"","2","'"}[last_rpt]
                    n += 1
                end if
                last = curr
                last_rpt = history_rpt[i]+1
            else
                last_rpt = mod(last_rpt+history_rpt[i]+1,4)
            end if
        end for
    end if
    return {moves,n,iff(n=1?"":"s")}
end function

function tomas(sequence args)
    search_mode = 0
    history_idx = 0
    depth_to_go = repeat(0,5*power(2,20))

    for i=0 to 19 do
        cubelet_pos[i+1] = i
    end for
    for i=0 to 3 do
        cur_phase = i
        {} = do_search(0)
    end for
    args = split(args)
    for i=0 to 19 do
        string s = args[i+1]    -- (may be rotated, eg RU or UR)
        integer p = find(xor_string(s),d1)
        if p=0 then ?9/0 end if -- sensible message(bad args)?
        cubelet_pos[i+1] = p-1
        int x = max(find('U',s), find('D',s));
        cubelet_twi[i+1] = iff(x!=0 ? x-1 : s[1]>'F')
    end for
    for i=0 to 4 do
        integer j = d3[i+1]+1,
                k = d3[i+6]+1
        -- swap(cubelet[j], cubelet[k]);        
        {cubelet_pos[j],cubelet_pos[k]} = {cubelet_pos[k],cubelet_pos[j]}
        {cubelet_twi[j],cubelet_twi[k]} = {cubelet_twi[k],cubelet_twi[j]}
    end for
    search_mode = 1;
    for cp=0 to 3 do
        cur_phase = cp
        for i=0 to 19 do
            if do_search(i) then exit end if
        end for
    end for
    return pack_moves()
end function

printf(1,"%s (%d move%s)\n",tomas("UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL"))
Output:
UF'R'FB2R2B2LD2L2DLR2U'F2UF2U2F2L2UF2DF2U2R2U2R2B2D2R2F2L2B2D2 (35 moves)

The distributed copy of demo\rosetta\rubik_cfop.exw also contains routines to convert between my 136-character cube and reid notation, and demo\rosetta\rubik_tomas.exw also contains the full 100-long test set from the original competition.

Wren

Translation of: Kotlin

Wren has a similar problem to Go in that Lists cannot be used as Map keys. Worse still Wren doesn't support fixed size arrays so I've had to convert the Lists to space delimited Strings which is an expensive operation.

Despite this, the script is taking an average of just over a second to calculate the number of moves for each line which is probably not too bad for an interpreted language. <lang ecmascript>/**********************************************************************

*
* A cube 'state' is an int array with 40 entries, the first 20
* are a permutation of {0,...,19} and describe which cubie is at
* a certain position (regarding the input ordering). The first
* twelve are for edges, the last eight for corners.
*
* The last 20 entries are for the orientations, each describing
* how often the cubie at a certain position has been turned
* counterclockwise away from the correct orientation. Again the
* first twelve are edges, the last eight are corners. The values
* are 0 or 1 for edges and 0, 1 or 2 for corners.
*
**********************************************************************/

import "os" for Process import "io" for File

var applicableMoves= [0, 262143, 259263, 74943, 74898]

var phase = 0

var affectedCubies = [

   [0,  1, 2,  3, 0, 1, 2, 3],   // U
   [4,  7, 6,  5, 4, 5, 6, 7],   // D
   [0,  9, 4,  8, 0, 3, 5, 4],   // F
   [2, 10, 6, 11, 2, 1, 7, 6],   // B
   [3, 11, 7,  9, 3, 2, 6, 5],   // L
   [1,  8, 5, 10, 1, 0, 4, 7]    // R

]

var btoi = Fn.new { |b| (b) ? 1 : 0 }

var applyMove = Fn.new { |move, origState|

   var state = origState[0..-1] // make copy so don't mutate original
   var turns = move%3 + 1
   var face = (move/3).floor
   while (turns != 0) {
       turns = turns - 1
       var oldState = state[0..-1]  // make a copy prior to mutation
       for (i in 0..7) {
           var isCorner = btoi.call(i > 3)
           var target = affectedCubies[face][i] + isCorner*12
           var temp = (i&3 == 3) ? i - 3 : i + 1
           var killer = affectedCubies[face][temp] + isCorner*12
           var orientationDelta
           if (i < 4) {
               orientationDelta = btoi.call(face > 1 && face < 4)
           } else if (face < 2) {
               orientationDelta = 0
           } else {
               orientationDelta = 2 - (i&1)
           }
           state[target] = oldState[killer]
           state[target+20] = oldState[killer+20] + orientationDelta
           if (turns == 0) state[target+20] = state[target+20] % (2 + isCorner)
       }
   }
   return state

}

var inverse = Fn.new { |move| move + 2 - 2*(move%3) }

var id = Fn.new { |state|

   //--- Phase 1: Edge orientations.
   if (phase < 2) return state[20...32]
   //--- Phase 2: Corner orientations, E slice edges.
   if (phase < 3) {
       var result = state[31...40]
       for (e in 0..11) result[0] = result[0] | ((state[e]/8).floor << e)
       return result
   }
   //--- Phase 3: Edge slices M and S, corner tetrads, overall parity.
   if (phase < 4) {
       var result = [0, 0, 0]
       for (e in 0..11) {
           var temp = ((state[e] > 7) ? 2 : state[e] & 1) << (2 * e)
           result[0] = result[0] | temp
       }
       for (c in 0..7) {
           var temp = ((state[c + 12] - 12) & 5) << (3 * c)
           result[1] = result[1] | temp
       }
       for (i in 12..18) {
           for (j in i+1..19) result[2] = result[2] ^ btoi.call(state[i] > state[j])
       }
       return result
   }
   //--- Phase 4: The rest.
   return state

}

var startTime = System.clock var aggregateMoves = 0

//--- Define the goal. var goal = ["UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",

   "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR"]

//--- Load dataset (file name should be passed as a command line argument). if (Process.arguments.count != 1) {

   Fiber.abort("The file name should be passed as a command line argument.")

}

var lines = File.read(Process.arguments[0]).split("\n") if (lines[-1] == "") lines.removeAt(-1) // if there's a final blank line remove it var lineCount = lines.count for (line in lines) {

   var inputs = line.split(" ")
   phase = 0
   var totalMoves = 0
   //--- Prepare current (start) and goal state.
   var currentState = List.filled(40, 0)
   var goalState = List.filled(40, 0)
   for (i in 0..19) {
       //--- Goal state.
       goalState[i] = i
       //--- Current (start) state.
       var cubie = inputs[i]
       while (true) {
           var idx = -1
           for (c in 0...goal.count) {
               if (goal[c] == cubie) {
                   idx = c
                   break
               }
           }
           currentState[i] = (idx >= 0) ? idx : 20
           if (currentState[i] != 20) break
           cubie = cubie[1..-1] + cubie[0]
           currentState[i+20] = currentState[i+20] + 1
       }
   }
   //--- Dance the funky Thistlethwaite..
   phase = phase + 1
   while (phase < 5) {
       var nextPhase = false
       //--- Compute ids for current and goal state, skip phase if equal.
       var currentId = id.call(currentState).join(" ")
       var goalId = id.call(goalState).join(" ")
       if (currentId != goalId) {
           //--- Initialize the BFS queue.
           var q = [currentState, goalState]
           //--- Initialize the BFS tables.
           var predecessor = {}
           var direction = {}
           var lastMove = {}
           direction[currentId] = 1
           direction[goalId] = 2
           //--- Dance the funky bidirectional BFS...
           while (true) {
               //--- Get state from queue, compute its ID and get its direction.
               var oldState = q[0]
               q = q[1..-1]
               var oldId = id.call(oldState).join(" ")
               var oldDir = direction[oldId]
               if (oldDir == null) {
                   oldDir = 0
                   direction[oldId] = 0
               }
               //--- Apply all applicable moves to it and handle the new state.
               var move = 0
               while (move < 18) {
                   if ((applicableMoves[phase] & (1 << move)) != 0) {
                       //--- Apply the move.
                       var newState = applyMove.call(move, oldState)
                       var newId = id.call(newState).join(" ")
                       var newDir = direction[newId]
                       if (newDir == null) {
                           newDir = 0
                           direction[newId] = 0
                       }
                       //--- Have we seen this state (id) from the other direction already?
                       //--- I.e. have we found a connection?
                       if (newDir != 0 && newDir != oldDir) {
                           //--- Make oldId represent the forwards
                           //--- and newId the backwards search state.
                           if (oldDir > 1) {
                               var t = newId
                               newId = oldId
                               oldId = t
                               move = inverse.call(move)
                           }
                           //--- Reconstruct the connecting algorithm.
                           var algorithm = [move]
                           while (oldId != currentId) {
                               var t = lastMove[oldId]
                               if (t == null) {
                                   t = 0
                                   lastMove[oldId] = 0
                               }
                               algorithm.insert(0, t)
                               oldId = predecessor[oldId]
                               if (oldId == null) {
                                   oldId = ""
                                   predecessor[oldId] = ""
                               }
                           }
                           while (newId != goalId) {
                               var t = lastMove[newId]
                               if (t == null) {
                                   t = 0
                                   lastMove[newId] = 0
                               }
                               algorithm.add(inverse.call(t))
                               newId = predecessor[newId]
                               if (newId == null) {
                                   newId = ""
                                   predecessor[newId] = ""
                               }
                           }
                           //--- Print and apply the algorithm.
                           for (i in 0...algorithm.count) {
                               System.write("UDFBLR"[(algorithm[i]/3).floor])
                               System.write(algorithm[i]%3 + 1)
                               System.write(" ")
                               totalMoves = totalMoves + 1
                               currentState = applyMove.call(algorithm[i], currentState)
                           }
                           nextPhase = true
                           break
                       }

                       //--- If we've never seen this state (id) before, visit it.
                       if (newDir == 0) {
                           q.add(newState)
                           direction[newId] = oldDir
                           lastMove[newId] = move
                           predecessor[newId] = oldId
                       }
                   }
                   move  = move + 1
               }
               if (nextPhase) break
           }
       }
       phase = phase + 1
   }
   System.print(" (moves %(totalMoves))")
   aggregateMoves = aggregateMoves + totalMoves

} var endTime = System.clock var elapsedTime = ((endTime - startTime) * 1000).round System.print("\nAverage number of moves = %(aggregateMoves/lineCount)") System.print("\nAverage time = %(elapsedTime/lineCount) milliseconds")</lang>

Output:

Using the original dataset of 100 lines, the results were as follows:

U1 U2  (moves 2)
U2  (moves 1)
U1  (moves 1)
F1 F2  (moves 2)
F2  (moves 1)
F1  (moves 1)
R1 R2  (moves 2)
R2  (moves 1)
R1  (moves 1)
D1 D2  (moves 2)
D2  (moves 1)
D1  (moves 1)
B1 B2  (moves 2)
B2  (moves 1)
B1  (moves 1)
L1 L2  (moves 2)
L2  (moves 1)
L1  (moves 1)
U2 B3 B2  (moves 3)
L2 U3  (moves 2)
R1 U1  (moves 2)
D3 L3  (moves 2)
D3 L2  (moves 2)
D2 F3 F2  (moves 3)
R2 F3  (moves 2)
R1 F2 F2 R2 F2  (moves 5)
D1 D2 U2  (moves 3)
L1 B2 F2 L2 R2 B2 F2  (moves 7)
L1 L2 D3  (moves 3)
D1 F2  (moves 2)
U2 R3  (moves 2)
L1 L2 U3  (moves 3)
U1 R2  (moves 2)
U1 R3  (moves 2)
F1 U2  (moves 2)
U2 R3 R2  (moves 3)
F2 D1 F3  (moves 3)
F2 D3 D2 U2  (moves 4)
L3 D2 R3  (moves 3)
D2 R3 R2 D3  (moves 4)
F1 R1 B2 B2 R2 B2  (moves 6)
L1 B2 F2  (moves 3)
U1 R2 B3 B2  (moves 4)
R2 F3 R2  (moves 3)
L2 D3 R3 R2  (moves 4)
L2 F3 L2 L2 F2 L2  (moves 6)
F1 R1 B3 D3 B2 D3 L3 U2 L3 U2 L2 U2 L2 U3 R2 U1 F2 L2 U2 B2 L2 F2 U2 L2 U2 F2 D2 F2 U2  (moves 29)
L1 L2 U3 R2  (moves 4)
L3 B3 B2 R3 R2  (moves 5)
B2 U1 R3 R2  (moves 4)
L3 B3 L2  (moves 3)
D1 B2 L3 L2  (moves 4)
B1 B2 R3 F2 F2 R2 F2  (moves 7)
D1 F3 D1 D2  (moves 4)
R1 B3 D1 R2 F3 L1 U2 F2 D3 B2 D1 L3 U1 F2 R2 U1 L2 U1 F2 U2 R2 U3 F2 U3 F2 D2 F2 L2 F2 L2 F2 U2 F2 D2 L2  (moves 35)
F1 R1 U3 D1 B3 U3 D2 L3 B2 R1 F2 D3 L3 U2 R2 D1 R2 B2 U2 L2 U3 U2 F2 U2 L2 B2 R2 D2 R2 D2 B2 L2 F2 U2  (moves 34)
U1 R1 F3 L1 R2 U3 L1 D2 F2 U3 L3 L2 U1 F2 D3 F2 F2 U2 D2 L2 U2 F2 R2 F2 D2 R2 U2  (moves 27)
R1 D3 R3 F3 R1 D3 F2 U1 R3 D2 U1 R3 F2 U1 L2 U3 F2 U1 B2 D2 L2 D3 F2 F2 U2 F2 D2 L2 U2 L2 F2 L2 U2 R2  (moves 34)
D2 R1 B1 L1 F3 U2 D3 L2 R1 D3 B2 U1 F2 L3 F2 U3 B2 U3 B2 L2 U3 B2 U3 F2 U2 F2 U2 L2 F2 R2 B2 D2 L2 D2 F2  (moves 35)
B3 U2 L1 F3 F2 U1 R3 D1 F2 R3 D3 B2 R3 B2 U1 F2 U3 R2 U1 R2 U3 R2 L2 F2 U2 R2 F2 D2 R2 B2 U2 R2 B2  (moves 33)
L1 F3 L2 D3 U1 F3 L1 B2 R1 U1 D1 B2 R3 U1 L2 U1 B2 U1 F2 U3 L2 D1 F2 U3 F2 U2 D2 R2 U2 L2 F2 R2 U2 F2 R2  (moves 35)
F1 R3 U2 F3 B2 U1 L1 U1 R3 B2 U1 R3 R2 U3 L2 U1 B2 U2 R2 U3 L2 U3 F2 L2 U2 F2 U2 B2 L2 D2 L2 F2 L2 F2 U2  (moves 35)
U2 D3 B3 U1 L2 D1 R1 U3 L3 D2 U1 R3 U3 B2 D3 R2 F2 U3 F2 U3 U2 B2 D2 B2 L2 F2 R2 D2 R2  (moves 29)
D2 L3 U3 F3 B2 U3 L1 U2 R3 D2 L3 U2 L2 U3 R2 B2 D3 F2 R2 U3 U2 L2 U2 F2 U2 D2 R2 F2 U2 B2 D2  (moves 31)
F1 L1 U1 L1 B3 U3 L1 F2 L1 B2 F2 U3 L3 F2 D3 B2 D3 R2 U1 F2 U3 L2 U3 U2 F2 D2 B2 U2 F2 R2 F2 L2  (moves 32)
B1 L1 U3 F3 B2 U1 L3 B2 R3 L3 U3 L3 D2 B2 D3 F2 L2 U2 R2 U3 F2 U3 F2 L2 U2 B2 L2 U2 B2 F2 R2 U2 F2  (moves 33)
F2 L3 F1 D3 B3 B2 U3 R1 D3 U3 L3 L2 R2 U3 B2 D1 B2 U3 R2 U3 F2 L2 F2 L2 U2 F2 B2 R2 B2 L2  (moves 30)
D3 F3 U1 B2 U3 L1 D1 R3 U3 F2 L3 U1 F2 U2 L2 U3 L2 B2 R2 L2 D1 F2 F2 L2 U2 F2 L2 U2 R2 D2 B2 R2 L2  (moves 33)
F2 R3 U2 F3 U2 L2 B2 D1 F2 R3 B2 D1 L3 D2 R2 B2 D1 R2 B2 U1 L2 B2 R2 B2 R2 D2 L2 D2 F2 L2 B2 L2 F2  (moves 33)
U1 R3 F3 D3 R3 B2 L3 D1 F2 U1 R3 L2 U1 B2 D1 L2 U3 R2 U1 L2 U3 F2 U3 F2 U2 B2 L2 D2 L2 U2 R2 F2  (moves 32)
F1 R1 F1 D3 B3 F3 U1 R2 F2 U1 L3 U1 F2 U2 R2 U1 R2 U3 L2 U3 D2 L2 F2 L2 F2 U2 B2 U2 L2 F2  (moves 30)
F3 R3 L2 B3 U1 B2 U1 F2 U2 B2 R3 D2 L3 B2 U1 F2 U3 L2 U1 B2 D3 L2 U1 L2 U2 L2 D2 R2 F2 D2 F2 U2 R2 U2  (moves 34)
D1 B3 D2 L1 F3 U3 F2 D2 L3 F2 L3 D3 L3 D1 L2 B2 U3 R2 U1 R2 U3 L2 U3 L2 D2 R2 D2 F2 R2 F2 L2 D2 U2 F2 U2  (moves 35)
U1 B1 D1 R3 F3 U1 B2 R1 U3 L1 D3 B2 U1 R3 U2 F2 L2 U3 R2 U1 B2 D3 B2 U1 L2 F2 U2 D2 L2 U2 B2 R2 B2 L2 D2 L2  (moves 36)
U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)
U1 B2 L1 B3 F3 U1 F2 B2 R2 D3 R3 U3 L3 B2 U1 F2 U3 F2 U3 L2 U2 F2 R2 B2 R2 U2 F2 U2 F2 U2 F2  (moves 31)
U1 B1 U3 D1 F3 U2 D3 R3 D1 U1 L1 F2 L3 D2 L2 U1 F2 B2 R2 U3 F2 U1 L2 U2 R2 F2 D2 F2 U2 L2 B2 U2 F2  (moves 33)
D1 F3 U2 R1 B3 L1 B2 R1 U3 L2 D3 F2 R3 L2 D2 L2 D3 L2 F2 U3 F2 B2 D2 L2 B2 L2 B2 D2 L2 F2 U2 F2 U2  (moves 33)
R1 B1 D3 F3 D1 R3 D3 B2 L2 B2 U2 L3 L2 U2 B2 L2 U2 F2 U3 U2 F2 L2 D2 L2 B2 U2 R2 F2 L2 B2  (moves 30)
U1 D2 F1 L1 B3 D1 B2 D3 L2 R1 D3 L2 U2 R3 D2 F2 U3 F2 R2 U1 B2 U1 F2 U3 B2 R2 U2 L2 U2 B2 D2 F2 L2 B2 F2 U2  (moves 36)
U1 L1 D1 L1 F3 L1 U1 L3 U3 L1 D1 R3 F2 U2 R2 U1 F2 U2 F2 L2 D1 F2 U3 F2 U2 R2 D2 F2 R2 B2 L2 B2 D2 B2  (moves 34)
L3 D3 U1 F3 U2 F2 D3 R3 B2 D3 U3 L3 R2 U2 L2 D3 R2 U1 L2 U2 F2 U3 F2 U3 U2 L2 U2 R2 B2 R2 B2 U2 F2 U2  (moves 34)
L1 B1 U2 D1 F3 B2 U3 R3 D2 U3 L2 U3 L3 F2 U3 R2 U1 F2 R2 L2 D3 F2 F2 B2 L2 D2 F2 R2 D2 B2 R2 F2 L2  (moves 33)
L1 B1 U3 F3 U1 L2 D3 L1 B2 R1 L3 U3 L3 U3 L2 D3 L2 U1 L2 B2 F2 U3 L2 D2 L2 U2 R2 F2 D2 B2 U2 R2 U2  (moves 33)
F1 U1 B3 F3 B2 U2 D3 L3 U3 L3 U3 R2 D3 B2 D2 L2 U3 R2 U2 F2 U3 F2 L2 D2 L2 R2 F2 L2 U2 L2 D2 U2 F2 U2  (moves 34)
D1 L3 R1 F2 U2 F3 U3 F2 D3 L3 D2 L3 U2 L3 D1 L2 U3 R2 D1 B2 U1 L2 R2 U2 L2 D2 B2 R2 F2 L2 D2 U2 F2 U2  (moves 34)
L2 R3 D1 F3 D3 L1 U3 L3 D2 L3 B2 L2 U1 R2 U2 F2 U3 F2 L2 F2 L2 B2 U2 R2 U2 R2 B2 U2 B2  (moves 29)
L2 U2 R1 B3 F3 U1 L1 D3 F2 U2 R3 U2 L3 L2 U2 L2 D2 L2 F2 U3 F2 U2 L2 U2 B2 U2 R2 D2 R2 B2  (moves 30)
L2 F1 U2 F3 D3 R3 U1 D3 L3 D1 U1 L3 R2 D3 R2 F2 D2 B2 U3 F2 U1 F2 D2 L2 B2 U2 L2 U2 R2 B2 F2 U2  (moves 32)
F3 D2 F3 L2 B2 D3 L2 U3 B2 L3 L2 F2 L2 D3 L2 B2 U3 L2 L2 U2 F2 D2 L2 D2 L2 B2 L2 F2 L2 U2  (moves 30)
F3 R2 U3 F3 U3 R3 D2 R2 D1 F2 U2 L3 D3 L2 D3 R2 U1 F2 U3 L2 U1 F2 L2 B2 D2 B2 L2 F2 U2 L2 F2 D2  (moves 32)
B1 R1 U1 D3 F3 R2 U1 L2 R2 D2 B2 U3 L3 R2 F2 U1 L2 B2 U1 F2 U3 L2 U3 R2 U2 F2 D2 F2 L2 B2 L2 U2 F2  (moves 33)
L3 D3 U1 B3 L2 F2 D3 L3 R1 U1 R3 L2 D3 F2 R2 U3 F2 R2 U3 L2 D2 R2 U2 B2 U2 B2 L2 U2 R2 F2 U2  (moves 31)
L1 F3 L2 R1 B3 L1 U3 L1 R1 D3 F2 D1 R3 B2 R2 U1 F2 L2 D1 R2 F2 D2 L2 R2 B2 R2 B2 U2 L2 U2  (moves 30)
U1 F1 U3 L1 B3 D1 L2 B2 R1 D3 R3 F2 L3 U3 F2 B2 L2 U3 B2 D3 L2 U3 L2 D2 R2 F2 D2 L2 F2 D2 F2  (moves 31)
D2 L3 U1 F3 U1 D3 L1 F2 D3 R3 F2 U3 R3 L2 U1 L2 U3 L2 U1 F2 L2 U1 R2 U3 F2 U2 L2 D2 B2 U2 L2 F2 U2 F2 U2  (moves 35)
F3 L2 F3 U1 L1 U1 D2 L3 U3 L3 B2 U1 F2 U1 F2 D2 R2 U3 L2 U2 F2 U3 R2 F2 D2 L2 D2 R2 F2 U2 F2 U2 F2 U2  (moves 34)
U2 L3 B3 U2 R3 U3 L2 B2 U1 R3 R2 D3 R2 U1 R2 U3 F2 U1 F2 U3 F2 U2 L2 F2 R2 F2 D2 L2 D2 L2 B2  (moves 31)
F1 B1 R3 F3 U3 F3 B2 D1 B2 R1 U3 L1 U2 L3 F2 U3 F2 R2 U1 R2 U2 B2 D3 F2 U3 F2 B2 L2 U2 F2 L2 D2 B2 F2 L2 B2  (moves 36)
B2 D3 B3 U2 B2 D3 L3 D1 R1 U2 L3 L2 U3 B2 U1 B2 D2 R2 U3 F2 U3 U2 L2 U2 F2 D2 F2 U2 B2 L2 D2 F2 R2 F2  (moves 34)

Average number of moves = 16.72

Average time = 1005.78 milliseconds

When run with a file containing the single line:

UL DL RF UB FD BR DB UF DR UR BL FL FDR BLU DLB URB RUF FLD BRD FUL

a typical result was:

U3 F1 L1 F3 B2 U1 B2 R2 D1 R1 U2 L3 U1 F2 R2 U3 L2 U3 B2 F2 R2 F2 B2 U2 R2 F2 L2 U2 L2  (moves 29)

Average number of moves = 29

Average time = 665 milliseconds