Skip to content

Commit

Permalink
day 23 (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
adaamz authored Dec 24, 2020
1 parent 10374a2 commit 36c5927
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions 23/final_input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
952438716
2 changes: 2 additions & 0 deletions 23/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Day 23: Crap Cups
https://adventofcode.com/2020/day/23
109 changes: 109 additions & 0 deletions 23/src/23.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
class ListNode<T>
{
public next!: ListNode<T>;

constructor(
public readonly data: T
) {
}
}

class LinkedList<T>
{
constructor(
public head: ListNode<T>
) {
}

public toList(limitFromHead=Infinity): T[]
{
const list = [];
let head: ListNode<T>["next"] = this.head;

let i = 0;
do {
list.push(head!.data);
head = head!.next;
i++;
} while(head !== this.head && i < limitFromHead);

return list;
}
}
type LinkedMapList<T> = Map<T, ListNode<T>>;

function playCrabGame(allCupsNumbers: number[], totalRounds: number, minCupLabel: number, maxCupLabel: number): ListNode<number>
{
const list = new LinkedList(new ListNode(allCupsNumbers[0]));
const map: LinkedMapList<number> = new Map([[list.head.data, list.head]]);
let prev = list.head;
for (let i = 1; i < allCupsNumbers.length; i++) {
const node = new ListNode(allCupsNumbers[i]);
map.set(allCupsNumbers[i], node);

prev.next = node;
prev = node;
}
// circular linked list
prev.next = list.head!;

let currentHead = list.head;

for (let round = 0; round < totalRounds; round++) {
//console.log(`\n-- move ${round + 1} --`);
//console.log(`cups: ${list.toList().map(n => n === currentHead.data ? `(${n})` : n).join(" ")}`);

const pickUpNodesStart = currentHead.next;
const pickUpNodesEnd = currentHead.next.next.next;
const pickUp = new LinkedList(currentHead.next).toList(3);
currentHead.next = currentHead.next.next.next.next;
let destination = currentHead.data - 1;
while (pickUp.indexOf(destination) > -1 || destination < minCupLabel) {
destination--;
if (destination < minCupLabel) {
destination = maxCupLabel;
}
}

//console.log(`pick up: ${pickUp.join(", ")}`);
//console.log(`destination: ${destination}`);

if (!map.has(destination)) {
console.log(`destination ${destination} not found in map: ${[...map.keys()]}`);
throw 'BUG';
}

const destinationNode = map.get(destination)!;
pickUpNodesEnd.next = destinationNode.next;
destinationNode.next = pickUpNodesStart;

currentHead = currentHead.next;
}

//console.log(`-- final --`);
//console.log(`cups: ${list.toList().map((c, i) => i === currentHead.data ? `(${c})` : c).join(" ")}`);

return map.get(1)!;
}

export function countPart1(allCupsNumbers: number[], totalRounds: number): number
{
const gameResult = playCrabGame(
allCupsNumbers,
totalRounds,
Math.min.apply(undefined, allCupsNumbers),
Math.max.apply(undefined, allCupsNumbers)
);

return Number(new LinkedList<number>(gameResult.next).toList(allCupsNumbers.length - 1).join(""));
}

export function countPart2(input: number[]): number
{
const max = Math.max.apply(undefined, input);
const allCupNumbers = [...input, ...Array.from({length: 1e6-max}, (_, i) => max + 1 + i)];

const gameResult = playCrabGame(allCupNumbers, 1e7, Math.min.apply(undefined, input), 1e6);

return gameResult.next.data * gameResult.next.next.data;
}
41 changes: 41 additions & 0 deletions 23/tests/23.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {assertStrictEquals} from "../../deps.ts";
import {countPart1, countPart2} from "../src/23.ts";

Deno.test("Crab Cups: Example test from introduction (Part one)", () => {
const input = (
"389125467"
).split("").map(Number);
const expectedOutput = 92658374;

assertStrictEquals(countPart1(input, 10), expectedOutput);
});

Deno.test("Crab Cups: Final test (Part one)", () => {
const input = (
Deno.readTextFileSync("23/final_input.txt").trimEnd()
).split("").map(Number);

const expectedOutput = 97342568;

assertStrictEquals(countPart1(input, 100), expectedOutput);
});

Deno.test("Crab Cups: Example test from introduction (Part two)", () => {
const input = (
"389125467"
).split("").map(Number);

const expectedOutput = 149245887792;

assertStrictEquals(countPart2(input), expectedOutput);
});

Deno.test("Crab Cups: Final test (Part two)", () => {
const input = (
Deno.readTextFileSync("23/final_input.txt").trimEnd()
).split("").map(Number);

const expectedOutput = 902208073192;

assertStrictEquals(countPart2(input), expectedOutput);
});

0 comments on commit 36c5927

Please sign in to comment.