Suppose I have an array lets say [1,2,3,4]:
I want to find the sum as follows:
First I generate pairs like:
(1 2 3 4)
(123)(4)
(1)(234)
(12)(34)
(12)(3)(4)
(1)(23)(4)
(1)(2)(34)
(1)(2)(3)(4)
The ans would then be sum of elements in one group multiplied by the length of that group(for all possible groups)
eg in the arrangement (123)(4), the sum would be
(1+2+3)*3 + (4)*1
I just want the final sum which is sum of all such values , not the actual groups. How can I do this?
I was able to do it by first generating all possible groups and then finding the sum
But since I only need the sum and not the actual groups, is there a better way?
The number of arrangements is 2**(len(L)-1). A list of 8 elements produce 128 different arrangements. It is an exponential problem. You either generate all possible solutions and then calculate each answer, or you calculate each answer on the fly. Either way it is still exp.
def part1(L, start, lsum):
if start == len(L):
print lsum
else:
for i in range(start, len(L)):
left = sum(L[start:i+1]) * (i-start+1)
part1(L, i + 1, lsum + left)
def part2(L, M, X, start):
if start == len(L):
M.append(X)
print sum([sum(x) * len(x) for x in X])
else:
for i in range(start, len(L)):
part2(L, M, X + [L[start:i+1]], i + 1)
ex:
>>> part1(L, 0, 0)
10
17
15
28
13
20
22
40
>>> M = []
>>> part2(L, M, [], 0)
10
17
15
28
13
20
22
40
edit: sum of all the sums in O(n**3)
for L = [1,2,3,4,5,6]
[[[1], [2], [3], [4], [5], [6]],
[[1], [2], [3], [4], [5, 6]],
[[1], [2], [3], [4, 5], [6]],
[[1], [2], [3], [4, 5, 6]],
[[1], [2], [3, 4], [5], [6]],
[[1], [2], [3, 4], [5, 6]],
[[1], [2], [3, 4, 5], [6]],
[[1], [2], [3, 4, 5, 6]],
[[1], [2, 3], [4], [5], [6]],
[[1], [2, 3], [4], [5, 6]],
[[1], [2, 3], [4, 5], [6]],
[[1], [2, 3], [4, 5, 6]],
[[1], [2, 3, 4], [5], [6]],
[[1], [2, 3, 4], [5, 6]],
[[1], [2, 3, 4, 5], [6]],
[[1], [2, 3, 4, 5, 6]],
[[1, 2], [3], [4], [5], [6]],
[[1, 2], [3], [4], [5, 6]],
[[1, 2], [3], [4, 5], [6]],
[[1, 2], [3], [4, 5, 6]],
[[1, 2], [3, 4], [5], [6]],
[[1, 2], [3, 4], [5, 6]],
[[1, 2], [3, 4, 5], [6]],
[[1, 2], [3, 4, 5, 6]],
[[1, 2, 3], [4], [5], [6]],
[[1, 2, 3], [4], [5, 6]],
[[1, 2, 3], [4, 5], [6]],
[[1, 2, 3], [4, 5, 6]],
[[1, 2, 3, 4], [5], [6]],
[[1, 2, 3, 4], [5, 6]],
[[1, 2, 3, 4, 5], [6]],
[[1, 2, 3, 4, 5, 6]]]
There seems to be a pattern. The odd case is: the sets having the first elements of the sequence as the smallest element as the sorted set, there are 32. But then all the rest there are 16. For each element of the list, I add all the sets which contains that element as the first sorted element.
def part3(L):
ret = 0
for i in range(len(L)):
p = 0
for k in range(len(L) - i - 1):
p += sum(L[i:i+k+1]) * (k+1) * 2**(len(L) - i - k - 2)
p += sum(L[i:]) * (len(L) - i)
ret += p * max(1, 2**(i-1))
return ret
edit2: to lower it to O(n^2) you need to use DP. building a table of sums to calculate each sum in O(1). You build an array S with S[i] = S[i-1] + L[i] and sum(L[a:b]) is S[b] - S[a].
Related
When I need to add two 2D lists element wise, the approach I am using is
l1 = [[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]
l2 = [[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]
new = list(map(lambda e: [sum(x) for x in zip(*e)], zip(l1, l2)))
print(new)
output : [[2, 2, 2],
[4, 4, 4],
[6, 6, 6]]
This code is already difficult to read.
So how would I add two n dimensional lists element wise? Is there a pythonic way to do it or should I use numpy?
I have a CSV dataset as shown below:
index
s_key
identifier
edge_pairs
0
[1683, 1684, 1685, 1686, 1688, 1689, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 12740]
[0, 0]
[[0, 793]]
1
[9774, 9800, 9807, 9818, 9831, 9834, 9836, 9837, 9839, 9843, 13723, 21455]
[0, 1]
[[1, 3], [1, 123], [1, 152], [1, 163], [1, 266], [1, 337], [1, 351], [1, 352], [1, 355], [1, 606], [1, 869], [1, 962], [1, 1125], [1, 1412], [1, 1413], [1, 1417], [1, 1435], [1, 1440], [1, 1454], [1, 1572], [1, 1588], [1, 1653], [1, 1726], [1, 1898], [1, 2075], [1, 2076], [1, 2166], [1, 2297], [1, 2299], [1, 2319], [1, 2327], [1, 2330], [1, 2335], [1, 2393], [1, 2395], [1, 2400], [1, 2405], [1, 2486]]
3
[2156, 2896, 3028, 4023, 4256, 6787, 7265, 8882, 8970, 9831, 10959, 11268, 11341, 12601, 13737, 17264, 18906, 20430, 21747, 22228, 22229, 22512, 22841, 24049, 25104, 25394, 25731, 26045, 26103, 31121, 31522, 31839, 31851, 31859, 31872, 35527, 35547, 36538, 37150, 37345, 37692, 37888, 37895, 38962, 45332]
[0, 3]
[[3, 8], [3, 11], [3, 12], [3, 13], [3, 27], [3, 34], [3, 99], [3, 123], [3, 125], [3, 130], [3, 132], [3, 133], [3, 134], [3, 144], [3, 147], [3, 152], [3, 154], [3, 180], [3, 181], [3, 207]]
4
[25203, 25204, 25215, 25219, 25227, 25232, 25235, 25248, 25251, 25252, 25259, 25270]
[0, 4]
[[4, 215], [4, 322], [4, 342], [4, 793], [4, 1043], [4, 1127], [4, 1176], [4, 1454], [4, 2154], [4, 2284], [4, 2331], [4, 2400], [4, 2759], [4, 2920], [4, 3335]]
5
[27099, 27101, 27104, 27107, 27108, 27111, 27117, 27120, 27123, 27131, 27143, 27153, 27156, 27158, 27162, 27167, 27172, 27175, 27176, 27178, 27184, 27185]
[0, 5]
[[5, 8], [5, 239], [5, 378], [5, 1163], [5, 1220], [5, 1378], [5, 1422], [5, 1440], [5, 1636], [5, 1681], [5, 2190], [5, 2303], [5, 2399]]
The index column represents each node.
The edge_pairs column represents the connection of each node.
For example: In Index 0, the edge pair column: [[0, 793]] represents the connection of node 0 with Node 793 and so on.
I want to make a graph out of this CSV in a format that PyG accepts data = Data(x=x, edge_index=edge_index, y=y).
I am unsure of what to take as Node Features & Labels and how to represent the connection of edges between them.
My function combinations(ary, p) is suposed to return every possible combination, of order of items in list.
But it always returns the first value multiple times, even tho it finds all the possible orders, which I know because it prints them.
EDIT: I would like to make it work my self, learn something and not use any external libs.
def combinations(ary, p):
ln = len(ary)
bary=[]
for a in range(ln-p):
if p<ln-2:
bb = combinations(ary, p+1)
for be in bb:
bary.append(be)
if p>=ln-2:
bary.append(ary)
ary.append(ary.pop(p))
return bary
Another version with debug print() functions. I will give its sample output.
def combinations(ary, p):
ln = len(ary)
bary=[]
for a in range(ln-p):
if p<ln-2:
bb = combinations(ary, p+1)
for be in bb:
bary.append(be)
if p>=ln-2:
--> bary.append(ary)
--> print('ary', ary, 'bary', bary)
ary.append(ary.pop(p))
return bary
Console output after running with combinations([7,3,2], 0)::
## There is clearly every possible combination:
##
## ||
## ||
\/
ary [7, 3, 2] bary [[7, 3, 2]]
ary [7, 2, 3] bary [[7, 2, 3], [7, 2, 3]]
ary [3, 2, 7] bary [[3, 2, 7]]
ary [3, 7, 2] bary [[3, 7, 2], [3, 7, 2]]
ary [2, 7, 3] bary [[2, 7, 3]]
ary [2, 3, 7] bary [[2, 3, 7], [2, 3, 7]]
[[7, 3, 2], [7, 3, 2], [7, 3, 2], [7, 3, 2], [7, 3, 2], [7, 3, 2]]
The last list is suposed to include every possible order, but it has only the input value order even tho it prints every order. So where did I mess up the return?
Your issue is there is only one copy of ary. You append it to bary many times. So bary is full of the same one list. Any time you make a change to ary. That will be reflected in all of them cause they are all the same list.
Instead when you append to bary assign a copy of ary but as a new list of its own so it wont be affected when you change ary
def combinations(ary, p):
ln = len(ary)
bary=[]
for a in range(ln-p):
if p<ln-2:
bb = combinations(ary, p+1)
for be in bb:
bary.append(be)
if p>=ln-2:
bary.append(ary[:]) #Changed this line to take a shallow copy of ary
print('ary', ary, 'bary', bary)
ary.append(ary.pop(p))
return bary
print(combinations([7,3,2], 0))
OUTPUT
ary [7, 3, 2] bary [[7, 3, 2]]
ary [7, 2, 3] bary [[7, 3, 2], [7, 2, 3]]
ary [3, 2, 7] bary [[3, 2, 7]]
ary [3, 7, 2] bary [[3, 2, 7], [3, 7, 2]]
ary [2, 7, 3] bary [[2, 7, 3]]
ary [2, 3, 7] bary [[2, 7, 3], [2, 3, 7]]
[[7, 3, 2], [7, 2, 3], [3, 2, 7], [3, 7, 2], [2, 7, 3], [2, 3, 7]]
a1=[[1, 2], [2, 3], [2, 4],[3, 4] ,[3, 6], [4, 5]]
i want the output to be:
a1=[[1, 2], [2, 3], [3, 4], [4, 5]]
I've tried removing it with a for loop, but it throws an error index out of range
You can use pop() if you want to remove by index (e.g. the fourth element):
In [1]: a1 = [[1, 2], [2, 3], [2, 4],[3, 4] ,[3, 6], [4, 5]]
In [2]: a1.pop(4)
Out[2]: [3, 6]
In [3]: a1
Out[3]: [[1, 2], [2, 3], [2, 4], [3, 4], [4, 5]]
Or, you can remove by specifying the element:
In [4]: a1 = [[1, 2], [2, 3], [2, 4],[3, 4] ,[3, 6], [4, 5]]
In [5]: a1.remove([3, 6])
In [6]: a1
Out[6]: [[1, 2], [2, 3], [2, 4], [3, 4], [4, 5]]
The answer is very simple just use the pop function.
https://www.geeksforgeeks.org/python-list-pop/
For your case it would be :
a1.pop(4)
you can loop over the Pop() function to remove multiple ones.
given input: theList = [<userID>,<number_of_views>]
theList = [
[[3, 5], [1, 1], [2, 3]],
[[1, 2], [3, 5], [3, 0], [2, 3], [4, 2]],
[[1, 2], [3, 5], [3, 0], [2, 3], [4, 2]],
[[1, 2], [1, 1], [4, 2]]
]
expected output = [
[[3, 5], [2, 3], [1, 1]],
[[3, 5], [2, 3], [1, 2], [4, 2]],
[[3, 5], [2, 3], [1, 2], [4, 2]],
[[1, 3], [4, 2]]
]
for sublist in theList:
e.x -->
theList[3] = [[1,2], [1,1], [4,2]]
how to merge items that have same userIDs = 1 in this case and sum all the corresponding views to this (userID=1) (2+1) = 3 views into a new_list --> [1,3]
expected theList[3] = [[1,3], [4,2]].
How could I make this process for all theList?
Thanks so much for spending time on this question!
This is one approach using collections.defaultdict.
Ex:
from collections import defaultdict
theList = [
[[3, 5], [1, 1], [2, 3]],
[[1, 2], [3, 5], [3, 0], [2, 3], [4, 2]],
[[1, 2], [3, 5], [3, 0], [2, 3], [4, 2]],
[[1, 2], [1, 1], [4, 2]]
]
result = []
for i in theList:
r = defaultdict(int)
for j, k in i:
r[j] += k
result.append(list(r.items()))
print(result)
Output:
[[(3, 5), (1, 1), (2, 3)],
[(1, 2), (3, 5), (2, 3), (4, 2)],
[(1, 2), (3, 5), (2, 3), (4, 2)],
[(1, 3), (4, 2)]]