const input = await Deno.readTextFile("input.txt");
const initMap = input.split("\n").map(x => x.trim())
    .filter(x => x.length > 0)
    .map(x => x.split(""));

function map2d<T, S>(map: T[][], fn: (ch: T, x: number, y: number) => S): S[][] {
    return map.map((line, y) => line.map((ch, x) => fn(ch, x, y)));
}
function mapToString(map: (string | number)[][]) {
    return map.map(x => x.map(ch => `${ch}`).join(",")).join("\n");
}

function newMap() {
    return map2d(initMap, (ch, x, y) => {
        return ch === "S" ? (".") : ch;
    }) as (string | number)[][];
}

let map = newMap();
map[65][65] = 0;
// let map = map2d(initMap, (ch, x, y) => {
//     return ch === "S" ? (0 as number) : ch;
// });


// let map = map2d(initMap, (ch, x, y) => {
//     return ch === "S" ? 0 : (ch === "." ? "unknown" : "rock");
// });
function cycle(map: (string | number)[][], steps: number) {
    for (let step = 0; step < steps; step++) {
        // copy map
        const nextMap = map2d(map, (ch) => { return ch; });
        // propagate steps
        map2d(map, (ch, x, y) => {
            if (typeof ch === "number") {
                const nextStep = ch + 1;

                const min = (a: number, b: number | string) => {
                    if (typeof b === "string") {
                        return a;
                    }
                    return Math.min(a, b);
                }

                if (x > 0 && nextMap[y][x - 1] !== "#") {
                    nextMap[y][x - 1] = min(nextStep, nextMap[y][x - 1]);
                }
                if (x < map[0].length - 1 && map[y][x + 1] != "#") {
                    nextMap[y][x + 1] = min(nextStep, nextMap[y][x + 1]);
                }
                if (y > 0 && map[y - 1][x] != "#") {
                    nextMap[y - 1][x] = min(nextStep, nextMap[y - 1][x]);
                }
                if (y < map.length - 1 && map[y + 1][x] != "#") {
                    nextMap[y + 1][x] = min(nextStep, nextMap[y + 1][x]);
                }
            }
            return nextMap[y][x];
        });
        map = nextMap;
    }
    // console.log(mapToString(map));
    const even = map.map(line => line.map(x => typeof x === "number" ? (x % 2) : 0)
        .reduce((a, b) => a + b, 0)).reduce((a, b) => a + b, 0);
    const odd = map.map(line => line.map(x => typeof x === "number" ? ((x + 1) % 2) : 0)
        .reduce((a, b) => a + b, 0)).reduce((a, b) => a + b, 0)
    console.log("even", even);
    console.log("odd", odd);
    return {
        even,
        odd
    }
}

console.log("full fill")
cycle(map, 131 * 2);
map = map2d(initMap, (ch, x, y) => {
    return ch === "S" ? (".") : ch;
});

console.log("0,0 start cycle 131 - 65")
map[0][0] = 0;
cycle(map, 131 - 65);
console.log("cycle 131 + 65")
cycle(map, 131 + 65);
map[0][0] = ".";

console.log("130,0 start cycle 131 - 65")
map[130][0] = 0;
cycle(map, 131 - 65);
console.log("cycle 131 + 65")
cycle(map, 131 + 65);
map[130][0] = ".";

console.log("0,130 start cycle 131 - 65")
map[0][130] = 0;
cycle(map, 131 - 65);
console.log("cycle 131 + 65")
cycle(map, 131 + 65);
map[0][130] = ".";

console.log("130,130 start cycle 131 - 65")
map[130][130] = 0;
cycle(map, 131 - 65);
console.log("cycle 131 + 65")
cycle(map, 131 + 65);
map[130][130] = ".";


console.log("65,0 start cycle 131")
// map = newMap();
map[65][0] = 0;
cycle(map, 131);
map[65][0] = ".";

console.log("0,65 start cycle 131")
// map = newMap();
map[0][65] = 0;
cycle(map, 131);
map[0][65] = ".";

console.log("130, 65 start cycle 131")
// map = newMap();
map[131 - 1][65] = 0;
cycle(map, 131);
map[131 - 1][65] = ".";

console.log("65,130 start cycle 131")
// map = newMap();
map[65][131 - 1] = 0;
cycle(map, 131);
map[65][131 - 1] = ".";
