I'm trying some python and I got this:
I have a string S='3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2' and m=9.
I want to know how many substrings with with sum equals m there are.
So with S and m above i whould get 7 as a result as:
'3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
_'0,4,0,3,1,0,1,0'_____________
_'0,4,0,3,1,0,1'_______________
___'4,0,3,1,0,1,0'_____________
____'4,0,3,1,0,1'_______________
____________________'0,0,5,0,4'_
______________________'0,5,0,4'_
_______________________'5,0,4'_
Now, the code i came up with does something like that
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for x in ls:
i= ls.index(x)
for y in ls[i+1:]:
M = x + y
if M == m:
c += 1
M = 0
break
if M > m:
M = 0
break
else:
continue
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
Where StringToInt obv gives me a list of int to work with.
The thing I don't get is where my concept is wrong since es1 returns 3
You could use zip to progressively add numbers to a list of sums and count how many 9s you have at each pass:
S = '3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
m = 9
numbers = list(map(int,S.split(",")))
result = 0
sums = numbers
for i in range(len(numbers)):
result += sums.count(m)
sums = [a+b for a,b in zip(sums,numbers[i+1:]) ]
print(result)
For a more "functional programming" approach, you can use accumulate from itertools:
from itertools import accumulate
numbers = list(map(int,S.split(",")))
ranges = (numbers[i:] for i in range(len(numbers)))
sums = (accumulate(r) for r in ranges)
result = sum( list(s).count(m) for s in sums )
print(result)
To explain how this works, let's first look at the content of ranges, which are substrings from each position up to the end of the list:
[3, 0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 0, 5, 0, 4, 2]
[0, 0, 5, 0, 4, 2]
[0, 5, 0, 4, 2]
[5, 0, 4, 2]
[0, 4, 2]
[4, 2]
[2]
When we make a cumulative sum of the rows (sums), we obtain the total of values starting at the position defined by the row number and for a length defined by the column number. e.g. line 5, column 3 represents the sum of 3 values starting at the fifth position:
[3, 3, 7, 7, 10, 11, 11, 12, 12, 13, 13, 13, 18, 18, 22, 24]
[0, 4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[0, 3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[1, 1, 2, 2, 3, 3, 3, 8, 8, 12, 14]
[0, 1, 1, 2, 2, 2, 7, 7, 11, 13]
[1, 1, 2, 2, 2, 7, 7, 11, 13]
[0, 1, 1, 1, 6, 6, 10, 12]
[1, 1, 1, 6, 6, 10, 12]
[0, 0, 5, 5, 9, 11]
[0, 5, 5, 9, 11]
[5, 5, 9, 11]
[0, 4, 6]
[4, 6]
[2]
In this triangular matrix each position corresponds to the sum of one of the possible substrings. We simply need to count the number of 9s in there to get the result.
The above solutions will perform in O(N^2) time but, if you are concerned with performance, there is a way to obtain the result in O(N) time using a dictionary. Rather than build the whole sub arrays in the above logic, you could simply count the number of positions that add up to each sum. Then, for the sum at each position, go directly to a previous sum total that is exactly m less to get the number of substrings for that position.
from itertools import accumulate
from collections import Counter
numbers = map(int,S.split(","))
result = 0
sums = Counter([0])
for s in accumulate(numbers):
result += sums[s-m]
sums[s] += 1
print(result)
Note that all these solutions support negative numbers in the list as well as a negative or zero target.
As mentioned by others, your code only looks at sums of pairs of elements from the list. You need to look at sublists.
Here is a O(n) complexity solution (i.e. it's efficient since it only scans though the list once):
def es2(s, m):
s = string_to_int(s)
c = 0
# index of left of sub-list
left = 0
# index of right of sub-list
right = 0
# running total of sublist sum
current_sum = 0
while True:
# if the sub-list has the correct sum
if current_sum == m:
# add as many zeros on the end as works
temp_current_sum = current_sum
for temp_right in range(right, len(s) + 1):
if temp_current_sum == m:
c += 1
if temp_right<len(s):
temp_current_sum += s[temp_right]
else:
break
if current_sum >= m:
# move the left end along and update running total
current_sum -= s[left]
left += 1
else:
# move the right end along and update running total
if right == len(s):
# if the end of the list is reached, exit
return c
current_sum += s[right]
right += 1
def string_to_int(ls):
s = [int(x) for x in ls.split(',')]
return s
if __name__ == '__main__':
print(es2('3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2', 9))
This is the code you are looking for man. i felt looking by position was better for this problem so I did it and it worked.
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for i in range(0, len(ls)):
M = 0
for x in range(i, len(ls)):
M += ls[x]
if M == m:
c += 1
elif M >= m:
break
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
OUTPUT:
7
Your code counts how many pairs of numbers there are in the String S which together give m while you actually want to test all possible substrings.
You could do something like:
numbers = [3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2]
m = 9
c = 0
for i in range(len(numbers)):
for j in range(len(numbers)-i):
sum = 0
for k in numbers[i:i+j]:
sum += k
if sum == m:
c += 1
print(c)
Output:
7
EDIT! ->This Code is actually all possible subsets, not sublists. I am going to leave this here though in case this solution is helpful to anyone who visits this question.
This code gets every solution. If you take a look in the function es1() the result variable is huge list of arrays with all the possible solutions.
import itertools
def es1(S,m):
result = [seq for i in range(len(StringToInt(S)), 0, -1) for seq in itertools.combinations(StringToInt(S), i) if sum(seq) == m]
return len(result)
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
OUTPUT:
4608
There are 4608 possible sets that add to the value 9.
s = "3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2"
m = 9
sn = s.replace(",","+") # replace "," with "+"
d = {} # create a dictionary
# create list of strings:
# s2 = ["3+0","0+4","4+0".............]
# s3 = ["3+0+4","0+4+0","4+0+3".............]
# .
# .
# .
for n in range(2,len(s.split(","))):
d["s%s"%n] = [sn[i:i+(2*n-1)] for i in range(0,len(sn),2)][:-n+1]
# evaluate whether sum of individual lists equal to m or not, then find out how many such lists are there
l = sum([eval(x)==m for y in d.values() for x in y] )
# remember we didnot add s1, i,e check whether individual string == m or not
l = l+sum([x==m for x in s.split(",")])
print(l)
7
Related
i have a list :
l= [3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 3, 4]
now i want to check if while going from index(x) to index(x+1) does it fall in any of the following pattern_list
pattern=['03','34','46','60'].
If that exists then make another list k where values are stored in the form 0 or 1, meaning 0 no pattern and 1 pattern exists.
e.g.
k=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
I tried this :
s_1_list=[]
str_1 = ""
for i in l:
str_1 += str(i)
regexList_1= ['03','34','46','60']
for regex in regexList_1:
s_1 = str_1.count(regex)
s_1_list.append(s_1)
print("Number of times " + regex + " repeated= ", s_1)
output :
Number of times 03 repeated= 0
Number of times 34 repeated= 1
Number of times 46 repeated= 0
Number of times 60 repeated= 0
but this doest give me a new list as desired with the following output, can anyone suggest how to proceed ?
Loop over s1, checking if any of the patterns are found at that index, and put 0 or 1 in the result list.
s_1_list = [1 if str_1[i:i+2] in regexList_1 else 0 for i in range(len(str_1)-1)]
Here is my solution.
pattern = ['03', '34', '46', '60']
l = [3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 4, 3, 0, 6, 3, 4]
k = []
for i in range(len(l) - 1):
temp = ''
temp += str(l[i]) + str(l[i + 1])
if temp in pattern:
k.append(1)
else:
k.append(0)
print(k)
I have a list like this:
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
So list_target consists of blocks of consecutive values, between which are jumps in values (like from 7 to 12). list_primer consists of values at the beginning of those blocks. Elements in list_primer are generated in another process.
My question is: for each element of list_primer, how can I identify the block in list_target and replace their values with what I want? For example, if I choose to replace the values in the first block with 1 and the second with 0, the outcome looks like:
list_target_result = [1, 1, 1, 1, 0, 0, 0]
Here's a simple algorithm which solves your task by looping through both lists beginning to end:
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_values = [1, 0]
result = []
for i, primer in enumerate(list_primer):
for j, target in enumerate(list_target):
if target == primer+1:
primer += 1
result.append(block_values[i])
else:
continue
print(result)
[1, 1, 1, 1, 0, 0, 0]
Note that you might run into trouble if not all blocks have a respective primer, depending on your use case.
Modifying method to find groups of strictly increasing numbers in a list
def group_seq(l, list_primer):
" Find groups which are strictly increasing or equals next list_primer value "
temp_list = cycle(l)
temp_primer = cycle(list_primer)
next(temp_list)
groups = groupby(l, key = lambda j: (j + 1 == next(temp_list)) or (j == next(temp_primer)))
for k, v in groups:
if k:
yield tuple(v) + (next((next(groups)[1])), )
Use group_seq to find strictly increasing blocks in list_target
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_values = [1, 0]
result = []
for k, v in zip(block_values, group_seq(list_target, list_primer)):
result.extend([k]*len(v)) # k is value from block_values
# v is a block of strictly increasing numbers
# ie. group_seq(list_target) creates sublists
# [(4, 5, 6, 7), (12, 13, 14)]
print(result)
Out: [1, 1, 1, 1, 0, 0, 0]
Here's a solution using numpy.
import numpy as np
list_target = np.array([4, 5, 6, 7, 12, 13, 14])
list_primer = np.array([3, 11])
values = [1, 0]
ix = np.searchsorted(list_target, list_primer)
# [0,4]
blocks = np.split(list_target, ix)[1:]
# [array([4, 5, 6, 7]), array([12, 13, 14])]
res = np.concatenate([np.full(s.size, values[i]) for i,s in enumerate(blocks)])
# array([1, 1, 1, 1, 0, 0, 0])
Here is a solution that works in O(n), where n=len(list_target). It assumes that your list_target list is consecutive in the way you described (increments by exactly one within block, increments of more than one between blocks).
It returns a dictionary with the beginning of each block as key (potential primers) and lower and upper indices of that block within list_target as values. Access to that dict is then O(1).
list_target = [4, 5, 6, 7, 12, 13, 14]
list_primer = [3, 11]
block_dict = dict()
lower_idx = 0
upper_idx = 0
for i, val in enumerate(list_target): # runs in O(n)
upper_idx = i + 1
if i == len(list_target) - 1: # for last block in list
block_dict[list_target[lower_idx] - 1] = (lower_idx, upper_idx)
break
if list_target[i + 1] - list_target[i] != 1: #if increment more than one, save current block to dict, reset lower index
block_dict[list_target[lower_idx] - 1] = (lower_idx, upper_idx)
lower_idx = i + 1
Here are the results:
print(block_dict) # quick checks
>>>> {3: (0,4), 11: (4,7)}
for p in list_primer: # printing the corresponding blocks.
lower, upper = block_dict[p] # dict access in O(1)
print(list_target[lower:upper])
>>>> [4, 5, 6, 7]
[12, 13, 14]
# getting the indices for first primer marked as in your original question:
list_target_result = [0] * len(list_target)
lower_ex, upper_ex = block_dict[3]
list_target_result[lower_ex: upper_ex] = [1]*(upper_ex-lower_ex)
print(list_target_result)
>>>> [1, 1, 1, 1, 0, 0, 0]
c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
desired output:
fc = [-1,0,1,2,3],[0,1,2,3,4]
fd = [2,3,4,5,6]
fa = []
I want to find how many times the ordered set is in the larger set given an interval. In my case, I choose 5 since this is for my poker game. Set's won't work since they need to be in order so I don't know what to use.
In my program, I tried using for loops but I'm not getting it.
ns = len(c)-5
nt = range(0,ns)
if ns >= 0:
for n in nt:
templist = c[n:n+5]
I just need a function to compare both lists.
Compare the small lists to slices of main.
c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
for sublist in [c, d, a]:
l = len(sublist)
i = 0
while i + l <= len(main):
if sublist == main[i:i+l]:
print 'sublist %s matches' % sublist
i = i + 1
Neither pretty nor optimal, but it does what seems to be asked:
c = [-1, 0, 1, 2, 3, 4]
d = [-1, 0, 2, 3, 4, 5, 6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
def find_in_order(to_find, to_search, num_to_find):
solutions = []
for bucket in to_find:
bucket_solutions = []
solutions.append(bucket_solutions)
for thing in [bucket[x:x + num_to_find] for x in range(len(bucket) - num_to_find + 1)]:
for section in [main[y:y + num_to_find] for y in range(len(to_search) - num_to_find + 1)]:
if thing == section:
bucket_solutions.append(thing)
return solutions
fc, fd, fa = find_in_order([c, d, a], main, 5)
# fc == [[-1, 0, 1, 2, 3], [0, 1, 2, 3, 4]]
# fd == [[2, 3, 4, 5, 6]]
# fa == []
There's not bounds-checking in this, so it might be brittle. I also don't like how the additions of the magic number 1 are needed to get things to align. If you care about speed, string searches do things like keeping a rolling checksum and only doing comparisons when the checksums match. This is left as an exercise. Also, I'm on:
sys.version
'3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) \n[GCC 7.3.0]'
Here is a function that I made that might help you. You can pass your list as an argument and it will compare the lists.
main_set = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
c = [-1, 0, 1, 2, 3, 4]
def compare(cmp_array):
new_arrays = []
temp = []
for pos, i in enumerate(cmp_array):
for i2 in range(pos, pos+5):
temp.append(cmp_array[i2])
new_arrays.append(temp)
temp = []
if pos >= len(cmp_array)-5:
break
return_arrays = []
for array in new_arrays:
for pos, i in enumerate(main_set):
match = True
if i == array[0]:
for pos2 in range(pos, pos+5):
if array[pos2-pos] != main_set[pos2]:
match = False
break
if match:
return_arrays.append(array)
return return_arrays
fc = compare(c)
print(fc)
I need to implement Sieve of Eratosthenes algorithm.
I have list:
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
I need to replace each odd element with "0".
Now I have code:
while viewIndex < maxNumber:
bar[viewIndex] = 0
viewIndex += 2
But I remember about slices. And for me it will be nice to write something like this:
bar[currentIndex::2] = 0
But I have error:
TypeError: must assign iterable to extended slice
Maybe you know a beautiful solution to this task.
You should assign the slice to an iterable of the same length as the number of odds:
bar[1::2] = [0]*(len(bar)//2)
print(bar)
# [2, 0, 4, 0, 6, 0, 8, 0, 10]
To extend this for even indices, you need to take into consideration lists with odd-lengths (not relevant for the above case) by adding the modulo 2 value of the list length:
bar[::2] = [0]*(len(bar)//2 + len(bar)%2)
Which is same as:
bar[::2] = [0]*sum(divmod(len(bar), 2))
I use numpy:
foo = np.ones(10)
foo[1::2] = 2
This just works.
You shouldn't have to keep track of indices -- the point of slicing is to make things more convenient, not to force you to keep track of which day of the week relative to the third Tuesday of last month you bought bread.
Use simple for loop
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(len(bar)):
if bar[i] % 2 != 0:
bar[i] = 0
print(bar)
Output
[2, 0, 4, 0, 6, 0, 8, 0, 10]
You can use map to set elements on odd index to zero,
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
print map(lambda i: 0 if bar.index(i)%2!=0 else i, bar)
[2, 0, 4, 0, 6, 0, 8, 0, 10]
or if you want to set odd element value to zero, you can do this,
map(lambda i: 0 if i%2!=0 else i, bar)
Thank to all for answers. My implementation of Sieve of Eatosthenes algorithm:
def resheto(data):
print("\tStart Resheto")
currentIndex = 0
while currentIndex < len(data) - 1:
data[currentIndex + data[currentIndex]::data[currentIndex]] = \
[0] * ((len(data) + 1) // data[currentIndex] - 1)
currentIndex += 1
while currentIndex < len(data) - 1 and data[currentIndex] == 0:
currentIndex += 1
if currentIndex >= len(data) - 1:
break
print("\tEnd Resheto") return data
def heap_sort(nos):
global size
size = len(nos)
print "the size of the List is : %d " %size
Build_heap(size,nos)
for i in range(size-1,0,-1):
nums[0],nums[i] = nums[i],nums[0]
size = size-1
print "\n", nums
heapify(nos,i,size)
print "heap sort array:" ,nums
def left_child(i):
return 2*i+1
def right_child(i):
return 2*i+2
def heapify(nums,i,size):
l = left_child(i)
r = right_child(i)
if l <= size and r <= size:
if r != size:
if nums[l] >= nums[r]:
max = nums[l]
max_index = l
elif nums[l] <= nums[r]:
max = nums[r]
max_index = r
if nums[i] >= max:
print nums
return
elif nums[i] <= max:
nums[i],nums[max_index] = max,nums[i]
heapify(nums,max_index,size)
else:
nums[i],nums[l] = nums[l],nums[i]
print nums
# build a heap A from an unsorted array
def Build_heap(size,elements):
iterate = size//2-1
for i in range(iterate,-1,-1):
print "In %d iteration" %i
heapify(elements,i,size)
print "heapified array is : " ,elements
if __name__ == '__main__':
#get input from user
nums = [6,9,3,2,4,1,7,5,10]
#sort the list
heap_sort(nums)
Output which I get is something like this:
the size of the List is : 9
In 3 iteration
[6, 9, 3, 10, 4, 1, 7, 5, 2]
In 2 iteration
[6, 9, 7, 10, 4, 1, 3, 5, 2]
In 1 iteration
[6, 10, 7, 9, 4, 1, 3, 5, 2]
[6, 10, 7, 9, 4, 1, 3, 5, 2]
In 0 iteration
[10, 6, 7, 9, 4, 1, 3, 5, 2]
[10, 9, 7, 6, 4, 1, 3, 5, 2]
[10, 9, 7, 6, 4, 1, 3, 5, 2]
heapified array is : [10, 9, 7, 6, 4, 1, 3, 5, 2]
heap sort array:
[9, 7, 6, 4, 1, 3, 5, 2, 10]
I tried implementing a heap sort algorithm in python. The final output is not sorted. There is something wrong in the heapify operation which I tried to figure out, but I couldn't find it.
Can someone point out what's wrong in my code and propose a solution for it?
The first item(0) was swaped with the last item. To keep max-heap invairant, you should call heapify with 0.
def heap_sort(nos):
size = len(nos)
build_heap(size,nos)
for i in range(size-1,0,-1):
nums[0],nums[i] = nums[i],nums[0]
size -= 1
heapify(nos, 0, size) # <--- i -> 0
The following is my PYTHON implementation. If the program is "heapsort.py", an example to run it is "python heapsort.py 10", to sort 10 randomly generated numbers.
The validation code is near the end of the program, to verify the correctness of the function, heapsort().
#!/bin/python
#
# TH #stackoverflow, 2016-01-20, HeapSort
#
import sys, random
def pushdown( A, root, size_of_A ):
M = root * 2
if(M <= size_of_A):
if(size_of_A > M):
if(A[M - 1] < A[M]):
M += 1
if(A[root - 1] < A[M - 1]):
A[root - 1], A[M - 1] = A[M - 1], A[root - 1]
pushdown(A, M, size_of_A)
def heapsort( H ):
for i in range(len(H)/2, 0, -1):
pushdown(H, i, len(H))
for i in range(len(H) - 1, 0, -1):
H[i], H[0] = H[0], H[i]
pushdown(H, 1, i)
return H
number_to_numbers = int(sys.argv[1])
X = [ random.randint(0, number_to_numbers) for i in range(number_to_numbers) ]
Y = X
print Y
print heapsort(X)
print sorted(Y)