Python: display subarray divisible by k , how do I solve with hashtable? - python

I am looking for Python solution
For example, For A=[2, -3, 5, 4, 3, -1, 7]. The for k = 3 there is a subarray for example {-3, 5, 4}. For, k=5 there is subarray {-3, 5, 4, 3, -1, 7} etc.

This is the solution. You can try to figure it out yourself.
def solve(a, k):
tbl = {0 : -1}
sum = 0
n = len(a)
for i in xrange(n):
sum = (sum + a[i]) % k
if sum in tbl:
key = tbl[sum]
result = a[key+1: i+1]
return result
tbl[sum] = i
return []

Related

Can this function be optimized to run in O(n) time using Python?

Here's the scenario.
The function takes in an array of n item weights and an array of q capacities. The objective is to find the number of items that each bin can hold, depending on its capacity.
I've written the following function but the problem I'm having is that it's timing out on very large input values. Check it out below:
def noItems(weights, capacities):
number_of_items = 0
result = []
weight_sums = [sum(weights[0:w:1]) for w in range(1, len(weights) + 1)]
for i in range(0, len(capacities)):
for j in range(0, len(weight_sums)):
if weight_sums[j] <= capacities[i]:
number_of_items = number_of_items + 1
result.append(number_of_items)
number_of_items = 0
return(result)
Update: sample input and output
input weights: [2, 3, 5, 8, 1, 4, 7]
input capacities: [10, 20, 18, 1, 40, 4]
input constraints:
weights[i] > 1 and < 1000
capacities[i] > 1 and < 10^9
output: [3, 5, 4, 0, 7, 1]
How can this function be optimized to have a faster runtime, so that it doesn't time out on very large inputs?
You can solve this problem in O(nlogn) time using binary search over cumulative weight list
from bisect import bisect_right
def noItems(weights, capacities):
result = []
# or you can use itertools.accumulate():
weight_sums = [0] * (len(weights))
weight_sums[0] = weights[0]
for i in range(1, len(weights)):
weight_sums[i] = weight_sums[i-1] + weights[i]
for x in capacities:
number_of_items = bisect_right(weight_sums, x)
result.append(number_of_items)
return(result)
we = [2, 3, 5, 8, 1, 4, 7]
ca = [10, 20, 18, 1, 40, 4]
print(noItems(we, ca))
[3, 5, 4, 0, 7, 1]
O(n) is possible only for previously sorted capacities.

Multiply every third element of a list by two

Input data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Output data: [1, 2, 6, 4, 5, 12, 7, 8, 18, 10]
I have read many answers where were suggested to use slice notation with including first element. But in my case I should take each 3rd element of the list.
Is it possible to improve my realization?
for index in range(len(data)):
if (index + 1) % 3 == 0:
data[index] = data[index] * 2
Yes, you can do it with slice notation:
data[2::3] = [x*2 for x in data[2::3]]
The data[2::3] means every 3rd element starting at element index 2 (i.e. the third element). You can reassign back to a slice as well, allowing for this very succinct syntax.
There is a "step" parameter on the range iterator:
for index in range(2, len(data), 3):
data[index] *= 2
Would that do?
Your solution isn't too bad. It can be improved by simply iterating over the desired indices directly, rather than iterating over all indices and skipping the ones you don't want:
for index in range(2, len(data), 3):
data[index] *= 2
This produces the desired result:
[1, 2, 6, 4, 5, 12, 7, 8, 18, 10]
You could use cycle from itertools and zip to pair items with their multipliers:
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
from itertools import cycle
result = [n*m for n,m in zip(data,cycle([1,1,2]))]
# [1, 2, 6, 4, 5, 12, 7, 8, 18, 10]
OR, you can use enumerate()
result = [ n*max(1,i%3) for i,n in enumerate(data) ]
You could organize it a little bit by passing a third argument to the range() function, like this:
for index in range(2, len(data), 3):
data[index] = data[index]*2
... and the winner is:
Calculation time in seconds and results validation test.
1.150 question_by_akrapovich
0.331 answer_by_Tom_Karzes_and_Prune
0.333 answer_2_by_Manuel_Montoya
0.373 answer_by_Blorgbeard
0.816 answer_1_by_Alain_T
2.850 answer_2_by_Alain_T
Combined code for time testing and results validation:
import time
def question_by_akrapovich(data):
for index in range(len(data)):
if (index + 1) % 3 == 0:
data[index] = data[index] * 2
return data
def answer_by_Tom_Karzes_and_Prune(data):
for index in range(2, len(data), 3):
data[index] *= 2
return data
def answer_by_Blorgbeard(data):
data[2::3] = [x*2 for x in data[2::3]]
return data
def answer_1_by_Alain_T(data):
from itertools import cycle
return [n * m for n, m in zip(data, cycle([1, 1, 2]))]
def answer_2_by_Alain_T(data):
return [ n*max(1,i%3) for i,n in enumerate(data) ]
def answer_2_by_Manuel_Montoya(data):
for index in range(2, len(data), 3):
data[index] = data[index]*2
return data
def test(f):
n = 10_000_000
data = [i + 1 for i in range(n)]
start_time = time.perf_counter()
data = f(data)
run_time = time.perf_counter() - start_time
if n != len(data):
print('error in list length', n, len(data))
exit(1)
for i in range(n):
j = i + 1
m = j * 2 if j % 3 == 0 else j
if data[i] != m:
print('error in data', i, m, data[i])
exit(1)
print('%.3f %s' % (run_time, f.__name__))
print('Calculation time in seconds and results validation test.')
for f in [question_by_akrapovich, answer_by_Tom_Karzes_and_Prune,
answer_2_by_Manuel_Montoya, answer_by_Blorgbeard,
answer_1_by_Alain_T, answer_2_by_Alain_T]:
test(f)

Python - Finds the index of the smallest element in the list A from index k onwards

I am stuck in finding how I can take the "k" in consideration to solve the following problem. Basically, it should start at index k and look for the lowest value in the range from k until the end of the list.
def find_min_index(A, k):
"""
Finds the index of the smallest element in the list A from index k onwards
Parameters:
A (list)
k: index from which start search
Example use:
>>> find_min_index([1, 2, 5, -1], 0)
3
>>> find_min_index([1, 1, 1, 5, 9], 2)
2
"""
minpos = A.index(min(A))
return minpos
One-liner solution is this:
return A[k:].index(min(A[k:]) + k
You select the minimal element from A[k:], find its index in A[k:] and add k to it to compensate the search area.
A slightly neater solution is this:
slice = A[k:]
return slice.index(min(slice)) + k
You can use enumerate to keep track of the original index before you slice the list with k as the starting index:
from operator import itemgetter
def find_min_index(A, k):
return min(list(enumerate(A))[k:], key=itemgetter(1))[0]
so that:
print(find_min_index([1, 2, 5, -1], 0))
print(find_min_index([1, 1, 1, 5, 9], 2))
would output:
3
2
You could use enumerate to find the index of min:
def find_min_index(A, k):
"""
Finds the index of the smallest element in the list A from index k onwards
Parameters:
A (list)
k: index from which start search
Example use:
>>> find_min_index([1, 2, 5, -1], 0)
3
>>> find_min_index([1, 1, 1, 5, 9], 2)
2
"""
o, _ = min(enumerate(A[k:]), key=lambda i: i[1])
minpos = k + o
return minpos
print(find_min_index([1, 2, 3, 4], 1))
print(find_min_index([4, 3, 2, 1], 1))
Output
1
3
You can add k to the index calculated from a sliced input list:
def find_min_index(A, k):
sliced = A[k:]
return k + sliced.index(min(sliced))
find_min_index([1, 2, 5, -1], 2) # 3
find_min_index([1, 1, 1, 5, 9], 2) # 2

Find LowCost path and print

I am trying to print the path for the LowCost script I found here the code
Find LowCost I change some small stuff only.
The script works but it gives me only the final cost; I want it also to give me the path I have taken.
Here is an example:
[ [1, 2, 3],
[4, 8, 2],
[1, 5, 3] ]
so here how look like the path its get the 1,2,2,3:
1-2 3
.....\
4 8 2
......|
1 5 3
i want to print correc the path like Correct
path : [1,2,2,3]
low cost : 8
Now I get a very big path result and it's no correct Wrong !
path : [1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 5, 5, 5]
low cost : 8
Here is the code:
import sys
def mymin(a,b,c):
return min(min(a,b),c)
def minCostMain(cost, m, n):
result = []
def minCost(cost, m, n):
if (n < 0 or m < 0):
return sys.maxsize
elif (m == 0 and n == 0):
return cost[m][n]
else:
t1= minCost(cost, m-1, n-1)
t2= minCost(cost, m-1, n)
t3= minCost(cost, m, n-1)
v=mymin(t1,t2,t3)
#this dosen't work get more items
result.append(v)
return cost[m][n] + v
return minCost(cost, m, n),result
cost= [ [1, 2, 3],
[4, 8, 2],
[1, 5, 3] ]
lowcost,path= minCostMain(cost, 2, 2)
print "path : " + str(path)
print "low cost : " + str(lowcost)
ok now understand how its working i need to keep list in function and the self function return list no value and after i add the new item :) like this now i can get the path and the map where it's in list the number 1,2,2,3
import sys
def MyPrint(mlist):
mlist[0]=str(mlist[0]) + " = (0,0)"
sum=0
for item in mlist:sum+=int(item.split(" = (")[0])
print "*"*20
print "Sum = "+str(sum)
print "*"*20
print "map"
print "*"*20
for item in mlist:print item
def Min(x,y, z):
if (x[-1] < y[-1]):
return x if (x[-1] < z[-1]) else z
else:
return y if (y[-1] < z[-1]) else z
def minCost(cost, m, n):
if (n < 0 or m < 0):
return [sys.maxsize]
elif (m == 0 and n == 0):
return [cost[m][n]]
else:
arr=Min(minCost(cost, m-1, n-1),
minCost(cost, m-1, n),
minCost(cost, m, n-1))
arr.append(str(cost[m][n])+" = ("+str(m)+","+str(n)+")")
return arr
cost= [ [1, 2, 3],
[4, 8, 2],
[1, 5, 3] ]
x=minCost(cost, 2, 2)
MyPrint(x)
the result it's
********************
Sum = 8
********************
map
********************
1 = (0,0)
2 = (0,1)
2 = (1,2)
3 = (2,2)

How do you calculate the greatest number of repetitions in a list?

If I have a list in Python like
[1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]
How do I calculate the greatest number of repeats for any element? In this case 2 is repeated a maximum of 4 times and 1 is repeated a maximum of 3 times.
Is there a way to do this but also record the index at which the longest run began?
Use groupby, it group elements by value:
from itertools import groupby
group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1])
print max(group, key=lambda k: len(list(k[1])))
And here is the code in action:
>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1])
>>> print max(group, key=lambda k: len(list(k[1])))
(2, <itertools._grouper object at 0xb779f1cc>)
>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3])
>>> print max(group, key=lambda k: len(list(k[1])))
(3, <itertools._grouper object at 0xb7df95ec>)
From python documentation:
The operation of groupby() is similar
to the uniq filter in Unix. It
generates a break or new group every
time the value of the key function
changes
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
If you also want the index of the longest run you can do the following:
group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3])
result = []
index = 0
for k, g in group:
length = len(list(g))
result.append((k, length, index))
index += length
print max(result, key=lambda a:a[1])
Loop through the list, keep track of the current number, how many times it has been repeated, and compare that to the most times youve seen that number repeated.
Counts={}
Current=0
Current_Count=0
LIST = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]
for i in LIST:
if Current == i:
Current_Count++
else:
Current_Count=1
Current=i
if Current_Count>Counts[i]:
Counts[i]=Current_Count
print Counts
If you want it for just any element (i.e. the element with the most repetitions), you could use:
def f((v, l, m), x):
nl = l+1 if x==v else 1
return (x, nl, max(m,nl))
maxrep = reduce(f, l, (0,0,0))[2];
This only counts continuous repetitions (Result for [1,2,2,2,1,2] would be 3) and only records the element with the the maximum number.
Edit: Made definition of f a bit shorter ...
This is my solution:
def longest_repetition(l):
if l == []:
return None
element = l[0]
new = []
lar = []
for e in l:
if e == element:
new.append(e)
else:
if len(new) > len(lar):
lar = new
new = []
new.append(e)
element = e
if len(new) > len(lar):
lar = new
return lar[0]
-You can make new copy of the list but with unique values and a corresponding hits list.
-Then get the Max of hits list and get from it's index your most repeated item.
oldlist = ["A", "B", "E", "C","A", "C","D","A", "E"]
newlist=[]
hits=[]
for i in range(len(oldlist)):
if oldlist[i] in newlist:
hits[newlist.index(oldlist[i])]+= 1
else:
newlist.append(oldlist[i])
hits.append(1);
#find the most repeated item
temp_max_hits=max(hits)
temp_max_hits_index=hits.index(temp_max_hits)
print(newlist[temp_max_hits_index])
print(temp_max_hits)
But I don't know is this the fastest way to do that or there are faster solution.
If you think there are faster or more efficient solution, kindly inform us.
I'd use a hashmap of item to counter.
Every time you see a 'key' succession, increment its counter value. If you hit a new element, set the counter to 1 and keep going. At the end of this linear search, you should have the maximum succession count for each number.
This code seems to work:
l = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]
previous = None
# value/repetition pair
greatest = (-1, -1)
reps = 1
for e in l:
if e == previous:
reps += 1
else:
if reps > greatest[1]:
greatest = (previous, reps)
previous = e
reps = 1
if reps > greatest[1]:
greatest = (previous, reps)
print greatest
i write this code and working easly:
lst = [4,7,2,7,7,7,3,12,57]
maximum=0
for i in lst:
count = lst.count(i)
if count>maximum:
maximum=count
indexx = lst.index(i)
print(lst[indexx])

Categories