Skip to content

Commit

Permalink
Solve day 13
Browse files Browse the repository at this point in the history
  • Loading branch information
Dlurak committed Dec 13, 2024
1 parent 1dc13cf commit 2c78eed
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 130 deletions.
34 changes: 15 additions & 19 deletions 2023/day06/part1.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import { filterOutNaN, loadData, mapToInt, product, transpose } from '@helper';
import {
lines,
loadData,
mapToInt,
product,
range,
transpose,
words,
} from '@helper';

const input = await loadData();

const races = transpose(
input
.split('\n')
.map((s) => filterOutNaN(mapToInt(s.split(' '))))
.slice(0, -1),
);
const races = transpose(lines(input, (s) => mapToInt(words(s)))).slice(1);

const calculateDistance = (buttonMs: number, time: number) =>
(time - buttonMs) * buttonMs;

const allPossibilites: number[] = [];

for (const race of races) {
const [raceTime, recordDistance] = race;

let possibilities = 0;
for (let i = 0; i <= raceTime; i++)
if (recordDistance < calculateDistance(i, raceTime)) possibilities++;

allPossibilites.push(possibilities);
}
const allPossibilites = races.map(([raceTime, recordDistance]) => {
return range(raceTime + 1).filter(
(i) => recordDistance < calculateDistance(i, raceTime),
).length;
});

console.log(product(allPossibilites));
13 changes: 4 additions & 9 deletions 2023/day06/part2.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import { filterOutNaN, loadData } from '@helper';
import { lines, loadData } from '@helper';

const input = await loadData();

const race = filterOutNaN(
input
.replace(/[^0-9\n]/g, '')
.split('\n')
.map((l) => parseInt(l)),
);
const race = lines(input, (l) => parseInt(l.replace(/[^0-9]/g, '')));

const calculateDistance = (buttonMs: number, time: number) =>
(time - buttonMs) * buttonMs;

const [raceTime, recordDistance] = race;

let possibilities = 0;
for (let i = 0; i <= raceTime; i++)
for (let i = 0; i <= raceTime; i++) {
if (recordDistance < calculateDistance(i, raceTime)) possibilities++;
}

console.log(possibilities);
38 changes: 38 additions & 0 deletions 2023/day07/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { countGroups } from "@helper";
import { sumBy } from "../../helpers/sum";

const numCardLabels = ['2', '3', '4', '5', '6', '7', '8', '9', 'T'];
const faceCardLabels = ['Q', 'K', 'A'];
const cardLabels = ['J', ...numCardLabels, ...faceCardLabels];

export const scoreHighCards = (cards: string) => {
return sumBy(
cards.split('').toReversed(),
(c, i) => (cardLabels.indexOf(c) + 1) * 100 ** i,
);
};

/**
* Things like full house...
*/
export const scoreHandType = (cards: string) => {
const cardCounts = countGroups(cards.split(''));

const counts = Object.entries(cardCounts)
.filter(([type]) => type !== 'J')
.map(([_, amount]) => amount)
.sort((a, b) => b! - a!);

const twoCount = counts.filter((c) => c === 2).length;

counts[0] = (counts[0] ?? 0) + (cardCounts.J ?? 0);

if (counts[0] === 5) return 70_000_000_000;
if (counts[0] === 4) return 60_000_000_000;
if (counts.includes(3) && counts.includes(2)) return 50_000_000_000;
if (counts[0] === 3) return 40_000_000_000;
if (twoCount === 2) return 30_000_000_000;
if (counts[0] === 2) return 20_000_000_000;

return 10_000_000_000;
};
58 changes: 10 additions & 48 deletions 2023/day07/part1.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,16 @@
import { loadData, sum, countGroups } from '@helper';
import { loadData, countGroups, sumBy, sort, words, lines } from '@helper';
import { scoreHandType, scoreHighCards } from './lib';

const input = await loadData();

const numCardLabels = ['2', '3', '4', '5', '6', '7', '8', '9', 'T'];
const faceCardLabels = ['J', 'Q', 'K', 'A'];
const cardLabels = [...numCardLabels, ...faceCardLabels];

const toCardValue = (card: string) => cardLabels.indexOf(card) + 1;

const scoreHighCards = (cards: string) =>
sum(
cards
.split('')
.reverse()
.map((c, i) => toCardValue(c) * 100 ** i),
);

/**
* Things like full house...
*/
const scoreHandType = (cards: string) => {
const cardCounts = countGroups(cards.split(''));

const counts = Object.values(cardCounts).sort((a, b) => b - a);
const amountOfTwo = counts.filter((c) => c === 2).length;

if (counts[0] === 5) return 70_000_000_000;
if (counts[0] === 4) return 60_000_000_000;
if (counts.includes(3) && counts.includes(2)) return 50_000_000_000;
if (counts[0] === 3) return 40_000_000_000;
if (amountOfTwo === 2) return 30_000_000_000;
if (counts[0] === 2) return 20_000_000_000;

return 10_000_000_000;
};

const scoreHand = (hand: string) => scoreHighCards(hand) + scoreHandType(hand);

const hands = input
.split('\n')
.map((l) => l.split(/\s+/))
.map(([cards, bid]) => ({
// cards: toCardValue(cards),
const hands = lines(input, (l) => {
const [cards, bid] = words(l);
return {
bid: parseInt(bid),
score: scoreHand(cards),
}))
.slice(0, -1);
score: scoreHighCards(cards) + scoreHandType(cards),
};
});

const winnings = hands
.sort(({ score: scoreA }, { score: scoreB }) => scoreA - scoreB)
.map(({ bid }, index) => bid * (index + 1));
const winnings = sort(hands, ({ score }) => score);

console.log(sum(winnings));
console.log(sumBy(winnings, ({ bid }, index) => bid * (index + 1)));
63 changes: 10 additions & 53 deletions 2023/day07/part2.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,16 @@
import { loadData, sum, countGroups } from '@helper';
import { loadData, sumBy, sort, lines, words } from '@helper';
import { scoreHandType, scoreHighCards } from './lib';

const input = await loadData();

const numCardLabels = ['2', '3', '4', '5', '6', '7', '8', '9', 'T'];
const faceCardLabels = ['Q', 'K', 'A'];
const cardLabels = ['J', ...numCardLabels, ...faceCardLabels];

const toCardValue = (card: string) => cardLabels.indexOf(card) + 1;

const scoreHighCards = (cards: string) =>
sum(
cards
.split('')
.reverse()
.map((c, i) => toCardValue(c) * 100 ** i),
);

/**
* Things like full house...
*/
const scoreHandType = (cards: string) => {
const cardCounts = countGroups(cards.split(''));

const counts = Object.entries(cardCounts)
.filter(([type, _]) => type !== 'J')
.map(([_, amount]) => amount)
.sort((a, b) => b - a);

const twoCount = counts.filter((c) => c === 2).length;

counts[0] = (counts[0] ?? 0) + (cardCounts.J ?? 0);

if (counts[0] === 5) return 70_000_000_000;
if (counts[0] === 4) return 60_000_000_000;
if (counts.includes(3) && counts.includes(2)) return 50_000_000_000;
if (counts[0] === 3) return 40_000_000_000;
if (twoCount === 2) return 30_000_000_000;
if (counts[0] === 2) return 20_000_000_000;

return 10_000_000_000;
};

const scoreHand = (hand: string) => scoreHighCards(hand) + scoreHandType(hand);

const hands = input
.split('\n')
.map((l) => l.split(/\s+/))
.map(([cards, bid]) => ({
const hands = lines(input, (l) => {
const [cards, bid] = words(l);
return {
bid: parseInt(bid),
score: scoreHand(cards),
}))
.slice(0, -1);
score: scoreHighCards(cards) + scoreHandType(cards),
};
});

const winnings = hands
.sort(({ score: scoreA }, { score: scoreB }) => scoreA - scoreB)
.map(({ bid }, index) => bid * (index + 1));
const winnings = sort(hands, ({ score }) => score);

console.log(sum(winnings));
console.log(sumBy(winnings, ({ bid }, index) => bid * (index + 1)));
45 changes: 45 additions & 0 deletions 2024/day12/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Coordinate, Matrix } from '@helper';
import { getFloodFillCoordinates, range, valueAtCoord } from '@helper';

type Groups = Record<string, Set<string>[]>;

const addToGroup = (
matrix: Matrix<string>,
groups: Groups,
coord: Coordinate,
) => {
const value = valueAtCoord(matrix, coord)!;

const setExists = groups[value]?.some((set) =>
set.has(`${coord.col}|${coord.row}`),
);
if (setExists) {
return;
}

const filledCoords = getFloodFillCoordinates(matrix, coord).map(
({ col, row }) => `${col}|${row}`,
);

if (!groups[value]) {
groups[value] = [new Set(filledCoords)];
return;
}
if (!setExists) {
groups[value].push(new Set(filledCoords));
return;
}
};

export const generateGroups = (matrix: Matrix<string>) => {
let groups: Record<string, Set<string>[]> = {};

for (const row of range(matrix.length)) {
for (const col of range(matrix[row].length)) {
const coord = { row, col };
addToGroup(matrix, groups, coord);
}
}

return Object.values(groups).flat()
};
26 changes: 26 additions & 0 deletions 2024/day12/part1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {
getneighboringItems,
lines,
loadData,
sumBy,
valueAtCoord,
} from '@helper';
import { generateGroups } from './lib';

const input = await loadData();
const matrix = lines(input, (l) => l.split(''));
const regions = generateGroups(matrix);

const regionPerimeter = (region: Set<string>) => {
const coords = [...region].map((str) => {
const [colStr, rowStr] = str.split('|', 2);
return { col: parseInt(colStr), row: parseInt(rowStr) };
});
const value = valueAtCoord(matrix, coords[0]);
return sumBy(coords, (c) => {
const neighboringValues = Object.values(getneighboringItems(matrix, c));
return neighboringValues.filter((v) => v !== value).length;
});
};

console.log(sumBy(regions, (r) => regionPerimeter(r) * r.size));
62 changes: 62 additions & 0 deletions 2024/day12/part2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { OFFSETS } from '@constants';
import {
Coordinate,
applyOffset,
lines,
loadData,
sumBy,
valueAtCoord,
} from '@helper';
import { generateGroups } from './lib';

const input = await loadData();
const matrix = lines(input, (l) => l.split(''));
const regions = generateGroups(matrix);

const innerCornerCounts = (coords: Coordinate[], value: string) => {
const offsets = [
[OFFSETS.top, OFFSETS.left, OFFSETS.topLeft],
[OFFSETS.top, OFFSETS.right, OFFSETS.topRight],
[OFFSETS.bottom, OFFSETS.left, OFFSETS.bottomLeft],
[OFFSETS.bottom, OFFSETS.right, OFFSETS.bottomRight],
];

return sumBy(coords, (coord) => {
return offsets.filter(([off1, off2, off3]) => {
return (
valueAtCoord(matrix, applyOffset(coord, off1)) === value &&
valueAtCoord(matrix, applyOffset(coord, off2)) === value &&
valueAtCoord(matrix, applyOffset(coord, off3)) !== value
);
}).length;
});
};

const outerCornerCounts = (coords: Coordinate[], value: string) => {
const offsets = [
[OFFSETS.top, OFFSETS.left],
[OFFSETS.top, OFFSETS.right],
[OFFSETS.bottom, OFFSETS.left],
[OFFSETS.bottom, OFFSETS.right],
];
return sumBy(coords, (coord) => {
return offsets.filter(([off1, off2]) => {
return (
valueAtCoord(matrix, applyOffset(coord, off1)) !== value &&
valueAtCoord(matrix, applyOffset(coord, off2)) !== value
);
}).length;
});
};

const sidesOfRegion = (region: Set<string>) => {
const coords = [...region].map((str) => {
const [colStr, rowStr] = str.split('|', 2);
return { col: parseInt(colStr), row: parseInt(rowStr) };
});
const value = valueAtCoord(matrix, coords[0])!;

return outerCornerCounts(coords, value) + innerCornerCounts(coords, value);
};

console.log(sumBy(regions, (r) => sidesOfRegion(r) * r.size));
17 changes: 17 additions & 0 deletions 2024/day13/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type Machine = Record<'a' | 'b' | 'prize', number[]>;

export const buttonPresses = ({ a, b, prize }: Machine) => {
const [xa, ya] = a;
const [xb, yb] = b;
const [xp, yp] = prize;

const d = xa * yb - xb * ya;
const d1 = xp * yb - xb * yp;
const d2 = xa * yp - xp * ya;

if (d === 0 || d1 % d !== 0 || d2 % d !== 0) {
return;
}

return { a: d1 / d, b: d2 / d };
};
Loading

0 comments on commit 2c78eed

Please sign in to comment.