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을 교체하는 단계는 하드 코딩되므로 루프가 끊어 질 수있는 두 위치가 있습니다.
알고리즘을 변경하는 것 외에도 속도 최적화 버전은 간단한 방식으로 회전을 수행하는 반면 크기 최적화 버전은 매핑으로 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에서 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" = }
“$”는 요소 자체를 푸시 한 후 배열의 모든 요소가 정렬 될 때마다 블록을 한 번 실행합니다.
"[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을 산출하는 요소 중 하나입니다. 마지막은 52를 산출하는 것 중 하나입니다. 내장 된 종류는 일반적으로 불안정하지만,이 특정한 경우에 안정적인 것으로 경험적으로 확인했습니다.
결과는 "[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
"를 의미합니까 ? 어떻게 읽는지 잘 모르겠습니다.