Public
Edited
Nov 19, 2022
1 star
Insert cell
Insert cell
Insert cell
class CircularLinkedList {
// Create a linked list from the given array
constructor(init = []) {
this.size = init.length;
this.nodes = [];
this.head = this.size > 0 ? init[0] : null;
init.forEach((v, i) => {
this.nodes[v] = {
prev: init[(i - 1 + this.size) % this.size],
next: init[(i + 1) % this.size]
};
});
}

// Given a node, what is the next one?
next(n) {
return this.nodes[n] !== undefined ? this.nodes[n].next : null;
}

// Move node n to be after node m
move(n, m) {
if (this.nodes[n] !== undefined && this.nodes[m] !== undefined) {
// Are we moving the node currently at the head, in which case, make the head the old head's next.
if (n === this.head) {
this.head = this.nodes[n].next;
}
// Remove from old position
this.nodes[this.nodes[n].prev].next = this.nodes[n].next;
this.nodes[this.nodes[n].next].prev = this.nodes[n].prev;
// Insert in new position
this.nodes[n].prev = m;
this.nodes[n].next = this.nodes[m].next;
this.nodes[m].next = n;
this.nodes[this.nodes[this.nodes[m].next].next].prev = n;
}
}

// Traverse from head until we reach head again. Allows conversion to array with spread syntax.
*[Symbol.iterator]() {
if (this.size > 0) {
let current = this.head;
while (this.nodes[current].next !== this.head) {
yield current;
current = this.nodes[current].next;
}
yield current;
}
}
}
Insert cell
Insert cell
function moveTriplet(cups, current) {
const destination = (v0, v1, v2, v3) => {
do {
v0 = ((v0 + cups.size - 2) % cups.size) + 1;
} while (v0 === v1 || v0 === v2 || v0 === v3);
return v0;
};

const v1 = cups.next(current);
const v2 = cups.next(v1);
const v3 = cups.next(v2);

cups.move(v1, destination(current, v1, v2, v3));
cups.move(v2, v1);
cups.move(v3, v2);

return cups.next(current);
}
Insert cell
Insert cell
function play(input, n) {
const cups = new CircularLinkedList(input);
let current = cups.head;
for (let i = 0; i < n; i++) {
current = moveTriplet(cups, current);
}
cups.head = 1;
return cups;
}
Insert cell
function part1(input) {
const cups = play(puzzleInput, 100);
return Number([...cups].slice(1).join(""));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function part2(input) {
const cups = play(puzzleInput.concat(AOC.range(10, 1000000)), 10000000);
return cups.next(1) * cups.next(cups.next(1));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more