NIRVANA

[level 1] 모의고사(240708 풀이방법 업데이트) 본문

Coding test(Python3)/Programmers

[level 1] 모의고사(240708 풀이방법 업데이트)

녜잉 2023. 8. 8. 23:37

문제

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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하는 값을 오름차순 정렬해주세요.

 

 

 

문제 풀이 접근법1

1) 학생들의 찍기 방법과 실제 답안의 길이를 비교하여, 길이가 다르다면 학생의 찍기 방법의 길이 만큼 답안을 더 추가한다.

2) 학생들의 찍기 방법과 실제 답안을 비교하여, 답이 같다면 count의 각자 value값을 1씩 올린다.

3) count에서 가장 높은 value의 key(학생)을 구한뒤 해당 학생을 rank 리스트에 추가한다.

4) 같은 등수의 학생이 있는 경우의 수를 고려하여, 가장 높은 value와 value값이 같고, rank에 없는 key(학생)를 찾아 추가한다.

def solution(answer):
    s_answer = [
    [1, 2, 3, 4, 5],
    [2, 1, 2, 3, 2, 4, 2, 5],
    [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
]

    match_answer = []

    count= {0:0, 1:0, 2:0}
    
    rank = []

    for i in range(len(s_answer)):
        match_answer.append(answer)



    for i in range(len(s_answer)):
    
    
        if len(s_answer[i]) != len(answer):
            for j in range(len(s_answer[i]) - len(match_answer[i])):
                match_answer[i] = match_answer[i] + answer[:len(s_answer[i]) - len(match_answer[i])]


    for i in range(len(s_answer)):
        for j in range(len(s_answer[i])):
        
            if s_answer[i][j] == match_answer[i][j]:
                count[i] += 1
                
    rank.append(max(count, key=count.get)+1)

    for key, value in count.items():
        if value == max(count) and key+1 not in rank:
            rank.append(key+1)


    return rank

장렬히...실패했다...

샘플 테스트 케이스는 맞았는데 14번 테스트를 제외하고 다 실패했다.

아 탐색 어려워...

 

 

문제 풀이 접근법2

문제에 answers의 길이가 5라고 나와 있지 않은데, 혹시 answers의 길이를 5라고 생각해서 그런건가? 라는 생각이 들었다. 따라서 if 문으로 answer의 길이보다 학생의 찍기 답안이 더 짧은 경우도 고려해봐야 할 것 같아서 추가했봤다. 또한 2차원 리스트로 하니까 너무 헷갈려서 딕셔너리로 바꿔서 도전해봤다.

 

def solution(answer):
    s_answer = {
    0:[1, 2, 3, 4, 5], 1:[2, 1, 2, 3, 2, 4, 2, 5], 2:[3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
}

    match_answer = {}

    count= {0:0, 1:0, 2:0}

    rank = []

    for i in range(len(s_answer)):
        match_answer[i] = answer


    for i in range(len(s_answer)):

    
        if len(s_answer[i]) > len(answer):
            for j in range(len(s_answer[i]) - len(match_answer[i])):
                match_answer[i] = match_answer[i] + answer[:len(s_answer[i]) - len(match_answer[i])]
            
        elif len(s_answer) < len(answer):
            for j in range(len(match_answer[i]) - len(s_answer[i])):
                tmp_lsit = s_answer[i]
                s_answer[i] = s_answer[i] + tmp_lsit[:len(match_answer[i]) - len(s_answer[i])]
    
    for i in range(len(s_answer)):
        for j in range(len(s_answer[i])):
        
            if s_answer[i][j] == match_answer[i][j]:
                count[i] += 1
            

    rank.append(max(count, key=count.get)+1)

    for key, value in count.items():
        if value == max(count) and key+1 not in rank:
            rank.append(key+1)

    return rank

 

2, 3, 4, 6, 10, 11, 12, 13번 케이스에서 실패했다.

반례를 생각해보니까

answer = [1, 4, 5, 2, 3] 일때 모두 1문제씩 맞추므로 [1, 2, 3]이 나와야 하는데 [1]만 나왔다.

 

 

문제 풀이 접근법3

생각해보니까 max(count)하면 걍 key값이 나와서 그런거였다. 따라서 딕셔너리의 value 중 큰 값과 같은 값을 확인하려면 max(count)가 아니라 max(count.value())여야 했다. 

def solution(answer):
    s_answer = {
    0:[1, 2, 3, 4, 5], 1:[2, 1, 2, 3, 2, 4, 2, 5], 2:[3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
}

    match_answer = {}

    count= {0:0, 1:0, 2:0}

    rank = []

    for i in range(len(s_answer)):
        match_answer[i] = answer


    for i in range(len(s_answer)):

    
        if len(s_answer[i]) > len(answer):
            for j in range(len(s_answer[i]) - len(match_answer[i])):
                match_answer[i] = match_answer[i] + answer[:len(s_answer[i]) - len(match_answer[i])]
            
        elif len(s_answer) < len(answer):
            for j in range(len(match_answer[i]) - len(s_answer[i])):
                tmp_lsit = s_answer[i]
                s_answer[i] = s_answer[i] + tmp_lsit[:len(match_answer[i]) - len(s_answer[i])]
    
    for i in range(len(s_answer)):
        for j in range(len(s_answer[i])):
        
            if s_answer[i][j] == match_answer[i][j]:
                count[i] += 1
            

    rank.append(max(count, key=count.get)+1)

    for key, value in count.items():
        if value == max(count.values()) and key+1 not in rank:
            rank.append(key+1)
    
    rank.sort()

    return rank

테스트 케이스 2, 3, 4에서 계속 오류남..내도 힘들다..

왜 오류 나는거지 내 코드는 존나 갓벽한데.....

 

 

문제 풀이 접근법4(성공!)

수학 시험의 답안과 학생들의 찍기 답안이 길이 만큼 계속 반복된다는 점을 이용하였다.

mod를 사용해서 i번째 문제에 대한 값을 가져와 비교하도록 변경하였다. 

1) 학생들의 찍기 답안을 저장하고 있는 딕셔너리 s_answer와 학생들의 점수를 기록할 count 딕셔너리를 선언한다.

2) 학생들의 수만큼 첫번째 for문을, answer의 길이만큼 두번째 반복문을 돌면서 i번째 문제에 대한 학생들의 답안과 i번째 문제에 대한 실제 답안을 비교한다.

3) 만약 답안이 실치하다면 학생의 count를 +1한다. 

4) 가장 높은 value값을 갖고, rank 리스트에 기록되지 않은 키가 있다면 해당 키를 rank 리스트에 추가한다.

5) rank 리스트 반환

def solution(answer):
    s_answer = {
    0:[1, 2, 3, 4, 5], 1:[2, 1, 2, 3, 2, 4, 2, 5], 2:[3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
}

    count = {0:0, 1:0, 2:0}


    rank = []

    for i in range(len(s_answer)):
    
        for j in range(len(answer)):
            if s_answer[i][j % len(s_answer[i])] == answer[j % len(answer)]:
                count[i] +=1
            
    for key, value in count.items():
        if value == max(count.values()) and key+1 not in rank:
            rank.append(key+1)
            
    return rank

풀었지만...여전히 왜 위의 3번 접근법에서는 실패했는지 몰겠음...

다시 고민해봐야겠죠 뭐

 

 

문제 풀이 접근법5

1) 학생들의 찍기 방법을 딕셔너리로 정의한다.

2) 맞은 개수와, 해당 개수 만큼 맞춘 학생 저장할 딕셔너리 rank를 선언한다.

3) answer의길이와 맞추기 위해 sol의 길이를 i만큼나눈 나머지 값을 인덱스로 하는 원소 값을 리스트에 추가 해준다. 

4) 맞은개수를 inco에 저장한다.

5) inco를 키값으로, 해당 개수만큼 맞춘 학생을 value 리스트에 저장한다. 

from collections import defaultdict

def solution(answer):  
    s ={
        1:[1, 2, 3, 4, 5],
        2:[ 2, 1,2, 3, 2, 4, 2, 5],
        3:[3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
    }
    
    rank = defaultdict(list)
    
    for student, sol in s.items():
        
        ex_sol =[sol[i % len(sol)] for i in range(len(answer))]
        
        inco = sum(1 for a, b in zip(ex_sol, answer) if a == b)
        rank[inco].append(student)
        
    
    return rank[max(rank)]

 


index(): https://jkim83.tistory.com/159

 

[Python] 파이썬 리스트에서 최소값, 최대값과 인덱스 구하기

숫자형으로 이루어진 리스트에서 최소값, 최대값과 해당 값의 리스트 인덱스를 구하는 방법입니다. 최소값, 최대값 구하기 우선 아래와 같이 숫자형으로 이루어진 리스트를 생성하겠습니다. ite

jkim83.tistory.com

 

'Coding test(Python3) > Programmers' 카테고리의 다른 글

[level 1] 소수 찾기(에라토스테네스의 체 다시)  (0) 2023.08.09
[level 1] 소수 만들기  (0) 2023.08.09
[level 1] 과일 장수  (0) 2023.08.04
[level 1] 카드 뭉치  (0) 2023.08.04
[level 1] 폰켓몬  (0) 2023.08.02