[코테] dx, dy 테크닉(2)

dx,dy 테크닉

  • dx, dy 테크닉을 이용해 격자에서의 이동을 간결하게 구현하는 방법을 배움

격자에서의 dx, dy

  • 격자는 2차원 배열로 표현 가능하다.
      i/j   0 1 2 3 4
      ---------------
      0|    0 0 0 1 0
      1|    0 1 1 1 0
      2|    0 0 0 0 1
      3|    1 0 1 1 1
      4|    1 0 1 1 0
    
    
  • 격자에서 dx, dy 테크닉을 이용하려면 격자에서의 x, y는 행, 열로 생각해야 한다
    image
  • zip 함수를 사용해서 각 방향에 대해 dx, dy의 쌍을 가져다 쓴다.
    • zip 함수 : 넘긴 인자에 list나 tuple 같이 순회가 가능한 변수를 여러 개 넘기면 순서대로 첫 번째 원소부터 끝 원소까지 쌍으로 값을 뽑아주는 함수
    • for elem1, elem2 in zip(arr1, arr2)
  • in_range 함수을 사용해서 (x,y)가 격자 안에 들어오면 true, 그렇지 않으면 false를 반환하도록 한다.
    • 격자 안에서 벗어나면 Runtime Error가 발생하기 때문
      def in_range(x, y):
        return 0 <= x < 5 and 0 <= y < 5
      


  • 5 * 5 크기의 격자가 주어질 때, (3행, 2열) 위치의 인접한 상하좌우 칸에 숫자 1이 몇 개 있는가?
    x, y = 2, 1
    dxs, dys = [0, 1, 0, -1], [1, 0, -1, 0]
    
    # in_range 함수 사용해서 (x,y)가 격자 안에 들어오는 지 판단
    def in_range(x, y):
        return 0 <= x < 5 and 0 <= y < 5
    
    cnt = 0
    # zip 함수 사용
    for dx, dy in zip(dxs, dys):
        nx, ny = x + dx, y + dy
        if in_range(nx, ny) and a[nx][ny] == 1:
            cnt += 1
    print (cnt)
    
    • 여기서 주의할 건 만약 if a[nx][ny] == 1 and in_range(nx, ny)가 되면 (nx, ny)가 격자를 벗어났음에도 값이 1인지를 확인하게 된다. (Runtime Error 발생)
      범위를 확인하는 조건의 경우, 항상 if문 가장 앞에 작성하는 것이 중요!

문제

숫자 0과 1로만 이루어진 n * n 크기의 격자 상태가 주어집니다. 각 칸 중 상하좌우로 인접한 칸 중 숫자 1이 적혀 있는 칸의 수가 3개 이상인 곳의 개수를 세는 프로그램을 작성해보세요. 단, 인접한 곳이 격자를 벗어나는 경우에는 숫자 1이 적혀있지 않은 것으로 생각합니다.

입력 형식

첫 번째 줄에 n이 주어집니다.
두 번째 줄부터는 n개의 줄에 걸쳐 각 줄마다 각각의 행에 해당하는 n개의 숫자가 공백을 사이에 두고 주어집니다. 전부 0과 1로 이루어져 있다고 가정해도 좋습니다.

  • 1 ≤ n ≤ 100

출력 형식

인접한 칸에 숫자 1이 3개 이상 적혀있는 서로 다른 칸의 수를 출력합니다.

입출력 예제

입력:
  4
  0 1 0 1
  0 0 1 1
  0 1 0 1
  0 0 1 0
출력:
  4

✔️ 문제 풀이

  n = int(input())
  arr = [
      list(map(int, input().split()))
      for _ in range(n)
  ]

  ans = 0
  dxs, dys = [0, 1, 0, -1], [1, 0, -1, 0]

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

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

dx, dy 테크닉과 범위를 제한하는 in_range() 함수를 사용해서 (x,y)값의 (nx, ny)가 격자의 범위 내에 있으며, 해당 값이 1인 경우 cnt를 1씩 증가하도록 구현하였다. cnt가 3 이상이면 ans는 1씩 증가하며, 최종적으로 ans를 출력한다.

  • 개선할 부분
    cnt를 리턴하는 함수를 따로 작성하는 게 깔끔할 거 같다.
    def adjacent_cnt(x, y) :
      cnt = 0
      for dx, dy in zip(dxs, dys):
        nx, ny = x + dx, y + dy
        if in_range(nx, ny) and arr[nx][ny] == 1:
          cnt += 1
    
      return cnt
    
    for x in range(n):
      for y in range(n):
          if adjacent_cnt(x, y) >= 3:
              ans += 1
    print(ans)
    



문제출처: 코드트리의 문제 및 풀이를 정리한 내용입니다.

https://www.codetree.ai/missions/5/problems/place-more-than-3-ones?&utm_source=clipboard&utm_medium=text


© 2021. All rights reserved.

yaejinkong의 블로그