✅ 20 회차 모의고사 D-11일
🚀 1차 코딩테스트 대비
- 백준 14719 (빗물)
- 백준 1747 (소수&팰린드롬)
- 백준 1972 (놀라운 문자열)
- 백준 16120 (PPAP)
- SQL 진료과별 예약 횟수 출력하기
1차 풀이
⭐ 1. 백준 14719 (빗물)
# 1. 알고(구현): 백준 14719 (빗물) - https://www.acmicpc.net/problem/14719
import sys
from io import StringIO
sys.stdin = StringIO('''4 8
3 1 2 3 4 1 1 2''')
input = sys.stdin.readline
def solve():
H, W = map(int, input().split())
heights = list(map(int, input().split()))
left, right = 0, W - 1
left_max = heights[left]
right_max = heights[right]
water = 0
while left < right:
if left_max < right_max:
left += 1
left_max = max(left_max, heights[left])
water += left_max - heights[left]
else:
right -= 1
right_max = max(right_max, heights[right])
water += right_max - heights[right]
print(water)
solve()⭐ 2. 백준 1747 (소수&팰린드롬)
# 2. 알고(수학): 백준 1747 (소수&팰린드롬) - https://www.acmicpc.net/problem/1747
import sys
from math import isqrt
from io import StringIO
sys.stdin = StringIO('''31''')
input = sys.stdin.readline
def solve():
N = int(input())
def is_pelin(num):
str_num = str(num)
return str_num == str_num[::-1]
def is_prime(num):
if num == 1:
return False
for denom in range(2, isqrt(num) + 1):
if num % denom == 0:
return False
return True
number = N
while True:
if is_pelin(number) and is_prime(number):
print(number)
break
number += 1
solve()⭐ 3. 백준 1972 (놀라운 문자열)
# 3. 알고(Map): 백준 1972 (놀라운 문자열) - https://www.acmicpc.net/problem/1972
import sys
from io import StringIO
sys.stdin = StringIO('''ZGBG
X
EE
AAB
AABA
AABB
BCBABCC
*''')
input = sys.stdin.readline
def solve():
def d_find(str_len):
for length in range(2, str_len + 1):
d_pair = set()
for start in range(0, str_len - length + 1):
end = start + length - 1
temp = string[start] + string[end]
if temp not in d_pair:
d_pair.add(temp)
else:
return False
return True
while True:
string = input().rstrip()
if string == '*':
break
str_len = len(string)
if d_find(str_len):
print(f"{string} is surprising.")
else:
print(f"{string} is NOT surprising.")
solve()⭐ 4. 백준 16120 (PPAP)
# 4. 알고(그리디): 백준 16120 (PPAP) - https://www.acmicpc.net/problem/16120
import sys
from io import StringIO
sys.stdin = StringIO('''PPPAPAP''')
input = sys.stdin.readline
def solve():
ppap = list(input().rstrip())
stack = []
for char in ppap:
stack.append(char)
if len(stack) >= 4 and stack[-4:] == ['P', 'P', 'A', 'P']:
del stack[-3:]
print('PPAP') if stack == ['P'] else print('NP')
solve()✏️ 5. SQL 진료과별 예약 횟수 출력하기
-- 5. SQL(Lv.2): 진료과별 예약 횟수 출력하기
-- https://school.programmers.co.kr/learn/courses/30/lessons/132202
SELECT
MCDP_CD AS 진료과코드,
COUNT(*) AS `5월예약건수` -- 백틱
FROM
APPOINTMENT
WHERE
APNT_YMD LIKE '2022-05%'
GROUP BY
MCDP_CD
ORDER BY
`5월예약건수` ASC,
진료과코드 ASC;🚀 2차 코딩테스트 대비
- 백준 17837 (새로운 게임 2)
- 백준 1937 (욕심쟁이 판다)
- 백준 13913 (숨바꼭질 4)
- 백준 12100 (2048 (Easy))
- SQL 상품을 구매한 회원 비율 구하기
2차 풀이
⭐ 1. 백준 17837 (새로운 게임 2)
# 1. 알고(시뮬): 백준 17837 (새로운 게임 2) - https://www.acmicpc.net/problem/17837
# https://www.youtube.com/@sejongclass (코드 짠 사람)
import sys
from io import StringIO
sys.stdin = StringIO('''6 10
0 1 2 0 1 1
1 2 0 1 1 0
2 1 0 1 1 0
1 0 1 1 0 2
2 0 1 2 0 1
0 2 1 0 2 1
1 1 1
2 2 2
3 3 4
4 4 1
5 5 3
6 6 2
1 6 3
6 1 2
2 4 3
4 2 1''')
input = sys.stdin.readline
def solve():
N, K = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(N)]
directions = [(0, +1), (0, -1), (-1, 0), (+1, 0)] # 우(0), 좌(1), 상(2), 하(3)
rev_dir = [1, 0, 3, 2] # 반대 방향
horses = list()
states = [[[] for _ in range(N)] for _ in range(N)] # 각 좌표마다 스텍
for i in range(K):
r, c, dir = map(lambda x: int(x) - 1, input().split()) # 0 인덱스
horses.append([r, c, dir])
states[r][c].append(i) # 말 배치
for turn in range(1, 1001):
for cur_i in range(K):
r, c, dir = horses[cur_i]
dr, dc = directions[dir]
nr, nc = r + dr, c + dc
in_range = 0 <= nr < N and 0 <= nc < N
if not in_range or board[nr][nc] == 2: # 벗어나거나, 파란색(2)인 경우
dir = rev_dir[dir] # 방향 전환
horses[cur_i][2] = dir
dr, dc = directions[dir]
nr, nc = r + dr, c + dc
in_range = 0 <= nr < N and 0 <= nc < N
if not in_range or board[nr][nc] == 2: # 또 벽, 파란색인 경우 다음 말.
continue
# 이동 확정.
cur_state = states[r][c]
nxt_state = states[nr][nc]
idx = cur_state.index(cur_i) # 해당 말의 위치
moving_group = cur_state[idx:] # 이동할 말 복사.
del cur_state[idx:] # 이전 말 제거
for move_i in moving_group: # 말 이동.
horses[move_i][:2] = nr, nc
if board[nr][nc] == 1: # 빨강이면 말 순서 뒤집기
moving_group.reverse()
nxt_state.extend(moving_group) # 다음칸에 말 쌓기.
if len(nxt_state) >= 4:
return print(turn) # 4개 이상 쌓이면 종료.
print(-1)
solve()⭐ 2. 백준 1937 (욕심쟁이 판다)
# 2. 알고(DP): 백준 1937 (욕심쟁이 판다) - https://www.acmicpc.net/problem/1937
import sys
from itertools import product
from io import StringIO
sys.stdin = StringIO('''4
14 9 12 10
1 11 5 4
7 15 2 13
6 3 16 8''')
input = sys.stdin.readline
def solve():
N = int(input())
board = [tuple(map(int, input().split())) for _ in range(N)]
directions = [(0, +1), (0, -1), (+1, 0), (-1, 0)]
starts = sorted( # 작은 수의 대나무 부터 조사.
(board[r][c], r, c)
for r, c in product(range(N), repeat=2)
)
# dp[r][c] = 이 위치에 도달 할 수 있는 최대 길이
dp = [[0] * N for _ in range(N)]
answer = 0
for cur_bamboo, r, c in starts:
max_len = 0
for dr, dc in directions:
pr, pc = r + dr, c + dc
if not 0 <= pr < N or not 0 <= pc < N:
continue
# 현재 위치로 올 수 있는 이전 방향 거리들 조사
if cur_bamboo > board[pr][pc]:
max_len = max(max_len, dp[pr][pc])
dp[r][c] = max_len + 1 # 자신의 값 추가.
answer = max(answer, max_len + 1)
print(answer)
solve()⭐ 3. 백준 13913 (숨바꼭질 4)
# 3. 알고(그래프): 백준 13913 (숨바꼭질 4) - https://www.acmicpc.net/problem/13913
import sys
from collections import deque
from io import StringIO
sys.stdin = StringIO('''5 17''')
input = sys.stdin.readline
def solve():
N, K = map(int, input().split())
MAX = 100_000
prev = [-1] * (MAX + 1) # 방문 기능 함께 통합
dq = deque([N])
prev[N] = N
while dq:
cur = dq.popleft()
if cur == K:
break
for nxt in (cur + 1, cur - 1, cur*2):
if not 0 <= nxt <= MAX or prev[nxt] != -1:
continue
dq.append(nxt)
prev[nxt] = cur
posi = K
answer = []
while posi != N:
answer.append(posi)
posi = prev[posi]
answer.append(N)
answer.reverse()
print(len(answer) - 1)
print(*answer)
solve()⭐ 4. 백준 12100 (2048 (Easy))
# 4. 알고(백트래킹): 백준 12100 (2048 (Easy)) - https://www.acmicpc.net/problem/12100
import sys
from io import StringIO
sys.stdin = StringIO('''3
2 2 2
4 4 4
8 8 8''')
input = sys.stdin.readline
def solve():
N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
max_val = max(map(max, board))
def compress_merge(one_line):
nonlocal max_val
arr = [x for x in one_line if x != 0] # 0 제거 후 복사
merged = list()
base_idx = 0
while base_idx < len(arr):
base = arr[base_idx]
target = base_idx + 1
if target < len(arr) and base == arr[target]:
max_val = max(max_val, base * 2)
merged.append(base * 2)
base_idx += 2
else:
merged.append(arr[base_idx])
base_idx += 1
merged.extend([0] * (N - len(merged)))
return merged
def can_move(dir):
is_moved = False # 이동이 일어났는지 체크
if dir == 0 or dir == 1: # dir, 0좌, 1우, 2위, 3아래
for r in range(N): # 우측이면 반전
line = board[r][::-1] if dir == 1 else board[r]
new_line = compress_merge(line)
if not is_moved: # 이동 여부
is_moved = line != new_line
if dir == 1:
new_line.reverse()
board[r][:] = new_line
else:
for c in range(N): # 아래면 반전
line = [board[r][c] for r in range(N)]
if dir == 3:
line.reverse()
new_line = compress_merge(line)
if not is_moved:
is_moved = line != new_line
if dir == 3:
new_line.reverse()
for r in range(N):
board[r][c] = new_line[r]
return is_moved
def dfs(trying_cnt):
if trying_cnt > 5:
return
snapshot = [row[:] for row in board] # 현재 상태 저장
for dir in range(4):
if can_move(dir):
dfs(trying_cnt + 1)
for r in range(N): # 보드 복원
board[r][:] = snapshot[r]
dfs(1)
print(max_val)
solve()✏️ 5. SQL 상품을 구매한 회원 비율 구하기
-- 5. SQL(Lv.5): 상품을 구매한 회원 비율 구하기
-- https://school.programmers.co.kr/learn/courses/30/lessons/131534
WITH
JOIN_21 AS (
SELECT
USER_ID,
COUNT(*) OVER() AS TOTAL_USERS
FROM
USER_INFO
WHERE
YEAR(JOINED) = 2021
)
SELECT
YEAR(SALES_DATE) AS `YEAR`,
MONTH(SALES_DATE) AS `MONTH`,
COUNT(DISTINCT USER_ID) AS `PURCHASED_USERS`,
ROUND(
COUNT(DISTINCT USER_ID) / TOTAL_USERS,
1
) AS `PUCHASED_RATIO`
FROM JOIN_21
JOIN ONLINE_SALE USING(USER_ID)
GROUP BY
YEAR, MONTH
ORDER BY
YEAR ASC, MONTH ASC;