From 03ffa62564b4c6a10ad99662ea395ed5368ac45e Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Fri, 25 Oct 2019 20:41:05 +0530 Subject: [PATCH 01/20] Add files via upload --- machine_learning/isotonic.py | 953 +++++++++++++++++++++++++++++++++++ 1 file changed, 953 insertions(+) create mode 100644 machine_learning/isotonic.py diff --git a/machine_learning/isotonic.py b/machine_learning/isotonic.py new file mode 100644 index 000000000000..b76003f67206 --- /dev/null +++ b/machine_learning/isotonic.py @@ -0,0 +1,953 @@ +import numpy as np + +from scipy import interpolate + +from scipy.stats import spearmanr + +from .base import BaseEstimator, TransformerMixin, RegressorMixin + +from .utils import check_array, check_consistent_length + + +import warnings + +import math + +cimport numpy as np + +cimport cython + +from cython cimport floating + + + + + +def _inplace_contiguous_isotonic_regression(floating[::1] y, floating[::1] w): + + cdef: + + Py_ssize_t n = y.shape[0], i, k + + floating prev_y, sum_wy, sum_w + + Py_ssize_t[::1] target = np.arange(n, dtype=np.intp) + + + + # target describes a list of blocks. At any time, if [i..j] (inclusive) is + + # an active block, then target[i] := j and target[j] := i. + + + + # For "active" indices (block starts): + + # w[i] := sum{w_orig[j], j=[i..target[i]]} + + # y[i] := sum{y_orig[j]*w_orig[j], j=[i..target[i]]} / w[i] + + + + with nogil: + + i = 0 + + while i < n: + + k = target[i] + 1 + + if k == n: + + break + + if y[i] < y[k]: + + i = k + + continue + + sum_wy = w[i] * y[i] + + sum_w = w[i] + + while True: + + # We are within a decreasing subsequence. + + prev_y = y[k] + + sum_wy += w[k] * y[k] + + sum_w += w[k] + + k = target[k] + 1 + + if k == n or prev_y < y[k]: + + # Non-singleton decreasing subsequence is finished, + + # update first entry. + + y[i] = sum_wy / sum_w + + w[i] = sum_w + + target[i] = k - 1 + + target[k - 1] = i + + if i > 0: + + # Backtrack if we can. This makes the algorithm + + # single-pass and ensures O(n) complexity. + + i = target[i - 1] + + # Otherwise, restart from the same point. + + break + + # Reconstruct the solution. + + i = 0 + + while i < n: + + k = target[i] + 1 + + y[i + 1 : k] = y[i] + + i = k + + + + + +def _make_unique(np.ndarray[dtype=floating] X, + + np.ndarray[dtype=floating] y, + + np.ndarray[dtype=floating] sample_weights): + + """Average targets for duplicate X, drop duplicates. + + + + Aggregates duplicate X values into a single X value where + + the target y is a (sample_weighted) average of the individual + + targets. + + + + +__all__ = ['check_increasing', 'isotonic_regression', + + 'IsotonicRegression'] + + + + + +def check_increasing(x, y): + + """Determine whether y is monotonically correlated with x. + + + + y is found increasing or decreasing with respect to x based on a Spearman + + correlation test. + + + + Parameters + + ---------- + + x : array-like, shape=(n_samples,) + + Training data. + + + + y : array-like, shape=(n_samples,) + + Training target. + + + + Returns + + ------- + + increasing_bool : boolean + + Whether the relationship is increasing or decreasing. + + + + Notes + + ----- + + The Spearman correlation coefficient is estimated from the data, and the + + sign of the resulting estimate is used as the result. + + + + In the event that the 95% confidence interval based on Fisher transform + + spans zero, a warning is raised. + + + + References + + ---------- + + Fisher transformation. Wikipedia. + + https://en.wikipedia.org/wiki/Fisher_transformation + + """ + + + + # Calculate Spearman rho estimate and set return accordingly. + + rho, _ = spearmanr(x, y) + + increasing_bool = rho >= 0 + + + + # Run Fisher transform to get the rho CI, but handle rho=+/-1 + + if rho not in [-1.0, 1.0] and len(x) > 3: + + F = 0.5 * math.log((1. + rho) / (1. - rho)) + + F_se = 1 / math.sqrt(len(x) - 3) + + + + # Use a 95% CI, i.e., +/-1.96 S.E. + + # https://en.wikipedia.org/wiki/Fisher_transformation + + rho_0 = math.tanh(F - 1.96 * F_se) + + rho_1 = math.tanh(F + 1.96 * F_se) + + + + # Warn if the CI spans zero. + + if np.sign(rho_0) != np.sign(rho_1): + + warnings.warn("Confidence interval of the Spearman " + + "correlation coefficient spans zero. " + + "Determination of ``increasing`` may be " + + "suspect.") + + + + return increasing_bool + + + + + +def isotonic_regression(y, sample_weight=None, y_min=None, y_max=None, + + increasing=True): + + """Solve the isotonic regression model:: + + + + min sum w[i] (y[i] - y_[i]) ** 2 + + + + subject to y_min = y_[1] <= y_[2] ... <= y_[n] = y_max + + + + where: + + - y[i] are inputs (real numbers) + + - y_[i] are fitted + + - w[i] are optional strictly positive weights (default to 1.0) + + + + Read more in the :ref:`User Guide `. + + + + Parameters + + ---------- + + y : iterable of floats + + The data. + + + + sample_weight : iterable of floats, optional, default: None + + Weights on each point of the regression. + + If None, weight is set to 1 (equal weights). + + + + y_min : optional, default: None + + If not None, set the lowest value of the fit to y_min. + + + + y_max : optional, default: None + + If not None, set the highest value of the fit to y_max. + + + + increasing : boolean, optional, default: True + + Whether to compute ``y_`` is increasing (if set to True) or decreasing + + (if set to False) + + + + Returns + + ------- + + y_ : list of floats + + Isotonic fit of y. + + + + References + + ---------- + + "Active set algorithms for isotonic regression; A unifying framework" + + by Michael J. Best and Nilotpal Chakravarti, section 3. + + """ + + order = np.s_[:] if increasing else np.s_[::-1] + + y = check_array(y, ensure_2d=False, dtype=[np.float64, np.float32]) + + y = np.array(y[order], dtype=y.dtype) + + if sample_weight is None: + + sample_weight = np.ones(len(y), dtype=y.dtype) + + else: + + sample_weight = np.array(sample_weight[order], dtype=y.dtype) + + + + _inplace_contiguous_isotonic_regression(y, sample_weight) + + if y_min is not None or y_max is not None: + + # Older versions of np.clip don't accept None as a bound, so use np.inf + + if y_min is None: + + y_min = -np.inf + + if y_max is None: + + y_max = np.inf + + np.clip(y, y_min, y_max, y) + + return y[order] + + + + + +class IsotonicRegression(BaseEstimator, TransformerMixin, RegressorMixin): + + """Isotonic regression model. + + + + The isotonic regression optimization problem is defined by:: + + + + min sum w_i (y[i] - y_[i]) ** 2 + + + + subject to y_[i] <= y_[j] whenever X[i] <= X[j] + + and min(y_) = y_min, max(y_) = y_max + + + + where: + + - ``y[i]`` are inputs (real numbers) + + - ``y_[i]`` are fitted + + - ``X`` specifies the order. + + If ``X`` is non-decreasing then ``y_`` is non-decreasing. + + - ``w[i]`` are optional strictly positive weights (default to 1.0) + + + + Read more in the :ref:`User Guide `. + + + + Parameters + + ---------- + + y_min : optional, default: None + + If not None, set the lowest value of the fit to y_min. + + + + y_max : optional, default: None + + If not None, set the highest value of the fit to y_max. + + + + increasing : boolean or string, optional, default: True + + If boolean, whether or not to fit the isotonic regression with y + + increasing or decreasing. + + + + The string value "auto" determines whether y should + + increase or decrease based on the Spearman correlation estimate's + + sign. + + + + out_of_bounds : string, optional, default: "nan" + + The ``out_of_bounds`` parameter handles how x-values outside of the + + training domain are handled. When set to "nan", predicted y-values + + will be NaN. When set to "clip", predicted y-values will be + + set to the value corresponding to the nearest train interval endpoint. + + When set to "raise", allow ``interp1d`` to throw ValueError. + + + + + + Attributes + + ---------- + + X_min_ : float + + Minimum value of input array `X_` for left bound. + + + + X_max_ : float + + Maximum value of input array `X_` for right bound. + + + + f_ : function + + The stepwise interpolating function that covers the input domain ``X``. + + + + Notes + + ----- + + Ties are broken using the secondary method from Leeuw, 1977. + + + + References + + ---------- + + Isotonic Median Regression: A Linear Programming Approach + + Nilotpal Chakravarti + + Mathematics of Operations Research + + Vol. 14, No. 2 (May, 1989), pp. 303-308 + + + + Isotone Optimization in R : Pool-Adjacent-Violators + + Algorithm (PAVA) and Active Set Methods + + Leeuw, Hornik, Mair + + Journal of Statistical Software 2009 + + + + Correctness of Kruskal's algorithms for monotone regression with ties + + Leeuw, Psychometrica, 1977 + + + + Examples + + -------- + + >>> from sklearn.datasets import make_regression + + >>> from sklearn.isotonic import IsotonicRegression + + >>> X, y = make_regression(n_samples=10, n_features=1, random_state=41) + + >>> iso_reg = IsotonicRegression().fit(X.flatten(), y) + + >>> iso_reg.predict([.1, .2]) # doctest: +ELLIPSIS + + array([1.8628..., 3.7256...]) + + """ + + def __init__(self, y_min=None, y_max=None, increasing=True, + + out_of_bounds='nan'): + + self.y_min = y_min + + self.y_max = y_max + + self.increasing = increasing + + self.out_of_bounds = out_of_bounds + + + + def _check_fit_data(self, X, y, sample_weight=None): + + if len(X.shape) != 1: + + raise ValueError("X should be a 1d array") + + + + def _build_f(self, X, y): + + """Build the f_ interp1d function.""" + + + + # Handle the out_of_bounds argument by setting bounds_error + + if self.out_of_bounds not in ["raise", "nan", "clip"]: + + raise ValueError("The argument ``out_of_bounds`` must be in " + + "'nan', 'clip', 'raise'; got {0}" + + .format(self.out_of_bounds)) + + + + bounds_error = self.out_of_bounds == "raise" + + if len(y) == 1: + + # single y, constant prediction + + self.f_ = lambda x: y.repeat(x.shape) + + else: + + self.f_ = interpolate.interp1d(X, y, kind='linear', + + bounds_error=bounds_error) + + + + def _build_y(self, X, y, sample_weight, trim_duplicates=True): + + """Build the y_ IsotonicRegression.""" + + self._check_fit_data(X, y, sample_weight) + + + + # Determine increasing if auto-determination requested + + if self.increasing == 'auto': + + self.increasing_ = check_increasing(X, y) + + else: + + self.increasing_ = self.increasing + + + + # If sample_weights is passed, removed zero-weight values and clean + + # order + + if sample_weight is not None: + + sample_weight = check_array(sample_weight, ensure_2d=False, + + dtype=X.dtype) + + mask = sample_weight > 0 + + X, y, sample_weight = X[mask], y[mask], sample_weight[mask] + + else: + + sample_weight = np.ones(len(y), dtype=X.dtype) + + + + order = np.lexsort((y, X)) + + X, y, sample_weight = [array[order] for array in [X, y, sample_weight]] + + unique_X, unique_y, unique_sample_weight = _make_unique( + + X, y, sample_weight) + + + + # Store _X_ and _y_ to maintain backward compat during the deprecation + + # period of X_ and y_ + + self._X_ = X = unique_X + + self._y_ = y = isotonic_regression(unique_y, unique_sample_weight, + + self.y_min, self.y_max, + + increasing=self.increasing_) + + + + # Handle the left and right bounds on X + + self.X_min_, self.X_max_ = np.min(X), np.max(X) + + + + if trim_duplicates: + + # Remove unnecessary points for faster prediction + + keep_data = np.ones((len(y),), dtype=bool) + + # Aside from the 1st and last point, remove points whose y values + + # are equal to both the point before and the point after it. + + keep_data[1:-1] = np.logical_or( + + np.not_equal(y[1:-1], y[:-2]), + + np.not_equal(y[1:-1], y[2:]) + + ) + + return X[keep_data], y[keep_data] + + else: + + # The ability to turn off trim_duplicates is only used to it make + + # easier to unit test that removing duplicates in y does not have + + # any impact the resulting interpolation function (besides + + # prediction speed). + + return X, y + + + + def fit(self, X, y, sample_weight=None): + + """Fit the model using X, y as training data. + + + + Parameters + + ---------- + + X : array-like, shape=(n_samples,) + + Training data. + + + + y : array-like, shape=(n_samples,) + + Training target. + + + + sample_weight : array-like, shape=(n_samples,), optional, default: None + + Weights. If set to None, all weights will be set to 1 (equal + + weights). + + + + Returns + + ------- + + self : object + + Returns an instance of self. + + + + Notes + + ----- + + X is stored for future use, as `transform` needs X to interpolate + + new input data. + + """ + + check_params = dict(accept_sparse=False, ensure_2d=False, + + dtype=[np.float64, np.float32]) + + X = check_array(X, **check_params) + + y = check_array(y, **check_params) + + check_consistent_length(X, y, sample_weight) + + + + # Transform y by running the isotonic regression algorithm and + + # transform X accordingly. + + X, y = self._build_y(X, y, sample_weight) + + + + # It is necessary to store the non-redundant part of the training set + + # on the model to make it possible to support model persistence via + + # the pickle module as the object built by scipy.interp1d is not + + # picklable directly. + + self._necessary_X_, self._necessary_y_ = X, y + + + + # Build the interpolation function + + self._build_f(X, y) + + return self + + + + def transform(self, T): + + """Transform new data by linear interpolation + + + + Parameters + + ---------- + + T : array-like, shape=(n_samples,) + + Data to transform. + + + + Returns + + ------- + + T_ : array, shape=(n_samples,) + + The transformed data + + """ + + + + if hasattr(self, '_necessary_X_'): + + dtype = self._necessary_X_.dtype + + else: + + dtype = np.float64 + + + + T = check_array(T, dtype=dtype, ensure_2d=False) + + + + if len(T.shape) != 1: + + raise ValueError("Isotonic regression input should be a 1d array") + + + + # Handle the out_of_bounds argument by clipping if needed + + if self.out_of_bounds not in ["raise", "nan", "clip"]: + + raise ValueError("The argument ``out_of_bounds`` must be in " + + "'nan', 'clip', 'raise'; got {0}" + + .format(self.out_of_bounds)) + + + + if self.out_of_bounds == "clip": + + T = np.clip(T, self.X_min_, self.X_max_) + + + + res = self.f_(T) + + + + # on scipy 0.17, interp1d up-casts to float64, so we cast back + + res = res.astype(T.dtype) + + + + return res + + + + def predict(self, T): + + """Predict new data by linear interpolation. + + + + Parameters + + ---------- + + T : array-like, shape=(n_samples,) + + Data to transform. + + + + Returns + + ------- + + T_ : array, shape=(n_samples,) + + Transformed data. + + """ + + return self.transform(T) + + + + def __getstate__(self): + + """Pickle-protocol - return state of the estimator. """ + + state = super().__getstate__() + + # remove interpolation method + + state.pop('f_', None) + + return state + + + + def __setstate__(self, state): + + """Pickle-protocol - set state of the estimator. + + + + We need to rebuild the interpolation function. + + """ + + super().__setstate__(state) + + if hasattr(self, '_necessary_X_') and hasattr(self, '_necessary_y_'): + + self._build_f(self._necessary_X_, self._necessary_y_) + + + + def _more_tags(self): + + return {'X_types': ['1darray']} \ No newline at end of file From 7b5fbaaebe2fabf69ce2a0451e77e871feaffd1b Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Fri, 25 Oct 2019 20:44:22 +0530 Subject: [PATCH 02/20] Update DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a4838d24dab7..b2d21ccfa395 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -207,6 +207,7 @@ - [knn sklearn](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/knn_sklearn.py) - [linear regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_regression.py) - [logistic regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/logistic_regression.py) +- [Isotonic regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/isotonic.py) - [naive bayes](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/naive_bayes.ipynb) - Random Forest Classification - [random forest classification](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/random_forest_classification/random_forest_classification.py) From 264615bfb4a810f4fd53c9bc4ecaf500cab87bec Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 12:17:16 +0530 Subject: [PATCH 03/20] Create sol1.py --- project_euler/Problem_27/sol1.py | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 project_euler/Problem_27/sol1.py diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py new file mode 100644 index 000000000000..2961c6ff4c7a --- /dev/null +++ b/project_euler/Problem_27/sol1.py @@ -0,0 +1,39 @@ +""" +Euler discovered the remarkable quadratic formula: +n2 + n + 41 +It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. +The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479. +Considering quadratics of the form: +n² + an + b, where |a| < 1000 and |b| < 1000 +where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 +Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. +""" +def isPrime(input): + if (input == 2): + return True + if (input <= 1): + return False + if (input % 2 == 0): + return False + for (int i = input - 2; i >= math.sqrt(input); i -= 2): + if (input % i == 0): + return False + return True + +def findMaxN(a,b): + max = 0 + n = 2 + while (isPrime(n*n + a*n + b)==True): + if (n > max): + max = n++ + return max + + +def findMaxN(a,b): + max = 0 + n = 2 + while (isPrime(n*n + a*n + b)==True): + if (n > max): + max = n++ + return max + From e802182151e320fe5c23d2f39bc40cad655b2127 Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 12:19:51 +0530 Subject: [PATCH 04/20] Update sol1.py --- project_euler/Problem_27/sol1.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py index 2961c6ff4c7a..c090a10e0ed5 100644 --- a/project_euler/Problem_27/sol1.py +++ b/project_euler/Problem_27/sol1.py @@ -36,4 +36,7 @@ def findMaxN(a,b): if (n > max): max = n++ return max + +if __name__ == "__main__": + print(solution(int(input().strip()))) From 8f2f0bec74603fd804754e0eaf31d111e6bbd16d Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 12:21:43 +0530 Subject: [PATCH 05/20] Create __init__.py --- project_euler/Problem_27/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 project_euler/Problem_27/__init__.py diff --git a/project_euler/Problem_27/__init__.py b/project_euler/Problem_27/__init__.py new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/project_euler/Problem_27/__init__.py @@ -0,0 +1 @@ + From 568d4083402391bfd434171fd3f93e86681122e8 Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 12:24:51 +0530 Subject: [PATCH 06/20] Update DIRECTORY.md --- DIRECTORY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index b2d21ccfa395..a4838d24dab7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -207,7 +207,6 @@ - [knn sklearn](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/knn_sklearn.py) - [linear regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_regression.py) - [logistic regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/logistic_regression.py) -- [Isotonic regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/isotonic.py) - [naive bayes](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/naive_bayes.ipynb) - Random Forest Classification - [random forest classification](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/random_forest_classification/random_forest_classification.py) From 8eaf27ff20061366dd2aaec0a59dea4a84377912 Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 12:26:32 +0530 Subject: [PATCH 07/20] Delete isotonic.py --- machine_learning/isotonic.py | 953 ----------------------------------- 1 file changed, 953 deletions(-) delete mode 100644 machine_learning/isotonic.py diff --git a/machine_learning/isotonic.py b/machine_learning/isotonic.py deleted file mode 100644 index b76003f67206..000000000000 --- a/machine_learning/isotonic.py +++ /dev/null @@ -1,953 +0,0 @@ -import numpy as np - -from scipy import interpolate - -from scipy.stats import spearmanr - -from .base import BaseEstimator, TransformerMixin, RegressorMixin - -from .utils import check_array, check_consistent_length - - -import warnings - -import math - -cimport numpy as np - -cimport cython - -from cython cimport floating - - - - - -def _inplace_contiguous_isotonic_regression(floating[::1] y, floating[::1] w): - - cdef: - - Py_ssize_t n = y.shape[0], i, k - - floating prev_y, sum_wy, sum_w - - Py_ssize_t[::1] target = np.arange(n, dtype=np.intp) - - - - # target describes a list of blocks. At any time, if [i..j] (inclusive) is - - # an active block, then target[i] := j and target[j] := i. - - - - # For "active" indices (block starts): - - # w[i] := sum{w_orig[j], j=[i..target[i]]} - - # y[i] := sum{y_orig[j]*w_orig[j], j=[i..target[i]]} / w[i] - - - - with nogil: - - i = 0 - - while i < n: - - k = target[i] + 1 - - if k == n: - - break - - if y[i] < y[k]: - - i = k - - continue - - sum_wy = w[i] * y[i] - - sum_w = w[i] - - while True: - - # We are within a decreasing subsequence. - - prev_y = y[k] - - sum_wy += w[k] * y[k] - - sum_w += w[k] - - k = target[k] + 1 - - if k == n or prev_y < y[k]: - - # Non-singleton decreasing subsequence is finished, - - # update first entry. - - y[i] = sum_wy / sum_w - - w[i] = sum_w - - target[i] = k - 1 - - target[k - 1] = i - - if i > 0: - - # Backtrack if we can. This makes the algorithm - - # single-pass and ensures O(n) complexity. - - i = target[i - 1] - - # Otherwise, restart from the same point. - - break - - # Reconstruct the solution. - - i = 0 - - while i < n: - - k = target[i] + 1 - - y[i + 1 : k] = y[i] - - i = k - - - - - -def _make_unique(np.ndarray[dtype=floating] X, - - np.ndarray[dtype=floating] y, - - np.ndarray[dtype=floating] sample_weights): - - """Average targets for duplicate X, drop duplicates. - - - - Aggregates duplicate X values into a single X value where - - the target y is a (sample_weighted) average of the individual - - targets. - - - - -__all__ = ['check_increasing', 'isotonic_regression', - - 'IsotonicRegression'] - - - - - -def check_increasing(x, y): - - """Determine whether y is monotonically correlated with x. - - - - y is found increasing or decreasing with respect to x based on a Spearman - - correlation test. - - - - Parameters - - ---------- - - x : array-like, shape=(n_samples,) - - Training data. - - - - y : array-like, shape=(n_samples,) - - Training target. - - - - Returns - - ------- - - increasing_bool : boolean - - Whether the relationship is increasing or decreasing. - - - - Notes - - ----- - - The Spearman correlation coefficient is estimated from the data, and the - - sign of the resulting estimate is used as the result. - - - - In the event that the 95% confidence interval based on Fisher transform - - spans zero, a warning is raised. - - - - References - - ---------- - - Fisher transformation. Wikipedia. - - https://en.wikipedia.org/wiki/Fisher_transformation - - """ - - - - # Calculate Spearman rho estimate and set return accordingly. - - rho, _ = spearmanr(x, y) - - increasing_bool = rho >= 0 - - - - # Run Fisher transform to get the rho CI, but handle rho=+/-1 - - if rho not in [-1.0, 1.0] and len(x) > 3: - - F = 0.5 * math.log((1. + rho) / (1. - rho)) - - F_se = 1 / math.sqrt(len(x) - 3) - - - - # Use a 95% CI, i.e., +/-1.96 S.E. - - # https://en.wikipedia.org/wiki/Fisher_transformation - - rho_0 = math.tanh(F - 1.96 * F_se) - - rho_1 = math.tanh(F + 1.96 * F_se) - - - - # Warn if the CI spans zero. - - if np.sign(rho_0) != np.sign(rho_1): - - warnings.warn("Confidence interval of the Spearman " - - "correlation coefficient spans zero. " - - "Determination of ``increasing`` may be " - - "suspect.") - - - - return increasing_bool - - - - - -def isotonic_regression(y, sample_weight=None, y_min=None, y_max=None, - - increasing=True): - - """Solve the isotonic regression model:: - - - - min sum w[i] (y[i] - y_[i]) ** 2 - - - - subject to y_min = y_[1] <= y_[2] ... <= y_[n] = y_max - - - - where: - - - y[i] are inputs (real numbers) - - - y_[i] are fitted - - - w[i] are optional strictly positive weights (default to 1.0) - - - - Read more in the :ref:`User Guide `. - - - - Parameters - - ---------- - - y : iterable of floats - - The data. - - - - sample_weight : iterable of floats, optional, default: None - - Weights on each point of the regression. - - If None, weight is set to 1 (equal weights). - - - - y_min : optional, default: None - - If not None, set the lowest value of the fit to y_min. - - - - y_max : optional, default: None - - If not None, set the highest value of the fit to y_max. - - - - increasing : boolean, optional, default: True - - Whether to compute ``y_`` is increasing (if set to True) or decreasing - - (if set to False) - - - - Returns - - ------- - - y_ : list of floats - - Isotonic fit of y. - - - - References - - ---------- - - "Active set algorithms for isotonic regression; A unifying framework" - - by Michael J. Best and Nilotpal Chakravarti, section 3. - - """ - - order = np.s_[:] if increasing else np.s_[::-1] - - y = check_array(y, ensure_2d=False, dtype=[np.float64, np.float32]) - - y = np.array(y[order], dtype=y.dtype) - - if sample_weight is None: - - sample_weight = np.ones(len(y), dtype=y.dtype) - - else: - - sample_weight = np.array(sample_weight[order], dtype=y.dtype) - - - - _inplace_contiguous_isotonic_regression(y, sample_weight) - - if y_min is not None or y_max is not None: - - # Older versions of np.clip don't accept None as a bound, so use np.inf - - if y_min is None: - - y_min = -np.inf - - if y_max is None: - - y_max = np.inf - - np.clip(y, y_min, y_max, y) - - return y[order] - - - - - -class IsotonicRegression(BaseEstimator, TransformerMixin, RegressorMixin): - - """Isotonic regression model. - - - - The isotonic regression optimization problem is defined by:: - - - - min sum w_i (y[i] - y_[i]) ** 2 - - - - subject to y_[i] <= y_[j] whenever X[i] <= X[j] - - and min(y_) = y_min, max(y_) = y_max - - - - where: - - - ``y[i]`` are inputs (real numbers) - - - ``y_[i]`` are fitted - - - ``X`` specifies the order. - - If ``X`` is non-decreasing then ``y_`` is non-decreasing. - - - ``w[i]`` are optional strictly positive weights (default to 1.0) - - - - Read more in the :ref:`User Guide `. - - - - Parameters - - ---------- - - y_min : optional, default: None - - If not None, set the lowest value of the fit to y_min. - - - - y_max : optional, default: None - - If not None, set the highest value of the fit to y_max. - - - - increasing : boolean or string, optional, default: True - - If boolean, whether or not to fit the isotonic regression with y - - increasing or decreasing. - - - - The string value "auto" determines whether y should - - increase or decrease based on the Spearman correlation estimate's - - sign. - - - - out_of_bounds : string, optional, default: "nan" - - The ``out_of_bounds`` parameter handles how x-values outside of the - - training domain are handled. When set to "nan", predicted y-values - - will be NaN. When set to "clip", predicted y-values will be - - set to the value corresponding to the nearest train interval endpoint. - - When set to "raise", allow ``interp1d`` to throw ValueError. - - - - - - Attributes - - ---------- - - X_min_ : float - - Minimum value of input array `X_` for left bound. - - - - X_max_ : float - - Maximum value of input array `X_` for right bound. - - - - f_ : function - - The stepwise interpolating function that covers the input domain ``X``. - - - - Notes - - ----- - - Ties are broken using the secondary method from Leeuw, 1977. - - - - References - - ---------- - - Isotonic Median Regression: A Linear Programming Approach - - Nilotpal Chakravarti - - Mathematics of Operations Research - - Vol. 14, No. 2 (May, 1989), pp. 303-308 - - - - Isotone Optimization in R : Pool-Adjacent-Violators - - Algorithm (PAVA) and Active Set Methods - - Leeuw, Hornik, Mair - - Journal of Statistical Software 2009 - - - - Correctness of Kruskal's algorithms for monotone regression with ties - - Leeuw, Psychometrica, 1977 - - - - Examples - - -------- - - >>> from sklearn.datasets import make_regression - - >>> from sklearn.isotonic import IsotonicRegression - - >>> X, y = make_regression(n_samples=10, n_features=1, random_state=41) - - >>> iso_reg = IsotonicRegression().fit(X.flatten(), y) - - >>> iso_reg.predict([.1, .2]) # doctest: +ELLIPSIS - - array([1.8628..., 3.7256...]) - - """ - - def __init__(self, y_min=None, y_max=None, increasing=True, - - out_of_bounds='nan'): - - self.y_min = y_min - - self.y_max = y_max - - self.increasing = increasing - - self.out_of_bounds = out_of_bounds - - - - def _check_fit_data(self, X, y, sample_weight=None): - - if len(X.shape) != 1: - - raise ValueError("X should be a 1d array") - - - - def _build_f(self, X, y): - - """Build the f_ interp1d function.""" - - - - # Handle the out_of_bounds argument by setting bounds_error - - if self.out_of_bounds not in ["raise", "nan", "clip"]: - - raise ValueError("The argument ``out_of_bounds`` must be in " - - "'nan', 'clip', 'raise'; got {0}" - - .format(self.out_of_bounds)) - - - - bounds_error = self.out_of_bounds == "raise" - - if len(y) == 1: - - # single y, constant prediction - - self.f_ = lambda x: y.repeat(x.shape) - - else: - - self.f_ = interpolate.interp1d(X, y, kind='linear', - - bounds_error=bounds_error) - - - - def _build_y(self, X, y, sample_weight, trim_duplicates=True): - - """Build the y_ IsotonicRegression.""" - - self._check_fit_data(X, y, sample_weight) - - - - # Determine increasing if auto-determination requested - - if self.increasing == 'auto': - - self.increasing_ = check_increasing(X, y) - - else: - - self.increasing_ = self.increasing - - - - # If sample_weights is passed, removed zero-weight values and clean - - # order - - if sample_weight is not None: - - sample_weight = check_array(sample_weight, ensure_2d=False, - - dtype=X.dtype) - - mask = sample_weight > 0 - - X, y, sample_weight = X[mask], y[mask], sample_weight[mask] - - else: - - sample_weight = np.ones(len(y), dtype=X.dtype) - - - - order = np.lexsort((y, X)) - - X, y, sample_weight = [array[order] for array in [X, y, sample_weight]] - - unique_X, unique_y, unique_sample_weight = _make_unique( - - X, y, sample_weight) - - - - # Store _X_ and _y_ to maintain backward compat during the deprecation - - # period of X_ and y_ - - self._X_ = X = unique_X - - self._y_ = y = isotonic_regression(unique_y, unique_sample_weight, - - self.y_min, self.y_max, - - increasing=self.increasing_) - - - - # Handle the left and right bounds on X - - self.X_min_, self.X_max_ = np.min(X), np.max(X) - - - - if trim_duplicates: - - # Remove unnecessary points for faster prediction - - keep_data = np.ones((len(y),), dtype=bool) - - # Aside from the 1st and last point, remove points whose y values - - # are equal to both the point before and the point after it. - - keep_data[1:-1] = np.logical_or( - - np.not_equal(y[1:-1], y[:-2]), - - np.not_equal(y[1:-1], y[2:]) - - ) - - return X[keep_data], y[keep_data] - - else: - - # The ability to turn off trim_duplicates is only used to it make - - # easier to unit test that removing duplicates in y does not have - - # any impact the resulting interpolation function (besides - - # prediction speed). - - return X, y - - - - def fit(self, X, y, sample_weight=None): - - """Fit the model using X, y as training data. - - - - Parameters - - ---------- - - X : array-like, shape=(n_samples,) - - Training data. - - - - y : array-like, shape=(n_samples,) - - Training target. - - - - sample_weight : array-like, shape=(n_samples,), optional, default: None - - Weights. If set to None, all weights will be set to 1 (equal - - weights). - - - - Returns - - ------- - - self : object - - Returns an instance of self. - - - - Notes - - ----- - - X is stored for future use, as `transform` needs X to interpolate - - new input data. - - """ - - check_params = dict(accept_sparse=False, ensure_2d=False, - - dtype=[np.float64, np.float32]) - - X = check_array(X, **check_params) - - y = check_array(y, **check_params) - - check_consistent_length(X, y, sample_weight) - - - - # Transform y by running the isotonic regression algorithm and - - # transform X accordingly. - - X, y = self._build_y(X, y, sample_weight) - - - - # It is necessary to store the non-redundant part of the training set - - # on the model to make it possible to support model persistence via - - # the pickle module as the object built by scipy.interp1d is not - - # picklable directly. - - self._necessary_X_, self._necessary_y_ = X, y - - - - # Build the interpolation function - - self._build_f(X, y) - - return self - - - - def transform(self, T): - - """Transform new data by linear interpolation - - - - Parameters - - ---------- - - T : array-like, shape=(n_samples,) - - Data to transform. - - - - Returns - - ------- - - T_ : array, shape=(n_samples,) - - The transformed data - - """ - - - - if hasattr(self, '_necessary_X_'): - - dtype = self._necessary_X_.dtype - - else: - - dtype = np.float64 - - - - T = check_array(T, dtype=dtype, ensure_2d=False) - - - - if len(T.shape) != 1: - - raise ValueError("Isotonic regression input should be a 1d array") - - - - # Handle the out_of_bounds argument by clipping if needed - - if self.out_of_bounds not in ["raise", "nan", "clip"]: - - raise ValueError("The argument ``out_of_bounds`` must be in " - - "'nan', 'clip', 'raise'; got {0}" - - .format(self.out_of_bounds)) - - - - if self.out_of_bounds == "clip": - - T = np.clip(T, self.X_min_, self.X_max_) - - - - res = self.f_(T) - - - - # on scipy 0.17, interp1d up-casts to float64, so we cast back - - res = res.astype(T.dtype) - - - - return res - - - - def predict(self, T): - - """Predict new data by linear interpolation. - - - - Parameters - - ---------- - - T : array-like, shape=(n_samples,) - - Data to transform. - - - - Returns - - ------- - - T_ : array, shape=(n_samples,) - - Transformed data. - - """ - - return self.transform(T) - - - - def __getstate__(self): - - """Pickle-protocol - return state of the estimator. """ - - state = super().__getstate__() - - # remove interpolation method - - state.pop('f_', None) - - return state - - - - def __setstate__(self, state): - - """Pickle-protocol - set state of the estimator. - - - - We need to rebuild the interpolation function. - - """ - - super().__setstate__(state) - - if hasattr(self, '_necessary_X_') and hasattr(self, '_necessary_y_'): - - self._build_f(self._necessary_X_, self._necessary_y_) - - - - def _more_tags(self): - - return {'X_types': ['1darray']} \ No newline at end of file From a91f13cfdba4546d0b14c6b32ed8cb7e19af5135 Mon Sep 17 00:00:00 2001 From: RitwickGhosh <56272528+RitwickGhosh@users.noreply.github.com> Date: Sat, 26 Oct 2019 13:08:43 +0530 Subject: [PATCH 08/20] Update sol1.py --- project_euler/Problem_27/sol1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py index c090a10e0ed5..798e276a56bd 100644 --- a/project_euler/Problem_27/sol1.py +++ b/project_euler/Problem_27/sol1.py @@ -25,7 +25,7 @@ def findMaxN(a,b): n = 2 while (isPrime(n*n + a*n + b)==True): if (n > max): - max = n++ + max = n+1 return max @@ -34,7 +34,7 @@ def findMaxN(a,b): n = 2 while (isPrime(n*n + a*n + b)==True): if (n > max): - max = n++ + max = n+1 return max if __name__ == "__main__": From 34a2715c006312fdd34d240266267ef757180132 Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Wed, 30 Oct 2019 23:07:25 +0530 Subject: [PATCH 09/20] Problem_27_project_euler --- project_euler/Problem_27/sol1.py | 66 +++++++++++++++++--------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py index 798e276a56bd..9b2dc773aa37 100644 --- a/project_euler/Problem_27/sol1.py +++ b/project_euler/Problem_27/sol1.py @@ -8,35 +8,41 @@ where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. """ -def isPrime(input): - if (input == 2): - return True - if (input <= 1): - return False - if (input % 2 == 0): - return False - for (int i = input - 2; i >= math.sqrt(input); i -= 2): - if (input % i == 0): - return False - return True - -def findMaxN(a,b): - max = 0 - n = 2 - while (isPrime(n*n + a*n + b)==True): - if (n > max): - max = n+1 - return max - - -def findMaxN(a,b): - max = 0 - n = 2 - while (isPrime(n*n + a*n + b)==True): - if (n > max): - max = n+1 - return max + +import math + +def isPrime(k): + # checks if a number is prime + if k < 2: return False + elif k == 2: return True + elif k % 2 == 0: return False + else: + for x in range(3, int(math.sqrt(k)+1), 2): + if k % x == 0: return False + + return True + + +def solution(a_limit, b_limit): + longest = [0, 0, 0] + # length, a, b + for a in range((a_limit * -1) + 1, a_limit): + for b in range(2, b_limit): + if isPrime(b): + count = 0 + n = 0 + while isPrime((n**2) + (a*n) + b): + count += 1 + n += 1 + + if count > longest[0]: + longest = [count, a, b] + + ans=longest[1]*longest[2] + return ans + + + if __name__ == "__main__": - print(solution(int(input().strip()))) - + print(solution(1000, 1000)) From ff5713733463d15091057818fa48059d23e7e217 Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 09:40:25 +0530 Subject: [PATCH 10/20] project_euler/Problem_27/sol1.py --- project_euler/Problem_27/sol1.py | 42 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py index 9b2dc773aa37..0134a67d0690 100644 --- a/project_euler/Problem_27/sol1.py +++ b/project_euler/Problem_27/sol1.py @@ -11,38 +11,52 @@ import math + def isPrime(k): - # checks if a number is prime - if k < 2: return False - elif k == 2: return True - elif k % 2 == 0: return False - else: - for x in range(3, int(math.sqrt(k)+1), 2): - if k % x == 0: return False + # checks if a number is prime + if k < 2: + return False + elif k == 2: + return True + elif k % 2 == 0: + return False + else: + for x in range(3, int(math.sqrt(k) + 1), 2): + if k % x == 0: + return False - return True + return True def solution(a_limit, b_limit): + """ + >>> solution(1000, 1000) + -59231 + >>> solution(2000, 2000) + -126479 + >>> solution(-1000, 1000) + 0 + >>> solution(-1000, -1000) + 0 + + """ longest = [0, 0, 0] - # length, a, b + # length, a, b for a in range((a_limit * -1) + 1, a_limit): for b in range(2, b_limit): if isPrime(b): count = 0 n = 0 - while isPrime((n**2) + (a*n) + b): + while isPrime((n ** 2) + (a * n) + b): count += 1 n += 1 if count > longest[0]: longest = [count, a, b] - ans=longest[1]*longest[2] + ans = longest[1] * longest[2] return ans - - if __name__ == "__main__": - print(solution(1000, 1000)) + print(solution(1000, 1000)) From aef684f8f8f06f4ad574df59a370964f49883185 Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 10:04:59 +0530 Subject: [PATCH 11/20] project_euler/Problem_27/sol1.py --- project_euler/Problem_27/sol1.py | 67 +++++++++++++++----------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py index 0134a67d0690..d0b86dc1a025 100644 --- a/project_euler/Problem_27/sol1.py +++ b/project_euler/Problem_27/sol1.py @@ -11,25 +11,23 @@ import math - -def isPrime(k): - # checks if a number is prime - if k < 2: - return False - elif k == 2: - return True - elif k % 2 == 0: - return False - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False - - return True - +def isprime(k): + # checks if a number is prime + if k < 2: + return False + elif k == 2: + return True + elif k % 2 == 0: + return False + else: + for x in range(3, int(math.sqrt(k) + 1), 2): + if k % x == 0: + return False + + return True def solution(a_limit, b_limit): - """ + """ >>> solution(1000, 1000) -59231 >>> solution(2000, 2000) @@ -40,23 +38,22 @@ def solution(a_limit, b_limit): 0 """ - longest = [0, 0, 0] - # length, a, b - for a in range((a_limit * -1) + 1, a_limit): - for b in range(2, b_limit): - if isPrime(b): - count = 0 - n = 0 - while isPrime((n ** 2) + (a * n) + b): - count += 1 - n += 1 - - if count > longest[0]: - longest = [count, a, b] - - ans = longest[1] * longest[2] - return ans - + longest = [0, 0, 0] + # length, a, b + for a in range((a_limit * -1) + 1, a_limit): + for b in range(2, b_limit): + if isprime(b): + count = 0 + n = 0 + while isprime((n ** 2) + (a * n) + b): + count += 1 + n += 1 + + if count > longest[0]: + longest = [count, a, b] + + ans = longest[1] * longest[2] + return ans if __name__ == "__main__": - print(solution(1000, 1000)) + print(solution(1000, 1000)) From e9fe8cbb6609da132aa6edceae5fa530ac2efe55 Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 10:24:38 +0530 Subject: [PATCH 12/20] project_euler/problem_27/ --- project_euler/problem_27/__init__.py | 1 + project_euler/problem_27/sol1.py | 59 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 project_euler/problem_27/__init__.py create mode 100644 project_euler/problem_27/sol1.py diff --git a/project_euler/problem_27/__init__.py b/project_euler/problem_27/__init__.py new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/project_euler/problem_27/__init__.py @@ -0,0 +1 @@ + diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/sol1.py new file mode 100644 index 000000000000..d0b86dc1a025 --- /dev/null +++ b/project_euler/problem_27/sol1.py @@ -0,0 +1,59 @@ +""" +Euler discovered the remarkable quadratic formula: +n2 + n + 41 +It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. +The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479. +Considering quadratics of the form: +n² + an + b, where |a| < 1000 and |b| < 1000 +where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 +Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. +""" + +import math + +def isprime(k): + # checks if a number is prime + if k < 2: + return False + elif k == 2: + return True + elif k % 2 == 0: + return False + else: + for x in range(3, int(math.sqrt(k) + 1), 2): + if k % x == 0: + return False + + return True + +def solution(a_limit, b_limit): + """ + >>> solution(1000, 1000) + -59231 + >>> solution(2000, 2000) + -126479 + >>> solution(-1000, 1000) + 0 + >>> solution(-1000, -1000) + 0 + + """ + longest = [0, 0, 0] + # length, a, b + for a in range((a_limit * -1) + 1, a_limit): + for b in range(2, b_limit): + if isprime(b): + count = 0 + n = 0 + while isprime((n ** 2) + (a * n) + b): + count += 1 + n += 1 + + if count > longest[0]: + longest = [count, a, b] + + ans = longest[1] * longest[2] + return ans + +if __name__ == "__main__": + print(solution(1000, 1000)) From bd47691bb46226c002a5317b09be34253d473dc4 Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 10:33:30 +0530 Subject: [PATCH 13/20] project_euler/problem_27 --- project_euler/Problem_27/__init__.py | 1 - project_euler/Problem_27/sol1.py | 59 ---------------------------- 2 files changed, 60 deletions(-) delete mode 100644 project_euler/Problem_27/__init__.py delete mode 100644 project_euler/Problem_27/sol1.py diff --git a/project_euler/Problem_27/__init__.py b/project_euler/Problem_27/__init__.py deleted file mode 100644 index 8b137891791f..000000000000 --- a/project_euler/Problem_27/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py deleted file mode 100644 index d0b86dc1a025..000000000000 --- a/project_euler/Problem_27/sol1.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Euler discovered the remarkable quadratic formula: -n2 + n + 41 -It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. -The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479. -Considering quadratics of the form: -n² + an + b, where |a| < 1000 and |b| < 1000 -where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 -Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. -""" - -import math - -def isprime(k): - # checks if a number is prime - if k < 2: - return False - elif k == 2: - return True - elif k % 2 == 0: - return False - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False - - return True - -def solution(a_limit, b_limit): - """ - >>> solution(1000, 1000) - -59231 - >>> solution(2000, 2000) - -126479 - >>> solution(-1000, 1000) - 0 - >>> solution(-1000, -1000) - 0 - - """ - longest = [0, 0, 0] - # length, a, b - for a in range((a_limit * -1) + 1, a_limit): - for b in range(2, b_limit): - if isprime(b): - count = 0 - n = 0 - while isprime((n ** 2) + (a * n) + b): - count += 1 - n += 1 - - if count > longest[0]: - longest = [count, a, b] - - ans = longest[1] * longest[2] - return ans - -if __name__ == "__main__": - print(solution(1000, 1000)) From 10e64cfe0d6a8f46409ae850c4b84a17a1788e0c Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 10:37:09 +0530 Subject: [PATCH 14/20] project_euler/problem_27 --- project_euler/Problem_27/__init__.py | 1 - project_euler/Problem_27/sol1.py | 59 ---------------------------- 2 files changed, 60 deletions(-) delete mode 100644 project_euler/Problem_27/__init__.py delete mode 100644 project_euler/Problem_27/sol1.py diff --git a/project_euler/Problem_27/__init__.py b/project_euler/Problem_27/__init__.py deleted file mode 100644 index 8b137891791f..000000000000 --- a/project_euler/Problem_27/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/project_euler/Problem_27/sol1.py b/project_euler/Problem_27/sol1.py deleted file mode 100644 index d0b86dc1a025..000000000000 --- a/project_euler/Problem_27/sol1.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Euler discovered the remarkable quadratic formula: -n2 + n + 41 -It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. -The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479. -Considering quadratics of the form: -n² + an + b, where |a| < 1000 and |b| < 1000 -where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 -Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. -""" - -import math - -def isprime(k): - # checks if a number is prime - if k < 2: - return False - elif k == 2: - return True - elif k % 2 == 0: - return False - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False - - return True - -def solution(a_limit, b_limit): - """ - >>> solution(1000, 1000) - -59231 - >>> solution(2000, 2000) - -126479 - >>> solution(-1000, 1000) - 0 - >>> solution(-1000, -1000) - 0 - - """ - longest = [0, 0, 0] - # length, a, b - for a in range((a_limit * -1) + 1, a_limit): - for b in range(2, b_limit): - if isprime(b): - count = 0 - n = 0 - while isprime((n ** 2) + (a * n) + b): - count += 1 - n += 1 - - if count > longest[0]: - longest = [count, a, b] - - ans = longest[1] * longest[2] - return ans - -if __name__ == "__main__": - print(solution(1000, 1000)) From e6a2a006933f728da1f06d9f1dd4b6539807b6dc Mon Sep 17 00:00:00 2001 From: itsvinayak Date: Thu, 31 Oct 2019 11:57:27 +0530 Subject: [PATCH 15/20] update sol1 of Euler Problem 27 solution script Added --- project_euler/problem_27/sol1.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/sol1.py index d0b86dc1a025..379f7ff9630b 100644 --- a/project_euler/problem_27/sol1.py +++ b/project_euler/problem_27/sol1.py @@ -11,14 +11,12 @@ import math -def isprime(k): +def is_prime(k): # checks if a number is prime - if k < 2: + if k < 2 or k % 2 == 0: return False elif k == 2: return True - elif k % 2 == 0: - return False else: for x in range(3, int(math.sqrt(k) + 1), 2): if k % x == 0: @@ -36,16 +34,15 @@ def solution(a_limit, b_limit): 0 >>> solution(-1000, -1000) 0 - """ longest = [0, 0, 0] # length, a, b for a in range((a_limit * -1) + 1, a_limit): for b in range(2, b_limit): - if isprime(b): + if is_prime(b): count = 0 n = 0 - while isprime((n ** 2) + (a * n) + b): + while is_prime((n ** 2) + (a * n) + b): count += 1 n += 1 From 2f0d1884cf46753df342be0adec8c44ac11af0da Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 31 Oct 2019 08:06:15 +0100 Subject: [PATCH 16/20] Remove slow test, wrap long comments, format with psf/black --- project_euler/problem_27/sol1.py | 71 ++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/sol1.py index 379f7ff9630b..ce12e40f0778 100644 --- a/project_euler/problem_27/sol1.py +++ b/project_euler/problem_27/sol1.py @@ -1,56 +1,63 @@ """ Euler discovered the remarkable quadratic formula: n2 + n + 41 -It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. -The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479. +It turns out that the formula will produce 40 primes for the consecutive values +n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible +by 41, and certainly when n = 41, 412 + 41 + 41 is clearly divisible by 41. +The incredible formula n2 − 79n + 1601 was discovered, which produces 80 primes +for the consecutive values n = 0 to 79. The product of the coefficients, −79 and +1601, is −126479. Considering quadratics of the form: n² + an + b, where |a| < 1000 and |b| < 1000 where |n| is the modulus/absolute value of ne.g. |11| = 11 and |−4| = 4 -Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. +Find the product of the coefficients, a and b, for the quadratic expression that +produces the maximum number of primes for consecutive values of n, starting with +n = 0. """ import math + def is_prime(k): - # checks if a number is prime - if k < 2 or k % 2 == 0: - return False - elif k == 2: - return True - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False + # checks if a number is prime + if k < 2 or k % 2 == 0: + return False + elif k == 2: + return True + else: + for x in range(3, int(math.sqrt(k) + 1), 2): + if k % x == 0: + return False + return True - return True def solution(a_limit, b_limit): - """ + """ >>> solution(1000, 1000) -59231 - >>> solution(2000, 2000) - -126479 + >>> solution(200, 1000) + -59231 + >>> solution(200, 200) + -4925 >>> solution(-1000, 1000) 0 >>> solution(-1000, -1000) 0 """ - longest = [0, 0, 0] - # length, a, b - for a in range((a_limit * -1) + 1, a_limit): - for b in range(2, b_limit): - if is_prime(b): - count = 0 - n = 0 - while is_prime((n ** 2) + (a * n) + b): - count += 1 - n += 1 - - if count > longest[0]: - longest = [count, a, b] + longest = [0, 0, 0] # length, a, b + for a in range((a_limit * -1) + 1, a_limit): + for b in range(2, b_limit): + if is_prime(b): + count = 0 + n = 0 + while is_prime((n ** 2) + (a * n) + b): + count += 1 + n += 1 + if count > longest[0]: + longest = [count, a, b] + ans = longest[1] * longest[2] + return ans - ans = longest[1] * longest[2] - return ans if __name__ == "__main__": - print(solution(1000, 1000)) + print(solution(1000, 1000)) From 4a9d42c7f94d687890ab8ecbb72acaba0c7601f0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 31 Oct 2019 08:06:45 +0100 Subject: [PATCH 17/20] Delete __init__.py --- project_euler/problem_27/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 project_euler/problem_27/__init__.py diff --git a/project_euler/problem_27/__init__.py b/project_euler/problem_27/__init__.py deleted file mode 100644 index 8b137891791f..000000000000 --- a/project_euler/problem_27/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From 5d98bc45e3cec1ee39a6a342775fb829f178030f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 31 Oct 2019 08:08:11 +0100 Subject: [PATCH 18/20] Add type hints --- project_euler/problem_27/sol1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/sol1.py index ce12e40f0778..4bfc26643653 100644 --- a/project_euler/problem_27/sol1.py +++ b/project_euler/problem_27/sol1.py @@ -18,7 +18,7 @@ import math -def is_prime(k): +def is_prime(k: int) -> bool: # checks if a number is prime if k < 2 or k % 2 == 0: return False @@ -31,7 +31,7 @@ def is_prime(k): return True -def solution(a_limit, b_limit): +def solution(a_limit: int, b_limit: int) -> int: """ >>> solution(1000, 1000) -59231 From e18154fbcca27068700ee5eb2f35fafc5c08d9a3 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 31 Oct 2019 08:10:26 +0100 Subject: [PATCH 19/20] Add doctests to function is_prime() --- project_euler/problem_27/sol1.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/sol1.py index 4bfc26643653..dbd07f81b713 100644 --- a/project_euler/problem_27/sol1.py +++ b/project_euler/problem_27/sol1.py @@ -19,7 +19,13 @@ def is_prime(k: int) -> bool: - # checks if a number is prime + """ + Determine if a number is prime + >>> is_prime(10) + False + >>> is_prime(11) + True + """ if k < 2 or k % 2 == 0: return False elif k == 2: From bb790078744e4063fa8ca912911ccba82bd86f6e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 31 Oct 2019 08:13:55 +0100 Subject: [PATCH 20/20] Rename project_euler/problem_27/project_euler/problem_27/sol1.pysol1.py to project_euler/problem_27/problem_27_sol1.py --- project_euler/problem_27/{sol1.py => problem_27_sol1.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename project_euler/problem_27/{sol1.py => problem_27_sol1.py} (100%) diff --git a/project_euler/problem_27/sol1.py b/project_euler/problem_27/problem_27_sol1.py similarity index 100% rename from project_euler/problem_27/sol1.py rename to project_euler/problem_27/problem_27_sol1.py