백준 코딩테스트/완전탐색(Brute force)

프로그래머스: 모의고사 (8 / 25)

monkeykim 2024. 10. 10. 23:55

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...

2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...

3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 조건

  • 시험은 최대 10,000 문제로 구성되어있습니다.
  • 문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
  • 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

입출력 예

answers return

[1,2,3,4,5] [1]
[1,3,2,4,2] [1,2,3]

입출력 예 설명

입출력 예 #1

  • 수포자 1은 모든 문제를 맞혔습니다.
  • 수포자 2는 모든 문제를 틀렸습니다.
  • 수포자 3은 모든 문제를 틀렸습니다.

따라서 가장 문제를 많이 맞힌 사람은 수포자 1입니다.

입출력 예 #2

  • 모든 사람이 2문제씩을 맞췄습니다.

코드

def solution(answers):
    num1 = [1, 2, 3, 4, 5]
    num2 = [2, 1, 2, 3, 2, 4, 2, 5]
    num3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]

    count1, count2, count3 = 0, 0, 0

    for i in range(len(answers)):
        if answers[i] == num1[i % len(num1)]:
            count1 += 1
        if answers[i] == num2[i % len(num2)]:
            count2 += 1
        if answers[i] == num3[i % len(num3)]:
            count3 += 1

    answer_dict = {
        1: count1,
        2: count2,
        3: count3
    }
    max_num = max(answer_dict.values())
    answer = [key for key, val in answer_dict.items() if val == max_num]

    return answer

코드 풀이

  1. 1번, 2번, 3번 수포자가 찍는 방식의 패턴이 정해져 있다. 따라서 num1, num2, num3으로 찍는 패턴을 초기화 한다.
  2. count1, count2, count3을 각 0으로 초기화 해준다.
  3. 문제의 정답은 배열에 담겨 함수의 input으로 주어진다. 해당 문제의 정답의 길이만큼 반복을 돌리며, 1번. 2번, 3번의 수포자가 찍은 번호와 일치한지 아닌지를 비교한다.
    • 일치한다면 count를 높인다.
    • answers[i] == num1[i % len(num1)]:
      • 이 부분에서 num[i % len(num)] 으로 진행한 이유는 index 에러가 발생하기 때문이다. (이것 때문에 틀림)
      • 예를들어, answers의 길이가 10인 배열이 있을 때, num1의 길이는 5이므로, i가 6이 넘어온다면 num[6]은 찾을 수 없기 때문에 index 에러가 발생한다.
      • 따라서, i % len(num1)을 해주면 6 % 5 는 1이므로 다시 1 index 부터 확인할 수 있게 된다.
  4. answer_dict로 초기화를 하며, key의 value로는 count를 해준다.
    • 출력 예시가 단순히 숫자이므로 일반 변수로 만들 수 없다. 따라서 dict의 key로 만들어준 것.
  5. max(answer_dict.value())를 사용하여 해당 dict의 value 중 가장 큰 값을 뽑아내고, 동일한 값이 있다면 같은 값을 출력해야 하므로 for loop를 진행하면서 max_num과 동일한 value의 key를 list에 담아준다.

핵심 포인트

  1. Brute force 알고리즘을 사용하여 완전탐색을 진행한다.
    • 완전 탐색 알고리즘은 2가지로 풀 수 있는데, loop와 재귀함수이다.
    • 단순한 문제는 loop를 사용하고 복잡한 문제는 재귀를 사용한다.
  2. 가장 많이 맞힌 수포자를 찾는 방법
    • 숫자를 변수로 지정할 수 없다. 따라서 dict를 초기화해주고 각 key에 1, 2, 3을 지정해주고 value에는 count를 지정한다.
    • dict.values() 를 통해 dict_values 객체를 리턴하고 max() 를 사용해 가장 큰 값을 출력한다.
    • 그리고 동일한 값을 가진 key도 같이 출력하기 위해 for loop를 사용한다.
      • answer = [key for key, val in answer_dict.items() if max_num == val]