악마의 계단 그리기


46

악마의 계단 프랙탈-같은 칸토어 집합에 관련된 기능입니다.

여기에 이미지 설명을 입력하십시오

당신의 임무는 ASCII 기술에서이 펑키 한 기능을 복제하는 것입니다!

입력

n >= 0출력의 크기를 나타내는 단일 정수 STDIN, 함수 인수 또는 명령 행 인수를 통해 입력 할 수 있습니다.

산출

size에서 악마 계단의 ASCII 예술 표현 n으로, 문자열로 반환되거나 STDOUT에 인쇄됩니다. 각 행의 끝에있는 공백은 괜찮지 만 선행 공백은 아닙니다. 선택적으로 단일 후행 줄 바꿈을 인쇄 할 수 있습니다.

size 0의 경우 출력은 다음과 같습니다.

x

(원하는 경우 공백 대신 다른 인쇄 가능한 ASCII 문자를 사용할 수 있습니다 x.)

크기의 n > 0경우 :

  • 크기의 출력을 n-1취하고 각 행을 3 배 늘립니다.
  • 하나의 행 사이 리플 x
  • x각 열에 정확히 하나가 있도록 행을 오른쪽으로 이동하고 행 x과 함께 줄이면서 첫 번째의 위치 는 최소화

예를 들어, 출력 n = 1은 다음과 같습니다.

    x
 xxx
x

에 대한 출력을 얻기 위해 n = 2각 행을 3 배씩 늘립니다.

            xxx
   xxxxxxxxx
xxx

단일 행 사이의 리플 x:

x
            xxx
x
   xxxxxxxxx
x
xxx
x

오른쪽으로 이동 :

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

다른 예로, 여기 있습니다 n = 3.

채점

이것은 코드 골프이므로 가장 적은 바이트의 솔루션이 이깁니다.

답변:


7

피스, 30

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

STDIN에서 입력을 받고 grc의 Cantor 세트를 찾는 방법을 사용하는 프로그램입니다. "문자를 사용하여 곡선을 표시합니다.

여기에서 온라인으로 사용해보십시오.

설명:

코드를 두 부분으로 설명하겠습니다. 먼저 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)

그리고 출력 형식 :

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

pyth에서는 기본적으로 N = ' "'입니다.


32

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

한동안 문제에 대해 생각한 후에, 나는 악마의 계단 패턴을 생성하는 완전히 다른 방법을 발견했습니다. 설명을 포함한 이전 답변이 제거되었습니다.이 답변의 개정판을 살펴보고 어떻게되었는지 확인할 수 있습니다.

이 답변은 악마의 계단을 나타내는 공백과 날카로운 배열을 반환합니다.

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

다음은 답변을 명시 적으로 두 부분으로 나눈 것입니다.

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

설명

접근 방식은 약간 다르므로 관찰하고 놀라십시오.

  1. >: 3 – 3 증가, 즉

    4
    
  2. 2 ^ >: 3 – 2에서 3의 거듭 제곱 즉,

    16
    
  3. i. 2 ^ >: 3– 첫 번째 2 ^ >: 3정수, 즉

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    
  4. }. i. 2 ^ 4– 첫 번째 2 ^ >: 3정수, 즉 참수

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

    이 시퀀스를 호출하자 s. 우리는 f지금 들어갑니다 .

  5. 1 q: s–의 각 항목의 주요 분해에서 2의 지수 s. 일반적으로 의 소수 분해에서 x q: y첫 번째 x소수에 대한 지수 표를 산출합니다 y. 결과는 다음과 같습니다.

    0
    1
    0
    2
    0
    1
    0
    3
    0
    1
    0
    2
    0
    1
    0
    
  6. 3 ^ 1 q: s –이 지수의 3 배, 즉

     1
     3
     1
     9
     1
     3
     1
    27
     1
     3
     1
     9
     1
     3
     1
    
  7. , 3 ^ 1 q: s– 이전 결과의 라벨 (즉, 구조가있는 인수가 벡터로 축소됨) 이것은 q:불필요한 후행 축을 도입 하기 때문에 필요합니다 . 이 결과

     1 3 1 9 1 3 1 27 1 3 1 9 1 3 1
    
  8. (, 3 ^ 1 q: s) # ss이전 결과의 해당 항목만큼 자주 복제되는 각 항목 , 즉

    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 – 이전 결과의 자체 분류, 이것은 각 행이 인수의 고유 항목 중 하나를 나타내고, 각 열이 인수의 해당 항목을 나타내고 각 셀이 행과 열의 항목이 같은지 여부를 나타내는 행렬입니다. 그건,

    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 – 이전 결과가 세로 축을 따라 뒤집 힙니다.

  11. (|. = (, 3 ^ 1 q: s) # s) { ' #'- 배열의 인덱스로서 사용되는 이전의 결과 항목 ' #'그래서 0로 대체  1교체되고 #있다,

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

    우리가 원하는 결과.


전력 루프 내부에서 1 바이트 (,],~3^#@~.)@](1,[:,1,"0~3*])절약합니다. 그리고 당신과 함께 확인 인 경우 !출력 문자로 u:32+대신이 ' #'{~다른 하나를 저장합니다.
randomra

#\ 대신에 i.@#당신은 APL을 추월합니다! :)
randomra

두 번째 솔루션은 모자가 필요하기 때문에 작동하지 않지만 APL을 이길 수있는 다른 방법을 찾았습니다.
FUZxxl

새로운 출력은 n-1not 의 계단 입니다 n.
randomra

@randomra 아 ... 그건 tty. 그것이 고칠 수 있는지 보자.
FUZxxl

26

헥사 고니 , 217 바이트

이것은 엄청나게 재미있었습니다. 이 과제를 게시 해 주셔서 감사합니다.

전체 공개 :이 챌린지가 게시 될 당시에는 언어 (헥사 고니)가 없었습니다. 그러나 나는 그것을 발명하지 않았으며 언어는이 도전 (또는 다른 특정 도전)을 위해 설계되지 않았습니다.

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

육각형으로 배치 :

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

프로그램은 실제로 #명령을 사용하지 않으므로 해당 문자를 사용하여 어떤 셀이 실제로 사용되지 않았는지 보여줍니다.

이 프로그램은 어떻게 작동합니까? 조건에 따라서. 짧은 버전 또는 긴 버전을 원하십니까?

간단한 설명

다음 설명에서“line”과“segment”의 의미를 설명하기 위해 의도 된 출력의이 해부를 고려하십시오.

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

그 설명으로 프로그램은 다음 의사 코드에 해당합니다.

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

긴 설명

이 색상으로 코드화 된 코드 경로 다이어그램을 참조하십시오.

실행 경로

왼쪽 상단에서 실행이 시작됩니다. 명령 순서 는 상당히 복잡한 경로를 추구하여 ){2'"''3''"2}?)실행됩니다 (예 : 중복 취소 "{등). 우리는 크림슨으로 강조 표시된 Instruction Pointer # 0으로 시작합니다. 도중에 오른쪽 상단에서 시작하여 녹색으로 칠해진 # 1로 전환합니다. IP # 2가 수레 국화 파란색 (오른쪽 가운데)으로 시작하면 메모리 레이아웃은 다음과 같습니다.

메모리 레이아웃

전체 프로그램에서 2a2b로 표시된 모서리 는 항상 값을 가지며 2(각각 2ⁿ⁺를 계산하고 2로 나누기 위해 사용) 3으로 표시된 모서리 는 항상 3( 3 (을 계산하는 데 사용)입니다.

수레 국화 파란색으로 강조 표시된 첫 번째 루프에 들어가면 사업을 시작합니다. 이 루프는 명령 (}*{=&}{=을 실행하여 값 2 to¹를 계산합니다. 루프가 종료되면 새들 브라운 경로가 생성되어 Instruction Pointer # 3으로 이동합니다. 이 IP는 단지 아래쪽 가장자리를 따라 서쪽으로 황금빛 노란색으로 변하고 곧 IP # 4로 제어를 전달합니다.

자홍색 경로는 IP # 4는 왼쪽 하단부터 감량을 신속히 진행 방법을 나타내는 , 설정된 채널32(스페이스 문자) 및 SEG (새로운 값)에 라인 . 우리가 실제로 2ⁿ⁺¹-1로 시작하고 결국 0 값으로 마지막 반복을 경험하는 것은 초기 감소로 인한 것입니다. 그런 다음 첫 번째 중첩 루프를 시작합니다.

우리는 분기 인디고에주의를 돌립니다. 여기서 seg 의 짧은 감소 후에 seg 가 이제 0 인 경우에만 ch가 업데이트되는 것을 볼 수 있습니다. 그런 다음 nline-seg 로 설정되어 우리가 속한 세그먼트의 실제 수를 결정합니다. 즉시 이번에는 토마토의 공정한 색상으로 다른 루프에 들어갑니다.x

여기서 우리는 n (현재 세그먼트 번호)을 2로 나눌 수있는 횟수를 계산합니다. 모듈로가 0을주는 한, i 를 증가 시키고 n 을 2로 나눕니다 . 만족할 때 n 은 더 이상 나눌 수 없습니다. , 우리는 두 개의 루프를 포함하는 슬레이트 그레이로 분기합니다. 먼저 계산 한 i 의 거듭 제곱으로 3을 올린 다음 ch 를 여러 번 출력 합니다. 이 루프 중 첫 번째 루프에는[명령을 사용하여 제어를 IP # 3으로 전환합니다.이 명령은 하단 가장자리를 따라 아기 발걸음을 내딛는 것입니다. 루프의 몸체 (3을 곱하고 감소)는 외로운 IP # 3에 의해 실행되며, 코드의 아래쪽 가장자리를 따라 끝없는 짙은 올리브 녹색 주기로 수감됩니다. 마찬가지로,이 슬레이트 회색 루프 중 두 번째 루프에는 ]IP # 5를 활성화하여 ch 및 감소 를 출력 하는 명령이 포함되어 있습니다. 여기에 어두운 인도 빨강으로 표시됩니다. 두 경우 모두, servitude에 갇힌 명령 포인터는 한 번에 하나의 반복을 순종적으로 실행하고 IP # 4로 제어권을 양도하고 서비스가 다시 한 번 호출되는 순간을 무시합니다. 한편, 슬레이트 그레이는 자홍색과 남색 형제들과 다시 합류합니다.

세그먼트가 필연적으로 0에 도달 함에 따라 , 인디고 루프는 잔디밭 녹색 경로로 빠져 나가며, 단지 개행 문자를 출력하고 즉시 자홍색으로 다시 병합되어 라인 루프 를 계속합니다 . 라인 루프 의 최종 반복을 넘어서서 궁극적 인 프로그램 종료의 짧은 세이블 경로입니다.


8
이제 이것은 단순한 구식 광기입니다.
FUZxxl

21

파이썬 2, 78

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

목록부터 시작하여 L=[1]복제하고 중간에 다음 3의 거듭 제곱을 삽입하여 결과를 얻습니다 [1, 3, 1]. 이것은 n우리에게 악마의 계단을위한 줄 길이를주기 위해 반복 됩니다. 그런 다음 공백으로 채워진 각 행을 인쇄합니다.


20

APL, 38

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

예:

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

설명:

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

좋은 해결책입니다.
FUZxxl

20
코드 설명이 악마의 계단처럼 보이는 것이 좋습니다.
Alex A.

더 짧은 APL 솔루션을 찾았습니다.
FUZxxl

14

GNU sed, 142

가장 짧은 대답은 아니지만 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

이것은 sed (원래 산술이 아님)이기 때문에 "출력의 크기를 나타내는 단일 정수 n> = 0" 규칙으로 자유를 취 합니다. 이 경우 입력 정수는 1길이가 n 인 s 의 문자열이어야합니다 . 나는 이것이 n과 직접적인 숫자가 아니지만 출력의 크기를 "표시" 한다고 생각합니다 . 따라서 n = 2의 경우 입력 문자열은 다음과 11같습니다.

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

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

이것은 O (c n ) 의 지수 시간 복잡도로 완료된 것으로 보이며 , 여기서 c는 약 17입니다. n = 8은 약 45 분이 걸렸습니다.


또는 숫자를 정확하게 숫자로 입력 해야하는 경우 다음을 수행 할 수 있습니다.

sed, 274 바이트

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

산출:

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

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

$ 

7
정말 멋지다.
FUZxxl

8

파이썬 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

프로그램 버전 (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- 색인 행 의 x 수 는 3의 거듭 제곱입니다 ( nlsb에서 시작 하여 첫 번째 세트 비트의 색인 ).


8

파이썬 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)

재귀 적 접근. 크기-$ n $ 악마의 계단은 세 부분으로 나뉩니다.

  • 왼쪽 재귀 분기, size의 계단 n-1, 길이는3**n - 2**n
  • x' 의 중심선 길이3**n
  • 오른쪽 재귀 브랜치, size의 계단 n-1, 길이는3**n - 2**n

세 부분의 총 길이는 3*(3**n) - 2*(2**n)또는 3**(n+1) - 2**(n+1)이며, 이는 유도를 확인합니다.

선택적 변수 s는 인쇄중인 현재 부품의 오프셋을 저장합니다. 먼저 큰 오프셋으로 왼쪽 분기로 돌아가서 중심선을 인쇄 한 다음 현재 오프셋에서 오른쪽 분기를 수행합니다.


6

CJam, 36 35 33 바이트

다음은 또 다른 CJam 접근 방식입니다 (최적화 코드를 보지 않았으므로 실제로 다른지 모르겠습니다).

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

0커브에 사용 합니다. 또는 (grc의 트릭을 사용하여)

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

사용하는 x.

여기에서 테스트하십시오.

설명

기본 아이디어는 먼저 행과 함께 배열을 형성하는 것입니다.

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

그런 다음 적절한 양의 공백을 추가 하여이 목록을 살펴보십시오.

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

다른 버전은 비슷하게 작동하지만 다음과 같은 길이의 배열을 만듭니다.

[1 3 1 9 1 3 1]

그런 다음 x최종지도에서 s 문자열로 바꿉니다 .


6

Dyalog APL, 34 자

grc에 의한 접근법 사용. (domino) 문자로 계단을 그리고 stdin에서 입력을받습니다. 이 솔루션은 가정합니다 ⎕IO←0.

' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
  • – stdin에서 입력을받습니다.
  • ⌽⍳1+⎕- 행 번호의 순서 0으로 다운 (예 3 2 1 0)
  • 3*⌽⍳1+⎕- 그 힘에 세 가지 (예 27 9 3 1)
  • (⊢,,)/3*⌽⍳1+⎕– 이전의 결과 는 grc 접근 방식에 따라 악마 계단의 계단 길이를 산출하는 ⊢,,dfn과 동일한 암묵 함수에 의해 오른쪽에서 접혔습니다 {⍵,⍺,⍵}.
  • {⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕ 단계 길이는 단계로 변환됩니다.
  • (∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕J 솔루션 에서와 같이 자체 분류됩니다 . 공지 이미 정확하게 결과를 뒤집습니다.
  • ' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕] 숫자는 공백과 도미노로 대체됩니다.

4

루비, 99

FUZxxl의 답변에서 영감을 얻은 다른 답변

FUZxxl은 x의 개수가 인덱스 2의 요인 개수에 해당한다는 점에 주목합니다. 예를 들어 n = 2의 경우 다음과 같은 인수 분해가 있습니다.

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

나는 2의 힘을 추출하는 다소 간단한 방법을 사용합니다 . 이는 i=m&-m시퀀스 1 2 1 4 1 2 1등 을 산출합니다 .

m-1m최상위 비트 와 동일 하지만 최하위 1의 비트는 0이되고 오른쪽의 모든 0은 1이됩니다.

원본과 함께 사용할 수 있으려면 비트를 뒤집어 야합니다. 이를 수행하는 다양한 방법이 있습니다. 한 가지 방법은에서 빼는 것입니다 -1.

그러면 전체 공식이 m& (-1 -(m-1)) 단순화됩니다.m&(-m)

예:

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

코드는 다음과 같습니다. 줄 바꿈이 계산되고 들여 쓰기가 불필요하므로 다른 답변으로 계산되지 않습니다. 기본 2 1 2 1 4 1 2 1 etc에서 기본 3으로 서투른 변환으로 인해 다른 답변보다 약간 깁니다 . 1 3 1 9 1 3 1 etc(피할 수있는 방법이 Math::있습니까?)

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

루비, 140 99

나의 두 번째 루비 코드와 언어의 첫 번째 사소한 사용. 제안은 가장 환영합니다. 바이트 수는 들여 쓰기를위한 선행 공백을 제외하지만 줄 바꿈을 포함합니다 (적어도 공백으로 바꾸지 않으면 대부분의 줄 바꿈을 삭제할 수없는 것 같습니다).

함수 호출에 의한 입력입니다. 출력은 문자열 배열이며, 루비는 편리하게 stdout을 singleline으로 개행으로 구분 된 목록으로 덤프합니다 puts.

알고리즘은 단순히 new iteration= previous iteration+ extra row of n**3 x's+ previous iteration입니다. 그러나이 많이 공정한 금액 의 코드는 바로 출력 오른쪽에서 최고의 공간을 얻을 수는.

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

편집 : 루비, 97

이것은 a위에서 설명한 방식으로 배열 에 필요한 모든 x 수의 숫자 테이블을 작성하고 나중에 문자열 테이블을 작성 하는 유사하지만 다른 접근법을 사용합니다 . 문자열 테이블은 기존 배열 앞에 추가하기 위해 c다소 이상한 이름의 unshift메소드를 사용하여 배열에서 거꾸로 빌드 됩니다.

현재이 접근법은 더 좋아 보이지만 2 바이트 만 :-)

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
당신은 대체 할 수 있습니다 for m in(0..n-1)do ... endn.times{|m|...}.
Omar

@Omar 감사합니다. 내일해볼 게요. 상수 구문 오류로 인해 실행하는 데 얼마나 많은 노력이 들었는지 믿지 못할 것입니다. 반복 변수에 액세스하는 방법을 몰랐으며 n.times확실히 기억할 것입니다. end너무 제거합니다 ! 그러나이 기회 for m in (1..n)를 피하기 위해 더 나은지 궁금 합니다 (m+1). 그것을 쓰는 더 짧은 방법이 있습니까?
Level River St

1
for는 주로 강제로 사용하기 때문에 길다 end( do개행 문자 또는로 대체 할 수 있음 ;). 들어 1..n당신은 사용할 수 있습니다 1.upto(n){|m|...}. 모양이 마음에 (1..n).each{|i|...}들지만 사용하는 것보다 약간 더 깁니다 upto. 그리고 호출하여 반복하는 것으로 each또는 것은 upto단지 짧은 아니라, 또한 더 관용적 루비를 고려합니다.
Omar

@ 다시 한번 감사합니다 1.upto(n)! 그와 불필요한 대괄호가 없어지면 이미 120으로 줄어 들었습니다. 100 이하가 가능하다고 생각하면 나중에 수정 된 코드를 게시 할 것입니다.
Level River St

3

하스켈, 99 자

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

기능은 d다음과 같습니다

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

이 모든 괄호! 적은 돈으로 도망 갈 수있는 방법이 정말로 없습니까?
FUZxxl

빈 목록 경우 q와 방정식을 바꾸면 바이트를 잃을 수 있습니다 q x=x. 또한 괄호 iterate...[1]가 불필요한 것 같습니다 .
Zgarb

3

PHP-137 바이트

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

나는 여기에 grc 와 같은 트릭을 사용하고 있습니다 . ungolfed 버전은 다음과 같습니다.

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과 같은 느낌입니다. 지정해야합니다. 이것은 거의 모든 PHP 설치와 호환되지 않습니다. 몇 바이트를 절약하려면 시작하고 $r=str_repeat;그 기능이있는 곳에서으로 대체하여 $r2 바이트를 절약 할 수 있습니다 . 또한 $r('x',$v)가능 $r(x,$v)하고 잘 작동합니다 (이미 함수 이름을 변수로 바꿨습니다). 또한 다른 바이트 ++$i<=$n$n>++$i절약 하여 다시 작성할 수 있다고 생각합니다 .
Ismael Miguel

여기에 귀하의 기능이 조금 멋진 트릭과,이다 : 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;}(대신 못생긴 줄 바꿈을 필요없이, 내가 이스케이프 시퀀스를 추가 한 \r변수로, 이중 인용 된 문자열 안에 $o. 그 안에 따라서 "\r$o"는 AS 같은 바이트 수를 가지고 ''.$o하나, 줄 바꿈은 마지막에 ommited과 같은 결과를 함께.
이스마엘 미구엘

사실,의 조건이 while되어야합니다 $n>$i++제대로 작동하려면이 감소.
Ismael Miguel

@IsmaelMiguel PHP 5.6은 PHP의 마지막 버전이므로 더 이상 말할 필요가 없습니다. 거의 모든 사람이 이전 버전을 사용하고 있고 대다수가 구식 버전을 사용하고 있다면 그것은 내 잘못이 아닙니다. $r=str_repeat트릭 주셔서 감사합니다 . 나는 $r='str_repeat';바이트 만 절약하지 않는 것에 대해서만 생각하고 있었습니다. 정의되지 않은 상수는 좋은 트릭입니다.;). 줄 바꿈은 쓰는 것보다 1 바이트 작으므로 \n계속 유지했지만와의 연결을 피하기 위해 큰 따옴표를 사용했습니다 $0. 다시 감사합니다!
Blackhole

그것은 당신에게만 잘 보일 것입니다. 내가 몰랐다면 나는 3 ** $i당신이 끔찍한 구문을 가지고 있다고 말할 것입니다. 그 정정을 다룰 수 있습니다. [1]PHP5.4에서 나왔기 때문에 이것에 대해서만 말하는 것이 아니라 아주 오래된 것입니다. 1 년 전, 나는 그것을 지정하도록 요청합니다. 오늘 나는 이것을 지정하는 (짧은 줄로) 간단히 지정하도록 요청합니다. 코드에 대해 말하면 여전히 ++$i<=$n로 바꿀 수 있습니다 $n>$i++. 테스트하기 위해 모든 코드를 PHP5.3으로 변환해야했습니다. 어느 쪽이 아 was습니다. 하지만 지금까지 7 바이트를 먹었습니다.
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');}}

압축을 풀고 약간 정리 한 동일한 코드는 다음과 같습니다.

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

이것은 행에 대한 암시 적 형식이 아닌 명시 적 형식을 사용한다는 문제에 대한 FUZxxl의 솔루션과 동일한 아이디어를 기반으로합니다. j를 선언하면 2 ^ (n + 1)로 설정되고 첫 번째 while 루프는 k = 3 ^ (n + 1)을 계산합니다. l = 3 ^ (n + 1) -2 ^ (n + 1)은 계단의 전체 너비입니다 (이는 증명하기 어렵지 않습니다). 그런 다음 모든 숫자 r을 1에서 2 ^ (n + 1) -1까지갑니다. 각각에 대해 (정확히) 2 ^ n으로 나눌 수 있으면 s = 3 ^ n 'X'를 인쇄 할 계획입니다. 나는 우리가 올바른 지점에서 시작하도록 조정됩니다 : 우리는 l 개의 공백과 s 'X'를 쓴 다음 줄 바꿈을 씁니다.


W를 정의하는 동안 int를 생략하고 일부 문자를 저장하십시오.
FUZxxl

또한 약간의 절약을 위해 t = l- = s.
FUZxxl

@FUZxxl 두 가지를 모두 시도했지만 C는 여전히 함수에서 암시 적 유형을 허용하지만 '클래식'플래그 (적어도 GCC에서는)로도 변수 선언에서 허용하지 않았습니다. 그리고 나는 #define W를 시도했지만 그 정의에 빠져 들었을지라도 그것을 신경 쓰지 않는 것 같습니다.
Steven Stadnicki

흠 ... 전역 변수에서만 유형을 생략 할 수 있다고 생각합니다. 그것은 당신을별로 가져 오지 않습니다. 당신은 추가 할 수 있습니다 (*p)()=putchar;호출 시작 부분 putchar으로 p. 나는 그것이 작동해야한다고 생각합니다.
FUZxxl

2

CJam, 46 43 41 39 36 35 바이트

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

다른 접근 방식을 사용하여 지금 업데이트하십시오 .


오래된 접근법 :

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

순진하고 오래되었지만 시작해야 할 것이 있습니다.

골프를 타면 설명을 추가하겠습니다.

여기에서 온라인으로 사용해보십시오


약간의 작업이 필요한 것 같습니다. n = 4, 5, 17에 대해 제대로 작동하지 않았습니다. 왼쪽에 x의 왼쪽 형식의 리플 문자열이 상단에 표시되었습니다. n = 17이면 화면에 코드를 덤프하고 바닥을 x로 채 웁니다.
DavidC

1
@DavidCarraher 4, 5의 경우 나는 그것이 줄 바꿈이라고 생각합니다. 줄 바꿈없이 텍스트 편집기로 출력을 복사하면 나에게 괜찮습니다.
Sp3000

승인. 알아요
DavidC

2

자바, 271 269 ​​바이트

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

들여 쓰기 :

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

어떤 제안이라도 환영합니다.

mbomb007로 인한 2 바이트


b.size()>0대신 !b.isEmpty()2 바이트를 절약 하여 사용할 수 있습니다 .
mbomb007

1

펄, 62

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

먼저 선행 공백없이 반복적으로 결과를 계산합니다. 그런 다음 x나머지 문자열 의 문자 수에 따라 각 줄 앞에 추가합니다 .


1

자바 스크립트 (ES6) 104 106 118

편집 재귀 함수를 제거하고 각 줄의 '*'목록을 반복적으로 얻습니다. 비트와 3의 거듭 제곱으로 계산합니다 (많은 다른 답변과 마찬가지로)
루프 내 에서 여러 줄 문자열이 아래에서 위로 올라와 실행 횟수를 유지합니다. 각 줄에 추가 할 선행 공백

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
}

첫 번째 시도 제거

재귀 R 함수는 각 줄에 대해 '*'의 숫자로 배열을 만듭니다. 예를 들어 R (2)는 [1, 3, 1, 9, 1, 3, 1]
이 배열을 스캔하여 맨 아래부터 여러 줄의 문자열을 만들어 각 줄에 추가 할 선행 공백 수를 유지합니다.

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 콘솔에서 테스트

F(3)

산출

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

1

R-111 자

간단한 구현으로 반복적으로 배열을 구축하고 천천히 파괴합니다.

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

용법:

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

가 필요하므로 좋은 지적, 내 코드를 수정 n명령 줄에서 인수
koekenbakker

1
STDIN에서 읽음으로써 8 바이트를 저장합니다. n=scan().
Alex A.

x커서로 사용 하도록 선언 하거나 필요하지 않습니다 if(n). 또한 줄 바꿈은 내가 생각하는 문자로 간주됩니다.
freekvd

감사합니다 x. if(n)그러나 확실하지 않습니다 . 나는 사건을 처리하기 위해 그 부분을 추가했다 n=0. 그런 if(n)다음 반환 F하고 단일을 반환합니다 x. 제거 n=0하면 원하지 않는 결과가 나타납니다. 새로운 기능이므로 줄 바꿈에 대해 몰랐습니다. 지금 포함되어 있습니다!
koekenbakker

a=0루프 를 설정 하고 시작하면 x in 0:nn = 0에서도 작동합니다. 그런 다음을 생략 할 수 있습니다 if(n).
freekvd

0

루비, 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}}

이것은 grc와 동일한 접근법을 사용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.