【问题标题】:Repeating triangle pattern in Python在 Python 中重复三角形模式
【发布时间】:2021-12-16 03:37:14
【问题描述】:

我需要根据输入的整数来制作*的三角形三角形图案。

例如:

n = 2

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

n = 3

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

我已经找到了单个三角形的代码,但我不知道如何复制它们,所以它们看起来就像一个三角形的三角形。

这是我的一个三角形的代码:

rows = int(input())

for i in range(rows):
    for j in range(i, rows):
        print(" ", end="")
    for j in range(i):
        print("*", end="")
    for j in range(i + 1):
        print("*", end="")
    print()

【问题讨论】:

  • 这似乎是那些旨在让人们逐步思考的练习之一,而仅仅获得解决方案并没有太大帮助。如果你能找出一个三角形的代码,那么只需复制粘贴几次并稍作更改,直到它适用于 n=3。然后尝试查看模式在这些副本之间的位置,以及如何将它们组合成 for 循环,以便让它适用于其他 n 值。重复几次后,您应该能够在脑海中执行类似的过程。
  • 这在我们的网站上有been posted 用于编码挑战、Code Golf 和编码挑战堆栈交换。看看一些疯狂的短节目,用一些非常深奥的语言,做到这一点!

标签: python algorithm


【解决方案1】:

代码

我已经简化了以下代码,因此现在看起来应该比以前更加清晰易懂了。

n = int(input("n = "))

rows = n ** 2
base = n * 2 - 1

for row in range(rows):
    triangle = row // n
    level = row % n

    a_space = " " * (n - triangle - 1) * base
    b_space = " " * (n - level - 1)

    line = (a_space + (b_space + "*" * (level * 2 + 1) + b_space)
        * (triangle * 2 + 1)).rstrip()

    print(line)

工作原理

这种方法一次打印出所有内容。在下面的解释中,我将分解代码的组成部分,这些变量的含义以及它们是如何工作的。

高度

我应该提到的第一个变量是n,即层数或每个三角形的高度。它也是堆叠在一起的三角形的数量。

第二个变量是rows,输出中的行数。我们可以看到行数等于n平方的模式。

基础

下一个变量是base。它是三角形底部的星号数。正如我们可能注意到的,它也遵循奇数模式。

之后,我们的循环开始,遍历每一行,并打印出结果。

三角形和水平

这些变量告诉我们当前处于哪个三角形和三角形的水平。您可以通过每次迭代打印出trianglelevel 自己尝试。

for row in range(rows):
    triangle = row // n
    level = row % n

    print(triangle, level)

两种空​​间

下一部分是缩进。只是为了让您简要了解 a_spaceb_space 是什么,这里是描述空间的视觉表示。

a_space 在每个三角形后缩小,b_space 在每个级别后缩小。

a_space = " " * (n - triangle - 1) * base
b_space = " " * (n - level - 1)

我们将a_space 乘以base,因为a_space 的长度等于底数。

打印行

让我们一步一步来看看。

  1. 首先,我们以a_space 开头。
a_space
  1. 然后,我们打印出星号。星号的数量遵循奇数的模式。
"*" * (level * 2 + 1)
  1. 我们用b_space 打开和关闭星号。
b_space + "*" * (level * 2 + 1) + b_space
  1. 然后,我们只需将整个事物乘以水平堆叠的三角形数量即可。
(b_space + "*" * (level * 2 + 1) + b_space) * (triangle * 2 + 1)

把所有东西放在一起,我们得到线,右剥离它,然后打印出来。

line = (a_space + (b_space + "*" * (level * 2 + 1) + b_space)
        * (triangle * 2 + 1)).rstrip()

print(line)

输出

让我们用几个测试用例来试试吧。

n = 1

*

n = 2

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

n = 3

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

n = 4

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

【讨论】:

  • 什么是数学?您能否在答案中提供一些提示和参考?
  • @PeterMortensen 当然。请在接下来的几次编辑中给我一些时间来解释。
  • 很好的解释,但是数学真的很难理解,
  • @MrBeast 我已经简化了代码。它看起来不再那么混乱了。
  • @Bharel 你好 Bharel,我使用 Google 幻灯片制作了这些图片,这些图片的灵感来自 this post 中的图片。
【解决方案2】:

使用辅助函数构建子三角形:

def tri(n):
   r = [(s:=(' '*(((2*n-1)-(2*i-1))//2)))+('*'*(2*i-1))+s for i in range(1, n+1)]
   return r

def triangle(n):
   v = [''.join(j) for i in range(n+1) for j in zip(*[tri(n) for _ in range(2*i-1)])]
   return '\n'.join((s:=' '*((len(v[-1]) - len(i))//2))+i+s for i in v) 

for i in range(1, 4):
   print(triangle(i))
   print('-'*25)
*
-------------------------
    *    
   ***   
 *  *  * 
*********
-------------------------
            *            
           ***           
          *****          
       *    *    *       
      ***  ***  ***      
     ***************     
  *    *    *    *    *  
 ***  ***  ***  ***  *** 
*************************
-------------------------

【讨论】:

    【解决方案3】:

    另一种方法是绘制内部三角形的函数和打印最终结果的主函数

    import sys
    
    n = int(sys.argv[1])
    
    def drawtriangle(num_lines):
        # prepares the inner triagle in a list and return it together with its width (size).
        size = (2*num_lines)-1
        triangle = []
        for i in range(num_lines):
            white_side = num_lines - i - 1
            asterisks = 2*i + 1
            triangle.append(" "*white_side + "*"*asterisks + " "*white_side)
        return triangle, size
    
    def main(num_lines):
        tr, tr_size = drawtriangle(num_lines)
    
        for j in range(num_lines):
            for line in tr:
                white_triangles = n - j - 1
                white_size = tr_size * white_triangles
                line_repeat = (2*j) + 1
                print(" "*white_size + line*line_repeat + " "*white_size)
    
    main(n)
    

    输出:

    n = 1

    *
    

    n = 2

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

    n = 3

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

    n = 4

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

    【讨论】:

      【解决方案4】:

      您编写的打印单个三角形的程序在这种情况下没有帮助,因为这意味着您必须在标准输出上并排打印这些三角形。它只能逐行打印,而且非常简单。这是一种不涉及任何严肃数学的幼稚方法。

      rows = int(input())
      p = 2 * rows *(rows - 1)  # Variable to print the left most spaces
      x = " "
      for i in range(rows):  # For every row
          space = 2 * (rows - 1)  # Space variable to print spaces after an asterisk when needed
          for j in range(rows):  # For every row inside the row
              print(p * x, end="")  # print the left most spaces
              for k in range(2*(i + 1) - 1): 
                  print((2*(j + 1) - 1) * "*", end = "")  # Print the asterisk(s) based on the row number
                  print(space * x, end = "")  # Print spaces(s) after the asterisk(s)
              space -= 2  # Decrement the number of spaces to be printed after an asterisk for every row
              p -= 1  # Every row has one lesser space on the left
              print()  # Print a new line after every row
          p -= (rows - 1)  # Update the number of spaces to be printed on the left most side for every outer row
      

      请通过上面的 cmets 了解详细信息。输出:

      n = 4

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

      n = 5

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

      等等。如前所述,这是一种幼稚的直觉方法。

      【讨论】:

        【解决方案5】:

        这就是我认为这个练习试图教给你的东西。

        让我们来看看你的三角码(它根本没有什么问题):

        size = int(input())
        
        for i in range(size):
            for j in range(i, size):
                print(" ", end = "")
            for j in range(i):
                print("*", end = "")
            for j in range(i + 1):
                print("*", end = "")
            print()
        

        并将其转换为返回行/行列表的函数:

        def triangle(size):
            rows = []
            for i in range(size):
                row = []
                for j in range(i + 1, size):
                    row.append(" ")
                for j in range(2 * i + 1):    # i + (i+1) = 2*i+1.
                    row.append("*")
                for j in range(i + 1, size):  # Let's add spaces at the end, too.
                    row.append(" ")           # It'll make sense in a moment!
                rows.append("".join(row))
            return rows
        
        for row in triangle(5):
            print(row)
        
        #     *
        #    ***
        #   *****
        #  *******
        # *********
        

        现在我们可以稍微调整一下以使用任何矩形字符串列表“构建块”而不是*

        def triangle(size, block):
            rows = []
            for i in range(size):
                strip = [[] for _ in block]
                for j in range(i + 1, size):
                    for s, b in zip(strip, block):
                        s.append(" " * len(b))     # Space as wide as the building block
                for j in range(2 * i + 1):
                    for s, b in zip(strip, block):
                        s.append(b)
                for j in range(i + 1, size):
                    for s, b in zip(strip, block):
                        s.append(" " * len(b))
                for s in strip:
                    rows.append("".join(s))
            return rows
        
        
        # Make a triangle out of ["abc",
        #                         "def"]:
        
        for row in triangle(3, ["abc", "def"]):
            print(row)
        
        #       abc
        #       def
        #    abcabcabc
        #    defdefdef
        # abcabcabcabcabc
        # defdefdefdefdef
        

        这是一个有点棘手的代码!尝试在此代码中添加一些 print() 语句,看看它是如何工作的。 zip() 并行循环两个列表。实际上,您应该尝试自己从头开始重写此函数。

        回报非常令人满意:?

        fractal = triangle(4, triangle(4, ["*"]))
        
        for row in fractal:
            print(row)
        
        #                         *
        #                        ***
        #                       *****
        #                      *******
        #                  *      *      *
        #                 ***    ***    ***
        #                *****  *****  *****
        #               *********************
        #           *      *      *      *      *
        #          ***    ***    ***    ***    ***
        #         *****  *****  *****  *****  *****
        #        ***********************************
        #    *      *      *      *      *      *      *
        #   ***    ***    ***    ***    ***    ***    ***
        #  *****  *****  *****  *****  *****  *****  *****
        # *************************************************
        

        当然你现在也可以创建一个“三角形的三角形”:

        for row in triangle(2, triangle(2, triangle(2, ["()"]))):
            print(row)
        
        #                           ()
        #                         ()()()
        #                     ()    ()    ()
        #                   ()()()()()()()()()
        #         ()                ()                ()
        #       ()()()            ()()()            ()()()
        #   ()    ()    ()    ()    ()    ()    ()    ()    ()
        # ()()()()()()()()()()()()()()()()()()()()()()()()()()()
        

        这里的教训是概括一个问题:从表面上看,很难制作一个由三角形组成的三角形。但是用 whatever 制作一个三角形相对容易。

        如果我们编写一些代码可以用任何东西制作三角形(例如我们的abc def 示例),我们可以使用该代码用三角形制作三角形。

        与其他答案不同,我们不需要为这里的两层“三角形”提供单独的逻辑。

        【讨论】:

          【解决方案6】:

          已经有很多有趣的答案,但我想我应该添加一个让 Python 处理字符串居中的问题。

          def print_fractal(n, char='*'):
              # Width of single triangle
              base = 2*n - 1
              
              # Width of overall figure
              width = base**2
              
              # Lines containing single triangle padded to rectangle of width `base`
              lines = [f'{(2*line + 1)*char:^{base}}' for line in range(n)]
              
              for row in range(n):
                  # Print (2*row + 1) triangle blocks next to each other
                  for line in lines:
                      print(f'{(2*row + 1)*line:^{width}}')
          
          >>> print_fractal(3)
                      *            
                     ***           
                    *****          
                 *    *    *       
                ***  ***  ***      
               ***************     
            *    *    *    *    *  
           ***  ***  ***  ***  *** 
          *************************
          

          得益于@Lynn's answer 的启发,递归解决方案也可以自行解决:

          def make_fractal(n, depth, block=['*']):
              if not depth:
                  return block
              
              width = (2*n - 1)*max(map(len, block))
              
              lines = []
              
              for row in range(n):
                  for line in block:
                      lines.append(f'{(2*row + 1)*line:^{width}}')
              
              return make_fractal(n, depth - 1, lines)
          
          >>> for line in make_fractal(3, 2): print(line)
                      *            
                     ***           
                    *****          
                 *    *    *       
                ***  ***  ***      
               ***************     
            *    *    *    *    *  
           ***  ***  ***  ***  *** 
          *************************
          >>> for line in make_fractal(2, 3): print(line)
                       *             
                      ***            
                    *  *  *          
                   *********         
              *        *        *    
             ***      ***      ***   
           *  *  *  *  *  *  *  *  * 
          ***************************
          >>> for line in make_fractal(2, 2, [' . ', '---']): print(line)
                       .             
                      ---            
                    .  .  .          
                   ---------         
              .        .        .    
             ---      ---      ---   
           .  .  .  .  .  .  .  .  . 
          ---------------------------
          

          【讨论】:

          • *char:^{base}} 中的:^ 是什么?
          • @AyushGupta 冒号表示格式化选项的开始(您可以在其中设置有效数字等内容)。插入符号告诉 Python 通过在字符串两边填充空格来使字符串居中,直到达到所需的长度(由以下整数(在本例中为基数)给出)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-20
          相关资源
          最近更新 更多