Estetik açıdan hoş bir bölen ağaç oluşturun


43

Estetik açıdan hoş bir bölen ağaç girişinin Bölen bir ağaçtır nherhangi kompozit sayı için, m, iki çocuk düğümleri var bölenler çifti en yakın olan kare kökü arasında m. Sol düğüm küçük bölen molmalı ve sağ düğüm büyük bölen olmalıdır m. Ağaçtaki asal bir sayı çocuk düğüm içermemelidir. Ağacınız metin sanatı veya resim şeklinde olabilir. Metin sanat çıktısı için kurallar aşağıdaki gibidir.

Boşluk kuralları

Ağaçtaki düğümleri boşaltmak için aşağıdaki kurallara sahibiz:

  • Kökten belirli bir derinlikte bulunan düğümlerin tümü, çıktıdaki aynı metin satırında olmalıdır.
  / \ DEĞİL / \  
 / \ / 3
2 3 2
  • Sol düğümlerde, düğüm tek basamaklı bir sayıysa, son basamağın hemen üstünde başka bir sayı varsa, gelen dal sağ üstte olmalıdır. Örnek:
 / VE /
3 720
  • Sağ düğümler için, düğüm tek basamaklı bir sayıysa, ilk basamağın hemen üzerinde, gelen dal sol üstte olmalıdır. Örnek:
\ VE \
 7 243
  • Giden sol dallar için dal sayının solunda bir boşluk başlamalıdır. Örnek:
  275
 /
11
  • Giden doğru dallar için dal sayının sağında bir boşluk başlamalıdır. Örnek:
275
   \
   25
  • Ağacın aynı seviyesindeki iki düğümün, aralarında en az iki boşluk olması gerekir. Aynı zamanda, ağacın aynı seviyesindeki iki alt ağaç, aralarında olabildiğince az boşluk olmalıdır.
Bu ağaç çalışmıyor çünkü ** alt ağaç ** çok yakındır.

        504           
       / \          
      / \         
     / \        
    / \       
   21. 24     
  / \. / \    
 / \. / \   
3 7. 4 6  
        . / \ / \
        .2 2 2 3

Bu ağaç dalları arasında yeterli boşluk olmasına rağmen.

         504           
        / \          
       / \         
      / \        
     / \       
    / \      
   21 ... 24     
  / \ ... / \    
 / \ ... / \   
3 7 ... 4 6  
        ... / \ / \ 
        ... 2 2 2 3
  • Bir ağaçta iki alt ağaç birbirine çok yakınsa /\, ebeveynlerin üzerindeki ağaca bir başka dal satırı ekleyerek ayrılabilir .
   441                              
  / \ Son satır henüz doldurulmadı ve zaten alanımız tükendi.
 21 21
/ \ / \

Başka bir dal satırı ekle

     441                              
    / \ Neredeyse, ancak 7 ve 3 birbirine çok yakın.
   / \ Bir satır daha yapmalı.
  21 21
 / \ / \
3 7 3 7

Başka bir dal satırı ekle

      441
     / \ Ve biz bitti.
    / \
   / \
  21 21
 / \ / \
3 7 3 7

Örnekler

Tam bir örnek olarak, 24 bölen ağacı şöyle görünecek:

     24
    /  \
   /    \
  4      6
 / \    / \
2   2  2   3

Şekil 4 ve 6 24'ün kareköküne en yakın bölen çiftidir. 4 soldadır, çünkü daha küçüktür. Bir sonraki satırda, 3'ün solundaki 2 sayısı, çünkü daha küçük.

63 için bölen ağaç şöyle görünmeli:

  63        and NOT like this        63
 /  \                               /  \
7    9                             3   21
    / \                               /  \
   3   3                             7    3

Yanlış ağacında, 3 ve 21, 63'ün kareköküne en yakın bölen çifti değildir ve 3 ve 7 düzgün bir şekilde sıralanmaz. Bununla birlikte, 21'deki dal yerleşimi doğrudur.

42 yaşında olmalısın:

    42      and NOT        42
   /  \                   /  \
  6    7                 21   2
 / \                    /  \
2   3                  3    7

720'ye bir göz atalım. Alt ve alt ağaçların doğru şekilde yerleştirilebilmesi 720için beş dal seviyesine ihtiyacımız olduğunu unutmayın . Ayrıca, not olduğunu ve dalları iki seviyede olduğundan ve doğru boşluklar ve çocukları düğümleri ihtiyaç çocuk düğümleri var çocukları düğümler aynı düzeyde olmasını ihtiyacı .24302430463024

           720
          /   \
         /     \
        /       \
       /         \
      /           \ 
     24           30
    /  \         /  \
   /    \       /    \
  4      6     5      6
 / \    / \          / \
2   2  2   3        2   3

Meydan okuma

  • Senin görevin giriş için doğru aralıklı estetik olarak hoş bir bölen ağaç oluşturmak n, n1'den büyük bir pozitif tamsayı.
  • Çıktınız satır aralığı ve sondaki boşluklar ve satır başı ve sondaki yeni satırları içerebilir, ancak aksi takdirde yukarıda verilen boşluk kurallarına uymalıdır.
  • Çıktınızın olmasına izin verilir: metin resmi, resim (gerekirse eklenecek diğer biçimler).
  • Görüntüler için, ağacınızın düğümlerinin iyi aralıklı olduğundan ve ağacın aynı yüksekliğindeki düğümlerin görüntüde aynı yükseklikte olduğundan emin olun.
  • Bu kod golfü. En az bayt sayısı (veya eşdeğeri) kazanır.

Stewie Griffin'i bu fikri düşündüğü için ödüllendirin ve Peter Taylor, Martin Ender, Mego ve Eᴀsᴛᴇʀʟʏ Iʀᴋ'ye spesifikasyonları yeniden yazmadaki yardımları için çok teşekkürler. Her zaman olduğu gibi, herhangi bir öneri veya düzeltmeler çok takdir edilmektedir. İyi şanslar ve iyi golf!

Daha fazla test durumu:

2

  4
 / \
2   2

    20
   /  \
  4    5
 / \
2   2

  323
 /   \
17   19

                        362880
                       /      \
                      /        \
                     /          \
                    /            \
                   /              \
                  /                \
                 /                  \
                /                    \
               /                      \
              /                        \
            576                        630
           /   \                      /   \
          /     \                    /     \
         /       \                  /       \
        /         \                /         \
       /           \              /           \
      /             \            /             \
     24             24          21             30
    /  \           /  \        /  \           /  \
   /    \         /    \      /    \         /    \
  4      6       4      6    3      7       5      6
 / \    / \     / \    / \                        / \
2   2  2   3   2   2  2   3                      2   3

              1286250
             /       \
            /         \
           /           \
          /             \
         /               \
      1050               1225
     /    \             /    \
    /      \           /      \
   /        \         /        \
  30        35       35        35
 /  \      /  \     /  \      /  \
5    6    5    7   5    7    5    7
    / \
   2   3

Bu meydan okuma için teşekkür ederim. Bu şeyleri her seferinde çizmeden görselleştirebiliyorum: D
Conor O'Brien

Ağacın örneklere benzemesi gerekiyor mu, yoksa yerleşik Mathematica işlevini kullanabilir miyim? Öyle görünüyor bu çarpanlarına sahip ama.
JungHwan Min

@JHM Grafik çıktı etiketini saklamam gerektiğini biliyordum . Evet, bu yerleşik kullanabilirsiniz. Mücadeleyi düzenleyeceğim.
Sherlock9

Yanıtlar:


29

Python 2 , 711 651 575 559 554 547 539 540 530 522 bayt

Dört ay sonra bu cevabı yazmaya çalıştıktan sonra, bir duvarın içine girip bir hafta boyunca bırakıp durulayın, tekrarlayın, sonunda bu meydan okuma için uygun bir ASCII sanat cevabını bitirdim. Geriye kalan tek şey golf, ve böylece, golf önerileri çok açığız. Çevrimiçi deneyin!

Golf: -60 bayt sık kullanılan bazı işlevleri yeniden adlandırmak ve sonucun nasıl döndürüleceğini değiştirmekten. -73 alt ağaçların yüksekliklerinin nasıl kontrol edildiğini, aralık değişkenlerinin nasıl hesaplandığını ve sonucun nasıl döndürüldüğünü değiştirerek bayt. FlipTack'in isdigit()değişiminden -3 bayt . -16 byte, bu isdigit()değişimi daha da fazla oynayarak "" ile değiştiriyor E. Küçük iyileştirmelerden -5 bayt ve Python 3'ten Python 2'ye geçme. -8 kadar küçük bir değişimden bayt Atanımlanır kadar değişen Ttanımlanır ve ekleme Wkarşı parçasına nazaran daha az bir uzun dal ile herhangi bir alt ağacı, karşı parçasına nazaran daha uzun bir genel zorunlu olduğu hipotezini kullanan, kaldırmaQtamamen ve sonucun nasıl döndürüleceğini düzenleme. -10 kullanarak bayt A<10yerine L(S(A))<2için Ave B. -8 varsayılan değiştirmesini bayt Hiçin [0]kod asla mutasyona uğratarak değişken varsayılan argümanlar sorununu önler beri Hnasıl değişiyor, qkullanılarak tanımlanır (B>9)yerine 1-(B<10), kaldırma ptamamen, ve oluşturma Fiçin bir yedek olarak p+q-M.

Hata düzeltmeleri: Hipotez hatalıydı, karşı örnek 11**9 = 2357947691. +1 bayt

G=range;L=len;E=" "
def t(n,H=[0]):
 A=max(z*(n%z<1)for z in G(1,int(n**.5)+1));B=n/A;Z=str(n);M=L(Z)
 if A<2:return[Z]
 T=max([i for i in G(L(w))if"/"not in w[i]]for w in(t(A),t(B)));V=H[1:]or[T[k+1]-T[k]-1for k in G(L(T)-1)];x=t(A,V);y=t(B,V);P=x[0].rindex(str(A)[-1])+(A<10);q=y[0].index(str(B)[0])+(B>9);F=L(x[0])-P+q-M;h=H[0]or(F+M%2+2)/2or 1;return[E*(P+J)+(J<h and"/"+E*(2*h+M-2*J-2)+"\\"or Z)+E*(L(y[0])-q+J)for J in G(h,-1,-1)]+[(E*(2*h-F)).join(I<L(w)and w[I]or E*L(w[0])for w in(x,y))for I in G(max(L(x),L(y)))]

açıklama

Tüm fonksiyon yaklaşık dört adıma kadar kaynatılabilir:

  1. En büyük böleni çiftini belirleyin n, Ave B.
  2. Ait alt ağaçlar yapın Ave Bgerektiği gibi yeniden çizilmesi.
  3. Alt ağaçların arasına girmesi gereken boşlukların sayısını belirleyin.
  4. Yeni bölen ağacını çizin ve iade edin.

Her adımı sırayla izleyeceğim.

Adım 1. Açıkçası, bu en kolay adımdır. z1 ile karekök arasındaki her rakamı bölünebilirlik nve en büyüğü zile n//zeşleşmesi için kontrol edin. Sadece asal str(n)ise geri dön n(ya A==1da B==n)

Adım 2. ve alt ağaçlar çizin Ave Bve sayısını almak /\alt ağaçlar düğümler arasındaki dalları. Bunu yapmak için, içinde basamak bulunan her adımın indekslerini alırız, endekslerin ilk farklarını alır ve tekrar 1'i çıkarırız. Yükseklikleri elde ettikten sonra, onları en büyüğünü elde etmek için karşılaştırırız ve alt alanları yeni yüksekliklerle yeniden çizeriz.

Genelde daha uzun olan alt ağacın, her zaman kısa alt ağaçtaki dallara eşit ya da eşit olan dalları olduğuna dair gizli bir şüphem var ve bunu kodu golf oynamak için kullanabiliyorum, ancak henüz bunun kanıtı yok. Örnek olarak girin 11**9 = 2357947691.

Adım 3. Bu adımın yazılması aylar aldı. Adım 2'nin yazılması ve hata ayıklaması birkaç gün sürdü, ancak boşluk için doğru formülleri bulmak uzun sürdü. Gördüğüm şeyi birkaç paragrafa sığdırabilir miyim bir bakalım. Bu açıklamadaki bazı kodların o zamandan beri gerçek kodun dışında kaldığını unutmayın.

İlk olarak, p, q, h, P, Q, sve M. psol dalın /sonundan sol alt ağacın sağ tarafına kadar olan karakter sayısıdır . qsağ alt ağacın sol ucundan sağ dalın sonuna kadar olan karakter sayısıdır /. hkök ve alt ağaçların arasındaki dal sayısıdır. Pve Qbunlar sadece tersidir pve dalların qetrafındaki /\kökleri köklere kadar yerleştirmek için kullanışlıdır n. sİki alt ağaç arasına eklenen boşlukların sayısıdır. Men basittir; uzunluğu n. Grafik olarak koy:

            M
           ---
           720           
 |        /   \          
 |       /     \         
h|      /       \        
 |     /         \       
 |    /           \      
   P    p    s   q   Q   
------______---____------
     24           30     
    /  \         /  \    
   /    \       /    \   
  4      6     5      6  
 / \    / \          / \ 
2   2  2   3        2   3

Belirleme formülü pşudur: p = len(x[0]) - x[0].rindex(str(A)[-1]) - (A<10)uzunluk, eksi A'daki son karakterin sıfır dizinini eksi, tek basamaklı As için bir eksi .

Belirleme formülü qşudur: q = y[0].index(str(B)[0]) + (B>9)B'deki ilk karakterin indeksi, ayrıca sıfır indeksleme için bir düzeltme, eksi tek haneli Bs için bir düzeltme (çok basamaklı Bs için bir düzeltmede birleştirilmiştir ).

Belirlenmesi formülü hşudur: h = H[0] or (p+q+M%2+2-M)//2 or 1. Ya önceden tanımlanmış bir taneden Halıyoruz; bu, ağacı yeniden çizdiğimizi, kullandığımızı (from_the_left + from_the_right + parity_space + 2 - len(root)) // 2)veya minimum sayıda dal seviyesi kullandığımızı gösterir.

Belirlenmesi formülü sşudur: s = 2*h+M-p-q. Biz çıkarmak pve qonların en geniş yeri ise root dalları arasındaki boşluk sayısından 2*h + M.

Adım 4. Sonunda hepsini bir araya getirdik. Önce kökü [" "*(P+h)+Z+" "*(Q+h)]yaparız, sonra dalları alt ağaçlara [" "*(P+J)+"/"+" "*(2*h+M-2*J-2)+"\\"+" "*(Q+J)for J in G(h)][::-1]koyarız, ve sonunda düzgün şekilde yerleştirilmiş alt ağaçlarımıza koyarız [(" "*(2*h+M-p-q)).join([(I<L(w)and w[I]or" "*L(w[0]))for w in(x,y)])for I in G(max(L(x),L(y)))].

Et voilà! Estetik açıdan hoş bir bölen ağacımız var!

Ungolfing:

def tree(n, H=[0]):
    A = max(z for z in range(1, int(n**.5)+1) if n%z<1)
    B = n/A
    Z = str(n)
    M = len(Z)
    if A < 2:
        return [Z]

    # redraw the tree so that all of the numbers are on the same rows
    x = tree(A)
    y = tree(B)
    for W in [x, y]:
        T = [i for i in range(len(W)) if "/" not in W[i]]
    V = H[1:] or [T[k+1]-T[k]-1 for k in range(len(T)-1)]
    x = tree(A, V)
    y = tree(B, V)

    # get the height of the root from the two trees
    P = x[0].rindex(str(A)[-1]) + (A < 10)
    p = len(x[0]) - P
    q = y[0].index(str(B)[0]) + (B > 9)
    Q = len(y[0]) - q
    h = hs[0] or (p+q+M%2+2-M)/2 or 1

    # and now to put the root down
    R = []
    s = 2*h+M-p-q
    for I in range(max(len(x),len(y))):
        c = I<len(x) and x[I] or " "*len(x[0])
        d = I<len(y) and y[I] or " "*len(y[0])
        R += c + " "*s + d,
    for J in range(h, -1, -1):
        if J<h:
            C = "/" + " "*(2*h+M-2*J-2) + "\\"
        else:
            C = Z
        R += [" "*(P+J) + C + " "*(Q+J)]
    return R

Çekiniz isdigitolabilir '/'<x[i].strip()[0]<':'mi?
FlipTack

14

Mathematica, 96 86 81 79 78 bayt

2 bayt için @ Martininder teşekkürler.

TreeForm[If[PrimeQ@#,#,#0/@(#2[#,#2/#]&[Max@Nearest[Divisors@#,#^.5],#])]&@#]&

Çıktı şöyle görünür:

görüntü tanımını buraya girin

açıklama

Max@Nearest[Divisors@#,#^.5]

Girişin bölenlerin listesini oluşturun. Girişin kareköküne en yakın elemanı bulun. ( Maxçıktıyı düzleştirmek içindir)

#2[#,#2/#]&

Girişi yukarıda bulunan bölene bölerek diğer böleni bulun, girdiyi sonucun başı olarak uygulayın.

#0/@

İşlemi tekrarlayın.

If[PrimeQ@#,#, ... ]

Girdi asal ise, hiçbir şey yapmayın.

TreeForm

Çıkışı biçimlendirin.

Düzenleme: Estetik açıdan daha hoş bir sürüm (258 bayt)

TreeForm[#/.{a_,_,_}:>a,VertexRenderingFunction->(#2~Text~#&),VertexCoordinateRules->Cases[#,{_,_},Infinity,Heads->True]]&@(If[PrimeQ@#,{##},{##}@@#0@@@({{#,#3-#4{1,√3}/2,#4/2},{#2/#,#3-#4{-1,√3}/2,#4/2}}&[Max@Nearest[Divisors@#,√#],##])]&[#,{0,0},1])&

Çıktı şöyle görünür:

görüntü tanımını buraya girin


3
Sqrt@#-> #^.5(elbette o zaman infix notasyonu için kullanamazsınız Nearestama sonra kullanabilirsiniz Max@).
Martin Ender,

5
Kurallara uyuyor, ama bu ağaç estetik açıdan hoş olmayan xD'den çok uzak
Beta Decay

2
Güzellik seyircinin gözünde :)
Nelson

1
Bunun geçerli olduğundan emin değilim. Örneklerden farklı olarak, her satırdaki düğümler eşit aralıklarla yerleştirilmez. Ek olarak, çizgiler doğru rakama bağlanmıyor.
Mego

1
@Mego Peki, OP geçerli olduğunu söyledi .
R. Kap,

3

Kömür , 302 bayt

≔⟦⟦N⁰θ⁰¦⁰⟧⟧θFθ«≔§ι⁰ζ≔⌈E…·²Xζ·⁵∧¬﹪ζκκη¿η«F⟦η÷ζη⟧«≔⟦κ⊕§ι¹Iκ⁰¦⁰⟧κ⊞ικ⊞θκ»⊞υι»»≔…⁰⌈Eθ§ι¹ηF⮌竧≔ηι⊕⌈⟦⁰⌈Eυ∧⁼§κ¹ι÷Σ⟦¹§§κ⁵¦⁴‹⁹§§κ⁵¦⁰§§κ⁶¦³‹⁹§§κ⁶¦⁰±L§κ²⟧²⟧FυF²§≔κ⁺³λ⁺⁺§ηι∨⊖L§§κ⁺⁵벦¹§§κ⁺⁵λ⁺³λ»Fυ«§≔§ι⁵¦³⁻⁻§ι³§η§ι¹∨⊖L§§ι⁵¦²¦¹§≔§ι⁶¦³⁻⁺⁺§ι³L§ι²§η§ι¹‹⁹§§ι⁶¦⁰»F⊕Lη«Fθ«F⁼§κ¹ι«←⸿M§κ³→F‹⁵Lκ«↙P↙§ηι↗»§κ²↓F‹⁵LκP↘§ηι»»M⊕§ηι↓

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Ayrıntılı sürüm çok ayrıntılı olduğundan, ana algoritmanın JavaScript çevirisidir:

u = []; // predefined variable, used as list of branches
q = [[+s, 0, s, 0, 0]]; // list of nodes starts with the root.
for (i of q) { // iterate nodes, includes new nodes
    z = i[0]; // get node value
    h = Math.max(...[...Array(Math.floor(z ** 0.5) + 1).keys()].slice(2).filter(
        k => z % k < 1)); // find largest factor not above square root
    if (h) {
        for (k of [h, z / h]) {
            k = [k, i[1] + 1, `${k}`, 0, 0]; // create child node
            i.push(k); // add each child to parent (indices 5 and 6)
            q.push(k); // and to master nodelist
        }
        u.push(i);
    }
}
h = new Array(Math.max(...q.map(i => i[1]))); // list of branch heights
for (i = h.length; i --> 0; ) {
    // find branch height needed to space immediate children apart at this depth
    h[i] = 1 + Math.max(...u.map(k => k[1] == j && // filter on depth
        1 + k[5][3] + (k[5][0] > 9) + k[6][2] + (k[6][0] > 9) - k[2].length
        >> 1)); // current overlap, halved, rounded up
    // calculate the new margins on all the nodes
    for (k of u) {
        k[3] = h[i] + (k[5][2].length - 1 || 1) + k[5][3]; // left
        k[4] = h[i] + (k[6][2].length - 1 || 1) + k[6][4]; // right
    }
}
// calculate the absolute left margin of all the nodes under the root
for (i of u) {
    i[5][3] = i[3] - h[i[1]] - (i[5][2].length - 1 || 1);
    i[6][3] = i[3] + i[2].length + h[i[1]] - (i[6][0] > 9);
}
// print the nodes (sorry, no transliteration available)
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.