Python Algorithm Practice
3.1. Sequence of characters
N개의 문자열 데이터를 입력받아 앞에서 읽을 때나 뒤에서 읽을 때나 같은 경우(회문 문자열)이면 YES를 출력하고 회문 문자열이 아니면 NO를 출력하는 프로그램을 작성한다. 단 회문을 검사할 때 대소문자를 구분하지 않습니다.
n = int(input())
for i in range(n):
s = input()
s = s.lower()
size = len(s)
for j in range(size//2):
if s[j] != s[-1-j]:
print(f"#{i+1} NO")
break
else:
print(f"#{i+1} YES")
# s[::-1]으로도 구현 가능함.
3.2. Extract only number
문자와 숫자가 섞여있는 문자열이 주어지면 그 중 숫자만 추출하여 그 순서대로 자연수를 만듭니다. 만들어진 자연수와 그 자연수의 약수 개수를 출력합니다. 만약 “t0e0a1c2h0er”에서 숫자만 추출하면 0, 0, 1, 2, 0이고 이것을 자연수를 만들면 120이 됩니다. 즉 첫자리 0은 자연수화 할 때 무시합니다. 출력은 120를 출력하고, 다음 줄에 120의 약수의 개수를 출력하면 됩니다. 추출하여 만들어지는 자연수는 100,000,000을 넘지 않습니다.
s = input()
res = 0
for i in s:
if i.isdigit():
res = res*10 + int(i)
cnt = 0
for i in range(1,res+1):
if res%i==0:
cnt += 1
print(cnt)
3.3. Reverse cards
1부터 20까지 숫자가 하나씩 쓰인 20장의 카드가 아래 그림과 같이 오름차순으로 한 줄로 놓여있다. 각 카드의 위치는 카드 위에 적힌 숫자와 같이 1부터 20까지로 나타낸다.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
카드의 위치를 바꾼다: 구간 [a, b] (단, 1 ≤ a ≤ b ≤ 20)가 주어지면 위치 a부터 위치 b까지의 카드를 현재의 역순으로 놓는다. 예를 들어, 현재 카드가 놓인 순서가 위의 그림과 같고 구간이 [5, 10]으로 주어진다면, 위치 5부터 위치 10까지의 카드 5, 6, 7, 8, 9, 10을 역순으로 하여 10, 9, 8, 7, 6, 5로 놓는다. 이제 전체 카드가 놓인 순서는 아래 그림과 같다.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 10 | 9 | 8 | 7 | 6 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
이 상태에서 구간 [9, 13]이 다시 주어진다면, 위치 9부터 위치 13까지의 카드 6, 5, 11, 12, 13을 역순으로 하여 13, 12, 11, 5, 6으로 놓는다. 이제 전체 카드가 놓인 순서는 아래 그림과 같다.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 10 | 9 | 8 | 7 | 6 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
1 | 2 | 3 | 4 | 10 | 9 | 8 | 7 | 13 | 12 | 11 | 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
오름차순으로 한 줄로 놓여있는 20장의 카드에 대해 10개의 구간이 주어지면, 주어진 구간의 순서대로 위의 규칙에 따라 순서를 뒤집는 작업을 연속해서 처리한 뒤 마지막 카드들의 배치를 구하는 프로그램을 작성하세요.
a = list(range(0,21))
for _ in range(10):
s, e = map(int, input().split())
for i in range((e-s+1)//2):
a[s+i], a[e-i] = a[e-i], a[s+i]
a.pop(0)
print(a)
## 또는 s,e 받고 난 후 역배열 바꿔서 해도 됨 아래 참조
tmp = a[s-1:e]
a[s-1:e] = tmp[::-1]
3.4. Merge lists
오름차순으로 정렬이 된 두 리스트가 주어지면 두 리스트를 오름차순으로 합쳐 출력하는 프로그램을 작성하세요.
# sort로 바로 구할 수도 있지만 포인터 연습으로 구현
n1 = int(input())
l1 = list(map(int, input().split()))
n2 = int(input())
l2 = list(map(int, input().split()))
p1=p2=0
res = []
while p1<n1 and p2<n2:
if l1[p1] <= l2[p2]:
res.append(l1[p1])
p1 += 1
else:
res.append(l2[p2])
p2 += 1
if p1<n1:
res = res + l1[p1:]
if p2<n2:
res = res + l2[p2:]
for i in res:
print(i, end=' ')
3.5. Sum of Numbers
N개의 수로 된 수열 $A[1], A[2], …, A[N]$ 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 $A[i]+A[i+1]+…+A[j-1]+A[j]$가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.
n, m = map(int, input().split())
a = list(map(int,input().split()))
cnt = 0
for i in range(n):
for j in range(i+1,n):
if m==sum(a[i:j+1]):
cnt += 1
print(cnt)
## 다른 방법
lt = 0
rt = 1
tot = a[0]
cnt = 0
while True:
if tot < m:
if rt < n:
tot += a[rt]
else:
break
elif tot == m:
cnt += 1
tot -= a[lt]
lt += 1
else:
tot -= a[lt]
lt += 1
3.6. Sum of Matrix
5*5 격자판에 아래와 같이 숫자가 적혀있습니다.
10 | 13 | 10 | 12 | 15 |
12 | 39 | 30 | 28 | 11 |
11 | 25 | 50 | 53 | 15 |
19 | 27 | 29 | 37 | 27 |
19 | 13 | 30 | 13 | 19 |
N*N의 격자판이 주어지면 각 행의 합, 각 열의 합, 두 대각선의 합 중 가 장 큰 합을 출력합니다.
n = int(input())
mat = [list(map(int, input().split())) for _ in range(n)]
max = 0
mrow = 0
mcol = 0
for i in range(n):
mrow = mcol = 0
for j in range(n):
mrow += mat[i][j]
mcol += mat[j][i]
if mrow > max:
max = mrow
if mcol > max:
max = mcol
rdiag = 0
ldiag = 0
for i in range(n): # diagonal
rdiag += mat[i][i] # right diagonal
ldiag += mat[i][n-i-1] # left diagonal
if rdiag > max:
max = rdiag
if ldiag > max:
max = ldiag
print(max)
3.7. Diamond
현수의 농장은 N*N 격자판으로 이루어져 있으며, 각 격자안에는 한 그루의 사과나무가 심어져있다. N의 크기는 항상 홀수이다. 가을이 되어 사과를 수확해야 하는데 현수는 격자판안의 사과를 수확할 때 다이아몬드 모양의 격자판만 수확하고 나머지 격자안의 사과는 새들을 위해서 남겨놓는다. 만약 N이 5이면 아래 그림과 같이 진한 부분의 사과를 수확한다.
10 | 13 | 10 | 12 | 15 |
12 | 39 | 30 | 28 | 11 |
11 | 25 | 50 | 53 | 15 |
19 | 27 | 29 | 37 | 27 |
19 | 13 | 30 | 13 | 19 |
현수과 수확하는 사과의 총 개수를 출력하세요.
n = int(input())
mat = [list(map(int, input().split())) for _ in range(n)]
res = 0
s = e = n//2
for i in range(n):
for j in range(s, e+1):
res += mat[i][j]
if i < n//2:
s -= 1
e += 1
else:
s += 1
e -= 1
print(res)
3.8. Sandglass
현수는 곳감을 만들기 위해 감을 깍아 마당에 말리고 있습니다. 현수의 마당은 N*N 격자판으로 이루어져 있으며, 현수는 각 격자단위로 말리는 감의 수를 정합니다. 그런데 해의 위치에 따라 특정위치의 감은 잘 마르지 않습니다. 그래서 현수는 격자의 행을 기준으로 왼쪽, 또는 오른쪽으로 회전시켜 위치를 변경해 모든 감이 잘 마르게 합니다. 만약 회전명령 정보가 2 0 3이면 2번째 행을 왼쪽으로 3만큼 아래 그림처럼 회전시키는 명령입니다.
10 | 13 | 10 | 12 | 15 |
12 | 39 | 30 | 28 | 11 |
11 | 25 | 50 | 53 | 15 |
19 | 27 | 29 | 37 | 27 |
19 | 13 | 30 | 13 | 19 |
10 | 13 | 10 | 12 | 15 |
23 | 11 | 12 | 39 | 30 |
11 | 25 | 50 | 53 | 15 |
19 | 27 | 29 | 37 | 27 |
19 | 13 | 30 | 13 | 19 |
첫 번째 수는 행번호, 두 번째 수는 방향인데 0이면 왼쪽, 1이면 오른쪽이고, 세 번째 수는 회전하는 격자의 수입니다. M개의 회전명령을 실행하고 난 후 아래와 같이 마당의 모래시계 모양의 영역에는 감 이 총 몇 개가 있는지 출력하는 프로그램을 작성하세요.
10 | 13 | 10 | 12 | 15 |
23 | 11 | 12 | 39 | 30 |
11 | 25 | 50 | 53 | 15 |
19 | 27 | 29 | 37 | 27 |
19 | 13 | 30 | 13 | 19 |
n = int(input())
mat = [list(map(int,input().split())) for _ in range(n)]
m = int(input())
for _ in range(m):
row, tw, k = map(int,input().split())
if tw == 0: # toward left
mat[row-1] = mat[row-1][k:]+mat[row-1][:k]
else: # toword right
mat[row-1] = mat[row-1][-k:]+mat[row-1][:-k]
s = 0
e = n
res = 0
for i in range(n):
res += sum(mat[i][s:e])
# print(mat[i][s:e])
if i < n//2:
s += 1
e -= 1
else:
s -= 1
e += 1
print(res)
3.9. Hill
지도 정보가 N*N 격자판에 주어집니다. 각 격자에는 그 지역의 높이가 쓰여있습니다. 각 격자판의 숫자 중 자신의 상하좌우 숫자보다 큰 숫자는 봉우리 지역입니다. 봉우리 지역이 몇 개 있는 지 알아내는 프로그램을 작성하세요. 격자의 가장자리는 0으로 초기화 되었다고 가정한다. 만약 N=5 이고, 격자판의 숫자가 다음과 같다면 봉우리의 개수는 10개입니다.
0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 5 | 3 | 7 | 2 | 3 | 0 |
0 | 3 | 7 | 1 | 6 | 1 | 0 |
0 | 7 | 2 | 5 | 3 | 4 | 0 |
0 | 4 | 3 | 6 | 4 | 1 | 0 |
0 | 8 | 7 | 3 | 5 | 2 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
n = int(input())
mat = [list(map(int,input().split())) for _ in range(n)]
mat.insert(0, [0]*n) # upper padding
mat.append([0]*n) # lower padding
for i in mat:
i.insert(0, 0) # left padding
i.append(0) # right padding
dx = [-1, 0, 1, 0] # direction x
dy = [0, 1, 0, -1] # direction y
cnt = 0
for i in range(1, n+1):
for j in range(1, n+1):
if all(mat[i][j] > mat[i+dx[k]][j+dy[k]] for k in range(4)):
cnt += 1
print(cnt)
3.10. Sudoku
스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다음을 보자.
1 | 4 | 3 | 6 | 2 | 8 | 5 | 7 | 9 |
5 | 7 | 2 | 1 | 3 | 9 | 4 | 6 | 8 |
9 | 8 | 6 | 7 | 5 | 4 | 2 | 3 | 1 |
3 | 9 | 1 | 5 | 4 | 2 | 7 | 8 | 6 |
4 | 6 | 8 | 9 | 1 | 7 | 3 | 5 | 2 |
7 | 2 | 5 | 8 | 6 | 3 | 9 | 1 | 4 |
2 | 3 | 7 | 4 | 8 | 1 | 6 | 9 | 5 |
6 | 1 | 9 | 2 | 7 | 5 | 8 | 4 | 3 |
8 | 5 | 4 | 3 | 9 | 6 | 1 | 2 | 7 |
위 그림은 스도쿠를 정확하게 푼 경우이다. 각 행에 1부터 9까지의 숫자가 중복 없이 나오고, 각 열에 1부터 9까지의 숫자가 중복 없이 나오고, 각 3×3짜리 사각형(9개이며, 예시로 위에서 굵은 숫자)에 1부터 9까지의 숫자가 중복 없이 나오기 때문이다. 완성된 9×9 크기의 수도쿠가 주어지면 정확하게 풀었으면 “YES”, 잘 못 풀었으면 “NO”를 출력하는 프로그램을 작성하세요.
mat = [list(map(int,input().split())) for _ in range(9)]
def check(mat):
for i in range(9):
chk1 = [0]*10 # row check
chk2 = [0]*10 # col check
for j in range(9):
chk1[mat[i][j]] = 1
chk2[mat[j][i]] = 1
if sum(chk1) != 9 or sum(chk2) != 9:
return False
for i in range(3): # outer
for j in range(3):
chk3 = [0]*10 # 3x3 group check
for i2 in range(3): # inner
for j2 in range(3):
chk3[mat[i*3+i2][j*3+j2]] = 1
if sum(chk3) != 9:
return False
return True
if check(mat):
print("YES")
else:
print("NO")
3.11. Mirrored String in Matrix
1부터 9까지의 자연수로 채워진 7*7 격자판이 주어지면 격자판 위에서 가로방향 또는 세로방향으로 길이 5자리 회문수가 몇 개 있는지 구하는 프로그램을 작성하세요. 회문수란 121과 같이 앞에서부터 읽으나 뒤에서부터 읽으나 같은 수를 말합니다.
빨간색처럼 구부러진 경우(87178)는 회문수로 간주하지 않습니다.
sys.stdin=open("input.txt", "r")
mat = [list(map(int, input().split())) for _ in range(7)]
cnt=0
for i in range(3):
for j in range(7):
tmp = mat[j][i:i+5]
if tmp == tmp[::-1]:
cnt+=1
for k in range(2):
if mat[i+k][j] != mat[i+5-k-1][j]:
break
else:
cnt+=1
print(cnt)