시뮬레이션 문제는 어떤 메소드가 필요할지 파악하는게 가장 중요한것 같다..

흐름이 복잡해서 직접 손으로 그려보는 과정도 느린거 같지만 정확도를 높여준다.

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
}

참고 : https://www.acmicpc.net/problem/20056