diff --git a/PrimePython/solution_4/Dockerfile b/PrimePython/solution_4/Dockerfile new file mode 100644 index 000000000..2be2b01c6 --- /dev/null +++ b/PrimePython/solution_4/Dockerfile @@ -0,0 +1,23 @@ +# For more information, please refer to https://aka.ms/vscode-docker-python +FROM python:3.9-slim-buster + +# Keeps Python from generating .pyc files in the container +ENV PYTHONDONTWRITEBYTECODE=1 + +# Turns off buffering for easier container logging +ENV PYTHONUNBUFFERED=1 + +# Install pip requirements +COPY requirements.txt . +RUN python -m pip install -r requirements.txt + +WORKDIR /app +COPY . /app + +# Creates a non-root user with an explicit UID and adds permission to access the /app folder +# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers +RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app +USER appuser + +# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug +CMD ["python", "prime_sieve.py"] diff --git a/PrimePython/solution_4/README.md b/PrimePython/solution_4/README.md new file mode 100644 index 000000000..e3b2ad43d --- /dev/null +++ b/PrimePython/solution_4/README.md @@ -0,0 +1,45 @@ +# Prime Sieve by jugge83 + +![Algorithm](https://img.shields.io/badge/Algorithm-base-green) +![Faithfulness](https://img.shields.io/badge/Faithful-no-yellowgreen) +![Parallelism](https://img.shields.io/badge/Parallel-no-green) +![Bit count](https://img.shields.io/badge/Bits-1-green) + +This solution is the resulting work from the discussion in [issue #25](https://github.com/PlummersSoftwareLLC/Primes/issues?page=3&q=is%3Aissue) of the [original repository](https://github.com/PlummersSoftwareLLC/Primes). The code is optimized and around 1,5 times faster than solution_3. +The code uses 2 external libraries, numpy and numba. +- Numpy is the de facto standard mathematical library for python. +- Numba is a jit compiler for python. + +The solution is **unfaithful** due to the inclusion of two dependencies and is rewritten in a non object oriented manner. +The rationale is: both libraries are used extensively in the community and the code structure is compact and more readable. + + +## Running with Python + +Install Python: https://www.python.org/downloads/ + +Install the dependencies: +``` +pip install numpy, numba +``` +or: +``` +cd path/to/requirements.txt +pip install -r requirements.txt +``` + +Run the file: +``` +cd path/to/prime_sieve.py +python prime_sieve.py +``` + +## Running with Dockerfile + +Build Docker image. + +Run Docker image. + +## Output + +jugge83;7714;5.0001099;1;algorithm=base,faithful=no,bits=1 \ No newline at end of file diff --git a/PrimePython/solution_4/prime_sieve.py b/PrimePython/solution_4/prime_sieve.py new file mode 100644 index 000000000..16a3b492c --- /dev/null +++ b/PrimePython/solution_4/prime_sieve.py @@ -0,0 +1,46 @@ +__author__ = "jugge83" + +import timeit +import itertools +from numba import njit, b1, int32 +import numpy as np + + +@njit(b1[:](int32), fastmath = True) +def run_sieve(limit): + prime_list = np.full(limit // 2, True) # defines a list for odd integers + prime_list[0] = False # 1 is not a prime + for factor in range(3, int(limit ** (1/2)) + 1, 2): + if prime_list[factor // 2]: # just looking at odd integers everything halves + prime_list[(factor ** 2) // 2:limit // 2:factor] = False + return prime_list[:(limit // 2) + 1] + +def print_results(time_delta, passes, primes, limit): + prime_counts = { + 10: 4, # Historical data for validating our results - the number of primes + 100: 25, # to be found under some limit, such as 168 primes under 1000 + 1000: 168, + 10000: 1229, + 100000: 9592, + 1000000: 78498, + 10000000: 664579, + 100000000: 5761455, + } + #print(f"""Passes: {passes}\nTime: {time_delta}\nAvg: {time_delta/passes}\ + # \nLimit: {limit}\nCount: {len(primes)}\nValid: {prime_counts[limit]==len(primes)}""") + print(f"jugge83;{passes};{time_delta};1;algorithm=base,faithful=no,bits=1") + +def primes(sieve): + return itertools.chain([2], (prime * 2 + 1 for (prime, is_prime) in enumerate(sieve) if is_prime)) + +if __name__=="__main__": + t_start = timeit.default_timer() # Record our starting time + passes = 0 + limit = 1_000_000 + while timeit.default_timer() - t_start < 5: + prime_validators = run_sieve(limit) + passes = passes + 1 + time_delta = timeit.default_timer() - t_start + primes = list(primes(prime_validators)) + #print(primes[:100]) + print_results(time_delta, passes, primes, limit) \ No newline at end of file diff --git a/PrimePython/solution_4/requirements.txt b/PrimePython/solution_4/requirements.txt new file mode 100644 index 000000000..4950d1f00 --- /dev/null +++ b/PrimePython/solution_4/requirements.txt @@ -0,0 +1,3 @@ +# To ensure app dependencies are ported from your virtual environment/host machine into your container, run 'pip freeze > requirements.txt' in the terminal to overwrite this file +numpy +numba \ No newline at end of file