코딩테스트 연습 > 완전탐색 > 모의고사

2019. 12. 26. 11:52Algorithm/python3

[모의고사] 문제 펼치기

더보기

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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):
    a = [1,2,3,4,5]
    b = [2,1,2,3,2,4,2,5]
    c = [3,3,1,1,2,2,4,4,5,5]
    
    aCount = 0
    bCount = 0
    cCount = 0
    
    aAnswersIdx = 0
    bAnswersIdx = 0
    cAnswersIdx = 0
    for num in answers:
        if num == a[aAnswersIdx]:
            aCount += 1
        aAnswersIdx += 1
        if aAnswersIdx == len(a):
            aAnswersIdx = 0
    for num in answers:
        if num == b[bAnswersIdx]:
            bCount += 1
        bAnswersIdx += 1
        if bAnswersIdx == len(b):
            bAnswersIdx = 0
    for num in answers:
        if num == c[cAnswersIdx]:
            cCount += 1
        cAnswersIdx += 1
        if cAnswersIdx == len(c):
            cAnswersIdx = 0
        
    resultList = [aCount, bCount, cCount]
    
    m = max(resultList)
    answer = [(i+1) for i, j in enumerate(resultList) if j == m]
    
    return answer

내가 풀이한 답이다.
다풀고 다른 풀이들을 보니 너무 허접한 풀이 인것 같다.
일단
파이썬에서 배열의 반복문을 사용할 때, 인덱스를 사용하는 여러 방법이 있는데 그걸 전혀 모르고 있는 상황이였다.
가장 깔끔한 방법이 마지막 리스트 컴프리헨션 부분에서 사용한 enumerate() 함수이다.
인덱스와, 해당 인덱스의 값을 반복문을 돌면서 리턴하는 함수인데, 이 문제를 풀때는 리스트 컴프리헨션의 문법을 검색했을때 사용법을 모른체 같이 사용을 하게 됐다.

또 다른 방법은 range()함수를 이용한 반복문이다.

for num in range(startIdx, lastIdx):
	print(num + " : " + list[num])

와 같이 인덱스를 임의로 지정하여 사용하는것도 가능하다.  ( range(0,5) => [0,1,2,3,4] 리스트 반환 )

def solution(answers):
    p = [[1, 2, 3, 4, 5],
         [2, 1, 2, 3, 2, 4, 2, 5],
         [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]]
    s = [0] * len(p)

    for q, a in enumerate(answers):
        for i, v in enumerate(p):
            if a == v[q % len(v)]:
                s[i] += 1
    return [i + 1 for i, v in enumerate(s) if v == max(s)]

같은 문제를 풀이한 부분인데 많은것을 배울수 있었다.

일단

1번, 2번, 3번 수포자의 찍는 방식을 2차원 리스트로 초기화하여 한번의 반복문으로 끝낼수 있게 한 것과,

s = [0] * len(p)

 

 

이와 같이 [0] * 5 를 하게되면 [0, 0, 0, 0, 0] 와 같은 리스트가 만들어 진다는 것,

if a == v[q % len(v)]:

와 같이 나누기 연산자 (%) 를 사용해 리스트 반복을 처리한 것,
(나는 len(v) 마다 인덱스를 직접 0으로 초기화 해주는 무식한 방법을 사용)

다중 반복문을 이용하여 answer 리스트 (모의고사 문제의 정답) 과
1번, 2번, 3번 수포자의 답안을 일일히 모두 비교하는 완전 탐색 알고리즘을 사용한 풀이로써 좋은 답안이라고 생각된다.

from itertools import cycle

이 모듈을 이용한 풀이들도 여럿 보이는데
데이터 분석에 매우 유용한 모듈이라고 한다. 기회가 되면 공부를 해봐야 겠다.