Python2 increment string in an alphanumeric format - string

I'm looking for a snippet which does stuff like :
from 'abcd8' string
i want to increment it like 'abcd9' then 'abcda' ... >'abcdz' and next 'abce0', 'abce1' ... 'abcez', 'abcf0' ....
Can't find a way to do it :(
I already tried stuff like using 'aaaa'.encode('hex') then increment it, but not working :(
Thanks for help,
Cheers !

Here is a way of doing it:
# written by 'imerso' to a StackOverflow answer
def increment(os):
s = list(os)
p = len(os)-1
while (p >= 0):
s[p] = chr(ord(s[p]) + 1)
if s[p] > 'z':
s[p] = '0'
p -= 1
continue
if s[p] > '9' and s[p] < 'a':
s[p] = 'a'
return ''.join(s)
s = raw_input("String: " )
for x in range(1, 32):
s = increment(s)
print s

Related

Why isn't chr() outputting the correct character?

I'm working on a Caesar Cypher with Python 3 where s is the string input and k is the amount that you shift the letter. I'm currently just trying to work through getting a letter like 'z' to wrap around to equal 'B'(I know the case is wrong, I'll fix it later). However when I run caesarCipher using the the following inputs: s = 'z' and k = 2, the line: s[n] = chr((122-ord(s[n]) + 64 + k)) causes s[n] to equal 'D'. If i adjust it down two(logically on the unicode scale this would equal 'B'), it makes s[n] = #. What am I doing wrong on that line that's causing 'B' not to be the output?
def caesarCipher(s, k):
# Write your code here
n = 0
s = list(s)
while n < len(s):
if s[n].isalpha() == True:
if (ord(s[n].lower())+k) < 123:
s[n] = (chr(ord(s[n])+k))
n += 1
else:
s[n] = chr((122-ord(s[n]) + 64 + k))
else:
n += 1
s = ''.join(s)
return s
You forgot to add 1 to n in the test of (ord(s[n].lower())+k) < 123 so that it would count s[n] twice or more.
Change it to
else:
s[n] = chr((122 - ord(s[n]) + 64 + k))
n += 1
and if you input "z" and 2, you'll get "B"
print(caesarCipher("z", 2))
# B
and if you adjust it down two, you'll get "#", which is the previous previous character of B in ASCII.
...
else:
s[n] = chr((122 - ord(s[n]) + 62 + k))
n += 1
...
print(caesarCipher("z", 2))
# #

local variable 'z' referenced before assignment

I've had a look around at older posts on this topic but can't see how to apply the knowledge to my code,
I'm trying to turn two functions into 1 as they are very similar but while trying to execute the function I get a:local variable 'z' referenced before assignmenterror,
and here is the code:
code_a = ['h','e','l','o']
code_b = ['d','t','u','x']
def encrypt(word, a):
if a == 'encrypt':
z = code_a
y = code_b
elif a == 'decrypt':
z = code_b
y = code_a
newword = ''
for char in word:
x = 0
found = False
while found == False:
if z[x] == char:
newword = newword + y[x]
found = True
x += 1
return newword
x = encrypt('hello', 'encrypt')
print(x)
any help would be greatly appreciated thanks in advance
EDIT: After messing around with my code I figured out that the problem was the uncertainty of z and 'y' so I got rid of the elif statement and swapped the values in the if statement and added an else statement to make the default what the original if statement was.

How to turn the duplicate part in my code to a checking function?

I come up a solution for leetcode "5. Longest Palindromic Substring" with parts of duplicate codes. One of good ways to solve duplicate code is to make a function. How do I write my check here to a function? I am confused what I should return to make both variables - longest and ans - being updated. Thanks!
The part of duplicate code:
if len(s[l:r+1]) > longest:
longest = len(s[l:r+1])
ans = s[l:r+1]
Full code:
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) == 0:
return ''
if len(s) == 1:
return s
longest = 0
ans = ''
for pos in range(len(s)-1):
l, r = pos, pos
if pos > 0 and pos < len(s) - 1 and s[pos-1] == s[pos+1]:
l, r = pos-1, pos+1
while l > 0 and r < len(s) - 1 and s[l-1] == s[r+1]:
l -= 1
r += 1
# duplicate code 1
if len(s[l:r+1]) > longest:
longest = len(s[l:r+1])
ans = s[l:r+1]
if s[pos] == s[pos+1]:
l, r = pos, pos+1
while l > 0 and r < len(s) - 1 and s[l-1] == s[r+1]:
l -= 1
r += 1
# duplicate code 2
if len(s[l:r+1]) > longest:
longest = len(s[l:r+1])
ans = s[l:r+1]
if ans == '' and len(s) > 0:
return s[0]
return ans
The if statements and while loops before the duplicate code blocks are mostly duplicated as well, as is using the longest variable to keep track of the length of ans when you already have ans -- here's one way you could simplify things via another function:
class Solution:
def find_longest(self, s, left, right):
if s[left] == s[right]:
if right - left + 1 > len(self.ans):
self.ans = s[left:right + 1]
if left > 0 and right < len(s) - 1:
self.find_longest(s, left - 1, right + 1)
def longestPalindrome(self, s: str) -> str:
if len(s) == 1:
return s
self.ans = ''
for pos in range(len(s) - 1):
self.find_longest(s, pos, pos)
self.find_longest(s, pos, pos + 1)
return self.ans

Unable to solve this issue with the code

I am having some issues with this question for which i have tried to make 2 solutions.The first one works partially but the second one does not.Here is the question
Question with which i am having the issue.Has sample input and output
Here are the 2 codes which i have written
number=int(input())
S=input()
w=list(S[:])
w_count=0
other_count=0
v_count=0
vv_count=0
i=0
while(i<(len(w))):
try:
if w[i]=='w':
w_count+=1
elif w[i]=='v' and w[i+1]=='v':
vv_count+=1
i+=1
else:
other_count+=1
except IndexError:
pass
i+=1
max_length=w_count*2+other_count+v_count
min_length=0
min_length=w_count+other_count+vv_count
print(min_length,max_length)
The other Logic has been implemented with the help of a for loop for which 3 test cases are passing
for value in range(len(w)):
try:
if w[value]=='w':
w_count+=1
elif w[value]=='v' and w[value+1]=='v':
vv_count+=1
else:
other_count+=1
except IndexError:
pass
If think you can keep it simple with:
my_string = "avwvb"
max_len = len(my_string.replace("w", "vv"))
min_len = len(my_string.replace("w", "vv").replace("vv", "w"))
print(max_len, min_len)
Or a little faster:
my_string = "avwvb"
max_string = my_string.replace("w", "vv")
min_string = max_string.replace("vv", "w")
max_len = len(max_string)
min_len = len(min_string)
print(max_len, min_len)
You can try this. It's similar to your for loop solution but uses string indexing a bit better.
For the first problem I'm just expanding the string as much as possible changing all ws into 2 vs.
The second is a bit trickier. I first expand the string using the previous method, and then build a new string where any vv combinations can be turned into w. I use 2 indexes, i for the longer string and j for the shorter version of the string, in order to avoid index errors.
def longer(s):
for i in range(0,len(s)):
x = s[i]
if x == 'w':
new_str = s[:i] + 'v' + s[i+1:]
if (i + 1 >= len(s)):
new_str = new_str + 'v'
else:
new_str = new_str[:i] + 'v' + new_str[i:]
s = new_str
return s
def shorter(s):
long_str = longer(s)
short_str = long_str[0]
j = 1
for i in range(1,len(long_str)):
x = long_str[i]
if x == 'v' and short_str[j-1] == 'v':
short_str = short_str[:j-1] + 'w'
j = j -1
else:
short_str = short_str + x
j = j +1
return short_str
print len(longer("avwvb"))
print len(shorter("avwvb"))

Simplify counting and appending to a list

Okay there must be a much more cleaner way to do this. I am still an amateur programmer but I feel like they have something that can shorten this. So basically I have this data set of numbers and I am counting the occurrences of 1, 2, 3, 4, 5, 6, 7, 8, 9 as the first digit and then appending the count to a list. This definitely seems long that I have to do it in this way
countList = []
for elm in pop_num:
s = str(elm)
if (s[0] == '1'):
count1 += 1
if (s[0] == '2'):
count2 += 1
if (s[0] == '3'):
count3 += 1
if (s[0] == '4'):
count4 += 1
if (s[0] == '5'):
count5 += 1
if (s[0] == '6'):
count6 += 1
if (s[0] == '7'):
count7 += 1
if (s[0] == '8'):
count8 += 1
if (s[0] == '9'):
count9 += 1
countList.append(count1)
countList.append(count2)
countList.append(count3)
countList.append(count4)
countList.append(count5)
countList.append(count6)
countList.append(count7)
countList.append(count8)
countList.append(count9)
You can do this in two lines using collections.Counter (basically a special dict designed for counting things) and list comprehensions (a more concise syntax for writing simple loops).
Here's how I'd do it.
import collections
counts = collections.Counter(str(x)[0] for x in pop_num)
countList = [counts[str(i)] for i in range(1,10)]
Edit: Here's how to get equivalent functionality without using collections.
counts = {}
for x in pop_num:
k = str(x)[0]
counts.setdefault(k, 0)
counts[k] += 1
countList = [counts[str(i)] for i in range(1,10)]

Resources