본문 바로가기
I can do it on my own!/우당탕탕

[이코테] 15강 문제 '왕실의 나이트'

by zivvon 2023. 5. 19.
목차 접기

문제

행복 왕국의 왕실 정원은 체스판과 같은 8 x 8 좌표 평면입니다. 왕실 정원의 특정한 한 칸에 나이트가 서있습니다. 나이트는 매우 충성스러운 신하로서 매일 무술을 연마합니다.

 

나이트는 말을 타고 있기 때문에 이동을 할 때는 L자 형태로만 이동할 수 있으며 정원 밖으로는 나갈 수 없습니다.

 

나이트는 특정 위치에서 다음과 같은 2가지 경우로 이동할 수 있습니다.

1. 수평으로 두 칸 이동한 뒤에 수직으로 한 칸 이동하기

2. 수직으로 두 칸 이동한 뒤에 수평으로 한 칸 이동하기

 

이처럼 8 x 8 좌표 평면에서 나이트의 위치가 주어졌을 때 나이트가 이동할 수 있는 경우의 수를 출력하는 프로그램을 작성하세요. 왕실의 정원에서 행 위치를 표현할 때는 1부터 8로 표현하며, 열 위치를 표현할 때는 a부터 h로 표현합니다.

c2에 있을 때 이동할 수 있는 경우의 수는 6가지입니다.

 

문제 조건

풀이 시간 20분, 시간 제한 1초, 메모리 제한 128MB

 

입력

첫째 줄에 8 x 8 좌표 평면상에서 현재 나이트가 위치한 곳의 좌표를 나타내는 두 문자로 구성된 문자열이 입력된다. 입력 문자는 a1처럼 열과 행으로 이뤄진다.

 

출력

첫째 줄에 나이트가 이동할 수 있는 경우의 수를 출력하시오.


'문제 접근'

우선, 방향벡터를 설정해보려 했지만 나이트가 '수평2, 수직1', '수직2, 수평1'일 때의 방향벡터가 다르게 설정되어 각각의 케이스로 나눴다. 그치만 나눠진 케이스 안에서도 '수평2, 수직1'에서는 y축의 좌표가 좌, 우 방향에 따라 다르게 설정되고 , '수직2, 수평1'에서는 x축의 좌표가 상, 하 방향에 따라 다르게 설정된다는 문제에 부딪쳤다.

 

s = input()

x = s[0] #행
y = s[1] #열

cnt = 0

for i in range(8):
  for j in range(8):
    # case 1 : 수평2, 수직1
    dx = [0, 0, -1, 1]
    x = x + dx[i]

    # 좌로 움직였을 경우
    if dx[0] :
      dy = [-2, 2, -2, -2]
      y = y + dy[i]

    # 우로 움직였을 경우
    if dx[1] :
      dy = [-2, 2, 2, 2,]
      y = y + dy[i]
      
    # case 2 : 수직2, 수평1
    pass

print(cnt)

따라서 위처럼 코드를 짜다가 도저히 해결할 수 없어서 결국 강의를 참고했다.

언제쯤이면 혼자 뚝딱뚝딱 구현해낼까? 🤯

 

'정답 코드'

s = input()

x = int(ord(s[0])) - int(ord('a')) + 1 #행
y = int(s[1]) #열

# 나이트 8가지 방향 정리
steps = [(-2, -1), (-1, -2), (1, -2), (2, -1), (2, 1), (1, 2), (-1, 2), (-2, 1)]

cnt = 0

for step in steps:
  # 이동 위치 확인
  next_row = x + step[0]
  next_col = y + step[1]

  # 공간 안에 들어왔는지 확인
  if next_row >= 1 and next_row <=8 and next_col >= 1 and next_col <=8:
    cnt += 1

print(cnt)

제일 첫 번째로 충격받았던 것 : 방향 벡터 8가지를 x, y축 따로 정의하지 않고 같이 묶어 리스트에 넣었다는 것

이렇게 쉬운 방법이 있었다는 걸 알고 머리가 지끈거렸다.

 

근데 하나 궁금한 점은 문제에는 아래처럼 조건이 주어져있는데 방향벡터는 아래처럼 설정하지 않았다는 점?

나는 문제 조건을 무조건 두 칸 이동 후 한 칸 이동으로 이해했지만 강의 정답 코드는 그냥 한 칸 이동 후 두 칸 이동하기도 하고 그러길래 이건 또 뭐지 싶었다.. 모로가도 정답이기만 하면 되는건지? 내가 이해를 너무 강박적으로 하는건지 모르겠다.

1. 수평으로 두 칸 이동한 뒤에 수직으로 한 칸 이동하기
2. 수직으로 두 칸 이동한 뒤에 수평으로 한 칸 이동하기

 

'공부한 것'

- 아스키 코드 (ASCII) : 영문 알파벳을 사용하는 대표적인 문자 인코딩
- ord() 함수 : 문자열을 아스키코드로 반환할 수 있는 함수
~> 구조 : ord(char)
~> ouput : char에 해당하는 아스키코드를 숫자로 반환
- chr() 함수 : 아스키코드를 문자열로 반환하는 함수
~> 구조 : chr(int) 
~> output : int 값의 아스키코드에 대응하는 문자 반환

 

'돌아보며'

생각보다 문제 접근은 쉽고 간단하게 해야함을 또 한번 깨달았다. 아무래도 짧은 소스코드는 간단한 아이디어에서 나오는 것 같은데 매번 빙빙 돌아가는 나여서 아직도 스스로가 답답하다.. 문제 자주 풀어보면 아이디어 떠올리는 법도 늘겠지! 낙담하지말고 열심히 하자.