Skip to content

Feature/2018 day 14 part 1 solution #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions 2018/day-14/recipes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* Circular linked list of recipes
*/
class Recipes {
constructor (recipe) {
this.head = null
this.tail = null
this.length = 0
this.addFirst(recipe)
}

addFirst (recipe) {
const newRecipe = { value: recipe }
newRecipe.next = newRecipe
newRecipe.prev = newRecipe
this.head = newRecipe
this.tail = newRecipe
this.length++
return this
}

/**
* Adds a recipe to the linked list
* @param {Number} recipe value
*/
addRecipe (recipe) {
const newRecipe = { value: recipe }
newRecipe.next = this.tail // link new recipe to tail
this.tail.prev = newRecipe
newRecipe.prev = this.head // link new recipe to old head
this.head.next = newRecipe
this.head = newRecipe // make new recipe the new head
this.length++
return this.head
}

/**
* Scoring the current recipes means adding new recipies base on the score value
* @param {Number} score of current recipe
*/
scoreRecipes (score) {
score.toString().split('').forEach((recipe) => {
this.addRecipe(parseInt(recipe))
})
}
}

/**
* Takes an array of numbers and totals the digits
* @param
*/
const totalDigitsInArray = (arr) => {
return arr.reduce(
(acc, num) => acc + num.toString().split('')
.reduce((sub, digit) => sub + parseInt(digit), 0), 0)
}

/**
* Loops the elves through the recipes list the specified number of times
* @param {Array} elves list of elves
* @param {LinkedList} recipes list of recipes
* @param {Numbe} repeat count of desired iterations
*/
const loopRecipesForElves = (elves, recipes, repeat) => {
for (let x = 1; x <= repeat; x++) {
const score = totalDigitsInArray(elves.map((elf) => elf.value))
recipes.scoreRecipes(score)
elves.forEach((elf, idx) => {
const distance = elf.value + 1
for (let x = 0; x < distance; x++) {
elf = elf.next
}
elves[idx] = elf
})
}
}

/**
* Determines the next X recipes after the elves have generated Y recipes
*/
const calculateXAfterY = (x, y, recipes, elves) => {
let iterator = recipes.head
while (recipes.length <= y) {
loopRecipesForElves(elves, recipes, 1)
}

if (recipes.length === y + 1) {
iterator = recipes.head
} else {
// In case multidigit recipe results created more than Y
iterator = recipes.head.prev
}

while (recipes.length < x + y) {
loopRecipesForElves(elves, recipes, 1)
}

let result = ''
while (result.length < x) {
result += iterator.value.toString()
iterator = iterator.next
}
return result
}

module.exports = {
calculateXAfterY,
loopRecipesForElves,
Recipes,
totalDigitsInArray
}
140 changes: 140 additions & 0 deletions 2018/day-14/recipes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* eslint-env mocha */
const expect = require('chai').expect
const {
calculateXAfterY,
loopRecipesForElves,
Recipes,
totalDigitsInArray
} = require('./recipes')

describe('--- Day 14: Chocolate Charts ---', () => {
describe('Part 1:', () => {
describe('new Recipes()', () => {
it('builds a linked list', () => {
const recipes = new Recipes(0)
for (let x = 1; x <= 5; x++) {
recipes.addRecipe(x)
}
expect(recipes.length).to.equal(6)
expect(recipes.head.value).to.equal(5)
expect(recipes.tail.value).to.equal(0)
expect(recipes.tail.prev).to.equal(recipes.head) // circular linked list for prev
expect(recipes.head.next).to.equal(recipes.tail) // circular linked list for next
})
describe('scoreRecipes()', () => {
it('adds new recipes based on the provided score', () => {
const recipes = new Recipes(0)
for (let x = 1; x <= 5; x++) {
recipes.addRecipe(x)
}
recipes.scoreRecipes(37)
expect(recipes.head.value).to.equal(7)
expect(recipes.head.prev.value).to.equal(3)
expect(recipes.head.prev.prev.value).to.equal(5)
expect(recipes.head.next).to.equal(recipes.tail)
})
})
})
describe('totalDigitsInArray()', () => {
it('calculates the total value of all the digits of all the numbers in the provided array', () => {
const expected = 34
const test = [1, 5, 13, 22, 3, 0, 971]
const actual = totalDigitsInArray(test)
expect(actual).to.equal(expected)
})
})
describe('loopRecipeForEleves()', () => {
it('loops through the recipe object for the specified elves the specified number of times', () => {
const expected = '37101012451589167792' // list of recipe values in the last iteration of the example
const elves = [3, 7]
const recipes = new Recipes(elves[0])
let actual = ''

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

loopRecipesForElves(elves, recipes, 15)

let iterator = recipes.tail.next
actual += recipes.tail.value.toString()
while (iterator !== recipes.tail) {
actual += iterator.value.toString()
iterator = iterator.next
}

expect(expected).to.equal(actual)
})
})
describe('calculateXAfterY(x, y, recipe, elves)', () => {
it('predicts the next X results after the elves have executed Y', () => {
const elves = [3, 7]
const recipes = new Recipes(elves[0])
let actual = ''

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

actual = calculateXAfterY(10, 9, recipes, elves)
expect(actual).to.equal('5158916779')
})
it('predicts the next X results after the elves have executed Y', () => {
const elves = [3, 7]
const recipes = new Recipes(elves[0])
let actual = ''

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

actual = calculateXAfterY(10, 5, recipes, elves)
expect(actual).to.equal('0124515891')
})
it('predicts the next X results after the elves have executed Y', () => {
const elves = [3, 7]
const recipes = new Recipes(elves[0])
let actual = ''

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

actual = calculateXAfterY(10, 18, recipes, elves)
expect(actual).to.equal('9251071085')
})
it('predicts the next X results after the elves have executed Y', () => {
const elves = [3, 7]
const recipes = new Recipes(elves[0])
let actual = ''

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

actual = calculateXAfterY(10, 2018, recipes, elves)
expect(actual).to.equal('5941429882')
})
})
})
})
25 changes: 25 additions & 0 deletions 2018/day-14/solution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const {
calculateXAfterY,
Recipes
} = require('./recipes')

const input = 540561

const elves = [3, 7]
const recipes = new Recipes(elves[0])

elves.forEach((elf, idx) => {
if (idx === 0) {
elves[0] = recipes.head
} else {
elves[idx] = recipes.addRecipe(elf)
}
})

const answer = calculateXAfterY(10, input, recipes, elves)
const answer2 = ''

console.log(`-- Part 1 --`)
console.log(`Answer: ${answer}`)
console.log(`-- Part 2 --`)
console.log(`Answer: ${answer2}`)
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./2018/day-14/solution')
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy