Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Super fly Python style #2

Open
wants to merge 1 commit into
base: drag-race
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions PrimePython/solution_4/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
45 changes: 45 additions & 0 deletions PrimePython/solution_4/README.md
Original file line number Diff line number Diff line change
@@ -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
46 changes: 46 additions & 0 deletions PrimePython/solution_4/prime_sieve.py
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 3 additions & 0 deletions PrimePython/solution_4/requirements.txt
Original file line number Diff line number Diff line change
@@ -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