GolfScript、39/83バイト
# Optimized for size:
{.4rand.p.2/+>`{?1420344440`=}+$..$>}do
# Optimized for speed:
6,(7++:t;~{.(1=.@7=9=+4\-rand+..2/+@.@>:s^[3s=0s=2s=4s=1s=]+s|.)9<\t>|}do.$>30764`*
速度とサイズ
サイズが最適化されたバージョンでは、目的の順列が達成されるまで、時計回りの回転がランダムに選択されます。反時計回りの回転は、同じ正方形の時計回りの3つの連続した回転に相当するため、これで十分です。
速度が最適化されたバージョンは、次の点を除いて同じことを行います。
番号1が左上隅にある場合、左上の正方形はもう回転しません。
数字の9が右下隅にある場合、右下の正方形はもう回転しません。
位置7と8を交換する手順はハードコードされているため、ループを中断できる位置は2つあります。
アルゴリズムの変更は別として、速度最適化バージョンは単純な方法で回転を実現しますが、サイズ最適化バージョンはGolfScriptの組み込みマッピングによる並べ替えを使用します。また、繰り返しごとに状態を並べ替えるのではなく、最終状態を(比較のために)ハードコード化します。
速度が最適化されたバージョンでは、必要な反復回数が少なくなり、すべての反復が単独ではるかに高速になります。
ベンチマーク
次のコードを使用して数字の位置をランダム化し、テストを実行して、テストするバージョンに対応する行のコメントを外しました。
[{[
0:c;10,1>{;2 32?rand}$
#{c):c;.4rand.2/+>`{?1420344440`=}+$..$>}do
#6,(7++:t;{.(1=.@7=9=+4\-rand+..2/+@.@>:s^[3s=0s=2s=4s=1s=]+s|.)9<\t>|}do.$>30764`*
],c+}\~*]
$.0='Min: '\+puts .-1='Max: '\+puts ..{+}*\,/'Avg: '\+puts .,2/='Med: '\+
出力には、順序付けにかかったステップの最小数と最大数、すべての実行の平均と中央値、および経過時間(秒)が表示されます。
$ TIME='\n%e s' time golfscript rotation-test-size.gs <<< 100
Min: 4652
Max: 2187030
Avg: 346668
Med: 216888
21500.10 s
$
$ TIME='\n%e s' time golfscript rotation-test-speed.gs <<< 1000
Min: 26
Max: 23963
Avg: 3036
Med: 2150
202.62 s
私のマシン(Intel Core i7-3770)では、サイズが最適化されたバージョンの平均実行時間は3.58分でした。速度最適化バージョンの平均実行時間は0.20秒でした。したがって、速度最適化バージョンは約1075倍高速です。
速度が最適化されたバージョンでは、回転が114倍少なくなります。各回転の実行は9.4倍遅くなりますが、これは主に状態の更新方法によるものです。
I / O
出力は3ビットの数値で構成されます。MSBは反時計回りに設定され、中間ビットは下の正方形に設定され、LSBは右の正方形に設定されます。したがって、0(4)は左上の正方形、1(5)右上の正方形、2(6)左下の正方形、3(7)右下の正方形です。
速度が最適化されたバージョンでは、すべての回転が1行に印刷されます。サイズが最適化されたバージョンでは、1行に1回転、その後に数字の最終位置が出力されます。
速度が最適化されたバージョンでは、評価時に1から9までの数値を含む配列が入力から得られなければなりません。サイズが最適化されたバージョンの場合、入力は最終改行のない文字列でなければなりません。評価されません。
実行例:
$ echo -n '253169748' | golfscript rotation-size.gs
3
0
123456789
$ golfscript rotation-speed.gs <<< '[5 4 7 1 2 9 3 8 6]'
2210300121312212222212211121122211122221211111122211211222112230764
サイズ最適化コード
{ #
. # Duplicate the state.
4rand # Push a randomly chosen integers between 0 and 3.
.p # Print that integer.
.2/+ # Add 1 to it if it is grater than one. Possible results: 0, 1, 3, 4
>` # Slice the state at the above index.
{ # Push a code block doing the following:
? # Get the index of the element of the iteration in the sliced state.
1420344440` # Push the string "14020344440".
= # Retrieve the element at the position of the computed index.
}+ # Concatenate the code block with the sliced state.
$ # Sort the state according to the above code block. See below.
..$> # Push two copies of the state, sort the second and compare the arrays.
}do # If the state is not sorted, repeat the loop.
状態の更新は、次の方法で実現されます。
回転2は、1を追加した後に整数3を生成します。状態が「123456789」の場合、状態をスライスすると「456789」が生成されます。
「$」を実行する直前に、スタックの最上位要素は次のとおりです。
[ 1 2 3 4 5 6 7 8 9 ] { [ 4 5 6 7 8 9 ] ? "1420344440" = }
「$」は、要素自体をプッシュした後、ソートされる配列のすべての要素に対してブロックを1回実行します。
「[4 5 6 7 8 9]」の1のインデックスは-1(存在しない)であるため、「1420344440」の最後の要素がプッシュされます。これにより、文字0に対応するASCIIコードである48が生成されます。2および3の場合、48もプッシュされます。
4、5、6、7、8、および9にプッシュされた整数は、49、52、50、48、51、および52です。
ソート後、状態の最初の要素は48を生成する要素の1つになります。組み込みのソートは一般的に不安定ですが、この特定のケースでは安定していることを経験的に検証しました。
結果は「[1 2 3 7 4 6 8 5 9]」で、これは左下の正方形の時計回りの回転に対応します。
速度最適化コード
6,(7++:t; # Save [ 1 2 3 4 5 7 ] in variable “t” and discard it.
~ # Interpret the input string.
{ #
:s # Duplicate the current state.
(1= # Unshift the first element and push 1 if it is equal to 1 and 0 otherwise.
.@ # Duplicate the boolean and rotate the unshifted array on top of it.
7=9= # Push 1 if the eighth element of “s” is equal to 9 and 0 otherwise.
+4\- # Add the booleans and subtract their sum from 4.
rand # Push a randomly chosen integers between 0 and the result from above.
+. # Add this integer to the first boolean and duplicate it for the output.
.2/+ # Add 1 to the result if it is grater than one. Possible results: 0, 1, 3, 4
@. # Rotate the state on top of the stack and duplicate it.
@>:s # Slice the state at the integer from above and save the result in “s”.
^ # Compute the symmetric difference of state and sliced state.
[ # Apply a clockwise rotation to the sliced array:
3s= # The fourth element becomes the first.
0s= # The first element becomes the second.
2s= # The third element remains the same.
4s= # The fifth element becomes the fourth.
1s= # The second element becomes the fifth.
] # Collect the results into an array.
+ # Concatenate with array of elements preceding the slice.
s| # Perform set union to add the remaining elements of “s”.
. # Duplicate the updated state.
)9< # Pop the last element; push 0 if it is equal to 9 and 1 otherwise.
\t # Swap the popped state on top and push [ 1 2 3 4 5 7 ].
> # Push 0 if the state begins with [ 1 2 3 4 5 6 ] and 1 otherwise.
| # Take the logical OR of the booleans.
}do # If the resulting boolean is 1, repeat the loop.
.$ # Duplicate the state and sort it.
>30764`* # If the state was not sorted, 7 and 8 are swapped, so push "30764".
回転3、0、7、6、4は、残りの7つの要素の位置を変更せずに、位置7と8の要素を交換することに注意してください。
...and return as output a sequence of moves representing the moves you must take to return the board back to its original
これは「戻る1 2 3\n4 5 6\n7 8 9
」という意味ですか?私はそれをどう読むかわかりません。