Skip to content

Commit 58d78d8

Browse files
author
Gonzalo Diaz
committed
[DOC] Better README.
1 parent 9029e9f commit 58d78d8

File tree

1 file changed

+196
-74
lines changed

1 file changed

+196
-74
lines changed

README.md

Lines changed: 196 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -16,153 +16,275 @@
1616
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-py&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-py)
1717
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-py&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-py)
1818

19+
## TL;DR
20+
21+
[Install and run](#install-and-run)
22+
1923
## What is this?
2024

21-
[Project Euler](https://algorithm-exercises.net/) provide some algorithms and
22-
mathematical problems to solve to be used as experience tests.
25+
This repository is part of a series that share and solve the same [objectives](#objetives),
26+
with the difference that each one is based on a different software ecosystem,
27+
depending on the chosen programming language:
2328

24-
Use this answers to learn some tip and tricks for algorithms tests.
29+
- [Modern Javascript: algorithm-exercises-py](https://github.com/sir-gon/algorithm-exercises-py)
30+
- [Python 3.x: algorithm-exercises-py](https://github.com/sir-gon/algorithm-exercises-py)
31+
- [Typescript: algorithm-exercises-ts](https://github.com/sir-gon/algorithm-exercises-ts)
32+
- [Go / Golang: algorithm-exercises-go](https://github.com/sir-gon/algorithm-exercises-go)
33+
- [Java: algorithm-exercises-java](https://github.com/sir-gon/algorithm-exercises-java)
34+
- [.NET / C#: algorithm-exercises-csharp](https://github.com/sir-gon/algorithm-exercises-csharp)
2535

26-
## Why I publish solutions?
36+
## Objetives
2737

28-
As Project Euler says:
38+
### Functional
2939

30-
<https://algorithm-exercises.net/about#publish>
40+
- For academic purposes, it is an backup of some algorithm exercises
41+
(with their solutions), proposed by various sources:
42+
[leetcode, hackerrank, projecteuler](#algorithm-excersices-sources), ...
3143

32-
```text
33-
I learned so much solving problem XXX, so is it okay to publish my solution elsewhere?
34-
It appears that you have answered your own question. There is nothing quite like that "Aha!" moment when you finally beat a problem which you have been working on for some time. It is often through the best of intentions in wishing to share our insights so that others can enjoy that moment too. Sadly, that will rarely be the case for your readers. Real learning is an active process and seeing how it is done is a long way from experiencing that epiphany of discovery. Please do not deny others what you have so richly valued yourself.
44+
- The solutions must be written on "vanilla code", that is,
45+
avoiding as much as possible the use of external libraries (in runtime).
3546

36-
However, the rule about sharing solutions outside of Project Euler does not apply to the first one-hundred problems, as long as any discussion clearly aims to instruct methods, not just provide answers, and does not directly threaten to undermine the enjoyment of solving later problems. Problems 1 to 100 provide a wealth of helpful introductory teaching material and if you are able to respect our requirements, then we give permission for those problems and their solutions to be discussed elsewhere.
37-
```
47+
- Adoption of methodology and good practices.
48+
Each exercise is implemented as a unit test set,
49+
using TDD (Test-driven Development) and Clean Code ideas.
3850

39-
If you have better answers or optimal solutions, fork and PR-me
51+
### Technical
4052

41-
Enjoy 😁 !
53+
Foundation of a project that supports:
4254

43-
## Using Python 3 native runtime
55+
- Explicit **typing** when the language supports it, even when it is not mandatory.
56+
- Static Code Analysis (**Lint**) of code, scripts and documentation.
57+
- Uniform **Code Styling**.
58+
- **Unit Test** framework.
59+
- **Coverge** collection. High coverage percentage. Equal or close to 100%.
60+
- **Pipeline** (Github Actions). Each command must take care of its
61+
return status code.
62+
- **Docker**-based workflow to replicate behavior in any environment.
63+
- Other tools to support the reinforcement of software development **good practices**.
4464

45-
## Requirements
65+
## Install and Run
4666

47-
You must install dependencies:
67+
You can run tests in the following ways:
4868

49-
```text
50-
pip3 install -r requirements.txt
51-
```
69+
- [Install and run directly](#install-and-run-directly) require runtime tools
70+
installed in your SO.
71+
- [Install and run with make](#install-and-run-using-make) require runtime tools
72+
and "make" installed in your SO.
73+
- [Install and in Docker](#install-and-running-with-docker-) require Docker and
74+
docker-compose installed.
75+
- (⭐️)
76+
[Install and in Docker with make](#install-and-running-with-docker--using-make)
77+
require docker-compose and make installed.
5278

53-
Or using make
79+
⭐️: Prefered way.
5480

55-
```text
56-
make dependencies
57-
```
81+
### Install and Run directly
5882

59-
### Minimal dependencies
83+
Using a Python 3.x runtime in your SO.
6084

61-
Third party libraries for CI/CD pipeline and TDD cycle (not used in runtime):
85+
First, load virtual env environment:
6286

63-
```text
64-
pip3 install coverage pylint pytest
87+
```bash
88+
source .venv/bin/activate
6589
```
6690

67-
### Testing silently
91+
You must install dependencies:
92+
93+
```bash
94+
pip3 install -r requirements.txt
95+
```
6896

6997
Every problem is a function with unit test.
98+
7099
Unit test has test cases and input data to solve the problem.
71100

72-
Run all tests:
101+
Run all tests collectino coverage:
73102

74-
```text
75-
pytest --verbose -o log_cli=true --log-cli-level=INFO --full-trace src/
103+
```bash
104+
python3 -m coverage run -m pytest --verbose src/
76105
```
77106

78-
### Testing with full logs
107+
#### Test run with alternative behaviors
79108

80-
Run all tests with debug outputs:
109+
You can change test running behaviour using some environment variables as follows:
81110

82-
```text
83-
pytest --verbose -o log_cli=true --log-cli-level=DEBUG --full-trace src/
111+
| Variable | Values | Default |
112+
| ------ | ------ | ------ |
113+
| LOG_LEVEL | `debug`, `warning`, `error`, `info` | `info` |
114+
| BRUTEFORCE | `true`, `false`| `false` |
115+
116+
- `LOG_LEVEL`: change verbosity level in outputs.
117+
- `BRUTEFORCE`: enable or disable running large tests.
118+
(long time, large amount of data, high memory consumition).
119+
120+
#### Examples running tests with alternative behaviors
121+
122+
Log level in pytest require to pass a parameter.
123+
So, to pass it in a similar way as another sibling stacks,
124+
the following example is proposed to run tests with debug outputs:
125+
126+
```bash
127+
LOG_LEVEL=debug python3 -m coverage run -m \
128+
pytest --verbose \
129+
-o log_cli=true \
130+
--log-cli-level=${LOG_LEVEL} \
131+
--full-trace src/
84132
```
85133

86-
### Testing using make
134+
Run brute-force tests with debug outputs:
87135

88-
```text
89-
make test
136+
```bash
137+
BRUTEFORCE=true LOG_LEVEL=debug python3 -m coverage run -m \
138+
pytest --verbose \
139+
-o log_cli=true \
140+
--log-cli-level=${LOG_LEVEL} \
141+
--full-trace src/
90142
```
91143

92-
### Enable all large BRUTEFORCE tests
144+
### Install and Run using make
93145

94-
Direct in host using a make:
146+
`make` tool is used to standardizes the commands for the same tasks
147+
across each sibling repository.
95148

96-
```text
97-
make test -e BRUTEFORCE=true
149+
Run tests (libraries are installed as dependency task in make):
150+
151+
```bash
152+
make test
98153
```
99154

100-
### Enable all DEBUG outputs
155+
Run tests with debug outputs:
101156

102-
```text
157+
```bash
103158
make test -e LOG_LEVEL=debug
104159
```
105160

106-
### Enable all large BRUTEFORCE tests and all DEBUG outputs
161+
Run brute-force tests with debug outputs:
107162

108-
```text
109-
make test -e LOG_LEVEL=debug -e BRUTEFORCE=true
163+
```bash
164+
make test -e BRUTEFORCE=true -e LOG_LEVEL=debug
110165
```
111166

112-
## Running with Docker 🐳
167+
Alternative way, use environment variables as prefix:
113168

114-
### Build a complete image with and run all tests
169+
```bash
170+
BRUTEFORCE=true LOG_LEVEL=debug make test
171+
```
115172

116-
Running container with testing (final) target.
173+
### Install and Running with Docker 🐳
117174

118-
Designed to store all application files and dependencies as a complete runnable image.
119-
Coverage results will be stored in host **/coverage** directory (mounted as volume).
175+
Build an image of the test stage.
176+
Then creates and ephemeral container an run tests.
120177

121-
```text
122-
# Build a complete image
123-
docker-compose build algorithm-exercises-py
124-
docker-compose run --rm algorithm-exercises-py make test coverage
178+
BRUTEFORCE and LOG_LEVEL environment variables are passing from current
179+
environment using docker-compose.
180+
181+
```bash
182+
docker-compose --profile testing run --rm algorithm-exercises-py-test
125183
```
126184

127-
### Enable BRUTEFORCE tests with full DEBUG output
185+
To change behavior using environment variables, you can pass to containers
186+
in the following ways:
128187

129-
With docker-compose:
188+
From host using docker-compose (compose.yaml) mechanism:
130189

131-
```text
132-
docker-compose --profile testing run --rm algorithm-exercises-py make test -e LOG_LEVEL=debug -e BRUTEFORCE=true
190+
```bash
191+
BRUTEFORCE=true LOG_LEVEL=debug docker-compose --profile testing run --rm algorithm-exercises-py-test
133192
```
134193

135-
Using make:
194+
Overriding docker CMD, as parameter of make "-e":
136195

137-
```text
138-
make docker/compose-run -e LOG_LEVEL=DEBUG -e BRUTEFORCE=true
196+
```bash
197+
docker-compose --profile testing run --rm algorithm-exercises-py-test make test -e LOG_LEVEL=DEBUG -e BRUTEFORCE=true
198+
```
199+
200+
### Install and Running with Docker 🐳 using make
201+
202+
```bash
203+
make compose/build
204+
make compose/test
205+
```
206+
207+
To pass environment variables you can use docker-compose
208+
or overriding CMD and passing to make as "-e" argument.
209+
210+
Passing environment variables using docker-compose (compose.yaml mechanism):
211+
212+
```bash
213+
BRUTEFORCE=true LOG_LEVEL=debug make compose/test
139214
```
140215

141-
### Build and run a development image
216+
## Development workflow using Docker / docker-compose
142217

143218
Running container with development target.
144-
Designed to develop on top of this image. All source application is mounted as
145-
a volume in **/app** directory.
146-
Dependencies should be installed to run (not present in this target) so, you
147-
must install dependencies before run (or after a dependency add/change).
219+
Designed for development workflow on top of this image.
220+
All source application is mounted as a volume in **/app** directory.
221+
Dependencies should be installed to run so, you must
222+
install dependencies before run (or after a dependency add/change).
148223

149-
```text
150-
# install dependencies using docker runtime and store them in host directory
151-
docker-compose build algorithm-exercises-py-dev
152-
docker-compose run --rm algorithm-exercises-py-dev make dependencies
153-
docker-compose run --rm algorithm-exercises-py-dev make test
224+
```bash
225+
# Build development target image
226+
docker-compose build --compress algorithm-exercises-py-dev
154227

228+
# Run ephemeral container and override CMD to run test
229+
docker-compose run --rm algorithm-exercises-py-dev python3 -m coverage run -m pytest --verbose src/
155230
```
156231

232+
## Run complete workflow (Docker + make)
233+
234+
Following command simulates a standarized pipeline across environments,
235+
using docker-compose and make.
236+
237+
```bash
238+
make compose/build && make compose/lint && make compose/test && make compose/run
239+
```
240+
241+
- Build all Docker stages and tag relevant images.
242+
- Run static analysis (lint) checks
243+
- Run unit tests
244+
- Run a "final" production ready image as a final container.
245+
Final "production" image just shows a minimal "production ready"
246+
build (with no tests).
247+
157248
## About development
158249

159250
Developed with runtime:
160251

161252
```text
162253
python3 --version
163-
Python 3.12.1
254+
Python 3.12.3
255+
```
256+
257+
258+
## Algorithm excersices sources
259+
260+
- [Leetcode](https://leetcode.com/) online platform for
261+
coding interview preparation.
262+
- [HackerRank](https://www.hackerrank.com/) competitive programming challenges
263+
for both consumers and businesses.
264+
- [Project Euler](https://projecteuler.net/) a series of computational problems
265+
intended to be solved with computer programs.
266+
267+
Use these answers to learn some tip and tricks for algorithms tests.
268+
269+
### Disclaimer. Why I publish solutions?
270+
271+
As Project Euler says:
272+
273+
<https://projecteuler.net/about#publish>
274+
275+
```text
276+
I learned so much solving problem XXX, so is it okay to publish my solution elsewhere?
277+
It appears that you have answered your own question. There is nothing quite like that "Aha!" moment when you finally beat a problem which you have been working on for some time. It is often through the best of intentions in wishing to share our insights so that others can enjoy that moment too. Sadly, that will rarely be the case for your readers. Real learning is an active process and seeing how it is done is a long way from experiencing that epiphany of discovery. Please do not deny others what you have so richly valued yourself.
278+
279+
However, the rule about sharing solutions outside of Project Euler does not apply to the first one-hundred problems, as long as any discussion clearly aims to instruct methods, not just provide answers, and does not directly threaten to undermine the enjoyment of solving later problems. Problems 1 to 100 provide a wealth of helpful introductory teaching material and if you are able to respect our requirements, then we give permission for those problems and their solutions to be discussed elsewhere.
164280
```
165281

282+
If you have better answers or optimal solutions, fork and PR-me
283+
284+
Enjoy 😁 !
285+
286+
## Status
287+
166288
### License
167289

168290
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bi.8713187.xyz%2Fsir-gon%2Fprojecteuler-py.svg?type=large)](https://app.fossa.com/projects/git%2Bi.8713187.xyz%2Fsir-gon%2Fprojecteuler-py?ref=badge_large)

0 commit comments

Comments
 (0)