내일배움캠프 13일차

2023년 04월 03일 by barryjung

    내일배움캠프 13일차 목차

[오늘 한일]

  • 새 챕터 주간 시작. 다시 한번 팀장을 맡았다.
  • 알고리즘 문제 풀이.
  • 장고 강의 수강.

 

[오늘 배운점]

오늘 알고리즘 문제를 풀면서 가능한대로 딕셔너리를 활용해봤다.

몇가지 알게된 포인트를 적어본다.

 

<검사는 key로, 가공은 value로>

'최빈값 구하기' 문제를 지난번 나는 리스트 두개를 활용해서, 꽤 기막힌 방법으로 풀었었다.

그런데 오늘 페어 프로그래밍 팀원분과 함께 풀어보며 다시 다른 방법을 고민해봤다.

 

딕셔너리를 활용할 생각을 해보니, 금방 직관적이고 좋은 방법이 떠올랐다.

딕셔너리를 하나 선언해서, 예제 리스트의 각 숫자를 key에 담고 각 개수를 value에 담는 것이다.

 

{'숫자':'개수', '숫자':'개수', '숫자':'개수'} 이런식이다.

array = [1, 2, 3, 3, 3, 4, 1]

def solution(array):
    dict = {}
    for i in array:
        if i not in dict:		#dict.keys()로 안해도 된다.
            dict[i] = 1
        else:
            count = dict[i]
            count += 1
            dict[i] = count
    print(dict)		#{1: 2, 2: 1, 3: 3, 4: 1}

여기서 흥미로웠던 부분은 조건문에 저렇게 딕셔너리에서 값을 검사하게 작성하면,

알아서 딕셔너리의 키 중에서만 값이 있는 지 검사한다.

(value 중에서는 있어도 상관없었다.)

 

반면에 기본적인 딕셔너리의 가공은 값 쪽에 이뤄진다.

즉, 검사는(혹은 찾는 건) 키를 통해, 가공은 값에 되는 것이다.

결론, 딕셔너리의 성질을 확실히 알게된 것 같다.

 


<입력 값에 알맞은 답을 건네주기>

어떤 입력 값에 어떤 정해진 답을 줘야하는 문제가 있다면 어떨까.

문제풀이 중 '가위바위보'가 그런 문제였다.

 

딕셔너리로 또 생각해보니, 답안지를 만들어야 겠다는 생각이 들었다.

def solution(rsp):
    answer = ''
    solution = {
        "2": "0",
        "0": "5",
        "5": "2"
    }
    for i in rsp:
        temp_answer = solution[i]
        answer += temp_answer

가위는 2, 바위는 0, 보는 5를 말한다.

입력 숫자에 대해 이기는 숫자를 출력되는 문제였다.

위처럼 작성하여 입력 값에 해당하는 답을 작성해서 출력할수 있었다.

 

다양한 다른 풀이가 있었지만 나는 내 방법이 꽤 직관적이여서 좋다고 생각한다.

결론, 딕셔너리를 입력될 값, 출력될 값의 짝 목록으로 활용할 수도 있다.

 


<키값은 해시 가능해야 한다.>

다음 문제 '점찍기' 도 비슷한 상황이다.

입력되는 x좌표, y좌표가 있는데 두 좌표가 양수냐 음수냐에 따라서,

4가지 중 해당하는 구역을 출력해주면 되는 문제였다.

 

문제풀이에서 내가 생각한 해법은 양수, 음수의 조합을 묶고,

출력이 필요한 값과 함께 짝지어 딕셔너리를 만들겠다는 생각이였다.

 

def solution(dot):
    dict = {
        1: [True, True],
        2: [False, True],
        3: [False, False],
        4: [True, False]
    }
    x = bool(dot[0] > 0)
    y = bool(dot[1] > 0)
    target = [x, y]

    for key, value in dict.items():
        if value == target:
            answer = key
    return answer

시행착오 끝에 작성한 첫번째 해답은 이렇다.

dot을 양수인지 아닌지로 참거짓을 구분하여 x,y에 각각 대입하고,

검사용 리스트로 만들어서 딕셔너리에서 숫자를 찾는 것이다.

 

자연스럽게 구역 숫자를 key로 참거짓 조합 리스트를 value로 작성했다.

쓰고보니 key와 value 역할을 반대로 넣은 것이다.

 

이 상태에서 value로 구분해서 key를 얻는 식으로 해결해보려고,

딕셔너리 뒤에 key()도 붙여보고 value()도 붙여보고 조건식도 바꿔가며 씨름을 했다.

 if target in dict.value()로 하면 참으로 value중에 값이 있음을 찾아낸다.

하지만 유무만 판단해서는 key를 못 얻는다.

 

결국 해결방법에 도달하긴 했다.

items로 딕셔너리의 key, value 나열을 불러오고, 그걸 반복문 key, value 인수에 각각 담는다.

이렇게 해서  타겟에 알맞은 키값 즉, 구역 숫자를 불러올수 있었다.

 

사실 끝까지 이 해결방법에 도전한 것은,

딕셔너리의 key, value가 뒤집어지지 않아서이기도 했다.

[참거짓 조합] : 숫자로 딕셔너리 작성 시 에러가 났던 것이다.

해쉬가능하지 않은 타입: 리스트.라는 에러다.

 

알고보니 딕셔너리의 키값은 해쉬가능한 요소여야만 한다는 규칙이 있었다!

변경 가능성이 없어서 해쉬가 가능한 요소여야 한다는 것이다.

그런데 리스트는 mutable한 요소이니 변경가능성이 있다.

 

그래서 이렇게 궁극적으로 내가 원한 모습의 해법을 작성할 수 있었다.

def solution2(dot):
    dict = {
        (True, True): 1,
        (False, True): 2,
        (False, False): 3,
        (True, False): 4
    }
    x = bool(dot[0] > 0)
    y = bool(dot[1] > 0)
    target = (x, y)

    answer = dict[target]
    return answer

 

imutable한 튜플을 이용한 것이다.

이렇게 하니 key로 찾아서 value를 검출, 정말 간단하고 쉽다.

 

여기서 흥미로운건 target변수의 경우도 튜플로 선언해줘야 하는데,

함수가 재차 동작할 때도 검사값이 잘 대체되며 잘 동작한다.

즉, 튜플의 선언으로 인한 값 대입은 회수가 반복되어도 상관없이 잘 동작하는 것이다.

 

 

결론, 딕셔너리는 아주 유용하다.

하지만 사용할때 key와(입력, 검사, 혹은 찾을 값), value(출력, 반환, 동작 시킬 값)의 관계를 잘 생각해야 한다.

(대등한 짝 묶음이 아니다.)