Skip to content

Commit 01cc7bc

Browse files
authored
Merge pull request #51 from ikostan/main
Merge from master
2 parents fb0fcfe + c7ab848 commit 01cc7bc

File tree

98 files changed

+5808
-232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+5808
-232
lines changed

.github/workflows/pylint.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Pylint
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.12"]
15+
steps:
16+
- uses: actions/checkout@v4
17+
- name: Set up Python ${{ matrix.python-version }}
18+
uses: actions/setup-python@v3
19+
with:
20+
python-version: ${{ matrix.python-version }}
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install pylint
25+
pip install -r requirements.txt
26+
- name: Analysing the code with pylint
27+
run: |
28+
python -m pylint --verbose $(find . -name "*.py" ! -path "*/.venv/*" ! -path "*/venv/*") --rcfile=.pylintrc

.github/workflows/pytest.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Pytest Workflow
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python 3.12
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: '3.12'
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install -r requirements.txt
26+
pip install pytest
27+
28+
- name: Run pytest
29+
run: pytest --verbose --ignore=solutions

.github/workflows/ruff.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Ruff Lint and Format
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
ruff:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- name: Set up Python 3.12
15+
uses: actions/setup-python@v5
16+
with:
17+
python-version: '3.12'
18+
- name: Install Ruff
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install -r requirements.txt
22+
- name: Run Ruff lint
23+
run: ruff check --output-format=github .
24+
- name: Run Ruff format check
25+
run: ruff format --check .

.pylintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[MASTER]
2+
ignore=.venv
3+
ignore-paths=^(.*/|)solutions/.*$

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
1-
# Exercism Python Track
1+
# [Exercism Python Track](https://exercism.io/my/tracks/python)
22

3-
Learn and master concepts to achieve fluency in Python.
3+
[![Pytest Workflow](https://github.com/ikostan/python/actions/workflows/pytest.yml/badge.svg)](https://github.com/ikostan/python/actions/workflows/pytest.yml)
4+
[![Pylint](https://github.com/ikostan/python/actions/workflows/pylint.yml/badge.svg)](https://github.com/ikostan/python/actions/workflows/pylint.yml)
5+
[![Ruff Lint and Format](https://github.com/ikostan/python/actions/workflows/ruff.yml/badge.svg)](https://github.com/ikostan/python/actions/workflows/ruff.yml)
6+
7+
<div align="center">
8+
<img width="9%" height="9%" src="https://github.com/ikostan/Exercism_Python_Track/blob/master/img/python-track.png" hspace="20">
9+
</div>
10+
11+
## Exercism exercises in Python
12+
13+
### About Exercism
14+
Exercism is an online platform designed to help you improve your coding skills through practice and mentorship.
15+
16+
Exercism provides you with thousands of exercises spread across numerous language tracks. Once you start a language track you are presented with a core set of exercises to complete. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language.
17+
18+
You complete a challenge by downloading the exercise to your computer and solving it in your normal working environment. Once you've finished you submit it online and one of our mentors will give you feedback on how you could improve it using features of the language that you may not be familiar with. After a couple of rounds of refactoring, your exercise will be complete and you will unlock both the next core exercise and also a series of related side-exercises for you to practice with.
19+
20+
Exercism is entirely open source and relies on the contributions of thousands of wonderful people.
21+
22+
Exercism is designed to be fun and friendly, and we place a strong emphasis on empathetic communication.
23+
24+
Sign up and have fun. Exercism is 100% free :)
425

5-
143 coding exercises for Python on Exercism. From Error Handling to ISBN Verifier.

armstrong-numbers/armstrong_numbers_test.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
# pylint: disable=C0301
2+
"""
3+
Armstrong Numbers Test Suite Documentation
4+
5+
## Overview
6+
7+
This test suite validates the `is_armstrong_number` function,
8+
ensuring its correct behavior for various types of numbers:
9+
10+
- Single-digit and multi-digit numbers
11+
- Known Armstrong numbers and non-Armstrong numbers
12+
13+
Tests are auto-generated based on canonical data from
14+
[Exercism problem specifications](https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json).
15+
16+
## Structure
17+
18+
- **Framework:** Uses Python's built-in `unittest`.
19+
- **Target Function:** `is_armstrong_number` (imported from `armstrong_numbers` module).
20+
21+
## Test Cases
22+
23+
| Test Description | Input | Expected Output |
24+
|---------------------------------------------------------|----------|-----------------|
25+
| Zero is an Armstrong number | 0 | `True` |
26+
| Single-digit numbers are Armstrong numbers | 5 | `True` |
27+
| No two-digit numbers (e.g. 10) are Armstrong numbers | 10 | `False` |
28+
| 153 is an Armstrong number | 153 | `True` |
29+
| 100 is not an Armstrong number | 100 | `False` |
30+
| 9474 is an Armstrong number | 9474 | `True` |
31+
| 9475 is not an Armstrong number | 9475 | `False` |
32+
| 9926315 is an Armstrong number | 9926315 | `True` |
33+
| 9926314 is not an Armstrong number | 9926314 | `False` |
34+
35+
## Usage
36+
37+
To run the tests, ensure `is_armstrong_number` is implemented and run:
38+
39+
```bash
40+
python -m unittest armstrong_numbers_test.py
41+
42+
"""
43+
144
# These tests are auto-generated with test data from:
245
# https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json
346
# File last updated on 2023-07-20
@@ -10,29 +53,88 @@
1053

1154

1255
class ArmstrongNumbersTest(unittest.TestCase):
56+
"""Armstrong Numbers Test."""
57+
1358
def test_zero_is_an_armstrong_number(self):
59+
"""
60+
Test that zero is correctly identified as an Armstrong number.
61+
62+
This test verifies that the function correctly determines that 0
63+
is an Armstrong number, as 0^1 == 0.
64+
65+
:returns: None
66+
:rtype: NoneType
67+
"""
1468
self.assertIs(is_armstrong_number(0), True)
1569

1670
def test_single_digit_numbers_are_armstrong_numbers(self):
71+
"""
72+
Test that all single digit numbers are Armstrong numbers.
73+
74+
:returns: None. Asserts that a single digit number (e.g., 5) is an Armstrong number.
75+
:rtype: NoneType
76+
"""
1777
self.assertIs(is_armstrong_number(5), True)
1878

1979
def test_there_are_no_two_digit_armstrong_numbers(self):
80+
"""
81+
Test that no two-digit numbers are Armstrong numbers.
82+
83+
:returns: None. Asserts that a two-digit number (e.g., 10) is not an Armstrong number.
84+
:rtype: NoneType
85+
"""
2086
self.assertIs(is_armstrong_number(10), False)
2187

2288
def test_three_digit_number_that_is_an_armstrong_number(self):
89+
"""
90+
Test that 153 is correctly identified as an Armstrong number.
91+
92+
:returns: None. Asserts that 153 is an Armstrong number.
93+
:rtype: NoneType
94+
"""
2395
self.assertIs(is_armstrong_number(153), True)
2496

2597
def test_three_digit_number_that_is_not_an_armstrong_number(self):
98+
"""
99+
Test that 100 is not identified as an Armstrong number.
100+
101+
:returns: None. Asserts that 100 is not an Armstrong number.
102+
:rtype: NoneType
103+
"""
26104
self.assertIs(is_armstrong_number(100), False)
27105

28106
def test_four_digit_number_that_is_an_armstrong_number(self):
107+
"""
108+
Test that 9474 is correctly identified as an Armstrong number.
109+
110+
:returns: None. Asserts that 9474 is an Armstrong number.
111+
:rtype: NoneType
112+
"""
29113
self.assertIs(is_armstrong_number(9474), True)
30114

31115
def test_four_digit_number_that_is_not_an_armstrong_number(self):
116+
"""
117+
Test that 9475 is not identified as an Armstrong number.
118+
119+
:returns: None. Asserts that 9475 is not an Armstrong number.
120+
:rtype: NoneType
121+
"""
32122
self.assertIs(is_armstrong_number(9475), False)
33123

34124
def test_seven_digit_number_that_is_an_armstrong_number(self):
125+
"""
126+
Test that 9926315 is correctly identified as an Armstrong number.
127+
128+
:returns: None. Asserts that 9926315 is an Armstrong number.
129+
:rtype: NoneType
130+
"""
35131
self.assertIs(is_armstrong_number(9926315), True)
36132

37133
def test_seven_digit_number_that_is_not_an_armstrong_number(self):
134+
"""
135+
Test that 9926314 is not identified as an Armstrong number.
136+
137+
:returns: None. Asserts that 9926314 is not an Armstrong number.
138+
:rtype: NoneType
139+
"""
38140
self.assertIs(is_armstrong_number(9926314), False)

black-jack/black_jack.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ def value_of_card(card) -> int:
1717
2. 'A' (ace card) = 1
1818
3. '2' - '10' = numerical value.
1919
"""
20-
if card in 'JKQ':
20+
if card in "JKQ":
2121
return 10
22-
elif card == 'A':
22+
23+
if card == "A":
2324
return 1
2425

2526
return int(card)
@@ -29,16 +30,19 @@ def higher_card(card_one, card_two) -> str | tuple[str, str]:
2930
"""
3031
Determine which card has a higher value in the hand.
3132
32-
:param card_one, card_two: str - cards dealt in hand. See below for values.
33-
:return: str or tuple - resulting Tuple contains both cards if they are of equal value.
33+
:param card_one: str - cards dealt in hand. See below for values.
34+
:param card_two: str - cards dealt in hand. See below for values.
35+
:return: str or tuple - resulting Tuple contains both cards if
36+
they are of equal value.
3437
3538
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
3639
2. 'A' (ace card) = 1
3740
3. '2' - '10' = numerical value.
3841
"""
3942
if value_of_card(card_one) == value_of_card(card_two):
4043
return card_one, card_two
41-
elif value_of_card(card_one) > value_of_card(card_two):
44+
45+
if value_of_card(card_one) > value_of_card(card_two):
4246
return card_one
4347

4448
return card_two
@@ -56,11 +60,14 @@ def value_of_ace(card_one, card_two) -> int:
5660
3. '2' - '10' = numerical value.
5761
"""
5862
total: int = value_of_card(card_one) + value_of_card(card_two)
59-
# Hint: if we already have an ace in hand, then the value for the upcoming ace would be 1.
60-
if card_one == 'A' or card_two == 'A':
63+
# Hint: if we already have an ace in hand, then the value for
64+
# the upcoming ace would be 1.
65+
if card_one == "A" or card_two == "A":
6166
return 1
62-
# The value of the hand with the ace needs to be as high as possible without going over 21.
63-
elif 21 - total >= 11:
67+
# The value of the hand with the ace needs to be as high as
68+
# possible without going over 21.
69+
70+
if 21 - total >= 11:
6471
return 11
6572

6673
return 1
@@ -70,7 +77,10 @@ def is_blackjack(card_one, card_two) -> bool:
7077
"""
7178
Determine if the hand is a 'natural' or 'blackjack'.
7279
73-
:param card_one, card_two: str - card dealt. See below for values.
80+
:param card_one: card dealt. See below for values.
81+
:type card_one: str
82+
:param card_two: card dealt. See below for values.
83+
:type card_two: str
7484
:return: bool - is the hand is a blackjack (two cards worth 21).
7585
7686
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
@@ -79,9 +89,10 @@ def is_blackjack(card_one, card_two) -> bool:
7989
"""
8090
# If a player is dealt an ace (A) and a ten-card (10, K, Q, or J)
8191
# as their first two cards, then the player has a score of 21.
82-
if card_one == 'A' and card_two in ('J', 'Q', 'K', '10'):
92+
if card_one == "A" and card_two in ("J", "Q", "K", "10"):
8393
return True
84-
elif card_two == 'A' and card_one in ('J', 'Q', 'K', '10'):
94+
95+
if card_two == "A" and card_one in ("J", "Q", "K", "10"):
8596
return True
8697

8798
return False
@@ -91,8 +102,10 @@ def can_split_pairs(card_one, card_two) -> bool:
91102
"""
92103
Determine if a player can split their hand into two hands.
93104
94-
:param card_one, card_two: str - cards dealt.
95-
:return: bool - can the hand be split into two pairs? (i.e. cards are of the same value).
105+
:param card_one: str - cards dealt.
106+
:param card_two: str - cards dealt.
107+
:return: bool - can the hand be split into two pairs?
108+
(i.e. cards are of the same value).
96109
"""
97110
if value_of_card(card_one) == value_of_card(card_two):
98111
return True
@@ -104,7 +117,9 @@ def can_double_down(card_one, card_two) -> bool:
104117
"""
105118
Determine if a blackjack player can place a double down bet.
106119
107-
:param card_one, card_two: str - first and second cards in hand.
108-
:return: bool - can the hand can be doubled down? (i.e. totals 9, 10 or 11 points).
120+
:param card_one: str - first and second cards in hand.
121+
:param card_two: str - first and second cards in hand.
122+
:return: bool - can the hand can be doubled down?
123+
(i.e. totals 9, 10 or 11 points).
109124
"""
110125
return 9 <= value_of_card(card_one) + value_of_card(card_two) <= 11

0 commit comments

Comments
 (0)