Trying to transcribe using ascii values using ord and chr - python

Trying to make an encrypter that shifts ascii values of each character in a message by the value of a corresponding character in a password - Output always results in either a single character or a string index out of range error:
msg = input()
pw = input()
pwN = 0
msgN = 0
for i in msg:
newmsg =""
nchar = chr(ord(msg[msgN]) + ord(pw[pwN]))
pwN += 1
msgN += 1
if pwN > len(pw):
pwN = 0
newmsg += nchar
print (newmsg)
Running it in this form results in a single character rather than a message length string in some cases, and in others gives me this error:
Traceback (most recent call last):
File "file", line 8, in <module>
nchar = str(chr(ord(msg[msgN]) + ord(pw[pwN])))
IndexError: string index out of range
I can't figure out what I'm missing.

The issue is that you're setting newmsg to the empty string in each loop. Moving newmsg = "" before the for loop should fix the issue of single characters, although figuring out the out of range error is difficult because of your manual increasing of several indices while also iterating over msg.
I would suggest taking a look at the iteration features Python offers. You are technically iterating over msg, but never actually use i, instead relying solely on indices. A more pythonic way to solve this might be as follows:
from itertools import cycle
msg = input()
pw = input()
newmsg = ""
for mchar, pwchar in zip(msg, cycle(pw)): # cycle loops the password so that abc becomes abcabcabc...
newmsg += chr(ord(mchar) + ord(pwchar))
print(newmsg)
if you want to stick to the loop. I would even use a generator expression to make it
from itertools import cycle
msg = input()
pw = input()
newmsg = "".join(chr(ord(mchar) + ord(pwchar)) for mchar, pwchar in zip(msg, cycle(pw)))
print(newmsg)

Related

Getting EOF error but running my code in Thonny produces no errors

I'm learning python and one of my labs required me to:
Write a program whose input is a string which contains a character and a phrase, and whose output indicates the number of times the character appears in the phrase. The output should include the input character and use the plural form, n's, if the number of times the characters appears is not exactly 1.
My code ended up being:
char = input()
string = input()
count = 0
for i in string:
if i == char:
count +=1
if count > 1 or count == 0:
print(f"{count} {char}'s")
else:
print(f'{count} {char}')
Whenever I run the code in Thonny or in the Zybooks development tab it works but when I select the submit option I keep getting and EOF error:
Traceback (most recent call last):
File "main.py", line 2, in <module>
string = input()
EOFError: EOF when reading a line
Does anyone know what's causing the error?
I tried using the break command but it didn't help though I think if I used break at the end of my for statement it wouldn't count all the way. Any ideas folks?
Thank you Mr. Roberts the number of inputs was the issue. I had to create a single input and pull what I needed from that single line. My code ended up being:
string = input()
char = string[0]
phrase = string[1:]
count = 0
for i in phrase:
if i == char:
count +=1
All good now.

Python: Length of list as single integer

I'm new to Python and I'm trying to output the length of a list as a single integer, eg:
l1 = ['a', 'b', 'c']
len(l1) = 3
However, it is printing on cmdline with 1s down the page, eg:
1
1
1
1
1
1
etc
How can I get it to just output the number rather than a list of 1s?
(Here's the code:)
def Q3():
from datetime import datetime, timedelta
inputauth = open("auth.log", "r")
authStrings = inputauth.readlines()
failedPass = 'Failed password for'
for line in authStrings:
time = line[7:15]
dateHour = line[0:9]
countAttack1 = []
if time in line and failedPass in line:
if dateHour == 'Feb 3 08':
countAttack1.append(time)
length1 = len(countAttack1)
print(length1)
Ideally, I'd like it to output the number in a print so that I could format it, aka:
print("Attack 1: " + length1)
I think you are looping and ifs are inside a loop. If so, just print the length outside loop scope.
Please share the complete code for a better answer
Well as Syed Abdul Wahab said, the problem is that the "list" is getting recreated each loop. This makes so that the print reports "1", as it is the actual length of the list.
The other problem, repetition of the printng is similar - you are actually printing "each time in the loop".
The solution is then simple: you initialize the list outside the loop; and also report outside the loop.
def Q3():
from datetime import datetime, timedelta
inputauth = open("auth.log", "r")
authStrings = inputauth.readlines()
failedPass = 'Failed password for'
countAttack1 = [] # after this line the countAttack will be empty
for line in authStrings:
time = line[7:15]
dateHour = line[0:9]
if time in line and failedPass in line:
if dateHour == 'Feb 3 08':
countAttack1.append(time)
length1 = len(countAttack1)
print("Attack 1: " + str(length1))
I'd also like to take a bit of time to link you to string formatting While the documentation is complex it will make printing much easier, above print is trnasformed into:
print("Attack 1: {0}".format(length1))
Further analysing the code gives some peculiarities, you check if time is in the line string. - However just a few codelines above you create time from a slice of line - so it will always be inside line. (Except for the edge case where line is not of correct length, but that'll error anyways). So that if statement should be simplified to:
if failedPass in line:
Here is the function that prints the the length:
def print_length():
if time in line and failedPass in line:
if dateHour == 'Feb 3 08':
countAttack1.append(time)
length1 = len(countAttack1)
print(length1)
print_length()
>>>Print length of the List.

Syntax error: 002: on assigning values to variables python

Im writing a program for Uni to find all the palindromic primes, i have written out the program already but when i run it, my first input gets an error while trying to assign values to the variable.
please could someone tell me why this is the case!
start =input("Enter the start point N:")
starteval= eval(start)
endval = eval(input("Enter the end point M:"))
reverse=""
x=starteval+1
while x<endval:
reverse+=start[::-1]
evalreverse=eval(reverse)
if evalreverse==starteval:
if starteval==2 or starteval==3:
print(starteval)
elif starteval%2==0 or starteval%3==0:
pass
i=5
w=2
a=0
while i<=starteval:
if starteval%i==0:
break
else:
a=True
i+=2
if a==True:
print (starteval)
else:
pass
x+=x+1
the ouput i recieve is
"Enter the start point N:200
Enter the end point M:800
Traceback (most recent call last):
File "", line 1, in <module>
start =input("Enter the start point N:")
Syntax Error: 002: <string>, line 1, pos 3"
please and thank you!
Try instead of the first 3 lines to use:
starteval = int(raw_input("Enter the start point N:"))
endval = int(raw_input("Enter the end point M:"))
In Python 3 integer literals cannot begin with a zero:
>>> i = 002
File "<stdin>", line 1
i = 002
^
SyntaxError: invalid token
Because you are applying the eval function to your string input, Python attempts to parse your input as a valid Python expression, whcih is why you see the error you see.
It would make more sense to use int(input(...)) to get the integer (though you would still have to handle any exceptions raised when the user types a non-integer into your code). This has the advantage that it will accept the input that is causing you trouble in eval.
You could write a small intParsing function, that handles simple input parsing for you, then basically replace every "eval()" function of your code with intParsing().
Here is your edited code:
def intParsing(input_str):
str = ""
# Delete all chars, that are no digits (you could use a regex for that too)
for char in input_str.strip():
if char.isdigit():
str += char
# Now you only got digits in your string, cast your string to int now
r = int( str )
print "result of parsing input_str '", input_str, "': ", r
return r
start =raw_input("Enter the start point N:")
starteval= intParsing(start) # I edited this line
end = raw_input("Enter the end point M:") # I edited this line
endval =intParsing(end) # I edited this line
reverse=""
x=starteval+1
while x<endval:
reverse+=start[::-1]
evalreverse= intParsing(reverse) # I edited this line

Python retrieve string input from int(input()) exception

I'm trying to make the following code work:
try:
x = int(input())
except ValueError as var:
#print the input of the user
If I try to print(var) it would print the error line and not the original input of the user.
For example, if the user would insert bla instead of an integer I would like to print bla
P.S I must not change the line x = int(input()), else I would've solved it easily
I would change the x = int(input()) line, but since you ask, here is an ugly hack wich exploits the format of a ValueError message:
invalid literal for int() with base 10: 'foobar'
by splitting it at first : and removing surrounding ':
try:
x = int(input())
except ValueError as e:
original_input = str(e).split(":")[1].strip()[1:-1]
print(original_input)
by the way, if you are still using Python 2.x, you should use raw_input instead of input. In fact old input will automatically attempt a conversion to int if possible:
try:
x = int(raw_input())
except ValueError as e:
original_input = str(e).split(":")[1].strip()[1:-1]
print original_input
What appears when you print var?
Until you provide that information, here is a possible hackish solution:
try:
x = int(input())
except NameError as var:
e = str(var)
print e[6:-16]
This is assuming var is equal to
NameError: name 'user_input' is not defined
where user_input is the user's input.
EDIT: This post assumed the code was running in Python 2.x whereas it seems to be running with Python 3. Leaving this up in case people are wondering for Python 2
This is hack that reads the input from the passed error message. It handles quotes in the input string and backslashes correctly.
#We get input from the user
try:
x = int(input())
except ValueError as var:
#we need to find the text between the quotes in the error message
#but we don't know what kind of quote it will be. We will look for
#the first quote which will be the kind of quotes.
#get the location or existence of each kind of quote
first_dquote = str(var).find('"')
first_squote = str(var).find("'")
used_quote = 0
#if double quotes don't exist then it must be a single quote
if -1 == first_dquote:
used_quote = first_squote
#if single quotes don't exist then it must be a dubble quote
elif -1 == first_squote:
used_quote = first_dquote
#if they both exist then the first one is the outside quote
else: used_quote = min(first_squote,first_dquote)
#the output is what is between the quotes. We leave of the end
#because there is the end quote.
output = str(var)[used_quote+1:-1]
#but the error message is escaped so we need to unescape it
output = bytes(output,"utf_8").decode("unicode_escape")
#print the output
print(output)

Converting string to int in serial connection

I am trying to read a line from serial connection and convert it to int:
print arduino.readline()
length = int(arduino.readline())
but getting this error:
ValueError: invalid literal for int() with base 10: ''
I looked up this error and means that it is not possible to convert an empty string to int, but the thing is, my readline is not empty, because it prints it out.
The print statement prints it out and the next call reads the next line. You should probably do.
num = arduino.readline()
length = int(num)
Since you mentioned that the Arduino is returning C style strings, you should strip the NULL character.
num = arduino.readline()
length = int(num.strip('\0'))
Every call to readline() reads a new line, so your first statement has read a line already, next time you call readline() data is not available anymore.
Try this:
s = arduino.readline()
if len(s) != 0:
print s
length = int(s)
When you say
print arduino.readline()
you have already read the currently available line. So, the next readline might not be getting any data. You might want to store this in a variable like this
data = arduino.readline()
print data
length = int(data)
As the data seems to have null character (\0) in it, you might want to strip that like this
data = arduino.readline().rstrip('\0')
The problem is when the arduino starts to send serial data it starts by sending empty strings initially, so the pyserial picks up an empty string '' which cannot be converted to an integer. You can add a delay above serial.readline(), like this:
while True:
time.sleep(1.5)
pos = arduino.readline().rstrip().decode()
print(pos)

Categories

Resources