[인프런] 파이썬 알고리즘 문제풀이 입문 - 탐색 & 시뮬레이션

bee·2023년 3월 4일
0

Algorithm

목록 보기
2/8
post-thumbnail

1. 회문 문자열 검사

N개의 문자열 데이터를 입력받아 앞에서 회문 문자열(읽을 때나 뒤에서 읽을 때나 같은 경우)이면 YES를, 아니면 NO를 출력하는 프로그램을 작성하시오. (단, 회문을 검사할 때 대소문자를 구분하지 않는다.)

## 내 풀이
N = int(input())

for i in range(N):
    a = input()
    a = a.upper() # 파이썬은 대소문자를 구분하므로 전부 대문자로 변환시켜준다
    s = 0 # 똑같은 문자쌍 개수
    for j in range(0,len(a)//2):
        if a[j] == a[-j-1]:
            s += 1
    if s == (len(a)//2) : 
        print("YES")
    else : 
        print("NO")

5
level
#1 YES
mooon
#2 NO
abcba
#3 YES
soon
#4 NO
gooG
#5 YES

## 모범답안
n = int(input())

for i in range(n):
    s = input()
    s = s.upper()
    size = len(s)
    for j in range(size//2):
        if s[j] != s[-1-j]:
            print("#%d NO" %(i+1))
            break
    else:
        print("#%d YES" %(i+1))

5
level
#1 YES
mooon
#2 NO
abcba
#3 YES
soon
#4 NO
gooG
#5 YES


2. 숫자만 추출

문자와 숫자가 섞여있는 문자열이 주어지면 그 중 숫자만 추출하여 그 순서대로 자연수를 만든다. 만들어진 자연수와 그 자연수의 약수 개수를 출력하는 프로그램을 작성하시오.
예) “t0e0a1c2h0er”에서 숫자만 추출하면 0, 0, 1, 2, 0이고 이것을 자연수를 만들면 120이 된다. 즉 첫자리 0은 자연수화할 때 무시한다.

## 내 풀이
s = input()
n = '' # 숫자만 추출(str)
for i in range(0, len(s)):
    if type(s[i]) == int:
        n = n + s[i]

n = int(n) # 다시 정수화
d = [] # 약수
for i in range(1, n+1):
    if n % i == 0:
        d.append(i)

print(n)
print(len(d))

ValueError: invalid literal for int() with base 10: ''
틀린이유 : 생각해보니까 이미 s는 문자열로 받았기 때문에 이를 구성하고 있는 요소들도 전부 문자열로 인식되었을 것이다.

## 모범답안
s = input()
res = 0
for i in range(len(s)):
	if s[i].isdecimal():
    	res = res * 10 + int(i)
print(res)

cnt = 0
for i in range(len(res)):
	if res[i] % i == 0:
    	cnt += 1
print(cnt)

g0en2Ts8eSoft

28
6

이번 문제의 핵심은 .isdecimal()을 사용해서 문자열이 숫자인지 아닌지 판별하는 것이었다. 그리고 문제에서 '첫자리 0은 자연수화 할 때 무시한다'라고 되어있기 때문에 저번 풀이 중 '뒤집은 소수' 문제를 풀 때 사용했던 res = res * 10 + int(i) 코드로 뒤에서부터 앞으로 수를 밀면서 추가하는 방식을 사용하는 것이었다. 아직도 모르는 함수가 많아서 머리 쥐뜯게되지만... 이렇게 배워가는구나 생각하자!


3. 카드 역배치

1부터 20까지 숫자가 하나씩 쓰인 20장의 카드가 오름차순으로 한 줄로 놓여있다. 각 카드의 위치는 카드 위에 적힌 숫자와 같이 1부터 20까지로 나타낸다. 다음과 같은 규칙으로 카드의 위치를 바꾼다.

  • 구간 [a, b] (단, 1 ≤ a ≤ b ≤ 20)가 주어지면 위치 a부터 위치 b까지의 카드를 현재의 역순으로 놓는다.
    오름차순으로 한 줄로 놓여있는 20장의 카드에 대해 10개의 구간이 주어지면, 주어진 구간의 순서대로 위의 규칙에 따라 순서를 뒤집는 작업을 연속해서 처리한 뒤 마지막 카드들의 배치를 구하는 프로그램을 작성하시오.

## 내 풀이
n = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
for i in range(10):
    a, b = map(int, input().split())
    d = b - a + 1 # a와 b사이의 거리
    for j in range(0, d//2):
        n[a-1+j], n[b-1-j] = n[b-1-j], n[a-1+j]

print(n)

5 10
9 13
1 2
3 4
5 6
1 2
3 4
5 6
1 20
1 20

[1, 2, 3, 4, 10, 9, 8, 7, 13, 12, 11, 5, 6, 14, 15, 16, 17, 18, 19, 20]

## 모범답안
s = list(range(21))
for _ in range(10) : # _ : 변수 없이 주어진 횟수만큼 반복한다
    a, b = map(int, input().split())
    for i in range((b-a+1) // 2):
        s[a+i], s[b-i] = s[b-i], s[a+i]

s.pop(0)
for x in s:
    print(x, end=' ')

5 10
9 13
1 2
3 4
5 6
1 2
3 4
5 6
1 20
1 20

[1, 2, 3, 4, 10, 9, 8, 7, 13, 12, 11, 5, 6, 14, 15, 16, 17, 18, 19, 20]

나는 손으로 써보면서 구조를 파악한 후 풀어보았다. 보니까 내 풀이가 더 간단한 것 같기도...?? 아님말고


4. 두 리스트 합치기

오름차순으로 정렬된 두 리스트가 주어지면, 두 리스트를 오름차순으로 합쳐 출력하는 프로그램을 작성하시오.

## 내 풀이
N = int(input())
a = list(map(int, input().split()))

M = int(input())
b = list(map(int, input().split()))

new = a + b
new.sort()
print(new)

3
1 3 5
5
2 3 6 7 9

[1, 2, 3, 3, 5, 6, 7, 9]

틀린이유 : 내 풀이는 정답을 출력하는 맞는 풀이이기는 하지만, 이렇게 풀 경우, .sort() 함수로 인한 시간복잡도 때문에 nlog(n)만큼의 시간이 소요된다. 문제에서 원하는 바는, 이미 오름차순으로 정렬된 리스트를 받았기 때문에 이 점을 활용하여 시간복잡도를 n으로 줄이는 것이었다.

## 모범답안
n = int(input())
a = list(map(int, input().split()))

m = int(input())
b = list(map(int, input().split()))

p1 = p2 = 0 # 포인트 변수 초기화
c = [] # 원소를 담을 빈 리스트 생성

while p1 < n and p2 < m:
    if a[p1] <= b[p2]:
        c.append(a[p1])
        p1 += 1
    else: # a[p1] > b[p2]
        c.append(b[p2])
        p2 += 1

# 남은 원소 확인
if p1 < n: # a의 원소가 남았다면 
    c = c + a[p1:] # 빈 리스트 끝에 a의 남은 원소를 이어 붙인다
if p2 < m: # b의 원소가 남았다면
    c = c + b[p2:] # 빈 리스트 끝에 b의 남은 원소를 이어 붙인다
print(c)


핵심은 반복문을 사용해서 시간복잡도를 줄이는 것 이었다. while p1 < N and p2 < M 을 통해서 포인트변수 p1,p2 중 하나가 nm 중 더 적은 수에 도달하게 되면 반복문이 끝나는 형식으로 시작한다. 그 다음 리스트 ab 중 원소가 남은 리스트에 대하여 남은 원소를 빈 리스트 c의 끝에 이어붙이는 식으로 코드를 작성하면 된다. 지금까지는 무작정 문제를 풀어서 정답을 반환시키는 것에만 집중했는데, 시간복잡도도 프로그래밍에 있어서는 문제 해결만큼 중요한 것이었다. 얼마나 효율적이고 좋은 코드를 만드느냐도 생각해야하니까... 그만큼 공부할 것들도 늘어난다는 뜻이겠지..?


5. 수들의 합

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 A:
    for j in A:
        if sum(A[i:j+1]) == M :
            cnt += 1
            
print(cnt)

8 3
1 2 1 3 1 1 1 2

11

오답이다..

## 모범답안
N, M = map(int, input().split())
A = list(map(int, input().split()))

lt, rt = 0, 1 # 부분합의 시작과 끝을 나타낼 인덱스 지정(lt는 rt와 같아질수는 있어도 넘어갈수 X)
tot = A[0] # lt부터 rt-1까지의 연속 부분합 (초기화된 상태. 1을 가리킴)
cnt = 0 # 경우의 수

while True :
    if tot < M : # (1) 부분합이 M보다 작은 경우
        if rt < N :
            tot += A[rt] # 부분합에서 rt에 해당하는 값을 더한다
            rt += 1 # rt 오른쪽으로 한 칸 이동
        else : # rt가 N과 같아져, 더이상 넘어갈 수 있는 인덱스가 없을 때
            break # 반복문 탈출
    
    elif tot == M : # (2) 부분합과 찾으려는 값 M이 일치하는 경우
        cnt += 1 # 경우의수 1 증가
        tot -= A[lt] # 부분합에서 lt에 해당하는 값을 뺀다
        lt += 1 # lt 오른쪽으로 한 칸 이동
    
    else: # (3) 부분합이 M보다 큰 경우
        tot -= A[lt] # 부분합에서 lt에 해당하는 값을 뺀다
        lt += 1 # lt 오른쪽으로 한 칸 이동

print(cnt)

8 3
1 2 1 3 1 1 1 2

5

풀이 아이디어는 다음과 같다.


6. 격자판의 최대합

N * N 의 격자판이 주어졌을 때, 각 행의 합, 각 열의 합, 두 대각선의 합 중 가장 큰 합을 출력하는 프로그램을 작성하시오.

## 내 풀이

# 입력
N = int(input())
a = []
for i in range(N):
    a.append(list(map(int, input().split())))

# 행의 합
r = []
r_sum = 0
for i in range(N):
    for j in range(N):
        r_sum += a[i][j]
    r.append(r_sum)
r_max = max(r)


# 열의 합
c = []
c_sum = 0
for j in range(N):
    for i in range(N):
        c_sum += a[i][j]
    c.append(c_sum)
c_max = max(c)


# 대각선의 합
d1_sum, d2_sum = 0, 0
for i in range(N):
    d1_sum += a[i][i]
    d2_sum += a[i][N-1-i]
d_max = max(d1_sum, d2_sum)

print(max(r_max, c_max, d_max))

5
10 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19

562

오답이다..💢💢💢

틀린이유 : r_sum = 0c_sum = 0for문 밖에 있어서 한 줄의 행/열을 순회할동안 각 행/열
의 합이 이전 행/열의 합에 누적되었던 것 이다. 아래 메모했던 것 처럼..

## 모범답안
N = int(input())
a = [list(map(int, input().split())) for _ in range(N)] # 2차원 배열 한줄에 입력받기

largest = -2147000000

for i in range(N):
    r_sum = c_sum = 0 # 행의 합, 열의 합 초기화
    
    for j in range(N):
        r_sum += a[i][j]
        c_sum += a[j][i]
    
    if r_sum > largest :
        largest = r_sum
    if c_sum > largest :
        largest = c_sum

d1_sum = d2_sum = 0
for i in range(N):
    d1_sum += a[i][i]
    d2_sum += a[i][N-1-i]
    
if d1_sum > largest :
    largest = d1_sum
if d2_sum > largest :
    largest = d2_sum
    
print(largest)

5
10 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19

155

풀이의 핵심은 (1) 2차원 배열 입력받기를 한줄로 쓰는 것, (2) 최댓값 찾기 알고리즘 이었다.
(1)은 행의 개수 N이 주어졌다는 가정하에 가능한 코드이다. 다음과 같이 작성하면 된다.
행렬이름 = [list(map(int, input().split())) for _ in range(N)]
(2)는 매번 하는 방식으로, 먼저 가장 작은 수로 최댓값을 설정한다. 그 다음에, 조건문을 사용해서 현재 값이 초기 최댓값보다 크다면 최댓값을 현재 값으로 변경하는 방식으로 찾아나간다. 이 방법은 최솟값 찾기에도 똑같이 적용되니까 잊지 말도록!

## 최댓값 찾기
n = int(input()) # 현재 값
largest = -2147000000 # 초기 최댓값
if n > largest : 
	largest = n # 최댓값을 현재 값으로 변경
    
## 최솟값 찾기
smallest = 2147000000 # 초기 최솟값
if n < smallest : 
	smallest = n # 최솟값을 현재 값으로 변경

7. 사과나무

N * N (N은 항상 홀수) 격자판으로 이루어진 농장의 각 격자안에는 한 그루의 사과나무가 심어져있다. 사과를 수확할 때 다이아몬드 모양에 해당하는 격자판의 사과만 수확해야할 때, 수확하는 사과의 총 개수를 출력하는 프로그램을 작성하시오.

## 내 풀이
N = int(input())
a = [list(map(int, input().split())) for _ in range(N)]
s = 0 # 총 사과 개수

for i in range(N):
    if i % 2 == 0:
    	s += a[i][(N-1)//2]
        
        
        

머리로는 알겠는데, 코드로 못 풀어내겠음...;;

## 모범답안
N = int(input())
a = [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 += a[i][j]
    if i < N//2 : # 절반 행까지는 인덱스 범위가 커진다
        s -= 1
        e += 1
    else: # 나머지 절반 행부터는 인덱스 범위가 좁혀진다 (s와 e의 증감이 뒤바뀜)
        s += 1
        e -= 1

print(res)

5
10 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19

379

풀이 아이디어 :


8. 곳감 (모래시계)

N * N 격자판으로 이루어진 마당에서 각 격자단위로 말리는 감의 수를 정하고 있다. 해의 위치에 따라 특정 위치의 감이 잘 마르지 않기 때문에, 격자의 행을 기준으로 왼쪽 또는 오른쪽으로 회전시켜 위치를 변경해 모든 감이 잘 마르게 해야한다. 회전명령 정보는 다음과 같다.

  • 첫 번째 수 : 행번호
  • 두 번째 수 : 방향 (0이면 왼쪽, 1이면 오른쪽)
  • 세 번째 수 : 회전하는 격자의 수
    예를들어 회정명령 정보가 2 0 3 이라면 2번째 행을 왼쪽으로 3만큼 회전시키는 명령이다.
    M개의 회전명령을 실행하고 난 후에 마당의 모래시계 모양의 영역에는 감이 총 몇개 있는지 출력하는 프로그램을 작성하시오.
## 내 풀이
N = int(input())
a = [list(map(int, input().split())) for _ in range(N)]
M = int(input()) # 회전명령 개수
b = [list(map(int, input().split())) for _ in range(M)]


for i in range(N) : # a의 행기준
    for j in range(N) : # a의 열기준
        for k in range(M) : # b의 행기준
            r = b[k][0] # r : 행번호
            d = b[k][1] # d : 회전 방향
            m = b[k][2] # m : 회전 격자 수
            if d == 0 : # 왼쪽방향 이동
                a[i][j] = a[i][j-m]
            elif d == 1 : # 오른쪽방향 이동
                a[i][j] = a[i][j+m]
                
                
res = 0 # 감의 개수 합 (초기화)
s = 0 # 탐색할 인덱스의 시작
e = N # 탐색할 인덱스의 끝

for i in range(N):
    for j in range(s,e+1):
        res += a[i][j]
    if i < N//2:
        s += 1
        e -= 1
    else :
        s -= 1
        e += 1

print(res)

a[i][j] = a[i][j+m] 여기서 IndexError: list index out of range 에러가 뜬다..

## 모범답안
N = int(input())
a = [list(map(int, input().split())) for _ in range(N)]
M = int(input())
for i in range(M):
	# h : 행번호/ t : 방향/ k : 회전 격자 수
    h, t, k = map(int, input().split())
    
    if t == 0 : # 방향 = 왼쪽(0)
    	for _ in range(k):
        	a[h-1].append(a[h-1].pop(0)) # 첫번째 원소를 pop하는 동시에 나머지 원소들이 앞으로 한칸씩 당겨진다 => 빈자리에 pop한 첫번째 요소를 다시 추가
    else : # 방향 = 오른쪽(1)
    	for _ in range(k):
        	a[h-1].insert(0, a[h-1].pop()) # 마지막 원소를 pop하는 동시에 나머지 원소들이 앞으로 한칸씩 당겨진다 => 0번째 자리에 pop한 마지막 원소를 삽입

# 모래시계 형태로 원소 합하기 (7번문제와 유사)
res = 0 # 원소 합(초기화)
s = 0 # 시작점
e = n-1 # 끝점

for i in range(N):
	for j in range(s, e+1) : # 0부터 n까지 순회
    	res += a[i][j]
        
        if i < N//2 :
        	s += 1 # 7번문제와 반대로 작동 (점점 좁아지는 형태)
            e -= 1
        else: 
        	s -= 1
            e += 1

print(res)

풀이 아이디어 :

이번 문제의 핵심은 .pop()함수와 .insert()의 작동원리를 알고 있느냐 였다.

  • .pop(인덱스) : 원하는 인덱스의 요소를 뽑아서 리턴하는 동시에, 나머지 원소들이 한칸씩 당겨진다. 괄호안에 아무것도 적지 않으면 자동으로 마지막 원소를 pop한다.
  • .insert(인덱스, 삽입할 원소) : 원하는 인덱스의 위치에 원소를 삽입한다.

문제에서는 h번째 행이라고 적혀있었기 때문에, 인덱스로 접근할때는 h-1을 해야한다는 것도 잊지 말자!
모래시계 형태로 원소의 합을 구하는 방법은 앞서 7번문제와 유사하게 풀면 된다. 7번문제는 다이아몬드 형태였기 때문에 시작점과 끝점 위치, 시작점과 끝점의 값이 변하는 것만 반대로 해주면 모래시계 형태로 변환 가능했다.


9. 봉우리

지도 정보가 N * N 격자판에 주어지고, 각 격자에는 그 지역의 높이가 써져있다. 각 격자판의 숫자 중 자신의 상하좌우 숫자보다 큰 숫자는 봉우리 지역이다. 봉우리 지역이 몇 개 있는지 출력하는 프로그램을 작성하시오. (단, 격자의 가장자리는 0으로 초기화 되었다고 가정한다.)

## 내 풀이
N = int(input())
a = [list(map(int, input().split())) for _ in range(n)]
res = 0

a.insert(0, [0] * n)
a.append([0] * n)

for i in range(N):
    for j in range(N):
        if a[i][j] > a[i-1][j] and a[i][j] > a[i+1][j] and a[i][j] > a[i][j-1] and a[i][j] > a[i][j+1] : 
            res += 1
            
print(res)

풀다가 이건 쫌 아닌듯 싶어서 풀이 들었음..(사유 : 조건문이 너무 길어져서)

## 모범답안
N = int(input())
a = [list(map(int, input().split() for _ in range(N)]

# 가장자리 0으로 초기화
a.insert(0, [0]*N) # 맨 위
a.append([0]*N) # 맨 아래
for x in a : # 각 행을 순회
	x.insert(0, 0) # 맨 왼쪽
    x.append(0) # 맨 오르쪽
    
cnt = 0 # 봉우리 개수 (초기화)
dx = [-1, 0, 1, 0] # x좌표 방향 (좌,상,우,하 순)
dy = [0, 1, 0, -1] # y좌표 방향 (좌,상,우,하 순)

for i in range(1, N+1): # 가장자리 제외하고 순회
	for j in range(1, N+1):
    	if all(a[i][j] > a[i+dx[k]][j+dy[k]] for k in range(4)) : # all(조건) : 조건이 모두 참일 경우에만 참이다
        	cnt += 1

print(cnt)

5
5 3 7 2 3
3 7 1 6 1
7 2 5 3 4
4 3 6 4 1
8 7 3 5 2
10

풀이 아이디어 :

이번 문제의 핵심은 두가지로 나눌 수 있겠다.
1) all() 함수를 알고있는가?
all() 내장함수의 괄호 안에는 반복문으로 순회할 수 있는 모든 원소를 인자로 받을 수 있고, 이 원소들이 모두 참일때만 True를 반환한다.
2) 좌표에 대한 방향벡터를 설정할 수 있는가?
상/하/좌/우 에 대한 각 원소의 방향벡터를 설정해서 반복문으로 원소끼리 비교하는 것이 중요했던 것 같다. 쌤도 이 방식은 웬만하면 외우라고 하셨음
x좌표 : dx = [-1, 0, 1, 0] , y좌표 : dy = [0, 1, 0, -1]


10. 스도쿠 검사

스도쿠는 각 행과 각 열, 그리고 9개의 3 3 크기의 보드에 1부터 9까지의 숫자가 중복없이 나타나도록 보드를 채우면 된다. 완성된 9 9 크기의 스도쿠가 주어졌을 때, 정확하게 풀었다면 "YES"를, 아니라면 "NO"를 출력하는 프로그램을 작성하시오.

## 내 풀이
a = [list(map(int, input().split())) for _ in range(9)]

# 행방향 체크
for i in range(9):
    cnt1 = 0
    for j in range(9):
        if a[i][].count(a[i][j]) == 1:
            cnt1 += 1

for j in range(9):
    cnt2 = 0
    for i in range(9):
        if a[][j].count(a[i][j]) == 1:
            cnt2 += 1
    
    
    
if cnt == 9 :
    print("YES")
else:
    print("NO")
## 모범답안
def sudoku(a):

	for i in range(9):
    	# i가 돌때마다 매번 체크리스트 초기화
		ch1 = [0] * 10 # 행 체크리스트
    	ch2 = [0] * 10 # 열 체크리스트
        
    	for j in range(9):
    		ch1[a[i][j]] = 1
            ch2[a[j][i]] = 1
           
        if sum(ch1) != 9 or sum(ch2) != 9: # 중복된 숫자가 있는 경우
            return False
    
    # 9개의 그룹 순회
    for i in range(3):
    	for j in range(3):
        	ch3 = [0] * 10 # 그룹 체크리스트
            
            # 9개의 각 그룹 내 9개의 숫자 순회
            for k in range(3):
            	for s in range(3):
                	ch3[a[i*3 + k][j*3 + s]] = 1
                    
            if sum(ch3) != 9:
                return False

	return True
    
    
a = [list(map(int, input().split())) for _ in range(9)]
if sudoku(a):
	print("YES")
else:
	print("NO")

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
YES

풀이 아이디어 :
우선 행과 열방향 탐색은 다음과 같다.
다음으로 그룹 탐색이 중요한데, 이 때 4중 for문을 돌기 때문에 다소 헷갈릴 수 있다. 동작원리는 다음과 같다.
모범답안을 보고서도 헷갈렸던 점은 if문의 들여쓰기였던 것 같다. 근데 생각해보면 9개의 숫자들을 모두 체크하고서 다시 초기화해야하니까 이부분을 생각하면 금방 찾을 수 있을 것 같기도 하다.


11. 격자판 회문수

1부터 9까지의 자연수로 채워진 7 * 7 격자판이 주어졌을 때, 가로 또는 세로방향으로 길이 5자리 회문수(앞에서 읽어도 뒤에서 읽어도 같은 수)의 개수를 출력하는 프로그램을 작성하시오.

## 내 풀이
a = [list(map(int, input().split())) for _ in range(7)]
cnt = 0

for i in range(5):
    for j in range(5):
        if a[i][j] == a[i][j+4] :
            if a[i][j+1] == a[i][j+3]:
                cnt += 1
        if a[i][j] == a[i+4][j] :
            if a[i+1][j] == a[i+3][j]:
                cnt += 1

print(cnt)

if a[i][j] == a[i][j+4] : 에서
IndexError: list index out of range 에러가 뜬다..

## 모범답안
board = [list(map(int, input().split())) for _ in range(7)]
cnt = 0

for i in range(3): # i : 5개를 분리하기위한 인덱스 (한 행에 원소7개가 있으므로 3번만 반복)
    for j in range(7): # j : 행을 순회
        
        # 가로방향
        tmp = board[j][i : i+5]
        if tmp == tmp[::-1] : 
            cnt += 1
            
        # 세로방향 (세로방향은 리스트가 아니기 때문에 슬라이싱 불가)
        for k in range(2):
            if board[i+k][j] != board[i+5-k-1][j] :
                break # 회문이 아닐경우
    
        else: # 회문일 경우 (for~else 구문)
            cnt += 1

print(cnt)

2 4 1 5 3 2 6
3 5 1 8 7 1 7
8 3 2 7 1 3 8
6 1 2 3 2 1 1
1 3 1 3 5 3 2
1 1 2 5 6 5 2
1 2 2 2 2 1 5
3

풀이 아이디어 :

ij가 for문을 계속 돌고 있기 때문에 세로방향은 for k in range(2) : 로 대칭에 해당하는 수들이 서로 같은지만 확인하면 된다. 서로 같은지 확인하는 코드가 바로 if a[i+k][j] != a[i+4-k][j]: 였다. 가로방향은 j인덱스가 행을 가리켰지만, 세로방향에서는 열을 가리키고 있으니 주의하자!

profile
벌집처럼 밀도있게 차곡차곡 쌓아나가는중

0개의 댓글