mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 15:01:08 +00:00
Add Josephus Problem (#10928)
* Add Josephus Problem * Add iterative implementation of Josephus Problem * Add descriptive variable names * Update maths/josephus_problem.py * Update josephus_problem.py --------- Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
parent
67c85ee289
commit
be60f42a5f
130
maths/josephus_problem.py
Normal file
130
maths/josephus_problem.py
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
"""
|
||||||
|
The Josephus problem is a famous theoretical problem related to a certain
|
||||||
|
counting-out game. This module provides functions to solve the Josephus problem
|
||||||
|
for num_people and a step_size.
|
||||||
|
|
||||||
|
The Josephus problem is defined as follows:
|
||||||
|
- num_people are standing in a circle.
|
||||||
|
- Starting with a specified person, you count around the circle,
|
||||||
|
skipping a fixed number of people (step_size).
|
||||||
|
- The person at which you stop counting is eliminated from the circle.
|
||||||
|
- The counting continues until only one person remains.
|
||||||
|
|
||||||
|
For more information about the Josephus problem, refer to:
|
||||||
|
https://en.wikipedia.org/wiki/Josephus_problem
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def josephus_recursive(num_people: int, step_size: int) -> int:
|
||||||
|
"""
|
||||||
|
Solve the Josephus problem for num_people and a step_size recursively.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
num_people: A positive integer representing the number of people.
|
||||||
|
step_size: A positive integer representing the step size for elimination.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The position of the last person remaining.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If num_people or step_size is not a positive integer.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> josephus_recursive(7, 3)
|
||||||
|
3
|
||||||
|
>>> josephus_recursive(10, 2)
|
||||||
|
4
|
||||||
|
>>> josephus_recursive(0, 2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive(1.9, 2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive(-2, 2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive(7, 0)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive(7, -2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive(1_000, 0.01)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
>>> josephus_recursive("cat", "dog")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: num_people or step_size is not a positive integer.
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
not isinstance(num_people, int)
|
||||||
|
or not isinstance(step_size, int)
|
||||||
|
or num_people <= 0
|
||||||
|
or step_size <= 0
|
||||||
|
):
|
||||||
|
raise ValueError("num_people or step_size is not a positive integer.")
|
||||||
|
|
||||||
|
if num_people == 1:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return (josephus_recursive(num_people - 1, step_size) + step_size) % num_people
|
||||||
|
|
||||||
|
|
||||||
|
def find_winner(num_people: int, step_size: int) -> int:
|
||||||
|
"""
|
||||||
|
Find the winner of the Josephus problem for num_people and a step_size.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
num_people (int): Number of people.
|
||||||
|
step_size (int): Step size for elimination.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: The position of the last person remaining (1-based index).
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> find_winner(7, 3)
|
||||||
|
4
|
||||||
|
>>> find_winner(10, 2)
|
||||||
|
5
|
||||||
|
"""
|
||||||
|
return josephus_recursive(num_people, step_size) + 1
|
||||||
|
|
||||||
|
|
||||||
|
def josephus_iterative(num_people: int, step_size: int) -> int:
|
||||||
|
"""
|
||||||
|
Solve the Josephus problem for num_people and a step_size iteratively.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
num_people (int): The number of people in the circle.
|
||||||
|
step_size (int): The number of steps to take before eliminating someone.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: The position of the last person standing.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> josephus_iterative(5, 2)
|
||||||
|
3
|
||||||
|
>>> josephus_iterative(7, 3)
|
||||||
|
4
|
||||||
|
"""
|
||||||
|
circle = list(range(1, num_people + 1))
|
||||||
|
current = 0
|
||||||
|
|
||||||
|
while len(circle) > 1:
|
||||||
|
current = (current + step_size - 1) % len(circle)
|
||||||
|
circle.pop(current)
|
||||||
|
|
||||||
|
return circle[0]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
Loading…
Reference in New Issue
Block a user