the results of these two print are absolutely different - python

n = 10
s = [True] * (n)
a = []
def dfs(m):
if m == 0:
print(s) #(1)
if s not in a:
print(s) #(2)
a.append(s)
return
for x in range(0, n, 2):
s[x] = not s[x]
dfs(m - 1)
for x in range(0, n, 2):
s[x] = not s[x]
for x in range(1, n, 2):
s[x] = not s[x]
dfs(m - 1)
for x in range(1, n, 2):
s[x] = not s[x]
for x in range(0, n, 3):
s[x] = not s[x]
dfs(m - 1)
for x in range(0, n, 3):
s[x] = not s[x]
dfs(10)
why the first print(s) has many kinds of different s, but the second print(s) only have the initial s. I can't understand.How can I avoid this
problem when I use recursion when I use python

When s gets appended to a the first time m is equal to zero, it is NOT appending a copy of the list s to a. It is appending a reference to s, so each time s changes, the contents of a change along with it. Your print #2 is only ever done once and if not s in a is only True the very first time.
Try this in a Python console to see a simpler example of this:
>>> a = [1,2,3,4]
>>> b = []
>>> b.append(a)
>>> a[2] = 7
>>> b
[[1, 2, 7, 4]]

Related

What is the most efficient way to find and replace continuing duplicates in the string?

What is the most efficient way to find and replace continuing duplicates in the string? I'm trying to make a script that finds continuing duplicates in the string and replaces them.
For example, after removing repeated substring of length 1: “abcababceccced” --> “abcababceced” (2 'c' are removed)
After removing repeated substring of length 2: “abcababceced” --> “abcabceced” (substring “ab” is removed)
and so on...
This is how I tried so far, but it seems not working properly as I wanted...
def f(a, b):
l = a
for j in range(len(a)):
try:
if l[j:j+b] == l[j+b:j+2*b]:
l = l[:j+b] + l[j+2*b:]
else: continue
except:
break
return l, b+1
x = "string"
b = 1
while True:
if b <= int(len(x)/2):
x, b = f(x,b)
else: break
print(x)
Here is a solution to the question. It tries to minimize string slicing (which can be inefficient since it copies the sliced substring) in the search for duplicates by using the find() method of the built-in str data type.
x = "abcababceccced"
print(x)
patLen = 1
while patLen * 2 < len(x):
i = 0
while i + patLen * 2 < len(x):
jPrev, j, pat = i, i + patLen, x[i:i + patLen]
while j + patLen <= len(x) and x.find(pat, j) == j:
jPrev, j = j, j + patLen
if j > i + patLen:
print(f"{' '*i + x[i:j - patLen]} removed")
x = x[:i] + x[j - patLen:]
print(x)
i += 1
patLen += 1
Output:
abcababceccced
cc removed
abcababceced
ab removed
abcabceced
ce removed
abcabced
abc removed
abced
Note that your original code can also be made to work with the following modifications (I added a couple of print statements too, to show what it's doing):
def f(a, b):
l = a
for j in range(len(a) - 2 * b):
try:
while l[j:j+b] == l[j+b:j+2*b]:
print(f"{' '*(j+b) + l[j+b:j+2*b]} removed")
l = l[:j+b] + l[j+2*b:]
else: continue
except:
break
return l, b+1
x = "abcababceccced"
b = 1
while b <= int(len(x) // 2):
print(x)
x, b = f(x,b)
print(x)
Output:
abcababceccced
c removed
c removed
abcababceced
ab removed
ce removed
abcabced
abc removed
abced

How do I find the index of variable b from list a?

How do I find the index of variable b from list a?
I suspect that the problem is in the data types.
a=[-202516736, '-202516736', '13886', '678280946', '14514', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946']
a_INT = [int(item) for item in a]
b_INT = [int(item) for item in b]
j = 0
while True:
try:
i = a_INT.index(b_INT, j)
print(i)
j = i + 1
except:
break
Let's take this a step further and add another value to the b list and also add a duplicate in the a list. Then:
a=[-202516736, '-202516736', '13886', '678280946', '14514', '678280946', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946', 13886]
ai = list(map(int, a))
for n in map(int, b):
offset = 0
r = []
while True:
try:
i = ai[offset:].index(n)
r.append(offset+i)
offset += i + 1
except ValueError:
break
print(f'{n} occurs at {r}')
Output:
678280946 occurs at [3, 5]
13886 occurs at [2]
Version 2:
The first piece of code is functionally correct. However, it could be very inefficient if the list being searched is very large.
Python's built-in sort function is very fast. So, let's build a list of 2-tuples each made up of a value from the list and its original index. Then sort the new list. Now that it's sorted we can perform a binary search and move on from there.
Added some more values to the OP's original list for demonstration purposes:
a = [-202516736, '-202516736', '13886', '678280946', '14514', '678280946',
'330251838', '14511', '639566631', '14510', '542472303', '14506', '678280946']
b = ['678280946', 13886, 14514, '-202516736', 99]
def bsearch(lst, x):
L = 0
R = len(lst) - 1
while L <= R:
m = (L + R) // 2
if (v := lst[m][0]) == x:
return m
if v < x:
L = m + 1
else:
R = m - 1
return -1
def findall(list_, n):
templist = sorted((v, i) for i, v in enumerate(list_))
result = None
if (i := bsearch(templist, n)) >= 0:
result = [templist[i][1]]
for j in range(i-1, -1, -1):
if templist[j][0] != n:
break
result.append(templist[j][1])
for j in range(i+1, len(templist)):
if templist[j][0] != n:
break
result.append(templist[j][1])
return result
ai = list(map(int, a))
for n in map(int, b):
print(f'{n} -> {findall(ai, n)}')
Output:
678280946 -> [5, 3, 12]
13886 -> [2]
14514 -> [4]
-202516736 -> [0, 1]
99 -> None
a=[-202516736, '-202516736', '13886', '678280946', '14514', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946']
for item in b:
print(a.index(item))
Since b has only one element the output is 3.

python put into list

def problem(n):
myList = []
for i in range(2, n):
if n % i == 0:
myList.append(i)
return myList
with this code I was wondering how you would get the factors for example 12 to print out as[[6,2],[3,4]] something like this dosnt have to be in same order thanks.
This should work for you:
import math
def problem(n):
myList = []
for i in range(2, int(math.sqrt(n) + 1)):
if n % i == 0:
myList.append([i, int(n/i)])
return myList
To get the factor pair, this divides n by i, if i is a factor, which will by i's pair.
example:
print(problem(12)) #output: [[2, 6], [3, 4]]
Another way. Loop using range and check if is_integer
num = 12
set([tuple(sorted(j)) for j in [[i, int(num/i)] for i in range(2,num) if (num/i).is_integer()]]
)
#Output:
#{(2, 6), (3, 4)}
You are almost correct . Using range you are not taking the number. Just add n+1 instead of n. That should work. Also you are not stroing the divident in the list. I added that too.
def problem(n):
myList = []
for i in range(2, n+1):
if n % i == 0 and [int(n/i),i] not in myList:
myList.append([i,int(n/i)])
return myList
In order to do the division only once:
for i in range(2, int(math.sqrt(n) + 1)):
d, m = divmod(n, i)
if m == 0:
myList.append([i, d])
You will not get duplicates with upper limit sqrt(n)

Given a string which consists of only 0, 1 or 2s, count the number of substring which have equal number of 0s, 1s and 2s

I am trying to learn algorithm/data structure. To improve my knowledge, I am trying to solve some of the online problems.
One of the problem I am trying to solve is given at practiceque
I have tried below method:
def count_zero_one_two():
s = '102100211'
s_len = len(s)
count = 0
for i in range (s_len-1):
j = i+1
k = j+1
#print i, j, k, count
#print s[i], s[j], s[k]
if k > (s_len-1):
print "end"
break
elif (s[i] != s[j]) and (s[i] !=s[k]) and (s[j] != s[k]):
print s[i], s[j], s[k]
print "not equal"
count = count+1
#print count
else:
print s[i], s[j], s[k]
print "equal"
k = j +i
print count
count_zero_one_two()
Question: if my input string is "102100211" then count should be 5 but I am getting 4. Any idea?
I would solve it like this:
def count_zero_one_two(s):
num = 0
for i in range(len(s)):
for j in range(1, len(s)/3 + 1):
if all(s[i:i+3*j].count(n) == j for n in '012'):
num += 1
return num
all() is used to check that all the 3 characters (for each iteration) are in '012'.
The inner for loop is used to count the number of 0, 1 and 2 in sequences of length 3, 6, 9, etc.
Output:
>>> s = '0102010'
>>> count_zero_one_two(s)
2
>>>
>>> s = '102100211'
>>> count_zero_one_two(s)
5
from collections import Counter
def countSub(s):
result = []
for i in range(3, len(s), 3):
t = s[:i]
c = list(Counter(t).values())
if (c[0]==c[1]==c[2]):
result.append((t, c[0]))
return result
def count(s):
result = []
for i in range(len(s)-2):
result.extend(countSub(s[i:]))
return set(result)
ss = count("102100211")
print("%s substrings found: " % len(ss), ss)
output:
4 substrings found (not counting duplicates and empty strings):
{('021', 1), ('210021', 2), ('210', 1), ('102', 1)}

Swapping list with index

Just want to ask how do i swap the list at the index with the list that follows it and if the list at the index is on the bottom, swap that with the top.
So that the index would swap places with the position the list is with the next number For example Normal = [1,2,3,4] and index of 1 would turn to = [1, 3, 2, 4]. making the 2 and 3 swap places and index of 3 would make [4, 2, 3, 1]
def swap(lst, swap_index):
try:
next_index = (swap_index + 1) % len(lst)
lst[swap_index], lst[next_index] = lst[next_index], lst[swap_index]
except IndexError:
print "index out of range"
lst = [1,2,3,4]
swap_index = 4
swap(lst,swap_index)
print lst
pay attention that everything in Python is reference, that is to say, the swap function swap elements in place
I threw together a quick function which should work with any values, though Hootings way may be better.
def itatchi_swap(x, n):
x_len = len(x)
if not 0 <= n < x_len:
return x
elif n == x_len - 1:
return [x[-1]] + x[1:-1] + [x[0]]
else:
return x[:n] + [x[n+1]] + [x[n]] + x[n+2:]
And slightly modified to mutate the list:
def itatchi_swap(x, n):
x_len = len(x)
if 0 <= n < x_len:
if n == x_len - 1:
v = x[0]
x[0] = x[-1]
x[-1] = v
else:
v = x[n]
x[n] = x[n+1]
x[n+1] = v

Categories