Try to print frame '*' and diagonal in python

Question:

I try to print ‘*’ in frame and in diagonal .

This is what I did:

x=10
y=10
def print_frame(n, m, c):
  print c * m
  for i in range(1, n - 1):
    print c ,' '*(n-2-i),c, ' '*i , c  , c
  print c * m

print_frame(10, 10, '*')

This is the result:

**********
*         *   * *
*        *    * *
*       *     * *
*      *      * *
*     *       * *
*    *        * *
*   *         * *
*  *          * *
**********
Asked By: learn

||

Answers:

As I specified in my comment, only square matrices have diagonals. But even for those, things are “a bit” more complex than they seem:

  • I could have done it in a single loop, but I think it’s better to see all the “sections”
  • The (string) calculations could have been written in a more compact way, but I left them as they are for clarity
  • Also added the recursive variant. I prefer this one as it’s clearer (although in general, recursion has limitations), especially since given the nature of the problem, the recursion doesn’t go deep enough in order to generate StackOverflow, or to have a negative effect on performance
  • Instead of printing the string inside the function, I “return” them. That is an optimization technique: if they are needed in more than one place, the function only needs to be called once
  • The functions are generators (yield instead of return). That is also an optimization (and it’s Pythonic)

code01.py:

#!/usr/bin/env python3

import sys


def square_frame_iterative(side, char="*"):
    yield char * side  # Upper row
    for i in range(1, side - 1):
        edge_space = min(i - 1, side - 2 - i)
        mid_space = side - 2 * edge_space - 4
        mid_text = char if mid_space < 0 else char + " " * mid_space + char
        yield char + " " * edge_space + mid_text + " " * edge_space + char
    yield char * side  # Lower row


# Recursion
def _square_frame_recursive(side, char, i):
    if i == side // 2 - 1:
        if side % 2 :
            yield char + " " * ((side - 3) // 2) + char + " " * ((side - 3) // 2) + char  # Mid row
    else:
        s = char + " " * i + char + " " * (side - 2 * i - 4) + char + " " * i + char
        yield s
        yield from _square_frame_recursive(side, char, i + 1)
        yield s


def square_frame_recursive(side, char="*"):
    yield char * side  # Upper row
    if side <= 1:
        return
    yield from _square_frame_recursive(side, char, 0)
    yield char * side  # Lower row

# Recursion end


def main(argv):
    dim = 10
    square_frame_func = square_frame_iterative
    if argv:
        if argv[0].isdigit():
            dim = int(argv[0])
        if (len(argv) > 1) and argv[1].lower().startswith("rec"):
            square_frame_func = square_frame_recursive
    frame_string = "n".join(square_frame_func(dim))
    print(frame_string)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}n".format(" ".join(item.strip() for item in sys.version.split("n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(sys.argv[1:])
    print("nDone.")

Output:

[cfati@CFATI-5510-0:e:WorkDevStackOverflowq055342983]> "e:WorkDevVEnvspy_064_03.07.03_test0Scriptspython.exe" code01.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

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

Done.

[cfati@CFATI-5510-0:e:WorkDevStackOverflowq055342983]> "e:WorkDevVEnvspy_064_03.07.03_test0Scriptspython.exe" code01.py 7 rec
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

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

Done.
Answered By: CristiFati
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.