Mark Element in List - python-3.x

I have an excercise about prime numbers that requires me to write a function which takes a list of elements and a number p and marks elements False which are in the range 2p, 3p...N
First I create a list of True and False:
true_value = [False, False] + [True for x in range(n-1)] #Let assumme that n=16
And then I write the function that find the even number in this list (with p = 2)
def mark_false(bool_list, p):
range_new = [x for x in range(len(bool_list))]
for i in range(2, len(range_new)):
for j in range(p, len(range_new), p):
if (i*p == range_new[j]) & (i*p <= len(range_new)):
bool_list[j] = False
return bool_list
This function help me to find the location of the even number (>2) and return to False
Example: a = list_true(16)
a = [False,False,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
b = mark_false(a, 2)
b = [False,False,True,True,False,True,False,True,False,True,False,True,False,True,False,True]
This function mark_false does work but the problem is everytime I run it I have to create a list range_new which takes a lot of time to calculate. So how do I rewrite this function so it can run faster without creating new lists?

You seem to be doing things the long way around, searching for the j value that matches the multiple of p you want to set to False. But since you already know that value already, there's no need to search for it, just set it directly.
I'd do:
def mark_false(bool_list, p):
for i in range(p, len(bool_list), p): # p, 2*p, 3*p, ...
bool_list[i] = False # do the assignment unconditionally
You probably shouldn't need a return statement, since you're modifying the list you are passed in-place. Returning the list could make the API misleading, as it might suggest that the returned list is a new one (e.g. a modified copy).
If you did want to return a new list, you could create one with a list comprehension, rather than modifying the existing list:
def mark_false_copy(bool_list, p):
return [x if i % p else False for i, x in enumerate(bool_list)]

Related

Finding a substring in a jumbled string

I am writing a script - includes(word1, word2) - that takes two strings as arguments, and finds if word1 is included in word2. Word2 is a letter jumble. It should return Boolean. Also repetition of letters are allowed, I am only checking if the letters are included in the both words in the same order.
>>>includes('queen', 'qwertyuytresdftyuiokn')
True
'queen', 'QwertyUytrEsdftyuiokN'
I tried turning each word into lists so that it is easier to work with each element. My code is this:
def includes(w1, w2):
w1 = list(w1)
w2 = list(w2)
result = False
for i in w1:
if i in w2:
result = True
else:
result = False
return result
But the problem is that I need to also check if the letters of word1 comes in the same order in word2, and my code doesn't controls that. I couldn't find a way to implement that with list. Just like I couldn't do this much with strings, so I think I need to use another data structure like dictionary but I don't know much about them.
I hope I understood what is your goal.
Python is not my thing, but I think I made it pythonic:
def is_subsequence(pattern, items_to_use):
items_to_use = (x for x in items_to_use)
return all(any(x == y for y in items_to_use) for x, _ in itertools.groupby(pattern))
https://ideone.com/Saz984
Explanation:
itertools.groupby transfers pattern in such way that constitutive duplicates are discarded
all items form form grouped pattern must fulfill conditions
any uses generator items_to_use as long as it doesn't matches current item. Note that items_to_use mus be defined outside of final expression so progress on it is kept every time next item from pattern is verified.
If you are not just checking substrings:
def include(a, b):
a = "".join(set(a)) # removes duplicates
if len(a) == 1:
if a in b:
return True
else:
return False
else:
try:
pos = b.index(a[0])
return include(a[1:], b[pos:])
except:
return False
print(include('queen', 'qwertyuytresdftyuiokn'))
#True

I want to know how can is shorten this code and make it look more proper

I want to know if the code I wrote can be shortened further, I was practicing and I came up to a task which asks you to return a boolean value, this is what the question says:
Given two strings, return True if either of the strings appears at the
very end of the other string, ignoring upper/lower case differences
(in other words, the computation should not be "case sensitive").
Note: s.lower() returns the lowercase version of a string.
def end_other(a, b):
x = len(b)
n = a[-x:]
y = len(a)
m = b[-y:]
if b.lower() == n.lower() or a.lower() == m.lower() :
return True
else:
return False
The Code is working properly but I wondered if it can be shortened more so it looks good.
You can write it like this:
def end_other(a, b):
n = a[-len(b):]
m = b[-len(a):]
return b.lower() == n.lower() or a.lower == m.lower()
I removed variables x and y because they are used just one time and then I also remove the if-else statement because it's unnecessary, in fact you can just return the result of the comparison instead of checking it's result and returning it a second time.

How to apply multiprocessing in python3.x for the following nested loop

for i in range(1,row):
for j in range(1,col):
if i > j and i != j:
x = Aglo[0][i][0]
y = Aglo[j][0][0]
Aglo[j][i] = offset.myfun(x,y)
Aglo[i][j] = Aglo[j][i]
Aglo[][] is a 2D array, which consists of lists in the first row
offset.myfun() is a function defined elsewhere
This might be a trivial question but i couldn't understand how to use multiprocessing for these nested loops as x,y (used in myfun()) is different for each process(if multiprocessing is used)
Thank you
If I'm reading your code right, you are not overwriting any previously calculated values. If that's true, then you can use multiprocessing. If not, then you can't guarantee that the results from multiprocessing will be in the correct order.
To use something like multiprocessing.Pool, you would need to gather all valid (x, y) pairs to pass to offset.myfun(). Something like this might work (untested):
pairs = [(i, j, Aglo[0][i][0], Aglo[j][0][0]) for i in range(1, row) for j in range(1, col) if i > j and i != j]
# offset.myfun now needs to take a tuple instead of x, y
# it additionally needs to emit i and j in addition to the return value
# e.g. (i, j, result)
p = Pool(4)
results = p.map(offset.myfun, pairs)
# fill in Aglo with the results
for pair in pairs:
i, j, value = pair
Aglo[i][j] = value
Aglo[j][i] = value
You will need to pass in i and j to offset.myfun because otherwise there is no way to know which result goes where. offset.myfun should then return i and j along with the result so you can fill in Aglo appropriately. Hope this helps.

k way merge sort divide and conquer

from math import ceil
def merge(all_lst):
sorted_lst = []
while all_lst:
min_value,index = all_lst[0][0],0
for lst in all_lst:
if lst[0]<min_value:
min_value = lst[0]
index = all_lst.index(lst)
sorted_lst.append(min_value)
all_lst[index].pop(0)
if not all_lst[index]:
all_lst.remove(all_lst[index])
return sorted_lst
def merge_sort(lst, k):
def split(lst):
split_lst = []
j = ceil(len(lst)/k) if len(lst)>=k else 1
for i in range(0,len(lst),j):
split_lst.append(lst[i:i+j])
return split_lst
lst=split(lst)
if len(lst[0])==1:
return lst
else:
for i in range(len(lst)):
lst[i]=merge(merge_sort(lst[i],k))
return merge(lst)
Above is my code for k-way merge sort. Basically what it does is split the list into k smaller list by calling the split function until each sublist in the list is a single element. Then the list containing sublists will be merged into one single list.
My code works fine when splitting is done twice. (eg.[3,6,8,5,2,1,4,7] -> [3,6,8],[5,2,1],[4,7] -> [3],[6],[8],[5],[2],[1],[4],[7]). But when the splitting is done more than twice, (eg,[3,6,8,5,2,1,4,7] -> [3,6,8,5],[2,1,4,7] -> [3,6],[8,5],[2,1],[4,7] -> [3],[6],[8],[5],[2],[1],[4],[7]), the code will fail. Can anyone help find me find out what goes wrong in my code? Thanks in advance.
I believe the problem you're having is that merge_sort sometimes returns a flattened list and other times returns a list of lists. You should probably return a flat list in all cases. There's some other cruft: You don't need split to be its own function, since you only call it the one time.
Here's a greatly simplified version of your code:
def merge_sort(lst, k):
if len(lst) == 1: # simpler base case
return lst
j = ceil(len(lst)/k) # no need to check for k < len(lst) (ceil handles it)
#split and recursively sort in one step
lst = [merge_sort(lst[i:i+j], k) for i in range(0, len(lst), j)]
return merge(lst) # always return a merged list (never a list of lists)

set from the union of elements contained in two lists

this is for a pre-interview questioner. i believe i have the answer just wanted to get confirmation that im right.
Part 1 - Tell me what this code does, and its big-O performance
Part 2 - Re-write it yourself and tell me the big-O performance of your solution
def foo(a, b):
""" a and b are both lists """
c = []
for i in a:
if is_bar(b, i):
c.append(i)
return unique(c)
def is_bar(a, b):
for i in a:
if i == b:
return True
return False
def unique(arr):
b = {}
for i in arr:
b[i] = 1
return b.keys()
ANSWERS:
It creates a set from the union of elements contained in two lists. It big O performance is O(n2)
my solution which i believe achieves O(n)
Set A = getSetA();
Set B = getSetB();
Set UnionAB = new Set(A);
UnionAB.addAll(B);
for (Object inA : a)
if(B.contains(inA))
UnionAB.remove(inA);
It seems like the original code is doing an intersection not a union. It's traversing all the elements in the first list (a) and checking if it exists in the second list (b), in which case it is adding it to list c. Then it is returning the unique elements from c. Performance of O(n^2) seems right.

Resources