[python] 프로그래머스 코딩테스트 (2)
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
- 공차수열 리스트 만들기
- zip으로 튜플단위로 묶음
- if로 T만 연산
#1
- included[i]로 if를 스킵한 것이 인상적
#2
- included를 numbering(enumerate)된 tuple로 변환
- 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) = [1, 2, 3]를 좌우가 모두 iterable 변수인 (a, b, c) = [1, 2, 3] 형태로 나타낼 수 있다.
일반적으로 대입 연산자는 왼쪽에 있는 '변수'에 오른쪽에 있는 값을 할당하는 역할을 한다.
하지만 좌우가 모두 iterable 변수인 경우 파이썬은,
- 왼쪽의 이터러블에 있는 값이 모두 변수인지 일단 확인
- 좌우 변수의 갯수가 같고(크기 동일), 둘 다 변수일 때,
왼쪽의 구조에 맞춰서 오른쪽의 값을 각각의 변수에 '풀어서' 대입
(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 유형을 섞어서 사용했다. (다시 봐야지)