1
\$\begingroup\$

Context:

Write a program to print the output for the given input(Example is given in comments of my code). String is of odd length.

I would be grateful if anyone could give feedback on my following code. The code runs correctly but I want to know if there can be any potential improvements in terms of code style and optimization.

 s=input("enter string")

#take s="12345"  for example
#output should be:
# 1   5 
#  2 4
#   3
#  2 4
# 1   5
for i in range(0,len(s)): # loop runs 5 times from  index 0 to index 4
    if i==((len(s)-1)//2):  #first condition prints the center of pattern
      print(" "*i,s[i])     #leading 2 spaces print 3
    elif i>(len(s)-1)//2:   # second condition prints the characters above the center 3
        print(" "*(len(s)-1-i),s[len(s)-i-1]," "*(i-(len(s)-i)-1)+s[i])
        # 1   5
        #  2 4
        #   3
    else:
     print(" "*i,s[i]," "*(len(s)-(2*(i+1))-1)+s[len(s)-i-1]) # else statement prints characters below the center
     # in reversed order
     #   3
     #  2 4
     # 1   5
\$\endgroup\$
5
  • \$\begingroup\$ Just a thought, this might make for simpler code: Iterate from both sides of the array at the same time. "left" indexes from 0 to 4 and "right" indexes 4 to 0. No fancy arithmetic. Just iterate, and print both values with appropriate spaces \$\endgroup\$
    – radarbob
    Commented Aug 28 at 18:41
  • \$\begingroup\$ Should the code work with the input of say 11 or 101? If not, you can build the X by mutating a list. \$\endgroup\$
    – Peilonrayz
    Commented Aug 28 at 18:45
  • \$\begingroup\$ There may be a special case when both "left" & "right" are at the same index. The value should be printed only once. \$\endgroup\$
    – radarbob
    Commented Aug 28 at 18:48
  • \$\begingroup\$ I did not get the last part . Could you please tell what you mean by special case? \$\endgroup\$
    – Silah
    Commented Aug 29 at 2:40
  • \$\begingroup\$ Are you talking about the center of X shape because the first condition deals with that special case. And any odd length string works as expected \$\endgroup\$
    – Silah
    Commented Aug 29 at 2:42

2 Answers 2

2
\$\begingroup\$

Writing index-conditional statements on the inside of a loop is a code smell. Instead you should prefer "looping like a native" making appropriate use of enumerate and zip.

You can also replace the string-multiply approach with formatting widths:

def print_x(s: str) -> None:
    n = len(s)

    # Converging (top half)
    forward = s[:n//2]
    reverse = s[-1: (-1 - n)//2: -1]
    for i, (char1, char2) in enumerate(zip(forward, reverse)):
        print(f'{char1:>{i + 1}}{char2:>{n - 2*i - 1}}')

    # Middle, single-character case
    if n % 2 == 1:
        print(f'{s[n//2]:>{1 + n//2}}')

    # Diverging (bottom half)
    reverse = s[-n//2 - 1: -1 - n: -1]
    forward = s[(n + 1)//2:]
    for i, (char1, char2) in enumerate(zip(reverse, forward)):
        print(f'{char1:>{n//2 - i}}{char2:>{(n - 1)//2 + 2*i}}')
\$\endgroup\$
2
  • \$\begingroup\$ I understand about the string formatting but did not get how index conditionals inside of loop can be a problem . Could you please explain a little or suggest resources where I can get a clearer understanding about code smell in general . Just a beginner right now . \$\endgroup\$
    – Silah
    Commented Aug 29 at 15:27
  • \$\begingroup\$ Thank you . I just gave it a read , got to know how using the approach I took can make my code more hard coded and less of something modular. It really doesn’t look quite right after you pointed out ,and discovered that python already has methods for characters’ alignment. Have a lot to improve on \$\endgroup\$
    – Silah
    Commented Aug 29 at 15:53
4
\$\begingroup\$

A big change would be to improve the readability of the program.

Some changes I would make are:

  • Add spacing between operators and make bracket style consistent (e.g. ((len(s)-1)//2) vs (len(s)-1)//2).
  • Convert calculations that are done multiple times (e.g. mid and size) into variables.
  • Break down the large print statements into smaller and more readable sections; just making the code more verbose.
input_string = input("Enter string: ")
size = len(input_string)
mid = size // 2

for i in range(size):
    if i == mid:
        print(' ' * i + input_string[i])
        
    elif i > mid:
        left_space = ' ' * (size - 1 - i)
        middle_space = ' ' * (2 * i - size + 1)
        print(f"{left_space}{input_string[size-i-1]}{middle_space}{input_string[i]}")
        
    else:
        left_space = ' ' * i
        middle_space = ' ' * (size - 2 * i - 2)
        print(f"{left_space}{input_string[i]}{middle_space}{input_string[size-i-1]}")
    
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Thank you . I am working on my code style and readability and your feedback helped . \$\endgroup\$
    – Silah
    Commented Aug 28 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.