While I am trying to solve Caesar cipher, I faced few problems.
#enciphered message = 'I wtvp olel decfnefcpd lyo lwrzctesxd'
plain = 'abcdefghijklmnopqrstuvwxyz'
cipher = 'lmnopqrstuvwxyzabcdefghijk'
cipher_text = input('Enter enciphered message: ')
clean_text = ' '
for i in cipher_text:
if i != " ":
clean_text = clean_text + plain[plain.index(cipher[(ord(i)-ord('a'))])]
else:
clean_text = clean_text + " "
print(clean_text)
Above is the code, that I created and this is what I got as a result:
Enter enciphered message: I wtvp olel decfnefcpd lyo lwrzctesxd
n hega zwpw opnqypqnao wjz whcknepdio
Here are my related questions:
Why wasn't it decoded properly? Like, It should be 'I like data structures and algorithms'
I'm also confused about the capital "I" at the beginning of the enciphered message. Do you have any insight on that?
Finally I have no idea how to decode uppercase and lowercase at the same time; how should I do that?
(1) Why wasn't it decoded properly? Like, It should be 'I like data structures and algorithms'
First of all, the alphabet is already present in ASCII. So there is no need to redefine the alphabet in plain or cipher. The key is the offset from the plaintext character to the ciphertext character, wrapping around directly after the z.
So you generally convert from a character to an index in the alphabet from 0..25, then you add (for encryption) or subtract (for decryption) the key, modulo 26 - the size of the alphabet. Then, to get the result, you convert back into a character. You're already doing the conversion to index using ord(character) - ord(a). The opposite can be done using chr.
(2) I'm also confused about the capital "I" at the beginning of the enciphered message. Do you have any insight on that?
Well, there are more possibilities for single character words. The word A would be a prime suspect.
(3) Finally I have no idea how to decode uppercase and lowercase at the same time; how should I do that?
The best way is to create a variable that indicates that something is uppercase or not; is_uppercase would be a good name. Then convert the character to lowercase. Perform the encryption / decryption operation and then convert the resulting character back into uppercase, if required. That way your encryption / decryption operation is not affected at all and kept relatively simple.
Related
This is one of the practice problems from Problem solving section of Hackerrank. The problem statement says
Steve has a string of lowercase characters in range ascii[‘a’..’z’]. He wants to reduce the string to its shortest length by doing a series of operations. In each operation he selects a pair of adjacent lowercase letters that match, and he deletes them.
For example : 'aaabbccc' -> 'ac' , 'abba' -> ''
I have tried solving this using slicing of strings but this gives me timeout runtime error on larger strings. Is there anything else to be used?
My code:
s = list(input())
i=1
while i<len(s):
if s[i]==s[i-1]:
s = s[:i-1]+s[i+1:]
i = i-2
i+=1
if len(s)==0:
print("Empty String")
else:
print(''.join(s))
This gives me terminated due to timeout message.
Thanks for your time :)
Interning each new immutable string can be expensive,
as it has O(N) linear cost with the length of the string.
Consider processing "aa" * int(1e6).
You will write on the order of 1e12 characters to memory
by the time you're finished.
Take a moment (well, take linear time) to
copy each character over to a mutable list element:
[c for c in giant_string]
Then you can perform dup processing by writing a tombstone
of "" to each character you wish to delete,
using just constant time.
Finally, in linear time you can scan through the survivors using "".join( ... )
One other possible solution is to use regex. The pattern ([a-z])\1 matches a duplicate lowercase letter. The implementation would involve something like this:
import re
pattern = re.compile(r'([a-z])\1')
while pattern.search(s): # While match is found
s = pattern.sub('', s) # Remove all matches from "s"
I'm not an expert at efficiency, but this seems to write fewer strings to memory than your solution. For the case of "aa" * int(1e6) that J_H mentioned, it will only write one, thanks to pattern.sub replacing all occurances at once.
While importing data from a flat file, I noticed some embedded hex-values in the string (<0x00>, <0x01>).
I want to replace them with specific characters, but am unable to do so. Removing them won't work either.
What it looks like in the exported flat file: https://i.imgur.com/7MQpoMH.png
Another example: https://i.imgur.com/3ZUSGIr.png
This is what I've tried:
(and mind, <0x01> represents a none-editable entity. It's not recognized here.)
import io
with io.open('1.txt', 'r+', encoding="utf-8") as p:
s=p.read()
# included in case it bears any significance
import re
import binascii
s = "Some string with hex: <0x01>"
s = s.encode('latin1').decode('utf-8')
# throws e.g.: >>> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 114: invalid start byte
s = re.sub(r'<0x01>', r'.', s)
s = re.sub(r'\\0x01', r'.', s)
s = re.sub(r'\\\\0x01', r'.', s)
s = s.replace('\0x01', '.')
s = s.replace('<0x01>', '.')
s = s.replace('0x01', '.')
or something along these lines in hopes to get a grasp of it while iterating through the whole string:
for x in s:
try:
base64.encodebytes(x)
base64.decodebytes(x)
s.strip(binascii.unhexlify(x))
s.decode('utf-8')
s.encode('latin1').decode('utf-8')
except:
pass
Nothing seems to get the job done.
I'd expect the characters to be replacable with the methods I've dug up, but they are not. What am I missing?
NB: I have to preserve umlauts (äöüÄÖÜ)
-- edit:
Could I introduce the hex-values in the first place when exporting? If so, is there a way to avoid that?
with io.open('out.txt', 'w', encoding="utf-8") as temp:
temp.write(s)
Judging from the images, these are actually control characters.
Your editor displays them in this greyed-out way showing you the value of the bytes using hex notation.
You don't have the characters "0x01" in your data, but really a single byte with the value 1, so unhexlify and friends won't help.
In Python, these characters can be produced in string literals with escape sequences using the notation \xHH, with two hexadecimal digits.
The fragment from the first image is probably equal to the following string:
"sich z\x01 B. irgendeine"
Your attempts to remove them were close.
s = s.replace('\x01', '.') should work.
Below is a shortened version of my code, without all the validation. I am writing a program that tells the user how strong their password is, by seeing their overall score at the end. If the password has 3 letters next to each other in a row, and those three letters are also next to each other on the 'qwerty' keyboard, then their overall score goes down by 5. I have created a dictionary to assign each letter on the keyboard a value, and then if 2 consecutive letters in the password have a difference of 1, it means there are 3 letters in a row on the keyboard.
However, I keep getting a
ValueError: invalid literal for int() with base 10:
I don't really know how to use dictionaries, so any help is much appreciated!
password=str(input("Please enter a password with more than 4 digits, and it should only be letters:"))
score=0
keyboard={'Q':1,'q':1,'W':2,'w':2,'E':3,'e':3,'R':4,'r':4,'T':5,'t':5,'Y':6,'y':6,'U':7,'u':7,'I':8,'i':8,'O':9,'o':9,'P':10,'p':10,'A':12,'a':12,'S':13,'s':13,'D':14,'d':14,'F':15,'f':15,'G':16,'g':16,'H':17,'h':17,'J':18,'j':18,'K':19,'k':19,'L':20,'l':20,'Z':22,'z':22,'X':23,'x':23,'C':24,'c':24,'V':25,'v':25,'B':26,'b':26,'N':27,'n':27,'M':28,'m':28}
for n in range ((len(password))-2):
if (int(password[n+1])-int(password[n])==1) and (int(password[n+2])-int(password[n+1]==1)):
score=score-5
print(score)
If your password input is only letters, then this following line will raise an error.
int(password[n+1])
and so will int(password[n]) and all your other int casts. The reason for this is because you're casting non-digit characters to int. That's what's causing the error you're seeing.
I believe, your intention is to do
int(keyboard[password[n+1]]) - int(keyboard[password[n]]) == 1
but since, the values of your keyboard dictionary are already int's, then the int casts in your if-statement are not required.
keyboard[password[n+1]] - keyboard[password[n]] == 1
i am not getting the desired results for Cryptopals challenge 4 set 1.
The concept of the program to check to see if any of these 300ish strings have been XORd by a single character. So with a brute force, my solution is take every string, XOR it with every character on the keyboard, and check to see if any of these results produce an english sentence. if not, then check the next string. Here is my code:
MY_DICT = {}
index = 0
my_plaintext = "Now that the party is jumping"
#fills the dictionary with hex strings from the txt file
with open("hexstrings.txt") as f:
my_list = f.readlines()
for x in my_list:
MY_DICT[index] = x.rstrip('\n')
index = index + 1
i=0
input() #this is just here to help me keep track of where i am when running it
#this loop fills possible_plaintext with all the possible 255 XORs of the i'th string
#of the dictionary that was previously filler from the txt file
for i in range(326):
possible_plaintexts = brute_force_singlechar_xor(MY_DICT[i])
print(possible_plaintexts)
if possible_plaintexts == my_plaintext: #line of concern
print("ya found it yay :) ")
Im sure that myBruteForce function works because it worked properly on the last problem where i XORd every possible char against a string. and i also know that the plaintext is the one provided bc i saw the solution. im just not sure why my program isnt recognizing that the plaintext is not in the dictionary.
(i am aware that using a scoring system to score every string to see if its close to english would be easier, but this is the way i chose to do it for now until i figure out how to get my scoring function to work /: )
How is your dictionary "possible_plaintexts" like when you print it?
Can you spot the solution in the printed text? How is it printed?
The decrypted string should also have a '\n' character.
The string I am given is as follows:
scrap1 =
a le h
ke fd
zyq b
ner i
You'll notice there are 2 blank spaces indicating a space (ASCII 32) in each row. I need to find the mean ASCII value in each column without taking into account the spaces (32). So first I would convert to with double(scrap1) but then how do I find the mean without taking into account the spaces?
If it's only the ASCII 32 you want to omit:
d = double(scrap1);
result = mean(d(d~=32)); %// logical indexing to remove unwanted value, then mean
You can remove the intermediate spaces in the string with scrap1(scrap1 == ' ') = ''; This replaces any space in the input with an empty string. Then you can do the conversion to double and average the result. See here for other methods.
Probably, you can use regex to find the space and ignore it. "\s"
findSpace = regexp(scrap1, '\s', 'ignore')
% I am not sure about the ignore case, this what comes to my mind. but u can read more about regexp by typying doc regexp.