https://school.programmers.co.kr/learn/courses/30/lessons/118666

문제

질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가 각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가 매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return 하도록 solution 함수를 완성해주세요.

풀이

내가 생각한 알고리즘

  1. 해시로 키-밸류 미리 저장해 키값으로 조회 후, 점수 올리기
  2. 2개씩 비교하여 정답 문자열 만들기

정답 코드

def solution(survey, choices):
    answer = ''
    table = {'R': 0, 'T': 0, 'C': 0, 'F': 0, 'M': 0, 'J': 0, 'A': 0, 'N': 0}
    
    for i in range(len(survey)):
        if choices[i] > 4:
            table[survey[i][1]] += choices[i] - 4
        elif choices[i] < 4:
            table[survey[i][0]] += 4 - choices[i]
    
    if table['R'] >= table['T']:
        answer += 'R'
    else:
        answer += 'T'
    
    if table['C'] >= table['F']:
        answer += 'C'
    else:
        answer += 'F'
        
    if table['J'] >= table['M']:
        answer += 'J'
    else:
        answer += 'M'
            
    if table['A'] >= table['N']:
        answer += 'A'
    else:
        answer += 'N'
            
    return answer
  1. 'table'이라는 딕셔너리를 생성합니다. 이 딕셔너리는 각 성격 유형('R', 'T', 'C', 'F', 'M', 'J', 'A', 'N')에 대한 카운트를 저장합니다. 초기에 모든 카운트는 0으로 설정됩니다.

  2. 'survey' 리스트와 'choices' 리스트를 반복하면서 각 사람이 선택한 성격 유형과 해당 선택에 대한 점수를 확인합니다.

  3. 점수가 4보다 크면, 해당 성격 유형의 두 번째 글자를 딕셔너리 키로 사용하여 점수에서 4를 뺀 값을 해당 성격 유형의 카운트에 더합니다.

  4. 점수가 4보다 작으면, 해당 성격 유형의 첫 번째 글자를 딕셔너리 키로 사용하여 4에서 점수를 뺀 값을 해당 성격 유형의 카운트에 더합니다.

  5. 딕셔너리를 사용하여 각 성격 유형의 카운트를 비교하고, 더 높은 카운트를 가진 성격 유형을 결과 문자열 'answer'에 추가합니다.

  6. 'answer'를 반환합니다.

Lesson Learn

파이썬 문법

  1. 딕셔너리 활용
  • 키-값 쌍 : 사전을 사용하면 데이터를 키-값 쌍으로 저장할 수 있습니다. 이 경우 성격 유형(예: 'R', 'T', 'C' 등)을 키로 사용하고 개수 또는 점수를 값으로 사용할 수 있습니다. 이 페어링을 사용하면 각 성격 유형의 개수를 쉽게 검색하고 조작할 수 있습니다.
  • 효율적인 조회 : 사전 조회는 일반적으로 목록을 통한 검색보다 더 효율적이며, 특히 대규모 데이터세트를 처리할 때 더욱 그렇습니다. Python 사전은 빠른 평균 사례 조회 시간을 제공하는 해시 테이블을 사용하여 구현됩니다.

딕셔너리 활용법 다시한번 정리

부끄럽지만 딕셔너리 선언 방법이 생각이 나지 않아서 리스트로 아주 꼬아서 문제를 풀었었다.
딕셔너리 활용법을 다시한번 정리해보겠다.

파이썬에서 딕셔너리는 중괄호 {}로 묶인 키-값 쌍의 집합입니다. 각 키는 콜론 :으로 해당하는 값과 구분됩니다. 기본적인 구문은 다음과 같습니다:

my_dict = {'키1':1, '키2':2, ...}
  • 딕셔너리 내의 각 키는 고유해야 합니다.
  • 각 키에 해당하는 값은 어떤 데이터 형식이든 될 수 있으며, 서로 다른 키는 서로 다른 형식의 값을 가질 수 있습니다.
  • 키는 문자열, 숫자 또는 튜플과 같은 불변 데이터 형식이어야 합니다.

문제에 딕셔너리를 적용하는 방법은 다음과 같습니다:

table = {'R': 0, 'T': 0, 'C': 0, 'F': 0, 'M': 0, 'J': 0, 'A': 0, 'N': 0}

위 코드는 'R', 'T', 'C', 'F', 'M', 'J', 'A', 'N'과 같은 성격 유형을 키로 하고, 초기에는 해당하는 값이 모두 0으로 설정된 딕셔너리인 'table'을 생성합니다.

그런 다음 키를 사용하여 딕셔너리의 값을 업데이트하거나 가져올 수 있습니다. 예를 들어:

table['R'] += 1

위 코드는 'R' 성격 유형에 대한 카운트를 1씩 증가시킵니다.

마찬가지로, 특정 키에 해당하는 값을 가져올 수 있습니다:

count_R = table['R']

위 코드는 'R' 성격 유형에 대한 현재 카운트를 가져와 변수 'count_R'에 할당합니다.

이와 같이 딕셔너리를 사용하면 데이터를 특정 키와 연결하여 코드를 보다 읽기 쉽고 유지 보수하기 쉽도록 만들 수 있습니다.

개선

값을 저장해서 연산하는게 좋은가?

내 생각에는 자주 쓰이는 값은 저장해서 쓰는게 가독성 면에서 좋다고 생각한다.
그치만 괜한 메모리 낭비가 생기지 않을까 걱정이 되긴 한다.
어떤 방법이 메모리 측면에서 좋은가?

값을 저장하고 계산을 수행할 것인지 아니면 필요할 때마다 값을 계산할 것인지 결정할 때는 메모리 사용량과 계산 효율성 사이의 절충안을 고려해야 합니다.

고려해야 할 사항은 다음과 같습니다.

  1. 메모리 사용량

    • 변수나 데이터 구조에 값을 저장하는 것은 값이 크거나 많은 변수가 저장되는 경우에 메모리 사용량을 증가시킵니다.
    • 필요할 때마다 값을 계산하면 최종 결과만 저장하면 되므로 메모리 사용량을 줄일 수 있습니다.
  2. 계산 효율성

    • 미리 계산된 값을 저장하면 특히 동일한 값을 여러 번 사용하는 경우 계산 효율성이 향상될 수 있습니다.
    • 필요할 때마다 값을 계산하면 특히 동일한 계산을 여러 번 수행하는 경우 중복 계산이 발생할 수 있습니다.
  3. 가독성과 유지보수성

    • 변수나 데이터 구조에 값을 저장하면 코드를 더욱 명확하게 만들어 가독성과 유지보수성이 향상될 수 있습니다.
    • 필요할 때마다 값을 계산하면 계산 논리가 복잡할 경우 코드가 더 복잡해질 수 있습니다.

메모리 사용량 측면에서는 변수나 데이터 구조에 값을 저장하는 것이 초기에는 더 많은 메모리를 사용할 수 있습니다. 그러나 그러한 값이 여러 번 재사용되는 경우, 그 값을 저장함으로써 계산이 한 번만 수행되기 때문에 실행이 더 효율적일 수 있습니다.

반면에 필요할 때마다 값을 계산하면 중간 결과를 저장하지 않아도 되므로 메모리를 절약할 수 있습니다. 그러나 특히 동일한 계산을 여러 번 수행하는 경우 중복 계산이 발생할 수 있습니다.

최종 결정은 데이터의 크기, 값의 사용 빈도, 계산의 복잡성 등과 같은 요소에 따라 다릅니다. 메모리 제약이나 성능 고려사항이 없는 한 가독성과 유지보수성을 최적화하는 것이 바람직합니다. 많은 경우에는 메모리 사용량과 계산 효율성 사이의 균형을 유지하는 것이 중요합니다.

즉, 메모리를 적당히 사용하면서 가독성을 추구하는 것이 답이다 !!

리스트 접근시 발생한 오류

list indices must be integers or slices, not str

리스트의 인덱스는 스트링값 그 자체로 접근할 수 없다. 따라서 다음과 같은 방법으로 접근해야한다.

table[str.index(survey[i][1])]

enumerate() 함수 사용하기

enumerate() 함수는 주어진 순회 가능한(iterable) 객체(리스트, 튜플, 문자열 등)를 입력으로 받아 인덱스와 해당 요소를 쌍으로 반환하는 반복자(iterator)를 생성합니다. 이 함수는 주로 순회할 때 인덱스를 추적해야 할 때 유용하게 사용됩니다.

enumerate() 함수의 기본 구문은 다음과 같습니다:

enumerate(iterable, start=0)
  • iterable: 순회 가능한(iterable) 객체입니다. 주로 리스트, 튜플, 문자열 등이 사용됩니다.
  • start: 선택적 매개변수로, 인덱스의 시작 값을 지정합니다. 기본값은 0입니다.

enumerate() 함수는 각 요소와 해당 요소의 인덱스를 튜플로 반환하는 반복자(iterator)를 생성합니다. 이 반복자를 사용하여 순회하면 각 요소와 해당하는 인덱스를 받을 수 있습니다.

예를 들어, 다음은 enumerate() 함수를 사용하여 리스트의 요소와 해당 인덱스를 출력하는 예제입니다:

my_list = ['apple', 'banana', 'orange']

for index, fruit in enumerate(my_list):
    print(index, fruit)

출력은 다음과 같습니다:

0 apple
1 banana
2 orange

위 코드에서 enumerate() 함수는 my_list라는 리스트의 요소와 해당 인덱스를 쌍으로 반환하며, 반복문을 통해 각 요소와 해당 인덱스를 순회합니다.

enumerate() 함수는 코드를 간결하게 만들고, 인덱스를 관리하는 데 유용합니다. 이 함수는 반복문에서 인덱스를 사용해야 할 때 자주 활용됩니다.

개선된 예시 코드

for i, choice in enumerate(choices):
        if choice - 4 > 0:
            scores[survey[i][1]] += choice - 4
        elif choice - 4 < 0:
            scores[survey[i][0]] += 4 - choice
profile
Spring Boot 백엔드 주니어 개발자

0개의 댓글

Powered by GraphCDN, the GraphQL CDN