Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby Transpose 메서드로 행과 열을 자유롭게 변환하는 방법

오늘은 Ruby의 transpose 메서드를 활용해 다차원 배열(그리드)을 손쉽게 다루는 방법을 알아보겠습니다.

3×3 정사각형 형태의 다차원 배열이 있다고 가정해 봅시다. 그리고 이 배열의 행(row)을 열(column)로 변환하고 싶다고 해보죠.

왜 이런 작업이 필요할까요?

대표적인 예가 바로 틱택토(Tic-Tac-Toe) 게임입니다. 게임 보드를 그리드 형태로 저장한 뒤, 승리 조건을 확인하려면 , , 대각선을 모두 검사해야 하기 때문입니다.

그런데 여기에 문제가 하나 있습니다. 그리드를 배열로 저장하면 행에는 직접 접근할 수 있지만, 열에는 그렇지 않다는 점입니다.

인덱스로 접근하는 번거로운 방법

여기서 말하는 '직접 접근'이란 each, map 같은 메서드로 배열을 순회할 때 불필요한 인덱싱 없이 간편하게 데이터를 다룰 수 있다는 의미입니다.

예제를 살펴보겠습니다. 먼저 그리드입니다:

grid = [
  [1,2,3],
  [4,5,6],
  [7,8,9]
]

첫 번째 열을 가져오려면 인덱스를 일일이 참조해야 합니다.

예를 들어 첫 번째 열은 다음과 같습니다:

[grid[0][0], grid[1][0], grid[2][0]]

# [1, 4, 7]

반면 첫 번째 행은 아주 간단합니다:

grid[0]

# [1, 2, 3]

열도 행만큼 쉽게 다룰 수 있는 방법은 없을까요?

Transpose 메서드로 해결하는 쉬운 방법

해답은 바로 Array#transpose 메서드입니다. 이 메서드는 행렬의 행과 열을 서로 뒤바꿔 새로운 배열을 반환해 줍니다.

예제:

columns = grid.transpose

네, 딱 한 줄이면 끝납니다!

이제 첫 번째 열을 이렇게 간단히 가져올 수 있습니다:

columns[0]

# [1, 4, 7]

다양한 내장 메서드를 알고 있으면 이처럼 많은 수고를 덜 수 있습니다. 🙂

틱택토 게임에 적용하기

전체 구현을 자세히 설명하지는 않고, 이 메서드가 실제 프로젝트에서 어떻게 활용되는지만 보여드리겠습니다.

틱택토에서 승리하려면 한 행, 한 열, 또는 대각선 중 하나를 자신의 말로 모두 채워야 합니다.

먼저 행을 검사하는 코드입니다:

def check_rows
  @board.each { |row| return row.first if all_equal?(row) }
end

그리고 열을 검사하는 코드입니다:

def check_columns
  @board.transpose.each { |row| return row.first if all_equal?(row) }
end

두 코드의 유일한 차이가 바로 transpose 메서드 하나라는 점에 주목하세요!

참고로 위 코드에서 사용된 all_equal? 메서드는 다음과 같이 구현할 수 있습니다:

def all_equal?(row)
   return if row.first == nil

   row.each_cons(2).all? { |x,y| x == y }
 end

each_cons 메서드에 대해 더 궁금하다면 Enumerable 관련 포스트를 참고해 보세요.

마무리

이번 글에서는 Ruby의 transpose 메서드에 대해 배웠습니다. 완전한 그리드 형태의 배열이 주어졌을 때, transpose를 사용하면 행을 열로 변환해 훨씬 편리하게 접근할 수 있습니다.

이 글이 도움이 되었다면, 더 깊이 있는 Ruby 학습을 위해 제 저서 『Ruby Deep Dive』도 확인해 보시길 추천합니다.