기초 알고리즘 문제 풀이: 조합, 수학적 추론 및 주기성 분석

백전백계 문제 (100전으로 100마리 닭 구입)

한 마리의 수탉은 5전, 암탉은 3전, 병아리는 3마리에 1전이다. 총 100전을 사용해 정확히 100마리의 닭을 사야 할 때, 각각의 수탉, 암탉, 병아리 수를 구하는 문제다.

이 문제는 세 변수에 대한 방정식으로 표현할 수 있다:

  • x + y + z = 100 (총 수)
  • 5x + 3y + z/3 = 100 (총 비용)

여기서 x는 수탉, y는 암탉, z는 병아리 수다. 가능한 해는 유한하므로 완전 탐색이 가능하다. 하지만 반복 범위를 줄여 효율성을 높일 수 있다.

def solve_chickens():
    solutions = []
    for rooster in range(0, 21):        # 최대 100 / 5 = 20
        for hen in range(0, 34):       # 최대 100 / 3 ≈ 33
            chick = 100 - rooster - hen
            if chick % 3 != 0 or chick < 0:
                continue
            total_cost = 5 * rooster + 3 * hen + chick // 3
            if total_cost == 100:
                solutions.append((rooster, hen, chick))
    return solutions

result = solve_chickens()
for r, h, c in result:
    print(f"수탉: {r}, 암탉: {h}, 병아리: {c}")

도서 대출 조합 문제

서로 다른 5권의 책을 A, B, C 세 명의 아이에게 한 명당 한 권씩 나눠줄 때 가능한 모든 배분 방법의 수를 구하는 문제다.

이 경우, 순서가 중요하며 중복이 허용되지 않는다. 즉, A가 책 1을 선택하면 B와 C는 그 책을 선택할 수 없다. 이는 순열 문제로 볼 수 있으며, 전체 경우의 수는 P(5,3) = 5×4×3 = 60가지다.

모든 가능한 조합을 출력하려면 다음과 같이 구현할 수 있다:

def distribute_books():
    count = 0
    books = [1, 2, 3, 4, 5]
    for a_book in books:
        for b_book in books:
            if b_book == a_book:
                continue
            for c_book in books:
                if c_book == a_book or c_book == b_book:
                    continue
                print(f"A:{a_book}, B:{b_book}, C:{c_book}")
                count += 1
    print(f"총 조합 수: {count}")

distribute_books()

삼일 낚시 이틀 말리기 (주기성 판단 문제)

"삼일 낚시 이틀 말리기"란 속담처럼, 어떤 사람이 1990년 1월 1일부터 5일 주기로 3일은 낚시를 하고 2일은 그물 말리기를 한다고 가정하자. 특정 날짜에 그 사람이 낚시 중인지, 말리기 중인지를 판단하는 문제다.

풀이 전략:

  1. 기준일(1990-01-01)부터 입력일까지의 총 일수를 계산한다.
  2. 윤년 여부를 고려하여 월별 일수를 누적한다.
  3. 총 일수를 5로 나눈 나머지에 따라 상태를 결정한다: 나머지가 1, 2, 3이면 낚시, 4 또는 0이면 말리기.
def fishing_or_drying():
    target_year = int(input("년도 입력: "))
    target_month = int(input("월 입력: "))
    target_day = int(input("일 입력: "))

    if target_year < 1990:
        print("기준일 이후의 날짜를 입력하세요.")
        return

    days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    total_days = 0

    # 1990년부터 전년도까지의 날짜 합산
    for year in range(1990, target_year):
        if is_leap(year):
            total_days += 366
        else:
            total_days += 365

    # 올해의 월별 일수 합산
    for month in range(1, target_month):
        total_days += days_in_month[month]
        if month == 2 and is_leap(target_year):
            total_days += 1

    # 일 추가
    total_days += target_day

    # 상태 판별
    remainder = total_days % 5
    if remainder in [1, 2, 3]:
        print("낚시 중")
    else:
        print("그물 말리기 중")

def is_leap(year):
    return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

fishing_or_drying()

태그: 알고리즘 완전탐색 조합 윤년계산 주기성판단

6월 21일 19:03에 게시됨