프로그래머스 파이썬 기초 트레이닝 :: 조건에 맞게 수열 변환하기 2 (저장용 배열)



     

              


    문제 설명 

    프로그래머스 URL

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



    프로그래머스 코딩 카테고리 

    코딩 기초 트레이닝

    Day 15 리스트(배열), 문자열 - 조건에 맞게 수열 변환하기 2

    Lv.0



    문제 내용 

    정수 배열 arr가 주어집니다. arr의 각 원소에 대해 값이 50보다 크거나 같은 짝수라면 2로 나누고, 50보다 작은 홀수라면 2를 곱하고 다시 1을 더합니다.

    이러한 작업을 x번 반복한 결과인 배열을 arr(x)라고 표현했을 때, arr(x) = arr(x + 1)인 x가 항상 존재합니다. 이러한 x 중 가장 작은 값을 return 하는 solution 함수를 완성해 주세요.

    단, 두 배열에 대한 "="는 두 배열의 크기가 서로 같으며, 같은 인덱스의 원소가 각각 서로 같음을 의미합니다.


    arr                                   result

    [1, 2, 3, 100, 99, 98]           5




    -----------------------------------




    2차원 배열 활용 

    내가 푼 코드

    값이 바뀐 배열을 2차원 배열에 추가해서, 이전 배열과 같은지 확인하는 방식을 사용했다.  
    def solution(arr):
        check = 1
        tmp = [arr.copy()] 
        while True : 
            for i, v in enumerate(arr) : 
                if v > 50 and v % 2 == 0 :
                    arr[i] = v // 2 
                elif v < 50 and v % 2 :
                    arr[i] = (v * 2)+1
            tmp.append(arr.copy())  
            if tmp[check] == tmp[check-1] : 
                break
            check += 1
        return check -1 



    1. 2차원 배열에 값 저장 

    tmp 라는 임시 배열(2차원)에 값을 저장할때 ,

    tmp = [ arr ] 로 선언하면, arr 객체 자체를 넣는거기 때문에 while, for문에서 변경되면 tmp에서도 변경이 된다. 

    따라서, tmp = [ arr.copy() ]로 선언하고, while문에서도 tmp.append(arr.copy())로 해야 arr의 복사본이 저장이된다. 

    arr와 값은 같지만 주소값은 다른 녀석이 저장이 되는 것이다. 


    2. 2차원 배열의 마지막 arr랑 현재 arr 비교 

    최종적으로 tmp 2차원 배열에 저장되는 값은 아래와 같다. 

    [[1, 2, 3, 100, 99, 98], [3, 2, 7, 50, 99, 49], [7, 2, 15, 50, 99, 99], [15, 2, 31, 50, 99, 99], 

    [31, 2, 63, 50, 99, 99], [63, 2, 63, 50, 99, 99], [63, 2, 63, 50, 99, 99]]


    마지막에 저장된 tmp[6] 이랑 바로 이전에 넣은 tmp[5] arr 값이랑 비교해서 

    똑같으면 while 문을 빠져나오고, tmp 인덱스를 위해 사용한 check 변수를 리턴한다.




    -----------------------------------




    나는 이렇게 전과정을 저장하는 이차원 배열을 만들어서 풀었지만, 

    임시 배열(1차원) 하나를 사용해서 문제를 풀 수 있다. 

    1차원 배열을 사용하더라도 다양한 방식이 있어서, 정리해봄 


    1차원 배열

    while - break 

    while 문을 빠져나올 때 break 를 쓰는 방식이다.  

    def solution(arr):
        answer = 0
        old = arr
        while(True):
            new = []
            for i in old:
                if i>=50 and i%2 == 0: i = i/2
                elif i<50 and i%2 == 1: i = i*2 + 1
                new.append(int(i))
            if old == new: 
                break
            else:
                old = new
                answer += 1
        return answer


    old, new, arr 배열로 총 3개가 나온다. 

    old는 원본 arr 배열을 복사해서 시작한다. 

    조건에 맞춰서 값을 바꾼 새로운 배열은 new 에 저장을 해서 

    old == new 배열이 서로 같은지 확인한 뒤에, 같으면 break 로 while문을 빠져나온다.

    다르면, old = new 로 바껴진 배열 값을 가진다 .



    while - return

    while 문을 빠져나올 때 return 를 쓰는 방식이다.  

    def solution(arr):
        answer = 0
    
        while True:
    
            arr_trans = []
    
            for i in arr:
                if i >= 50 and i % 2 == 0:
                    arr_trans.append(i//2)
                elif i < 50 and i % 2 == 1:
                    arr_trans.append(i*2 + 1)
                arr_trans.append(i)
    
            if arr == arr_trans:
                return answer
    
            answer += 1
            arr = arr_trans 

    이 코드는 arr 원본 배열과 arr_trans 배열 두개를 사용한다. 

    변화시킨 arr 값을 arr_trans 에 저장하고, arr == arr_trans 같은지 비교한다. 

    같다면, break문이 아니라 return을 바로 줘서 while문을 빠져나온다. 

    다르다면, arr = arr_trans 한 뒤에 arr_trans 해서 새로운 값을 넣을 준비를 한다. 

     


    배열 없이, flag 변수

    while 문을 빠져나올 때 boolean 값을 가진 flag 변수를 쓰는 방식이다.

    def solution(arr):
        answer = 0
        while True :
            flag = False
            for i, num in enumerate(arr) :
                if num >= 50 and num % 2 == 0 :
                    arr[i] = num // 2
                    flag = True
                elif num < 50 and num % 2 == 1 :
                    arr[i] = num * 2 + 1
                    flag = True
            if flag :
                answer += 1
            else :
                break
        return answer

    arr 외에 다른 배열은 사용하지 않고, 

    while 문을 멈추는 기능을 하는 flag 변수를 사용하는 코드이다. 

    배열을 추가로 사용하지 않는 이유는 배열의 값이 이전과 같다는 건 요소 값들이 변하지 않는다는 말과 같다. 

    for 문 안에있는 if 문들이 실행이되면, 값이 변하는 거니까 이전 배열과 다르다는걸 뜻하는데 if, elif문 둘다 안거치고 지나가면 이전 배열과 같으니까 flag 값이 False로 유지가 된다. 

    flag 값이 false 일때 while문 break가 실행되서 반복에서 빠져나오게 된다. 








    댓글

    이 블로그의 인기 게시물

    [KT 에이블스쿨 - IT 트랜드] 국내외 AI 관련 규제

    KT 에이블스쿨 : 6-7차 미니프로젝트 - 제안서 기반 솔류션 기획 및 설계

    KT 에이블스쿨 : 클라우드 서비스 1일차 정리