시뮬레이션 문제는 어떤 메소드가 필요할지 파악하는게 가장 중요한것 같다..
흐름이 복잡해서 직접 손으로 그려보는 과정도 느린거 같지만 정확도를 높여준다.
dy, dx 부분에서 애를 좀 많이 먹었다.. 대각선을 어떻게 처리해 주어야 할까 한참 고민하다가 결국 다른 분들껄 참조..
import Foundation
struct FireBall {
let y: Int, x:Int, m: Int, s: Int, d: Int
}
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let N = input[0], M = input[1], K = input[2]
var field: [[Int]: [FireBall]] = [:]
(0..<M).forEach { _ in
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let fireBall = FireBall(y: input[0], x: input[1], m: input[2], s: input[3], d: input[4])
field[[input[0], input[1]]] = field[[input[0], input[1]]] != nil ? field[[input[0], input[1]]]! + [fireBall] : [fireBall]
}
(0..<K).forEach { _ in
move()
}
print( field.flatMap { $1 }.reduce(0) { $0 + $1.m } )
func move() {
var newField: [[Int]: [FireBall]] = [:]
field.flatMap { $1 }.forEach { moveFireBall($0, &newField) }
newField.filter { $0.1.count > 1 }.forEach {
newField[$0.0] = []
divisionFireBall($0.0, $0.1, &newField)
}
field = newField
}
func moveFireBall(_ fireBall: FireBall, _ field: inout [[Int]: [FireBall]]) {
let dy = [-1, -1, 0, 1, 1, 1, 0, -1]
let dx = [0, 1, 1, 1, 0, -1, -1, -1]
let ny = (fireBall.y + N + ((fireBall.s % N) * dy[fireBall.d])) % N
let nx = (fireBall.x + N + ((fireBall.s % N) * dx[fireBall.d])) % N
let new = FireBall(y: ny, x: nx, m: fireBall.m, s: fireBall.s, d: fireBall.d)
field[[ny, nx]] = field[[ny, nx]] != nil ? field[[ny, nx]]! + [new] : [new]
}
func divisionFireBall(_ point: [Int], _ fireBalls: [FireBall], _ field: inout [[Int]: [FireBall]]) {
var sumM = 0
var sumS = 0
var d = [0,2,4,6]
fireBalls.enumerated().forEach {
sumM += $1.m
sumS += $1.s
if $0 == 0 { return }
if !isSame(fireBalls[$0-1].d, $1.d) {
d = [1,3,5,7]
}
}
let nm = sumM / 5
let ns = sumS / fireBalls.count
if nm == 0 {
field[point] = []
return
}
let newFireBalls = d.map { FireBall(y: point[0], x: point[1], m: nm, s: ns, d: $0) }
field[point] = newFireBalls
}
func isSame(_ pre: Int, _ now: Int) -> Bool {
(pre + now) % 2 == 0
}