画出魔鬼的楼梯


46

恶魔的楼梯是一个分形样相关Cantor集功能。

在此处输入图片说明

您的任务是复制这个时髦的功能-以ASCII艺术形式!

输入项

一个整数n >= 0,指示输出的大小。输入可以通过STDIN,函数参数或命令行参数给出。

输出量

魔鬼楼梯的ASCII艺术形式,大小为n,可作为字符串返回或打印到STDOUT。每行末尾的尾随空格都可以,但前导空格不行。您可以选择打印单个尾随换行符。

对于size 0,输出仅为:

x

(如果愿意,可以使用空格以外的任何其他可打印ASCII字符代替x。)

对于大小n > 0,我们:

  • 取大小的输出n-1并将每行拉伸三倍
  • 单行x的行之间的波纹
  • 向右移动各行,以便x每列正好有一行,并且第一x行的位置最小,而随行减少

例如,输出为n = 1

    x
 xxx
x

为了获得的输出n = 2,我们将每行拉伸三倍:

            xxx
   xxxxxxxxx
xxx

单身行之间的波纹x

x
            xxx
x
   xxxxxxxxx
x
xxx
x

向右移动:

                  x
               xxx
              x
     xxxxxxxxx
    x
 xxx
x

再举一个例子,这里n = 3

计分

这是代码高尔夫球,因此以最少字节为单位的解决方案将获胜。

Answers:


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个字符)

考虑了一段时间后,我发现了一种完全不同的方式来生成Devil's Staircase模式。原来的答案(包括其解释)已被删除,您可以查看该答案的修订版,以了解其答案。

该答案返回代表魔鬼的楼梯的一排空白和锋利的物体。

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

这是将答案分为两部分的显式表示法:

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

说明

方法有些不同,因此请观察并感到惊讶。

  1. >: 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 ^ 42 ^ >: 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 –这三个指数的幂,即

     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被替换为#,即,

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

    我们想要的结果。


在电源环路内部,(,],~3^#@~.)@]而不是(1,[:,1,"0~3*]) 节省1个字节。如果您可以接受!输出char u:32+而不是' #'{~另存一个。
randomra

#\ 而不是i.@#您超过了APL!:)
randomra

您的第二个解决方案无效,因为需要上限,但是我找到了另一种击败APL的方法。
FUZxxl 2015年

新的输出是n-1not 的阶梯n
randomra

@randomra啊...太糟糕了。让我看看它是否可修复。
FUZxxl 2015年

26

六边形,217字节

这非常有趣。感谢您发布此挑战。

完全公开:发布此挑战时不存在该语言(六边形)。但是,我没有发明它,并且该语言并不是针对这种挑战(或任何其他特定挑战)而设计的。

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

六角形布置:

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

该程序实际上并未使用该#指令,因此我使用该字符来显示哪些单元格确实未被使用。

该程序如何工作?那要看。您要短版还是长版?

简短说明

为了在以下说明中说明“线”和“段”的含义,请考虑对预期输出的这种分解:

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}?)来执行指令序列(加上一些多余的取消,例如,"{等等)。我们从深红色突出显示的指令指针#0开始。中途,我们切换到#1,从右上角开始,然后涂上深绿色。当IP#2以矢车菊蓝色(右中)开始时,内存布局是这样的:

内存布局

在整个程序中,标记为2a2b的边将始终具有该值2(我们分别使用它们来计算2 ^ 1并除以2),标记为3的边将始终3为该值(我们使用它来计算3ⁱ)。

进入第一个循环时,我们开始做生意,以矢车菊蓝色突出显示。该循环执行指令(}*{=&}{=以计算值2 11。当循环退出时,采用鞍形棕色路径,这将我们带到指令指针3。该IP仅以金黄色黄色沿底部边缘向西涉水,不久便将控制权交给IP#4。

紫红色的路径表示从左下角开始的IP#4如何迅速进行到递减,将ch设置为32(空格字符)并将seg设置为(line的新值)。由于早期递减的缘故,我们实际上开始于2 -1−1,最终经历了值0的最后一次迭代。然后,我们进入第一个嵌套循环。

我们将注意力转向分支靛蓝,其中在seg短暂递减后,仅当seg现在为零时,我们才会将ch更新为。然后,将n设置为-seg行,以确定我们所在的段的实际数量。我们立即进入另一个循环,这次使用的是番茄的鲜艳颜色。x

在这里,我们找出了多少次ñ(当前段号)可以通过2整除,只要模为我们提供了零,我们增加和鸿沟ñ通过2.当我们感到满意ñ不再正是如此整除,我们分成灰色的板岩,它包含两个循环:首先,它将3提高到我们计算的i的幂,然后输出ch多次。观察到这些循环中的第一个包含一个[指令,将控制权切换到IP#3,这只是较早地沿底部边缘迈出的一步。循环的主体(乘以3并递减)由一个孤独的IP#3执行,该IP#3沿代码的底部边缘被无休止的深橄榄绿色循环包围。类似地,这些板岩灰色循环中的第二个包含一条]指令,该指令激活IP#5以输出ch和减量,此处以深印度红显示。在这两种情况下,陷入困境的那些指令指针一次只能执行一次迭代,然后将控制权交还给IP#4,只是为了等待再次调用它们的服务。同时,石板灰重新加入了其紫红色和靛蓝弟兄风格。

不可避免地达到零时,靛蓝回路退出到草坪绿色路径中,该路径仅输出换行符,并迅速合并回到紫红色中以继续循环。在行循环的最后迭代之外,还有最终程序终止的较短的稳定路径。


8
现在,这只是普通的老式精神错乱。
FUZxxl 2015年

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

从列表开始L=[1],我们将其复制并在中间插入下一个3的幂,结果为[1, 3, 1]。重复此操作n以使我们获得魔鬼楼梯的行长。然后,我们打印每行填充空格。


20

杀伤人员地雷,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 2015年

20
我喜欢代码的解释就像是魔鬼的楼梯。
Alex A.

我发现了一个更短的APL解决方案。
FUZxxl 2015年

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,指示输出的大小”的规则。在这种情况下,输入整数必须是1s 的字符串,其长度为n。我认为这是“指示”输出的大小,即使它不是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分钟。


或者,如果要求精确输入数字n,那么我们可以这样做:

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 2015年

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

程式版本(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)

n第1个索引行中的x的数目是3的幂(n从lsb开始的in中的第一个置位的索引)的幂。


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)

递归方法。大小为$ n $的魔鬼楼梯分为三个部分

  • 左递归分支,大小阶梯 n-1,其长度为3**n - 2**n
  • 中心线 x,长度3**n
  • 正确的递归分支,一个大小为的楼梯n-1,其长度为3**n - 2**n

注意,这三个部分的总长度是3*(3**n) - 2*(2**n)3**(n+1) - 2**(n+1),这确定了归纳法。

可选变量s存储我们正在打印的当前零件的偏移量。我们首先递归到具有较大偏移量的左分支,然后打印中心线,然后以当前偏移量进行右分支。


6

果酱,36 35 33字节

这是另一种CJam方法(我没有看过Optimizer的代码,所以我不知道它是否实际上有很大不同):

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+⎕]
  • –从标准输入中获取输入。
  • ⌽⍳1+⎕–从低到0 的数字顺序(例如3 2 1 0
  • 3*⌽⍳1+⎕ –这就是力量的三倍(例如 27 9 3 1
  • (⊢,,)/3*⌽⍳1+⎕–先前的结果是通过默认函数从右折叠的,⊢,,等于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,而右侧的所有零都变为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

我的第二次Ruby代码,以及我对该语言的第一次平凡使用。欢迎提出建议。字节数不包括缩进的前导空格,但包括换行符(似乎大多数换行符都不能删除,除非它们至少被空格代替。)

通过函数调用输入。输出是一个字符串数组,ruby可以方便地将其作为带有单个换行符的列表转储到stdout 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

编辑:Ruby,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|...}
奥马尔2015年

@Omar谢谢,我明天再试试。由于不断出现语法错误,您不会相信要花多少精力才能运行它。我不知道如何访问迭代变量n.times,我一定会记住这一点。它也消除了end!但是,在这种情况下,我想知道是否for m in (1..n)可能会更好(m+1)。有没有更短的书写方式?
水平河圣

1
for很长,主要是因为您被迫使用end(您可以用do换行符或用;)。供1..n您使用1.upto(n){|m|...}。我喜欢的外观,(1..n).each{|i|...}但比使用稍长upto。请注意,通过调用each或进行迭代upto不仅要短一些,而且还要考虑使用更多惯用的Ruby。
奥马尔2015年

@再次感谢,1.upto(n)是!有了这个和一些不必要的括号,我已经降到了120。我认为100以下是可能的,我将在以后发布修订后的代码。
水平河圣

3

Haskell,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 2015年

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相同的技巧。这是非高尔夫版本:

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;在具有该功能的地方,可以替换为$r,为您节省2个字节。另外,$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",其字节数与字符串相同''.$o,最后一行省略换行符,并产生相同的结果
Ismael Miguel

实际上,必须满足的条件while才能$n>$i++使此还原正常工作。
伊斯梅尔·米格尔

@IsmaelMiguel PHP 5.6是PHP的最新版本,我不必多说。如果几乎每个人都在使用旧版本,并且大多数人都在使用旧版本,这不是我的错。谢谢你的$r=str_repeat把戏。我只是在考虑$r='str_repeat';,它没有保存任何字节。未定义的常量也是个好办法,做得很好;)。换行符比写入的要小一个字节\n,因此我保留了它,但是我使用了双引号来避免与的串联$0。再次感谢 !
Blackhole,2015年

只会对你好看。如果我不了解,3 ** $i我会说您的语法很糟糕。您可以解决该更正。我只说这不是[1]因为它来自PHP5.4,这已经很“老了”。1年前,我想请您具体说明。今天,我请您简单地指定(以很短的一行)来指定此内容。说到代码,您仍然++$i<=$n可以将替换为$n>$i++。我必须将所有代码转换为PHP5.3进行测试。真痛苦。但我看到你到目前为止吃了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)是楼梯的总宽度(这很难证明)。然后,我们遍历所有从1到2 ^(n + 1)-1的数字r;对于每一个,如果它可以被(精确)2 ^ n整除,那么我们计划打印s = 3 ^ n'X'。调整l以确保我们从正确的位置开始:我们写入l空格和s'X',然后输入换行符。


将W定义为; while并省略int以保存一些字符。
FUZxxl 2015年

也可以t = l- = s保存。
FUZxxl 2015年

@FUZxxl我尝试了这两种方法,但是C仍然允许在函数上使用隐式类型,即使使用'classic'标志(至少在GCC上),也不允许在变量声明上使用它们。我尝试了#define W;虽然它可能并不在乎它的定义,但它似乎并不在意它。
史蒂文·斯塔德尼基

嗯...我想您只能在全局变量中省略类型。它不会带给您太多。你可以尝试添加(*p)()=putchar;在开始时调用putcharp。我认为应该可以。
FUZxxl 2015年

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

Java中,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;
}

欢迎任何建议。

2字节归功于mbomb007


您可以使用b.size()>0代替!b.isEmpty(),节省2个字节。
mbomb007

1

Perl,62岁

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

首先,在没有前导空格的情况下迭代计算结果。然后根据x其余字符串中的字符数在每行之前添加它们。


1

的JavaScript(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)。另外,我认为换行符是一个字符。
freekvd15年

谢谢,您是对的x。不确定if(n)但是。我添加了该部分以处理此案n=0。所述if(n)然后返回F并因此返回单个x。如果我将其删除,则会n=0产生不需要的结果。这里是新手,所以不知道换行符。现在包括!
koekenbakker

如果设置a=0并开始循环,x in 0:n则它也适用于n = 0。然后,您可以省略if(n)
freekvd15年

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相同的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.