I'm attempting to write a program that will take a word entered by the user and give a concatenation of the corresponding triple quote strings.

I've looked at http://www.daniweb.com/forums/thread189881.html, but didn't quite find the piece I'm missing.

The idea is fairly simple:

User inputs a word (or numbers)
Exchanges letters for corresponding "symbols" (for lack of a better term)
Outputs concatenated symbols

Here's how I've got it set up so far:

# Create a "normal" alphabet to compare it to

base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

FIVEHIGH = (
"""
X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X 
""",
"""
0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X
""",
"""
X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X
""")
# Cut for the sake of space

### PROGRAM START ###

cypher = string.maketrans(base, FIVEHIGH)

print "Welcome to the Word Converter!\n\n"

# OTHER DEFINITIONS

word = raw_input("What word should we convert?  ").upper()

# FEEDBACK

if word == "":
    print "No word entered"
else:
    print "Your word is",word
    word.translate(cypher)
    print word
    
raw_input("\nPress any key")

I've also toyed with dictionaries, but couldn't get them to work either. Any help would be greatly appreciated.

Recommended Answers

All 29 Replies

I've also toyed with dictionaries, but couldn't get them to work either. Any help would be greatly appreciated.

When "it doesn't work" in python, most of the time, there is an exception traceback (python complains). Here is what I get in my terminal when I try to run your program

[t215809] python cypher.py
Traceback (most recent call last):
  File "cypher.py", line 31, in <module>
    cypher = string.maketrans(base, FIVEHIGH)
NameError: name 'string' is not defined

Python tells us that when it reaches the line cypher = string.maketrans(base, FIVEHIGH) , it fails because you didn't say what the variable "string" is. When it doesn't work, you must study the traceback and understand what it means. Now your problem is to tell python what "string" is. After this problem, there are other problems waiting for you, with other tracebacks.
So, go one step after the other, and when you have a traceback, put it in your posts because it's very useful for helpers.

"".stringmethod() works if you need an empty string to use the string methods to.

word = raw_input("What word should we convert? ").upper()
word.translate(cypher)

If the first statement, you define 'word' as a string. In the second statement, it appears to be a class with the method "translate". You can not use the same variable name for two different types of memory.

Python tells us that when it reaches the line cypher = string.maketrans(base, FIVEHIGH) , it fails because you didn't say what the variable "string" is. When it doesn't work, you must study the traceback and understand what it means. Now your problem is to tell python what "string" is. After this problem, there are other problems waiting for you, with other tracebacks.
So, go one step after the other, and when you have a traceback, put it in your posts because it's very useful for helpers.

I apologize for not giving you guys more information. I forgot to mention that at the very beginning, I have:

import string

If the first statement, you define 'word' as a string. In the second statement, it appears to be a class with the method "translate". You can not use the same variable name for two different types of memory.

Thanks woooee. I went back, and fixed it to say string.translate(word,cypher).

With the changes I've made, here's what I've got:

import string

base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
FIVEHIGH = (
"""
X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X 
""",
"""
0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X
""",
"""
X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X
""")
#Goes through "Z," then 1-0

cypher = string.maketrans(base, FIVEHIGH)

print "Welcome to the Converter!\n\n"

word = raw_input("What word should we make?  ").upper()

# FEEDBACK

if word == "":
    print "No word entered"
else:
    print "Your word is",word
    string.translate(word,cypher)
    print word
    
raw_input("\nPress any key")

When run, I get the traceback:

cypher = string.maketrans(base, FIVEHIGH)
TypeError: maketrans() argument 2 must be string or read-only character buffer, not tuple

Now for my question: How would I make a string or read-only character buffer out of triple quoted strings?

Look at the documentation of maketrans. It can only replace a character by a single character. This means that you can't use maketrans and translate for your purpose. Here is how you could iterate over the characters

if word == "":
    print "No word entered"
else:
    print "Your word is",word
    for c in word:
        print(c)

Now, instead of printing the character, you must find the triple quoted string which corresponds to this character (if any). You should then put all these strings in a list and finally concatenate all the strings of the list.

Now, instead of printing the character, you must find the triple quoted string which corresponds to this character (if any). You should then put all these strings in a list and finally concatenate all the strings of the list.

Alright, I've got the strings concatenated (which took a while), but I'm still stuck with the question I started with:

How would I get the letters to know which triple quoted string corresponds to it?

You can create a dictionary to associate a string to each letter

translation = dict()
for i in range(len(base)):
    translation[base[i]] = FIVEHIGH[i]

and then use translation[c] to get the string corresponding to c. Post your new code when it's written.

Alright, now we're getting somewhere!

Here's a shorter version of the program with only the letters A, B, and C used (for easier testing and conversion of symbols list):

# DEFINE VARIABLES

base = "ABC"
FIVEHIGH = (
"""
X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X 
""" +
"""
0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X
""" +
"""
X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X
""")

translation = dict()
for l in range(len(base)):
    translation[base[l]] = FIVEHIGH[l]

#PROGRAM START

print "Welcome to the Converter!\n\n"

word = raw_input("What word should we make?  ").upper()

# FEEDBACK

if word == "":
    print "No word entered"
else:
    print "Your word is",word
    for c in word:
        print translation[c]
    
raw_input("\nPress any key")

I got pretty excited because I didn't get any errors, but then this is what happened:

Welcome to the Converter!


What word should we make?  cab
Your word is CAB
 


X

Press any key

What happened to my gorgeous, museum-worthy ASCII letters? I read over the code several times, and I just can't see where the rest of the strings got swallowed.


One other minor question. I understand very basically what the below code is doing, but how does it work in the background (or how would you say it in layman's terms)?

translation = dict()
for l in range(len(base)):
    translation[base[l]] = FIVEHIGH[l]

You must not add the triple quoted strings in FIVEHIGH.

Wait, I shouldn't use triple quoted strings as the desired output?

That's what my original question was asking:

How can I get an input of 'cab' to
X 0 X X X 0 X X 0 0 X X
0 X 0 X 0 X 0 X 0 X 0 X
0 X X X 0 0 0 X 0 0 X X
0 X 0 X 0 X 0 X 0 X 0 X
X 0 X X 0 X 0 X 0 0 X X

First, make a list with the strings which correspond to CAB, then think about how to produce your output with this list.

The only way I could come up with is to have the program print four letters (one row), and then start a new line. Print the next four, start a new line, etc.

The problem with that is they wouldn't form next to each other like a word, they would be stacked like the for c in word: print(c) did, wouldn't it?

To fix that, I would have to "scrape off" the top layer of each word, print it as a concatenation, then strip out the next line, print it, and so forth.

Is it possible to pull only part of a string, or would I have to make a list with five lines for each letter?

Well, even if I did that, how would I tell it where to find it's information? I don't think there's a fairly simple way to have it read 1.1, then skip to 2.1 five strings away, then come back to 1.2.

I'm afraid I have no idea where you're trying to lead me, Gribouillis.

Here is how we could do in pseudo-algorithmic language. Let's call the elements of FIVEHIGH "ideograms"

create an empty list L
for each character c in word:
    find the ideogram x corresponding to c
    append x to our list L
# now the problem is to display the result
# we display the 5 lines one after the other
for each i in 1, 2, 3, 4, 5:
    initialize the i-th line S to the empty string
    for each ideogram x in L:
        find the i-th line y of x # for example 2nd line of the first ideogram is 0 X 0 X
        concatenate y to S
    print S

Now, you write the python code for this strategy !

This may take me a bit, but I'll get on it!

I'm afraid I'm going to have to throw my hands up on this one. My brain is leaking out of my ears.

I get what we're trying to do, but I don't know how to tell the computer itself. I'm brand-spanking new to Python and can't find what I need in the documentation. find the ideogram x corresponding to c / append x to our list L I know what this means, but I can't for the life of me figure out how to do it. I'm trying to read Greek and speak Russian!

The biggest problem I'm having with it is that I can't figure out how to get the system to read them as a group of letters, rather than X's and 0's.

Wait, would I want to use a list and slice it? But then how would it know which position is correct?

I for one am not sure what you are trying to do. It is something like this? If not, please post some input and desired output examples. Also, if joining, remember that each triple quoted string is one string and not a list.

base_dict = {}
base_dict["A"] = """X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X"""

base_dict["B"] = """0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X"""

base_dict["C"] = """X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X
"""

for key in ("A", "B", "C"):
   print key, "-" *60
   print base_dict[key]

Woooee, I'm not sure how else to explain it. I laid out my thought process earlier, and don't know any other way to show it.

How can I get an input of 'cab' to
X 0 X X X 0 X X 0 0 X X
0 X 0 X 0 X 0 X 0 X 0 X
0 X X X 0 0 0 X 0 0 X X
0 X 0 X 0 X 0 X 0 X 0 X
X 0 X X 0 X 0 X 0 0 X X

I want the letters to be converted into the ascii "art" of letters. I'm trying to make a program to output a blueprint for making letters with cups in chain link fences.

Ok, here is a solution

base = "ABC"

FIVEHIGH = (
"""
X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X 
""",
"""
0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X
""",
"""
X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X
""")

class Ideogram(tuple):
    def __new__(cls, string):
        return tuple.__new__(cls, (y for y in (x.strip() for x in string.split("\n")) if y))
    def __init__(self, *args):
        assert(len(self) == 5)


base_dict = dict(zip(tuple(base), (Ideogram(x) for x in FIVEHIGH)))

def translate(word):
  lines = list(list() for i in range(5))
  for letter in (c for c in word.upper() if c in base_dict): # skip characters that dont belong to base
     for i, x in enumerate(base_dict[letter]):
        lines[i].append(x)
  return "\n".join(" ".join(L) for L in lines)

if __name__ == "__main__":
    word = raw_input("Enter word:")
    print translate(word)

My attempt. Once again, if not correct, post back with more info. The trick (I think) is to split each string on the "\n" to create individual rows, and is similiar to Gribouillis' solution but doesn't use list comprehension (which is an amazing tool). It instead uses a dictionary with row number as the key, in this case 0 through 4, and appends each row to the corresponding key. Finally, the joined rows are spaced and printed. Hopefully, using a dictionary with the row number is easy to understand.

def join_letters( letter_list, base_dict ):
   combined_rows_dict = {}

   ##---  base length to test for equality
   len_letter = len(base_dict[letter_list[0]])

   for j in range(0, len(letter_list)):
      this_letter = letter_list[j]

      ##--- all letters must be in the dictionary
      if this_letter not in base_dict:
         print "letter %s not in base_dict" % (this_letter)
         return "***"

      ##--- test for all translations are equal in length
      if len(base_dict[this_letter]) != len_letter:
         print "unequal letter lengths", len_letter, len(base_dict[this_letter])
         return "***"

      ##--- convert triple quote string into rows in a list
      string_list = base_dict[this_letter].split("\n")
      print "string_list", string_list

      ##---  append each row to the corresponding dictionary key
      for row in range(0, len(string_list)):
         if row not in combined_rows_dict:
            combined_rows_dict[row] = []
         combined_rows_dict[row].append(string_list[row])

   print
   for row in range(0, len(combined_rows_dict)):
      this_row = combined_rows_dict[row]
      print " ".join(this_row)
   return "Success"

base_dict = {}
base_dict["A"] = """X 0 X X
0 X 0 X
0 0 0 X
0 X 0 X
0 X 0 X"""

base_dict["B"] = """0 0 X X
0 X 0 X
0 0 X X
0 X 0 X
0 0 X X"""

base_dict["C"] = """X 0 X X
0 X 0 X
0 X X X
0 X 0 X
X 0 X X"""

##for key in ("A", "B", "C"):
##   print key, "-" *60
##   print base_dict[key]

print join_letters(["A", "C", "B"], base_dict)
commented: You're the best teacher in forum 114 ! +4
class Ideogram(tuple):
    def __new__(cls, string):
        return tuple.__new__(cls, (y for y in (x.strip() for x in string.split("\n")) if y))
    def __init__(self, *args):
        assert(len(self) == 5)

base_dict = dict(zip(tuple(base), (Ideogram(x) for x in FIVEHIGH)))

if __name__ == "__main__":
    word = raw_input("Enter word:")
    print translate(word)

Thank you so much for your help guys. Not to sound incredibly ignorant, but what are the commands surrounded by underscores, and why are they written like that? What makes them different?

My attempt. Once again, if not correct, post back with more info. The trick (I think) is to split each string on the "\n" to create individual rows, and is similiar to Gribouillis' solution but doesn't use list comprehension (which is an amazing tool). It instead uses a dictionary with row number as the key, in this case 0 through 4, and appends each row to the corresponding key. Finally, the joined rows are spaced and printed. Hopefully, using a dictionary with the row number is easy to understand.

Actually, it's very easy to understand. I had a brainstorm myself last night, and this is how far I've gotten:

## Define Variables

LINONE = {'A':'X 0 X X ','B':'0 0 X X ','C':'X 0 X X '}
LINTWO = {'A':'0 X 0 X ','B':'0 X 0 X ','C':'0 X 0 X '}
LINTHR = {'A':'0 0 0 X ','B':'0 0 X X ','C':'0 X X X '}
LINFOU = {'A':'0 X 0 X ','B':'0 X 0 X ','C':'0 X 0 X '}
LINFIV = {'A':'0 X 0 X ','B':'0 0 X X ','C':'X 0 X X '}
ALLINONE = ()
ALLINTWO = ()
ALLINTHR = ()
ALLINFOU = ()
ALLINFIV = ()
code1 = ()
code2 = ()
code3 = ()
code4 = ()
code5 = ()

## Program starts

# Get the user's word they want converted
word = raw_input("What word?  ")

# Make it upper case for uniformity
word = word.upper()

## Workhorse loop:
# For each letter,
#     Take the letter's value out of the line's dictionary
#     Add the letter's value to the end of the line that will be printed
#     Move on to the next line.  Rinse and repeat
for letter in word:
    code1 = LINONE.get(letter)
    ALLINONE += code1
    code2 = LINTWO.get(letter)
    ALLINTWO += code2
    code3 = LINTHR.get(letter)
    ALLINTHR += code3
    code4 = LINFOU.get(letter)
    ALLINFOU += code4
    code5 = LINFIV.get(letter)
    ALLINFIV += code5

## Output
# Print the original user-input word, then concatenate the
# lines formed by the above loop and print each one on a
# separate line
print '\n' + word + '\n\n' + ALLINONE + '\n' + ALLINTWO + '\n' + ALLINTHR + '\n' + ALLINFOU + '\n' + ALLINFIV + '\n'

raw_input("Any key to exit")

I think it's a solid idea, and uses only the commands I've learned (I'm in chapter five of a book. Lists, tuples and dictionaries, pretty much).

As you can see, I also came up with a "line by line" solution. The problem now is, when I run it, I get:

line 34, in <module>
    ALLINONE += code1
TypeError: can only concatenate tuple (not "NoneType") to tuple

Now, I understand the error message, and where the error took place. What I don't understand is why one of my variables (either ALLINONE or code1, not sure which) isn't a tuple. I defined them previously as tuples, and can't see where they'd become "NoneType."

Any ideas?

The problem is that LINONE.get(letter) returns None if letter is not in LINONE (type >>> help(dict.get) in the python console). So you must handle the case where the letter is not in the dictionary.

Belay my last. It turns out that I'm just retarded. I was putting words in that weren't just made up of A, B, and C. Now that I gave myself a swift kick in the head, this is the output of "CAB:"

What word?  cab

CAB

['X', ' ', '0', ' ', 'X', ' ', 'X', ' ', 'X', ' ', '0', ' ', 'X', ' ', 'X', ' ', '0', ' ', '0', ' ', 'X', ' ', 'X', ' ']
['0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ']
['0', ' ', 'X', ' ', 'X', ' ', 'X', ' ', '0', ' ', '0', ' ', '0', ' ', 'X', ' ', '0', ' ', '0', ' ', 'X', ' ', 'X', ' ']
['0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ']
['X', ' ', '0', ' ', 'X', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', 'X', ' ', '0', ' ', '0', ' ', 'X', ' ', 'X', ' ']

Any key to exit

Note that I changed the output code to make it a whole lot cleaner.

print '\n' + word + '\n'
print ALLINONE
print ALLINTWO
print ALLINTHR
print ALLINFOU
print ALLINFIV

Now for the next problem: How would I strip out the brackets, commas and apostrophes from the output to make it look clean?

I could use your ways, and there's nothing against them, but I'd like to A) have written at least a part of it, and B) be able to understand most of the commands within the program. I feel like I'm about to suffer from an aneurism when I read through your code, simply because I don't know that many commands yet.

Any ideas on a simple way to make the output pretty?

Replace print ALLINONE by print "".join(ALLINONE) .

That is exactly what I was looking for. I know you're most likely sick to death of my stupidity, but would you mind explaining just how print "".join(ALLINONE) works?

try

>>> print "abc" . join(['H', 'E', 'L', 'L', 'O'])

That's pretty nifty. Well, thank you so much for your help. I really do appreciate it. I'll try not to be such a bother in the future!

You could try using one of the old lisp functions EXPLODE which separates all the character in the word - I use

(defun explo (a)
(map 'list #'(lambda (char)
(intern (string char)))
(prin1-to-string a)))

for 'abc12 (must have a ' in lisp) it would return (A B C \1 \2)
Then you would write a function re: the numbers with / to convert
to regular numbers to produce (A B C 1 2). Then write code for this that
replaces the atoms inside the parentheses with whatever you choose and then write a function to assemble the atoms into a single atom.I have a functin such that if you substituted "d e" for the "1 2" in the list and called (concat-list2 '(A B C D E))
the return would be ABCDE
Hope that helps.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.