I have 5 multidimensional arrays
A = [ [1,2,3,4,5,6]
[3,4,5,6,7,8]
[5,6,7,8,9,0] ]
B = [ [11,12,13,14,15,16]
[21,22,23,24,25,26]
[13,14,15,16,17,18] ]
C = [ [31,32,33,34,35,36]
[12,13,14,15,16,17]
[20,21,22,23,24,25] ]
D = [ [2,3,4,5,6,7]
[3,4,5,6,7,8]
[6,7,8,9,0,11] ]
Base = [ [11,22,33,44,55,66]
[12,23,34,45,56,67]
[33,44,55,66,77,88]
[1,2,3,4,5,6] ]
So I want to multiply the array A, B, C, and D by the Base array. Which will produce output like the following
Output = [ [A[0]*Base[0] + B[0]*Base[1] + C[0]*Base[2] + D[0]*Base[3] ], (this is summed)
[A[1]*Base[0] + B[1]*Base[1] + C[1]*Base[2] + D[1]*Base[3] ], (this is summed)
[A[2]*Base[0] + B[2]*Base[1] + C[2]*Base[2] + D[2]*Base[3] ], (this is summed)
[A[3]*Base[0] + B[3]*Base[1] + C[3]*Base[2] + D[3]*Base[3] ] (this is summed)
]
what I've been trying to do is to use an algorithm like the following.
Multiply them one by one,
Output 1 = A*Base[0]
Output 2 = B*Base[1]
Output 3 = C*Base[2]
Output 4 = D*Base[3]
then add them up one by one
Sum1 = sum(Output1[0])
Sum2 = sum[Output1[1])
Sum3 = sum(Output1[2])
Sum4 = sum(Output2[0])
Sum5 = sum(Output2[1])
...
...
...
...
So I get the output by adding them up : [Sum1 + Sum4 +.....], [Sum2 + Sum5+....]....
Is there a simpler and shorter way to do this, apart from multiplying them one by one?
It's not very clear what operation result you want with multiplying arrays, but just use numpy to make your life easier.
A, B, C, D, Base = np.array(A), np.array(B), np.array(C), np.array(D), np.array(Base)
For instance, the following operation multiplies and sum A * Base resulting in 4 * 3 sum arrays:
[sum(list(base_list * A_list)) for base_list in Base for A_list in A]
[1001, 1463, 1265, 1022, 1496, 1300, 1463, 2189, 2035, 91, 133, 115]
Then just sum the results to obtain the full sum of A*Base in 1/2 lines (and do the same with the remaining ones)
sum([1001, 1463, 1265, 1022, 1496, 1300, 1463, 2189, 2035, 91, 133, 115])
13573
numpy is really useful for this type of operation. Here a code snippet for what you want to do:
import numpy as np
A = [[1, 2, 3, 4, 5, 6],
[3, 4, 5, 6, 7, 8],
[5, 6, 7, 8, 9, 0]]
B = [[11, 12, 13, 14, 15, 16],
[21, 22, 23, 24, 25, 26],
[13, 14, 15, 16, 17, 18]]
C = [[31, 32, 33, 34, 35, 36],
[12, 13, 14, 15, 16, 17],
[20, 21, 22, 23, 24, 25]]
D = [[2, 3, 4, 5, 6, 7],
[3, 4, 5, 6, 7, 8],
[6, 7, 8, 9, 0, 11]]
Base = [
[11, 22, 33, 44, 55, 66],
[12, 23, 34, 45, 56, 67],
[33, 44, 55, 66, 77, 88],
[1, 2, 3, 4, 5, 6]
]
A = np.asarray(A)
B = np.asarray(B)
C = np.asarray(C)
D = np.asarray(D)
Base = np.asarray(Base)
Output = np.asarray([
[A[0] * Base[0] + B[0] * Base[1] + C[0] * Base[2] + D[0] * Base[3]],
[A[1] * Base[0] + B[1] * Base[1] + C[1] * Base[2] + D[1] * Base[3]],
[A[2] * Base[0] + B[2] * Base[1] + C[2] * Base[2] + D[2] * Base[3]],
# [A[3] * Base[0] + B[3] * Base[1] + C[3] * Base[2] + D[3] * Base[3]] # IndexError: index 3 is out of bounds for axis 0 with size 3 -> the matrices A, B, C and D have only 3 rows
]).squeeze()
print(f"{A.shape = } {B.shape = } {C.shape = } {D.shape = } {Base.shape = }, {Output.shape = }")
# simple math
results_simple = A * Base[0] + B * Base[1] + C * Base[2] + D * Base[3]
print(f"{results_simple.shape = }")
print(f"{np.allclose(results_simple, Output) = }")
# result with more algebra
M = np.stack([A, B, C, D], axis=1)
print(f"{M.shape = }")
results_algebra = np.sum(M * Base, axis=1)
print(f"{results_algebra.shape = }")
print(f"{np.allclose(results_algebra, Output) = }")
# results with einsum
results_einsum = np.einsum("ijk,jk->ik", M, Base)
print(f"{results_einsum.shape = }")
print(f"{np.allclose(results_einsum, Output) = }")
out:
A.shape = (3, 6) B.shape = (3, 6) C.shape = (3, 6) D.shape = (3, 6) Base.shape = (4, 6), Output.shape = (3, 6)
results_simple.shape = (3, 6)
np.allclose(results_simple, Output) = True
M.shape = (3, 4, 6)
results_algebra.shape = (3, 6)
np.allclose(results_algebra, Output) = True
results_einsum.shape = (3, 6)
np.allclose(results_einsum, Output) = True
After this, you can get the sum of the output in a certain axis using the function numpy.sum. You will have something like this:
out_sum = np.sum(Output, axis=-1)
Related
from the book data-science for supply chain forecast by Nicolas Vandeput
first chap, in this code snippet plt.show() dispaly data but I can not find at what point the arguments passed to it.
from chap_01_05_moving_average_function import (
moving_average,
)
import matplotlib.pyplot as plt
d = [28, 19, 18, 13, 19, 16, 19, 18, 13, 16, 16, 11, 18, 15, 13, 15, 13, 11, 13, 10, 12]
df = moving_average(d)
print(df)
df[["Demand", "Forecast"]].plot()
df.index.name = "Periods"
print("index", df.index.name)
df[["Demand", "Forecast"]].plot(
figsize=(8, 3), title="Moving average", ylim=(0, 30), style=["-", "--"]
)
plt.show()
this is chap_01_05_moving_average_function.py:
# page 5 - moving average
import numpy as np
import pandas as pd
def moving_average(d, extra_periods=1, n=3):
d = np.array(d)
cols = len(d)
d = np.append(d, [np.nan] * extra_periods)
f = np.full(cols + extra_periods, np.nan)
for t in range(n, cols + 1):
f[t] = np.mean(d[t - n : t])
f[cols + 1 :] = f[t]
df = pd.DataFrame.from_dict({"Demand": d, "Forecast": f, "Error": d - f})
return df
# numpy - add arrays
ts = np.array([1, 2, 3, 4, 5, 6])
ts2 = np.array([10, 20, 30, 40, 50, 60])
print(ts + ts2)
# numpy - list
alist = [1, 2, 3]
alistmean = np.mean(alist)
print(alistmean)
# slicing
alist = ["cat", "dog", "mouse"]
print(alist[1])
anarray = np.array([1, 2, 3])
print(anarray[0])
# slicing - start:end
alist = ["cat", "dog", "mouse"]
print(alist[1:])
anarray = np.array([1, 2, 3])
print(anarray[:1])
# slicing - negative
alist = ["cat", "dog", "mouse"]
print(alist[-1])
print(alist[:-1])
I am new to python I dont know if there is an implicit way of passing parameters
I have one list representing point in time of a change, and another one of values:
indexes_list = [5, 6, 8, 9, 12, 15]
# [ 5 6 8 9 12 15]
values_list = [i * 10 for i in range(6)]
# [ 0 10 20 30 40 50]
I want to create the "full" list, which in the above example is:
expanded_values = [0, 0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
# [ 0 0 0 0 0 0 10 20 20 30 40 40 40 50 50 50]
I wrote something, but it feels wrong and I guess there is a better, more pythonic way of doing that:
result = []
for i in range(len(values_list)):
if i == 0:
tmp = [values_list[i]] * (indexes_list[i] + 1)
else:
tmp = [values_list[i]] * (indexes_list[i] - indexes_list[i - 1])
result += tmp
# result = [0, 0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
Use:
indexes_array = [5, 6, 8, 9, 12, 15]
values_array = [i * 10 for i, _ in enumerate(range(6))]
diffs = indexes_array[:1] + [j - i for i, j in zip(indexes_array, indexes_array[1:])]
res = [v for i, v in zip(diffs, values_array) for _ in range(i)]
print(res)
Output
[0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
As an alternative, you could use the pairwise recipe with a twist:
from itertools import tee
def pairwise(iterable, prepend):
a, b = tee(iterable)
yield prepend, next(b, None)
yield from zip(a, b)
indices = [5, 6, 8, 9, 12, 15]
values = [i * 10 for i, _ in enumerate(range(6))]
differences = [second - first for first, second in pairwise(indices, prepend=0)]
res = [v for i, v in zip(differences, values) for _ in range(i)]
print(res)
Output
[0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
Finally if you are doing numerical work I advise that you use numpy, as below:
import numpy as np
indices = [5, 6, 8, 9, 12, 15]
values = [i * 10 for i, _ in enumerate(range(6))]
differences = np.diff(indices, prepend=0)
res = np.repeat(values, differences).tolist()
print(res)
I would argue that it is pythonic to use the appropriate library, which in this case is pandas:
import pandas as pd
indexes_array = [5, 6, 8, 9, 12, 15]
values_array = [i * 10 for i in range(6)]
series = pd.Series(values_array, indexes_array).reindex(
range(indexes_array[-1] + 1), method='backfill')
series
0 0
1 0
2 0
3 0
4 0
5 0
6 10
7 20
8 20
9 30
10 40
11 40
12 40
13 50
14 50
15 50
dtype: int64
See the reindex documentation for details.
Try this:
indexes_array = [5, 6, 8, 9, 12, 15]
# [ 5 6 8 9 12 15]
values_array = [i * 10 for i, _ in enumerate(range(6))]
# [ 0 10 20 30 40 50]
result = []
last_ind = 0
zipped = zip(indexes_array, values_array)
for ind, val in zipped:
count = ind - last_ind
last_ind = ind
for i in range(count):
result.append(val)
print(result)
Output:
[0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
Try this:
indexes_array = [5, 6, 8, 9, 12, 15]
values_array = [i * 10 for i, _ in enumerate(range(6))]
output=[]
for x in range(len(indexes_array)):
if x ==0:
output.extend([values_array[x]]*indexes_array[x])
else:
output.extend([values_array[x]]*(indexes_array[x]-indexes_array[x-1]))
print(output)
The output is :
[0, 0, 0, 0, 0, 10, 20, 20, 30, 40, 40, 40, 50, 50, 50]
So i'm doing pyschools topic 6 question 23:
Write a function getNumbers(number) that takes in a number as argument and return a list of numbers as shown in the samples given below.
Examples
>>> getNumbers(10)
[100, 64, 36, 16, 4, 0, 4, 16, 36, 64, 100]
>>> getNumbers(9)
[81, 49, 25, 9, 1, 1, 9, 25, 49, 81]
>>> getNumbers(8)
[64, 36, 16, 4, 0, 4, 16, 36, 64]
>>> getNumbers(0)
[0]
This is my code:
def getNumbers(num):
x = []
y = []
if num % 2 == 0:
x = [i**2 for i in range(0, num+2, 2)]
y = [i**2 for i in range(0, num+2, 2)]
z = sorted(x, reverse=True) + y
if z.count(0) > 1:
z.remove(0)
return z
elif num % 3 == 0:
x = [i**2 for i in range(1, num+2, 2)]
y = [i**2 for i in range(1, num+2, 2)]
return sorted(x, reverse=True) + y
elif num == 1:
x.append(num)
y.append(num)
return sorted(x, reverse=True) + y
Which works but, i'm not passing Private Test Case. Any ideea why?
Private Test Case is something made by them to see if you hard code.
Test Cases Expected Result Returned Result
getNumbers(10) [100, 64, 36, 16, 4, 0, 4, 16, 36, 64, 100] [100, 64, 36, 16, 4, 0, 4, 16, 36, 64, 100]
getNumbers(9) [81, 49, 25, 9, 1, 1, 9, 25, 49, 81] [81, 49, 25, 9, 1, 1, 9, 25, 49, 81]
Private Test Cases Passed Failed
getNumbers(0) [0] [0]
getNumbers(1) [1, 1] [1, 1]
This was the easiest thing to do:
def getNumbers(num):
x = -num
y = list(range(x, num+1, 2))
return [i**2 for i in y]
getNumbers(10)
[100, 64, 36, 16, 4, 0, 4, 16, 36, 64, 100]
Also please find below a version
def getNumbers(num):
n=list(range(num+1))
num1=[]
x=num
for i in n:
x=num**2
num1.append(x)
num-=2
return num1
def getNumbers(num):
return [i * i for i in range(-num, num + 1, 2)]
Square of a number is always positive. You need to end the range on num + 1 to include number in the result. The range is iterable, so the list around range is spurious.
I have come across the classic problem today.
The problem description is on Timus : 1005.
I know how to solve it in c++.
But when I tried it in python, I got Time Limit Exceeded.
I use brute force but failed. Then I tried DP, also failed.
Here is my solution:
n = int(input())
wi = list(map(int, input().split()))
ans = 1<<21
up = (1<<(n-1))-1
su = 0
for x in range(up, -1, -1):
su = 0
for y in range(n):
su += wi[y] if (x & 1<<y) else -wi[y]
ans = min(ans, abs(su))
print(ans)
It got TLE on Test3.
Here is another DP solution:
n = int(input())
wi = list(map(int, input().split()))
wi.sort()
ans = sum(x for x in wi)
up = ans // 2
dp = [0] * (up + 1)
dp[0] = 1
for x in range(n):
for y in range(up, wi[x]-1, -1):
dp[y] |= dp[y-wi[x]]
aw = up
while not dp[aw]:
aw -= 1
print(ans - 2 * aw)
Got TLE on Test 4.
So my question is how to pass the problem time limit while using Python ?
this just dummy algorithm, and don't know if it returns correct result.
actually for smaller ranges, that I can calculate it always return correct result, but for the greater ones - really don't know :) it should be better to check with your working c++ code, if it's ok.
def minimizing_diff(lst):
a = list()
b = list()
for i in sorted(lst, reverse = True):
if sum(a)>sum(b):
b.append(i)
else:
a.append(i)
return (len(a), a, len(b), b, abs(sum(a)-sum(b)))
# I am returning the first 4 elements to debug by eye :)
These are ok. You can check by pen and papaer :)
0..9 => (5, [9, 6, 5, 2, 1], 5, [8, 7, 4, 3, 0], 1)
0..19 => (10, [19, 16, 15, 12, 11, 8, 7, 4, 3, 0], 10, [18, 17, 14, 13, 10, 9, 6, 5, 2, 1], 0)
0..14 => (7, [14, 11, 10, 7, 6, 3, 2], 8, [13, 12, 9, 8, 5, 4, 1, 0], 1)
Other results (random 20 numbers between 1 and 9999): All of them completed less than 0.1 seconds.
(10, [9944, 8573, 8083, 6900, 6664, 4644, 4544, 2362, 1522, 947], 10, [9425, 8647, 8346, 7144, 6252, 6222, 3749, 1803, 1760, 126], 709)
(10, [9839, 7087, 6747, 6016, 5300, 4174, 3702, 2469, 1970, 1758], 10, [9490, 9246, 6436, 6010, 4690, 4168, 3608, 2374, 1879, 1684], 523)
(10, [9209, 8754, 8613, 6383, 6286, 5222, 4992, 3119, 2950, 147], 10, [9102, 8960, 7588, 7317, 6042, 5769, 4861, 3041, 2078, 1516], 599)
(10, [8096, 7757, 6975, 6677, 5204, 4354, 3174, 3132, 1237, 425], 10, [8033, 7765, 7140, 6089, 5511, 4385, 3482, 2877, 1253, 1139], 643)
(10, [9243, 7887, 6890, 6689, 6347, 5173, 3953, 3380, 3079, 1032], 10, [9131, 7996, 7791, 6403, 5621, 5585, 3632, 3436, 2959, 1291], 172)
(10, [9697, 8504, 7731, 7504, 6696, 4671, 4464, 3057, 1929, 1691], 10, [9384, 8540, 8319, 7233, 6252, 5549, 4275, 2154, 2023, 1794], 421)
Because Python integers can be arbitrarily large, a single integer can be used to represent a boolean array, such as the variable dp in your second solution. This lets you replace the inner loop with a couple of bitwise operations:
ans = sum(wi)
up = ans // 2
mask = 2 ** (up + 1) - 1
dp = 1
for x in wi:
dp |= dp << x & mask
aw = dp.bit_length() - 1
print(ans - 2 * aw)
I have two lists of numbers, say [1, 2, 3, 4, 5] and [7, 8, 9, 10, 11], and I would like to form a new list which consists of the products of each member in the first list with each member in the second list. In this case, there would be 5*5 = 25 elements in the new list.
I have been unable to do this so far with a while() loop.
This is what I have so far:
x = 0
y = 99
results = []
while x < 5:
x = x + 1
results.append(x*y)
while y < 11:
y = y + 1
results.append(x*y)
Use itertools.product to generate all possible 2-tuples, then calculate the product of that:
[x * y for (x, y) in itertools.product([1,2,3,4,5], [7,8,9,10,11])]
The problem is an example of an outer product. The answer already posted with itertools.product is the way I would do this as well.
But here's an alternative with numpy, which is usually more efficient than working in pure python for crunching numeric data.
>>> import numpy as np
>>> x1 = np.array([1,2,3,4,5])
>>> x2 = np.array([7,8,9,10,11])
>>> np.outer(x1,x2)
array([[ 7, 8, 9, 10, 11],
[14, 16, 18, 20, 22],
[21, 24, 27, 30, 33],
[28, 32, 36, 40, 44],
[35, 40, 45, 50, 55]])
>>> np.ravel(np.outer(x1,x2))
array([ 7, 8, 9, 10, 11, 14, 16, 18, 20, 22, 21, 24, 27, 30, 33, 28, 32,
36, 40, 44, 35, 40, 45, 50, 55])
Wht dont you try with known old ways;
list1 = range(1, 100)
list2 = range(10, 50, 5)
new_values = []
for x in list1:
for y in list2:
new_values.append(x*y)
Without any importing, you can do:
[x * y for x in range(1, 6) for y in range(7, 12)]
or alternatively:
[[x * y for x in range(1, 6)] for y in range(7, 12)]
To split out the different multiples, but it depends which order you want the results in.
from functools import partial
mult = lambda x, y: x * y
l1 = [2,3,4,5,5]
l2 = [5,3,23,4,4]
results = []
for n in l1:
results.extend( map( partial(mult, n) , l2) )
print results