Ruby (135 karakter)
a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.each_slice(7){|r|puts"%-3s"*7%r}
Örnek çıktı
2 1 6 9 4 5 1
9 34 4 37 2 31 3
7 2 3 1 8 1 7
5 42 4 40 2 47 9
3 9 9 4 9 4 7
3 44 4 41 2 47 4
6 9 1 5 7 6 8
Yıkmak
Bunun nasıl çalıştığı çok açık değil, bu yüzden hızlı bir arıza. NOT: Muhtemelen bu adımlardan bazılarını atlayabilir ve daha kısa sürümlere daha hızlı atlayabilirsiniz, ancak karakterleri tıraş ettiğim farklı yolları görmek için yeterince eğitici olduğunu düşünüyorum, özellikle 2 basamaklı sayıları 1 basamaklı sürümlere dönüştürmek için harfleri düzenleyerek .
Saf sürüm
İki boyutlu bir diziye dayanan diğer Ruby çözümlerinin aksine, 1 boyutlu bir diziden başlayıp kalıplar tekrarlandığından ofset değerleriyle çalışarak (sonunda) daha kısa bir sürüm elde edebilirsiniz.
ary=(0..48).map { rand(9) + 1 }
offsets = [-8,-7,-6,-1,1,6,7,8]
3.times do |i|
[8,10,12].each do |j|
ary[j + 14*i] = ary.values_at(*offsets.map { |e| j+14*i + e }).inject(:+)
end
end
ary.each.with_index do |e,i|
$> << ("%-3s" % e)
$> << ?\n if i % 7==6
end
Buradaki temel ilke, 8, 10, 12 dizin konumlarında çalışıyoruz. Sadece 14'ün katları ile dengeleniyoruz. 8, 10 ve 12 pozisyonları, topladığımız 3x3 ızgaralarının merkezleridir. Örnek çıktısında 34 konum 8, 42 konum 8 + 14 * 1 vb . [-8,-7,-6,-1,1,6,7,8]
Konumdur 34 = sum(ary[8-8], ary[8-7], ..., ary[8+8])
. Başka bir deyişle , konum 8'i konum 8'den ofset konumlarla değiştiririz . Aynı prensip [8 + 14*i, 10 + 14*i, 12 + 14*i]
, örüntü tekrarlandığından tüm değerleri için geçerlidir .
Optimize etme
İlk olarak, bazı hızlı optimizasyonlar:
- Bunun yerine
3.times { ... }
ve j + 14*i
her seferinde hesaplama "inline" pozisyonları [8,10,12,22,24,26,36,38,40]
.
offsets
Dizi çok sabitin değişkeni yerine, bir kere kullanılır.
- Değiştir
do ... end
ile {...}
ve yazdırmayı etrafında geçiş $> << foo
. (Burada puts nil
ve ile ilgili bir numara var () == nil
.)
- Daha kısa değişken adları.
Bundan sonraki kod 177 karakterdir:
a=(0..48).map{rand(9)+1}
[8,10,12,22,24,26,36,38,40].each{|j|a[j]=a.values_at(*[-8,-7,-6,-1,1,6,7,8].map{|e|j+e}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
Bir sonraki azaltma için, inject
ofset dizisinin sırayla olması gerekmediğini unutmayın . [-8,-7,-6,-1,1,6,7,8]
Toplama değişmeli olduğu için ya ya da başka bir düzenimiz olabilir.
Bu yüzden önce pozitifleri ve negatifleri eşleştirin [1,-1,6,-6,7,-7,8,-8]
.
Şimdi kısaltabilirsiniz
[1,-1,6,-6,7,-7,8,-8].map { |e| j+e }.inject(:+)
için
[1,6,7,8].flat_map { |e| [j+e, j-e] }
Bu sonuç
a=(0..48).map{rand(9)+1}
[8,10,12,22,24,26,36,38,40].each{|j|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
ki bu 176 karakter.
8 ileri kaydırın ve farklılıklara geçin
İki karakterlik değişmez değerler kısaltılabilecek gibi görünüyor, bu nedenle döngü başlangıcında güncellenerek [8,10,12,22,24,26,36,38,40]
her şeyi alıp aşağı kaydırın . ( Ofset değerlerini güncellemeniz gerekmediğini unutmayın .)8
j
+=8
1,6,7,8
a=(0..48).map{rand(9)+1}
[0,2,4,14,16,18,28,30,32].each{|j|j+=8;a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
Bu 179, daha büyük, ama j+=8
aslında çıkarılabilir.
İlk değişiklik
[0,2,4,14,16,18,28,30,32]
farklılıklar dizisine:
[2,2,10,2,2,10,2,2]
ve bu değerleri bir baş harfine kümülatif olarak ekler j=8
. Bu sonunda aynı değerleri kapsayacaktır. (Muhtemelen önce 8'e geçmek yerine doğrudan buna atlayabiliriz.)
Biz de bir kukla değer ekleriz Not 9999
farklılıkları dizinin sonuna ve eklemek j
de sonunda değil, başlangıç döngünün. Gerekçe, 3 kez tekrarlanan aynı 3 sayı olmaya çok yakın 2,2,10,2,2,10,2,2
görünüyor ve döngünün sonunda hesaplayarak , son değerin çıktıyı etkilemeyeceği, çünkü bir değerin olduğu bir çağrı olmadığı için bitti .j+difference
9999
a[j]
j
10000
a=(0..48).map{rand(9)+1}
j=8
[2,2,10,2,2,10,2,2,9999].each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
Bu farklılıklar dizisi ile, j+=8
şimdi sadece j=8
, tabii ki, aksi takdirde tekrar tekrar 8
çok fazla eklerdik. Ayrıca blok değişkenini olarak j
değiştirdik l
.
Dolayısıyla, 9999
öğenin çıktı üzerinde hiçbir etkisi olmadığından 10
, diziyi değiştirebilir ve diziyi kısaltabiliriz.
a=(0..48).map{rand(9)+1}
j=8
([2,2,10]*3).each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
Bu 170 karakterdir.
Ama şimdi j=8
biraz hantal görünüyor ve atama için kullanabileceğiniz [2,2,10]
bir rahatlık elde etmek için 2 karakter aşağı kaydırarak 2 karakter kaydedebilirsiniz 8
. Bu aynı zamanda ihtiyacı j+=l
olmak j+=l+2
.
a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l+2}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
Bu 169 karakterdir. 7 karakteri sıkmanın yuvarlak bir yolu, ama temiz.
Son düzenlemeler
values_at
Çağrı aslında sıralama yedekli taşımaktadır ve bu konuda bir satır içine alabilirsiniz Array#[]
çağrı. Yani
a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)
olur
[1,6,7,8].flat_map{|e|[a[j+e],a[j-e]]}.inject(:+)
Ayrıca , dizide bir ilk harfle flat_map
+ + j+e/j-e
işaretinin inject
daha doğrudan bir toplamaya indirgenebileceğini de görebilirsiniz 0
.
Bu size 152 karakter bırakır :
a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}
En sonunda:
map.with_index
olabilir each_slice
.
- Yazdırma yaklaşımını değiştirin.
135 :
a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.each_slice(7){|r|puts"%-3s"*7%r}