Max Points on a Line with python 3 - python-3.x

algorithm question:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
the working python 3 code is below:
wondering
snippet 1 d[slope] = d.get(slope, 1) + 1 is working
but why this snippet 2 is not working correctly for example 2 even though snippet 1 and 2 are the same
if slope in d:
d[slope] += 1
else:
d[slope] = 1
def gcd(self, a, b):
if b == 0:
return a
return self.gcd(b, a%b)
def get_slope(self, p1, p2):
dx = p1[0] - p2[0]
dy = p1[1] - p2[1]
c = self.gcd(dx, dy)
dx /= c
dy /= c
return str(dy) + "/" + str(dx)
def is_same_points(self, p1:List[int], p2:List[int]):
return p1[0] == p2[0] and p1[1] == p2[1]
def maxPoints(self, points: List[List[int]]) -> int:
if not points:
return 0
n = len(points)
count = 1
for i in range(0, n):
d = {}
duped = 0
localmax = 1
p1 = points[i]
for j in range(i+1, n):
p2 = points[j]
if self.is_same_points(p1, p2):
duped += 1
else:
slope = self.get_slope(p1, p2)
# 1) not work: output is 3 in example 2
# if slope in d:
# d[slope] += 1
# else:
# d[slope] = 1
# 2) works: correct output 4 for example 2
d[slope] = d.get(slope, 1) + 1
localmax = max(localmax, d[slope]);
count = max(count, localmax + duped)
return count

Interesting problem and nice solution.
The reason why the commented out code doesn't work is because of that:
else:
d[slope] = 1 ## correct would be d[slope] = 2
Every 2 points are on the same line, you are counting only one point for the first two p1 p2, thus you get one less in the final answer.

Related

Python(AI Constraint satisfaction problem) Fitting square and/or rectangular (2d) tiles onto a rectangular ground

I have to arrange and/or fit 2d tiles into a 2d square or rectangular plane with AI algorithm using python program. Each tile has a length and width. For example if a plane is 4x3 and set of tiles is
S={(2,3),(1,2),(2,2)}
these tiles can be rotated 90 degrees in order to fit the matrix.
input
first line contains length and width of the plane
second line number of tiles
and then the length,width of the subsequent tiles
but the inputs should be tab seperated
for eg
4 3
3
2 3
1 2
2 2
output
for eg
1 1 2 2
1 1 3 3
1 1 3 3
I have trouble solving this as i have to use only standard libraries in python no NumPy and no CSP library
~Edit 2`
my code so far I cant figure out how to add algorithm without csp library or to generate grid
from sys import stdin
a = stdin.readline()
x = a.split()
rectangular_plane = [[0] * int(x[0]) for i in range(int(x[1]))]
num_of_rectangles = stdin.readline()
r_widths = []
r_lengths= []
for l in range(int(num_of_rectangles)):
b = stdin.readline()
y = b.split()
r_lengths.insert(l,y[0])
r_widths.insert(l,y[1])
I've solved task with backtracking approach and without any non-standard modules.
Try it online!
import sys
nums = list(map(int, sys.stdin.read().split()))
pw, ph = nums[0:2]
ts = list(zip(nums[3::2], nums[4::2]))
assert len(ts) == nums[2]
if sum([e[0] * e[1] for e in ts]) != pw * ph:
print('Not possible!')
else:
def Solve(*, it = 0, p = None):
if p is None:
p = [[0] * pw for i in range(ph)]
if it >= len(ts):
for e0 in p:
for e1 in e0:
print(e1, end = ' ')
print()
return True
for tw, th in [(ts[it][0], ts[it][1]), (ts[it][1], ts[it][0])]:
zw = [0] * tw
ow = [it + 1] * tw
for i in range(ph - th + 1):
for j in range(pw - tw + 1):
if all(p[k][j : j + tw] == zw for k in range(i, i + th)):
for k in range(i, i + th):
p[k][j : j + tw] = ow
if Solve(it = it + 1, p = p):
return True
for k in range(i, i + th):
p[k][j : j + tw] = zw
return False
if not Solve():
print('Not possible!')
Example input:
4 3
3
2 3
1 2
2 2
Output:
1 1 2 2
1 1 3 3
1 1 3 3

Why doesn't assigning new values to a numpy array work?

I have the following code. The beggining is quite long, but only serves to generate data. The problem happens with a few lines at the end.
##### Import packages
import numpy as np
import scipy.linalg as la
##### Initial conditions
N = 5
lamda = 7
mu = 2
a = 0.5
r = - np.log(a).copy()
St_Sp = np.arange(- N, N + 1)
Card = St_Sp.shape[0]
##### Define infintesimal generator
def LL(x, y):
if x == N or x == - N: re = 0
elif x - y == - 1: re = lamda
elif x - y == 1: re = mu
elif x - y == 0: re = - (mu + lamda)
else: re = 0
return re
def L(x):
return - LL(x, x)
##### Define function Phi
def Phi(x): return max(x, 0)
Phi = np.vectorize(Phi)
##### Define vector b
b = Phi(St_Sp).copy()
##### Define function Psi
def Psi(x): return L(x) / (L(x) + r)
Psi = np.vectorize(Psi)
##### Generate a Boolean vector whose all elements are False
d = np.array([0] * Card).astype(bool)
##### Define matrix A
A = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if (i != j) & (L(St_Sp[i]) != 0):
A[i, j] = LL(St_Sp[i], St_Sp[j]) / L(St_Sp[i])
elif (i != j) & (L(St_Sp[i]) == 0):
A[i, j] = 0
elif (i == j) & (Psi(St_Sp[i]) != 0):
A[i, j] = - 1 / Psi(St_Sp[i])
else: A[i, j] = 1
##### Row names of A
rows = np.arange(0, Card)
##### Define matrix B
B = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if i != j:
B[i, j] = LL(St_Sp[i], St_Sp[j])
else: B[i, j] = LL(St_Sp[i], St_Sp[j]) - r
##### Generate I_0
I = [np.array([1] * Card).astype(bool), d.copy()]
Z = b.copy()
index0 = np.matmul(B, Z) <= 0
index1 = ~ index0
##### Generate I_1
I = [index0, index1]
Z = b.copy()
if np.sum(I[1]) > 0:
order = np.concatenate((rows[I[1]], rows[~ I[1]]))
A1 = A[np.ix_(rows[I[1]], order)]
A2 = la.lu(A1)[2]
p = np.atleast_2d(A1).shape[0]
B1 = A2[:, range(p)]
B2 = - np.matmul(A2[:, p:], Z[I[0]])
print('Before being assigned new values, Z is \n', Z)
print('\n The index I[1] of elements of Z to be change \n', I[1])
M = la.solve_triangular(B1, B2, lower = False)
print('\n The values to be assigned to Z[I[1]] is \n', M)
Z[I[1]] = M
print('\n After being assigned new values, Z is \n', Z)
with result
Before being assigned new values, Z is
[0 0 0 0 0 0 1 2 3 4 5]
The index I[1] of elements of Z to be change
[False False False False False True True True True True False]
The values to be assigned to Z[I[1]] is
[2.08686055 2.88974949 3.40529229 3.88978577 4.41338306]
After being assigned new values, Z is
[0 0 0 0 0 2 2 3 3 4 5]
It's very weird to me that the command Z[I[1]] = M does not assign new values from M to the postion of Z indexed by I[1]. Could you please elaborate on why this problem arises and how to resolve it?
The datatype of your array Z is int, to the values are typecasted by python automatically, resulting in the interger values of int([2.08686055 2.88974949 3.40529229 3.88978577 4.41338306]) = [2 2 3 3 4 5].
If you want to change that behavour, you just need to add a line to change the type of your original array:
Z = Z.astype(float)

Code fails on Test case. (InterQuartile Range)

This is a challenge from 10 Day statistics on Hackerrank.(https://www.hackerrank.com/challenges/s10-interquartile-range/problem?h_r=next-challenge&h_v=zen)
Task :
Task
The interquartile range of an array is the difference between its first (Q1) and third (Q3) quartiles (i.e., Q3 - Q1).
Given an array,X, of n integers and an array, F, representing the respective frequencies of X's elements, construct a data set, S, where each xi occurs at frequency fi. Then calculate and print S's interquartile range, rounded to a scale of 1 decimal place (i.e., 12.3 format).
Following is my code.
n = int(input())
x = list(map(int, input().split()))
f = list(map(int, input().split()))
s = []
for i in range(len(x)):
j = f[i]
for k in range(j):
s.append(x[i])
n = len(s)
s.sort()
if n%2 == 0:
Q21 = s[n//2]
Q22 = s[n//2 - 1]
Q2 = (Q21 + Q22) / 2
else:
Q2 = s[n//2]
LH = s[:n//2]
if n%2==0:
UH = s[n//2:]
else:
UH = s[n//2+1:]
Q1_len = len(LH)
Q3_len = len(UH)
if Q1_len%2 == 0:
Q11 = LH[Q1_len//2]
Q12 = LH[Q1_len//2 - 1]
Q1 = (Q11 + Q12) / 2
else:
Q1 = LH[Q1_len//2]
if Q3_len%2 == 0:
Q31 = UH[Q3_len//2]
Q32 = UH[Q3_len//2 - 1]
Q3 = (Q31 + Q32) / 2
else:
Q3 = UH[Q3_len//2]
print(round(Q3 - Q1,1))
# print(int(Q2))
# print(int(Q3))
Here is the test case: with std input.
5
10 40 30 50 20
1 2 3 4 5
Expected output:
30.0
My code output:
30.0 # I get this output on my code editor but not on Hackerrank
Can someone help me on this where I am wrong ?
I get the output what is expected but it shows as failed.
print(float(Q3 - Q1))
Basically is the answer.

Where should I put the count in this tim sort algorithm, to accurately compare runtime to other algorithms

I've written a Timsort sorting algorithm for a computer science class, I would like to be able to compare the runtime to other similar algorithms, such as merge sort for instance. However, I am not sure where I should put the count (ie: count +=1)within the code to have an accurate run time. Any help would be much appreciated.
RUN = 32
def insertion_sort(arr, left, right):
for i in range(left + 1, right + 1):
temp = arr[i]
j = i - 1
while (arr[j] > temp and j >= left):
arr[j + 1] = arr[j]
arr[j] = temp
j -= 1
def merge(arr, left, right, count):
c = 0
index = count
length = len(left) + len(right)
while left and right:
if left[0] < right[0]:
arr[index] = left.pop(0)
c += 1
index += 1
else:
arr[index] = right.pop(0)
c += 1
index += 1
if len(left) == 0:
while c < length:
arr[index] = right.pop(0)
c += 1
index += 1
elif len(right) == 0:
while c < length:
arr[index] = left.pop(0)
c += 1
index += 1
def tim_sort(arr):
n = len(arr)
for i in range(0, n, RUN):
insertion_sort(arr, i, min((i + (RUN - 1)), (n - 1)))
size = RUN
while size < n:
for left in range(0, n, 2 * size):
if (left + size > n):
merge(arr, arr[left:n], [], left)
else:
left_sub_arr = arr[left:(left + size)]
right_sub_arr = arr[(left + size):min((left + 2 * size), n)]
merge(arr, left_sub_arr, right_sub_arr, left)
size *= 2
return arr

How do I calculate a factorial for a specific amount of iterations in Python

I am trying to calculate a factorial for the number 56 for only 5 times, such that my answer should be = 458,377,920; where the factorial looks like this:
56 x 55 x 54 x 53 x 52 = 458,377,920.
my current code looks like the following and it is not working:
def my_factorial(n, b):
count = 1
vlue = n
if n == 1:
return n
else:
while b > count:
for i in range(b):
vlue = vlue * (vlue - 1)
b -= 1
print(vlue)
return vlue
my_factorial(56, 5)
the results are not as expected:
3080
9483320
89933348739080
8088007215424892292570507320
65415860716765120080996841652938441974495741189603075080
The body of the loop never decrement or used n
n -= 1
vlue = vlue * n
b -= 1
Try this
def my_factorial(n, b):
vlue = n
if n == 1:
return n
else:
for _ in range(b):
vlue = vlue * (n - 1)
n = n - 1
return vlue
print(my_factorial(56, 5))
FWIW, I rewrote the function from the ground up, as an exercise.
def falling_factorial(n, b):
"""
Return the product of n..n-b+1.
>>> falling_factorial(4, 2) # 4*3
12
>>> falling_factorial(5, 3) # 5*4*3
60
>>> falling_factorial(56, 1)
56
>>> falling_factorial(56, 0)
1
"""
r = 1 # Running product
for i in range(n, n-b, -1):
r *= i
return r
Usage:
>>> falling_factorial(56, 5)
458377920

Resources