Day 9
This commit is contained in:
parent
560fe542e6
commit
3e70ac4498
1
aoc-9/inputs.txt
Normal file
1
aoc-9/inputs.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
462 players; last marble is worth 71938 points
|
188
aoc-9/main.ts
Normal file
188
aoc-9/main.ts
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
function mod(n: number, m: number): number {
|
||||||
|
return ((n % m) + m) % m;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BoardNode<T> {
|
||||||
|
prev: BoardNode<T> | null,
|
||||||
|
data?: T,
|
||||||
|
next: BoardNode<T> | null
|
||||||
|
}
|
||||||
|
|
||||||
|
// doubly linked "board"
|
||||||
|
class Board<T> {
|
||||||
|
private head: BoardNode<T>;
|
||||||
|
private tail: BoardNode<T>;
|
||||||
|
|
||||||
|
private current: BoardNode<T> | null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.head = {
|
||||||
|
prev: null,
|
||||||
|
next: this.tail
|
||||||
|
};
|
||||||
|
this.tail = {
|
||||||
|
prev: this.head,
|
||||||
|
next: null
|
||||||
|
}
|
||||||
|
|
||||||
|
this.current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(): boolean {
|
||||||
|
return this.head.next == this.tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertAfter(data: T): Board<T> {
|
||||||
|
let next: BoardNode<T>;
|
||||||
|
let prev: BoardNode<T>;
|
||||||
|
|
||||||
|
if (this.current == null) {
|
||||||
|
next = this.tail;
|
||||||
|
prev = this.head;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next = this.current.next;
|
||||||
|
prev = this.current;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.current = {
|
||||||
|
prev: prev,
|
||||||
|
data: data,
|
||||||
|
next: next
|
||||||
|
};
|
||||||
|
this.current.prev.next = this.current;
|
||||||
|
this.current.next.prev = this.current;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCurrent(): T {
|
||||||
|
let data: T = this.current.data;
|
||||||
|
|
||||||
|
this.current.prev.next = this.current.next;
|
||||||
|
this.current.next.prev = this.current.prev;
|
||||||
|
|
||||||
|
if (this.isEmpty()) this.current = null;
|
||||||
|
else this.next();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(): Board<T> {
|
||||||
|
if (this.current == null) return this;
|
||||||
|
|
||||||
|
this.current = this.current.next;
|
||||||
|
if (this.current == this.tail) this.current = this.head.next;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev(): Board<T> {
|
||||||
|
if (this.current == null) return this;
|
||||||
|
|
||||||
|
this.current = this.current.prev;
|
||||||
|
if (this.current == this.head) this.current = this.tail.prev;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBy(amount: number): Board<T> {
|
||||||
|
if (amount > 0) {
|
||||||
|
for (let i = 0; i < amount; i++) {
|
||||||
|
this.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (amount < 0) {
|
||||||
|
amount = Math.abs(amount);
|
||||||
|
for (let i = 0; i < amount; i++) {
|
||||||
|
this.prev();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
let output: string = "[ ";
|
||||||
|
|
||||||
|
if (this.current != null) {
|
||||||
|
let node: BoardNode<T> = this.head;
|
||||||
|
|
||||||
|
while (node.next != this.tail) {
|
||||||
|
node = node.next;
|
||||||
|
|
||||||
|
if (node == this.current) {
|
||||||
|
output += "(" + node.data + "), ";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
output += node.data + ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = output.slice(0, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
output += " ]";
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Players {
|
||||||
|
scores: Array<number>;
|
||||||
|
currentPlayer: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
private board: Board<number>;
|
||||||
|
private roundNo: number;
|
||||||
|
private players: Players;
|
||||||
|
|
||||||
|
constructor(numPlayers: number) {
|
||||||
|
this.players = {
|
||||||
|
scores: Array(numPlayers).fill(0),
|
||||||
|
currentPlayer: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this.board = new Board<number>();
|
||||||
|
this.roundNo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private nextTurn(): void {
|
||||||
|
let points: number = 0;
|
||||||
|
|
||||||
|
if (this.roundNo % 23 === 0 && this.roundNo > 0) {
|
||||||
|
points = this.roundNo + this.board.moveBy(-7).removeCurrent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.board.next().insertAfter(this.roundNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.roundNo++;
|
||||||
|
|
||||||
|
this.players.scores[this.players.currentPlayer] += points;
|
||||||
|
this.players.currentPlayer = (this.players.currentPlayer + 1) % this.players.scores.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
runUntil(round: number): Game {
|
||||||
|
while (this.roundNo <= round) {
|
||||||
|
this.nextTurn();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHighScore(): number {
|
||||||
|
return Math.max(... this.players.scores);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let input: string = fs.readFileSync("inputs.txt", "utf8");
|
||||||
|
let numPlayers: number = Number(input.split(' ')[0]);
|
||||||
|
let lastRound: number = Number(input.split(' ')[6]);
|
||||||
|
|
||||||
|
let game: Game = new Game(numPlayers);
|
||||||
|
|
||||||
|
console.log(game.runUntil(lastRound).getHighScore());
|
||||||
|
console.log(game.runUntil(lastRound * 100).getHighScore());
|
16
aoc-9/package.json
Normal file
16
aoc-9/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "aoc-9",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "main.js",
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^10.12.12",
|
||||||
|
"ts-node": "^7.0.1",
|
||||||
|
"typescript": "^3.2.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "ts-node -O '{\"lib\": [ \"es2017\" ]}' main.ts"
|
||||||
|
},
|
||||||
|
"author": "Jack Bond-Preston"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user