How to find the max array from both sides - python

Given an integer array A, I need to pick B elements from either left or right end of the array A to get maximum sum. If B = 4, then you can pick the first four elements or the last four elements or one from front and three from back etc.
Example input:
A = [5, -2, 3, 1, 2]
B = 3
The correct answer is 8 (by picking 5 from the left, and 1 and 2 from the right).
My code:
def solve(A, B):
n = len(A)
# track left most index and right most index i,j
i = 0
j = n-1
Sum = 0
B2 = B # B for looping and B2 for reference it
# Add element from front
for k in range(B):
Sum += A[k]
ans = Sum
# Add element from last
for _ in range(B2):
# Remove element from front
Sum -= A[i]
# Add element from last
Sum += A[j]
ans = max(ans, Sum)
return ans
But the answer I get is 6.

Solution
def max_bookend_sum(x, n):
bookends = x[-n:] + x[:n]
return max(sum(bookends[i : i + n]) for i in range(n + 1))
Explanation
Let n = 3 and take x,
>>> x = [4, 9, -7, 4, 0, 4, -9, -8, -6, 9]
Grab the "right" n elements, concatenate with the "left" n:
>>> bookends = x[-n:] + x[:n]
>>> bookends # last three elements from x, then first three
[-8, -6, 9, 4, 9, -7]
Take "sliding window" groups of n elements:
>>> [bookends[i : i + n] for i in range(n + 1)]
[[-8, -6, 9], [-6, 9, 4], [9, 4, 9], [4, 9, -7]]
Now, instead of producing the sublists sum them instead, and take the max:
>>> max(sum(bookends[i : i + n]) for i in range(n + 1))
22
For your large array A from the comments:
>>> max(sum(bookends[i : i + n]) for i in range(n + 1))
6253

Solution based on sum of the left and right slices:
Data = [-533, -666, -500, 169, 724, 478, 358, -38, -536, 705, -855, 281, -173, 961, -509, -5, 942, -173, 436, -609,
-396, 902, -847, -708, -618, 421, -284, 718, 895, 447, 726, -229, 538, 869, 912, 667, -701, 35, 894, -297, 811,
322, -667, 673, -336, 141, 711, -747, -132, 547, 644, -338, -243, -963, -141, -277, 741, 529, -222, -684,
35] # to avoid var shadowing
def solve(A, B):
m, ln = None, len(A)
for i in range(B):
r = -(B-i-1) # r is right index to slice
tmp = sum(A[0:i + 1]) + sum(A[r:]) if r < 0 else 0
m = tmp if m is None else max(m, tmp)
return m
print(solve(Data, 48)) # 6253

A recursive approach with comments.
def solve(A, B, start_i=0, end_i=None):
# set end_i to the index of last element
if end_i is None:
end_i = len(A) - 1
# base case 1: we have no more moves
if B == 0:
return 0
# base case 2: array only has two elemens
if end_i - start_i == 1:
return max(A)
# next, we need to choose whether to use one of our moves on
# the left side of the array or the right side. We compute both,
# then check which one is better.
# pick the left side to sum
sum_left = A[start_i] + solve(A, B - 1, start_i + 1, end_i)
# pick the right side to sum
sum_right = A[end_i] + solve(A, B - 1, start_i, end_i - 1)
# return the max of both options
return max(sum_left, sum_right)
arr = [5, -2, 3, 1, 2]
print(solve(arr, 3)) # prints 8

The idea is if we have this list:
[5, 1, 1, 8, 2, 10, -2]
Then the possible numbers for B=3 would be:
lhs = [5, 1, 1] # namely L[+0], L[+1], L[+2]
rhs = [2, 10, -2] # namely R[-3], R[-2], R[-1]
The possible combinations would be:
[5, 1, 1] # L[+0], L[+1], L[+2]
[5, 1, -2] # L[+0], L[+1], R[-1]
[5, 10, -2] # L[+0], R[-2], R[-1]
[2, 10, -2] # R[-3], R[-2], R[-1]
As you can see, we can easily perform forward and backward iterations which will start from all L (L[+0], L[+1], L[+2]), and then iteratively replacing the last element with an R (R[-1], then R[-2], then R[-3]) up until all are R (R[-3], then R[-2], then R[-1]).
def solve(A, B):
n = len(A)
max_sum = None
for lhs, rhs in zip(range(B, -1, -1), range(0, -(B+1), -1)):
combined = A[0:lhs] + (A[rhs:] if rhs < 0 else [])
combined_sum = sum(combined)
max_sum = combined_sum if max_sum is None else max(max_sum, combined_sum)
return max_sum
for A in [
[5, 1, 1, 8, 2, 10, -2],
[5, 6, 1, 8, 2, 10, -2],
[5, 6, 3, 8, 2, 10, -2],
]:
print(A)
print("\t1 =", solve(A, 1))
print("\t2 =", solve(A, 2))
print("\t3 =", solve(A, 3))
print("\t4 =", solve(A, 4))
Output
[5, 1, 1, 8, 2, 10, -2]
1 = 5
2 = 8
3 = 13
4 = 18
[5, 6, 1, 8, 2, 10, -2]
1 = 5
2 = 11
3 = 13
4 = 20
[5, 6, 3, 8, 2, 10, -2]
1 = 5
2 = 11
3 = 14
4 = 22

public int solve(int[] A, int B) {
int sum = 0;
int i = 0;
int n = A.length -1;
for (int k = 0; k < B; k++){
sum += A[k];
}
int ans = sum;
int B2 = B -1;
for (int j = n; j > n -B; j--){
sum -= A[B2];
sum += A[j];
ans = Math.max(ans, sum);
B2--;
}
return ans;
}
}

Related

Trying to code bi-Directional Fibonacci Sequence i.e. even negative numbers

With suggestions, trail and errors; i have iterated the code. However, i still have query:
Current Result : [1, -1, 2, -3, 5, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
Expected & Accurate Result: [5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
value has correct sequence. each value corresponds to the range value.
However, - value are reversed. (-1) position has 5 & (-5) position has 1. How do i solve it?
Also, if i try bi_fibonacci(5,10):
Ans: [0, 1, 1, 2, 3, 5] - it consider len of the range. irrespective of values.
I would like it to show: [8, 13, 21, 34, 55] - The actual answer.
How do i solve it?
Thanks in advance.
def bi_fibonacci(num1, num2):
a = 1
b = -1
for item in range(num1, num2+1):
if item < 0:
yield a
temp = a
a = b
b = temp - b
a = 0
b = 1
for item in range(num1,num2+1):
if item > -1:
yield a
temp = a
a = b
b = temp + b
fibo_seq = [x for x in bi_fibonacci(-8,8)]
print(fibo_seq)
print(len(fibo_seq))
First, I believe you need a stack for the negative fibonacci sequence. Either an explicit stack (e.g. a list) or an implicit one (i.e. recursion.) Second, you need to do careful bookkeeping on this problem. Consider these three cases:
sequence = bi_fibonacci(-10, -5)
sequence = bi_fibonacci(-10, 10)
sequence = bi_fibonacci(5, 10)
You want to handle all three correctly but without making any of them a special case. Below is my solution using an explicit stack
# ..., −8, 5, −3, 2, −1, 1, 0, 1, 1, 2, 3, 5, 8, ...
def bi_fibonacci(num1, num2):
n = -1
a = 1
b = 0
stack = []
while n >= num1:
if n <= num2:
stack.append(a)
a, b = b - a, a
n -= 1
if stack:
yield from reversed(stack)
n = 0
a = 0
b = 1
while n <= num2:
if n >= num1:
yield a
a, b = b, a + b
n += 1
sequence = bi_fibonacci(-10, -5)
print(*sequence, sep=', ')
sequence = bi_fibonacci(-10, 10)
print(*sequence, sep=', ')
sequence = bi_fibonacci(5, 10)
print(*sequence, sep=', ')
OUTPUT
> python3 test.py
-55, 34, -21, 13, -8, 5
-55, 34, -21, 13, -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
5, 8, 13, 21, 34, 55
>

Count Overlap Between Neighboring Indices in NumPy Array

I have a NumPy array of integers:
x = np.array([1, 0, 2, 1, 4, 1, 4, 1, 0, 1, 4, 3, 0, 1, 0, 2, 1, 4, 3, 1, 4, 1, 0])
and another array of indices that references the array above:
indices = np.array([22, 12, 8, 1, 14, 21, 7, 0, 13, 19, 5, 3, 9, 16, 2, 15, 11, 18, 20, 6, 4, 10, 17])
For every pair of neighboring indices, we need to count how many consecutive values in x are overlapping starting at each of the two neighboring indices. For example, for indices[2] and indices[3], we have index 8 and 1, respectively, and they both reference positions in x. Then, starting at x[8] and x[1], we count how many consecutive values are the same or are overlapping but we stop checking the overlap under specific conditions (see below). In other words, we check if:
x[8] == x[1]
x[9] == x[2] # increment each index by one
... # continue incrementing each index except in the following conditions
stop if i >= x.shape[0]
stop if j >= x.shape[0]
6. stop if x[i] == 0
7. stop if x[j] == 0
stop if x[i] != x[j]
In reality, we do this for all neighboring index pairs:
out = np.zeros(indices.shape[0], dtype=int)
for idx in range(indices.shape[0]-1):
count = 0
i = indices[idx]
j = indices[idx + 1]
k = 0
# while i+k < x.shape[0] and j+k < x.shape[0] and x[i+k] != 0 and x[j+k] != 0 and x[i+k] == x[j+k]:
while i+k < x.shape[0] and j+k < x.shape[0] and x[i+k] == x[j+k]:
count += 1
k += 1
out[idx] = k
And the output is:
# [0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 2, 3, 0, 3, 0, 1, 0, 2, 2, 1, 2, 0] # This is the old output if x[i] == 0 and x[j] == 0 are included
[1 2 1 4 0 2 2 5 1 4 3 2 3 0 3 0 1 0 3 2 1 2 0]
I'm looking for a vectorized way to do this in NumPy.
This should do the trick (I am ignoring the two conditions x[i]=0 and x[j]=0)
for idx in range(indices.shape[0]-1):
i = indices[idx]
j = indices[idx + 1]
l = len(x) - max(i,j)
x1 = x[i:i+l]
x2 = x[j:j+l]
# Add False at the end to handle the case in which arrays are exactly the same
x0 = np.append(x1==x2, False)
out[idx] = np.argmin(x0)
Notice that with np.argmin I am exploiting the following two facts:
False < True
np.argmin only returns the first instance of the min in the array
Performance Analysis
Regarding time performance, I tested with N=10**5 and N=10**6, and as suggested in the comments, this cannot compete with numba jit.
def f(x, indices):
out = np.zeros(indices.shape[0], dtype=int)
for idx in range(indices.shape[0]-1):
i = indices[idx]
j = indices[idx + 1]
l = len(x) - max(i,j)
x1 = x[i:i+l]
x2 = x[j:j+l]
x0 = np.append(x1==x2, False)
out[idx] = np.argmin(x0)
return out
N=100_000
x = np.random.randint(0,10, N)
indices = np.arange(0, N)
np.random.shuffle(indices)
%timeit f(x, indices)
3.67 s ± 122 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
N=1_000_000
x = np.random.randint(0,10, N)
indices = np.arange(0, N)
np.random.shuffle(indices)
%time f(x, indices)
Wall time: 8min 20s
(I did not have the patience to let %timeit finish)

i need help getting stDev without using importmath, python

### import math
def mean(values):
return sum(values)*1.0/len(values)
def std():
pass
print(std())
def std(values):
length = len(values)
if length < 2:
return("Standard deviation requires at least two data points")
m = mean(values)
total_sum = 0
for i in range(length):
total_sum += (values[i]-m)**2
under_root = total_sum*1.0/length
return math.sqrt(under_root)
vals = [5]
stan_dev = std(vals)
print(stan_dev)
values = [1, 2, 3, 4, 5]
stan_dev = std(values)
print(stan_dev)
__________________________________________________________________________
lst = [3, 19, 21, 1435, 653342]
sum = reduce((lambda x, y: x +y), lst)
print (sum)
# list = [3, 19, 21, 1435, 653342]
i need to be able to get the stDev without using sum or len
i need to 'unpack' the stDev ???
You can do it with two loops (there are shorter ways but this is simple):
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Calculate the mean first
N, X = 0, 0
for xi in arr:
N += 1
X += xi
mean = X/N
# Calculate the standard deviation
DSS = 0
for xi in arr:
DSS += (xi - mean)**2
std = (DSS/N)**(1/2)
Outputs 4.5 for mean and 2.872 for std.

Python Recursion in pascal's triangle [duplicate]

As a learning experience for Python, I am trying to code my own version of Pascal's triangle. It took me a few hours (as I am just starting), but I came out with this code:
pascals_triangle = []
def blank_list_gen(x):
while len(pascals_triangle) < x:
pascals_triangle.append([0])
def pascals_tri_gen(rows):
blank_list_gen(rows)
for element in range(rows):
count = 1
while count < rows - element:
pascals_triangle[count + element].append(0)
count += 1
for row in pascals_triangle:
row.insert(0, 1)
row.append(1)
pascals_triangle.insert(0, [1, 1])
pascals_triangle.insert(0, [1])
pascals_tri_gen(6)
for row in pascals_triangle:
print(row)
which returns
[1]
[1, 1]
[1, 0, 1]
[1, 0, 0, 1]
[1, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
However, I have no idea where to go from here. I have been banging my head against the wall for hours. I want to emphasize that I do NOT want you to do it for me; just push me in the right direction. As a list, my code returns
[[1], [1, 1], [1, 0, 1], [1, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1]]
Thanks.
EDIT: I took some good advice, and I completely rewrote my code, but I am now running into another problem. Here is my code.
import math
pascals_tri_formula = []
def combination(n, r):
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))
def for_test(x, y):
for y in range(x):
return combination(x, y)
def pascals_triangle(rows):
count = 0
while count <= rows:
for element in range(count + 1):
[pascals_tri_formula.append(combination(count, element))]
count += 1
pascals_triangle(3)
print(pascals_tri_formula)
However, I am finding that the output is a bit undesirable:
[1, 1, 1, 1, 2, 1, 1, 3, 3, 1]
How can I fix this?
OK code review:
import math
# pascals_tri_formula = [] # don't collect in a global variable.
def combination(n, r): # correct calculation of combinations, n choose k
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))
def for_test(x, y): # don't see where this is being used...
for y in range(x):
return combination(x, y)
def pascals_triangle(rows):
result = [] # need something to collect our results in
# count = 0 # avoidable! better to use a for loop,
# while count <= rows: # can avoid initializing and incrementing
for count in range(rows): # start at 0, up to but not including rows number.
# this is really where you went wrong:
row = [] # need a row element to collect the row in
for element in range(count + 1):
# putting this in a list doesn't do anything.
# [pascals_tri_formula.append(combination(count, element))]
row.append(combination(count, element))
result.append(row)
# count += 1 # avoidable
return result
# now we can print a result:
for row in pascals_triangle(3):
print(row)
prints:
[1]
[1, 1]
[1, 2, 1]
Explanation of Pascal's triangle:
This is the formula for "n choose k" (i.e. how many different ways (disregarding order), from an ordered list of n items, can we choose k items):
from math import factorial
def combination(n, k):
"""n choose k, returns int"""
return int((factorial(n)) / ((factorial(k)) * factorial(n - k)))
A commenter asked if this is related to itertools.combinations - indeed it is. "n choose k" can be calculated by taking the length of a list of elements from combinations:
from itertools import combinations
def pascals_triangle_cell(n, k):
"""n choose k, returns int"""
result = len(list(combinations(range(n), k)))
# our result is equal to that returned by the other combination calculation:
assert result == combination(n, k)
return result
Let's see this demonstrated:
from pprint import pprint
ptc = pascals_triangle_cell
>>> pprint([[ptc(0, 0),],
[ptc(1, 0), ptc(1, 1)],
[ptc(2, 0), ptc(2, 1), ptc(2, 2)],
[ptc(3, 0), ptc(3, 1), ptc(3, 2), ptc(3, 3)],
[ptc(4, 0), ptc(4, 1), ptc(4, 2), ptc(4, 3), ptc(4, 4)]],
width = 20)
[[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1]]
We can avoid repeating ourselves with a nested list comprehension:
def pascals_triangle(rows):
return [[ptc(row, k) for k in range(row + 1)] for row in range(rows)]
>>> pprint(pascals_triangle(15))
[[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
[1, 5, 10, 10, 5, 1],
[1, 6, 15, 20, 15, 6, 1],
[1, 7, 21, 35, 35, 21, 7, 1],
[1, 8, 28, 56, 70, 56, 28, 8, 1],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1],
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1],
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1],
[1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1],
[1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1],
[1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
Recursively defined:
We can define this recursively (a less efficient, but perhaps more mathematically elegant definition) using the relationships illustrated by the triangle:
def choose(n, k): # note no dependencies on any of the prior code
if k in (0, n):
return 1
return choose(n-1, k-1) + choose(n-1, k)
And for fun, you can see each row take progressively longer to execute, because each row has to recompute nearly each element from the prior row twice each time:
for row in range(40):
for k in range(row + 1):
# flush is a Python 3 only argument, you can leave it out,
# but it lets us see each element print as it finishes calculating
print(choose(row, k), end=' ', flush=True)
print()
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1
1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1
1 18 153 816 3060 8568 18564 31824 43758 48620 43758 31824 18564 8568 3060 816 ...
Ctrl-C to quit when you get tired of watching it, it gets very slow very fast...
I know you want to implement yourself, but the best way for me to explain is to walk through an implementation. Here's how I would do it, and this implementation relies on my fairly complete knowledge of how Python's functions work, so you probably won't want to use this code yourself, but it may get you pointed in the right direction.
def pascals_triangle(n_rows):
results = [] # a container to collect the rows
for _ in range(n_rows):
row = [1] # a starter 1 in the row
if results: # then we're in the second row or beyond
last_row = results[-1] # reference the previous row
# this is the complicated part, it relies on the fact that zip
# stops at the shortest iterable, so for the second row, we have
# nothing in this list comprension, but the third row sums 1 and 1
# and the fourth row sums in pairs. It's a sliding window.
row.extend([sum(pair) for pair in zip(last_row, last_row[1:])])
# finally append the final 1 to the outside
row.append(1)
results.append(row) # add the row to the results.
return results
usage:
>>> for i in pascals_triangle(6):
... print(i)
...
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
Without using zip, but using generator:
def gen(n,r=[]):
for x in range(n):
l = len(r)
r = [1 if i == 0 or i == l else r[i-1]+r[i] for i in range(l+1)]
yield r
example:
print(list(gen(15)))
output:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1], [1, 7, 21, 35, 35, 21, 7, 1], [1, 8, 28, 56, 70, 56, 28, 8, 1], [1, 9, 36, 84, 126, 126, 84, 36, 9, 1], [1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1], [1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1], [1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1], [1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1], [1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
DISPLAY AS TRIANGLE
To draw it in beautiful triangle(works only for n < 7, beyond that it gets distroted. ref draw_beautiful for n>7)
for n < 7
def draw(n):
for p in gen(n):
print(' '.join(map(str,p)).center(n*2)+'\n')
eg:
draw(10)
output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
for any size
since we need to know the max width, we can't make use of generator
def draw_beautiful(n):
ps = list(gen(n))
max = len(' '.join(map(str,ps[-1])))
for p in ps:
print(' '.join(map(str,p)).center(max)+'\n')
example (2) :
works for any number:
draw_beautiful(100)
Here is my attempt:
def generate_pascal_triangle(rows):
if rows == 1: return [[1]]
triangle = [[1], [1, 1]] # pre-populate with the first two rows
row = [1, 1] # Starts with the second row and calculate the next
for i in range(2, rows):
row = [1] + [sum(column) for column in zip(row[1:], row)] + [1]
triangle.append(row)
return triangle
for row in generate_pascal_triangle(6):
print row
Discussion
The first two rows of the triangle is hard-coded
The zip() call basically pairs two adjacent numbers together
We still have to add 1 to the beginning and another 1 to the end because the zip() call only generates the middle of the next row
# combining the insights from Aaron Hall and Hai Vu,
# we get:
def pastri(n):
rows = [[1]]
for _ in range(1, n+1):
rows.append([1] +
[sum(pair) for pair in zip(rows[-1], rows[-1][1:])] +
[1])
return rows
# thanks! learnt that "shape shifting" data,
# can yield/generate elegant solutions.
def pascal(n):
if n==0:
return [1]
else:
N = pascal(n-1)
return [1] + [N[i] + N[i+1] for i in range(n-1)] + [1]
def pascal_triangle(n):
for i in range(n):
print pascal(i)
Beginner Python student here. Here's my attempt at it, a very literal approach, using two For loops:
pascal = [[1]]
num = int(input("Number of iterations: "))
print(pascal[0]) # the very first row
for i in range(1,num+1):
pascal.append([1]) # start off with 1
for j in range(len(pascal[i-1])-1):
# the number of times we need to run this loop is (# of elements in the row above)-1
pascal[i].append(pascal[i-1][j]+pascal[i-1][j+1])
# add two adjacent numbers of the row above together
pascal[i].append(1) # and cap it with 1
print(pascal[i])
Here is an elegant and efficient recursive solution. I'm using the very handy toolz library.
from toolz import memoize, sliding_window
#memoize
def pascals_triangle(n):
"""Returns the n'th row of Pascal's triangle."""
if n == 0:
return [1]
prev_row = pascals_triangle(n-1)
return [1, *map(sum, sliding_window(2, prev_row)), 1]
pascals_triangle(300) takes about 15 ms on a macbook pro (2.9 GHz Intel Core i5). Note that you can't go much higher without increasing the default recursion depth limit.
I am cheating from the popular fibonacci sequence solution. To me, the implementation of Pascal's triangle would have the same concept of fibonacci's. In fibonacci we use a single number at a time and add it up to the previous one. In pascal's triangle use a row at a time and add it up to the previous one.
Here is a complete code example:
>>> def pascal(n):
... r1, r2 = [1], [1, 1]
... degree = 1
... while degree <= n:
... print(r1)
... r1, r2 = r2, [1] + [sum(pair) for pair in zip(r2, r2[1:]) ] + [1]
... degree += 1
Test
>>> pascal(3)
[1]
[1, 1]
[1, 2, 1]
>>> pascal(4)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
>>> pascal(6)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
Note: to have the result as a generator, change print(r1) to yield r1.
# call the function ! Indent properly , everything should be inside the function
def triangle():
matrix=[[0 for i in range(0,20)]for e in range(0,10)] # This method assigns 0's to all Rows and Columns , the range is mentioned
div=20/2 # it give us the most middle columns
matrix[0][div]=1 # assigning 1 to the middle of first row
for i in range(1,len(matrix)-1): # it goes column by column
for j in range(1,20-1): # this loop goes row by row
matrix[i][j]=matrix[i-1][j-1]+matrix[i-1][j+1] # this is the formula , first element of the matrix gets , addition of i index (which is 0 at first ) with third value on the the related row
# replacing 0s with spaces :)
for i in range(0,len(matrix)):
for j in range(0,20):
if matrix[i][j]==0: # Replacing 0's with spaces
matrix[i][j]=" "
for i in range(0,len(matrix)-1): # using spaces , the triangle will printed beautifully
for j in range(0,20):
print 1*" ",matrix[i][j],1*" ", # giving some spaces in two sides of the printing numbers
triangle() # calling the function
would print something like this
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
Here is a simple way of implementing the pascal triangle:
def pascal_triangle(n):
myList = []
trow = [1]
y = [0]
for x in range(max(n,0)):
myList.append(trow)
trow=[l+r for l,r in zip(trow+y, y+trow)]
for item in myList:
print(item)
pascal_triangle(5)
Python zip() function returns the zip object, which is the iterator of tuples where the first item in each passed iterator is paired together, and then the second item in each passed iterator are paired together. Python zip is the container that holds real data inside.
Python zip() function takes iterables (can be zero or more), makes an iterator that aggregates items based on the iterables passed, and returns the iterator of tuples.
I did this when i was working with my son on intro python piece. It started off as rather simple piece, when we targeted -
1
1 2
1 2 3
1 2 3 4
However, as soon as we hit the actual algorithm, complexity overshot our expectations. Anyway, we did build this -
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
Used some recursion -
def genRow(row:list) :
# print(f"generatig new row below {row}")
# printRow(row)
l = len(row) #2
newRow : list = []
i = 0
# go through the incoming list
while i <= l:
# print(f"working with i = {i}")
# append an element in the new list
newRow.append(1)
# set first element of the new row to 1
if i ==0:
newRow[i] = 1
# print(f"1:: newRow = {newRow}")
# if the element is in the middle somewhere, add the surroundng two elements in
# previous row to get the new element
# e.g. row 3[2] = row2[1] + row2[2]
elif i <= l-1:
# print(f"2:: newRow = {newRow}")
newRow[i] = row[i-1] + row[i]
else:
# print(f"3 :: newRow = {newRow}")
newRow[i] = 1
i+=1
# print(newRow)
return newRow
def printRow(mx : int, row:list):
n = len(row)
spaces = ' ' *((mx - n)*2)
print(spaces,end=' ')
for i in row:
print(str(i) + ' ',end = ' ')
print(' ')
r = [1,1]
mx = 7
printRow(mx,[1])
printRow(mx,r)
for a in range(1,mx-1):
# print(f"working for Row = {a}")
if len(r) <= 2:
a1 = genRow(r)
r=a1
else:
a2 = genRow(a1)
a1 = a2
printRow(mx,a1)
Hopefully it helps.

Quicksort implement in Python run with none stop

This is my quicksort algorithms. Very simple
x = 0
def swap(list, a, b):
temp = list[a]
list[a] = list[b]
list[b] = temp
return list
def quicksort2(list, left, right):
if right > left:
global x
x = x + 1
print x , list, left, right
l = left+1
r = right
while l <= r :
while list[l] < list[left]:
l = l + 1
while list[r] > list[left]:
r = r - 1
if l < r:
list = swap(list, l, r)
list = swap(list, left, r)
list = quicksort2(list, left, r-1);
return quicksort2(list, r+1, right);
return list
But when i run my testcase
b = list([1, 2, 2, 3, 4, 5, 6, 12, 6, 32])
quicksort2(b, 0, len(b)-1)
the result is
1 [1, 2, 2, 3, 4, 5, 6, 12, 6, 32] 0 9
2 [1, 2, 2, 3, 4, 5, 6, 12, 6, 32] 1 9
and stop at this...
Anybody have any reason ...
Have you tried to trace the program execution under a debugger...?
The while l <= r loop runs forever, because after several decrements of r
left == 1
l == 2
r == 2
and
l is not incremented, because list[2] is not less than list[1]
r is not decremented any longer, because list[2] is not greater than list[1]
no swap is done, because l is not less than r
and loop will continue, because l is still equal to r.......
I simply modified your code a bit.. Found several mistakes, some already mentioned by others. The rest I am not going to go through.
However, you do not have to return a modified list, as lists in python are always passed by reference.
This should be working:
def quicksort2(list, low, high):
global x
x = x + 1
print x , list, low, high
l = low
r = high
mid = list[(r + l) / 2]
while l <= r:
while list[l] < mid: l += 1
while list[r] > mid: r -= 1
if l <= r:
list[l], list[r] = list[r], list[l] #swap(r,l)
l += 1
r -= 1
if r > low: quicksort2(list, low, r);
if l < high: quicksort2(list, l, high);
if __name__ == '__main__':
x = 0
b = [1, 2, 2, 3, 4, 5, 6, 12, 6, 32]
quicksort2(b, 0, len(b)-1)
print b

Categories

Resources