Skip to content

Commit

Permalink
2023/12 - pretty messy
Browse files Browse the repository at this point in the history
  • Loading branch information
CForrest97 committed Dec 12, 2023
1 parent 60f9f23 commit 94ca659
Show file tree
Hide file tree
Showing 7 changed files with 1,170 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
| 09 | 0.4ms | 0.4ms |
| 10 | 19.8ms | 27.7ms |
| 11 | 1.9ms | 1.9ms |
| 12 | 1.4ms | 17.2ms |

### 2018

Expand Down
1 change: 1 addition & 0 deletions src/2023/12/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[--- Day 12: Hot Springs ---](https://adventofcode.com/2023/day/12)
39 changes: 39 additions & 0 deletions src/2023/12/hotSprings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { hotSprings } from "./hotSprings";

describe("2023/12", () => {
describe("part A", () => {
it("should solve the example input", async () => {
const input = await hotSprings.partA.getExampleInput();

const output = hotSprings.partA.solve(input);

expect(output).toBe(21);
});

it("should solve the puzzle input", async () => {
const input = await hotSprings.partA.getPuzzleInput();

const output = hotSprings.partA.solve(input);

expect(output).toBe(7_047);
});
});

describe("part B", () => {
it("should solve the example input", async () => {
const input = await hotSprings.partB.getExampleInput();

const output = hotSprings.partB.solve(input);

expect(output).toBe(525_152);
});

it("should solve the puzzle input", async () => {
const input = await hotSprings.partB.getPuzzleInput();

const output = hotSprings.partB.solve(input);

expect(output).toBe(17_391_848_518_844);
});
});
});
122 changes: 122 additions & 0 deletions src/2023/12/hotSprings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { add, repeat } from "ramda";
import { parseLines, parseNumber } from "../../helpers/parsers";
import { readInput } from "../../helpers/readInput";
import { Day } from "../../helpers/types";

type Spring = "?" | "." | "#";
type ParsedRow = { springs: Spring[]; groups: number[] };

const parseInput = (input: string): ParsedRow[] =>
parseLines(input).map((row) => {
const [springs, groups] = row.split(" ");

return {
springs: springs.split("") as Spring[],
groups: groups.split(",").map(parseNumber),
};
});

const isEnoughSpaceForBroken = (
springs: Spring[],
groups: number[],
springIndex: number,
groupIndex: number,
) => {
let groupsSum = groups.length - groupIndex - 1;

for (let i = groupIndex; i < groups.length; i += 1) groupsSum += groups[i];

return groupsSum <= springs.length - springIndex;
};

const onlyOperationalRemaining = (springs: Spring[], springIndex: number) => {
for (let i = springIndex; i < springs.length; i += 1)
if (springs[i] === "#") return false;

return true;
};

const isStartOfContiguousBroken = (
springs: Spring[],
groups: number[],
springIndex: number,
groupIndex: number,
) => {
if (
springIndex + groups[groupIndex] > springs.length ||
!(springs[springIndex + groups[groupIndex]] !== "#")
)
return false;

for (let i = 0; i < groups[groupIndex]; i += 1)
if (springs[springIndex + i] === ".") return false;

return true;
};

const countArrangements = ({ springs, groups }: ParsedRow) => {
const cache: Map<number, number> = new Map();

const memCountArrangements = (springIndex: number, groupIndex: number) => {
const key = springIndex * (groups.length + 1) + groupIndex;

const cachedValue = cache.get(key);
if (cachedValue !== undefined) return cachedValue;

let value = 0;

if (springIndex === springs.length) {
value = groupIndex === groups.length ? 1 : 0;
} else if (groupIndex === groups.length) {
value = onlyOperationalRemaining(springs, springIndex) ? 1 : 0;
} else if (
!isEnoughSpaceForBroken(springs, groups, springIndex, groupIndex)
) {
value = 0;
} else if (springs[springIndex] === ".") {
value = memCountArrangements(springIndex + 1, groupIndex);
} else {
if (isStartOfContiguousBroken(springs, groups, springIndex, groupIndex)) {
value = memCountArrangements(
springIndex + groups[groupIndex] + 1,
groupIndex + 1,
);
}

if (springs[springIndex] === "?") {
value += memCountArrangements(springIndex + 1, groupIndex);
}
}

cache.set(key, value);
return value;
};

return memCountArrangements(0, 0);
};

const unfold = ({ springs, groups }: ParsedRow): ParsedRow => ({
springs: repeat(springs.join(""), 5).join("?").split("") as Spring[],
groups: repeat(groups, 5).flat(),
});

const solvePartA = (input: string) =>
parseInput(input).map(countArrangements).reduce(add);

const solvePartB = (input: string) =>
parseInput(input).map(unfold).map(countArrangements).reduce(add);

export const hotSprings: Day = {
day: 12,
year: 2023,
partA: {
getExampleInput: () => readInput(__dirname, "input/example"),
getPuzzleInput: () => readInput(__dirname, "input/puzzle"),
solve: solvePartA,
},
partB: {
getExampleInput: () => readInput(__dirname, "input/example"),
getPuzzleInput: () => readInput(__dirname, "input/puzzle"),
solve: solvePartB,
},
};
6 changes: 6 additions & 0 deletions src/2023/12/input/example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1
Loading

0 comments on commit 94ca659

Please sign in to comment.