[kata][python] 프로그래머스 - 모의고사
- 6 mins#
출처: 프로그래머스 - 모의고사
문제
수포자는 수학을 포기한 사람의 준말입니다.
수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다.
수포자는 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
수포자 1은 [1, 4]번 문제를 맞혔습니다.
수포자 2는 다섯 번째 문제를 맞혔습니다
내 풀이
1 from itertools import cycle
2
3 def solution(answers):
4 winner = []
5 pattern_supo_1 = [1 ,2, 3, 4, 5]
6 pattern_supo_2 = [2, 1, 2, 3, 2, 4, 2, 5]
7 pattern_supo_3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
8 score_supo = [0, 0, 0]
9
10 for supo_1, supo_2, supo_3, answer in zip(cycle(pattern_supo_1), cycle(pattern_supo_2), cycle(pattern_supo_3), answers):
11 if supo_1 == answer: score_supo[0] += 1
12 if supo_2 == answer: score_supo[1] += 1
13 if supo_3 == answer: score_supo[2] += 1
14
15 for i, score in enumerate(score_supo):
16 if score == max(score_supo):
17 winner.append(i+1)
18
19 return winner
(5~7) 수포자들의 문제 찍는 패턴을 각각의 리스트에 담아둔다.
(8) 수포자들의 점수를 체크할 길이 3짜리 배열을 만들고, 0점으로 초기화한다.
이제부터는 이러나 저러나 for문을 돌면서 실제 정답과 수포자들이 찍은 답을 비교해야한다.
이 때, 수포자들이 문제를 찍는 반복되는 패턴을 자동으로 계속 돌려줄 수 있는 방법이 없을까?
라는 의문이 들어 찾아보니 itertools에 cycle이라는 녀석이 있길래 한 번 써봤다.
특정 반복 가능한 객체를 cycle에 넣어주면, 다음과 같이 사용할 수 있다.
>>> a = [1, 3, 5]
>>> cycle_a = cycle(a)
>>> next(cycle_a)
1
>>> next(cycle_a)
3
>>> next(cycle_a)
5
>>> next(cycle_a)
1
>>> next(cycle_a)
3
>>> next(cycle_a)
5
(10~13) 어쨌든 이것을 좀 응용해서 세 개의 패턴을 모두 cycle화 시킨 후, zip으로 묶어 for문에 넣었다.
그리고 각각이 찍은 답이 실제 정답과 맞으면 각각의 score에 1씩 더해주었다.
(15~19) 이제 최종 스코어가 나왔으니, 점수가 가장 높은 사람의 번호를 winner 리스트에 넣어서 리턴해준다.
(왠지 10번 라인에서 PEP8의 한 줄 문자길이(79) 컨벤션을 어긴 것 같은 느낌이 들긴 하지만, 그냥 넘어가도록 하자.)
다른사람 풀이
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)]
기본적인 로직은 내가 해결한 방식과 동일하다고 보면 되고,
‘문제 번호를 각자의 패턴 길이로 나눈 나머지’를 각자의 패턴 인덱스로 사용함으로써 센스있게 해결했다.
분석
최근엔 파이썬의 숨겨진(나만 몰랐던)기능을 찾아 쓰는데 한참 재미를 느끼고있다.
특히 operator, itertools, functools 같은 모듈에는 뭔가
“자주 사용하는데 굳이 모듈까지 찾아 쓸 정도로 복잡하지는 않아서 그냥 구현했었던” 기능이 꽤 있었다.
물론 모듈을 제공하지 않는다면 본인이 직접 구현해서 쓸 수 있는 내공은 있어야하겠지만,
누누이 말하듯 알고 안쓰는것과 몰라서 못쓰는것은 완전히 다른 문제이다.
그리고 대부분은 직접 구현한 알고리즘보다 내장 모듈이 성능면에서 좋은 경우가 대부분이었다.
뜬금없는데, 작년에 젤다의 전설이라는 게임을 엄청 재밌게 했던 기억이 있다.
맨몸으로 길거리에서 막대기를 하나 주워 끝판왕을 바로 잡을수도 있는 매우 자유도가 높은 게임인데,
사실 상황에 알맞은 스킬이나 아이템, 지형지물등을 적절히 사용하면 훨씬 더 쉽고 재밌게 즐길 수 있다.
보통 게임을 거의 100% 마스터한, 이른바 “고인물”들이 “맨몸 막대기”같은 플레이를 하는데,
파이썬에서 다양하고 재밌는 모듈을 알고있지만 직접 효율적인 알고리즘을 구현하는 것과 비슷한 맥락이 아닐까 싶다.
물론 나는 아직 파이썬 맨몸 입문자이고, 그 발끝에도 미치지 못한다.
최근에 파이썬으로 코딩을하면서 가끔씩 젤다같은 자유도 높은 게임을 하는 느낌이 들곤 하는데,
하루빨리 병원에 가봐야겠다