Alandaki faktörleri sığdırmak


11

1000'in altında pozitif bir tamsayı verildiğinde, o alanla ilgili tüm dikdörtgenleri görüntüleyin.

Görev

Diyelim ki giriş 20'dir. 20 × 1, 10 × 2 veya 5 × 4 dikdörtgen yapabiliriz, bu geçerli bir çıktıdır:

********************

**********
**********

*****
*****
*****
*****

Her olası dikdörtgenin tam olarak bir kez göründüğünü unutmayın.

Dikdörtgenler herhangi bir sırada, yönde veya konumda görünebilir, ancak köşelerde bile iki dikdörtgen üst üste gelemez veya temas edemez. Aşağıdakiler de geçerlidir:

********************

            ****
**********  ****
**********  ****
            ****
            ****

puanlama

Çıktının sınırlama kutusu alanı (BBA), tüm dikdörtgeni çevreleyen minimum dikdörtgenin alanıdır. İlk örnek çıktısında, boyut 20 × 9'dur, bu yüzden BBA 180'dir. İkinci örnek çıktısında boyut 20 × 7'dir, bu yüzden BBA sadece 140'tır.

Giriş 60, 111, 230, 400 ve 480 olduğunda çıkışın BBA'sını bulun ve ekleyin. Bu toplamı kodunuzun bayt cinsinden boyutuyla çarpın. Sonuç puanınızdır; en düşük puan kazanır.

kurallar

  • Program (veya fonksiyon) 1000'in altındaki herhangi bir pozitif tamsayı için geçerli çıktı üretmelidir.
  • Çıktıda yalnızca yıldız ( *), boşluk ( ) ve yeni satırlar bulunmalıdır .
  • Dikdörtgenler arasında herhangi bir boşluk olabilir, ancak bu BBA'ya aittir.
  • Satırları veya sütunları, yalnızca boşlukları varsa, BBA'ya dahil etmeyin.

Özel durumlar sabit kodlanabilir mi?
Calvin'in Hobileri

@ Calvin'sHobbies Evet, ama çok yardımcı olacağından şüpheliyim.
Ypnypn

3
@ Calvin'sHobbies Volkswagen çözümü.
Level River St

Yanıtlar:


3

Yakut, 228 bayt * 21895 = 4992060

->n{a=(0..n*2).map{$b=' '*n}
g=0
m=n*2
(n**0.5).to_i.downto(1){|i|n%i<1&&(m=[m,n+h=n/i].min
g+=h+1
g<m+2?(a[g-h-1,1]=(1..h).map{?**i+$b}):(x=(m-h..m).map{|j|r=a[j].rindex(?*);r ?r:0}.max 
(m-h+1..m).each{|j|a[j][x+2]=?**i}))}
a}

Yasadışı koddan birkaç değişiklik. Bunlardan men büyüğü , değişkenin anlamının en kareli dikdörtgenin yüksekliğinden en kareli dikdörtgenin yüksekliğine kadar değişmesidir n.

Önemsiz olarak, büyük için sağda çok fazla gereksiz boşluk anlamına gelen *40değiştirildi ; ve değiştirildiğinde hangi alt kısmında çizilen araçlar dikdörtgenler her zaman (sadece çarpanlara olan sayılar için yoksul ambalaj içinde bu sonuçlar ilk iki sütun özledim )*nn-20(n/2)*2

açıklama

Sonunda buna geri dönmek için zaman buldum.

Belirli için nen küçük alan en uzun dikdörtgen ikisi için yeterli alana sahip olmalıdır 1*nve squarest dikdörtgen x*y. Her iki dikdörtgenin de uzun kenarları aynı yönde olacaksa, en iyi yerleşimin elde edilebileceği açıktır.

Dikdörtgenler arasındaki boşluk gereksinimini göz ardı ederek, toplam alanın ya (n+y)*x = (n+n/x)*xya olduğunu buluruz n*(x+1). Her iki durumda da, bu değerlendirir n*x + n. Boşluk da dahil olmak üzere x, dikdörtgenleri uç uca nyerleştirirsek veya dikdörtgenleri yan yana yerleştirirsek fazladan bir şey eklememiz gerekir . Bu nedenle birincisi tercih edilir.

Bu (n+y+1)*x, alan alanı için aşağıdaki alt sınırları verir :

n     area
60    71*6=426
111  149*3=447
230  254*10=2540
400  421*20=8240
480  505*20=10100

Bu, aşağıdaki algoritmayı önerir:

Find the value (n+y+1) which shall be the field height
Iterate from the squarest rectangle to the longest one
  While there is space in the field height, draw each rectangle, one below the other, lined up on the left border.
  When there is no more space in the field height, draw the remaining rectangles, one beside the other, along the bottom border, taking care not to overlap any of the rectangles above.
  (Expand the field rightwards in the rare cases where this is necessary.)

Aşağıdaki 71 * 8 = 568 çıktıyı veren 60 hariç, gerekli test senaryoları için tüm dikdörtgenleri yukarıda belirtilen alt sınırlar dahilinde almak mümkündür. Bu, en ince iki dikdörtgeni bir kare ve sonra yukarı doğru hareket ettirerek 60 * 9 = 540'a biraz geliştirilebilir, ancak tasarruf minimaldir, bu nedenle muhtemelen herhangi bir ekstra kod değmez.

10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******

*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
       *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
       *
***    *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *

Bu toplam 21895 alan verir.

Kod çözülmemiş kod

f=->n{
  a=(0..n*2).map{' '*40}                                      #Fill an array with strings of 40 spaces
  g=0                                                         #Total height of all rectangles
  m=n                                                         #Height of squarest rectangle (first guess is n) 
  (n**0.5).to_i.downto(1){|i|n%i<1&&(puts n/i                 #iterate through widths. Valid ones have n%i=0. Puts outputs heights for debugging.
    m=[m,h=n/i].min                                           #Calculate height of rectangle. On first calculation, m will be set to height of squarest rectangle.
    g+=h+1                                                    #Increment g
    g<n+m+2?                                                  #if the rectangle will fit beneath the last one, against the left margin
      (a[g-h-1,1]=(1..h).map{'*'*i+' '*40})                      #fill the region of the array with stars
    :                                                         #else  
      (x=(n+m-h..n+m).map{|j|r=a[j].rindex('* ');r ?r:-2}.max    #find the first clear column
      (n+m-h+1..n+m).each{|j|a[j][x+2]='*'*i}                    #and plot the rectangle along the bottom margin
    )
  )}
a}                                                            #return the array

puts f[gets.to_i]


1

Yakut, 56 bayt

90385 * 56 = 5061560 çıktısının Martin ile aynı olduğunu varsayarsak (olduğuna inanıyorum.)

->n{1.upto(n){|i|i*i<=n&&n%i==0&&puts([?**(n/i)]*i,'')}}

İşte yararlı bir test programında başka bir yararlı fonksiyon

f=->n{1.upto(n){|i|i*i<=n&&n%i==0&&print(n/i,"*",i,"\n")};puts}

f[60];f[111];f[230];f[400];f[480]

Hangi referans için aşağıdaki çıktıyı verir:

60*1
30*2
20*3
15*4
12*5
10*6

111*1
37*3

230*1
115*2
46*5
23*10

400*1
200*2
100*4
80*5
50*8
40*10
25*16
20*20

480*1
240*2
160*3
120*4
96*5
80*6
60*8
48*10
40*12
32*15
30*16
24*20
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.