Vẽ cầu thang của quỷ


46

Các Quỷ Cầu thang là một fractal giống như chức năng liên quan đến các thiết lập Cantor.

nhập mô tả hình ảnh ở đây

Nhiệm vụ của bạn là tái tạo chức năng thú vị này - trong nghệ thuật ASCII!

Đầu vào

Một số nguyên duy nhất n >= 0, cho biết kích thước của đầu ra. Đầu vào có thể được cung cấp thông qua STDIN, đối số chức năng hoặc đối số dòng lệnh.

Đầu ra

Phiên bản nghệ thuật ASCII của cầu thang Quỷ có kích thước n, được trả lại dưới dạng chuỗi hoặc được in thành STDOUT. Không gian lưu trữ ở cuối mỗi hàng là được, nhưng không gian hàng đầu thì không. Bạn có thể tùy ý in một dòng mới duy nhất.

Đối với kích thước 0, đầu ra chỉ là:

x

(Nếu bạn muốn, bạn có thể sử dụng bất kỳ ký tự ASCII có thể in nào khác ngoài không gian, thay cho x.)

Về kích thước n > 0, chúng tôi:

  • Lấy đầu ra của kích thước n-1và kéo dài mỗi hàng theo hệ số ba
  • Vơ vét giữa hàng đơn xs
  • Chuyển các hàng sang phải sao cho có chính xác một hàng xtrong mỗi cột và vị trí của hàng đầu tiên xlà tối thiểu trong khi giảm dần với các hàng

Ví dụ: đầu ra cho n = 1là:

    x
 xxx
x

Để có được đầu ra cho n = 2, chúng tôi kéo dài mỗi hàng theo hệ số ba:

            xxx
   xxxxxxxxx
xxx

Riffle giữa các hàng của đơn x:

x
            xxx
x
   xxxxxxxxx
x
xxx
x

Chuyển sang phải:

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

Một ví dụ khác, đâyn = 3.

Chấm điểm

Đây là môn đánh gôn, vì vậy giải pháp trong vài byte nhất sẽ thắng.

Câu trả lời:


7

Bình thường, 30

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

Đây là chương trình lấy đầu vào từ STDIN và sử dụng phương pháp tìm bộ Cantor của grc. Sử dụng "ký tự để hiển thị đường cong.

Hãy thử trực tuyến tại đây.

Giải trình:

Tôi sẽ giải thích mã trong hai phần, đầu tiên, thế hệ tập hợp cantor:

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)

Và định dạng đầu ra:

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 * '"'

Lưu ý rằng trong pyth N = '"' theo mặc định.


32

J ( 73 68 58 41 39 38 35 34 ký tự)

Sau khi suy nghĩ về vấn đề này một thời gian, tôi tìm thấy một cách hoàn toàn khác để tạo ra mẫu Cầu thang của quỷ. Câu trả lời cũ bao gồm cả lời giải thích của nó đã bị xóa, bạn có thể xem xét các sửa đổi của câu trả lời này để tìm ra nó như thế nào.

Câu trả lời này trả về một loạt các khoảng trống và vật sắc nhọn, đại diện cho cầu thang của quỷ.

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

Đây là câu trả lời được chia thành hai phần của nó trong ký hiệu rõ ràng:

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

Giải trình

Cách tiếp cận hơi khác một chút, vì vậy hãy quan sát và ngạc nhiên.

  1. >: 3 - tăng ba, nghĩa là,

    4
    
  2. 2 ^ >: 3 - hai đến sức mạnh của ba tăng, nghĩa là,

    16
    
  3. i. 2 ^ >: 3- 2 ^ >: 3số nguyên đầu tiên , nghĩa là,

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    
  4. }. i. 2 ^ 4- 2 ^ >: 3số nguyên đầu tiên , chặt đầu, nghĩa là

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

    Hãy gọi trình tự này s; chúng tôi nhập fngay bây giờ

  5. 1 q: s- số mũ của 2 trong phân tách nguyên tố của từng vật phẩm của s. Nói chung, x q: ymang lại một bảng các số mũ cho các xsố nguyên tố đầu tiên trong phân rã chính của y. Sản lượng này:

    0
    1
    0
    2
    0
    1
    0
    3
    0
    1
    0
    2
    0
    1
    0
    
  6. 3 ^ 1 q: s - ba đến sức mạnh của các số mũ này, nghĩa là,

     1
     3
     1
     9
     1
     3
     1
    27
     1
     3
     1
     9
     1
     3
     1
    
  7. , 3 ^ 1 q: s- ravel (có nghĩa là, đối số với cấu trúc của nó được thu gọn thành một vectơ) của kết quả trước đó. Điều này là cần thiết bởi vì q:giới thiệu một trục kéo không mong muốn. Sản lượng này

     1 3 1 9 1 3 1 27 1 3 1 9 1 3 1
    
  8. (, 3 ^ 1 q: s) # s- mỗi mục được ssao chép thường xuyên như mục tương ứng trong kết quả trước đó, nghĩa là

    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 - tự phân loại kết quả trước đó, đây là một ma trận trong đó mỗi hàng đại diện cho một trong các mục duy nhất của đối số, mỗi cột biểu thị mục tương ứng của đối số và mỗi ô biểu thị xem các mục của hàng và cột có bằng nhau không, đó là,

    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 - kết quả trước đó được lật dọc theo trục dọc.

  11. (|. = (, 3 ^ 1 q: s) # s) { ' #'- các mục của kết quả trước đó được sử dụng làm chỉ mục vào mảng ' #', do đó 0được thay thế bởi  1được thay thế bởi #, đó là,

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

    kết quả mà chúng ta muốn


Bên trong vòng nguồn (,],~3^#@~.)@]thay vì (1,[:,1,"0~3*]) tiết kiệm 1 byte. Và nếu bạn ổn với !vai trò đầu ra u:32+thay vì ' #'{~lưu một cái khác.
Randomra

#\ thay vì i.@#và bạn đã vượt qua APL! :)
Randomra

Giải pháp thứ hai của bạn không hoạt động vì sẽ cần một nắp, nhưng tôi đã tìm một cách khác để đánh bại APL.
FUZxxl

Đầu ra mới là cầu thang cho n-1không n.
Randomra

@randomra Ah, đó là shitty. Hãy để tôi xem nếu nó có thể sửa chữa.
FUZxxl

26

Lục giác , 217 byte

Điều này là vô cùng thú vị. Cảm ơn bạn đã đăng thử thách này.

Tiết lộ đầy đủ: Ngôn ngữ (Hexagony) không tồn tại tại thời điểm thử thách này được đăng. Tuy nhiên, tôi đã không phát minh ra nó và ngôn ngữ không được thiết kế cho thử thách này (hoặc bất kỳ thử thách cụ thể nào khác).

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

Đặt ra hình lục giác:

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

Chương trình không thực sự sử dụng #hướng dẫn, vì vậy tôi đã sử dụng ký tự đó để hiển thị các ô nào thực sự không được sử dụng.

Chương trình này hoạt động như thế nào? Mà phụ thuộc. Bạn muốn phiên bản ngắn, hay dài?

Giải thích ngắn

Để minh họa những gì tôi muốn nói về dòng sản phẩm và dòng phân khúc của Google trong phần giải thích sau đây, hãy xem xét cách phân tích đầu ra dự định này:

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

Với giải thích đó, chương trình tương ứng với mã giả sau:

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

Giải thích dài

Vui lòng tham khảo sơ đồ đường dẫn mã màu này.

Đường dẫn thực thi

Thực hiện bắt đầu ở góc trên cùng bên trái. Chuỗi các hướng dẫn ){2'"''3''"2}?)được thực hiện (cộng với một vài lần hủy dự phòng, như "{v.v.) bằng cách theo đuổi một đường dẫn khá phức tạp. Chúng tôi bắt đầu với Con trỏ lệnh # 0, được tô sáng màu đỏ thẫm. Nửa chừng, chúng tôi chuyển sang số 1, bắt đầu ở góc trên bên phải và sơn màu xanh lá cây. Khi IP # 2 bắt đầu có màu xanh hoa ngô (giữa bên phải), bố cục bộ nhớ là:

Bố cục bộ nhớ

Trong toàn bộ chương trình, các cạnh có nhãn 2a2b sẽ luôn có giá trị 2(chúng tôi sử dụng chúng để tính 2ⁿ⁺¹ và chia cho 2, tương ứng) và cạnh có nhãn 3 sẽ luôn luôn 3(chúng tôi sử dụng giá trị đó để tính 3ⁱ).

Chúng tôi có được doanh nghiệp khi chúng tôi bước vào vòng lặp đầu tiên của chúng tôi, nổi bật với màu xanh hoa ngô. Vòng lặp này thực hiện các hướng dẫn (}*{=&}{=để tính giá trị 2ⁿ⁺¹. Khi vòng lặp thoát ra, đường dẫn màu nâu yên được thực hiện, đưa chúng ta đến Con trỏ lệnh # 3. IP này chỉ đơn thuần là chạy dọc theo cạnh dưới về phía tây về màu vàng Goldenrod và sớm chuyển quyền kiểm soát sang IP # 4.

Đường dẫn fuchsia cho biết có bao IP # 4, bắt đầu từ phía dưới bên trái, tiến hành nhanh chóng để sụt dòng , bộ ch để 32(nhân vật không gian) và seg đến (giá trị mới của) dòng . Đó là do sự sụt giảm sớm mà chúng ta thực sự bắt đầu với 2ⁿ⁺¹ 1 và cuối cùng trải qua lần lặp cuối cùng với giá trị 0. Sau đó chúng ta vào vòng lặp lồng đầu tiên .

Chúng tôi chuyển sự chú ý của chúng tôi sang màu chàm phân nhánh, trong đó, sau một thời gian giảm dần của seg , chúng tôi thấy ch được cập nhật xchỉ khi seg bây giờ bằng không. Sau đó, n được đặt thành dòng - seg để xác định số lượng thực tế của phân khúc chúng tôi đang ở. Ngay lập tức chúng tôi nhập một vòng lặp khác, lần này là màu cà chua công bằng.

Ở đây, chúng tôi tính xem có thể chia bao nhiêu lần n (số phân khúc hiện tại) cho 2. Miễn là modulo cho chúng tôi bằng 0, chúng tôi tăng i và chia n cho 2. Khi chúng tôi hài lòng thì n không còn chia hết , chúng tôi phân nhánh thành màu xám đá phiến, chứa hai vòng: đầu tiên, nó tăng 3 đến sức mạnh của i mà chúng tôi đã tính toán, và sau đó nó tạo ra ch nhiều lần. Quan sát rằng các vòng lặp đầu tiên chứa một[hướng dẫn chuyển đổi điều khiển sang IP # 3 - hướng dẫn chỉ thực hiện các bước bé dọc theo cạnh dưới trước đó. Phần thân của vòng lặp (nhân với 3 và giảm dần) được thực thi bởi một IP # 3 cô đơn, bị giam cầm trong một chu kỳ màu xanh ô liu vô tận dọc theo cạnh dưới của mã. Tương tự, phần thứ hai của các vòng màu xám đá phiến này chứa một ]lệnh, kích hoạt IP # 5 để xuất ch và giảm, được hiển thị ở đây bằng màu đỏ Ấn Độ. Trong cả hai trường hợp, những Con trỏ Hướng dẫn bị mắc kẹt trong sự phục vụ đều ngoan ngoãn thực hiện một lần lặp lại tại một thời điểm và điều khiển năng suất trở lại IP # 4, chỉ để chờ đợi thời điểm dịch vụ của chúng được gọi lại một lần nữa. Màu xám, trong khi đó, tham gia lại anh em fuchsia và chàm của nó.

Như seg chắc chắn đạt đến số không, các lối ra vòng lặp chàm vào con đường màu xanh lá cây cỏ, mà chỉ đơn thuần là kết quả đầu ra kí tự xuống dòng và kịp thời kết hợp trở lại vào cây khoa vản anh để tiếp tục dòng vòng lặp. Ngoài vòng lặp cuối cùng của vòng lặp dòng là con đường ebon ngắn có thể kết thúc chương trình cuối cùng.


8
Bây giờ đây chỉ là sự điên rồ kiểu cũ.
FUZxxl

21

Con trăn 2, 78

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

Bắt đầu với danh sách L=[1], chúng tôi nhân đôi nó và chèn sức mạnh tiếp theo của 3 vào giữa, kết quả là [1, 3, 1]. Điều này được lặp đi lặp lại nhiều nlần để cho chúng ta độ dài hàng cho cầu thang của Quỷ. Sau đó, chúng tôi in mỗi hàng đệm với không gian.


20

APL, 38

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

Thí dụ:

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

Giải trình:

⊖↑'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 

Đó là một giải pháp tốt.
FUZxxl

20
Tôi thích cách giải thích về mật mã trông giống như Cầu thang của Quỷ dữ.
Alex A.

Tôi tìm thấy một giải pháp APL thậm chí còn ngắn hơn.
FUZxxl

14

GNU sed, 142

Không phải là câu trả lời ngắn nhất, nhưng nó là 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

Vì đây là sed (không có số học bản địa), nên tôi có quyền tự do với quy tắc "Một số nguyên duy nhất n> = 0, cho biết kích thước của đầu ra" . Trong trường hợp này, số nguyên đầu vào phải là một chuỗi 1s, có độ dài là n. Tôi nghĩ rằng đây là "chỉ ra" kích thước của đầu ra, mặc dù nó không phải là số trực tiếp tương đương với n. Do đó với n = 2, chuỗi đầu vào sẽ là 11:

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

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

Điều này dường như hoàn thành với độ phức tạp theo thời gian theo cấp số nhân của O (c n ), trong đó c khoảng 17. n = 8 mất khoảng 45 phút cho tôi.


Ngoài ra, nếu n được yêu cầu nhập chính xác bằng số, thì chúng ta có thể làm điều này:

sed, 274 byte

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

Đầu ra:

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

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

7
Điều này thực sự mát mẻ.
FUZxxl

8

Con trăn 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

Phiên bản chương trình (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)

Số lượng x trong nhàng được lập chỉ mục thứ 1 là 3 với sức mạnh của (chỉ số của bit được đặt đầu tiên trong n, bắt đầu từ lsb).


8

Con trăn 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)

Một cách tiếp cận đệ quy. Cầu thang có kích thước- $ n $ devil được chia thành ba phần

  • Nhánh đệ quy bên trái, một cầu thang có kích thước n-1, có chiều dài là3**n - 2**n
  • Đường trung tâm của x', có độ dài3**n
  • Nhánh đệ quy bên phải, một cầu thang có kích thước n-1, có chiều dài là3**n - 2**n

Lưu ý rằng tổng chiều dài của ba phần là 3*(3**n) - 2*(2**n)hoặc 3**(n+1) - 2**(n+1), xác nhận cảm ứng.

Biến tùy chọn slưu trữ phần bù của các phần hiện tại chúng tôi đang in. Đầu tiên chúng ta lặp lại xuống nhánh bên trái với phần bù lớn hơn, sau đó in đường trung tâm, sau đó thực hiện nhánh bên phải ở phần bù hiện tại.


6

CJam, 36 35 33 byte

Đây là một cách tiếp cận khác của CJam (Tôi chưa xem mã của Trình tối ưu hóa, vì vậy tôi không biết liệu nó có thực sự khác biệt nhiều không):

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

Điều này sử dụng 0cho các đường cong. Ngoài ra, (sử dụng thủ thuật của grc)

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

trong đó sử dụng x.

Kiểm tra nó ở đây.

Giải trình

Ý tưởng cơ bản là đầu tiên tạo thành một mảng với các hàng, như

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

Và sau đó để đi qua danh sách này, chuẩn bị đúng số lượng không gian.

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.";

Phiên bản khác hoạt động tương tự, nhưng tạo ra một loạt các độ dài, như

[1 3 1 9 1 3 1]

Và sau đó biến nó thành chuỗi xs trong bản đồ cuối cùng.


6

APL Dyalog, 34 ký tự

Sử dụng cách tiếp cận của grc. Vẽ cầu thang với các ký tự (domino) và lấy đầu vào từ stdin. Giải pháp này giả định ⎕IO←0.

' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
  • - lấy đầu vào từ stdin.
  • ⌽⍳1+⎕- dãy số từ xuống đến 0. (ví dụ 3 2 1 0)
  • 3*⌽⍳1+⎕- ba đến sức mạnh của điều đó (ví dụ 27 9 3 1)
  • (⊢,,)/3*⌽⍳1+⎕- kết quả trước đó được gấp lại từ bên phải bởi hàm ngầm ⊢,,tương đương với dfn {⍵,⍺,⍵}mang lại độ dài bước của cầu thang của quỷ theo cách tiếp cận của grc.
  • {⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕ độ dài bước chuyển đổi thành các bước.
  • (∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕mà tự phân loại, như trong giải pháp J của tôi . Lưu ý rằng đã lật kết quả chính xác.
  • ' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕] các số được thay thế bằng khoảng trống và domino.

4

Hồng ngọc, 99

Một câu trả lời khác cho câu hỏi khác của tôi, lấy cảm hứng từ câu trả lời của FUZxxl

FUZxxl lưu ý rằng số của x tương ứng với số lượng các yếu tố của 2 chỉ số. ví dụ với n = 2, chúng ta có hệ số hóa sau:

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

Tôi sử dụng một cách khá đơn giản hơn để trích xuất các lũy thừa 2: i=m&-mmang lại chuỗi, 1 2 1 4 1 2 1v.v ... Điều này hoạt động như sau:

m-1giống như mtrong các bit có ý nghĩa nhất của nó, nhưng bit 1 có ý nghĩa nhỏ nhất trở thành số 0 và tất cả các số 0 ở bên phải đều trở thành 1.

Để có thể VÀ cái này với bản gốc, chúng ta cần lật các bit. Có nhiều cách khác nhau để làm điều này. Một cách là trừ nó ra -1.

Công thức tổng thể sau m& (-1 -(m-1)) đó đơn giản hóa thànhm&(-m)

Thí dụ:

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

Đây là mã: dòng mới được tính, thụt lề là không cần thiết và do đó không được tính, như câu trả lời khác của tôi. Nó hơi dài hơn câu trả lời khác của tôi do sự chuyển đổi vụng về từ cơ sở 2: 1 2 1 4 1 2 1 etcsang cơ sở 3: 1 3 1 9 1 3 1 etc(có cách nào để tránh điều đó Math::không?)

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

Mã Ruby thứ hai của tôi và sử dụng ngôn ngữ không đầu tiên của tôi. Gợi ý được chào đón nhất. Số lượng byte không bao gồm các khoảng trắng hàng đầu cho các điểm thụt lề, nhưng bao gồm các dòng mới (dường như hầu hết các dòng mới không thể bị xóa trừ khi chúng được thay thế bằng một khoảng trắng ít nhất.)

Đầu vào là bằng chức năng gọi. Đầu ra là một chuỗi các chuỗi, mà ruby ​​thuận tiện chuyển sang thiết bị xuất chuẩn dưới dạng một danh sách được phân tách bằng dòng mới với một danh sách puts.

Thuật toán chỉ đơn giản là new iteration= previous iteration+ extra row of n**3 x's+ previous iteration. Tuy nhiên, có rất nhiềuhợp lý chỉ để có được các khoảng trắng hàng đầu trong đầu ra.

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

Chỉnh sửa: Ruby, 97

Điều này sử dụng cách tiếp cận tương tự nhưng khác nhau của việc xây dựng một bảng số gồm tất cả các số x được yêu cầu trong mảng atheo cách được mô tả ở trên, nhưng sau đó xây dựng một chuỗi các chuỗi sau đó. Bảng chuỗi được xây dựng ngược trong mảng cbằng cách sử dụng unshiftphương thức được đặt tên khá kỳ lạ để thêm vào mảng hiện có.

Hiện tại phương pháp này có vẻ tốt hơn - nhưng chỉ bằng 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
Bạn có thể thay thế for m in(0..n-1)do ... endbằng n.times{|m|...}.
Omar

@Omar Cảm ơn, tôi sẽ thử vào ngày mai. Bạn sẽ không tin phải mất bao nhiêu nỗ lực để chạy nó, do các lỗi cú pháp liên tục. Tôi không biết làm thế nào để truy cập vào biến lặp n.timesvà tôi chắc chắn sẽ nhớ điều đó. Nó loại bỏ endquá! Tuy nhiên trong dịp này tôi đã tự hỏi nếu for m in (1..n)có thể tốt hơn, để tránh (m+1). Có cách viết ngắn hơn không?
Cấp sông St

1
fordài chủ yếu là do bạn buộc phải sử dụng end(bạn có thể thay thế dobằng một dòng mới hoặc bằng ;). Để 1..nbạn có thể sử dụng 1.upto(n){|m|...}. Tôi thích vẻ ngoài của (1..n).each{|i|...}nó nhưng nó hơi dài hơn so với sử dụng upto. Và lưu ý rằng việc lặp lại bằng cách gọi eachhoặc uptokhông chỉ ngắn hơn, nó cũng xem xét Ruby thành ngữ hơn.
Omar

@ Cảm ơn một lần nữa, 1.upto(n)nó là! Với điều đó và một vài dấu ngoặc không cần thiết đã biến mất, tôi đã giảm xuống còn 120. Tôi nghĩ rằng dưới 100 là có thể, tôi sẽ đăng mã sửa đổi sau.
Cấp sông St

3

Haskell, 99 ký tự

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

Chức năng là d:

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

Tất cả những dấu ngoặc đơn này! Có thực sự không có cách nào để có được xung quanh với ít hơn?
FUZxxl

Bạn có thể mất một byte bằng cách hoán đổi các phương trình qvà thực hiện q x=xtrong trường hợp danh sách trống. Ngoài ra, dường như các dấu ngoặc đơn xung quanh iterate...[1]là không cần thiết.
Zgarb

3

PHP - 137 byte

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;}

Tôi đang sử dụng ở đây thủ thuật tương tự như grc . Đây là phiên bản chưa được chỉnh sửa:

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-> cảm thấy như PHP 5.6. Bạn nên chỉ định nó. Điều này không tương thích với hầu hết mọi cài đặt của PHP. Để tiết kiệm cho bạn một vài byte, bạn nên bắt đầu với $r=str_repeat;và nơi bạn có chức năng đó, bạn có thể thay thế bằng $r, tiết kiệm cho bạn 2 byte. Ngoài ra, $r('x',$v)có thể $r(x,$v)và nó sẽ hoạt động tốt (lưu ý rằng tôi đã thay thế tên hàm bằng biến). Ngoài ra, tôi tin rằng ++$i<=$ncó thể được viết lại như $n>++$itiết kiệm cho bạn một byte khác.
Ismael Miguel

Đây là chức năng của bạn, với một mẹo nhỏ thú vị: 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;}(thay vì có dòng mới xấu xí đó, tôi đã thêm chuỗi thoát \rbên trong một chuỗi trích dẫn kép, với biến $obên trong nó. Do đó, "\r$o"có cùng số byte như ''.$omột, với dòng mới được giới thiệu ở cái cuối cùng và tạo ra kết quả tương tự.
Ismael Miguel

Trên thực tế, điều kiện của whilephải là $n>$i++để giảm này để hoạt động đúng.
Ismael Miguel

@IsmaelMiguel PHP 5.6 là phiên bản cuối cùng của PHP, tôi không phải nói gì thêm. Đó không phải là lỗi của tôi nếu hầu hết mọi người đang sử dụng một phiên bản cũ và nếu phần lớn đang sử dụng một phiên bản lỗi thời. Cảm ơn vì $r=str_repeatmánh khóe. Tôi chỉ nghĩ về việc $r='str_repeat';không lưu bất kỳ byte nào. Hằng số không xác định cũng là một mẹo hay, cũng được thực hiện;). Một dòng mới nhỏ hơn một byte so với viết \n, vì vậy tôi đã giữ nó, nhưng tôi đã sử dụng dấu ngoặc kép để tránh ghép nối với $0. Cảm ơn một lần nữa!
Hố đen

Nó sẽ chỉ nhìn tốt về bạn. Nếu tôi không nhận thức được thì 3 ** $itôi sẽ nói rằng bạn có một cú pháp khủng khiếp. Bạn có thể giải quyết sự điều chỉnh đó. Tôi chỉ nói về cái này chứ không phải [1]vì nó xuất phát từ PHP5.4, cái này khá 'cũ'. 1 năm trước, tôi sẽ yêu cầu bạn chỉ định điều đó. Hôm nay, tôi yêu cầu bạn chỉ định đơn giản (trong một dòng rất ngắn) chỉ định điều này. Nói về mã, bạn vẫn có ++$i<=$ncái có thể được thay thế bằng $n>$i++. Tôi đã phải chuyển đổi tất cả mã của bạn thành PHP5.3 để kiểm tra nó. Mà đã đau. Nhưng tôi thấy bạn đã ăn 7 byte cho đến nay.
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');}}

Đây là cùng một mã được giải nén và làm sạch một chút:

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');
    }
}

Điều này dựa trên cùng một ý tưởng như giải pháp của FUZxxl cho vấn đề này, về việc sử dụng một hình thức rõ ràng thay vì ẩn cho các hàng. Khai báo của j đặt nó thành 2 ^ (n + 1) và vòng lặp while đầu tiên tính k = 3 ^ (n + 1); thì l = 3 ^ (n + 1) -2 ^ (n + 1) là tổng chiều rộng của cầu thang (điều này không quá khó để chứng minh). Sau đó chúng ta đi qua tất cả các số r từ 1 đến 2 ^ (n + 1) -1; đối với mỗi người, nếu nó chia hết cho (chính xác) 2 ^ n thì chúng tôi dự định in s = 3 ^ n 'X's. Tôi được điều chỉnh để đảm bảo chúng tôi bắt đầu từ vị trí phù hợp: chúng tôi viết l khoảng trắng và s 'X, sau đó là một dòng mới.


định nghĩa W đến; while và bỏ qua int để lưu một số ký tự.
FUZxxl 24/2/2015

cũng t = l- = s cho một số tiết kiệm.
FUZxxl 24/2/2015

@FUZxxl Tôi đã thử cả hai thứ đó, nhưng trong khi C vẫn cho phép các kiểu ẩn trên các hàm thì nó không cho phép chúng khai báo biến ngay cả với các cờ 'cổ điển' (ít nhất là trên GCC). Và tôi đã thử #define W; trong khi và nó dường như không quan tâm đến nó, mặc dù tôi có thể đã trượt trong định nghĩa.
Steven Stadnicki

hm ... tôi nghĩ bạn chỉ có thể bỏ qua loại trong một biến toàn cục. Nó không mang lại cho bạn rất nhiều. Bạn có thể thử thêm (*p)()=putchar;vào lúc đầu để gọi putcharp. Tôi nghĩ rằng nó sẽ làm việc.
FUZxxl

2

CJam, 46 43 41 39 36 35 byte

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

CẬP NHẬT bằng cách sử dụng một cách tiếp cận khác nhau bây giờ.


Cách tiếp cận cũ:

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

Khá ngây thơ và dài, nhưng một cái gì đó để bắt đầu.

Sẽ thêm lời giải thích một khi tôi chơi nó.

Dùng thử trực tuyến tại đây


Có vẻ cần một số công việc. Không hoạt động đúng cho n = 4, 5, 17. Hiển thị các chuỗi riffles được định dạng bên trái của x 'ở phần trên. Với n = 17, nó đổ mã vào màn hình và điền vào đáy với x's.
DavidC

1
@DavidCarraher Cho 4, 5 Tôi nghĩ đó chỉ là gói hàng. Nếu bạn sao chép đầu ra vào một trình soạn thảo văn bản mà không có dòng nào thì nó có vẻ ổn đối với tôi.
Sp3000

Đồng ý. Tôi biết xem.
DavidC

2

Java, 271 269 ​​byte

Sử dụng phương pháp của grc.

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;}

Thụt lề:

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;
}

Mọi góp ý đều được chào đón.

2 byte nhờ mbomb007


Bạn có thể sử dụng b.size()>0thay vì !b.isEmpty(), tiết kiệm 2 byte.
mbomb007

1

Perl, 62

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

Đầu tiên tính toán kết quả lặp mà không có khoảng trắng hàng đầu. Sau đó thêm chúng trước mỗi dòng theo số lượng xký tự trong phần còn lại của chuỗi.


1

JavaScript (ES6) 104 106 118

Chỉnh sửa Đã xóa hàm đệ quy, danh sách '*' cho mỗi dòng được lặp đi lặp lại, thay đổi theo bit và
lũy thừa 3 (như trong nhiều câu trả lời khác) Bên trong vòng lặp, một chuỗi nhiều dòng được đặt từ dưới lên, giữ số đếm chạy không gian hàng đầu để thêm vào mỗi dòng

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
}

Trước tiên hãy thử loại bỏ

Hàm R đệ quy xây dựng một mảng với số '*' cho mỗi dòng. Ví dụ R (2) là [1, 3, 1, 9, 1, 3, 1]
mảng này được quét để xây dựng một chuỗi nhiều dòng từ dưới lên, giữ một số lượng không gian hàng đầu đang chạy để thêm vào mỗi dòng

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 

Kiểm tra trong bảng điều khiển Firefox / FireBug

F(3)

Đầu ra

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

1

R - 111 ký tự

Thực hiện đơn giản, xây dựng các mảng lặp và phá hủy nó từ từ.

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]}

Sử dụng:

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

Điểm hay, đã sửa đổi mã của tôi để nó lấy nđối số từ dòng lệnh
koekenbakker

1
Bạn lưu 8 byte bằng cách đọc từ STDIN. n=scan().
Alex A.

Bạn không cần phải khai báo xđể sử dụng nó như một con trỏ, cũng không cần if(n). Ngoài ra, ngắt dòng được tính là một nhân vật tôi nghĩ.
freekvd

Cảm ơn, bạn đã đúng x. Không chắc chắn về if(n)tuy nhiên. Tôi đã thêm phần đó để giải quyết vụ việc n=0. Sau if(n)đó trả về Fvà do đó trả về một x. Nếu tôi loại bỏ nó, n=0cho kết quả không mong muốn. Mới ở đây, vì vậy không biết về ngắt dòng. Bao gồm ngay bây giờ!
koekenbakker

Nếu bạn đặt a=0và bắt đầu vòng lặp, x in 0:nnó cũng hoạt động với n = 0. Sau đó, bạn có thể bỏ qua if(n).
freekvd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.