basic encryption in python using loop and if elif - python

I am trying to make a caesar cipher encryption program in python using loop and if/elif, but I my program returns unwanted results. There may be a little error in my programming logic and maybe someone wants to help me to fix it.
this input :
caesar
2
and should show an output:
ecguct
but my program show output : caesar #thats wrong
This my code I'm trying:
x = []
ch = ""
i = 0
x = input(" enter words : ")
y = int(input("enter number : "))
for i in range(len(x)):
i+1
ch = x[i]
if(ord(ch)>=ord('a') and ord(ch)<=ord('z')):
chr(ord(ch)+y)
elif(ord(ch)>ord('z')):
(ord(ch)- ord('z')-ord('a')-1)
x[i]=ch
elif(ord(ch)>=ord('A') and ch<=ord('Z')):
chr(ord(ch)+y)
elif(ord(ch)>ord('Z')):
(ord(ch)- ord('Z')+ord('A')-1)
x[i]=ch
print(x)
I feel unsure about iteration that I made i+1 , and also x[i]=ch it's right syntax?. Also I use ord() to change value string to integer. I need your opinion to fix it.

You got several bugs in your code. First of all you have to turn your calculations to char again using the chr() function. Sometimes you do, sometimes you don't. Then you can't index strings - here x[i]=ch. Instead you have to assign your result to a new string using += operator or some other append method. At last your if and elif does not cover the overflows it should. In case you input a string with a letter y, z, Y or Z it will overflow. The if-questions covering those overflows need to be nested inside the top level if-elif which processes the different upper case and lower case letters.
There is also a minor bug within the overflow calculation where you use a - minus instead of a + plus operation.
Here is the slightly fixed version of your code:
x = input(" enter words : ")
y = int(input("enter number : "))
y = y % 26 # limit y to the amount of possible letters
result = ""
for ch in x:
if(ch>='a' and ch<='z'):
ch = chr(ord(ch)+y)
if(ch>'z'):
ch = chr(ord(ch)- ord('z')+ord('a')-1)
elif(ch>='A' and ch<='Z'):
ch = chr(ord(ch)+y)
if(ch>'Z'):
ch = chr(ord(ch)- ord('Z')+ord('A')-1)
result += ch
print("input:", x)
print("output:", result)
You also can iterate directly over the letters of a string like 'for ch in x' does without the need of extra indexing with x[i]. The ord(...) function is not required for comparison of characters.
Some further shrinking:
x = input(" enter words : ")
y = int(input("enter number : "))
result = "".join ( [ [ # encrypting a string by adding a number to all letters
c, chr((ord(c)-ord('Aa'[c.islower()])+y)%26+ord('Aa'[c.islower()]))
] [ c.isalpha() ] for c in x ] )
print("output:", result)
This code is harder to read and should cover some remarks on what it actually does. If you have some more code, shrinking might make it easier to understand because otherwise you have tons of files and modules within a project.

Related

Why is my function not prompting me to enter input?

I’m using Python IDE 3. My goal is this: If I have a string of text, ‘ABCDEFGHIJKL’, I want to sort it into groups, like three groups (‘ADGJ’,’BEHK’,’CFIL’). I require input for this, but the prompts aren’t showing up and I can’t type in input. Here’s my code:
#data
code_text = input('Text: ').lower()
code_skip = int(input('Shift length: '))
code_list = []
#function
def countSkip(text, shift, listt):
i = 0
group = 1
if group <= shift:
for e in text:
#make sure the set starts at the right place
if e.index()+1 < group:
pass
elif shift != 0:
if i = shift:
listt.append(e)
i = 0
i += 1
else:
listt.append(e)
group += 1
Calling the function
countSkip(code_text, code_shift, code_list)
There's a few things stopping your code from working that people have pointed out in the comments. Instead of trying to dissect your code and get that to work, I wrote a much more concise function that will get you the results you're after
def text_splitter(input_text, set_length):
num_sets = int(len(input_text)/set_length)
split_text = ["".join([input_text[(n * num_sets) + m] for n in range(set_length)]) for m in range(num_sets)]
return split_text
text_to_split = input('Text: ').lower()
len_set = int(input('Set Length: '))
text_list = text_splitter(text_to_split, len_set)
Sorry I was struggling to name the variables in an effective manner but the function above uses a list expression to get you the results you need. Keep in mind that if you use say a 7 letter string and ask for sets of length 2, the last letter won't be appended. However this shouldn't be too hard to check and correct. For example you could add this code to the function or around the initial input for the set length:
while len(input_text) % set_length != 0:
set_length = int(input("The text is length " + str(len(input_text)) + " please enter a different set length: "))

How to convert user input into a list and remove all occurrences of a particular digit or character?

I assume I am tackling this problem from the wrong angles or lack the proper understanding of built-in functions and syntax to resolve my issues despite my trying. I also discovered using:
input("Enter input: ")
is dangerous and should use raw_input instead, but can't seem to get this functioning correctly.
I want to write a script that can take user input, convert it into a list, multiply each individual element by 3, scan the solution to that problem for any "3" and remove all occurences of "3" while maintaining all other figures in their respective elements in the list, to then print or return the final result.
ex. entering 1 2 3 would output 6 9 as 1 * 3 = 3 which would be omitted.
ex. entering 2 6 11 would output 6 18 as 11 * 3 = 33 and both 3's would be omitted.
If for instance, user was to input x where x * 3 = 2381193 - I want for this to be converted to 28119.
I believe the simplest way to do this would be to convert to a string?
I started with something like this:
userInput = input("list element seperated by space: ")
nums = userInput.split()
x = int(nums[0]) * 3
y = int(nums[1]) * 3
z = int(nums[2]) * 3
output = x, y, z
negate = list(output)
if "3" in str(x):
del negate[0]
if "3" in str(y):
del negate[1]
if "3" in str(z):
del negate[2]
print(negate)
and now I've re-thought it to:
userInput = raw_input("list element seperated by space: ")
nums = userInput.split()
for x in list(nums):
numsList = int(x) * 3
output = list(numsList)
y = "3"
while y in str(output): output.remove(y)
print(output)
But overall, I am unable to achieve the desired result.
Could you please provide feedback?
It would be greatly appreciated :)
In your case, your first snippet was close to making a solution to your problem. The only thing you would want to do, is to change the conditional statement into an interative statement, like so:
nums = str(input("list element seperated by space: ")).split(" ")
num_list = []
if len(nums) != 1:
num_list = [*(int(num.replace("3", "")) * 3 for num in nums)]
else:
num_list = [nums[0]]
for x in num_list:
if x != 3:
print(str(x).replace("3", "") + " ", end="")
else:
print("0 ", end="")
If you input 11 you would receive 0 and if for instance you had 133 - you would want to remove the 3 but keep the 1.
This part of your question is not clear/elaborated enough hence i did not include this logic in my snippet above. So anyone is free to edit my answer and include it once the point above is clear.
[EDIT]: So i made changes to my snippet above. I have not tested this so there is a chance for it to be wrong. If that is the case, then inform me of any specific patterns/tests that would end as unwanted.

Linear Search - Matching integer with list

Hi am new to python here is what am trying to do , i have this below list.
x= [1,2,3,4,5,6,7,8,9]
and here is my python code:
length = len(x)
c = input("Enter a no\n")
for i in range (length):
if x[i] == c:
print ("Found at position ", i)
else:
print("not found")
and the output am receiving.
Enter a no
2
not found
not found
not found
not found
not found
not found
not found
not found
not found
Now with my very few little knowledge what i figured out is this multiple not found is happening because every time loop takes a no checks with the list and if its not available its moving to else part due to lack no proper beak statement but what am not able to figure out that when it takes to in x[i] its matching then output should be Found at position 1 . i read somewhere need to use if c in x[i] but it didn't work. on the hand i re-wrote the code.
def ls():
t = int(input("Enter your search no \n"))
for i in x:
if i!= t:
continue
print("Your value is present in ")
break
else:
print ("parrrrrrrrrrr")
ls()
which is working all good. It will be of help if i can get to know:
with 1st program why its showing not found even the input is present in the list
the part where c in x[i] was entered same issue happened as per my knowing (which now makes no-sense) it should also work
if it is the case of integer vs list then how my 2nd code is working
-is it the rigt way to do linear search.
Because input returns you a str object and then compared with int object without implicit conversion, so the expression always be False.
c in x where x is a list works, but x[i] is an integer in your case
2nd code is working because you convert the input into int implicitly
The most elegant way in my opinion is:
c = input("Enter a no\n")
items = [1,2,3]
print(items.index(int(c)) if int(c) in items else 'Not found')
And of course dont forget to catch ValueError if input is not convertable into integer

Python Vigenere working, but I can't account for the spaces and non alphabetical characters using functions

I am currently working on a cipher program for a beginners python course. We first were told to create a function that would return the position of a given letter, using a string of the alphabet as a reference (that is my alphabet_position function.) Next, we were told to make a function that would allow for a single letter to be rotated by a chosen number(that is my rotate_character function). Third, we were tasked with creating a basic caesar cipher using the previous two functions. All of those I was able to make work as demonstrated by my code below.
The vigenere, however, is proving much more difficult. I was actually able to find a snippet of code that I was able to modify with my first function (alphabet_position) to make work if only alphabetic characters are used, but as soon as i enter any non alphabetical character (such as ! or ?) I get a return of ValueError: Substring Not found. When the program encounters these non alphabetical characters, the key is supposed to skip over them and carry the Nth character of the key to the next alphabetical character.
I am guessing the answer lies in somehow incorporating my rotate_character function into my Encrypt function, but I am unsure how to do this, as the rotate_character function expects a alphabetical character, and the vigenere function turns that parameter into an int before running it through.
Any advice? And as I am a new programmer, I will gladly take any other helpful criticism on my coding practices you may want to instill!`
> #Create function alphabet_position(letter) to turn letter into number
> #such as a=0 or e=4, using lowercase to make sure case doesnt matter.
alphabet = "abcdefghijklmnopqrstuvwxyz"
def alphabet_position(letter):
> lower_letter = letter.lower() #Makes any input lowercase.
> return alphabet.index(lower_letter) #Returns the position of input
as a number.
>
> def rotate_character(char, rot):
> if char.isalpha():
> a = alphabet_position(char);
> a = (a + rot) % (int(len(alphabet))); #needs modulo
> a = (alphabet[a]);
> if char.isupper():
> a = a.title()
> return a
> else:
> return char
>
> def caesar(text, rot):
> list1 = ""
> for char in text:
> list1 += rotate_character(char, rot)
> return list1
>
> def vigenere(text,key):
m = len(key)
>
> newList = ""
>
> for i in range(len(text)):
text_position = alphabet_position(text[i])
key_position = alphabet_position(key[i % m])
value = (text_position + key_position) % 26
newList += alphabet[value]
return newList
>
> def main():
> x = input("Type a message: ")
> y = input("Rotate by: ")
> result = vigenere(x, y)
> print (result)
>
> if __name__ == '__main__':
main()
No, you don't need the rotate function anymore. You just need to directly add any character that is not in the alphabet to newlist and then skip the encryption part.
Now a sub-optimal way of doing this is to use if ... in ...:
if text[i] in alphabet:
# do your thing
else:
newList += text[i]
Of course more optimal is to only go through the alphabet once and use a variable:
pt_c = text[i]
pt_i = alphabet.find(pt_c) # returns -1 instead of an error when not found
if pt_i == -1:
newList += pt_c
else:
newList += pt_c
# do your thing *with the given index*
This won't make any difference in the runtime for a Vigenère cipher of course. But it shows you how to think of efficient programming for later: there is no need to search twice.
You could also continue the loop instead of having an else statement:
pt_c = text[i]
pt_i = alphabet.find(pt_c) # returns -1 instead of an error when not found
if pt_i == -1:
continue
# do your thing with the given index
this will make the indentation depth of your loop (the amount of scopes) less, with the unfortunate side effect of making your loop more complex (creating a local exit point).

Line 8: ValueError: invalid literal for int() with base 10: ' '

I'm a beginner programmer. I want to write a program that gives me the maximum product of all the products of 4-adjacent digits in an input number.
So, if the input is "12345678"
Possible selections are 1234, 2345,3456,4567,5678 and the largest product is 5*6*7*8.
My code:
number = str(input("Enter a number:"))
i = 0
L = []
while (i!=len(number)-3):
a = int(number[i])
b = int(number[i+1])
c = int(number[i+2])
d = int(number[i+3])
product = a*b*c*d
L.append(product)
i = i+1
print(L)
print(number)
print(max(L))
I need to apply this to a 1000-digited number. My code works for 8-digited input number and gave an answer for a 500-digited number.
But I tried it with a 600-digited number and it throws this error.
I understand ValueError is an error that appears when the argument given to a function call has correct type, but inappropriate value. There are also examples of when the user gives a string "Alexander" as input in code Eg: int(input("Enter a number"))
the error is for '' an empty string that cannot be converted to an integer. But I cannot understand where/why the empty string was formed.
I have read a few other answers of this Error type, but all involve code that use features of Python I am NOT familiar with and hence cannot understand. I'm just a beginner! So, please help!
And apologies for breaking any rules laid out with regards to question formation!
You've got a space there, not an empty string. Most likely, you just hit the space bar at the end of your input, and Python can't convert that to an integer. You can either just ensure that you don't leave a space at the end, or do some checking of your input (e.g., add a line number = number.strip() to remove any trailing whitespace).
Validate your input as numeric, and strip any whitespace:
number ='123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
def foo(number):
number = number.strip()
if number.isdigit():
i = 0
L = []
while (i in range(len(number)-3)):
a = int(number[i])
b = int(number[i+1])
c = int(number[i+2])
d = int(number[i+3])
product = a*b*c*d
L.append(product)
i = i+1
return max(L)
This functions should return a None if user has provided invalid input (e.g., "Alexander"), this should avoid the error you describe:
There are also examples of when the user gives a string "Alexander" as input in code Eg: int(input("Enter a number"))
You can also simplify this using a generator statement for a set of only the unique results:
def foo2(number):
number = number.strip()
if number.isdigit():
return max({int(number[i]) * int(number[i+1]) * int(number[i+2]) * int(number[i+3]) for i in range(len(number)-3)})

Categories