공부/오답노트

[python] 프로그래머스 코딩테스트 (2)

시송 2025. 1. 6. 13:52

1. 원소들의 곱과 합

  정수가 담긴 리스트 num_list가 주어질 때, 모든 원소들의 곱이 모든 원소들의 합의 제곱보다 작으면 1을 크면 0을 return하도록 solution 함수를 완성해주세요.

#0 나의 풀이
def solution(num_list):
    mmul = 1
    ssum = 0
    for a in num_list: 
        mmul *= a 
    #for a in num_list:
        ssum += a
    if mmul < ssum**2: # return int(mul < sum**2)
        return 1
    else:
        return 0
        
        
#1
def solution(num_list):
    mul = 1 
    for n in num_list:
        mul *= n
    return int(mul < sum(num_list) ** 2)
  • for문 1개에 2개의 변수를 계산할 수 있음
  • 논리 연산자 T/F를 int로 변환

 

2. 등차수열의 특정한 항만 더하기


두 정수 a, d와 길이가 n인 boolean 배열 included가 주어집니다. 첫째항이 a, 공차가 d인 등차수열에서 included[i]가 i + 1항을 의미할 때, 이 등차수열의 1항부터 n항까지 included가 true인 항들만 더한 값을 return 하는 solution 함수를 작성해 주세요.

#0 나의 풀이
def solution(a, d, included):
    answer = 0
    adlist = list(i for i in range(a, a+d*len(included), d))
    for TF, num in zip(included, adlist):
        if TF:
            answer += num            
    return answer

#1
def solution(a, d, included):
    answer = 0
    for i in range(len(included)):
        answer += (a + d * i) * int(included[i]) #int(included[i])로 if skip
    return answer


#2
def solution(a, d, included):
    l = []
    for i, x in enumerate(included):
        if x == True:
            l.append(d*i + a)

    return sum(l)


#3
def solution(a, d, included):
    return sum(a + i * d for i, f in enumerate(included) if f) # 계산은 앞에 몰아서

 

#0

  1. 공차수열 리스트 만들기
  2. zip으로 튜플단위로 묶음
  3. if로 T만 연산

#1

  • included[i]로 if를 스킵한 것이 인상적

#2

  1. included를 numbering(enumerate)된 tuple로 변환
  2. list append

 

#3

2번 comprehesion

  • 연산 결과 sum
  • 계산 공식을 종합적으로 볼 수 있어야 함
  • 가장 컴팩트한 코드는 역으로 접근할 때 나오는 것 같다 (a + d*1) + (a + d*2) + ... + (a + d*n)

 

3. 이어 붙인 수

  정수가 담긴 리스트 num_list가 주어집니다. num_list의 홀수만 순서대로 이어 붙인 수와 짝수만 순서대로 이어 붙인 수의 합을 return하도록 solution 함수를 완성해주세요.

#0 나의 풀이
def solution(num_list):
    odd = ''.join([str(i) for i in num_list if i%2==1]) #for문부터 ##sum은 오류 ##join()
    # odd = ''.join(list(str(i) for i in num_list if i%2==1))
    even = ''.join([str(i) for i in num_list if i%2==0])
    answer = int(odd)+int(even)
    return answer
    
    
#1
def solution(num_list):
    answer = 0
    a=""#홀수
    b=""#짝수
    for i in num_list:
        if i%2!=0:
            a+=str(i)
        else:
            b+=str(i)
    return int(a)+int(b)
  • for문 > if문 순서 (지키지 않으면 오류)
  • comprehension은 list에 담아주어야 함
  • num > str(연결) > num(으로 바꿔서 더하기)

 

4. 수열과 구간 쿼리 2

 정수 배열 arr와 2차원 정수 배열 queries이 주어집니다. queries의 원소는 각각 하나의 query를 나타내며, [s, e, k] 꼴입니다. 각 query마다 순서대로 s ≤ i ≤ e인 모든 i에 대해 k보다 크면서 가장 작은 arr[i]를 찾습니다. 각 쿼리의 순서에 맞게 답을 저장한 배열을 반환하는 solution 함수를 완성해 주세요. 단, 특정 쿼리의 답이 존재하지 않으면 -1을 저장합니다.

#0
def solution(arr, queries):
    answer = []
    for query in queries:
        temp = list(i for i in arr[query[0]:query[1]+1] if query[2] < i) # ex) [4, 3]
        if temp:
            answer.append(min(temp))
        else: # []
            answer.append(-1)
    return answer

#1
def solution(arr, queries):
    answer = []
    for s, e, k in queries:
        l = [i for i in arr[s:e+1] if i > k]
        answer.append(-1 if len(l) == 0 else min(l))
    return answer
  
#2
def solution(arr, queries):
    answer = []
    for s, e, k in queries:
        tmp = []
        for x in arr[s:e+1]:
            if x > k:
                tmp.append(x)
        answer.append(-1 if not tmp else min(tmp))
    return answer

 

 

5. 수열과 구간 쿼리 3

  정수 배열 arr와 2차원 정수 배열 queries이 주어집니다. queries의 원소는 각각 하나의 query를 나타내며, [i, j] 꼴입니다. 각 query마다 순서대로 arr[i]의 값과 arr[j]의 값을 서로 바꿉니다. 위 규칙에 따라 queries를 처리한 이후의 arr를 return 하는 solution 함수를 완성해 주세요.

#0
def solution(arr, queries):
    for query in queries:
        num1 = arr[query[0]]
        num2 = arr[query[1]]
        arr[query[0]] = num2
        arr[query[1]] = num1 
    return arr
    
#1
def solution(arr, queries):
    for a,b in queries:
        arr[a],arr[b]=arr[b],arr[a]
    return arr
  • 이렇게 동시에 바꿀 수 있음을 꼬옥 기억하도록 해...

 

5-1) unpacking 보충 예제

(a, b) = [0, 3] = query

(a) = [1, 2, 3]를 좌우가 모두 iterable 변수인 (a, b, c) = [1, 2, 3] 형태로 나타낼 수 있다.

일반적으로 대입 연산자는 왼쪽에 있는 '변수'에 오른쪽에 있는 값을 할당하는 역할을 한다.

하지만 좌우가 모두 iterable 변수인 경우 파이썬은,

  1. 왼쪽의 이터러블에 있는 값이 모두 변수인지 일단 확인
  2. 좌우 변수의 갯수가 같고(크기 동일), 둘 다 변수일 때,
    왼쪽의 구조에 맞춰서 오른쪽의 값을 각각의 변수에 '풀어서' 대입

(a, b, c) = [1, 2, 3]와 a, b, c = [1, 2, 3]은 동일하다.

 

enumerate(d.items())를 반복문에서 언패킹하려면 형태가 똑같아야됩니다.

: n, (keyt, value)
(not n, k, v
하나가 넘치네요- 튜블로 한번 더 묶어주는 건 약간 차원 문제)

for query in queries:
        s, e, k = query

 

6. 수 조작하기 1

  정수 n과 문자열 control이 주어집니다. control은 "w", "a", "s", "d"의 4개의 문자로 이루어져 있으며, control의 앞에서부터 순서대로 문자에 따라 n의 값을 바꿉니다.

  • "w" : n이 1 커집니다.
  • "s" : n이 1 작아집니다.
  • "d" : n이 10 커집니다.
  • "a" : n이 10 작아집니다.

  위 규칙에 따라 n을 바꿨을 때 가장 마지막에 나오는 n의 값을 return 하는 solution 함수를 완성해 주세요.

#0
def solution(n, control):
    for alph in control:
        if alph == 'w':
            n += 1
        elif alph == 's':
            n -= 1
        elif alph == 'd':
            n += 10
        elif alph == 'a':
            n -= 10
    return n
    
#1
def solution(n, control):
    key = dict(zip(['w','s','d','a'], [1,-1,10,-10]))
    return n + sum([key[c] for c in control])

#2
def solution(n, control):
    answer = n
    c = {'w':1, 's':-1, 'd':10, 'a':-10}
    for i in control:
        answer += c[i]
    return answer

 

#1

  • zip으로 묶인 두 튜플은 dict에 key와 value로 들어간다

 

#2

  • 처음부터 dict형태로 만들어 준다

 

7. 수 조작하기 2

  정수 배열 numLog가 주어집니다. 처음에 numLog[0]에서 부터 시작해 "w", "a", "s", "d"로 이루어진 문자열을 입력으로 받아 순서대로 다음과 같은 조작을 했다고 합시다.

  • "w" : 수에 1을 더한다.
  • "s" : 수에 1을 뺀다.
  • "d" : 수에 10을 더한다.
  • "a" : 수에 10을 뺀다.

  그리고 매번 조작을 할 때마다 결괏값을 기록한 정수 배열이 numLog입니다. 즉, numLog[i]는 numLog[0]로부터 총 i번의 조작을 가한 결과가 저장되어 있습니다. 주어진 정수 배열 numLog에 대해 조작을 위해 입력받은 문자열을 return 하는 solution 함수를 완성해 주세요.

#0
def solution(numLog):
    answer = ""
    c = {1: 'w', (-1) : 's', 10 : 'd', (-10) : 'a'}
    for n in range(len(numLog)-1):
        a = numLog[n+1]-numLog[n]
        answer += c[a]
    return answer
    
#1
def solution(log):
    res=''
    joystick=dict(zip([1,-1,10,-10],['w','s','d','a']))
    for i in range(1,len(log)):
        res+=joystick[log[i]-log[i-1]]
    return res

 

 

8. 마지막 두 원소

  정수 리스트 num_list가 주어질 때, 마지막 원소가 그전 원소보다 크면 마지막 원소에서 그전 원소를 뺀 값을 마지막 원소가 그전 원소보다 크지 않다면 마지막 원소를 두 배한 값을 추가하여 return하도록 solution 함수를 완성해주세요.

#0
def solution(num_list):
    if num_list[-1] > num_list[-2] :
        num = num_list[-1] - num_list[-2] 
    else :
        num = int(num_list[-1])*2
    num_list.append(num)
    return num_list

#1
def solution(num_list):
    n1, n2 = num_list[-1], num_list[-2]
    if n1 > n2:
        num_list.append(n1 - n2)
    else:
        num_list.append(n1 * 2)
    return num_list

#2
def solution(l):
    l.append(l[-1]-l[-2] if l[-1]>l[-2] else l[-1]*2)
    return l

 

#0

  • if에서 연산> append를 나중에

 

#1

  • n을 언패킹
  • if 대소비교 후 action

action에서 정확히 '해야할 일'을 하는 쪽이 더 가독성이 좋다. 

 

#2

  • append와 comprehnetion의 사용
  • a if 조건 else b일 때, a와 b는 모두 객체이다. 따라서 append가 적용 됨

 

8. 수열과 구간 쿼리 4

  정수 배열 arr와 2차원 정수 배열 queries이 주어집니다. queries의 원소는 각각 하나의 query를 나타내며, [s, e, k] 꼴입니다. 각 query마다 순서대로 s ≤ i ≤ e인 모든 i에 대해 i가 k의 배수이면 arr[i]에 1을 더합니다. 위 규칙에 따라 queries를 처리한 이후의 arr를 return 하는 solution 함수를 완성해 주세요.

#0
def solution(arr, queries):
    for s, e, k in queries:
        for n in range(s, e+1):
            if n%k == 0:
                arr[n] += 1
    return arr
    
#1
def solution(arr, queries):
    for s,e,k in queries:
        for i in range(s,e+1):
            if not i%k: arr[i]+=1
    return arr
  • range(s, e+1)을 생각해내는 것이 오래걸렸다.
  • 아래 if는 조건이고, range는 arr을 돌리기 위함
  • not i%k를 돌리면 0/n이라는 예외를 상정가능함

 

9. 주사위 게임 3

1부터 6까지 숫자가 적힌 주사위가 네 개 있습니다. 네 주사위를 굴렸을 때 나온 숫자에 따라 다음 점수를 얻습니다. 

  • 네 주사위에서 나온 숫자가 모두 p로 같다면 1111 × p점을 얻습니다. 
  • 세 주사위에서 나온 숫자가 p로 같고 나머지 다른 주사위에서 나온 숫자가 q(p ≠ q)라면 (10 × p + q)2 점을 얻습니다. 
  • 주사위가 두 개씩 같은 값이 나오고, 나온 숫자를 각각 p, q(p ≠ q)라고 한다면 (p + q) × |p - q|점을 얻습니다. 
  • 어느 두 주사위에서 나온 숫자가 p로 같고 나머지 두 주사위에서 나온 숫자가 각각 p와 다른 q, r(q ≠ r)이라면 q × r점을 얻습니다. 네 주사위에 적힌 숫자가 모두 다르다면 나온 숫자 중 가장 작은 숫자 만큼의 점수를 얻습니다. 

네 주사위를 굴렸을 때 나온 숫자가 정수 매개변수 a, b, c, d로 주어질 때, 얻는 점수를 return 하는 solution 함수를 작성해 주세요.

 

#0
def solution(a, b, c, d): 
    
    basic = sorted([a, b, c, d]) #sort() sorted
    check = len(list(set(basic)))
    
    if check == 1: 
        return 1111 * a
    
    elif check == 2: 
        if basic[0] == basic[2] : # 1112
            return (10 * basic[0] + basic[3])**2
        elif basic[1] == basic[3] :
            return (10 * basic[1] + basic[0])**2
        else: # 1122
            return (basic[0] + basic[2]) * abs(basic[0] - basic[2])

    
    elif check == 3:
        temp = []
        for i in basic:
            if i not in temp:
                temp.append(i)
            else:
                temp.remove(i)
        return temp[0] * temp[1]
        
    else:
        return min(a, b, c, d) 
 
 
 #1
 def solution(a, b, c, d):
    x = [a, b, c, d]
    x.sort()   # 주사위 리스트 오름차순 정렬
 
    # 1. 네 주사위가 모두 같을 경우
    if x[0] == x[3] :  
        return 1111*a
 
    # 2. 세 주사위가 같을 경우 ## 같은 결과를 2가지 경우로 나눠야하는게 아쉬웠음
    elif x[0] == x[2] : 
        return (10 * x[1] + x[3])**2
    elif x[1] == x[3] : 
        return (10 * x[1] + x[0])**2
    
    # 3. 두 개씩 같을 경우
    elif x[0] == x[1] and x[2] == x[3] :
        return (x[0] + x[3]) * abs(x[0] - x[3])
    
    # 4. 두 개만 같고, 나머지는 각각 다를 경우 ## 앞에서 다른 같은 경우의 수는 모두 filtered
    elif x[0] == x[1] : 
        return x[2] * x[3]
    elif x[1] == x[2] : 
        return x[0] * x[3]
    elif x[2] == x[3] : 
        return x[0] * x[1]
    
    # 5. 네 주사위가 모두 다를 경우
    else :
        return x[0]
 
 
 
#2
def solution(a, b, c, d):
    dice = [a, b, c, d] # 주사위의 숫자들을 리스트에 저장
    abcd = dict() # 각 숫자의 등장 횟수를 저장할 딕셔너리를 생성
    
    # 주사위의 숫자들을 하나씩 확인하면서
    for num in dice:
        if num not in abcd: # 해당 숫자가 딕셔너리에 없다면 새로 추가하고,
            abcd[num] = 1
        else: # 있다면 등장 횟수를 1 증가
            abcd[num] += 1

    # 딕셔너리의 키를 등장 횟수에 따라 정렬 # sort() and #sorted()
    abcd = sorted(abcd, key=lambda x:abcd[x])

    if len(abcd) == 1: # 주사위에서 나온 숫자가 모두 같을 때, ## dict는 key값 counting
        return 1111 * a
    
    elif len(abcd) == 2: # 주사위에서 나온 숫자가 2개 일 때,
        if dice.count(abcd[0]) in [1, 3]: # 세 주사위에서 같은 값을 가지는 경우
            return (10 * abcd[1] + abcd[0]) ** 2
        # {num1: 1, num2: 3}의 형태로 저장된 dict이므로, 1번째 key의 value가 1이나 3이면
        
        else: # 주사위가 2개씩 같은 값을 가지는 경우
            return (abcd[0] + abcd[1]) * abs(abcd[0] - abcd[1])
        
    elif len(abcd) == 3: # 주사위에서 나온 숫자가 3개 일 때,
        return abcd[0] * abcd[1]
    
    # 주사위에서 나온 숫자가 모두 다를 때, 가장 작은 값을 반환
    return min(dice)
    
 
#3
def solution(a, b, c, d):
    nums = [a, b, c, d]
    counts = [nums.count(i) for i in nums] # 각 원소의 갯수를 받는 list=counts
    
    if max(counts) == 4: # 각 원소 갯수가 4개이면
        return a * 1111
        
    elif max(counts) == 3:
        p = nums[counts.index(3)] # counts, p:[[3,1,3,3],4] # max가 3일때, counts 내 maxnum index
        q = nums[counts.index(1)] # maxnum의 index는 nums에서도 호환되므로
        return (10 * p + q) ** 2 ## 기존의 위치 index 정보를 보존할 수 있으나, 코드 해석이 어려움
    
    elif max(counts) == 2:
        if min(counts) == 2:
            return (a + c) * abs(a - c) if a == b else (a + b) * abs(a - b)
        else:
            p = nums[counts.index(2)]
            return (a * b * c * d) / p**2
            
    else:
        return min(nums)

 
#4
 def solution(a, b, c, d):
 
    l = sorted([a, b, c, d])

    return a * 1111 if l[0] == l[-1] else (10 * l[0] + l[3]) ** 2 
                    if l[0] == l[-2] else (10 * l[-1] + l[0]) ** 2 
                    if l[1] == l[-1] else (l[0] + l[-1]) * abs(l[0] - l[-1]) 
                    if l[0] == l[1] and l[2] == l[3] else min(l) 
                    if len(set(l)) == 4 else a * b * c * d 
                    // next(filter(lambda x: [a, b, c, d].count(x) == 2, l)) ** 2

 

   간만에 감 잡기 어려웠던 문제. 이전에 풀었던 문제의 set을 응용해보려고 했는데 2가지 숫자가 나오는 상황에서 각 p와 q를 어떻게 구분해야하는지, 다시말해 중복되는 숫자가 무엇인지 확인하기 어려웠다. 다른 사람들의 코드를 보고 2 유형을 섞어서 사용했다. (다시 봐야지)