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*iher seferinde hesaplama "inline" pozisyonları [8,10,12,22,24,26,36,38,40].
offsetsDizi çok sabitin değişkeni yerine, bir kere kullanılır.
- Değiştir
do ... endile {...}ve yazdırmayı etrafında geçiş $> << foo. (Burada puts nilve 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, injectofset 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 .)8j+=81,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+=8aslı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 9999farklılıkları dizinin sonuna ve eklemek jde 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,2gö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+difference9999a[j]j10000
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 jdeğ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=8biraz 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+=lolmak 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-eişaretinin injectdaha 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_indexolabilir 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}