[이코테] 구현

Journey log·2021년 4월 1일
0
post-thumbnail

1. 상하좌우

  1. 첫째 줄은 공간의 크기(N*N)를 나타내는 N을 입력.
    1<=N<=100
  2. 둘째 줄에는 이동 방향 입력 1<=이동횟수<=100
    • L:왼쪽으로 한칸, R:오른쪽으로 한칸, U:위로 한 칸, D:아래로 한 칸

1.1 내풀이

N = int(input())
plan = list(input().split())
print(plan)
now = [1, 1]
for step in plan:

  if step == 'R':
    new = [x+y for x, y in zip(now, [0, 1])]
  elif step == 'U':
    new = [x+y for x, y in zip(now, [-1, 0])]
  elif step == 'D':
    new = [x+y for x, y in zip(now, [1, 0])]
  else:
    new = [x+y for x, y in zip(now, [0, -1])]
  
  #공간 벗어나는 경우
  p = [0, N+1]
  new = [i for i in new if i not in p]
  if len(new)==2:
    now = new
print(now)

1.2 책 답안

  • 나는 단계별로 [x, y] 리스트로 만들어서 공간 벗어나는 조건문 만들 때 헷갈렸는데
  • 책은 이동방향, x좌표, y좌표를 각각 리스트로 만들었음
  • 시간복잡도는 O(N) , N은 이동횟수
n = int(input())
x, y = 1, 1
plans = input().split()

# L, R, U, D에 따른 이동 방향
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
move_type = ['L', 'R', 'U', 'D']

for plan in plans:
  # 이동 후 좌표 구하기
  for i in range(len(move_type)):
    if plan == move_type[i]:
      nx = x + dx[i]
      ny = y + dy[i]
  if nx < 1 or ny <1 or nx > n or ny > n:
    continue
  x, y = nx, ny

print(x, y)

2. 시각

정수 N이 입력되고 0<= N <= 23
00시 00분 00초부터 N시 59분 59초까지 모든 시각 중에서 3이 하나라도 포함되는 경우의 수를 구하기

2.1 내 풀이

  • 처음에 3들어간 후보군 [3, 13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
    43, 53] 만들고 합집합으로 풀다가 포기
n = int(input())


count = 0
for i in range(n+1):
  for j in range(60):
    for k in range(60):
      a = list(str(i))+list(str(j))+list(str(k))
      if '3' in a:
        count+=1
print(count)

2.2 책 답안

  • 총 경우의 수 24*60*60 = 86,400 즉, 10만 개 미만이라 완전 탐색해도 시간 많이 걸리지 않음. 전체 100만개 이하일 때는 완전 탐색 할 만 함
  • list로 만들 필요없이 문자열에도 in을 쓸 수 있음.
n = int(input())


count = 0
for i in range(n+1):
  for j in range(60):
    for k in range(60):
      if '3' in str(i)+str(j)+str(k)
        count+=1
print(count)

3. 왕실의 나이트

8x8 좌표평면에 상의 위치를 입력받음. 행은 1~8, 열은 a~h (입력 예시 : a1)
나이트는 L자 형태로만 이동 가능
이동가능한 경우의 수는?

3.1 내 풀이

  • 17분

c, r = list(input())

column = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
c = column.index(c)+1
r = int(r)


x = [1, 1, -1, -1, 2, 2, -2, -2]
y = [2, -2, 2, -2, 1, -1, 1, -1]
count = 0
for i in range(len(x)):
  c2 = c+ x[i]
  r2 = r+ y[i]
  if c2 < 1 or r2 < 1 or c2 > len(column) or r2 > len(column):
    continue
  count += 1
print(count)

3.2 책 답안

  • 알파벳을 좌표로 옮기기 위한 int(ord('b'))-int(ord('a'))+1
  • 1a가 입력되어도 처리되게 하려면? if input_data[0] in ['1','2','3','4','5','6','7','8'] 조건문 추가?
input_data = input()
row = int(input_data[1])
column = int(ord(input_data[0]))-int(ord('a'))+1

steps = [(-2, -1), (-1, -2), (1,-2), (2,-1), (2, 1), (1, 2), (-1, 2), (-2, 1)]

result = 0
for step in steps:
  next_row = row + step[0]
  next_column = column + step[1]
  if next_row >= 1 and next_row <= 8 and next_column >= 1 and next_column <= 8:
    result += 1
print(result)

4. 게임게발

  • NxM 크기의 직사각형 맵. 각각의 칸은 육지(0) 또는 바다(1), 캐릭터는 북(0), 동(1), 남(2), 서(3) 중 한 곳을 바라봄.
  • 캐릭터의 좌표는 (A, B). A는 북쪽으로부터 떨어진 칸 개수, B는 서쪽으로부터 떨어진 칸 개수
  • 매뉴얼
    1. 현재 위치, 방향 기준으로 왼쪽 방향(반시계 90도 회전)부터 차례대로 갈 곳을 정함
    2. 왼쪽 방향에 아직 가보지 않은 칸이 존재한다면, 왼쪽 방향 회전 후 왼쪽으로 한 칸 전진. 왼쪽 방향에 가보지 않은 칸이 없다면, 왼쪽 방향으로 회전만 하고 다시 1단계로
    3. 만약 네 방향 모두 이미 가본 칸이거나 바다로 되어있는 칸인 경우, 바라보는 방향을 유지한 채로 한 칸 뒤로가고 1단계로 돌아감. 단, 뒤쪽 방향이 바다인 칸이라 뒤로 갈 수 없는 경우, 움직임을 멈춤
    3<= N, M <= 50 처음에 캐릭터가 위치한 칸은 항상 육지
  • 이동을 마친 후 캐릭터가 방문한 칸의 수는?

4.1 내풀이

  • 소요시간 : 50분
  • 풀이 틀림.
    (네 방향 모두 이미 가본 칸이거나 바다로 되어있는 칸인 경우 방향 유지한 채로 한 칸 뒤로가는 걸 빠트림)
  • 문제에서 주어진 것처럼 '이미 가본 칸을 기록하는 배열'과 '바다로 되어있는지 알 수 있는 배열'을 따로 만들었다면 조건 설정하기 좀 더 수월했을 것 같다. 나는 이동하기 이전 칸의 방향을 제외한 3방향만 고려하다보니 break하는 조건도 설정하기 어려웠음.
  • 나는 적어도 4번 회전한다고 생각하고 길이 4짜리 리스트를 만들었는데 그럴 필요 없이 답안에선 turn_left() 함수 만들었음.
  • 주변이 다 바다여서 이전칸으로 이동하는거, 나는 왼쪽으로 두번 회전한 (irection+2)%4 방향으로 이동하면 된다고 생각했는데 답안에선 간단히 nx = x - dx[direction] 해줌. (더하는게 아니라 빼줌)

n, m = map(int, input().split())
a, b, d = map(int, input().split())
map1 = [] #지도
for i in range(n):
  map1.append(list(map(int, input().split())))



direction= [0, 3, 2, 1] #북, 서, 남, 동 (반시계 방향)
move = [[-1, 0], [0, -1], [1, 0], [0, 1]] # 북, 서, 남, 동 순으로
result = 1 # 처음 위치한 칸은 항상 육지이므로 기본값 1

while True:
  d_index = direction.index(d) 
  d_index_list = list(range(d_index, d_index+4)) # 최대 4 회 회전
  d_index_list = [x%4 for x in d_index_list] # direction인덱스로 쓰기 위해

  for ind in d_index_list: 
    temp = 0 # (임시) 이동 횟수
    new_a = a + move[ind][0]
    new_b = b + move[ind][1]
    
    # 바다일 때
    if new_a <0 or new_b <0 or new_a >=n or new_b >= n or map1[new_a][new_b] == 1: 
      continue
    # 육지일 떄
    a, b = new_a, new_b
    temp += 1 
    d = direction[ind] # 현재 방향 업데이트
    result += 1
    continue
  if temp == 0: # 주변이 모두 바다일 때
    break


print(result)



4.2 책 답안

  • 최대 4번 회전하니까 for _ in range(4) 생각했었는데 책 답안에서 turn_time 사용.
n, m = map(int, input().split())

# 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
d = [[0]*m for _ in range(n)]

# 현재 좌표와 방향 입력받기
x, y, direction = map(int, input().split())
d[x][y] = 1 # 현재 좌표 방문 처리

# 전체 맵 정보를 입력받기
array = []
for i in range(n):
  array.append(list(map(int, input().split() )))

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

# 방향 바꾸는 함수. 방향과 이동을 분리하는군..
def turn_left():
  global direction
  direction -= 1
  if direction == -1:
    direction = 3

# 시뮬레이션 시작
count = 1
turn_time = 0
while True:
  # 왼쪽으로 회전
  turn_left()
  nx = x + dx[direction]
  ny = y + dy[direction]
  #회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동
  if d[nx][ny] == 0 and array[nx][ny]==0:
    d[nx][ny] = 1
    x = nx
    y = ny
    count += 1
    turn_time = 0
    continue 
  #회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우
  else:
    turn_time += 1
  #네 방향 모두 갈 수 없는 경우
  if turn_time ==4:
    nx =  x - dx[direction] #turn_left 4번 돌아간 상태이므로 원래 방향일것임
    ny = y - dy[direction]
    #뒤로 갈 수 있다면 뒤로 이동하기
    if array[nx][ny] == 0: #뒤로 갈 수 없는 경우는?
      x = nx
      y = ny
    # 뒤가 바다로 막혀있는 경우 
    else :
      break
    turn_time = 0  
print(count)



profile
DEEP DIVER

0개의 댓글

관련 채용 정보