I followed the algorithm in the book for this problem. when I print result it is not correct. the algorithm is exactly as in the book
my code
import math
def quickSelect(A, k):
m = A[math.floor(len(A)/2)]
L = [i for i in A if i < m]
E = [i for i in A if i == m]
G = [i for i in A if i > m]
print(L)
print(E)
print(G)
if k <= len(L):
return quickSelect(L, k)
elif k <= (len(E) + len(G)):
return m
else:
return quickSelect(G, k- len(L) - len(E))
result = quickSelect([7, 14, 10, 12, 2, 11, 29, 3, 4], 4)
print(result)
These statements:
L = [i for i in A if i < m] # less than m
E = [i for i in A if i == m] # equal to m
G = [i for i in A if i > m] # greater than m
partition the array into three ranges:
| L1 L2 L3 L4 | E1 | G1 G2 G3
| | |
0 | |
len(L) |
len(L) + len(E)
Your condition for the second range,
elif k <= (len(L) + len(G)):
return m
is wrong. It should be:
elif k <= (len(L) + len(E)):
return m
Node: Instead of using floating-point math, you can just calculate m with Python's integer division: m = A[len(A) // 2]
Related
This is a codewars problem. The idea is given that arr = [x(1), x(2), x(3), x(4), ..., x(i), x(i+1), ..., x(m), x(m+1)] where all x(i) are positive integers. (the length (len(arr)) of this array will be a positive multiple of 4)
And let P = (x(1) ** 2 + x(2) ** 2) * (x(3) ** 2 + x(4) ** 2) * ... * (x(m) ** 2 + x(m+1) ** 2)
Find A and B such that A**2 + B**2 == P
If only one solution is found, it is already valid.
I solved, but the efficiency is low. Initially I wrote this:
[Original Method]
from math import sqrt, ceil
def solve(arr):
if len(arr) % 2 != 0: return []
n = len(arr)
P = 1
i = 0
while i < n:
P *= (arr[i]**2 + arr[i + 1]**2)
i += 2
m = ceil(sqrt(P))
for A in range(1, m):
B = sqrt(P - A**2)
if B == int(B):
return [A, int(B)]
return []
To improve the performance I tried to use the Cauchy inequality.
[Improvement but Failing]
from math import sqrt, ceil
def solve(arr):
if len(arr) % 4 != 0: return []
n = len(arr)
P = 1
for i in range(0, n, 2):
P *= (arr[i]**2 + arr[i + 1]**2)
C = 1
D = 1
for i in range(0, n, 4):
C *= (arr[i]**2 + arr[i + 1]**2) * (arr[i + 2]**2 + arr[i + 3]**2)
D *= (arr[i] * arr[i + 2] + arr[i + 1] * arr[i + 3])**2
A = int(sqrt(D))
B = int(sqrt(P - A**2))
if A ** 2 + B ** 2 == P:
return [A, B]
return []
But the code above starts having problems for high numbers. For example: arr = [3, 9, 8, 4, 6, 8, 7, 8, 4, 8, 5, 6, 6, 4, 4, 5] should result in A = 13243200 and B = 25905600, but my result is that not has A and B for this case.
I need help to improve my performance. I don't know if using the Cauchy inequality solves it, but if you have another idea it's already valid.
I have a list of n numbers. I want to divide the list into sub lists, such as the sub list consists of continuous increasing numbers or continuous decreasing numbers. Then take the product of each sub list's min value and it's length. Finally take the sum of all this product's
Input:
l = [1,2,6,4,2,3,1,8,9,7]
Output:
32
Details:
[1,2,6],[6,4,2],[2,3],[3,1],[1,8,9],[9,7]
(1*3) +(2*3) + (2*2)+(1*2)+(1*3)+ (7*2) = 32
Code so far:
n = 10
l = [1,2,6,4,2,3,1,8,9,7]
tot = 0
count = 0
inc=dec=False
min_val = 1001 # max value in list won't exceed 1000
for idx, e in enumerate(l):
if idx+1<=n:
if e > l[idx+1]:
count+=1
if min_val > l[idx+1]:
min_val=l[idx+1]
inc=True
dec=False
elif e < l[idx+1]:
count+=1
if min_val > e:
min_val=e
dec=True
# if not inc
inc=False
*Note: No Two adjacent value will be equal in the list.
Update-1:
itemp = [1001]
dtemp = [1001]
result=0
for e in l:
# if not itemp or not dtemp:
# itemp.append(e)
# dtemp.append(e)
if e > itemp[-1]:
if not dtemp:
itemp.append(e)
else:
result+=(min(dtemp)*(len(dtemp)-1))
dtemp=[1001]
itemp.append(e)
elif e < dtemp[-1]:
dtemp.append(e)
if not itemp:
dtemp.append(e)
else:
result+=(min(itemp)*(len(itemp)-1))
itemp=[1001]
dtemp.append(e)
print(result)
This results 0 as output. Can some one help?
l = [1,2,6,4,2,3,1,8,9,7]
local_max= [i for i in range(1, len(l)-1) if l[i-1]<l[i]>l[i+1]]
local_min= [i for i in range(1, len(l)-1) if l[i-1]>l[i]<l[i+1]]
idx= sorted(local_max+local_min +[0,len(l)-1])
idx_pairs = zip(idx[:-1],idx[1:])
sum(min(l[i_1],l[i_2])*(i_2+1-i_1) for i_1,i_2 in idx_pairs)
You could identify the breaking positions (peaks and bottoms) using zip to detect changes of increasing/decreasing values between each sequence of 3 elements. Then use these breaks to form the sub-lists and apply the calculation in a comprehension.
L = [1,2,6,4,2,3,1,8,9,7]
breaks = [i+1 for i,(a,b,c) in enumerate(zip(L,L[1:],L[2:])) if (a<b)==(b>c)]
subL = [ L[s:e+1] for s,e in zip([0]+breaks,breaks+[len(L)]) ]
result = sum(min(s)*len(s) for s in subL)
print(breaks) # [2, 4, 5, 6, 8] indices of peaks and bottoms
# [1,2,6,4,2,3,1,8,9,7]
# ^ ^ ^ ^ ^
# 0 1 2 3 4 5 6 7 8 9
print(subL) # [ [1, 2, 6], [6, 4, 2], [2, 3], [3, 1], [1, 8, 9], [9, 7]]
# 0..2+1 2..4+1 4..5+1 5..6+1 6..8+1 8..len(L)
# | | | | | | | | | | | |
# [0] | + [2, | 4, | 5, | 6, | 8] |
# [2, 4, 5, 6, 8] + [len(L)]
print(result) # 32
tot = start = m = n = 0
direc = -1
for n, x in enumerate(lis):
if n == 0:
m = x
else:
old = lis[n - 1]
if (x > old and direc == 0) or (x < old and direc == 1):
tot += m * (n - start)
start = n - 1
m = min(old, x)
direc ^= 1
else:
direc = 1 if x > old else 0
m = min(m, x)
ln = n - start + 1
if ln > 1:
tot += m * ln
I want to factor a number and count the number of times each prime number is multiplied to get the desired one. For example 200=2*2*2*5*5 which would give me [[2,3],[5,2].
This is what I wrote:
def factor(N):
f = []
k = 2
c = 0
while k <= N:
if N % k == 0:
while N % k == 0:
b = N / k
N = b
c += 1
f.append([k, c])
else:
k += 1
return f
n = factor(200)
print(n)
output:
[[2, 3], [5, 5]]
expected output:
[[2, 3], [5, 2]] # come from 200 = 2x2x2x5x5
Move the counter on the first loop, like on the code below.
def factor(N):
f = []
k = 2
while k <= N:
c = 0
if N % k == 0:
while N % k == 0:
b = N/k
N = b
c += 1
f.append([k, c])
else:
k += 1
return f
n = factor(200)
print(n)
You need to reset your count (c) after adding to the resulting array.
You should also stop the loop when your factor reaches the square root of the number (or the square of the factor is higher than the number):
Here's a generator version of the prime factor function that does not need to store the prime factors in memory:
def primeFactors(N):
prime = 2
while N >= prime * prime:
power = 0
while N % prime == 0:
power += 1
N //= prime
if power: yield (prime,power)
prime += 1 + (prime&1)
if N>1: yield (N,1)
print(*primeFactors(200)) # (2, 3) (25, 1)
print(*primeFactors(360324)) # (2, 2) (3, 2) (10009, 1)
print(*primeFactors(2485335125)) # (5, 3) (7, 6) (13, 2)
print(*primeFactors(882635521699397)) # (149, 2) (3413, 3)
print(*primeFactors(5196703574764221304787)) # (4733, 1) (101611, 1) (119923, 1) (90104863, 1)
print(*primeFactors(13059300506111507933977974861361)) # (17, 4) (5521, 7)
def factor(N):
f = []
k = 2
while k <= N:
c = 0
if N%k == 0:
while N%k == 0:
b = N/k
N = b
c += 1
f.append([k, c])
else:
k += 1
c = 0 **#You have to reset the counter here..**
return f
n = factor(200)
print(n)
Trying to create a double pivot with user inputs, through recursion, although the recursion can be left out, how would a person get the inputs/ints into the list and then let it sort according to the quicksort formula shown.
def swap(lst, i, j):
if min(i,j) >= 0 and max(i,j) < len(lst) and i != j:
lst[i], lst[j] = lst[j], lst[i]
def dpquicksort(lst, left=0, right=None):
if right is None:
right = len(lst) - 1
if right - left >= 1:
p = min(lst[left], lst[right])
q = max(lst[left], lst[right])
l = left + 1
g = right - 1
k = l
while k <= g:
if lst[k] < p:
swap(lst, k, l)
l += 1
elif lst[k] >= q:
while lst[g] > q and k < g:
g -= 1
swap(lst, k, g)
g -= 1
if lst[k] < p:
swap(lst, k, l)
l += 1
k += 1
l -= 1
g += 1
swap(lst, left, l)
swap(lst, right, g)
dpquicksort(lst, left, l-1)
dpquicksort(lst, l+1, g-1)
dpquicksort(lst, g+1, right)
return right
def quickSortHelper(alist, first, last):
if first<last:
splitpoint= partition(alist, first, last)
quickSortHelper(alist, first, splitpoint-1)
quickSortHelper(alist, splitpoint+1, last)
def quicksort(lst):
dpquicksort(lst, 0, len(lst)-1)
print(lst)
lst = [54,26,93,17,77,31,44,55,20]
#lst = int(input("enter integers: "))
quicksort(lst)
lst = [54,6,93,17,7,1,44,55,20]
#lst = [2, 4, 6, 8, 10, 12, 14, 16, 18]
quicksort(lst)
You can utilise map and int built-in,
>>> lst = list(map(int,input("enter integers: ").split()))
enter integers: 2 3 8 1 3 4 1 8 9 2
>>> lst
[2, 3, 8, 1, 3, 4, 1, 8, 9, 2]
Or list comprehension,
[int(num) for num in input("enter integers: ").split()]
It is up to you, put it top or bottom are both fine. Your code become,
def swap(lst, i, j):
if min(i,j) >= 0 and max(i,j) < len(lst) and i != j:
lst[i], lst[j] = lst[j], lst[i]
def dpquicksort(lst, left=0, right=None):
if right is None:
right = len(lst) - 1
if right - left >= 1:
p = min(lst[left], lst[right])
q = max(lst[left], lst[right])
l = left + 1
g = right - 1
k = l
while k <= g:
if lst[k] < p:
swap(lst, k, l)
l += 1
elif lst[k] >= q:
while lst[g] > q and k < g:
g -= 1
swap(lst, k, g)
g -= 1
if lst[k] < p:
swap(lst, k, l)
l += 1
k += 1
l -= 1
g += 1
swap(lst, left, l)
swap(lst, right, g)
dpquicksort(lst, left, l-1)
dpquicksort(lst, l+1, g-1)
dpquicksort(lst, g+1, right)
return right
def quickSortHelper(alist, first, last):
if first<last:
splitpoint= partition(alist, first, last)
quickSortHelper(alist, first, splitpoint-1)
quickSortHelper(alist, splitpoint+1, last)
def quicksort(lst):
dpquicksort(lst, 0, len(lst)-1)
print(lst)
lst = list(map(int,input("enter integers: ").split()))
quicksort(lst)
Is it possible to do magic squares with the Siamese/De La Loubere method without using modulo?
I would like to make odd n x n magic squares using it.
Yes, it's possible. Written on Python 3.5:
def siamese_method(n):
assert(n % 2 != 0), 'Square side size should be odd!'
square = [[0 for x in range(n)] for x in range(n)]
x = 0
y = int((n + 1) / 2 - 1)
square[x][y] = 1
for i in range(2, n * n + 1):
x_old = x
y_old = y
if x == 0:
x = n - 1
else:
x -= 1
if y == n - 1:
y = 0
else:
y += 1
while square[x][y] != 0:
if x == n - 1:
x = 0
else:
x = x_old + 1
y = y_old
square[x][y] = i
for j in square:
print(j)
siamese_method(3)
I've got following on output:
[8, 1, 6]
[3, 5, 7]
[4, 9, 2]