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)
Related
def findxinkindowSize(arr, x, k, n) :
i = 0
while i < n :
j = 0
# Search x in segment
# starting from index i
while j < k :
if arr[i + j] == x :
break
j += 1
# If loop didn't break
if j == k :
return False
i += k
# If n is a multiple of k
if i == n :
return True
j = i - k
# Check in last segment if n
# is not multiple of k.
while j < n :
if arr[j] == x :
break
j += 1
if j == n :
return False
return True
# Driver Code
if __name__ == "__main__" :
arr = [ 3, 5, 2, 4, 9, 3,
1, 7, 3, 11, 12, 3 ]
x, k = 3, 3
n = len(arr)
if (findxinkindowSize(arr, x, k, n)) :
print("Yes")
else :
print("No")
Above code works good for the array of size 3, 6, 9, 12, ... i.e multiples of size of k (segment size), but for the array arr = [3, 5, 2, 4, 9, 3, 1, 7] which is of size 8 there is an error in the line if arr[i + j] == x : shows out of index.
Is there any better solution for this problem?
This is a simple approach using slicing.
Iterate through every slice of size k and check if x is present in that slice or not.
def findxinkindowSize(arr, x, k, n):
for i in range(0, n, k):
if x not in arr[i: i+k]:
return False
return True
This code doesn't give IndexError.
I have the following problem to solve:
Given a set of integers, e.g. {1,3,2}, and an array of random integers, e.g.
[1, 2, 2, -5, -4, 0, 1, 1, 2, 2, 0, 3,3]
Find the shortest continuous subarray that contains all of the values from the set. If the subarray can not be found, return an empty array.
Result: [1, 2, 2, 0, 3]
Or
[1, 2, 2, -5, -4, 3, 1, 1, 2, 0], {1,3,2}.
Result: [3, 1, 1, 2]
I have tried the following put there seems to be something wrong with my second loop. I'm not sure what I need to change:
def find_sub(l, s):
i = 0
counts = dict()
end = 0
while i < len(s):
curr = l[end]
if curr in s:
if curr in counts:
counts[curr] = counts[curr] + 1
else:
counts[curr] = 1
i += 1
end += 1
curr_len = end
start = 0
for curr in l:
if curr in counts:
if counts[curr] == 1:
if end < len(l):
next_item = l[end]
if next_item in counts:
counts[next_item] += 1
end += 1
else:
counts[curr] -= 1
start += 1
else:
start += 1
if (end - start) < curr_len:
return l[start:end]
else:
return l[:curr_len]
You are using two-pointer approach, but move both indexes only once - until the first match found. You should repeat move right - move left pattern to get the best index interval.
def find_sub(l, s):
left = 0
right = 0
ac = 0
lens = len(s)
map = dict(zip(s, [0]*lens))
minlen = 100000
while left < len(l):
while right < len(l):
curr = l[right]
right += 1
if curr in s:
c = map[curr]
map[curr] = c + 1
if c==0:
ac+=1
if ac == lens:
break
if ac < lens:
break
while left < right:
curr = l[left]
left += 1
if curr in s:
c = map[curr]
map[curr] = c - 1
if c==1:
ac-=1
break
if right - left + 1 < minlen:
minlen = right - left + 1
bestleft = left - 1
bestright = right
return l[bestleft:bestright]
print(find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 0, 3, 3], {1,3,2}))
print(find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1,3,2}))
>>[2, -5, -4, 3, 1]
>>[2, 1, 0, 3]
You can use a sliding window approach (using a generator), the idea is to generate all subsets of size n (size of the set) to size N (size of the list), and check if any of them exists, stopping when finding the first one:
from itertools import islice, chain
def window(seq, n=2):
"Returns a sliding window (of width n) over data from the iterable"
" s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ... "
it = iter(seq)
result = tuple(islice(it, n))
if len(result) == n:
yield result
for elem in it:
result = result[1:] + (elem,)
yield result
l = [1, 2, 2, -5, -4, 3, 1, 1, 2, 0]
s = {1,3,2}
def minimum_subset(l, s):
for w in chain.from_iterable(window(l, i) for i in range(len(s), len(l)+1)):
if s == set(w):
return w
return []
print(minimum_subset(l, s))
Result (3, 1, 1, 2)
Here you have the live example
This should be the most performant solution, running in O(n):
def find_sub(l, s):
if len(l) < len(s):
return None
# Keep track of how many elements are in the interval
counters = {e: 0 for e in s}
# Current and best interval
lo = hi = 0
best_lo = 0
best_hi = len(l)
# Increment hi until all elements are in the interval
missing_elements = set(s)
while hi < len(l) and missing_elements:
e = l[hi]
if e in counters:
counters[e] += 1
if e in missing_elements:
missing_elements.remove(e)
hi += 1
if missing_elements:
# Array does not contain all needed elements
return None
# Move the two pointers
missing_element = None
while hi < len(l):
if missing_element is None:
# We have all the elements
if hi - lo < best_hi - best_lo:
best_lo = lo
best_hi = hi
# Increment lo
e = l[lo]
if e in counters:
counters[e] -= 1
if counters[e] == 0:
missing_element = e
lo += 1
else:
# We need more elements, increment hi
e = l[hi]
if e in counters:
counters[e] += 1
if missing_element == e:
missing_element = None
hi += 1
return l[best_lo:best_hi]
assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 0, 3, 3], {1, 3, 2}) == [2, -5, -4, 3, 1]
assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1, 3, 2}) == [2, 1, 0, 3]
assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1, 3, 7}) is None
Joining in the fun, here's my attempt. I'm not familiar with algorithm names, but this would seem like a sliding window approach based on #Netwave's description for his answer.
I = {1, 3, 2}
A = [1, 2, 2, -5, -4, 0, 1, 1, 2, 2, 0, 3, 3]
setcount = {i: 0 for i in I}
stage = []
shortest = A
for i in range(len(A)):
# Subset
stage.append(A[i])
# Update the count
if A[i] in I:
setcount[A[i]] += 1
while 0 not in setcount.values():
# Check if new subset is shorter than existing's
if len(stage) < len(shortest):
shortest = stage.copy()
# Consume the head to get progressively shorter subsets
if stage[0] in I:
setcount[stage[0]] -= 1
stage.pop(0)
>>>print(shortest)
[1, 2, 2, 0, 3]
I am trying to create some code that returns the positions and the values of the "peaks" (or local maxima) of a numeric array.
For example, the list arr = [0, 1, 2, 5, 1, 0] has a peak at position 3 with a value of 5 (since arr[3] equals 5).
The first and last elements of the array will not be considered as peaks (in the context of a mathematical function, you don't know what is after and before and therefore, you don't know if it is a peak or not).
def pick_peaks(arr):
print(arr)
posPeaks = {
"pos": [],
"peaks": [],
}
startFound = False
n = 0
while startFound == False:
if arr[n] == arr[n+1]:
n += 1
else:
startFound = True
endFound = False
m = len(arr) - 1
while endFound == False:
if arr[m] == arr[m-1]:
m -= 1
else:
endFound = True
for i in range(n+1, m):
if arr[i] == arr[i-1]:
None
elif arr[i] >= arr[i-1] and arr[i] >= arr[i+1]:
posPeaks["pos"].append(i)
posPeaks["peaks"].append(arr[i])
return posPeaks
My issue is with plateaus. [1, 2, 2, 2, 1] has a peak while [1, 2, 2, 2, 3] does not. When a plateau is a peak, the first position of the plateau is recorded.
Any help is appreciated.
I suggest you use groupby to group contiguous equal values, then for each group store the first position, example for [1, 2, 2, 2, 1] it creates the following list following list of tuples [(1, 0), (2, 1), (1, 4)], putting all together:
from itertools import groupby
def peaks(data):
start = 0
sequence = []
for key, group in groupby(data):
sequence.append((key, start))
start += sum(1 for _ in group)
for (b, bi), (m, mi), (a, ai) in zip(sequence, sequence[1:], sequence[2:]):
if b < m and a < m:
yield m, mi
print(list(peaks([0, 1, 2, 5, 1, 0])))
print(list(peaks([1, 2, 2, 2, 1])))
print(list(peaks([1, 2, 2, 2, 3])))
Output
[(5, 3)]
[(2, 1)]
[]
I know I may be a little late for the party, but I'd like to share my solution using NumPy arrays:
def get_level_peaks(v):
peaks = []
i = 1
while i < v.size-1:
pos_left = i
pos_right = i
while v[pos_left] == v[i] and pos_left > 0:
pos_left -= 1
while v[pos_right] == v[i] and pos_right < v.size-1:
pos_right += 1
is_lower_peak = v[pos_left] > v[i] and v[i] < v[pos_right]
is_upper_peak = v[pos_left] < v[i] and v[i] > v[pos_right]
if is_upper_peak or is_lower_peak:
peaks.append(i)
i = pos_right
peaks = np.array(peaks)
"""
# uncomment this part of the code
# to include first and last positions
first_pos, last_pos = 0, v.size-1
peaks = np.append([first_pos], peaks)
peaks = np.append(peaks, [last_pos])
"""
return peaks
Example 1 (see graph):
v = np.array([7, 2, 0, 4, 4, 6, 6, 9, 5, 5])
p = get_peaks(v)
print(v) # [7 2 0 4 4 6 6 9 5 5]
print(p) # [0 2 7 9] (peak indexes)
print(v[p]) # [7 0 9 5] (peak elements)
Example 2 (see graph):
v = np.array([8, 2, 1, 0, 1, 2, 2, 5, 9, 3])
p = get_peaks(v)
print(v) # [8 2 1 0 1 2 2 5 9 3]
print(p) # [0 3 8 9] (peak indexes)
print(v[p]) # [8 0 9 3] (peak elements)
Example 3 (see graph):
v = np.array([9, 8, 8, 8, 0, 8, 9, 9, 9, 6])
p = get_peaks(v)
print(v) # [9 8 8 8 0 8 9 9 9 6]
print(p) # [0 4 6 9] (peak indexes)
print(v[p]) # [9 0 9 6] (peak elements)
In example 3, we have a flatten upper peak that goes from index 6 to index 8. In this case, the index will always indicate the leftmost position of the plateau. If you want to indicate the middle position or the rightmost position, just change this part of the code:
...
if is_upper_peak or is_lower_peak:
peaks.append(i)
...
to this:
...
# middle position
if is_upper_peak or is_lower_peak:
peaks.append((pos_left + pos_right) // 2)
...
...
# rightmost position
if is_upper_peak or is_lower_peak:
peaks.append(pos_right)
...
This code takes a window number and gives the peak within that window size
l=[1,2,3,4,5,4,3,2,1,2,3,4,3,2,4,2,1,2]
n=int(input("The size of window on either side "))
for i in range(n,len(l)-n):
if max(l[i-n:i]+l[i+1:i+n+1])<l[i]:
print(l[i],' at index = ',i)
You can use the same algorithm with the plateaus as well if you can preprocess the data to remove the repeating numbers and keep only 1 unique number. Thus, you can convert the example [1, 2, 2, 2, 1] to [1, 2, 1] and apply the same algorithm.
Edit:
The Code:
from itertools import groupby
def process_data(data):
return [list(val for num in group) for val, group in groupby(data)]
def peaks(arr):
#print(arr)
posPeaks = {
"pos": [],
"peaks": [],
}
startFound = False
n = 0
while startFound == False:
if arr[n][0] == arr[n+1][0]:
n += 1
else:
startFound = True
endFound = False
m = len(arr) - 1
while endFound == False:
if arr[m][0] == arr[m-1][0]:
m -= 1
else:
endFound = True
for i in range(n+1, m):
if arr[i][0] == arr[i-1][0]:
None
elif arr[i][0] >= arr[i-1][0] and arr[i][0] >= arr[i+1][0]:
pos = sum([len(arr[idx]) for idx in range(i)])
posPeaks["pos"].append(pos) #.append(i)
posPeaks["peaks"].append(arr[i][0])
return posPeaks
print(peaks(process_data([0, 1, 2, 5, 1, 0])))
print(peaks(process_data([1, 2, 2, 2, 1])))
print(peaks(process_data([1, 2, 2, 2, 3])))
Output:
{'pos': [3], 'peaks': [5]}
{'pos': [1], 'peaks': [2]}
{'pos': [], 'peaks': []}
Here is a fairly simple generator function. Just loop and maintain the necessary state: i (last index of of "growth"), up (true if last value change was "growth")
def peaks(ar):
i, up = 0, False
for j in range(1, len(ar)):
prev, val = ar[j-1], ar[j]
if up and val < prev:
yield prev, i
up = False
if val > prev:
i, up = j, True
>>> list(peaks([0,1,2,5,1,0]))
[(5, 3)]
>>> list(peaks([0,1,2,5,1,2,0]))
[(5, 3), (2, 5)]
>>> list(peaks([0,1,2,5,1,2,0,3]))
[(5, 3), (2, 5)]
>>> list(peaks([1,2,2,2,1]))
[(2, 1)]
>>> list(peaks([1,2,2,2,3]))
[]
A shorter script could be:
data_array = [1, 2, 5, 4, 6, 9]
# Delete the first and the last element of the data array.
reduced_array = [ data_array[i] for i in range(1, len(data_array)-1) ]
# Find the maximum value of the modified array
peak_value = max(reduced_array)
# Print out the maximum value and its index in the data array.
print 'The peak value is: ' + str(peak_value)
print 'And its position is: ' + str(data_array.index(peak_value))
Output:
The peak value is: 6
And its position is: 4
This question already has an answer here:
Dynamic programming for primitive calculator
(1 answer)
Closed 6 years ago.
This assignment aims to implement a dynamic programming approach to a primitive calculator that can only add 1, multiply by 2 and multiply by 3. So with an input of n determine the minimum number of operations to reach n. I've implemented a very naive dp or what I think is a dp approach. It is not working. I have no-one else to ask. For an input of n = 5 the output of the below is: ([0, 1, 2, 2, 3, 4], [1, 1, 2, 3, 4, 5]) whereas there are two correct outputs for the list numbers = [1, 2, 4, 5] or [1, 3, 4, 5]. Some help would be greatly appreciated.
def DPmin_operations(n):
numbers = []
minNumOperations = [0]*(n+1)
numOps = 0
numbers.append(1)
for k in range(1,n+1):
minNumOperations[k] = 10000
# for *3 operator
if k % 3 == 0:
numOps = minNumOperations[k//3] + 1
if numOps < minNumOperations[k]:
minNumOperations[k] = numOps
numbers.append(k)
# for *2 operator
elif k % 2 == 0:
numOps = minNumOperations[k//2] + 1
if numOps < minNumOperations[k]:
minNumOperations[k] = numOps
numbers.append(k)
# for + 1 operator
elif k >= 1:
numOps = minNumOperations[k - 1] + 1
if numOps < minNumOperations[k]:
minNumOperations[k] = numOps
numbers.append(k)
return (minNumOperations, numbers)
Note that the elif blocks should really be if blocks. Currently, you're using a greedy algorithm of always trying to divide by 3; if that fails, then trying to divide by 2; if that fails, then subtracting 1. It's possible that a number is divisible by 6 so that all three options are possible, and yet dividing by 2 is more optimal then dividing by 3.
As for getting your list of numbers, do that at the end. Store all possible parents, then work backwards from your goal to see how you got there.
def dp_min_ops(n):
all_parents = [None] * (n + 1)
all_min_ops = [0] + [None] * n
for k in range(1, n + 1):
curr_parent = k - 1
curr_min_ops = all_min_ops[curr_parent] + 1
if k % 3 == 0:
parent = k // 3
num_ops = all_min_ops[parent] + 1
if num_ops < curr_min_ops:
curr_parent, curr_min_ops = parent, num_ops
if k % 2 == 0:
parent = k // 2
num_ops = all_min_ops[parent] + 1
if num_ops < curr_min_ops:
curr_parent, curr_min_ops = parent, num_ops
all_parents[k], all_min_ops[k] = curr_parent, curr_min_ops
numbers = []
k = n
while k > 0:
numbers.append(k)
k = all_parents[k]
numbers.reverse()
return all_min_ops, numbers
print(dp_min_ops(5)) # ([0, 1, 2, 2, 3, 4], [1, 3, 4, 5])
print(dp_min_ops(10)) # ([0, 1, 2, 2, 3, 4, 3, 4, 4, 3, 4], [1, 3, 9, 10])
The task is to define a function with argument x, where x is a list of integers.The function should print out the median value of items in it. My function always return None, I've tried to fix it, but after many tries I am out of ideas.
Code:
def median(x):
x = sorted(x)
med_val = 0
if len(x) % 2.0 == 0:
for i in x:
if len(x[:i]) == len(x[i:]) + 1:
return x[i]
else:
for i in x:
if len(x[:i + 1]) == len(x[i: + 1]) + 1:
return (x[i] + x[i + 1]) / 2
print (median([1, 4, 2, 6, 8]))
Any ideas how to make it work?
In your method, replace the print statements by return expression. And in your function call, do:
print(median(list))
PS: It is better not to use list as a variable name in python.
Here's a slightly different approach:
def median(x):
x = sorted(x)
middle_index = float(len(x)/2.0) # this 2.0 part is very important
if middle_index % 2 == 0: #check if it's even
med_val = float((x[int(middle_index)]+x[int(middle_index-1)])/2) # take the average of the 2 middle values if so
else: med_val = x[int(middle_index)] #otherwise, select the center value
return med_val #return median
lists = [[2, 1, 4, 6], [9,1,1,9,3], [1, 4, 2, 6, 8]]
for item in lists:
print median(item)
In: [2, 1, 4, 6]
Out: 3.0
In: [9, 1, 1, 9, 3]
Out: 3
In: [1, 4, 2, 6, 8]
Out: 4