GolfScript, 39/83 bayt
# 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`*
Hız vs boyut
Boyuta göre optimize edilmiş versiyon, istenen permütasyon elde edilene kadar rastgele saat yönünde dönüşleri seçer. Bu yeterli, çünkü saat yönünün tersine dönüş, aynı karenin saat yönünde art arda üç dönüşüne eşdeğerdir.
Hızı optimize edilmiş sürüm aşağıdakiler dışında aynı şeyi yapar:
1 sayısı sol üst köşedeyse, artık sol üst kareyi döndürmez.
9 sayısı sağ alt köşedeyse, artık sağ alt kareyi döndürmez.
Konum 7 ve 8'i değiştirme adımları sabit kodlanmıştır, bu nedenle ilmeğin kırılmasına izin veren iki konum vardır.
Algoritmayı değiştirmenin yanı sıra, hızı optimize edilmiş sürüm, dönüşü basit bir şekilde gerçekleştirirken, boyutu optimize edilmiş sürüm, GolfScript'in yerleşik sıralamasını eşleyerek kullanır. Ayrıca her yinelemede durumu sıralamak yerine son durumu (karşılaştırma için) kodlar.
Hızı optimize edilmiş sürüm daha az yineleme gerektirir ve her yineleme kendi başına çok daha hızlıdır.
Deneyler
Ben sayıların konumlarını rasgele ve test çalıştırılacak sürüme karşılık gelen çizgi uncommenting, test çalışmalarını gerçekleştirmek için aşağıdaki kodu kullandım:
[{[
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: '\+
Çıktı, sayıları sipariş etmek için attığı minimum ve maksimum adım sayısını, tüm çalışmaların ortalamasını ve medyanını ve saniye cinsinden geçen süreyi gösterir:
$ 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
Makinemde (Intel Core i7-3770), boyutu optimize edilmiş sürümün ortalama yürütme süresi 3,58 dakikaydı. Hızı optimize edilen sürümün ortalama yürütme süresi 0.20 saniyeydi. Böylece, hızı optimize edilmiş versiyon yaklaşık 1075 kat daha hızlıdır.
Hızı optimize edilmiş versiyon 114 kat daha az dönüş sağlar. Her dönüşün gerçekleştirilmesi, esas olarak durumun nasıl güncellendiğinden kaynaklanmaktadır.
I / O
Çıktı 3 bit sayıdan oluşur. MSB saat yönünün tersine dönüşler için ayarlanmış, orta bit ise alt kareler için ve LSB sağ kareler için ayarlanmıştır. Böylece, 0 (4) sol üst kare, 1 (5) sağ üst, 2 (6) sol alt ve 3 (7) sağ alt karedir.
Hızı optimize edilmiş sürüm tüm dönüşleri tek bir satıra yazdırır. Boyutu optimize edilmiş sürüm, her satıra bir dönüş ve ardından sayıların son konumunu yazdırır.
Hızı optimize edilmiş versiyon için, giriş değerlendirilirken 1 ile 9 arasındaki sayıları içeren bir dizi vermelidir. Boyutu optimize edilmiş sürüm için, girişin son satırsonu olmayan bir dize olması gerekir; değerlendirilmez.
Örnek çalıştırmalar:
$ echo -n '253169748' | golfscript rotation-size.gs
3
0
123456789
$ golfscript rotation-speed.gs <<< '[5 4 7 1 2 9 3 8 6]'
2210300121312212222212211121122211122221211111122211211222112230764
Boyuta göre optimize edilmiş kod
{ #
. # 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.
Durumun güncellenmesi aşağıdaki şekilde gerçekleştirilir:
Dönme 2, 1 eklendikten sonra 3 tamsayısını verir. Durum "123456789" ise, durumun dilimlenmesi "456789" verir.
“$” Öğesini çalıştırmadan hemen önce, yığının en üstteki öğeleri şunlardır:
[ 1 2 3 4 5 6 7 8 9 ] { [ 4 5 6 7 8 9 ] ? "1420344440" = }
“$”, Öğenin kendisini ittikten sonra dizinin sıralanacak her öğesi için bloğu bir kez yürütür.
“[4 5 6 7 8 9]” deki 1 indeksi -1'dir (mevcut değildir), bu nedenle "1420344440" ın son elemanı itilir. Bu, 48 karakterini verir. 0 karakterine karşılık gelen ASCII kodu. 2 ve 3 için, 48 de itilir.
4, 5, 6, 7, 8 ve 9 için itilen tamsayılar 49, 52, 50, 48, 51 ve 52'dir.
Ayıklamadan sonra, devletin ilk elemanı 48 veren elemanlardan biri olacaktır; Son olarak, bu tür bir verim olacaktır. Yerleşik sıralama genel olarak kararsızdır, ancak bu özel durumda kararlı olduğunu ampirik olarak doğruladım.
Sonuç, sol alt karenin saat yönünde dönmesine karşılık gelen “[1 2 3 7 4 6 8 5 9]” dir.
Hızı optimize edilmiş kod
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 ve 4 rotasyonlarının, kalan yedi elemanın pozisyonlarını değiştirmeden 7 ve 8 konumlarındaki elemanları değiştirdiğini gözlemleyin.
...and return as output a sequence of moves representing the moves you must take to return the board back to its original
Bu "geri1 2 3\n4 5 6\n7 8 9
" demek mi? Bunu nasıl okuyacağımdan emin değilim.