Adding 2 ascii converted characters using nested loops in Python 3.2 - python

I'm trying to add together strings where each letter has been converted to ASCII and then added together accordingly. So for example, adding together the strings "goodbye" "hello" I'd like to convert each letter to ascii then add them together like so:
103 + 104 (g + h)
111 + 101 (o + e)
111 + 108 (o + l)
100 + 108 (d + l)
98 + 111 (b + o)
121 + 104 (y + h)
101 + 101 (e + e)
In this instance, "goodbye" must be interchangeable, i.e. user inputted. This is the code I've generated so far:
input1 = input("Enter word: ")
input2 = "goodbye"
l = len(upnumber)
count = 0
for i in (input1):
x = (ord(i))
while count <= l:
for j in (input2):
y = (ord(j))
total = (x + y)
count = count + 1
print (total)
This code doesn't work. It just seems to add the first character of input1 to every character in input2, an innumerate amount of times.
The count is in there as I'd like the loop to stop after each character in input1 has been added to the loop of input2.

You are looping over all of input2 for each character in input1, because you nested the loops.
Use the zip() function instead to pair up letters:
input1 = input("Enter word: ")
input2 = "goodbye"
# make input1 at least as long as input2
while len(input1) <= len(input2):
input1 += input1
for x, y in zip(input1, input2):
total = ord(x) + ord(y)
print(total)
where zip() will stop iterating once the shortest of the two strings is done. Since input1 has been extended to repeat until it is at least as long as input2, that means you end up processing all characters of input2, and no more, unless input1 was longer to start with.
Instead of manually repeating input2, you can also use itertools.cycle() to cycle through all characters in input1 indefinitely:
from itertools import cycle
input1 = input("Enter word: ")
input2 = "goodbye"
for x, y in zip(cycle(input1), input2):
total = ord(x) + ord(y)
print(total)
Demo of the latter approach, with some extra formatting to illustrate what is going on:
>>> from itertools import cycle
>>> input1 = 'hello'
>>> input2 = "goodbye"
>>> for x, y in zip(cycle(input1), input2):
... total = ord(x) + ord(y)
... print('{!r} + {!r} = {:3d} + {:3d} = {:3d}'.format(x, y, ord(x), ord(y), total))
...
'h' + 'g' = 104 + 103 = 207
'e' + 'o' = 101 + 111 = 212
'l' + 'o' = 108 + 111 = 219
'l' + 'd' = 108 + 100 = 208
'o' + 'b' = 111 + 98 = 209
'h' + 'y' = 104 + 121 = 225
'e' + 'e' = 101 + 101 = 202

Related

Decrypting a Caesar Cipher with ord() and chr()?

I have an assignment for a lab that asks me to decrypt an input file that has been encrypted with a ceasar cipher. As background, my instructor has already let everyone know that the cipher has a shift distance of three.
I was able to get my to write to an output file, but my output.txt is completely unreadable, and not close at all to what the expected output should be. I remember my instructor mentioning that we could use ord() and chr() combined with arithmetic to transform the encoded characters to plaintext.
decode = inpf.readlines()
for line in decode:
output = ""
c = str()
for c in line:
if c >= "a" and c <= "z":
x = ord(c)
x += 23
x %= 26
y = chr(x)
output = output + y
if c >= "A" and c <= "Z":
x = ord(c)
x += 23
x %= 26
y = chr(x)
output = output + y
else:
output = output + c
outf.write(output + "\n")
I appreciate any help or advice you can offer! Thanks!!
EDIT:
Sample Input: "Wkh Orug Ri Wkh Ulqjv:"
Output: " :"
Expected Output: "The Lord Of The Rings:"
The ord() method in Python converts a character into its Unicode code value. Capital 'A' starts from unicode 65 and small 'a' from 97. Also you should use 'elif' instead of second 'if' statement. Otherwise, in case of a small letter, the letter will repeat. You need to get the letters position in alphabet, apply the shift and convert it back to unicode. A working example of your code is given below:
inpf = open("input.txt",'r')
outf = open("output.txt",'w')
decode = inpf.readlines()
for line in decode:
output = ""
c = str()
for c in line:
if c >= "a" and c <= "z":
x = ord(c) - 97 #small a
x -= 3
x = (x+26)%26 #For handling negative numbers
y = chr(x + 97)
output = output + y
elif c >= "A" and c <= "Z":
x = ord(c) - 65 #Capital A
x -= 3
x = (x+26)%26 #For handling negative numbers
y = chr(x + 65)
output = output + y
else:
output = output + c
outf.write(output + "\n")

how do i make a ceaser cipher where the letter "z" becomes "a" on +1 shift in python

How do I shift the end of the alphabet so "z" becomes "a"?
i was thinking a if statement
plaintext = input("please type message:")
def split(plaintext):
return list(plaintext)
print(split(plaintext))
for s in plaintext:
a = ord(s)
print (a)
list1=[]
for t in plaintext:
b = ord(t)
c = b+1
print (c)
list1.append(c)
print (list1)
aa =""
for ab in list1:
aa = aa + chr(ab)
print (str(aa))
print(split(aa))
if you just want to increase the character by one you could do this:
def inc_chr(c):
return chr((ord(c) + 1 - ord("a")) % 26 + ord("a"))
test:
for char in "abcxyz":
print(f"{char} {inc_chr(char)}")
outputs:
a b
b c
c d
x y
y z
z a
basically you do calculations modulo 26 with an offset of ord("a") = 97.
You can use a look up dict and convert the characters.
import string
alphabets = string.ascii_lowercase
look_up = {alphabets[i]: alphabets[i-1] for i in range(len(alphabets))}
You can then use this lookup for cypher
test = "This will be encoded"
out = = "".join([look_up.get(char, char) for char in test])
print(out)

How to replace each letter in a string with a consecutive letter with increasing offset?

Suppose the word is "CAT" and I want the output to be "DCW". Where the C changes to the next letter D and the A changes into the second next letter from A to C and the T changes into the third next letter from T to W.
I am on the first step here:
a = input("Enter a letter: ")
a = chr(ord(a) + 1)
print(a)
You need to loop over the word:
word = 'CAT'
result = ''
for i, a in enumerate(word,1):
result += chr(ord(a) + i)
print(result)
# alternatively, same loop as list comprehension
print(''.join(chr(ord(a) + i) for i, a in enumerate(word,1)))
Out:
DCW
DCW
What you are looking for is called Caesar cypher, but the offset changes with the character's position:
def encrypt(text):
result = ""
for i in range(len(text)):
char = text[i]
if (char.isupper()):
result += chr((ord(char) -65) % 26 + 65 + i + 1)
else:
result += chr((ord(char) - 97) % 26 + 97 + i + 1)
return result
print(encrypt(input()))
Source: https://www.tutorialspoint.com/cryptography_with_python/cryptography_with_python_caesar_cipher.htm
try this :
import string
a =input("Enter a letter: ")
r=''
for i,e in enumerate(a,1):
r=r+string.ascii_lowercase[string.ascii_lowercase.index(e.lower())+i]
print(r.upper())
or in one line like this :
print(''.join(list(string.ascii_lowercase[string.ascii_lowercase.index(e.lower())+i] for i,e in enumerate(a,1) )).upper())
Note: in Python 2, string.ascii_lowercase is string.lowercase.

Sum of Digits in a specific way in Python

I'm looking for a code that runs, i.e:
int(input) = 2565
Printed Output should be like:
2 + 5 + 6 + 5 = 18 = 1 + 8 = 9
I wrote the code that gives final answer "9". But I couldn't managed to write it with every digit separated "+" sign. Assuming that I need to use while loop but how can I write the code so it will be like the output above?
You can use something like this:
def sum_of_digits(s):
if s < 10:
return s
return sum_of_digits(sum(int(c) for c in str(s)))
> sum_of_digits(2565)
9
It recursively checks if the numerical value is less than 10. If it does, it returns this value. If not, it adds the digits, then recursively calls itself on the result.
Edit
To print out the steps as it goes along, you could do something like this:
def sum_of_digits(s):
if s < 10:
print(s)
return s
print(' + '.join(c for c in str(s)) + ' = ')
return sum_of_digits(sum(int(c) for c in str(s)))
First, initiate an empty string output_str.
With a while loop which contniues when our integer is > 9:
[s for s in str(x)] would create a list of the digits (as strings) of our integer. It's called a list comprehension, is very useful, and my advice is to read a bit about it.
With " + ".join() we create a string with " + " between the
digits. Add this string at the end of output_str.
Add " = " to the end of output_str.
Calculate the sum of the digits (we cannot use sum(lst_of_digits) because it's a list of strings. sum([int(s) for s in lst_of_digits]) converts the string list into an inter list, which can be summed using sum()). Store the sum into x.
Add the new x + " = " to output_string.
At the end of the string, we have a redundant " = " (because the last (5) was not needed), let's just remove the last 3 chars (=) from it.
x = 2565
output_str = ""
while x > 9:
lst_of_digits = [s for s in str(x)]
output_str += " + ".join(lst_of_digits)
output_str += " = "
x = sum([int(s) for s in lst_of_digits])
output_str += f"{x} = "
output_str = output_str[:-3]
outputs:
output_str = '2 + 5 + 6 + 5 = 18 = 1 + 8 = 9'
You can play around with the end keyword argument of the print function which is the last character/string that print will put after all of its arguments are, well, printed, by default is "\n" but it can be change to your desire.
And the .join method from string which put the given string between the given list/iterable of strings to get the desire result:
>>> " + ".join("123")
'1 + 2 + 3'
>>>
Mixing it all together:
def sum_digit(n):
s = sum(map(int,str(n)))
print(" + ".join(str(n)),"=",s, end="")
if s<10:
print()
return s
else:
print(" = ",end="")
return sum_digit(s)
Here we first get the sum of the digit on s, and print it as desire, with end="" print will not go to the next line which is necessary for the recursive step, then we check if done, and in that case print a new empty line if not we print an additional = to tie it for the next recursive step
>>> sum_digit(2565)
2 + 5 + 6 + 5 = 18 = 1 + 8 = 9
9
>>>
This can be easily be modify to just return the accumulated string by adding an extra argument or to be iterative but I leave those as exercise for the reader :)
I am a noob but this should do what you want.
Cheers,
Guglielmo
import math
import sys
def sumdigits(number):
digits = []
for i in range( int(math.log10(number)) + 1):
digits.append(int(number%10))
number = number/10
digits.reverse()
string = ''
thesum = 0
for i,x in enumerate(digits):
string += str(x)
thesum += x
if i != len(digits)-1: string += ' + '
else: string += ' = '
if thesum > 10:
return string,thesum,int(math.log10(number))+1
else:
return string,thesum,0
def main():
number = float(sys.argv[1])
finalstring = ''
string,thesum,order = sumdigits(number)
finalstring += string
finalstring += str(thesum)
while order > 0:
finalstring += ' = '
string,thesum,order = sumdigits(thesum)
finalstring += string
finalstring += str(thesum)
print 'myinput = ',int(number)
print 'Output = ',finalstring
if __name__ == "__main__":
main()

insert letter and number - shift letter to right in alphabet 'number' of times

def char():
letter = str(input("Input Letter from alphabet: "))
x = int(input("Input Value to shift letter to the right x number of times: : "))
newLetter = ord(letter) + x
if newLetter > 90 and newLetter < 97:
remainder = newLetter % 90
newLetterI = 65 + remainder
print(chr(newLetterI))
elif newLetter > 122:
remainder = newLetter % 122
newLetterI = 97 + remainder
print(chr(newLetterI))
char()
This is my code that shifts the letter to the right a 'number' of times.
It is very long winded, but it was the only way i found how to do it without having lots of errors that i didn't really understand. I was just wondering if it is ok, and was just wondering if the wrapping back around once the alphabet reached Z or z ok.
Could you please check this:
#!/usr/bin/python
def next_nchar(char, n):
# 97, 122
upper = None
if char.isupper():
upper = True
lw = char.lower()
start = ord(lw)
num = ord(lw) + n
if num > 122:
ex = num - 122
else:
ex = None
if not ex:
r = range(start, num)
else:
r = range(start, 123) + range(97, 97+ex-1)
if upper:
return [chr(x).upper() for x in r]
return [chr(x) for x in r]
for i in ['a', 'k', 'y', 'P']:
print next_nchar(i, 5)
Output:
['a', 'b', 'c', 'd', 'e']
['k', 'l', 'm', 'n', 'o']
['y', 'z', 'a', 'b', 'c']
['P', 'Q', 'R', 'S', 'T']
you should use like this one
import sys
def char():
letter = sys.stdin.readline().strip()
x = int(sys.stdin.readline())
oldLetter = ord(letter)
if oldLetter > 64 and oldLetter < 91:
if (oldLetter+x) <= 90:
remainder = (oldLetter + x) % 65
newLetter = 65 + remainder
else:
remainder = (oldLetter + x) % 90
newLetter = 64 + remainder
print(chr(newLetter))
elif oldLetter > 96 and oldLetter < 123:
if (oldLetter+x) <= 122:
remainder = (oldLetter + x) % 97
newLetter = 97 + remainder
else:
remainder = (oldLetter + x) % 122
newLetter = 96 + remainder
print(chr(newLetter))
char()
One problem I can find with your code is that the wraparound doesn't seem to make much sense. If you modulo 122 your newLetter, you will run into problems when you have shifts of 26, for example, and also it's a bit hard to read since you have to remember ascii values.
I will try to explain a slightly improved version:
letter = input("Enter a letter from the alphabet: ") # No need for str, it is already a string
shift = int(input("Enter your letter shift: "))
if letter.islower(): # Much better than worrying about ascii values
initial = 'a'
else:
initial = 'A'
letterIndex = (ord(letter) - ord(initial)) # So 'a' would have index 0, 'b' 1, 'z' 25
newIndex = (letterIndex + shift) % 26 # Making sure our index is from 0 to 25
newLetter = chr(ord(initial) + newIndex) # after 'a' or 'A', increment by newIndex
print newLetter
Here is a more concise version of it, without comments:
letter = input("Enter a letter from the alphabet: ")
shift = int(input("Enter your letter shift: "))
initial = 'a' if letter.islower() else 'A'
newIndex = (ord(letter) - ord(initial) + shift) % 26
print(chr(ord(initial) + newIndex))
This is the most readable way to do it, IMO:
import string
def shiftchar(char, n):
if char.isupper():
letters = string.uppercase # all uppercase letters in alphabetical order
elif char.islower():
letters = string.lowercase # all lowercase letters in alphabetical order
try:
initcharpos = letters.index(char)
newchar = letters[(initcharpos + n) % 26]
# get the letter n characters later, with wraparound
return newchar
except (NameError, ValueError):
# NameError: char is mixed-case or non-English, so letters is never defined
# ValueError: char not found in letters; probably a multi-char string
raise TypeError("Expected a single English char as first argument")
print shiftchar('A', 5) # F
print shiftchar('z', 1) # a
print shiftchar('foo', 5) # TypeError

Categories