220925_COS PRO 2급 : 위험한 지역 몇 개인지 알려주기

Csw·2022년 9월 24일
0

TIL

목록 보기
11/18
post-custom-banner

위험한 지역 몇 개인지 알려주기

COS PRO 2급 Python 4차

문제 안내

문제 설명

4 x 4 크기 격자 모양 지형에 위험 지역이 몇 개인지 알고 싶습니다. 위험지역이란 , , , 인접한 지역이 모두 해당 지역보다 높은 지역입니다.

예를 들어 지역 높이가 아래와 같다면

빨간 영역은 인접한 지역이 모두 해당 지역보다 높은 위험지역입니다.

지역별 높이가 담긴 2차원 배열 height, height의 길이 height_lensolution 함수의 매개변수로 주어질 때, 위험 지역이 몇 개인지 return 하도록 solution 함수를 완성해주세요.

매개변수 설명

지역별 높이가 담긴 2차원 배열 height, height의 길이 height_lensolution 함수의 매개변수로 주어집니다.
각 지역의 높이는 1 이상 50 이하인 자연수입니다.
height_len은 항상 4입니다.

return 값 설명

위험지역이 몇 개인지 return 해주세요.

예시

height = [[3, 6, 2, 8], [7, 3, 4, 2], [8, 6, 7, 3], [5, 3, 2, 9]]
height_len = 4
→ solution(height) = 5

풀이 1

Logic 구조

  1. 2차원 배열이므로, i번째 리스트의 j번째 값의 위치를 좌표를 통해 표현함.
height = [[3, 6, 2, 8], [7, 3, 4, 2], [8, 6, 7, 3], [5, 3, 2, 9]]
# height[0][3]=8 이므로 (0,3)의 좌표값은 8을 의미한다고 해석하면 됨.
  1. 2가지 함수를 생성
  • 1번째 함수
    ▶ 현재 확인하고자 하는 숫자가 4방향(상/하/좌/우)의 값들 중 최소 한 개보다 크다면 더이상 확인할 필요가 없으니 다음 숫자로 넘어가고, 그렇지 않다면(4방향의 값들보다 모두 작다면) 우리가 찾는 값임.
    ▶ 내 값이 비교 대상보다 큰지/작은지를 if문을 통해 4번의 가지치기로 진행하여 판단하고, 모두 통과하는 경우가 바로 우리가 찾는 위험지역이므로 1을 반환
    1. 나보다 왼쪽에 위치한 값이 있는데, 내 값보다 작다면? pass
    2. 나보다 오른쪽에 위치한 값이 있는데, 내 값보다 작다면? pass
    3. 나보다 위쪽에 위치한 값이 있는데, 내 값보다 작다면? pass
    4. 나보다 아래쪽에 위치한 값이 있는데, 내 값보다 작다면? pass
  • 2번째 함수 : 위의 과정을 순서대로 모든 값들에 대해 진행
    • 위험지역을 카운트할 변수를 total로 지정하여 초기 값을 0으로 설정
    • 2차원 배열이므로, 반복문을 중첩으로 사용
    • 1번째 함수의 결과를 total에 누적시켜 최종 위험지역의 갯수를 반환

Code

def check(i,j):
	# 나보다 왼쪽에 값이 있고, 내 값이 내 왼쪽 값보다 크다면
    if i > 0 and height[i][j] > height[i-1][j]:
    # 아무것도 안하고 그냥 넘어감
		pass
    # 나보다 오른쪽에 값이 있고, 내 값이 내 오른쪽 값보다 크다면
    elif i < 3 and height[i][j] > height[i+1][j]:
    # 아무것도 안하고 그냥 넘어감
		pass
    # 나보다 위쪽에 값이 있고, 내 값이 내 위쪽 값보다 크다면
	elif j > 0 and height[i][j] > height[i][j-1]:
    # 아무것도 안하고 그냥 넘어감
		pass
    # 나보다 아래쪽에 값이 있고, 내 값이 내 아래쪽 값보다 크다면
	elif j < 3 and height[i][j] > height[i][j+1]:
    # 아무것도 안하고 그냥 넘어감
		pass
    # 결과적으로, 내가 내 주변(상/하/좌/우)에 있는 값들보다 모두 작다면
	else:
    	# 1을 반환
		return 1
    
    # 내 주변(상/하/좌/우)에 있는 값들 중 최소 하나보다 크다면 1을 반환
	return 0


def solution(height):
	count = 0
    # 16개의 모든 값을 순회하면서
    for i in range(4):
		for j in range(4):
        	# check 함수를 통해 확인한 값을 추가
			count += check(i,j)
	return count

풀이 2

  1. 상/하/좌/우에 대한 비교를 if문의 열거로 구현해야 했던 위의 코드를 개선
    • 아래와 같이 방향을 의미하는 dx, dy 리스트를 도입하여 for문을 통해 간결하게 변경
    • 그러나, 격자 모양 지형의 테두리에 있는 값들은 상/하/좌/우 중 없는 값들도 있을 것이기 때문에, 그런 경우는 for문을 그냥 지나치게 코드를 작성
    • 반복문을 시행하는 모든 횟수에 대해 현재 위치의 값이 비교 위치의 값보다 작다면, 위험지역으로 판단하여 카운트를 1 증가시키는 방향으로 코드 작성

Logic 구조

※ 2가지 함수를 생성

  • 1번째 함수 :
    • target이라는 변수를 도입하여, 초기 값을 0으로 지정.
      • 순차적으로 작업이 진행될 때마다 계속하여 1씩 증가시킴.
      • 반복문의 시행 횟수를 의미함.
      • 코드 내 continue를 사용하기 때문에, 현재 내 위치가 격자 모양 지형의 테두리에 있는 경우에는 target 값이 2 혹은 3이 될 것임.
    • cnt라는 변수를 도입하여, 초기 값을 0으로 지정
      • 반복문을 돌면서 현재 위치의 값이 비교 위치의 값보다 작은 경우, cnt 값을 1씩 증가시킴.
        1. 현재 내 위치를 좌표(x, y)로 설정
        2. 비교할 위치를 좌표 (nx, ny)로 설정
          (nx와 nynew x, new y를 의미)
          for문을 돌면서 dx, dy를 이용하여 nxnyxy와의 관계로 수식을 표현
        3. 그런데, 비교 위치의 좌표 (nx, ny)가 현재 격자 모양 지형의 밖으로 벗어나는 경우는 continue를 통해 다음 반복문을 시행하도록 만듦
        4. for문을 모두 돌고 난 후 target 값과 cnt 값을 비교
        5. target == cnt인 경우만 체크 → 이 경우가 바로 위험지역을 의미하므로, 카운트를 1 증가시킴.
  • 2번째 함수 : 위의 과정을 순서대로 모든 값들에 대해 진행
    • 위험지역을 카운트할 변수를 total로 지정하여 초기 값을 0으로 설정
    • 2차원 배열이므로, 반복문을 중첩으로 사용
    • 1번째 함수의 결과를 total에 누적시켜 최종 위험지역의 갯수를 반환

Code

def check(x,y):
	# target : continue 때문에 건너뛰는 횟수를 제외한, 실제로 for문을 반복하는 횟수
	target = 0
    # cnt : 현재 내 위치(x,y)의 값이 상/하/좌/우의 비교 위치(nx, ny)의 값보다 작은 횟수
	cnt = 0
    # 상/하/좌/우 최대 4번을 반복하겠다
	for _ in range(4):
    	# 비교 대상 nx, ny를 x, y와 dx, dy를 이용하여 표현
        # for문을 4번 돌 때 새로운 점의 좌표는 현재 위치 좌표를 기준으로 각각 우/좌/상/하의 좌표를 의미함.
		nx, ny = x + dx[_], y + dy[_]
        # 만약, 비교 위치의 좌표가 격자 모양 지형의 밖으로 벗어난다면?
		if nx < 0 or nx >=4 or ny < 0 or ny >= 4:
        	# 현재 작업은 그만하고 다음 반복문을 시행해라
			continue
        # 비교 대상의 좌표가 격자 모양 지형 내에 위치한다면    
		else:
        	# 이번 시행은 진행 한것이기 때문에 시행 횟수를 1 증가시킴.
			target += 1
            # 만약, 현재 위치의 좌표값이 비교 위치의 좌표값보다 작다면
			if height[x][y] < height[nx][ny]:
            	# 내가 주변 값보다 작은 횟수를 1 증가시킴.
				cnt +=1
    # 작업을 시행한 횟수가 주변 값보다 작은 횟수와 동일하다면 모든 시행 횟수에 대해 주변 값보다 작은 것이이므로
    # 위험지역에 해당하기 때문에 1을 반환하고, 그렇지 않은 경우는 0을 반환
	return 1 if target == cnt else 0

# dx는 오른쪽(1)/왼쪽(-1)으로의 이동을, dy는 위쪽(1)/아래쪽(-1)으로의 이동을 지정하기 위해 사용하는 리스트
dx = [1,-1,0,0]
dy = [0,0,1,-1]

def solution(height):
	# total : 위험지역을 카운트 하기 위해 할당한 변수
	total = 0
    # i번째 행, j번째 열에 위치한 모든 값들에 대해
	for i in range(4):
		for j in range(4):
        	# 위험지역 여부를 체크하여 반환 값을 위험지역에 더함.
            # 반환값은 0 혹은 1뿐이므로, total 값 자체가 위험지역의 개수를 의미
			total += check(i,j)
	return total
post-custom-banner

0개의 댓글