954,541 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Creating a replacement cypher with triple-quoted strings

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.

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 
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.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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

willygstyle
Junior Poster in Training
60 posts since Aug 2009
Reputation Points: 17
Solved Threads: 9
 
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.

woooee
Nearly a Posting Maven
2,454 posts since Dec 2006
Reputation Points: 777
Solved Threads: 714
 
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?

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 
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?

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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]

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

You must not add the triple quoted strings in FIVEHIGH.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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.

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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 !

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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?

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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
Nearly a Posting Maven
2,454 posts since Dec 2006
Reputation Points: 777
Solved Threads: 714
 

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.

Warkthogus
Newbie Poster
16 posts since Sep 2009
Reputation Points: 10
Solved Threads: 0
 

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)
Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

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)
woooee
Nearly a Posting Maven
2,454 posts since Dec 2006
Reputation Points: 777
Solved Threads: 714
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You