diff --git a/logic_building_problems/collatz_conjecture.py b/logic_building_problems/collatz_conjecture.py new file mode 100644 index 000000000000..205cd628677b --- /dev/null +++ b/logic_building_problems/collatz_conjecture.py @@ -0,0 +1,40 @@ +""" +The Collatz Conjecture (3n + 1 Problem) +https://en.wikipedia.org/wiki/Collatz_conjecture +""" + + +def collatz_sequence(start_number: int) -> list[int]: + """ + Generates the Collatz sequence for a given starting number. + >>> collatz_sequence(6) + [6, 3, 10, 5, 16, 8, 4, 2, 1] + >>> collatz_sequence(1) + [1] + """ + if start_number <= 0: + return [] + + number = start_number + sequence = [number] + while number != 1: + if number % 2 == 0: + number = number // 2 + else: + number = 3 * number + 1 + sequence.append(number) + return sequence + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + try: + num = int(input("Enter a positive integer to start the Collatz sequence: ")) + if num > 0: + print(f"Sequence: {collatz_sequence(num)}") + else: + print("Please enter a positive integer.") + except ValueError: + print("Invalid input. Please enter an integer.") diff --git a/logic_building_problems/hangman.py b/logic_building_problems/hangman.py new file mode 100644 index 000000000000..70302b94695e --- /dev/null +++ b/logic_building_problems/hangman.py @@ -0,0 +1,54 @@ +""" +A classic word-guessing game: Hangman. +The computer picks a secret word, and the player tries to guess it letter by letter. +""" + +import random + + +def play_hangman() -> None: + """ + Starts an interactive session of Hangman. + This function is interactive and does not have a testable return value. + """ + words = ["python", "github", "algorithm", "developer", "computer"] + secret_word = random.choice(words) + guessed_letters = set() + incorrect_guesses = 0 + max_attempts = 6 + + print("Welcome to Hangman!") + + while incorrect_guesses < max_attempts: + # Display the current state of the word + display_word = "".join( + letter if letter in guessed_letters else "_" for letter in secret_word + ) + print(f"\nWord: {display_word}") + print(f"Incorrect guesses left: {max_attempts - incorrect_guesses}") + + if display_word == secret_word: + print(f"Congratulations! You guessed the word: {secret_word}") + return + + guess = input("Guess a letter: ").lower() + + if len(guess) != 1 or not guess.isalpha(): + print("Please enter a single letter.") + continue + + if guess in guessed_letters: + print("You already guessed that letter.") + elif guess in secret_word: + print("Good guess!") + guessed_letters.add(guess) + else: + print("Sorry, that letter is not in the word.") + incorrect_guesses += 1 + guessed_letters.add(guess) + + print(f"\nGame over! The word was: {secret_word}") + + +if __name__ == "__main__": + play_hangman() diff --git a/logic_building_problems/kaprekars_constant.py b/logic_building_problems/kaprekars_constant.py new file mode 100644 index 000000000000..15566a641466 --- /dev/null +++ b/logic_building_problems/kaprekars_constant.py @@ -0,0 +1,42 @@ +""" +Kaprekar's Constant (6174) +https://en.wikipedia.org/wiki/6174_(number) +""" + +KAPREKARS_CONSTANT = 6174 + + +def kaprekar_routine(four_digit_number: int) -> list[int]: + """ + Performs the Kaprekar routine and returns the sequence of numbers. + >>> kaprekar_routine(3524) + [3524, 3087, 8352, 6174] + """ + if not 1000 <= four_digit_number <= 9999: + raise ValueError("Input must be a four-digit number.") + if len(set(str(four_digit_number).zfill(4))) < 2: + raise ValueError("Input must have at least two different digits.") + + number = four_digit_number + sequence = [number] + while number != KAPREKARS_CONSTANT: + s_num = str(number).zfill(4) + desc_str = "".join(sorted(s_num, reverse=True)) + asc_str = "".join(sorted(s_num)) + number = int(desc_str) - int(asc_str) + sequence.append(number) + return sequence + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + try: + num = int( + input("Enter a 4-digit number (with at least two different digits): ") + ) + result_sequence = kaprekar_routine(num) + print(f"Sequence: {' -> '.join(map(str, result_sequence))}") + except ValueError as e: + print(f"Error: {e}") diff --git a/logic_building_problems/number_guessing_game.py b/logic_building_problems/number_guessing_game.py new file mode 100644 index 000000000000..21f60f60ed6b --- /dev/null +++ b/logic_building_problems/number_guessing_game.py @@ -0,0 +1,34 @@ +""" +A simple number guessing game. +The program generates a random number and the user has to guess it. +""" + +import random + + +def guessing_game(low: int, high: int) -> None: + """ + Starts an interactive number guessing game. + This function is interactive and does not have a return value for doctests. + """ + secret_number = random.randint(low, high) + attempts = 0 + print(f"I'm thinking of a number between {low} and {high}. Can you guess it?") + + while True: + try: + guess = int(input("Enter your guess: ")) + attempts += 1 + if guess < secret_number: + print("Too low! Try again.") + elif guess > secret_number: + print("Too high! Try again.") + else: + print(f"Congratulations! You guessed it in {attempts} attempts.") + break + except ValueError: + print("Invalid input. Please enter an integer.") + + +if __name__ == "__main__": + guessing_game(1, 100) diff --git a/logic_building_problems/rock_paper_scissors.py b/logic_building_problems/rock_paper_scissors.py new file mode 100644 index 000000000000..781eadd8216a --- /dev/null +++ b/logic_building_problems/rock_paper_scissors.py @@ -0,0 +1,46 @@ +""" +A simple, interactive Rock, Paper, Scissors game. +The user plays against the computer, which makes a random choice. +""" + +import random + + +def play_rock_paper_scissors() -> None: + """ + Starts an interactive session of Rock, Paper, Scissors. + This function is interactive and does not have a testable return value. + """ + options = ["rock", "paper", "scissors"] + + while True: + user_choice = input( + "Choose rock, paper, or scissors (or 'quit' to exit): " + ).lower() + + if user_choice == "quit": + print("Thanks for playing!") + break + + if user_choice not in options: + print("Invalid choice. Please try again.") + continue + + computer_choice = random.choice(options) + print(f"Computer chose: {computer_choice}") + + if user_choice == computer_choice: + print("It's a tie!") + elif ( + (user_choice == "rock" and computer_choice == "scissors") + or (user_choice == "scissors" and computer_choice == "paper") + or (user_choice == "paper" and computer_choice == "rock") + ): + print("You win!") + else: + print("You lose!") + print("-" * 20) + + +if __name__ == "__main__": + play_rock_paper_scissors()