6

So I want to know, is there any simple code for making an Hour Glass pattern with odd or even input using Java or Python? Because my code is not simple (I'm using Python).

Here's the output example:

Expected Output

And then, here is my code:

def evenGlassHour(target):
 jsp=1
 jtop=target
 jbot=2
 jbotspace=int(target/2)
 eventarget=int(target/2)
 temp=""
 for i in range(eventarget):
     for j in range(i):
         temp+=" "
     for jsp in range(jtop):
         temp+="@"
     jtop-=2
     temp+="\n"
 for i in range(eventarget-1):
     for j in range(jbotspace-2):
         temp+=" "
     for j in range(jbot+2):
         temp+="@"
     jbot+=2
     jbotspace-=1
     temp+="\n"

 print(temp)

def oddGlassHour(target):
 jsp=1
 jtop=target
 jbot=1
 jbotspace=int(target/2)
 oddtarget=int(target/2)
 temp=""
 for i in range(oddtarget):
     for j in range(i):
         temp+=" "
     for jsp in range(jtop):
         temp+="@"
     jtop-=2
     temp+="\n"
 for i in range(oddtarget+1):
     for j in range(jbotspace):
         temp+=" "
     for j in range(jbot):
         temp+="@"
     jbot+=2
     jbotspace-=1
     temp+="\n"

 print(temp)

target=int(input("Input : "))

if(target%2==0):
 evenGlassHour(target)
else:
 oddGlassHour(target)

And this is the result from my code:

 Input : 6
 @@@@@@
  @@@@
   @@
  @@@@
 @@@@@@

 Input : 7
 @@@@@@@
  @@@@@
   @@@
    @
   @@@
  @@@@@
 @@@@@@@
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Adji
  • 89
  • 1
  • 9

4 Answers4

1

In java you can write something like below:

public static void printPattern(int size) {
    int n = size; 
    boolean upper = true;
    for(int i = 0; size%2 == 0? i< size-1 : i<size; i++){            
        String str = String.join("", Collections.nCopies(n, "@"));
        String pad = String.join("", Collections.nCopies((size-n)/2 , " "));
        System.out.println(pad+str+pad);
        if(n-2>0 && upper){
            n-=2;
        }
        else {
            n+=2;
            upper = false;
        }           
    }
}
Eritrean
  • 15,851
  • 3
  • 22
  • 28
1

You can use string formatting with str.zfill and recursion:

def _glass(_input, _original, flag=True):
  if _input in {1, 2}:
    return ('00' if _input == 2 else '0').center(_original) if flag else ''
  if flag:
    return ('0'*(_input)).center(_original)+'\n'+_glass(_input-2, _original, flag=flag)
  return _glass(_input-2, _original, flag=flag)+'\n'+('0'*(_input)).center(_original)

def print_glasses(_input):
  print(_glass(_input, _input)+_glass(_input, _input, False))

for i in range(3, 8):
  print_glasses(i)
  print('-'*20)

Output:

000
 0 
000
--------------------
0000
 00 
0000
--------------------
00000
 000 
  0  
 000 
00000
--------------------
000000
 0000 
  00  
 0000 
000000
--------------------
0000000
 00000 
  000  
   0   
  000  
 00000 
0000000
--------------------
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
1

Use center-justication string formatting

inspiration: https://stackoverflow.com/a/44781576

def render(size):
    char = "*"
    #build a center-justified format mask
    mask = '{:^%ds}' % (size)

    print("size:%s:\n" % (size))

    #count down your shrinking
    for i in range(size, 0, -2):
        print(mask.format(char * i))

    #trickier:  you've already printed the narrowest
    #and your next line is different depending on odd/even input 
    if size % 2:
        start = 3
    else:
        start = 4

    for i in range(start, size+1, 2):
        print(mask.format(char * i))
    print()


render(3)
render(5)
render(12)

outputs:

size:3:

***
 *
***

size:5:

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

size:12:

************
 **********
  ********
   ******
    ****
     **
    ****
   ******
  ********
 **********
************
JL Peyret
  • 10,917
  • 2
  • 54
  • 73
0

In Python, you can take advantage of the fact that you can multiply a string by x and get the string concatenated with itself x times, like:

"test" * 3 # becomes testtesttest

Further you can use the same function for top and bottom of the hourglass, by using different values for range:

def evenGlassHour(target, direction = 1):
    for i in range(target, 1, -2) if direction == 1 else range(4, target+1, 2):
        pad = int((target - i) / 2)
        print((" " * pad) + "@" * i + " " * pad)
    if direction == 1:
        evenGlassHour(target, -1)

def oddGlassHour(target, direction = 1):
    for i in range(target, 1, -2) if direction == 1 else range(1, target+1, 2):
        pad = int((target - i) / 2)
        print((" " * pad) + "@" * i + " " * pad)
    if direction == 1:
        oddGlassHour(target, -1)

target=int(input("Input : "))

if target % 2 == 0:
    evenGlassHour(target)
else:
    oddGlassHour(target)

EDIT: You can even remove the recursive-call, and just chain the two ranges together, making the function even smaller:

from itertools import chain

def evenGlassHour(target):
    for i in chain(range(target, 1, -2), range(4, target+1, 2)):
        pad = int((target - i) / 2)
        print((" " * pad) + "@" * i + " " * pad)

Finally, you can make the functions accept the desired symbol to be printed (of any length), like this:

def evenGlassHour(target, symbol = "@"):
    for i in chain(range(target, 1, -2), range(4, target+1, 2)):
        pad = int((target - i) / 2) * len(symbol)
        print((" " * pad) + symbol * i + " " * pad)

You can also combine the two functions, to make it even more ridiculous:

from itertools import chain
def glassHour(t, s = "@"):
    for i in chain(range(t, 1, -2), range((4 if t % 2 == 0 else 1), t+1, 2)): 
        print((" " * (int((t - i) / 2)*len(s)) + s * i + " " * (int((t - i) / 2)*len(s))))

target=int(input("Input : "))
glassHour(target, "$$")
Jeppe
  • 1,830
  • 3
  • 24
  • 33