2

I'm making a program which takes a file with an ASCII art alphabet and uses it to print words. It takes 3 lines of input The width, The Height and The desired word. My problem is that I can make the characters print on the same line, they print one after the other like so:

Height: 8
Width: 9
Text: TOP
_________
\__   __/
   ) (   
   | |   
   | |   
   | |   
   | |   
   )_(   
 _______ 
(  ___  )
| (   ) |
| |   | |
| |   | |
| |   | |
| (___) |
(_______)
 _______ 
(  ____ )
| (    )|
| (____)|
|  _____)
| (      
| )      
|/       

This is my code:

temp = []
hi = input('Height: ')
wi = input('Width: ')
tx = input('Text: ')
fi = open("font.txt")
for i in tx:
  temp = cd[i]
  var1 = int(temp[0])
  ra1 = (var1 * int(hi))
  ra1n = (ra1 + int(hi))
  temp = []
  fi = open("font.txt")
  lines = fi.readlines()
  print(''.join(lines[ra1:ra1n]),end='')

font.txt looks like this

 _______ 
(  ___  )
| (   ) |
| (___) |
|  ___  |
| (   ) |
| )   ( |
|/     \|
 ______  
(  ___ \ 
| (   ) )
| (__/ / 
|  __ (  
| (  \ \ 
| )___) )
|/ \___/ 
 _______ 
(  ____ \
| (    \/
| |      
| |      
| |      
| (____/\
(_______/
 ______  
(  __  \ 
| (  \  )
| |   ) |
| |   | |
| |   ) |
| (__/  )
(______/ 
 _______ 
(  ____ \
| (    \/
| (__    
|  __)   
| (      
| (____/\
(_______/
 _______ 
(  ____ \
| (    \/
| (__    
|  __)   
| (      
| )      
|/       
 _______ 
(  ____ \
| (    \/
| |      
| | ____ 
| | \_  )
| (___) |
(_______)

|\     /|
| )   ( |
| (___) |
|  ___  |
| (   ) |
| )   ( |
|/     \|
_________
\__   __/
   ) (   
   | |   
   | |   
   | |   
___) (___
\_______/
_________
\__    _/
   )  (  
   |  |  
   |  |  
   |  |  
|\_)  )  
(____/   
 _       
| \    /\
|  \  / /
|  (_/ / 
|   _ (  
|  ( \ \ 
|  /  \ \
|_/    \/
 _       
( \      
| (      
| |      
| |      
| |      
| (____/\
(_______/
 _______ 
(       )
| () () |
| || || |
| |(_)| |
| |   | |
| )   ( |
|/     \|
 _       
( (    /|
|  \  ( |
|   \ | |
| (\ \) |
| | \   |
| )  \  |
|/    )_)
 _______ 
(  ___  )
| (   ) |
| |   | |
| |   | |
| |   | |
| (___) |
(_______)
 _______ 
(  ____ )
| (    )|
| (____)|
|  _____)
| (      
| )      
|/       
 _______ 
(  ___  )
| (   ) |
| |   | |
| |   | |
| | /\| |
| (_\ \ |
(____\/_)
 _______ 
(  ____ )
| (    )|
| (____)|
|     __)
| (\ (   
| ) \ \__
|/   \__/
 _______ 
(  ____ \
| (    \/
| (_____ 
(_____  )
      ) |
/\____) |
\_______)
_________
\__   __/
   ) (   
   | |   
   | |   
   | |   
   | |   
   )_(   

|\     /|
| )   ( |
| |   | |
| |   | |
| |   | |
| (___) |
(_______)

|\     /|
| )   ( |
| |   | |
( (   ) )
 \ \_/ / 
  \   /  
   \_/   

|\     /|
| )   ( |
| | _ | |
| |( )| |
| || || |
| () () |
(_______)

|\     /|
( \   / )
 \ (_) / 
  ) _ (  
 / ( ) \ 
( /   \ )
|/     \|

|\     /|
( \   / )
 \ (_) / 
  \   /  
   ) (   
   | |   
   \_/   
 _______ 
/ ___   )
\/   )  |
    /   )
   /   / 
  /   /  
 /   (_/\
(_______/
  • You need to adjust your thinking; you have to print line by line, not character by character. – jonrsharpe Sep 05 '15 at 16:51
  • I figured that but try as I might I can't think of a way to do it. Everything I've tried has been a garbled mess. –  Sep 05 '15 at 16:53
  • 1
    Instead of writing the first (nth) row of a single letter at a time, write the first (nth) row of every letter, separated by some spaces. Just make sure that your font defines all letters as the same width (for proper padding) and that you add, say, 5 spaces everywhere. – boxmein Sep 05 '15 at 16:57
  • Yes I tried that but it didn't end well. I'd appreciate a fresh view of the problem or even a solution before I head off to bed. –  Sep 05 '15 at 17:04
  • What's the format of the data in `font.txt`? What does `cd[i]` refer to? – martineau Sep 05 '15 at 17:14
  • cd is a dictionary of the alphabet (A,B,C) and each character's place in the file (line-wise) assuming length and width equal 1 –  Sep 05 '15 at 17:17
  • the file looks something like this –  Sep 05 '15 at 17:17
  • ` _______ ( ___ ) | ( ) | | (___) | | ___ | | ( ) | | ) ( | |/ \| ______ ( ___ \ | ( ) ) | (__/ / | __ ( | ( \ \ | )___) ) |/ \___/ _______ ( ____ \ | ( \/ | | | | | | | (____/\ (_______/ ______ ( __ \ | ( \ ) | | ) | | | | | | | ) | | (__/ ) (______/ ` –  Sep 05 '15 at 17:19

2 Answers2

1

If your font has been properly padded (all lines are the same length) then you can use a list of lists that represent a matrix of lines and characters; you only assemble this into output to print after processing all letters of your text:

hi = int(hi)
output = [[] for _ in range(hi)]
with open("font.txt") as fi:
    lines = fi.readlines()

for character in tx:
    offset = int(cd[character])
    start = offset * hi
    end = start + hi
    letter = lines[start:end]
    for outputline, letterline in zip(output, letter):
        outputline.append(letterline.rstrip('\n'))

for line in output:
    print(''.join(line))

Note that you need to remove the newlines included in the font file; the str.rstrip() call takes care of that.

Alternatively, you can remove all the newlines when reading the file:

with open("font.txt") as fi:
    lines = fi.read().splitlines()

If your font is not properly padded, you need to get the maximum width of any given character first and pad out the rest of the lines:

width = max(len(l) for l in lines[start:end])
letter = lines[start:end]
for outputline, letterline in zip(output, letter):
    outputline.append(letterline.rstrip('\n').ljust(width))
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • ♦ That is similar to what I tried but I'm not sure what is going on here `for outputline, letterline in zip(output, letter): outputline.append(letterline)` . I tried this however, the result was nearly identical to another attempt I had made the lines were printed one after the other rather than next to each other. –  Sep 05 '15 at 17:42
  • @user5303899: That pairs up the lists in the `output` list, with each line in the font. So the first line of the font letter with the first list in `output`, then the second, etc. – Martijn Pieters Sep 05 '15 at 17:46
  • @user5303899: So the first line of the letter T goes into the first list. So does the first line of the letter O, then the first line of P. When then printing those lines at the end (`for line in output`) you only print the first lines of the letters together. The same for the second lines, etc. – Martijn Pieters Sep 05 '15 at 17:47
  • It isn't quite working that way though. It prints the first line T on the first line of output and then the first letter of O on the next one. –  Sep 05 '15 at 17:51
  • @user5303899: ah, your lines have newlines included. Will update. – Martijn Pieters Sep 05 '15 at 17:52
  • 1
    @user5303899: done; the `str.rstrip()` call removes the newline included in your font file. – Martijn Pieters Sep 05 '15 at 17:53
  • Sorry but I've accidentally left some details out. 1: There can be no spaces between characters and 2: There needs to be a space so you can write words like TO DO properly. –  Sep 05 '15 at 18:51
  • 1
    @user5303899: I removed the space from the `''.join()` call. Doesn't your font include a space 'character' in the file? You could then produce a list off lines like `space = [' ' * int(wi) for _ in range(hi)]` and then use that instead of a character from `lines` every time you need to insert a space. – Martijn Pieters Sep 05 '15 at 19:47
  • The file is 26 lines (from 0) and has a space character but I will not print anything if I leave it as is –  Sep 05 '15 at 23:13
  • @user5303899 sounds like the space character is merely a set of blank lines then (no width, only height). – Martijn Pieters Sep 05 '15 at 23:15
  • Yeah one space is the maximum I've ever been able to get –  Sep 05 '15 at 23:18
  • I feel like with a few dodgy for loops I could get this working but I feels kind of wrong –  Sep 05 '15 at 23:19
  • You could fix the font; replace the lines that represent a space with lines that actually use spaces to create width. – Martijn Pieters Sep 05 '15 at 23:20
  • I'm not allowed to edit the file and the code will be used on multiple similar files with different fonts so I would have to change all of them as well. –  Sep 05 '15 at 23:23
  • 1
    @user5303899: you can do so *in Python*; alter the `lines` list, replace the parts that represent a space: `lines[spacestart:spaceend] = [' ' * width for _ in range(height)]`. – Martijn Pieters Sep 05 '15 at 23:25
1

Just saw this question a bit late. I happened to have done something similar so this might also be helpful:

import itertools

def load_font(font_filename, width, height):
    with open(font_filename, 'r') as figlet:
        return [map(lambda x: x.rstrip('\n').ljust(width+1), character) for character in iter(lambda: list(itertools.islice(figlet, height)), [])]

def figlet(font, text):
    for line in zip(*[font[ord(letter)-65] for letter in text]):
        print "".join(line)

font = load_font('file.txt', 8, 8)

figlet(font, "HELLO")
figlet(font, "WORLD")

This would display the following output:

          _______  _        _        _______ 
|\     /|(  ____ \( \      ( \      (  ___  )
| )   ( || (    \/| (      | (      | (   ) |
| (___) || (__    | |      | |      | |   | |
|  ___  ||  __)   | |      | |      | |   | |
| (   ) || (      | |      | |      | |   | |
| )   ( || (____/\| (____/\| (____/\| (___) |
|/     \|(_______/(_______/(_______/(_______)
          _______  _______  _        ______  
|\     /|(  ___  )(  ____ )( \      (  __  \ 
| )   ( || (   ) || (    )|| (      | (  \  )
| | _ | || |   | || (____)|| |      | |   ) |
| |( )| || |   | ||     __)| |      | |   | |
| || || || |   | || (\ (   | |      | |   ) |
| () () || (___) || ) \ \__| (____/\| (__/  )
(_______)(_______)|/   \__/(_______/(______/

The width parameter can also be used to add additional padding.

Martin Evans
  • 45,791
  • 17
  • 81
  • 97