Python encoding key, minus one character if too long - python

Here is my code so far:
def code_block(text, key):
itext = int(text)
rkey = int(key)
res= itext + rkey
def last():
return res[-1:]
if res>=11111111:
last()
return res
Here is the task I've been set:
Now we need a function to take a block of code and a key as input, where both are assumed to be 8 digits long, and encrypts each digit of the number with the corresponding digit of the key:
>>> code_block('12341234','12121212')
'24462446'
>>> code_block('66554433','44556677')
'00000000'
Where am I going wrong? Could you point me in the right direction and indicate me how I was wrong?

You are going about this the wrong way. Treat this character by character:
def code_block(text, key):
res = [str(int(c) + int(k))[-1:] for c, k in zip(text, key)]
return ''.join(res)
which gives me:
>>> code_block('12341234','12121212')
'24462446'
>>> code_block('66554433','44556677')
'00000000'
The code sums each and every character separately, turning it back into a string and only using the last character of the result; 9 + 9 is 18, but the result would be '8'.
Your code would sum the whole numbers, but that would result in:
>>> 66554433 + 44556677
111111110
which is not the correct result. Neither did you ever turn your sum back into a string again, so your code, attempting to treat the sum result as a string by slicing it, gave an exception:
>>> code_block('12341234', '12121212')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in code_block
File "<stdin>", line 6, in last
TypeError: 'int' object has no attribute '__getitem__'

Related

Python XOR operation

I want XOR of characters but getting Type error:
sign value is - \xc5\x06\x92\xd0\x02k=\x91
How do I solve this?
def xor(str1, str2):
print(str1)
print(str2)
for i, j in zip(str1, str2):
value[i] = chr(ord(str[i]) ^ ord(str[j])) # Doing character by character XOR here
return value
user = xor("admin\00\00\00", sig)
print(user)
Getting Error:
Traceback (most recent call last):
File "exploit.py", line 36, in <module>
username2 = xor("rator\00\00\00", signature1)
File "exploit.py", line 32, in xor
value[i] = chr(ord(str[i]) ^ ord(str[j]))
TypeError: 'type' object is not subscriptable
As GZ0 notes, you tried to index str itself (the type), not str1 or str2 (your arguments).
As it happens, you don't need to index at all; you're already iterating the characters themselves, so all you need to do is actually declare value, and use i and j directly:
value = []
for i, j in zip(str1, str2):
value.append(chr(ord(i) ^ ord(j))) # Doing character by character XOR here
return ''.join(value)
This statement chr(ord(str[i]) ^ ord(str[j])) is indexing the built-in function str, causing the error.
value = []
for i, j in zip(str1, str2):
value.append(chr(ord(i) ^ ord(j))) # Doing character by character XOR here
return ''.join(value)
As #ShadowRanger showed above, this worked

Converting a list of tuples into a string

I'm new to run-length coding and need help. I've been given a run-length string of a series of integer followed by characters that include letters/characters.
For example, I have a string:
1-4c8k2)
And I need to convert it into:
-cccckkkkkkkk))
What I've done is convert the run-length string into a list of tuples:
[('1','-'),('4','c'),('8','k'),('2','c')]
And tried creating a function which would convert it into a string however I get a TypeError: can't multiply sequence by non-int of type 'str'.
def decode(lst):
q = ''
for count, character in lst:
q += count * character
return q
I'm trying to think of a way to improve space complexity instead of creating a new list of tuples and more so, trying to resolve this TypeError.
I suspect that what has happened is you forgot to convert the counts into ints:
>>> 3 * 'a'
'aaa'
>>> '3' * 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
>>> int('3') * 'a'
'aaa'
You try through this way :
lst = [('1','-'),('4','c'),('8','k'),('2','c')]
def decode(lst):
q = ''
for count, character in lst:
q += int(count) * character
return q
print(decode(lst))
Output :
-cccckkkkkkkkcc
Check this code here

Using str.replace to replace letters in a string at different placeholders of the string

I have a problem that I am working on. The goal of the problem is to take the string placeholder i. If i is an even placeholder, replace the letter at i with the letter at i -1. If the i place holder is odd, then replace the letter i with the letter at i +1.
Here is my code so far:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
str(s).replace(i,((i-1)))
if i % 2 != 0:
str(s).replace(i,((i+2)))
print (s)
My error:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
str(s).replace(i,((i-1)))
TypeError: Can't convert 'int' object to str implicitly
update!!
New code based on answers:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
s = str(s).replace(s(i),(s(i-1)))
else:
s = s.replace(s(i), s(i + 1))
print (s)
However I still have the following errors:
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
s = str(s).replace(s(i),(s(i-1)))
TypeError: 'str' object is not callable
Any ideas? thank you
Use s[i] instead of s(i), and likewise for the other indexes.
There are two things here:
str.replace does not automatically stringify its arguments. You need to manually convert them into strings. Remember that: "Explicit is better than implicit."
str.replace does not work in-place because strings are immutable in Python. You need to reassign s to the new string object returned by str.replace.
Your code should be:
s = s.replace(str(i), str(i-1))
Also, you can replace if i % 2 != 0: with else: since the condition of the second if-statement can only be true if the first is false:
if i % 2 == 0:
s = s.replace(str(i), str(i-1))
else:
s = s.replace(str(i), str(i+1))
Regarding your edited question, you are trying to call the string s as a function by placing parenthesis after it. You need to use square brackets to index the string:
>>> 'abcde'[0]
'a'
>>> 'abcde'[3]
'd'
>>>
In your case it would be:
s = s.replace(s[i], s[i-1])
As a general rule of thumb, parenthesis (...) are for calling functions while square brackets [...] are for indexing sequences/containers.

Why is this giving me an index error in python?

In the code below, s refers to a string (although I have tried converting it to a list and I still have the same problem).
s = "".join(s)
if s[-1] == "a":
s += "gram"
I the last item in the string is the letter "a", then the program needs to add the string "gram" to the end of the string 's' represents.
e.g. input:
s = "insta"
output:
instagram
But I keep getting an IndexError, any ideas why?
If s is empty string s[-1] causes IndexError:
>>> s = ""
>>> s[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
Instead of s[-1] == "a", you can use s.endswith("a"):
>>> s = ""
>>> s.endswith('a')
False
>>> s = "insta"
>>> s.endswith('a')
True
If s is empty, there is no last letter to test:
>>> ''[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
Use str.endswith() instead:
if s.endswith('a'):
s += 'gram'
str.endswith() does not raise an exception when the string is empty:
>>> 'insta'.endswith('a')
True
>>> ''.endswith('a')
False
Alternatively, using a slice would also work:
if s[-1:] == 'a':
as slices always return a result (at minimum an empty string) but str.endswith() is more self-evident as to what it does to the casual reader of your code.

196 algorithm with optional inputs in function

what I am trying to do:
If the user specifies return_length=True when calling your function, it should return one plus the number of steps the algorithm required to reach a palindromic number. For example, with an input of 5280 and return_length=True, your function should return 4 (Note that this is the total number of entries in the sequence [5280, 6105, 11121, 23232]). With an input of 11, for example, the function should return 1 because it is already a palindromic number.
If the user did not specify return_length or specified return_length=False, your function should return the palindromic number at which the algorithm terminates. For example, with an input of 5280, the algorithm should return 23232 (an integer, not a string). Similarly, with an input of 89, it should return the integer 8813200023188.
Some background on the 196 algorithm:
Take any positive integer of two digits or more, reverse the digits, and add to the original number. This is the operation of the reverse-then-add sequence. Now repeat the procedure with the sum so obtained until a palindromic number is obtained. This procedure quickly produces palindromic numbers for most integers. For example, starting with the number 5280 produces the sequence 5280, 6105, 11121, 23232. The end results of applying the algorithm to 1, 2, 3, ... are 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 11, 33, 44, 55, 66, 77, 88, 99, 121, ... (Sloane's A033865). The value for 89 is especially large, being 8813200023188. (from http://mathworld.wolfram.com/196-Algorithm.html)
What I have so far:
def alg196(x, y = false):
if y==False:
while x == x[::-1]:
x==x+x[::-1]
return x
else:
seq = [x]
while x == x[::-1]:
x==x+x[::-1]
seq.append(x)
return seq
I get the error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_sage_input_36.py", line 10, in <module>
exec compile(u"print _support_.syseval(python, u'alg196(34)', __SAGE_TMP_DIR__)" + '\n', '', 'single')
File "", line 1, in <module>
File "/sagenb/sage_install/sage-5.3-sage.math.washington.edu-x86_64-Linux/devel/sagenb-git/sagenb/misc/support.py", line 487, in syseval
return system.eval(cmd, sage_globals, locals = sage_globals)
File "/sagenb/sage_install/sage-5.3-sage.math.washington.edu-x86_64-Linux/local/lib/python2.7/site-packages/sage/misc/python.py", line 56, in eval
eval(z, globals)
File "", line 1, in <module>
File "", line 3, in alg196
TypeError: 'int' object has no attribute '__getitem__'
I am not sure how to fix this problem or the error exactly.
Taking some of the information for the answers i have this new code:
def alg196(x, y = false):
if y==False:
while str(x) == str(x)[::-1]:
x=str(x)+str(x)[::-1]
return x
else:
seq = [x]
while str(x) == str(x)[::-1]:
x = str(x)+str(x)[::-1]
seq.append(x)
return seq
But is still do not get the palindromic number for or the sequence to the palindromic number..
x[::-1] does not work on a number:
>>> 42[::-1]
TypeError: 'int' object has no attribute '__getitem__'
You need to convert it to a string, reverse it, then convert it back to an int:
>>> int(str(42)[::-1])
24
Secondly, the line
x==x+x[::-1]
does absolutely nothing. Don't confuse = and ==
something like this:
def algo(r,ret_len=None):
count=0
while 1:
r=str(r)
if r==r[::-1]:
break
else:
count+=1
r=int(r)+int(r[::-1])
return count+1 if ret_len else r
print (algo(5280,True))
print (algo(5280))
print (algo(89,True))
print (algo(89))
output:
4
23232
25
8813200023188
You can't get a 'slice' of an integer. You need to convert it to a string, first. x[::-1] <-- this operation is illegal if x is an integer.
Incidentally, this would be better written as a few functions-- functions that perform the calculations, and a function that runs functions while under a certain constraint, and takes in the return_length=True argument.
def reverse(n):
return int(str(n)[::-1])
def is_palindrome(n):
return str(n) == str(n)[::-1]
def alg196(n, return_length=False):
results = [n]
while not is_palindrome(results[-1]):
results.append(n + reverse(n))
n = results[-1]
return results[-1] if not return_length else len(results)
edit
A slightly quicker variation based on Ashwini Chaudhary's code. The above version produces a list of results, it's nice if you want to do something with the intermediate numbers. But, I think the following function is the best compromise between readability and speed. I have no idea why he starts with count=0 though.
def alg196(n, return_length=False):
count = 1
while not is_palindrome(n):
n = n + reverse(n)
count += 1
return count if return_length else n

Categories