Discussion:
calling upper() on a string, not working?
Felipe Almeida Lessa
2006-05-16 20:34:39 UTC
Permalink
it doesn't seem to work. The full code is below if it helps to understand.
Why doesn't it work? What does it do, what did you expect it to do?
''.join(set('hi'))
'ih'
''.join(set('HI'))
'IH'
''.join(set('hiHI'))
'ihIH'
''.join(set('hiHI'.upper()))
'IH'
--
Felipe.
John Salerno
2006-05-16 20:48:26 UTC
Permalink
And here you're translating 'original' (which contains a lot of
lowercase letters) with use of trans_table that maps only uppercase
return original.upper().translate(trans_table)
Thank you!!! :)
Michal Kwiatkowski
2006-05-16 20:43:12 UTC
Permalink
original_letters = filter_letters(original)
You call filter_letters() which makes upper() on all letters, so
original_letters contain only uppercase letters.
new_letters = list(string.ascii_uppercase)
random.shuffle(new_letters)
trans_letters = ''.join(new_letters)[:len(original_letters)]
trans_table = string.maketrans(original_letters,
trans_letters) break
return original.translate(trans_table)
And here you're translating 'original' (which contains a lot of
lowercase letters) with use of trans_table that maps only uppercase
characters. This return should be:

return original.upper().translate(trans_table)

mk
--
. o . >> http://joker.linuxstuff.pl <<
. . o It's easier to get forgiveness for being wrong
o o o than forgiveness for being right.
Scott David Daniels
2006-05-16 23:00:07 UTC
Permalink
John Salerno wrote:
<Some code, with a request to get case working.>
Others have shown you where the bug was.

You might want to change encrypt_quote like this:

XXX> def encrypt_quote(original):
def encrypt_quote(original, casemap=True):
XXX> original_letters = filter_letters(original)
if casemap:
original_letters = filter_letters(original.upper())
else:
original_letters = filter_letters(original)
XXX> new_letters = list(string.ascii_uppercase)
if len(original_letters) > 26:
new_letters = list(string.ascii_uppercase +
string.ascii_lowercase)
casemap = False
else:
new_letters = list(string.ascii_uppercase)
random.shuffle(new_letters)
trans_letters = ''.join(new_letters)[:len(original_letters)]
XXX> trans_table = string.maketrans(original_letters,
trans_letters)
if casemap:
trans_table = string.maketrans(
original_letters + original_letters.lower(),
trans_letters + trans_letters.lower())
else:
trans_table = string.maketrans(original_letters,
trans_letters)
break
return original.translate(trans_table)
--Scott David Daniels
scott.daniels at acm.org
John Salerno
2006-05-16 20:41:02 UTC
Permalink
Post by Felipe Almeida Lessa
it doesn't seem to work. The full code is below if it helps to understand.
Why doesn't it work? What does it do, what did you expect it to do?
If you run the whole script with the first line (the one not commented),
you get output similar to this, which is correct:
["AMN RIPQ LP WOQ SNIS. BW VIDQ, LQ'P WOQ NHNW RIPQ.", 'ULJJLIY TIZJXWNE']
But if you use the line with the upper() call, you get this:
["Bhe past is not dead. Dn fact, it's not even past.", 'Killiam Qaulkner']
Now, I know the actual upper() function works, but I can't understand if
there's a problem with *when* it's being called, or what's being done
with it to get the second result above.
unknown
2006-05-17 00:16:05 UTC
Permalink
Post by John Salerno
Now, I know the actual upper() function works, but I can't understand
if there's a problem with *when* it's being called, or what's being
done with it to get the second result above.
You are translating "original" which still has lower case letters:

return original.translate(trans_table)

You want:

return original.upper().translate(trans_table)
Bruno Desthuilliers
2006-05-17 12:29:45 UTC
Permalink
# Since it's here that we define that the new letters
# will be uppercase only, it's our responsability
# to handle any related conditions and problems
# The other functions shouldn't have to even know this.
original = original.upper()
# here, we *dont* have to do anything else than filtering
# upper/lower case is *not* our problem.
return ''.join(set(original) - PUNCT_SPACE_SET)
Thanks, I was wondering if it only needed to be done in a single place
like that.
It's always better to do something in a single place - you may here of
this as the DRY (Dont Repeat Yourself) or SPOT (Single Point Of
Transformation) rule.

The way you wrote it, part of encrypt_quote's responsability and
knowldege was leaking into filter_letters. This is a Bad Thing(tm), and
should be avoided by any mean.
John Salerno
2006-05-16 20:25:04 UTC
Permalink
Can someone tell me what's happening here. This is my code:



PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)

def filter_letters(original):
return ''.join(set(original) - PUNCT_SPACE_SET)



'original' is a string. The above works as expected, but when I change
it to

return ''.join(set(original.upper()) - PUNCT_SPACE_SET)

it doesn't seem to work. The full code is below if it helps to understand.



import string
import random
import itertools

PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)

def convert_quote(quote):
return encrypt_quote(quote).split('|')

def encrypt_quote(original):
original_letters = filter_letters(original)
new_letters = list(string.ascii_uppercase)
while True:
random.shuffle(new_letters)
trans_letters = ''.join(new_letters)[:len(original_letters)]
if test_code(original_letters, trans_letters):
trans_table = string.maketrans(original_letters, trans_letters)
break
return original.translate(trans_table)

def filter_letters(original):
return ''.join(set(original) - PUNCT_SPACE_SET)
#return ''.join(set(original.upper()) - PUNCT_SPACE_SET)

def test_code(original_letters, trans_letters):
for pair in itertools.izip(original_letters, trans_letters):
if pair[0] == pair[1]:
return False
return True

if __name__ == '__main__':
print convert_quote("The past is not dead. In fact, it's not even
past.|William Faulkner")
Larry Bates
2006-05-16 20:50:51 UTC
Permalink
Post by John Salerno
PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
return ''.join(set(original) - PUNCT_SPACE_SET)
'original' is a string. The above works as expected, but when I change
it to
return ''.join(set(original.upper()) - PUNCT_SPACE_SET)
it doesn't seem to work. The full code is below if it helps to understand.
import string
import random
import itertools
PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
return encrypt_quote(quote).split('|')
original_letters = filter_letters(original)
new_letters = list(string.ascii_uppercase)
random.shuffle(new_letters)
trans_letters = ''.join(new_letters)[:len(original_letters)]
trans_table = string.maketrans(original_letters, trans_letters)
break
return original.translate(trans_table)
return ''.join(set(original) - PUNCT_SPACE_SET)
#return ''.join(set(original.upper()) - PUNCT_SPACE_SET)
return False
return True
print convert_quote("The past is not dead. In fact, it's not even
past.|William Faulkner")
Not exactly sure why you think its not working. When you create a set
from the original.upper() you get a smaller number of characters because
you no longer get both 'T' and 't' as well as 'I' and 'i' as you do in
the lower case version of the string.
Post by John Salerno
set(original.split('|')[0])
set(['a', ' ', 'c', 'e', 'd', "'", 'f', 'i', 'h', ',', 'o', 'n', 'p', 's', 'T',
'v', 'I', '.', 't'])
Post by John Salerno
set(original.split('|')[0].upper())
set(['A', ' ', 'C', 'E', 'D', "'", 'F', 'I', 'H', ',', 'O', 'N', 'P', 'S', 'T',
'V', '.'])
sets can only contain "unique" entries. Letters that are repeated only get
added once. When you do .upper() you convert lowercase 't' to 'T' and lower
case 'i' to 'I' so that letter only gets added to the set a single time.

Hope info helps.

Larry Bates
Bruno Desthuilliers
2006-05-17 00:12:23 UTC
Permalink
Post by John Salerno
PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
return ''.join(set(original) - PUNCT_SPACE_SET)
'original' is a string. The above works as expected, but when I change
it to
return ''.join(set(original.upper()) - PUNCT_SPACE_SET)
it doesn't seem to work. The full code is below if it helps to understand.
Don't assume str.upper() is broken !-)

In fact, your problem is that you create the translation table based on
Post by John Salerno
import string
import random
import itertools
PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
return encrypt_quote(quote).split('|')
# Since it's here that we define that the new letters
# will be uppercase only, it's our responsability
# to handle any related conditions and problems
# The other functions shouldn't have to even know this.
original = original.upper()
Post by John Salerno
original_letters = filter_letters(original)
new_letters = list(string.ascii_uppercase)
random.shuffle(new_letters)
trans_letters = ''.join(new_letters)[:len(original_letters)]
trans_table = string.maketrans(original_letters, trans_letters)
break
return original.translate(trans_table)
# here, we *dont* have to do anything else than filtering
# upper/lower case is *not* our problem.
Post by John Salerno
return ''.join(set(original) - PUNCT_SPACE_SET)
return False
return True
print convert_quote("The past is not dead. In fact, it's not even
past.|William Faulkner")
["XCD ONKX AK IGX LDNL. AI WNBX, AX'K IGX DYDI ONKX.", 'UAEEANP WNREQIDS']
John Salerno
2006-05-16 20:58:53 UTC
Permalink
# Since it's here that we define that the new letters
# will be uppercase only, it's our responsability
# to handle any related conditions and problems
# The other functions shouldn't have to even know this.
original = original.upper()
# here, we *dont* have to do anything else than filtering
# upper/lower case is *not* our problem.
return ''.join(set(original) - PUNCT_SPACE_SET)
Thanks, I was wondering if it only needed to be done in a single place
like that.

Loading...