-3

Possible Duplicate:
Overriding the newline generation behaviour of Python's print statement
PPM image to ASCII art in Python

This is my code, I have the characters printing but I need them to be on the same line and break at the end of the line.

import sys

def main(filename):
    image = open(filename)
    #reads through the first three lines
    color = image.readline().splitlines()
    size_width, size_height = image.readline().split()
    max_color = image.readline().splitlines()

    #reads the body of the file
    pixels = image.read().split()
    red = 0
    green = 0
    blue = 0
    r_g_b_value = []
    #pulls out the values of each tuple and coverts it to its grayscale value 
    for i in pixels:
      if i !=  "\n" or " ":
        if len(i) == 3:
            red = int(i[0]) * .3
            green = int(i[1]) * .59
            blue = int(i[2]) * .11
        elif len(i) == 2:
            red == int(i[0])
            green == int(i[1])
            blue == 0
        elif len(i) == 1:
            red == int(i[0])
            green == 0
            blue == 0

        r_g_b_value = [red + green + blue]
        grayscale = []
        character = []

        for j in r_g_b_value:
            if int(j) <= .2:
                character = "M"
            elif int(j) > .2 and int(j) <= .4:
                character = "#"
            elif int(j) > .4 and int(j) <= .6:
                character = "A"
            elif int(j) > .6 and int(j) <= .8:
                character = "@"
            elif int(j) > .8 and int(j) <= 1:
                character = "$"
            elif int(j) > 1 and int(j) <= 1.2:
                character = "0"
            elif int(j) > 1.2 and int(j) <= 1.4:
                character = "e"
            elif int(j) > 1.4 and int(j) <= 1.6:
                character = "a"
            elif int(j) > 1.8 and int(j) <= 2:
                character = "o"
            elif int(j) > 2 and int(j) <= 2.2:
                character = "="
            elif int(j) > 2.25 and int(j) <= 2.5:
                character = "+"
            elif int(j) > 2.5 and int(j) <= 2.75:
                character = ";"
            elif int(j) > 2.75 and int(j) <= 3:
                character = ":"
            elif int(j) > 3 and int(j) <= 3.4:
                character = ","
            elif int(j) > 3.4 and int(j) <= 3.9:
                character = "."
            else:
                character = " "
            character += character
            grayscale = [character]
            print(grayscale)

Any help would be appreciated.

Community
  • 1
  • 1
asmith
  • 69
  • 1
  • 1
  • 5

1 Answers1

3

Specify the end parameter for print() to be an empty string, and it won't automatically add a newline:

>>> print('foo', end=''); print('bar'); print('baz')
foobar
baz

The default value for end is '\n'; end is added after all of the regular arguments passed to print() have been output. For instance, print('foo', 'bar'); print('baz') would output the same as above.

There is also the sep parameter which is added in between each of the objects being printed, a la join(). It defaults to nothing.


By the way, you can rewrite the entire block below:

    for j in r_g_b_value:
        if int(j) <= .2:
            character = "M"
        elif int(j) > .2 and int(j) <= .4:
            character = "#"
        elif int(j) > .4 and int(j) <= .6:
            character = "A"
        elif int(j) > .6 and int(j) <= .8:
            character = "@"
        elif int(j) > .8 and int(j) <= 1:
            character = "$"
        elif int(j) > 1 and int(j) <= 1.2:
            character = "0"
        elif int(j) > 1.2 and int(j) <= 1.4:
            character = "e"
        elif int(j) > 1.4 and int(j) <= 1.6:
            character = "a"
        elif int(j) > 1.8 and int(j) <= 2:
            character = "o"
        elif int(j) > 2 and int(j) <= 2.2:
            character = "="
        elif int(j) > 2.25 and int(j) <= 2.5:
            character = "+"
        elif int(j) > 2.5 and int(j) <= 2.75:
            character = ";"
        elif int(j) > 2.75 and int(j) <= 3:
            character = ":"
        elif int(j) > 3 and int(j) <= 3.4:
            character = ","
        elif int(j) > 3.4 and int(j) <= 3.9:
            character = "."
        else:
            character = " "

with this much simpler code:

# Mapping of values to symbol tuples, ordered from least to greatest upper bound.
# Format is (symbol, upperbound) - lower bounds are implied by
# the previous symbol's upper bound, non-inclusive.
symbol_set = [('M', 0.2), ('#', 0.4), ('A', 0.6), ('@', 0.8), ('$', 1.0),
    ('0', 1.2), ('e', 1.4), ('a', 1.6), ('o', 2.0), ('=', 2.2), ('+', 2.5),
    (';', 2.75), (':', 3.0), (',', 3.4), ('.', 3.9)]

for j in r_g_b_value:
    for symbol, cutoff in symbol_set:
        if j <= cutoff:
            character = symbol
            break
    else:
        character = ' '

(The for: else: construction just means that "if there was never a break triggered in the loop, do what's in the else: section. It handles your 'else' case from the old code.)

You should always endeavor to let the computer do the work for you - instead of writing out 10-15 nearly identical elif clauses, use a little bit of cleverness to make it work with a loop instead.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • maybe using `bisect` (http://docs.python.org/library/bisect.html#other-examples) is an even better option here – Yannick Loiseau Sep 12 '11 at 11:45
  • Yes, `bisect` would be an even more succinct way of writing the loop - the downside is that it requires a different format for the symbol set (separate arrays of cutoffs and things that indices should map to). You could generate those two lists from the list format I used above (`symbols = [x[0] for x in symbol_set]`, `cutoffs = [x[1] for x in symbol_set]`), but it'd be about as much work either way. Really just comes down to how you prefer to specify your data. – Amber Sep 12 '11 at 11:59
  • `symbols, cutoffs = zip(*symbol_set)` – Yannick Loiseau Sep 12 '11 at 12:07
  • Good call. ;) Why do I always seem to forget how useful `zip()` always is, even after I've used it in the past 24 hours? However, I'm going to leave the answer as it is w/o bisect because I think writing it out a little better gets across how things are being automated (relative to the `elif` stack). – Amber Sep 12 '11 at 12:20