두 개의 자연수 N과 K가 주어졌을 때, N의 약수들 중 K번째로 작은 수를 출력하는 프로그램을 작성하시오.
## 내 풀이
N, K = map(int,input().split())
d = []
for i in range(1, N+1):
if N % i == 0:
d.append(i)
print(d[K-1])
if len(d) < K :
print(-1)
6 3
3
## 모범답안
N, K = map(int, input().split())
cnt = 0 # 약수의 개수
for i in range(1, N+1):
if N % i == 0:
cnt += 1
if cnt == K :
print(i)
break # for문에 정상적으로 끝났다 = 약수를 찾지 못했다
else : # 약수를 찾지 못했을때
print(-1)
핵심은 for ~ else
구문을 활용하는 것이었다. for ~ else
문은 for
문이 break
등으로 중간에 끊기지 않고 정상적으로 실행되었을 경우 else
문이 실행된다. 즉 이 문제에서는 for
문이 정상적으로 끝났을 경우(=약수를 찾지 못했을 때), else
문이 실행되면서 -1
을 출력하게 된다. 내가 푼 풀이도 맞기는 하지만, 좀 더 체계적으로 코드를 작성하려면 이번 문제에서는 for ~ else
문 사용이 핵심 포인트였던 것!
N개의 숫자로 이루어진 숫자열이 주어지면 해당 숫자열 중에서 s번째부터 e번째 까지의 수를 오름차순 정렬했을 때 k번째로 나타나는 숫자를 출력하는 프로그램을 작성하세요.
## 내 풀이
T = int(input())
for i in range(T):
N, s, e, k = map(int, input().split())
num = list(map(int, input().split()))
for j in range(num[s-1], num[e]):
num.append(j)
num.sort()
print(num[k-1])
2
6 2 5 3
5 2 7 3 8 9
3
15 3 10 3
4 15 8 16 6 6 17 3 10 11 18 7 14 7 15
6
## 모범답안
T = int(input())
for t in range(T):
N, s, e, K = map(int, input().split())
num = list(map(int, input().split()))
num = [s-1 : e]
num.sort()
print(num[K-1])
2
6 2 5 3
5 2 7 3 8 9
7
15 3 10 3
4 15 8 16 6 6 17 3 10 11 18 7 14 7 15
6
핵심은 '리스트 슬라이스' 였다. 여기서 주의할 점은 k번째 원소를 말하더라도 인덱싱의 규칙을 생각하면 리스트의 k-1번째 원소를 지칭하는 것이다. 또 한 가지는 테스트케이스 별 실행이 필요하기 때문에 큰 틀로 for
문을 활용하여 하나의 테스트케이스를 돌고 그 다음 테스트케이스를 실행할 수 있도록 해야한다는 것이다. 이 점을 주의해서 문제를 푼다면 충분히 풀 수 있는 문제였다.
1부터 100사이의 자연수가 적힌 N장의 카드를 가지고 있고, 같은 숫자의 카드가 여러장 있을 수 있다. 이 중 3장을 뽑아 각 카드에 적힌 수를 합한 값을 기록하려고 하며, 3장을 뽑을 수 있는 모든 경우를 기록한다. 기록한 값 중 K번째로 큰 수를 출력 하는 프로그램을 작성하시오.
## 내 풀이
N, K = map(int, input().split())
card = list(map(int, input().split()))
# 뽑은 카드 3장의 값을 합한 조합
cardsum = []
for i in range(0, len(card)-2):
for j in range(i+1, len(card)-1):
for k in range(j+1, len(card)):
s = card[i] + card[j] + card[k]
cardsum.append(s)
# 내림차순 정렬
cardsum.sort(reverse=True)
# K번째 수 출력 (중복제외)
print(cardsum[K-1])
10 3
13 15 34 23 45 65 33 11 26 42
143
## 모범답안
N, K = map(int, input().split())
card = list(map(int, input().split()))
cardsum = set() # 중복을 제거하는 자료구조
for i in range(N):
for j in range(i+1, N):
for k in range(j+1, N):
cardsum.add(card[i]+card[j]+card[k]) # set자료구조는 append가 아닌 add를 사용
cardsum = list(cardsum) # set자료구조는 sort를 사용할 수 없으므로 list로 변환
cardsum.sort(reverse=True)
print(cardsum[K-1])
손으로 가능한 합의 조합 몇 개만 적어봐도 금방 규칙을 찾을 수 있었다. for
문의 range
범위를 정할때 헷갈려서 직접 눈으로 규칙을 확인해보았다.
이 문제의 또 한 가지 핵심 포인트는 set
자료구조의 사용이었다. 제일 처음에 풀었을 때는 sum
을 리스트의 형태로 잡고 풀었는데, 문제를 읽어보면 중복되는 숫자가 나올 수는 있지만, 우리가 구해야하는 것은 중복없이 큰 순으로 K번째의 합을 구하는 것이다. 중복을 허용하지 않는 set
(집합) 자료구조의 특징을 고려하면서 풀면 쉽게 풀릴 수 있는 문제였다. 집합에서는 원소를 추가할 때 .append()
가 아니라 .add()
를 사용해야하고, 집합은 .sort()
를 적용할 수 없기 때문에 리스트로 변환 후 사용해야하는 것도 잊지말자!
N명의 학생의 수학점수가 주어질 때, N명의 학생들의 평균(소수 첫째자리 반올림)을 구하고, N명의 학생 중 평균에 가장 가까운 학생은 몇 번째 학생인지 출력하는 프로그램을 작성하시오. (단, 평균과 가장 가까운 점수가 여러 개일 경우 먼저 점수가 높은 학생의 번호를 답으로 하고, 높은 점수를 가진 학생이 여러 명일 경우 그 중 학생번호가 빠른 학생의 번호를 답으로 한다.)
## 내 풀이
N = int(input()) # 학생수
score = list(map(int, input().split()))
avg = sum(score)/len(score)
round(avg, 0)
bias = list(map(lambda x:abs(x-avg), score))
a = min(bias)
모르겠음..
## 모범답안
N = int(input())
s = list(map(int, input().split()))
avg = int((sum(a)/n) + 0.5)
min = 2147000000
for idx, x in enumerate(s):
tmp = abs(x-avg) # 편차 절댓값(=평균과의 거리)
if tmp < min:
min = tmp # 최솟값은 tmp가 된다
score = x # score : 답이되는 점수
res = idx + 1 # res : 답이되는 점수의 학생번호
elif tmp == min # 같은 점수차를 갖는 학생들이 있다면
if x > score: # 그 중 더 높은 점수를 갖는 학생들에 한해서
score = x
res = idx + 1
print(avg, res)
10
45 73 66 87 92 67 75 79 75 80
74 7
핵심은 '최솟값 구하기' 알고리즘과 조건을 잘 활용하는 것이었다.
파이썬에서의 round
함수는 round_half_even
방식을 택한다. 즉, 파이썬에서의 round
함수는 우리가 일반적으로 알고있는 5이상의 수를 올림해주는 round_half_up
의 방식을 따르지 않는다는 것이다. 따라서 round
함수를 써도 5이상의 수가 올림되지 않을 수 있다. 정확하게 .5000000 의 지점에 있다면 짝수(even)쪽으로 근사하게 된다.
예시로 알아보자.
## round_half_even
a = 4.500
print(round(a))
b = 5.5000
print(round(b))
4
6
round_half_up
의 방식을 따랐다면 원래 a는 5가 나와야 하지만, 파이썬에서는 4가 나온다.
a = 4.511
print(round(a))
5
## round_half_even 해결방법
a = 66.5
a = a + 0.5
a = int(a)
print(a)
67
즉, 반올림하려는 수에 +0.5를 한 후 int화 시켜서 소수점을 날리면 우리가 원하는 round_half_up
방식의 반올림을 할 수 있다.
두 개의 정 N면체와 정 M면체의 두 개의 주사위를 던져서 나올 수 있는 눈의 합 중 가장 확률이 높은 숫자를 출력하는 프로그램을 작성하시오. (정답이 여러 개일 경우 오름차순으로 출력하시오.)
## 내 풀이
N, M = map(int, input().split())
ch = [0] * (N*M) + 3
res = []
print(res)
## 모범답안
(수정중)