[코드트리 챌린지] dx dy technique_기본개념

HKTUOHA·2023년 9월 11일
0

코드트리

목록 보기
1/15
post-thumbnail

⭐실력진단 결과



dx, dy 테크닉을 이용해 격자에서의 이동을 간결하게 구현하는 방법을 배우게 됩니다.

🟢방향에 맞춰 이동

✏️좌표평면 상에서의 dx, dy 테크닉

012 3
dx10-10
dy0-101

⇒ 순서대로 +x축 방향(동쪽), -y축 방향(남쪽), -x축 방향(서쪽), +y축 방향(북쪽)

📌문제


📌나의 코드

n = int(input())
dx, dy = [-1, 0, 0, 1], [0, -1, 1, 0]  # 서, 남, 북, 동

x, y = 0, 0

for _ in range(n):
    direction, distance = input().split()
    distance = int(distance)

    if direction == 'W':
        x += dx[0] * distance
        y += dy[0] * distance
    if direction == 'S':
        x += dx[1] * distance
        y += dy[1] * distance
    if direction == 'N':
        x += dx[2] * distance
        y += dy[2] * distance
    if direction == 'E':
        x += dx[3] * distance
        y += dy[3] * distance

print(x, y)

✏️개선점

move_dir 변수를 선언해 move_dir이 0이면 '서쪽', 1이면 '남쪽', 2이면 '북쪽', 3이면 '동쪽'과 같이 dx, dy에 한번에 접근할 수 있도록 하면 반복되는 코드를 줄일 수 있다.




🟢문자에 따른 명령 2

✏️방향 회전을 위한 dx, dy 정의 방법

  • 시계 방향, 오른쪽 방향
dir_num = (dir_num + 1) % 4

북쪽, 즉 dir_num = 3인 경우 시계 방향으로 90' 회전하면 dir_num = 0이 되어야 하므로 dir_num = (dir_num + 1) % 4가 된다.

  • 반시계 방향, 왼쪽 방향
dir_num = (dir_num - 1 + 4) % 4

반시계 방향의 경우 -1을 하면 되지만, dir_num = 0일 때 dir_num = 3이 되려면 +4을 추가적으로 하며 dir_num = (dir_num + 3) % 4가 되도록 해야 한다.


📌문제


📌나의 코드

# 북쪽 시작
dir_num = 3
x, y = 0, 0

# 동, 남, 서, 북
dx, dy = [1, 0, -1, 0], [0, -1, 0, 1]

n = input()

for i in n:
    if i == 'L':
        dir_num = (dir_num - 1 + 4) % 4
    elif i == 'R':
        dir_num = (dir_num + 1) % 4
    else:
        x, y = x + dx[dir_num], y + dy[dir_num]

print(x, y)

🔓풀이

'L', 'R'일 때 방향 전환을 하고, 'F'일 때 이동한다.




🟠1이 3개 이상 있는 위치

✏️격자에서의 dx, dy

  • 행 = x축, 열 = y축
012 3
dx10-10
dy0-101

⇒ 순서대로 행(x) 아래쪽 방향(남쪽), 열(y) 왼쪽 방향(서쪽), 행(x) 위쪽 방향(북쪽), 열(y) 오른쪽 방향(동쪽)

  • zip 함수를 이용해 dx, dy 좌표를 하나로 묶을 수 있다.
for dx, dy in zip(dxs, dys)
	nx, ny = x + dx, y + dy
  • 확인하고자 하는 위치가 격자 안에 들어오는지 in_range 함수를 작성해 확인해야 한다.
    이때, in_range와 같이 범위를 확인하는 함수는 if문(조건문) 앞에 작성해야 한다.
def in_range(x, y):
	return 0 <= x and x < n and 0 <= y and y < n

📌문제


📌나의 코드

n = int(input())                                            # 격자 크기
grid = [list(map(int, input().split())) for _ in range(n)]  # 격자

# 상하좌우
dxs, dys = [-1, 1, 0, 0], [0, 0, -1, 1]

# 범위 확인
def in_range(x, y):
    return 0 <= x and x < n and 0 <= y and y < n

ans = 0

for i in range(n):
    for j in range(n):
        cnt = 0
        for dx, dy in zip(dxs, dys):
            nx, ny = i + dx, j + dy
            if in_range(nx, ny) and grid[nx][ny] == 1:
                cnt += 1
        if cnt >= 3:
            ans += 1

print(ans)

🔓풀이

i행 j열을 한칸씩 돌아가며 상하좌우 중 1이 있으면 cnt += 1, cnt가 3 이상이면 ans += 1




🟠작은 구슬의 이동

✏️조건에 따라 방향이 변하는 경우

  • 0번과 3번, 1번과 2번이 서로 반대 방향이 되도록 한다.
    3 - 0 = 3, 3 - 1 = 2
012 3
dx01-10
dy100-1
  • 딕셔너리 타입을 이용하면 key-value 형태로 저장되어, 문자에 따른 방향 변환을 쉽게 할 수 있다.

📌문제


📌나의 코드

  • while문
# 격자 크기, 시간
n, t = map(int, input().split())

# 구슬 정(r행 c열 d방향)
r, c, d = input().split()
r = int(r) - 1
c = int(c) - 1

# 0번과 3번, 1번과 2번 반대방향
dxs, dys = [0, 1, -1, 0], [1, 0, 0, -1]

mapper = {
    'R': 0,
    'D': 1,
    'U': 2,
    'L': 3
}

dir_num = mapper[d]

def in_range(x, y):
    return 0 <= x and x < n and 0 <= y and y < n

while t:
    nx, ny = r + dxs[dir_num], c + dys[dir_num]
    if not in_range(nx, ny):
        dir_num = 3 - dir_num
        t -= 1
    t -= 1
    if t < 0:
        break
    r, c = r + dxs[dir_num], c + dys[dir_num]
    

print(r + 1, c + 1)
  • for문 (정답)
# 격자 크기, 시간
n, t = map(int, input().split())

# 구슬 정(r행 c열 d방향)
r, c, d = input().split()
r = int(r) - 1
c = int(c) - 1

# 0번과 3번, 1번과 2번 반대방향
dxs, dys = [0, 1, -1, 0], [1, 0, 0, -1]

mapper = {
    'R': 0,
    'D': 1,
    'U': 2,
    'L': 3
}

dir_num = mapper[d]

def in_range(x, y):
    return 0 <= x and x < n and 0 <= y and y < n

for _ in range(t):
    nx, ny = r + dxs[dir_num], c + dys[dir_num]
    if in_range(nx, ny):
        r, c = nx, ny
    else:
        dir_num = 3 - dir_num
    

print(r + 1, c + 1)
    

🔓풀이

  • while문의 경우 t가 0보다 클 때 t을 1씩 감소시키면서 nx, ny가 격자 범위를 벗어날 경우 방향을 바꾸고, 마지막에 r행 c열을 계산한다.
  • for문의 경우 격자 범위 내에 있을 때 r행 c열을 계산하고, 아니면 방향을 바꾼다.



🔴빙빙 돌며 숫자 사각형 채우기

✏️빙빙 돌며 숫자 적기

  • 격자에서의 이동
    오른쪽(dir = 0): x는 그대로, y += 1
    아래쪽(dir = 1): x += 1, y는 그대로
    왼쪽(dir = 2): x는 그대로, y -= 1
    위쪽(dir = 3): x -= 1, y는 그대로

  • 확인사항

  1. 격자를 벗어났는지 → in_range 함수로 확인
  2. 이미 방문했던 곳인지 → 2차원 배열의 값이 0인지 확인

📌문제


📌나의 코드

n, m = map(int, input().split())
answer = [[0] * m for _ in range(n)]

def in_range(x, y):
    return 0 <= x and x < n and 0 <= y and y < m

# 우, 하, 좌, 상
dxs, dys = [0, 1, 0, -1], [1, 0, -1, 0]  
x, y = 0, 0                  # 시작 위치
dir_num = 0                  # 0: 우, 1: 하, 2: 좌, 3: 상

# 초기값
answer[x][y] = 1

for i in range(2, n * m + 1):
	# 다음 위치값 계산
    nx, ny = x + dxs[dir_num], y + dys[dir_num]
	
    # 나아갈 수 없으면 90' 회전
    if not in_range(nx, ny) or answer[nx][ny] != 0:
        dir_num = (dir_num + 1) % 4
	
    # 다음 위치에 올바른 값 저장
    x, y = x + dxs[dir_num], y + dys[dir_num]
    answer[x][y] = i

for i in range(n):
    for j in range(m):
        print(answer[i][j], end=' ')
    print()

profile
공부 기록

0개의 댓글