Yürüyen Kareler Arama


9

Yürüyen Kareler , bir örnek ızgaradan 2B izocontours'ları kurtarmak için kullanılan bilgisayar grafiklerinden bir algoritmadır (ayrıca bkz. Ağabeyi 3D ayarları için büyük küpü Yürüyen Küpleri ). Fikir, ızgaranın her hücresini bağımsız olarak işlemek ve köşedeki değerlere dayanarak o hücreden geçen konturları belirlemektir.

Bu işlemdeki ilk adım, köşelerin kontur değerinin üstünde veya altında olup olmadığına bağlı olarak hangi kenarların konturlarla bağlandığını belirlemektir. Basitlik için, değer boyunca konturları dikkate alacağız 0, böylece köşelerin pozitif veya negatif olup olmadığıyla ilgileniyoruz. Ayırmak için durumlar var :24 = 16

resim açıklamasını buraya girin
Görüntü Kaynağı: Wikipedia

Beyaz ve siyahın tanımlanması burada gerçekten önemli değil, ama kesin olarak beyazın pozitif ve siyahın negatif olduğunu söylüyor. Köşelerden birinin tam olarak olduğu vakaları görmezden geleceğiz 0.

Sele noktaları (5 ve 10 numaralı vakalar) biraz ekstra zorluk sağlar: sadece köşelere bakarak hangi diyagonallerin kullanılması gerektiği açık değildir. Bu, dört köşenin ortalamasını (yani merkez değerinin yaklaşık bir değerini) bularak ve konturları merkezin köşelerden ters işaretle ayıracağı şekilde köşegenler seçerek çözülebilir. Ortalama tam ise 0, her iki durum da seçilebilir.

Normalde, bu 16 vaka basitçe bir arama tablosunda saklanır. Bu verimlilik için harika, ama elbette, kodun burada kısa olmasını tercih ederiz . Yani sizin göreviniz bu arama adımını gerçekleştirmek ve bir ASCII temsilini mümkün olduğunca az kodda yazdırmaktır.

Meydan okuma

Seçtiğiniz sabit bir sırayla dört köşenin (sıfır olmayan tamsayı) değerlerini alırsınız. Daha sonra konturların doğru düzenini oluşturmalı ve eyer noktası durumlarını doğru bir şekilde çözmelisiniz.

STDIN (veya en yakın alternatif), komut satırı bağımsız değişkeni veya işlev bağımsız değişkeni ile girdi alarak ve sonucu STDOUT (veya en yakın alternatif), işlev dönüş değeri veya işlev (çıkış) parametresi aracılığıyla çıktı alarak bir program veya işlev yazabilirsiniz.

Giriş herhangi bir uygun dize veya liste formatında alınabilir.

16 vaka, aşağıdaki 5x5 bloklardan biri kullanılarak ASCII sanatında temsil edilecektir:

o---o  o---o  o---o
|   |  |   |  | | |
|   |  |---|  | | |
|   |  |   |  | | |
o---o  o---o  o---o

o---o  o---o  o---o  o---o
|/  |  |  \|  |   |  |   |
|   |  |   |  |   |  |   |
|   |  |   |  |\  |  |  /|
o---o  o---o  o---o  o---o

o---o  o---o
|/  |  |  \|
|   |  |   |
|  /|  |\  |
o---o  o---o

Öncü veya sondaki boşlukları yazdırmamalısınız, ancak tek bir isteğe bağlı yeni satır yazdırabilirsiniz.

Bu kod golf, yani en kısa cevap (bayt cinsinden) kazanır.

Test Durumları

Test durumları bu giriş sırası verilmiştir varsayalım Sol üstteki , sağ üst , sol alt , sağ alt . Test vakaları, yukarıda verilen 9 gösterimden her birine karşılık gelen 9 grupta sunulur (aynı sırayla, boş hücreden başlayarak, iki sele noktasıyla biter).

[1, 2, 1, 3]
[-9, -2, -2, -7]

[4, 5, -1, -2]
[-1, -2, 3, 4]

[7, -7, 7, -7]
[-5, 5, -5, 5]

[1, -6, -4, -1]
[-2, 3, 3, 4]

[-1, 6, -4, -1]
[2, -3, 3, 4]   

[-1, -6, 4, -1]
[2, 3, -3, 4]

[-1, -6, -4, 1]
[2, 3, 3, -4]

[3, -8, -9, 2]
[-3, 8, 9, -2]

[8, -3, -2, 9]
[-8, 3, 2, -9]

Ayrıca, aşağıdaki test senaryoları eyer noktalarından herhangi birini döndürebilir (seçiminiz):

[1, -4, -2, 5]
[-1, 4, 2, -5]

Yanıtlar:


5

Yakut, 201, 180 176

Bu isimsiz bir örnekte gösterilen şekilde çağrılacak anonim bir lambda fonksiyonudur.

Bu değişken içermez s. Çözülmemiş versiyonda s, kullanılmadan önce açıklık sağlamak için karmaşık bir ifade atanır . 4 bayt, golf sürümüne satır içine koyarak kaydedilir. Sürümler arasındaki diğer tek fark boşluk ve yorumlardır.

Çıktıyı stdout'a yazdırmak yerine beş karakterlik beş dizeden oluşan bir dizi olarak döndürmek kabul edilebilirse, bir bayt daha kaydedilebilir.

->a{p=t=0
4.times{|i|t+=a[i]*=a[3];p+=a[i]>>9&1<<i}
q=p==6&&t>0?19:'@AC@P*10'[p].ord
puts c='o---o',(0..2).map{|i|b=p*i==3?'|---|':'|   |';b[q%4]='|/|\|/'[q%4+(i&2)];q/=4;b},c}

Dizinin ayrıştırılmasından memnunum, ancak çıktıyı oluşturmanın daha kısa yolları olabileceğini düşünüyorum.

Giriş dizisinin dört öğesinin tümü de son öğeyle çarpılır. Bu, son öğenin pozitif olduğunu garanti eder ve vaka sayısını 16'dan 8'e düşürür. Öğeler, 9 basamaklı haklara sahiptir, böylece tüm pozitif sayılar 0 olur ve tüm negatif sayılar -1 olur (en azından girdi aralığında). Daha sonra paterni 1<<array indexgösteren 3 bitlik bir ikili sayı vermek için AND (ve) olurlar (aslında 4 bit, ancak son eleman her zaman pozitif olduğu için 4. bit her zaman sıfırdır.)

0..7'den itibaren bu sayı daha sonra her satırın hangi karakterlerinin boşluk olmadığını belirlemek için (iç çekme) bir arama tablosuna beslenir. Bu aşamada, eyer davası için iki farklı ekran ele alınmaktadır, toplam pozitifse, arama tablosundaki sayıya bir alternatif olarak (soru "ortalama" olarak dikkate alınmaktadır, ancak yalnızca işaretle ilgileniyorsa, bunun yerine toplamı dikkate almamızın önemi yoktur.)

Çıktı gösteriminin çalışma şekli, koddaki yorumlardan açıkça anlaşılmaktadır.

test programında çözülmemiş

f=->a{p=t=0
  4.times{|i|                      #for each number in the input
    t+=a[i]*=a[3];                   #multiply each number by a[3]; totalize the sum in t
    p+=a[i]>>9&1<<i                  #shift right to find if negative; AND with 1<<i to build index number for pattern 
  }                                #q is a 3-digit base 4 number indicating which character of each line is non-whitespace (if any). 
  q=p==6&&t>0?19:'@AC@P*10'[p].ord #It's encoded in the magic string, except for the case of saddles with a positive total, which is encoded by the number 19.
  s=(0..2).map{|i|                 #build an array of 3 strings, indexes 0..2
    b=p*i==3?'|---|':'|   |';        #IF p is 3 and we are on row 1, the string is |---| for the horizontal line case. ELSE it is |   |.
    b[q%4]='|/|\|/'[q%4+(i&2)];      #The numbers in q indicate which character is to be modified. The characters in the string indicate the character to replace with.
    q/=4;                            #If q%4=0, the initial | is replaced by | (no change.) i&2 shifts the string index appropriately for the last row.
    b                                #divide q by 4, and terminate the loop with the expression b so that this is the object loaded into array s.  
  }
puts c='o---o',s,c}                #print the array s, capped with "o---o" above and below.


[[1, 2, 1, 3],
[-9, -2, -2, -7],

[4, 5, -1, -2],
[-1, -2, 3, 4],

[7, -7, 7, -7],
[-5, 5, -5, 5],

[1, -6, -4, -1],
[-2, 3, 3, 4],

[-1, 6, -4, -1],
[2, -3, 3, 4],

[-1, -6, 4, -1],
[2, 3, -3, 4],

[-1, -6, -4, 1],
[2, 3, 3, -4],

[3, -8, -9, 2],
[-3, 8, 9, -2],

[8, -3, -2, 9],
[-8, 3, 2, -9],

[1, -4, -2, 5],
[-1, 4, 2, -5]].each{|k|f.call(k)}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.