diff --git a/maths/Gaussiandistribution.py b/maths/Gaussiandistribution.py new file mode 100644 index 000000000000..2ee1516f7ce6 --- /dev/null +++ b/maths/Gaussiandistribution.py @@ -0,0 +1,181 @@ +import math +import matplotlib.pyplot as plt +from .Generaldistribution import Distribution + +class Gaussian(Distribution): + """ Gaussian distribution class for calculating and + visualizing a Gaussian distribution. + + Attributes: + mean (float) representing the mean value of the distribution + stdev (float) representing the standard deviation of the distribution + data_list (list of floats) a list of floats extracted from the data file + + """ + def __init__(self, mu=0, sigma=1): + + Distribution.__init__(self, mu, sigma) + + + + def calculate_mean(self): + + """Function to calculate the mean of the data set. + + Args: + None + + Returns: + float: mean of the data set + + """ + + avg = 1.0 * sum(self.data) / len(self.data) + + self.mean = avg + + return self.mean + + + + def calculate_stdev(self, sample=True): + + """Function to calculate the standard deviation of the data set. + + Args: + sample (bool): whether the data represents a sample or population + + Returns: + float: standard deviation of the data set + + """ + + if sample: + n = len(self.data) - 1 + else: + n = len(self.data) + + mean = self.calculate_mean() + + sigma = 0 + + for d in self.data: + sigma += (d - mean) ** 2 + + sigma = math.sqrt(sigma / n) + + self.stdev = sigma + + return self.stdev + + + + def plot_histogram(self): + """Function to output a histogram of the instance variable data using + matplotlib pyplot library. + + Args: + None + + Returns: + None + """ + plt.hist(self.data) + plt.title('Histogram of Data') + plt.xlabel('data') + plt.ylabel('count') + + + + def pdf(self, x): + """Probability density function calculator for the gaussian distribution. + + Args: + x (float): point for calculating the probability density function + + + Returns: + float: probability density function output + """ + + return (1.0 / (self.stdev * math.sqrt(2*math.pi))) * math.exp(-0.5*((x - self.mean) / self.stdev) ** 2) + + + def plot_histogram_pdf(self, n_spaces = 50): + + """Function to plot the normalized histogram of the data and a plot of the + probability density function along the same range + + Args: + n_spaces (int): number of data points + + Returns: + list: x values for the pdf plot + list: y values for the pdf plot + + """ + + mu = self.mean + sigma = self.stdev + + min_range = min(self.data) + max_range = max(self.data) + + # calculates the interval between x values + interval = 1.0 * (max_range - min_range) / n_spaces + + x = [] + y = [] + + # calculate the x values to visualize + for i in range(n_spaces): + tmp = min_range + interval*i + x.append(tmp) + y.append(self.pdf(tmp)) + + # make the plots + fig, axes = plt.subplots(2,sharex=True) + fig.subplots_adjust(hspace=.5) + axes[0].hist(self.data, density=True) + axes[0].set_title('Normed Histogram of Data') + axes[0].set_ylabel('Density') + + axes[1].plot(x, y) + axes[1].set_title('Normal Distribution for \n Sample Mean and Sample Standard Deviation') + axes[0].set_ylabel('Density') + plt.show() + + return x, y + + def __add__(self, other): + + """Function to add together two Gaussian distributions + + Args: + other (Gaussian): Gaussian instance + + Returns: + Gaussian: Gaussian distribution + + """ + + result = Gaussian() + result.mean = self.mean + other.mean + result.stdev = math.sqrt(self.stdev ** 2 + other.stdev ** 2) + + return result + + + def __repr__(self): + + """Function to output the characteristics of the Gaussian instance + + Args: + None + + Returns: + string: characteristics of the Gaussian + + """ + + return "mean {}, standard deviation {}".format(self.mean, self.stdev) \ No newline at end of file diff --git a/maths/Generaldistribution.py b/maths/Generaldistribution.py new file mode 100644 index 000000000000..ae1cf60df508 --- /dev/null +++ b/maths/Generaldistribution.py @@ -0,0 +1,41 @@ +class Distribution: + + def __init__(self, mu=0, sigma=1): + + """ Generic distribution class for calculating and + visualizing a probability distribution. + + Attributes: + mean (float) representing the mean value of the distribution + stdev (float) representing the standard deviation of the distribution + data_list (list of floats) a list of floats extracted from the data file + """ + + self.mean = mu + self.stdev = sigma + self.data = [] + + + def read_data_file(self, file_name): + + """Function to read in data from a txt file. The txt file should have + one number (float) per line. The numbers are stored in the data attribute. + + Args: + file_name (string): name of a file to read from + + Returns: + None + + """ + + with open(file_name) as file: + data_list = [] + line = file.readline() + while line: + data_list.append(int(line)) + line = file.readline() + file.close() + + self.data = data_list + diff --git a/maths/abs_max.py b/maths/abs_max.py index e5a8219657ac..4a4b4d9ebca3 100644 --- a/maths/abs_max.py +++ b/maths/abs_max.py @@ -7,7 +7,13 @@ def abs_max(x: list[int]) -> int: 11 >>> abs_max([3,-10,-2]) -10 + >>> abs_max([]) + Traceback (most recent call last): + ... + ValueError: abs_max() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_max() arg is an empty sequence") j = x[0] for i in x: if abs(i) > abs(j): @@ -15,13 +21,19 @@ def abs_max(x: list[int]) -> int: return j -def abs_max_sort(x): +def abs_max_sort(x: list[int]) -> int: """ >>> abs_max_sort([0,5,1,11]) 11 >>> abs_max_sort([3,-10,-2]) -10 + >>> abs_max_sort([]) + Traceback (most recent call last): + ... + ValueError: abs_max_sort() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_max_sort() arg is an empty sequence") return sorted(x, key=abs)[-1] @@ -32,4 +44,7 @@ def main(): if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) main() diff --git a/maths/abs_min.py b/maths/abs_min.py index eb84de37ce23..00dbcb025cfb 100644 --- a/maths/abs_min.py +++ b/maths/abs_min.py @@ -1,13 +1,21 @@ +from __future__ import annotations + from .abs import abs_val -def absMin(x): +def abs_min(x: list[int]) -> int: """ - >>> absMin([0,5,1,11]) + >>> abs_min([0,5,1,11]) 0 - >>> absMin([3,-10,-2]) + >>> abs_min([3,-10,-2]) -2 + >>> abs_min([]) + Traceback (most recent call last): + ... + ValueError: abs_min() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_min() arg is an empty sequence") j = x[0] for i in x: if abs_val(i) < abs_val(j): @@ -17,8 +25,11 @@ def absMin(x): def main(): a = [-3, -1, 2, -11] - print(absMin(a)) # = -1 + print(abs_min(a)) # = -1 if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) main() diff --git a/project_euler/problem_112/sol1.py b/project_euler/problem_112/sol1.py index d8cb334c9508..b3ea6b35654a 100644 --- a/project_euler/problem_112/sol1.py +++ b/project_euler/problem_112/sol1.py @@ -47,7 +47,9 @@ def check_bouncy(n: int) -> bool: """ if not isinstance(n, int): raise ValueError("check_bouncy() accepts only integer arguments") - return "".join(sorted(str(n))) != str(n) and "".join(sorted(str(n)))[::-1] != str(n) + str_n = str(n) + sorted_str_n = "".join(sorted(str_n)) + return sorted_str_n != str_n and sorted_str_n[::-1] != str_n def solution(percent: float = 99) -> int: diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 030cf12f2a85..fe4d14b20c92 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -75,17 +75,15 @@ def get_primes_squared(max_number: int) -> list[int]: >>> get_primes_squared(100) [4, 9, 25, 49] """ - max_prime = round(math.sqrt(max_number)) - non_primes = set() + max_prime = math.isqrt(max_number) + non_primes = [False] * (max_prime + 1) primes = [] for num in range(2, max_prime + 1): - if num in non_primes: + if non_primes[num]: continue - counter = 2 - while num * counter <= max_prime: - non_primes.add(num * counter) - counter += 1 + for num_counter in range(num ** 2, max_prime + 1, num): + non_primes[num_counter] = True primes.append(num ** 2) return primes