문제에서 주어진대로 그대로 구현하면 되는 문제입니다. 두 직선의 교점을 구하는 공식, 교점이 생기지 않는 두 직선의 특징까지 모두 주어졌습니다.
일단 x, y 좌표가 모두 정수인 교점부터 구해야 하는데요. 조합을 활용해서 직선 2개씩 묶어서 교점 구하는 공식에 대입해서 교점들을 구합니다.
교점을 표시할 때 조건은 사각형을 최소한의 크기로 만들어야 한다는 것입니다. 최소한의 크기의 사각형을 만들기 위해서는 교점들의 x, y좌표의 최소, 최댓값을 구해야 합니다. 최소, 최댓값을 가지고 사각형의 가로, 세로 크기를 구하고 사각형에 교점들을 표시하면 됩니다.
// 직선 2개씩 묶어주는 조합
func combination(_ array: [[Int]]) -> [[[Int]]] {
var result = [[[Int]]]()
func combi(_ now: [[Int]], _ index: Int) {
if now.count == 2 {
result.append(now)
return
}
for i in index..<array.count {
let new = now + [array[i]]
combi(new, i + 1)
}
}
combi([], 0)
return result
}
// 두 직선 사이에 교점을 구하는 함수 -> 교점이 없거나 교점의 좌표가 정수가 아닌 경우 nil을 리턴
func getPoint(_ line1: [Int], _ line2: [Int]) -> (Int, Int)? {
// 나눗셈을 위해서 Double로 타입 변환
let line1 = line1.map { Double($0) }
let line2 = line2.map { Double($0) }
let a = line1[0], b = line1[1], e = line1[2]
let c = line2[0], d = line2[1], f = line2[2]
// 교점이 없는 경우 (= 기울기가 같은 경우) nil
if a * d == b * c { return nil }
// 교점 좌표 구하기
let x = (b * f - e * d) / (a * d - b * c)
let y = (e * c - a * f) / (a * d - b * c)
// 교점 좌표가 둘 다 정수가 아니면 nil
guard x - Double(Int(x)) == 0 && y - Double(Int(y)) == 0 else { return nil }
// 정수 리턴
return (Int(x), Int(y))
}
func solution(_ line:[[Int]]) -> [String] {
let points = combination(line).compactMap { getPoint($0[0], $0[1]) }
// 교점의 x, y의 최솟값, 최댓값을 구한다.
var minX = Int.max, maxX = Int.min
var minY = Int.max, maxY = Int.min
for point in points {
let x = point.0, y = point.1
if x < minX {
minX = x
}
if x > maxX {
maxX = x
}
if y < minY {
minY = y
}
if y > maxY {
maxY = y
}
}
// 최소 크기의 사각형을 만든다.
var ans = Array(repeating: Array(repeating: ".", count: maxX - minX + 1), count: maxY - minY + 1)
// 그 사각형에 교점을 나타내는 *을 찍는다.
for point in points {
let x = point.0 - minX
let y = maxY - point.1
ans[y][x] = "*"
}
// x축은 String으로 다시 합쳐서 리턴
return ans.map { $0.joined() }
}