Skip to content

Commit c6dd678

Browse files
Merge pull request #6 from amclin/feature/2018-day-14
Feature/2018 day 14 part 1 solution
2 parents 1c46a1f + 7ed06b7 commit c6dd678

File tree

4 files changed

+277
-0
lines changed

4 files changed

+277
-0
lines changed

2018/day-14/recipes.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* Circular linked list of recipes
3+
*/
4+
class Recipes {
5+
constructor (recipe) {
6+
this.head = null
7+
this.tail = null
8+
this.length = 0
9+
this.addFirst(recipe)
10+
}
11+
12+
addFirst (recipe) {
13+
const newRecipe = { value: recipe }
14+
newRecipe.next = newRecipe
15+
newRecipe.prev = newRecipe
16+
this.head = newRecipe
17+
this.tail = newRecipe
18+
this.length++
19+
return this
20+
}
21+
22+
/**
23+
* Adds a recipe to the linked list
24+
* @param {Number} recipe value
25+
*/
26+
addRecipe (recipe) {
27+
const newRecipe = { value: recipe }
28+
newRecipe.next = this.tail // link new recipe to tail
29+
this.tail.prev = newRecipe
30+
newRecipe.prev = this.head // link new recipe to old head
31+
this.head.next = newRecipe
32+
this.head = newRecipe // make new recipe the new head
33+
this.length++
34+
return this.head
35+
}
36+
37+
/**
38+
* Scoring the current recipes means adding new recipies base on the score value
39+
* @param {Number} score of current recipe
40+
*/
41+
scoreRecipes (score) {
42+
score.toString().split('').forEach((recipe) => {
43+
this.addRecipe(parseInt(recipe))
44+
})
45+
}
46+
}
47+
48+
/**
49+
* Takes an array of numbers and totals the digits
50+
* @param
51+
*/
52+
const totalDigitsInArray = (arr) => {
53+
return arr.reduce(
54+
(acc, num) => acc + num.toString().split('')
55+
.reduce((sub, digit) => sub + parseInt(digit), 0), 0)
56+
}
57+
58+
/**
59+
* Loops the elves through the recipes list the specified number of times
60+
* @param {Array} elves list of elves
61+
* @param {LinkedList} recipes list of recipes
62+
* @param {Numbe} repeat count of desired iterations
63+
*/
64+
const loopRecipesForElves = (elves, recipes, repeat) => {
65+
for (let x = 1; x <= repeat; x++) {
66+
const score = totalDigitsInArray(elves.map((elf) => elf.value))
67+
recipes.scoreRecipes(score)
68+
elves.forEach((elf, idx) => {
69+
const distance = elf.value + 1
70+
for (let x = 0; x < distance; x++) {
71+
elf = elf.next
72+
}
73+
elves[idx] = elf
74+
})
75+
}
76+
}
77+
78+
/**
79+
* Determines the next X recipes after the elves have generated Y recipes
80+
*/
81+
const calculateXAfterY = (x, y, recipes, elves) => {
82+
let iterator = recipes.head
83+
while (recipes.length <= y) {
84+
loopRecipesForElves(elves, recipes, 1)
85+
}
86+
87+
if (recipes.length === y + 1) {
88+
iterator = recipes.head
89+
} else {
90+
// In case multidigit recipe results created more than Y
91+
iterator = recipes.head.prev
92+
}
93+
94+
while (recipes.length < x + y) {
95+
loopRecipesForElves(elves, recipes, 1)
96+
}
97+
98+
let result = ''
99+
while (result.length < x) {
100+
result += iterator.value.toString()
101+
iterator = iterator.next
102+
}
103+
return result
104+
}
105+
106+
module.exports = {
107+
calculateXAfterY,
108+
loopRecipesForElves,
109+
Recipes,
110+
totalDigitsInArray
111+
}

2018/day-14/recipes.test.js

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/* eslint-env mocha */
2+
const expect = require('chai').expect
3+
const {
4+
calculateXAfterY,
5+
loopRecipesForElves,
6+
Recipes,
7+
totalDigitsInArray
8+
} = require('./recipes')
9+
10+
describe('--- Day 14: Chocolate Charts ---', () => {
11+
describe('Part 1:', () => {
12+
describe('new Recipes()', () => {
13+
it('builds a linked list', () => {
14+
const recipes = new Recipes(0)
15+
for (let x = 1; x <= 5; x++) {
16+
recipes.addRecipe(x)
17+
}
18+
expect(recipes.length).to.equal(6)
19+
expect(recipes.head.value).to.equal(5)
20+
expect(recipes.tail.value).to.equal(0)
21+
expect(recipes.tail.prev).to.equal(recipes.head) // circular linked list for prev
22+
expect(recipes.head.next).to.equal(recipes.tail) // circular linked list for next
23+
})
24+
describe('scoreRecipes()', () => {
25+
it('adds new recipes based on the provided score', () => {
26+
const recipes = new Recipes(0)
27+
for (let x = 1; x <= 5; x++) {
28+
recipes.addRecipe(x)
29+
}
30+
recipes.scoreRecipes(37)
31+
expect(recipes.head.value).to.equal(7)
32+
expect(recipes.head.prev.value).to.equal(3)
33+
expect(recipes.head.prev.prev.value).to.equal(5)
34+
expect(recipes.head.next).to.equal(recipes.tail)
35+
})
36+
})
37+
})
38+
describe('totalDigitsInArray()', () => {
39+
it('calculates the total value of all the digits of all the numbers in the provided array', () => {
40+
const expected = 34
41+
const test = [1, 5, 13, 22, 3, 0, 971]
42+
const actual = totalDigitsInArray(test)
43+
expect(actual).to.equal(expected)
44+
})
45+
})
46+
describe('loopRecipeForEleves()', () => {
47+
it('loops through the recipe object for the specified elves the specified number of times', () => {
48+
const expected = '37101012451589167792' // list of recipe values in the last iteration of the example
49+
const elves = [3, 7]
50+
const recipes = new Recipes(elves[0])
51+
let actual = ''
52+
53+
elves.forEach((elf, idx) => {
54+
if (idx === 0) {
55+
elves[0] = recipes.head
56+
} else {
57+
elves[idx] = recipes.addRecipe(elf)
58+
}
59+
})
60+
61+
loopRecipesForElves(elves, recipes, 15)
62+
63+
let iterator = recipes.tail.next
64+
actual += recipes.tail.value.toString()
65+
while (iterator !== recipes.tail) {
66+
actual += iterator.value.toString()
67+
iterator = iterator.next
68+
}
69+
70+
expect(expected).to.equal(actual)
71+
})
72+
})
73+
describe('calculateXAfterY(x, y, recipe, elves)', () => {
74+
it('predicts the next X results after the elves have executed Y', () => {
75+
const elves = [3, 7]
76+
const recipes = new Recipes(elves[0])
77+
let actual = ''
78+
79+
elves.forEach((elf, idx) => {
80+
if (idx === 0) {
81+
elves[0] = recipes.head
82+
} else {
83+
elves[idx] = recipes.addRecipe(elf)
84+
}
85+
})
86+
87+
actual = calculateXAfterY(10, 9, recipes, elves)
88+
expect(actual).to.equal('5158916779')
89+
})
90+
it('predicts the next X results after the elves have executed Y', () => {
91+
const elves = [3, 7]
92+
const recipes = new Recipes(elves[0])
93+
let actual = ''
94+
95+
elves.forEach((elf, idx) => {
96+
if (idx === 0) {
97+
elves[0] = recipes.head
98+
} else {
99+
elves[idx] = recipes.addRecipe(elf)
100+
}
101+
})
102+
103+
actual = calculateXAfterY(10, 5, recipes, elves)
104+
expect(actual).to.equal('0124515891')
105+
})
106+
it('predicts the next X results after the elves have executed Y', () => {
107+
const elves = [3, 7]
108+
const recipes = new Recipes(elves[0])
109+
let actual = ''
110+
111+
elves.forEach((elf, idx) => {
112+
if (idx === 0) {
113+
elves[0] = recipes.head
114+
} else {
115+
elves[idx] = recipes.addRecipe(elf)
116+
}
117+
})
118+
119+
actual = calculateXAfterY(10, 18, recipes, elves)
120+
expect(actual).to.equal('9251071085')
121+
})
122+
it('predicts the next X results after the elves have executed Y', () => {
123+
const elves = [3, 7]
124+
const recipes = new Recipes(elves[0])
125+
let actual = ''
126+
127+
elves.forEach((elf, idx) => {
128+
if (idx === 0) {
129+
elves[0] = recipes.head
130+
} else {
131+
elves[idx] = recipes.addRecipe(elf)
132+
}
133+
})
134+
135+
actual = calculateXAfterY(10, 2018, recipes, elves)
136+
expect(actual).to.equal('5941429882')
137+
})
138+
})
139+
})
140+
})

2018/day-14/solution.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const {
2+
calculateXAfterY,
3+
Recipes
4+
} = require('./recipes')
5+
6+
const input = 540561
7+
8+
const elves = [3, 7]
9+
const recipes = new Recipes(elves[0])
10+
11+
elves.forEach((elf, idx) => {
12+
if (idx === 0) {
13+
elves[0] = recipes.head
14+
} else {
15+
elves[idx] = recipes.addRecipe(elf)
16+
}
17+
})
18+
19+
const answer = calculateXAfterY(10, input, recipes, elves)
20+
const answer2 = ''
21+
22+
console.log(`-- Part 1 --`)
23+
console.log(`Answer: ${answer}`)
24+
console.log(`-- Part 2 --`)
25+
console.log(`Answer: ${answer2}`)

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('./2018/day-14/solution')

0 commit comments

Comments
 (0)