I have a python function which increments the character by 1 ascii value if the index is odd and decreases the ascii value by 1 if index is even .I want to convert it to a function which do the same increment and decrement but in the next set i want to increment by 2 and then decrement by -2 then by 3 and -3 and so on..
What Iam trying to do is to increment the counter variable by 1 each time an even index occurs after performing the ascii decrement.
I also dont want to do it with a for loop is there any way to do it in the list comprehension itself?
In my function if the input is
input :'abcd' output: is 'badc' what i want is 'baeb'
input :'cgpf' output: is 'dfqe' what i want is 'dfrd'
def changer(s):
b=list(s)
count=1
d=[chr(ord(b[i])+count) if i%2==0 else chr(ord(b[i])-count) for i in range(0,len(b))]
return ''.join(d)
I need something like count++ as show but sadly python dont support it.
def changer(s):
b=list(s)
count=1
d=[chr(ord(b[i])+count) if i%2==0 else chr(ord(b[i])-count++) for i in range(0,len(b))]
return ''.join(d)
Here is the runnable code
If I correctly understood what you're after, something like this (compact form) should do:
def changer(s):
return "".join(chr(ord(c) + ((i // 2) + 1) * (-1 if i % 2 else 1))
for i, c in enumerate(s))
We get index and character from string by means of enumerate() and use that to feed a generator comprehension (as asked for) far of index (i) and character (c) from the string.
For each ASCII value of c, we add result of integer division of i (incremented by one as index was 0 based) by 2 and multiply it by (-1 if i % 2 else 1) which flips +/- based on even/odd number: multiply by -1 when modulo of i division by 2 is non-zero (and bool() evaluates as True), otherwise use 1.
Needless to say: such comprehension is not necessarily easy to read, so if you'd use it in your script, it would deserve a good comment for future reference. ;)
Combine a stream of plus/minus with the string.
import itertools
s = 'abcdefg'
x = range(1,len(s)+1)
y = range(-1,-len(s)+1,-1)
z = itertools.chain.from_iterable(zip(x,y))
r = (n + ord(c) for (n,c) in zip(z,s))
''.join(chr(n) for n in r)
I don't think I'd try to put it all in one line. Uses generator expressions instead of list comprehensions.
Try the code below,
def changer(s):
return ''.join([chr(ord(j) + (i // 2 + 1)) if i % 2 == 0 else chr(ord(j) - (i // 2 + 1)) for i, j in enumerate(s)])
s = 'abcd'
changer(s)
output
baeb
Related
I want to write a code for this question:
write a code which creates a new number 'n2' which consists reverse order of digits of a number 'n' which divides it without any remainder for example if input is 122
it will print 221 because 1,2,2 can divide 122 without any remainder another example is 172336 here 1,2,3,3,6 can divide it without any remainder so the output should be 63321(reverse order).
my code is:
n = str(input())
x = ""
z = 0
for z in range(len(n)):
if int(n)%int(n[z])==0:
x = n[z] + ""
else:
n.replace(n[z],"")
z = z+1
print(x[::-2])
if I input the number 122 here i get the output 2 but i should be getiing output of 221 why.
The reason why you are not getting the desired output in this code is because of several logical and syntactical errors in your code. Here are some of them:
You are using x = n[z] + "" to append the digits that divide n without any remainder, but this will overwrite the previous value of x every time. You should use x = x + n[z] instead.
You are using n.replace(n[z],"") to remove the digits that do not divide n without any remainder, but this will not modify the original value of n, since strings are immutable in Python. You should assign the result of n.replace(n[z],"") to a new variable, or use a different approach to filter out the unwanted digits.
You are using z = z+1 to increment the loop variable, but this is unnecessary and redundant, since the for loop already does that for you. You can remove this line.
You are using print(x[::-2]) to print the reversed value of x, but this will skip every other digit, since the negative step of -2 means you are slicing the string from the end to the beginning with a step of 2. You should use print(x[::-1]) instead, which will reverse the whole string. A possible corrected version of your code is:
python
n = str(input())
x = ""
for z in range(len(n)):
if int(n)%int(n[z])==0:
x = x + n[z]
print(x[::-1])
This code will print the reversed order of the digits of n that divide it without any remainder, as expected. For example, if the input is 122, the output will be 221.
The code works by iterating over each digit of the input number n, which is converted to a string for convenience. For each digit, it checks if it divides n without any remainder, using the modulo operator %. If it does, it appends the digit to the end of the string x, using the + operator. If it does not, it ignores the digit. After the loop, it prints the reversed value of x, using the slicing notation [::-1], which means start from the end and go backwards until the beginning.
This should do the Trick
num = input()
new_num = ""
for i in num:
if int(num)%int(i) == 0:
new_num += i
print(new_num[::-1])
I'm new to python (although it's more of a logical question rather than syntax question I belive), and I wonder what's the proper way to access two folowing objects in a loop.
I can't really provide a specific example without getting too cumbersome with my explanation but let's just say that I usually try to tackle this with either [index + 1] or [index - 1] and both are problematic when it comes to either the last (IndexError) or first (addresses the last position right at the beginning) iterations respectively.
Is there a well known way to address this? I haven't really seen any questions regarding this floating around so it made me think it's basic logic I'm missing here.
For example this peice of code that wouldn't have worked had I not wrapped everything with try/except, and also the second inner loop works only since it checks for identical characters, otherwise it could have been a mess.
(explanation for clarity - it recieves a string (my_string) and a number (k) and checks whether a sequence of identical characters the length of k exists in my_string)
# ex2 5
my_string = 'abaadddefggg'
sub_my_string = ''
k = 9
count3 = 0
try:
for index in range(len(my_string)):
i = 0
while i < k:
sub_my_string += my_string[index + i]
i += 1
for index2 in range(len(sub_my_string)):
if sub_my_string[index2] == sub_my_string[index2 - 1]:
count3 += 1
if count3 == k:
break
else:
sub_my_string = ""
count3 = 0
print(f"For length {k}, found the substring {sub_my_string}!")
except IndexError:
print(f"Didn't find a substring of length {k}")
Thanks a lot
First off, by definition you need to give special attention to the first or last element, because they really don't have a pair.
Second-off, I personally tend to use list-comprehensions of the following type for these cases -
[something_about_the_two_consecutive_elements(x, y) for x, y in zip(my_list, my_list[1:])]
And last but not least, the whole code snippet seems like major overkill. How about a simple one-liner -
my_string = 'abaadddefggg'
k = 3
existing_substrings = ([x * k for x in set(my_string) if x * k in my_string])
print(f'For length {k}, found substrings {existing_substrings}')
(To be adapted by one's needs of course)
Explanation:
For each of the unique characters in the string, we can check if a string of that character repeated k times appears in my_string.
set(my_string) gives a set of the unique characters over which we iterate (that's the for x in set(my_string) in the list comprehension).
Taking a character x and multiplying by k gives a string xx...x of length k.
So x * k in my_string tests whether my_string includes the substring xx...x.
Summing up the list-comprehension, we return only characters for which x * k in my_string is True.
If I am understanding what you are trying to achieve, I would approach this differently using string slices and a set.
my_string = "abaadddefggg"
sub_my_string = ""
k = 3
count3 = 0
found = False
for index, _ in enumerate(my_string):
if index + k > len(my_string):
continue
sub_my_string = my_string[index : index + k]
if len(set(sub_my_string)) == 1:
found = True
break
if found:
print(f"For length {k}, found the substring {sub_my_string}!")
else:
print(f"Didn't find a substring of length {k}")
Here we use:
enumerate as this usually signals that we are looking at the indices of an iterable.
Check whether the slice will be take us over the string length as there's no point in checking these.
Use the string slice to subset the string
Use the set to see if all the characters are the same.
I need to create a function that receives a positive integer number (n) and returns a string, using nested loops.
For example:
when n = 3 the returned string should be:
"1+2+3+..1+2+3+..1+2+3+.."
when n = 5 the returned string should be:
1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..
As an example, the following code fragment:
n = 5
res = addnestedloops(n)
print (res)
should produce the output:
1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..
Can't seem to find out how to return the string in which it counts upwards until the inputted number...
def themethod(n):
var toprint="";
var tmp;
if(n>0)tmp="1";
for(var i=2;i<=n;i++):
tmp+= "+".i;
for(var i=0;i<n;i++):
toprint += tmp;
print toprint;
I think what you are looking for is head-recursion in python
Here is the code which will let you achieve this
def recursive(n):
if n == 1:
return 1
else:
return str(recursive(n-1)) + "+"+str(n)
A nested loop is just a loop within a loop. If I understand you correctly, you need n strings concatenated, each containing n numbers.
I have a feeling this is a school assignment, so I wont give you the full answer, but I believe the nested loop construction you need is
for i in range(n):
for j in range(n):
# Construct the sub string here and append it to a result variable
Remember that the range function output is zero based, so range(3) produces 0, 1 and 2.
I don't however see why you need a nested loop, other than it should be a part of the assignment. You could just construct the sub string and repeat it n times with substring * n. For example 'hello' * 3 results in 'hellohellohello'.
Oh, and just to give you a bit more to think about, the one-liner solution for your problem is
('+'.join('{0:d}'.format(i+1) for i in range(n)) + '+..') * n
I am writing a small program, in python, which will find a lone missing element from an arithmetic progression (where the starting element could be both positive and negative and the series could be ascending or descending).
so for example: if the input is 1 3 5 9 11, then the function should return 7 as this is the lone missing element in the above AP series.
The input format: the input elements are separated by 1 white space and not commas as is commonly done.
Here is the code:
def find_missing_elm_ap_series(n, series):
ap = series
ap = ap.split(' ')
ap = [int(i) for i in ap]
cd = []
for i in range(n-1):
cd.append(ap[i+1]-ap[i])
common_diff = 0
if len(set(cd)) == 1:
print 'The series is complete'
return series
else:
cd = [abs(i) for i in cd]
common_diff = min(cd)
if ap[0] > ap[1]:
common_diff = (-1)*common_diff
new_ap = []
for i in range(n+1):
new_ap.append(ap[0] + i*common_diff)
missing_element = set(new_ap).difference(set(ap))
return missing_element
where n is the length of the series provided (the series with the missing element:5 in the above example).
I am sure there are other shorter and more elegant way of writing this code in python. Can anybody help ?
Thanks
BTW: i am learning python by myself and hence the question.
Based on the fact that if an element is missing it is exactly expected-sum(series) - actual-sum(series). The expected sum for a series with n elements starting at a and ending at b is (a+b)*n/2. The rest is Python:
def find_missing(series):
A = map(int, series.split(' '))
a, b, n, sumA = A[0], A[-1], len(A), sum(A)
if (a+b)*n/2 == sumA:
return None #no element missing
return (a+b)*(n+1)/2-sumA
print find_missing("1 3 5 9") #7
print find_missing("-1 1 3 5 9") #7
print find_missing("9 6 0") #3
print find_missing("1 2 3") #None
print find_missing("-3 1 3 5") #-1
Well... You can do simpler, but it would completely change your algorithm.
First, you can prove that the step for the arithmetic progression is ap[1] - ap[0], unless ap[2] - ap[1] is lower in magnitude than it, in which case the missing element is between terms 0 and 1. (This is true as there is a single missing element.)
Then you can just take ap[0] + n * step and print the first one that doesn't match.
Here is the source code (also implementing some minor shortcuts, such as grouping your first three lines into one):
def find_missing_elm_ap_series(n, series):
ap = [int(i) for i in series.split(' ')]
step = ap[1] - ap[0]
if (abs(ap[2] - ap[1]) <= abs(step)): # Check missing elt is not between 0 and 1
return ap[0] + ap[2] - ap[1]
for (i, val) in zip(range(len(ap)), ap): # And check position of missing element
if ap[0] + i * step != val:
return ap[0] + i * step
return series # missing element not found
The code appears to be working. There is perhaps a slightly easier way to get it done. This is due to the fact that you don't have to attempt to look through all of the values to get the common difference. The following code simply looks at the difference between the 1st and 2nd as well as the last and second last.
This works in the event that only a single value is missing (and the length of the list is at least 3). As the min difference between the values will provide you the common difference.
def find_missing(prog):
# First we cast them to numbers.
items = [int(x) for x in prog.split()]
#Then we compare the first and second
first_to_second = items[1] - items[0]
#then we compare the last to second last
last_to_second_last = items[-1] - items[-2]
#Now we have to care about which one is closes
# to zero
if abs(first_to_second) < abs(last_to_second_last):
change = first_to_second
else:
change = last_to_second_last
#Iterate through the list. As soon as we find a gap
#that is larger than change, we fill in and return
for i in range(1, len(items)):
comp = items[i] - items[i-1]
if comp != change:
return items[i-1] + change
#There was no gap
return None
print(find_missing("1 3 5 9")) #7
print(find_missing("-1 1 3 5 9")) #7
print(find_missing("9 6 0")) #3
print(find_missing("1 2 3")) #None
The previous code shows this example. First of all attempting to find change between each of the values of the list. Then iterating till the change is missed, and returning the value that has been expected.
Here's the way I thought about it: find the position of the maximum difference between the elements of the array; then regenerate the expected number in the sequence from the other differences (which should be all the same and the minimum number in the differences list):
def find_missing(a):
d = [a[i+1] - a[i] for i in range(len(a)-1)]
i = d.index(max(d))
x = min(d)
return a[0] + (i+1)*x
print find_missing([1,3,5,9,11])
7
print find_missing([1,5,7,9,11])
3
Here are some ideas:
Passing the length of the series seems like a bad idea. The function can more easily calculate the length
There is no reason to assign series to ap, just do a function using series and assign the result to ap
When splitting the string, don't give the sep argument. If you don't give the argument, then consecutive white space will also be removed and leading and trailing white space will also be ignored. This is more friendly on the format of the data.
I've combined a few operations. For example the split and the list comprehension converting to integer make sense to group together. There is also no need to create cd as a list and then convert that to a set. Just build it as a set to start with.
I don't like that the function returns the original series in the case of no missing element. The value None would be more in keeping with the name of the function.
Your original function returned a one item set as the result. That seems odd, so I've used pop() to extract that item and return just the missing element.
The last item was more of an experiment with combining all of the code at the bottom into a single statement. Don't know if it is better, but it's something to think about. I built a set with all the correct numbers and a set with the given numbers and then subtracted them and returned the number that was missing.
Here's the code that I came up with:
def find_missing_elm_ap_series(series):
ap = [int(i) for i in series.split()]
n = len(ap)
cd = {ap[i+1]-ap[i] for i in range(n-1)}
if len(cd) == 1:
print 'The series is complete'
return None
else:
common_diff = min([abs(i) for i in cd])
if ap[0] > ap[1]:
common_diff = (-1)*common_diff
return set(range(ap[0],ap[0]+common_diff*n,common_diff)).difference(set(ap)).pop()
Assuming the first & last items are not missing, we can also make use of range() or xrange() with the step of the common difference, getting rid of the n altogether, it can also return more than 1 missing item (although not reliably depending on number of items missing):
In [13]: def find_missing_elm(series):
ap = map(int, series.split())
cd = map(lambda x: x[1]-x[0], zip(ap[:-1], ap[1:]))
if len(set(cd)) == 1:
print 'complete series'
return ap
mcd = min(cd) if ap[0] < ap[1] else max(cd)
sap = set(ap)
return filter(lambda x: x not in sap, xrange(ap[0], ap[-1], mcd))
....:
In [14]: find_missing_elm('1 3 5 9 11 15')
Out[14]: [7, 13]
In [15]: find_missing_elm('15 11 9 5 3 1')
Out[15]: [13, 7]
I am trying to use the regex module to find non-overlapping repeats (duplicated sub-strings) within a given string (30 char), with the following requirements:
I am only interested in non-overlapping repeats that are 6-15 char long.
allow 1 mis-match
return the positions for each match
One way I thought of is that for each possible repeat length, let python loop through the 30char string input. For example,
string = "ATAGATATATGGCCCGGCCCATAGATATAT" #input
#for 6char repeats, first one in loop would be for the following event:
text = "ATAGAT"
text2 ="(" + text + ")"+ "{e<=1}" #this is to allow 1 mismatch later in regex
string2="ATATGGCCCGGCCCATAGATATAT" #string after excluding text
for x in regex.finditer(text2,string2,overlapped=True):
print x.span()
#then still for 6char repeats, I will move on to text = "TAGATA"...
#after 6char, loop again for 7char...
There should be two outputs for this particular string = "ATAGATATATGGCCCGGCCCATAGATATAT". 1. The bold two "ATAGATATAT" + 1 mismatch: "ATAGATATATG" &"CATAGATATAT" with position index returned as (0,10)&(19, 29); 2. "TGGCCC" & "GGCCCA" (need add one mismatch to be at least 6 char), with index (9,14)&(15,20). Numbers can be in a list or table.
I'm sorry that I didn't include a real loop, but I hope the idea is clear...As you can see, this is a very less efficient method, not to mention it would create redundancy --- e.g. 10char repeats will be counted more than once, because it would suit for 9,8,7 and 6 char repeats loops. Moreover, I have a lot of such 30 char strings to work with, so I would appreciate your advice on some cleaner methods.
Thank you very much:)
I'd try straightforward algorithm instead of regex (which are quite confusing in this instance);
s = "ATAGATATATGGCCCGGCCCATAGATATAT"
def fuzzy_compare(s1, s2):
# sanity check
if len(s1) != len(s2):
return False
diffs = 0
for a, b in zip(s1, s2):
if a != b:
diffs += 1
if diffs > 1:
return False
return True
slen = len(s) # 30
for l in range(6, 16):
i = 0
while (i + l * 2) <= slen:
sub1 = s[i:i+l]
for j in range(i+l, slen - l):
sub2 = s[j:j+l]
if fuzzy_compare(sub1, sub2):
# checking if this could be partial
partial = False
if i + l < j and j + l < slen:
extsub1 = s[i:i+l+1]
extsub2 = s[j:j+l+1]
# if it is partial, we'll get it later in the main loop
if fuzzy_compare(extsub1, extsub2):
partial = True
if not partial:
print (i, i+l), (j, j+l)
i += 1
It's a first draft, so feel free to experiment with it. It also seems to be clunky and not optimal, but try running it first - it may be sufficient enough.