171 lines
3.8 KiB
TypeScript
171 lines
3.8 KiB
TypeScript
type Dir = "U" | "D" | "L" | "R"
|
|
type PipeType = "." | "|" | "7" | "J" | "F" | "L" | "-" | "S";
|
|
|
|
type MoveState = {
|
|
fromDir: Dir,
|
|
curX: number,
|
|
curY: number,
|
|
}
|
|
|
|
const transitionTable: Record<Dir, Record<PipeType, Dir | null>> = {
|
|
"U": {
|
|
"|": "U",
|
|
"7": "L",
|
|
"F": "R",
|
|
".": null,
|
|
"J": null,
|
|
"L": null,
|
|
"-": null,
|
|
"S": null
|
|
},
|
|
"D": {
|
|
"|": "D",
|
|
"7": null,
|
|
"F": null,
|
|
".": null,
|
|
"J": "L",
|
|
"L": "R",
|
|
"-": null,
|
|
"S": null
|
|
},
|
|
"L": {
|
|
"|": null,
|
|
"7": null,
|
|
"F": "D",
|
|
".": null,
|
|
"J": null,
|
|
"L": "U",
|
|
"-": "L",
|
|
"S": null,
|
|
},
|
|
"R": {
|
|
"|": null,
|
|
"7": "D",
|
|
"F": null,
|
|
".": null,
|
|
"J": "U",
|
|
"L": null,
|
|
"-": "R",
|
|
"S": null
|
|
}
|
|
}
|
|
|
|
function getNextState(pipeMap: PipeType[][], state: MoveState) {
|
|
const curPipe = pipeMap[state.curY][state.curX];
|
|
const nextDir = transitionTable[state.fromDir][curPipe];
|
|
if (nextDir === null) {
|
|
return null;
|
|
}
|
|
switch (nextDir) {
|
|
case "U":
|
|
state.curY--;
|
|
break;
|
|
case "D":
|
|
state.curY++;
|
|
break;
|
|
case "L":
|
|
state.curX--;
|
|
break;
|
|
case "R":
|
|
state.curX++;
|
|
break;
|
|
}
|
|
state.fromDir = nextDir;
|
|
return state;
|
|
}
|
|
|
|
const input = await Deno.readTextFile("input.txt");
|
|
const lines = input.split("\n").map(x => x.trim()).filter(x => x.length > 0);
|
|
const pipeMap = lines.map(x => {
|
|
return x.split("");
|
|
}) as PipeType[][];
|
|
let startX = 0, startY = 0;
|
|
startY = pipeMap.findIndex(pipeLine => {
|
|
const xIndex = pipeLine.findIndex(x => x === "S")
|
|
if (xIndex !== -1) {
|
|
startX = xIndex;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
console.log(startX, startY);
|
|
|
|
const simplePipeMap: string[][] = new Array(pipeMap.length).fill(".").map(_ => new Array(pipeMap[0].length).fill("."));
|
|
|
|
function iterateStep(pipeMap: PipeType[][],
|
|
state: MoveState,
|
|
fn: (state: MoveState) => void) {
|
|
fn({...state});
|
|
while (true) {
|
|
const nextState = getNextState(pipeMap,{...state});
|
|
if (nextState === null) {
|
|
throw new Error("dead end at " + state.curX + "," + state.curY);
|
|
}
|
|
if (pipeMap[nextState.curY][nextState.curX] === "S") {
|
|
return;
|
|
}
|
|
fn(nextState);
|
|
state = nextState;
|
|
}
|
|
}
|
|
|
|
const initStates = [
|
|
// {
|
|
// fromDir: "U",
|
|
// curX: startX,
|
|
// curY: startY - 1,
|
|
// },
|
|
// {
|
|
// fromDir: "R",
|
|
// curX: startX + 1,
|
|
// curY: startY,
|
|
// },
|
|
{
|
|
fromDir: "D",
|
|
curX: startX,
|
|
curY: startY + 1,
|
|
},
|
|
{
|
|
fromDir: "L",
|
|
curX: startX - 1,
|
|
curY: startY,
|
|
}
|
|
] as MoveState[];
|
|
|
|
for (const initState of initStates) {
|
|
// const index = initStates.indexOf(initState);
|
|
try {
|
|
iterateStep(pipeMap, {...initState}, (state) => {
|
|
simplePipeMap[state.curY][state.curX] = pipeMap[state.curY][state.curX];
|
|
});
|
|
}
|
|
catch(_) {
|
|
console.log("error",initState);
|
|
}
|
|
}
|
|
|
|
simplePipeMap[startY][startX] = "7";
|
|
|
|
// line scan
|
|
// When the line intersects the line of the figure, it is a state in which the line enters or exits the figure.
|
|
|
|
let count = 0;
|
|
for(let iy = 0; iy < simplePipeMap.length; iy++){
|
|
let isInside = false;
|
|
const row = simplePipeMap[iy];
|
|
for(let ix = 0; ix < row.length; ix++){
|
|
const pipe = row[ix];
|
|
if (["|", "J", "L"].includes(pipe)) {
|
|
isInside = !isInside;
|
|
}
|
|
if (pipe === "." && isInside) {
|
|
count++;
|
|
}
|
|
}
|
|
// Reset isInner to false for each new row
|
|
isInside = false;
|
|
}
|
|
|
|
console.log(count);
|