본문 바로가기
알고리즘

[HackerRank] Forming a Magic Square

by 워냥 2024. 11. 28.

0. 들어가며

급하게 코딩테스트가 잡혀서 알고리즘 재활 훈련을 하고 있다.

풀면서 뿌듯했던 문제가 있어 포스팅한다.

1. 문제

Forming a Magic Square | HackerRank

 

Forming a Magic Square | HackerRank

Find the minimum cost of converting a 3 by 3 matrix into a magic square.

www.hackerrank.com

문제 한 장 요약

문제를 간단하게 요약하자면 아래와 같다.

  • 1~9까지의 숫자를 하나씩만 사용하여 가로(3) 세로(3) 대각선(2) 총 8개의 모든 합이 같은 사각형을 magic square라고 부름
  • 입력으로 주어진 사각형에서 magic square를 만드는 최소 비용을 구하는 문제

2. 풀이 과정

처음 문제를 읽었을 때는 굉장히 막막했다.

숫자를 바꾸는 순서가 중요한 줄 알고 DFS or 백트래킹을 생각하고 접근했다.

봐도 봐도 해답이 전혀 보이지 않길래 브루트포스 문제구나 싶었다.

 

좀 더 생각해 보니 사각형의 크기가 3*3으로 고정이었다.

1~9를 하나씩 사용하여 사각형 조합을 만드는 모든 경우의 수는 9! = 약 36만 가지.

경우의 수가 굉장히 넉넉해서 모든 magic square를 만들고 비용을 비교하기로 했다.

코드

더보기
#!/bin/python3

import math
import os
import random
import re
import sys

#
# Complete the 'formingMagicSquare' function below.
#
# The function is expected to return an INTEGER.
# The function accepts 2D_INTEGER_ARRAY s as parameter.
#

def valid_square(arr):
    s = set()
    for i in range(3):
        s.add(sum(arr[i]))
    for j in range(3):
        res = 0
        for i in range(3):
            res += arr[i][j]
        s.add(res)
    s.add(arr[0][0] + arr[1][1] + arr[2][2])
    s.add(arr[0][2] + arr[1][1] + arr[2][0])
    return len(s) == 1

def square_diff(arr, origin_arr):
    res = 0
    for i in range(3):
        for j in range(3):
            res += abs(arr[i][j] - origin_arr[i][j])
    return res

def make_magic_square(num_set, arr, x, y, origin_arr, res):
    if x == 2 and y == 3:
        if not valid_square(arr):
            return res
        tmp = square_diff(arr, origin_arr)
        return min(res, tmp)
    elif y == 3:
        x += 1
        y = 0

    for n in num_set:
        arr[x][y] = n
        new_set = num_set - {n}
        res = make_magic_square(new_set, arr, x, y + 1, origin_arr, res)
    
    return res

def formingMagicSquare(s):
    num_set = set(range(1, 10))
    arr = [[0] * 3 for _ in range(3)]
    return make_magic_square(num_set, arr, 0, 0, s, 1e9)

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    s = []

    for _ in range(3):
        s.append(list(map(int, input().rstrip().split())))

    result = formingMagicSquare(s)

    fptr.write(str(result) + '\n')

    fptr.close()

 

재귀로 1~9까지의 숫자를 이용해 모든 사각형 조합을 만들었고, 사각형이 magic square인 경우 원본 사각형과 비교하여 비용을 구하였다.

코드가 많이 더럽지만... 풀었으니까 됐다.

3. 느낀 점

오랜만에 구현 문제를 풀어서 풀이 중간중간 실수가 있었지만 무난하게 solve 하였다.

방법만 알면 금방 풀어서 백준으로 치면 실버 1~2 정도? 인 것 같다.

역시 알고리즘이 제일 재밌는 것 같다.

'알고리즘' 카테고리의 다른 글

[백준] 파이썬 17396 - 다익스트라와 1e9  (0) 2024.12.07

댓글