@Mufeed's answer is excellent, and well suited for beginners. This answer is a bit more complex.
One thing I would suggest is to write your letters using Python's multi-line strings. It makes them much easier to edit. My letters are a bit bigger and I've only defined the three letters b, g, and i (using artist mode in emacs..):
letter_definitions = {
'b': Letter("""
****************
******************
***** *****
*** ***
*** ****
*** ****
*** ******
******************
*********************
*** * *****
*** ******
*** *****
*** ****
*** ****
*** ****
*** ****
*** **********
*********************
*****************
"""),
'g': Letter("""
****************
*** * **** **
*** *****
****
****
*****
****
****
**** ************
**** *************
***** *
***** *
***** **
****** *
******* **
********* *****
*************
"""),
'i': Letter("""
+---+
|***|
+---+
+-+
|*|
|*|
|*|
|*|
|*|
|*|
+-+
"""),
}
The Letter
class stores the shape, and records height/width/baseline (__init__
method), and can write itself to a 2-dimensional buffer (the add_to_buffer()
method):
import textwrap
class Letter(object):
def __init__(self, shape):
# remove space to the left (textwrap.dedent)
# and split the shape string into lines (self.shape is a list of strings)
self.shape = textwrap.dedent(shape).split('\n')
# remove any initial empty lines
while self.shape[0] == '':
self.shape = self.shape[1:]
# remove any trailing empty lines
while self.shape[-1] == '':
self.shape = self.shape[:-1]
self.height = len(self.shape)
self.width = max(len(line) for line in self.shape)
# we're doing the easy case where all letters are capitals
# and the baseline is at the bottom
self.baseline = self.height
def add_to_buffer(self, buffer, x, y):
"Write this letter shape to a 2-dimensional buffer at position x, y."
# justify our baseline with the buffer's baseline
y += buffer.baseline - self.baseline
# keeping track of which line and character we're at,
# we go through each line in the shape
for lineno, line in enumerate(self.shape):
# .. and each character in the line
for charpos, ch in enumerate(line):
# and put the character into the buffer
buffer[x + charpos, y + lineno] = ch
The buffer is implemented in the TextLine
class, which creates a (simulated) 2 dimensional buffer of sufficient size to hold all the letter shapes by asking each letter how tall/wide it is:
class TextLine(object):
def __init__(self, letters):
self.letters = letters
self.width = sum(letter.width for letter in self.letters)
# one space between each letter, except the last one
self.width += len(self.letters) - 1
self.height = max(letter.height for letter in self.letters)
self.baseline = self.height
# add letters to buffer
self.buffer = [' '] * (self.width * self.height) # should probably use a buffer.buffer here..
x = 0
for letter in self.letters:
letter.add_to_buffer(self, x, 0)
x += letter.width + 1
def __setitem__(self, (x, y), ch):
# calculate the position and assign the character
self.buffer[y * self.width + x] = ch
def __str__(self):
chunks = []
# divide the buffer into pieces/chunks of length self.width..
# (see https://stackoverflow.com/a/312464/75103 for how this works)
for i in range(0, len(self.buffer), self.width):
chunk = self.buffer[i:i + self.width]
chunks.append(''.join(chunk))
# .. and start each chunk on a new line
return '\n'.join(chunks)
Finally I've renamed the print_big()
function to big_text()
and it returns the string to print:
def big_text(text):
lines = text.splitlines(False) # don't keep newlines
res = []
for line in lines:
# convert each character to the corresponding Letter
letters = [letter_definitions[ch] for ch in line]
# put the letters into a TextLine
text_line = TextLine(letters)
# and append the buffer to the result
res.append(str(text_line))
return '\n\n'.join(res)
quite often you'll need to re-use functions like these, and it's easier to reuse them if they return the string rather than print it, and you can use it just as easy for printing:
print big_text('big')
The result:
****************
******************
***** ***** ****************
*** *** *** * **** **
*** **** *** *****
*** **** ****
*** ****** ****
****************** +---+ *****
********************* |***| ****
*** * ***** +---+ ****
*** ****** **** ************
*** ***** +-+ **** *************
*** **** |*| ***** *
*** **** |*| ***** *
*** **** |*| ***** **
*** **** |*| ****** *
*** ********** |*| ******* **
********************* |*| ********* *****
***************** +-+ *************