Şeytanın Merdiveni Çiz


46

Şeytan Merdiven fraktal benzeri Cantor kümesi ile ilişkili işlevi olduğunu.

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

Görevin bu korkak işlevi tekrarlamak - ASCII sanatında!

Giriş

n >= 0Çıktının boyutunu belirten tek bir tamsayı . Girdi, STDIN, işlev argümanı veya komut satırı argümanı yoluyla verilebilir.

Çıktı

Şeytanın merdivenindeki ASCII-sanat sunumu nya bir dize olarak ya da STDOUT'a basılmıştır. Her satırın sonundaki sondaki boşluklar tamamdır, ancak baştaki boşluklar değildir. İsteğe bağlı olarak tek bir izleyen yeni satır basabilirsiniz.

Boyut 0için çıktı sadece:

x

(İsterseniz, bunun yerine boşluk dışında yazdırılabilir başka bir ASCII karakteri kullanabilirsiniz x.)

Boyut için n > 0biz:

  • Boyut çıktısını alın n-1ve her sırayı üç kat faktörü ile gerin
  • Tek xs sıraları arasında oluk
  • Satırları sağa doğru kaydırın, böylece xher sütunda tam olarak bir tane olur ve ilklerin sıraları xminimum olurken sıralar azalır.

Örneğin, çıktı n = 1:

    x
 xxx
x

Çıktısını elde etmek için n = 2, her satırı üç katına kadar uzatırız:

            xxx
   xxxxxxxxx
xxx

Bekarların sıraları arasındaki oluk x:

x
            xxx
x
   xxxxxxxxx
x
xxx
x

Sağa kaydırın:

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

Başka bir örnek olarak, burada olduğu n = 3.

puanlama

Bu kod golf, bu yüzden en az bayttaki çözüm kazanıyor.

Yanıtlar:


7

Pyth, 30

jb_u+G+*leGd*HNu+N+^3hTNUQ]1]k

Bu, STDIN'den girdi alan ve Grc'nin Cantor kümesini bulma yöntemini kullanan bir programdır. Eğriyi görüntülemek için "karakterini kullanır.

Burada çevrimiçi deneyin.

Açıklama:

Kodu iki bölüm halinde anlatacağım, ilk önce kantor seti üretimi:

u+N+^3hTNUQ]1
u        UQ]1         : reduce( ... , over range(input), starting with [1])
 +N                   : lambda N,T: N + ...
   +^3hTN             : 3 ** (T+1) + N   (int + list in pyth is interpreted as [int] + list)

Ve çıktı biçimlendirmesi:

jb_u+G+*leGd*HN    ]k
jb_                    : "\n".join(reversed(...)
   u               ]k  : reduce(lambda G,H: ... , over cantor set, starting with [""])
    +G+*leGd           : G + len(G[-1]) * " " + ...
            *HN        : H * '"'

Varsayılan olarak pyth N = '"' işaretine dikkat edin.


32

J ( 73 68 58 41 39 38 35 34 karakter)

Bir süre sorun hakkında düşündükten sonra, Şeytanın Merdiven desenini oluşturmak için tamamen farklı bir yol buldum. Açıklamasını içeren eski cevap kaldırıldı, nasıl olduğunu anlamak için bu cevabın revizyonlarını inceleyebilirsiniz.

Bu cevap, şeytanın merdivenini temsil eden bir dizi boşluk ve keskinlik döndürür.

' #'{~1(]|.@=@#~[:,3^q:)2}.@i.@^>:

Açık gösterimde iki bölüme ayrılan cevap:

f =: 3 : '|. = (, 3 ^ 1 q: y) # y'
g =: 3 : '(f }. i. 2 ^ >: y) { '' #'''

açıklama

Yaklaşım biraz farklı, bu yüzden gözlemleyin ve hayran olun.

  1. >: 3 - üç artımlı, yani

    4
    
  2. 2 ^ >: 3 - iki, üçlü artışın gücüne, yani

    16
    
  3. i. 2 ^ >: 3- ilk 2 ^ >: 3tamsayılar, yani

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    
  4. }. i. 2 ^ 4- 2 ^ >: 3baştaki ilk tamsayılar,

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    

    Bu sırayı arayalım s; fşimdi giriyoruz .

  5. 1 q: s- Her bir öğenin birincil ayrıştırmasında 2'nin üsleri s. Genel olarak, primer ayrıştırmasındaki x q: yilk xprimerler için üslerin bir tablosunu verir y. Bu verim:

    0
    1
    0
    2
    0
    1
    0
    3
    0
    1
    0
    2
    0
    1
    0
    
  6. 3 ^ 1 q: s - bu üslerin gücüne üç, yani

     1
     3
     1
     9
     1
     3
     1
    27
     1
     3
     1
     9
     1
     3
     1
    
  7. , 3 ^ 1 q: s- önceki sonucun ravel'i (yani yapısıyla argüman bir vektöre çarptı). Bu gereklidir, çünkü q:istenmeyen bir takip ekseni ortaya çıkar. Bu verim

     1 3 1 9 1 3 1 27 1 3 1 9 1 3 1
    
  8. (, 3 ^ 1 q: s) # s- sönceki sonuçtaki karşılık gelen öğe kadar sık ​​çoğaltılan öğenin, yani

    1 2 2 2 3 4 4 4 4 4 4 4 4 4 5 6 6 6 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 10 10 10 11 12 12 12 12 12 12 12 12 12 13 14 14 14 15
    
  9. = (, 3 ^ 1 q: s) # s - önceki sonucun kendi kendini sınıflandırması, bu, her satırın bağımsız değişkenin benzersiz öğelerinden birini temsil ettiği bir matris, her sütun, bağımsız değişkenin karşılık gelen öğesini temsil eder ve her hücre, satır ve sütun öğelerinin eşit olup olmadığını temsil eder. yani,

    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    
  10. |. = (, 3 ^ 1 q: s) # s - önceki sonuç dikey eksen boyunca çevrilmiş.

  11. (|. = (, 3 ^ 1 q: s) # s) { ' #'- diziye endeksleri olarak kullanılan önceki sonuç ürün ' #', yani 0ile ikame edilir  ve 1değiştirilir #olup,

                                                                    #
                                                                 ### 
                                                                #    
                                                       #########     
                                                      #              
                                                   ###               
                                                  #                  
                       ###########################                   
                      #                                              
                   ###                                               
                  #                                                  
         #########                                                   
        #                                                            
     ###                                                             
    #      
    

    İstediğimiz sonuç.


Güç döngüsü (,],~3^#@~.)@]içinde (1,[:,1,"0~3*]) 1 bayt yerine tasarruf sağlar. Ve ile Tamam !çıkış karakter olarak u:32+yerine ' #'{~başka bir tasarruf sağlar.
randomra

#\ yerine i.@#ve APL sollamak! :)
randomra

İkinci çözümün işe yaramıyor çünkü bir kere ihtiyaç duyulacak, ama APL'yi yenmenin başka bir yolunu buldum.
FUZxxl

Yeni çıktı için n-1değil merdiven n.
randomra,

@randomra Ah… bu boktan. Düzeltilebilir olup olmadığını göreyim.
FUZxxl

26

Altıgen , 217 bayt

Bu son derece eğlenceliydi. Bu mücadeleyi gönderdiğiniz için teşekkür ederiz.

Tam açıklama: Bu zorluğun yayınlandığı tarihte dil (Hexagony) mevcut değildi. Bununla birlikte, onu icat etmedim ve dil bu zorluk için (ya da başka herhangi bir özel zorluk için) tasarlanmadı.

){_2"_{\"{{""}"{'2//_.\><*\"\/_><[\]/3\'\_;|#__/(\2\'3_'}(#:|{$#{>_\//(#={/;01*&"\\_|[##={|}$_#></)]$_##|){*_.>.(/?#//~-="{}<_"=#/\}.>"%<.{#{x\"<#_/=&{./1#_#>__<_'\/"#|@_|/{=/'|\"".{/>}]#]>(_<\'{\&#|>=&{{(\=/\{*'"]<$_

Altıgen olarak yerleştirilmiş:

        ) { _ 2 " _ { \ "
       { { " " } " { ' 2 /
      / _ . \ > < * \ " \ /
     _ > < [ \ ] / 3 \ ' \ _
    ; | # _ _ / ( \ 2 \ ' 3 _
   ' } ( # : | { $ # { > _ \ /
  / ( # = { / ; 0 1 * & " \ \ _
 | [ # # = { | } $ _ # > < / ) ]
$ _ # # | ) { * _ . > . ( / ? # /
 / ~ - = " { } < _ " = # / \ } .
  > " % < . { # { x \ " < # _ /
   = & { . / 1 # _ # > _ _ < _
    ' \ / " # | @ _ | / { = /
     ' | \ " " . { / > } ] #
      ] > ( _ < \ ' { \ & #
       | > = & { { ( \ = /
        \ { * ' " ] < $ _

Program aslında #talimatı kullanmıyor, bu yüzden hangi hücrelerin kullanılmadığını göstermek için bu karakteri kullandım.

Bu program nasıl çalışır? Bu bağlıdır. Kısa versiyonunu mu yoksa uzun mu istiyorsun?

Kısa açıklama

Aşağıdaki açıklamada "hat" ve "bölüm" ile ne demek istediğimi göstermek için, amaçlanan çıktının bu diseksiyonu düşünün:

segments →
 │   │ │         │ │   │x   lines
─┼───┼─┼─────────┼─┼───┼─     ↓
 │   │ │         │ │xxx│
─┼───┼─┼─────────┼─┼───┘
 │   │ │         │x│
─┼───┼─┼─────────┼─┘
 │   │ │xxxxxxxxx│
─┼───┼─┼─────────┘
 │   │x│
─┼───┼─┘
 │xxx│
─┼───┘
x│

Açıklanan, program aşağıdaki sözde koduna karşılık gelir:

n = get integer from stdin

# Calculate the number of lines we need to output.
line = pow(2, n+1)

while line > 0:
    line = line - 1

    # For all segments except the last, the character to use is spaces.
    ch = ' ' (space, ASCII 32)

    # The number of segments in each line is
    # equal to the line number, counting down.
    seg = line

    while seg > 0:
        seg = seg - 1

        # For the last segment, use x’s.
        if seg = 0:
            ch = 'x' (ASCII 120)

        # Calculate the actual segment number, where the leftmost is 1
        n = line - seg

        # Output the segment
        i = pow(3, number of times n can be divided by 2)
        i times: output ch

    output '\n' (newline, ASCII 10)

end program

Uzun açıklama

Lütfen bu renk kodlu kod yolu şemasına bakın.

Yürütme yolu

İşlem sol üst köşede başlar. Talimatların sırası oldukça sarsılmış bir yol izleyerek ){2'"''3''"2}?)(artı birkaç gereksiz iptali, "{vb.) Gerçekleştirilir . Koyu kırmızı renkle vurgulanmış olan İşaretçi No. 0 ile başlıyoruz. Yarıda, sağ üst köşeden başlayıp orman yeşili renkle boyanmış olarak # 1'e geçiyoruz. IP # 2 peygamber çiçeği mavisi (orta sağda) ile başladığında, hafıza düzeni şu şekildedir:

Bellek düzeni

Tüm program boyunca, 2a ve 2b etiketli kenarlar her zaman değere sahip olacaktır 2(bunları sırasıyla 2 by hesaplamak ve 2'ye bölmek için kullanırız) ve 3 etiketli kenar her zaman 3(3ⁱ hesaplamak için kullanırız) olacaktır.

Peygamber Çiçeği mavisi ile vurgulanan ilk döngümüze girerken işe başlıyoruz. Bu döngü (}*{=&}{=2ⁿ⁺¹ değerini hesaplamak için talimatları yürütür . Döngüden çıktığında, eyer kahverengii yolu izlenir ve bu bizi Talimat İşaretçisi # 3'e götürür. Bu IP yalnızca alt kenarı boyunca batıya doğru altıncı sarı sarıya bakar ve kısa süre sonra kontrolü IP # 4'e geçirir.

Fuşya yolu, sol alttan başlayarak IP # 4'ün hızlı bir şekilde azalan çizgiye doğru ilerlediğini , ch32 (boşluk karakteri) ve seg'ı (yeni değer) satırının nasıl ayarlanacağını gösterir . Gerçekte 2ⁿ⁺¹ − 1 ile başladığımız ve sonunda 0 değerinde son bir yineleme yaşadığımızdan önceki azalmadan kaynaklanıyor. Sonra ilk iç içe döngüye giriyoruz .

Biz kısa bir eksiltme sonra, dallanma çivit, yöneltebileceğiz seg , gördüğümüz ch güncellendi xyalnızca seg şimdi sıfırdır. Daha sonra, içinde bulunduğumuz segmentin gerçek sayısını belirlemek için n - line segmente ayarlanır . Hemen bu sefer domatesin renginde başka bir döngüye gireriz.

Burada, kaç kez n'in (mevcut segment numarası) 2'ye bölünebileceğini anlarız. Modulo bize sıfırı verdiği sürece, i'yi artırır ve n'yi 2'ye böleriz. Memnun olduğumuzda n artık böylesi bölünemez ilk olarak gücü 3 ila yükseltir:, iki döngü içeren gri, içine dal i biz hesaplanır ve daha sonra çıkış olarak ch birçok kez. Bu döngülerden ilki bir[Kumandayı IP # 3'e geçiren komut - daha önce alt kenarı boyunca sadece bebek adımlarını atıyordu. Döngünün gövdesi (3 ile çarpma ve azaltma), kodun alt kenarı boyunca bitmeyen koyu zeytin yeşili bir çevrede hapsedilen yalnız bir IP # 3 tarafından yürütülür. Benzer şekilde, bu kayrak gri halkalarının ikincisi, burada koyu Hint kırmızısı ile gösterilen ch ve azalmayı göstermek ]için IP # 5'i aktive eden bir talimat içerir . Her iki durumda da, serviste hapsolmuş olan Talimat İşaretçileri, bir seferde bir kez yineleme gerçekleştirir ve yalnızca hizmetlerinin bir kez daha çağrılacağı zamanı ısırmak için IP # 4'e geri dönüş kontrolü sağlar. Bu arada, kayrak grisi fuşyası ve indigo kardeşleriyle birleşiyor.

As seg kaçınılmaz sıfıra ulaştığında, sadece derhal satır karakteri verir ve çim yeşil yolu, içine çivit döngüden çıkılır devam etmek için geri fuşya içine birleştirir hat döngü. Hat döngüsünün son yinelemesinin ötesinde, nihai program sonlandırmasının kısa samurlu ebon yolu yer alır.


8
Şimdi bu sadece düz eski moda delilik.
FUZxxl

21

Python 2, 78

L=[1]
i=3
exec"L+=[i]+L;i*=3;"*input()
while L:x=L.pop();print' '*sum(L)+'x'*x

Listeden başlayarak L=[1], onu kopyalayıp ortadaki 3 gücünü bir araya getirdik, sonuçta [1, 3, 1]. Bu nbize Şeytanın merdiveni için sıra uzunluğu vermek için tekrarlanır . Sonra boşluklarla doldurulmuş her satırı yazdırıyoruz.


20

APL, 38

⊖↑'x'/⍨¨D,⍨¨0,¯1↓-+\D←{1,⍨∊1,⍪3×⍵}⍣⎕,1

Örnek:

      ⊖↑'x'/⍨¨D,⍨¨0,¯1↓-+\D←{1,⍨∊1,⍪3×⍵}⍣⎕,1
⎕:
      2
                  x
               xxx 
              x    
     xxxxxxxxx     
    x              
 xxx               
x   

Açıklama:

⊖↑'x'/⍨¨D,⍨¨0,¯1↓-+\D←{1,⍨∊1,⍪3×⍵}⍣⎕,1

                                     ⎕       ⍝ read a number from the keyboard
                       {           }⍣ ,1      ⍝ apply this function N times to [1]
                               3×⍵           ⍝ multiply each value by 3
                           ∊1,⍪               ⍝ add an 1 in front of each value
                        1,⍨                  ⍝ add an 1 to the end
                     D←                      ⍝ store values in D (lengths of rows)
                   +\                        ⍝ get running sum of D
                  -                          ⍝ negate (negative values on / give spaces)
             0,¯1↓                           ⍝ remove last item and add a 0 to the beginning
                                             ⍝ (each row needs offset of total length of preceding rows)   
         D,⍨¨                                ⍝ join each offset with each row length
   'x'/⍨¨                                    ⍝ get the right number of x-es and spaces for each row
 ↑                                           ⍝ make a matrix out of the rows
⊖                                            ⍝ mirror horizontally 

Bu güzel bir çözüm.
FUZxxl

20
Kodun açıklanmasının Şeytanın Merdiveni gibi görünmesini seviyorum.
Alex A.

Daha da kısa bir APL çözümü buldum.
FUZxxl

14

GNU sed, 142

En kısa cevap değil, ama sed !:

s/$/:/
:l
s/x/xxx/g
s/:/:x:/g
tb
:b
s/^1//
tl
s/:x/X/g
s/^/:/
:m
s/.*:([Xx]+)Xx*:$/&\1:/
tm
:n
s/([ :])[Xx](x*Xx*)/\1 \2/g
tn
s/:/\n/g
s/X/x/g

Bu sed (yerel aritmetik değil) olduğundan, "Çıktının büyüklüğünü belirten tek bir tamsayı n> = 0" kuralını kullanarak özgürlük alıyorum . Bu durumda, giriş tamsayısı 1, uzunluğu n olan bir s dizesi olmalıdır . Bunun n'nin doğrudan sayısal bir eşdeğeri olmasa da, çıktının boyutunu "gösterdiğini" düşünüyorum . Böylece n = 2 için giriş dizisi şöyle olacaktır 11:

$ echo 11 | sed -rf devils-staircase.sed

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

Bu, üstel zamandaki O (cn) ' nin karmaşıklığı ile tamamlanıyor gibi görünüyor ; c, yaklaşık 17'dir. N = 8, benim için yaklaşık 45 dakika sürdü.


Alternatif olarak, n'nin sayısal olarak tam olarak girilmesi gerekiyorsa, bunu yapabiliriz:

sed, 274 bayt

s/[0-9]/<&/g
s/9/8Z/g
s/8/7Z/g
s/7/6Z/g
s/6/5Z/g
s/5/4Z/g
s/4/3Z/g
s/3/2Z/g
s/2/1Z/g
s/1/Z/g
s/0//g
:t
s/Z</<ZZZZZZZZZZ/g
tt
s/<//g
s/$/:/
:l
s/x/xxx/g
s/:/:x:/g
tb
:b
s/^Z//
tl
s/:x/X/g
s/^/:/
:m
s/.*:([Xx]+)Xx*:$/&\1:/
tm
:n
s/([ :])[Xx](x*Xx*)/\1 \2/g
tn
s/:/\n/g
s/X/x/g

Çıktı:

$ echo 2 | sed -rf devils-staircase.sed

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

7
Bu gerçekten havalı.
FUZxxl

8

Python 2, 81

def f(n,i=1,s=0):
 if i<2<<n:q=3**len(bin(i&-i))/27;f(n,i+1,s+q);print' '*s+'x'*q

Program versiyonu (88)

def f(n,s=0):
 if n:q=3**len(bin(n&-n))/27;f(n-1,s+q);print' '*s+'x'*q
f((2<<input())-1)

n1 indeksli satırdaki x sayısı 3'tür ( nlsb'den başlayarak ilk ayarlanan bitin indeksi ).


8

Python 2, 74

def f(n,s=0):
 if~n:B=3**n;A=s+B-2**n;f(n-1,A+B);print' '*A+'x'*B;f(n-1,s)

Özyinelemeli bir yaklaşım. Büyüklüğü- $ n $ şeytanın merdiveni üç bölüme ayrılmıştır

  • Sol özyinelemeli dalı, n-1uzunluğu bir merdiven büyüklüğü3**n - 2**n
  • Merkez çizgisi xuzunluğunun',3**n
  • Doğru özyinelemeli şube, büyüklüğü bir merdiven n-1, uzunluğu olan3**n - 2**n

Üç parçanın toplam uzunluğunun indüksiyonu onaylayan 3*(3**n) - 2*(2**n)ya da olduğuna dikkat edin 3**(n+1) - 2**(n+1).

İsteğe bağlı değişken s, yazdırmakta olduğumuz mevcut parçaların ofsetini saklar. Önce daha büyük bir ofsetle sol dalına geri döndük, daha sonra orta çizgiyi yazdırın, sonra sağ dalı geçerli ofsette yapalım.


6

CJam, 36 35 33 bayt

İşte bir başka CJam yaklaşımı (Optimizer’in koduna bakmadım, bu yüzden aslında çok farklı olup olmadığını bilmiyorum):

L0sl~{{3*0s}%0s\+}*{1$,S*\+}%W%N*

Bu 0, eğri için kullanır . Alternatif olarak, (grc's hilesi kullanılarak)

LLl~){3\#a1$++}/{1$,S*\'x*+}%W%N*

hangi kullanır x.

Burada test et.

açıklama

Temel fikir, ilk önce satırlar gibi bir dizi oluşturmaktır.

["0" "000" "0" "000000000" "0" "000" "0"]

Ve sonra bu listeyi gözden geçirmek için doğru miktarda boşluk hazırlamak.

L0sl~{{3*0s}%0s\+}*{1$,S*\+}%W%N*
L                                 "Push an empty string for later.";
 0s                               "Push the array containing '0. This is the base case.";
   l~                             "Read and evaluate input.";
     {           }*               "Repeat the block that many times.";
      {    }%                     "Map this block onto the array.";
       3*                         "Triple the current string.";
         0s                       "Push a new zero string.";
             0s\+                 "Prepend another zero string.";
                   {       }%     "Map this block onto the result.";
                    1$            "Copy the last line.";
                      ,S*         "Get its length and make a string with that many spaces.";
                         \+       "Prepend the spaces to the current row.";
                             W%   "Reverse the rows.";
                               N* "Join them with newlines.";

Diğer sürüm benzer şekilde çalışır, ancak

[1 3 1 9 1 3 1]

Ve sonra bunu xfinal haritasında s dizgisine çevirir .


6

Dyalog APL, 34 karakter

Yaklaşımın grc ile kullanılması. (Domino) karakterli merdivenleri çizer ve stdin'den girdi alır. Bu çözüm varsayılır ⎕IO←0.

' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
  • - stdin'den girdi alın.
  • ⌽⍳1+⎕- gelen sayı sırası 0 olarak aşağı (örneğin 3 2 1 0)
  • 3*⌽⍳1+⎕- bunun gücüne üç (örneğin 27 9 3 1)
  • (⊢,,)/3*⌽⍳1+⎕- önceki sonuç ⊢,,, grc'nin {⍵,⍺,⍵}yaklaşımına göre şeytanın merdivenlerinin adım uzunluklarını veren dfn'ye eşit olan tacit işlevi tarafından sağdan katlandı .
  • {⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕ adım uzunlukları adımlara dönüştürülür.
  • (∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕ Bu benim gibi J çözümümde . Sonucu doğru bir şekilde çeviren dikkat edin .
  • ' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕] sayılar boşlukları ve dominolarla değiştirilir.

4

Ruby, 99

FUZxxl’ın cevabından ilham alan başka bir cevap daha

FUZxxl, x sayısının, dizinin 2 faktörünün sayısına karşılık geldiğini belirtir. örneğin n = 2 için aşağıdaki faktörlendirmeye sahibiz:

1 =1
2 =1 * 2
3 =3
4 =1 * 2 * 2
5 =5
6 =3 * 2
7 =7

Bu 2 güçlerini çıkarmak için daha basit bir yol kullanıyorum: i=m&-mbu da sekansı 1 2 1 4 1 2 1vb . Verir . Bu şöyle çalışır:

m-1men önemli bitlerinde olduğu gibi aynıdır , ancak en az anlamlı 1'in biti sıfır olur ve sağdaki tüm sıfırlar 1 olur.

Orijinali ile VE edebilmek için, bitleri çevirmemiz gerekir. Bunu yapmanın çeşitli yolları vardır. Bir yol onu çıkarmaktır -1.

Genel formül o zaman m& (-1 -(m-1)) basitleştiren şeydir.m&(-m)

Örnek:

          100   01100100
100-1=     99   01100011
-1-99=   -100   10011100
100&-100=   4   00000100

İşte kod: yeni satırlar sayılır, girintiler gereksizdir ve bu nedenle diğer cevabım olarak sayılmaz. Taban 2: 1 2 1 4 1 2 1 etctaban 3: arasındaki sakar dönüşümden dolayı diğer cevabımdan biraz daha uzun : 1 3 1 9 1 3 1 etc(bundan kaçmanın bir yolu var Math::mı?)

def s(n)
  a=[]
  t=0
  1.upto(2*2**n-1){|m|i=3**Math::log(m&-m,2)
    a.unshift" "*t+"x"*i 
    t+=i}
  puts a
end

3

Ruby, 140 99

Şimdiye kadarki ikinci Ruby kodum ve dilimi ilk başta kullanmam. Öneriler çok açığız. Bayt sayısı, girintiler için baştaki boşlukları hariç tutar, ancak yeni satırlar içerir (yeni satırların çoğu, en azından bir boşlukla değiştirilmedikçe silinemez.)

Giriş işlev çağrısı ile yapılır. Çıktı, yakutun tek bir yeni satırla ayrılmış bir liste olarak stdout'a rahatça dökülen bir dizi dizisidir puts.

Algoritma basitçe new iteration= previous iteration+ extra row of n**3 x's+ previous iteration. Bununla birlikte, yalnızca çıktıdaki doğru boşlukları elde etmek için oldukça fazla miktarda kod vardır.

def s(n)
  a=["x"]
  1.upto(n){|m|t=" "*a[0].length
    a=a.map{|i|t+" "*3**m+i}+[t+"x"*3**m]+a}
  puts a
end

Düzenleme: Yakut, 97

Bu, dizide gerekli olan tüm x sayıları aiçin yukarıda açıklanan şekilde sayısal bir tablo oluşturma , ancak daha sonra bir dizi tablo oluşturma benzer ancak farklı bir yaklaşım kullanır . Dizeler tablosu , mevcut diziye hazırlanmak ciçin oldukça garip olarak adlandırılmış unshiftyöntem kullanılarak dizide geriye doğru oluşturulur .

Şu anda bu yaklaşım daha iyi görünüyor - ama sadece 2 byte :-)

def s(n)
  a=c=[]
  (n+1).times{|m|a=a+[3**m]+a}
  t=0
  a.each{|i|c.unshift" "*t+"x"*i
    t+=i}
  puts c
end

1
Sen yerini alabilir for m in(0..n-1)do ... endile n.times{|m|...}.
Omar

@Omar Teşekkürler, yarın deneyeceğim. Sürekli sözdizimi hataları nedeniyle, bunu çalıştırmak için ne kadar çaba harcadığına inanmazsınız. Yineleme değişkenine nasıl erişeceğimi bilmiyordum n.timesve bunu kesinlikle hatırlayacağım. Bir de ortadan kaldırır end! Ancak bu vesileyle for m in (1..n), önlemek için daha iyi olup olmadığını merak ediyordum (m+1). Bunu yazmanın daha kısa bir yolu var mı?
Seviye Nehri St

1
foruzun süredir kullanmaya zorlandığınızdan dolayı end(yenisiyle doveya ile değiştirebilirsiniz ;). İçin 1..nkullanabilirsiniz 1.upto(n){|m|...}. Görünümünü seviyorum (1..n).each{|i|...}ama kullanmaktan biraz daha uzun upto. Ve şunu söyleyerek yinelemenin eachya uptoda sadece daha kısa olmadığına dikkat edin, aynı zamanda daha aptal Ruby'yi de düşünün.
Omar

@ Teşekkürler tekrar, 1.upto(n)öyle! Bu ve birkaç gereksiz parantez gitti, ben zaten 120'ye düştüm. 100'ün altında mümkün olduğunu düşünüyorum, daha sonra revize edilmiş kodu göndereceğim.
Seviye Nehri St

3

Haskell, 99 karakter

d=q.((iterate((1:).(>>=(:[1]).(*3)))[1])!!)
q[]=[];q(a:r)=sum r&' '++a&'x'++'\n':q r
(&)=replicate

İşlev d:

λ: putStr $ d 3
                                                                x
                                                             xxx
                                                            x
                                                   xxxxxxxxx
                                                  x
                                               xxx
                                              x
                   xxxxxxxxxxxxxxxxxxxxxxxxxxx
                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

Bütün bu parantezler! Gerçekten daha az şeyle uğraşmanın bir yolu yok mu?
FUZxxl

Boş liste durumunda denklemleri değiştirerek qve yaparak bir bayt kaybedebilirsiniz q x=x. Ayrıca, etrafındaki parantezlerin iterate...[1]gereksiz olduğu görülüyor .
Zgarb

3

PHP - 137 bayt

function f($n){for($a=[];$i<=$n;array_push($a,3**$i++,...$a))$r=str_repeat;foreach($a as$v){$o=$r(' ',$s).$r(x,$v)."
$o";$s+=$v;}echo$o;}

Burada grc ile aynı numarayı kullanıyorum . İşte ungolfed versiyonu:

function staircase($n)
{
    $lengthsList = [];
    for ($i = 0; $i <= $n; ++$i) {
        array_push($lengthsList, 3 ** $i, ...$lengthsList);
    }

    $output = '';
    $cumulatedLength = 0;
    foreach ($lengthsList as $length)
    {
        $output = str_repeat(' ', $cumulatedLength) . str_repeat('x', $length) . "\n" . $output;
        $cumulatedLength += $length;
    }

    echo $output;
}

3**$i-> PHP 5.6 gibi geliyor. Bunu belirtmelisin. Bu hemen hemen her PHP kurulumuyla uyumlu değildir. Size bir kaç bayt kazandırmak $r=str_repeat;için bu fonksiyonla başlayacağınız yerle başlamalısınız ve yerine $r2 byte tasarruf sağlayabilirsiniz . Ayrıca $r('x',$v)olabilir $r(x,$v)ve iyi çalışacaktır (fonksiyon ismini değişkenle değiştirdiğime dikkat edin). Ayrıca, bunun size başka bir bayt kazandırdığı ++$i<=$nşeklinde yeniden yazılabileceğine inanıyorum $n>++$i.
Ismael Miguel

İşte işlevi biraz serin hile ile şöyledir: function f($n){$r=str_repeat;$a=[1];while($n>++$i)$a=array_merge($a,[3**$i],$a);foreach($a as$v){$o=$r(' ',$s).$r(x,$v)."\r$o";$s+=$v;}echo$o;}(yerine o çirkin yeni satır sahip, ben kaçış dizisi ekledim \rdeğişken ile, bir çift tırnaklar $o. İçindeki Böylece "\r$o"aynı bayt sayısına sahip ''.$obiri, newline ile sonuncusu ommited ve aynı sonucu verir
Ismael Miguel

Aslında, bu azaltma işleminin düzgün çalışması whileiçin olması şarttır $n>$i++.
Ismael Miguel

@IsmaelMiguel PHP 5.6, PHP'nin son sürümüdür, daha fazla bir şey söylemek zorunda değilim. Neredeyse herkes eski bir sürüm kullanıyorsa ve çoğunluğu eski bir sürüm kullanıyorsa bu benim suçum değil. Numara için teşekkürler $r=str_repeat. Sadece $r='str_repeat';bir bayttan tasarruf etmeyen, hakkında düşünüyordum . Tanımsız sabit aynı zamanda iyi bir hiledir;). Yeni satır, yazmadan daha küçük bir bayttır \n, bu yüzden kalmasını sağladım, ancak bir birleşimden kaçınmak için çift tırnak kullandım $0. Tekrar teşekkürler !
Blackhole

Sadece sana yakışacaktı. Farkında 3 ** $iolmasaydım, korkunç bir sözdizimine sahip olduğunuzu söylerdim. Bu düzeltmeyi ele alabilirsiniz. Ben sadece bu konuda söylüyorum [1]çünkü bu oldukça 'eski' olan PHP5.4'ten geldi. 1 yıl önce, bunu belirtmenizi rica ediyorum. Bugün sizden bunu belirten basitçe (çok kısa bir satırda) belirtmenizi istiyorum. Kod hakkında konuşursak, hala ++$i<=$nhangisinin yerine geçebileceğini sizde bulabilirsiniz $n>$i++. Test etmek için tüm kodunuzu PHP5.3'e dönüştürmek zorunda kaldım. Acı vericiydi. Ama görüyorum ki şu ana kadar 7 byte yedin.
Ismael Miguel

3

C, 165

#define W while
f(n){int i=n+1,j=1<<i,k=1,l,r,s,t;W(i--)k*=3;l=k-j;W(--j){r=j,s=1;W(!(r%2))r/=2,s*=3;l-=s;t=l;W(t--)putchar(32);W(++t<s)putchar(88);putchar('\n');}}

İşte aynı kodu paketlenmiş ve biraz temizlenmiş:

int f(int n) {
    int i=n+1, j=1<<i, k=1;
    while (i--) k*=3;
    int l=k-j;
    while (--j) {
        int r=j,s=1;
        while (!(r%2))
            r/=2, s*=3;
        l-=s;
        int t=l;
        while (t--) putchar(' ');
        while (++t<s) putchar('X');
        putchar('\n');
    }
}

Bu, FUZxxl'in soruna yönelik çözümüyle aynı fikir üzerine kuruludur, satırlar için açık biçimden ziyade açık bir şekilde kullanılır. J'nin bildirimi onu 2 ^ (n + 1) değerine ayarlar ve ilk sırada döngü k = 3 ^ (n + 1) değerini hesaplar; o zaman l = 3 ^ (n + 1) -2 ^ (n + 1) merdivenin toplam genişliğidir (bunu kanıtlamak zor değildir). Sonra 1'den 2'ye kadar olan r sayılarını gözden geçiririz ^ (n + 1) -1; her biri için, (tam olarak) 2 ^ n ile bölünebilirse, s = 3 ^ n 'X'in basılmasını planlıyoruz. Doğru noktadan başladığımızdan emin olmak için ayarlanır: l boşlukları ve s 'X'leri, sonra yeni bir satır yazarız.


W ile tanımlayın, süre ve bazı karakterleri kaydetmek için int ihmal edin.
FUZxxl

ayrıca bazı tasarruflar için t = l- = s.
FUZxxl

@FUZxxl İkisini de denedim ama C hala fonksiyonlarda örtük tiplere izin verirken, 'klasik' bayraklarla bile (en azından GCC'de) değişken bildirimlerde izin vermiyordu. Ben de tanımladım W; bu arada ve tanımına uymamış olmama rağmen bununla ilgilenmiyor gibi görünüyordu.
Steven Stadnicki

hm ... Sanırım türünü sadece global bir değişkende atlayabilirsin. Seni pek getirmedi. Ekleyebilir deneyebilirsiniz (*p)()=putchar;çağrısına başlangıçta putcharolduğu gibi p. Çalışması gerektiğini düşünüyorum.
FUZxxl

2

CJam, 46 43 41 39 36 35 bayt

L0ri),(a*+_W%(;+{3\#'x*+_,S*}%$1>N*

GÜNCELLEME şimdi farklı bir yaklaşım kullanarak.


Eski yaklaşım:

]ri){3f*_,)"x"a*\]z:+}*_s,f{1$,U+:U-S*\N}

Oldukça saf ve uzun, ama başlamak için bir şey.

Golf yaptıktan sonra açıklama ekleyeceğim.

Burada çevrimiçi deneyin


Biraz işe ihtiyacım var. N = 4, 5, 17 için düzgün çalışmamıştır. Görüntülenen sol biçimli x'in üstündeki x'lerin dizgilerini görüntüler. N = 17 ile ekrana kodu attı ve altını x'lerle doldurdu.
DavidC

1
@DavidCarraher 4, 5 Sanırım bu sadece çizgi kaplaması. Çıktıyı, satır sargısı olmayan bir metin düzenleyiciye kopyalarsanız bana tamam görünüyor.
Sp3000

Tamam. Biliyorum.
DavidC

2

Java, 271 269 ​​bayt

Grc metodunu kullanır.

import java.util.*;String a(int a){List<Integer>b=new ArrayList<>();int c=-1,d=1;for(;c++<a;b.add(d),b.addAll(b),b.remove(b.size()-1),d*=3);String f="";for(;b.size()>0;f+="\n"){d=b.remove(b.size()-1);for(int g:b)for(c=0;c<g;c++)f+=' ';for(c=0;c<d;c++)f+='x';}return f;}

Girintili'ye:

import java.util.*;
String a(int a){
    List<Integer>b=new ArrayList<>();
    int c=-1,d=1;
    for(;c++<a;b.add(d),b.addAll(b),b.remove(b.size()-1),d*=3);
    String f="";
    for(;b.size()>0;f+="\n"){
        d=b.remove(b.size()-1);
        for(int g:b)
            for(c=0;c<g;c++)
                f+=' ';
        for(c=0;c<d;c++)
            f+='x';
    }
    return f;
}

Herhangi bir öneriniz açıktır.

Mbomb007 sayesinde 2 bayt


Sen kullanabilirsiniz b.size()>0yerine !b.isEmpty()2 bayt tasarruf.
mbomb007

1

Perl, 62

#!perl -p
eval's/x+/$&$&$&
x/g,s/\d*/x
/;'x++$_;s/x+/$"x$'=~y!x!!.$&/ge

İlk önce sonucu, baştaki boşluklar olmadan tekrarlayarak hesaplar. Sonra bunları her satırın xönüne, dizenin geri kalanındaki karakter sayısına göre ekler .


1

JavaScript (ES6) 104 106 118

Düzenleme Özyinelemeli işlevi kaldırıldı, her satır için '*' listesi yinelemeli olarak elde edilir, 3 bit ve güçlerle
uğraşır (diğer birçok cevabında olduğu gibi) Her satıra eklenecek satır aralığı

F=n=>{
  for(i=a=s='';++i<2<<n;a=s+'*'.repeat(t)+'\n'+a,s+=' '.repeat(t))
    for(t=u=1;~i&u;u*=2)t*=3;
  return a
}

İlk önce kaldırıldı

Özyinelemeli R işlevi her satır için '*' sayısı olan bir dizi oluşturur. Örneğin, R (2) [1, 3, 1, 9, 1, 3, 1]
Bu dizi, her satıra eklenecek önde gelen boşluk sayısını tutarak, çok satırlı bir dize oluşturmak üzere taranır.

F=n=>
(R=n=>[1].concat(...n?R(n-1).map(n=>[n*3,1]):[]))(n)
.map(n=>a=' '.repeat(s,s-=-n)+'*'.repeat(n)+'\n'+a,a=s='')
&&a 

Firefox / FireBug konsolunda test edin

F(3)

Çıktı

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

1

R - 111 karakter

Basit uygulama, diziyi yinelemeli oluşturma ve yavaşça tahrip etme.

n=scan()
a=1
if(n)for(x in 1:n)a=c(a,3^x,a)
for(A in a){cat(rep(' ',sum(a)-A),rep('x',A),'\n',sep='');a=a[-1]}

Kullanımı:

> source('devil.r')
1: 2
2: 
Read 1 item
                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

İyi nokta, kodumu değiştirdiğim niçin komut satırındaki argümanı alır
koekenbakker

1
STDIN'den okuyarak 8 bayttan tasarruf edersiniz. n=scan().
Alex A.

xİmleç olarak kullanmak için beyanda bulunmak zorunda değilsiniz , ne de ihtiyacınız yok if(n). Ayrıca, satır sonları bence bir karakter olarak sayılır.
freekvd

Sağol, haklısın x. if(n)Ancak emin değilim . Dava ile başa çıkmak için o kısmı ekledim n=0. if(n)Daha sonra geri döner Fve o nedenle yalınkat bir döner x. Bunu kaldırırsanız, n=0istenmeyen sonuçlar vermektedir. Yeni burada, bu yüzden satır sonları hakkında bilmiyordum. Şimdi dahil!
koekenbakker 19'15

a=0Döngüyü ayarlarsanız ve başlatırsanız, x in 0:nn = 0 için de çalışır. O zaman ihmal edebilirsiniz if(n).
freekvd

0

Ruby, 93

f=->n{s,p,k=[1],1;n.times{s=s+[p=p*3]+s};k=s.dup;k.each{m=s.pop;puts' '*s.reduce(0,:+)+?x*m}}

Bu, grc ile aynı yaklaşımı kullanır.

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.