-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.

5
  • 12
    this code scares me!! Commented Sep 12, 2011 at 4:42
  • Don't think that particular previous question is actually a good duplicate, phooji. Commented Sep 12, 2011 at 4:52
  • @asmith: I've marked your question as a duplicate of an older stackoverflow question. In addition, your asking many questions that are very similar in nature; this is discouraged (blog.stackoverflow.com/2009/04/a-day-in-the-penalty-box ). Commented Sep 12, 2011 at 4:54
  • @Amber: You're right stackoverflow.com/questions/2623470/… probably closer. Note that OP's other questions are very similar. Commented Sep 12, 2011 at 4:59
  • Stop asking the same question over and over. Commented Sep 12, 2011 at 12:26

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

maybe using bisect (docs.python.org/library/bisect.html#other-examples) is an even better option here
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.
symbols, cutoffs = zip(*symbol_set)
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).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.