Last active
December 3, 2018 18:15
-
-
Save MinimumViablePerson/fb7168c277eec664909d703967aeb35e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******** ANSWERS ********/ | |
// ⭐: 1 | |
const addThemAllUp = frequencyChanges => frequencyChanges.reduce((a, b) => a + b) | |
// ⭐: 2 | |
const findFirstRepeatedFrequency = frequencyChanges => { | |
let index = 0 | |
let currentFrequency = 0 | |
const frequencies = new Set() | |
while (true) { | |
frequencies.add(currentFrequency) | |
currentFrequency += frequencyChanges[index] | |
if (frequencies.has(currentFrequency)) { | |
break | |
} else { | |
index = index === frequencyChanges.length - 1 ? 0 : index + 1 | |
} | |
} | |
return currentFrequency | |
} | |
// ⭐: 3 | |
const getBoxIdChecksum = boxIds => { | |
const counts = {2: 0, 3: 0} | |
for (const boxId of boxIds) { | |
if (anyCharAppearsNTimes(boxId, 2)) counts[2]++ | |
if (anyCharAppearsNTimes(boxId, 3)) counts[3]++ | |
} | |
return counts[2] * counts[3] | |
} | |
// ⭐: 4 | |
const findPrototypeFabric = boxIds => { | |
boxIds = [...boxIds] | |
let currentBoxId | |
while (boxIds.length > 0) { | |
currentBoxId = boxIds.pop() | |
for (const boxId of boxIds) { | |
let differenceCount = 0 | |
let differingIndex | |
for (const index in currentBoxId) { | |
if (currentBoxId[index] !== boxId[index]) { | |
differenceCount++ | |
differingIndex = parseInt(index) | |
} | |
if (differenceCount > 1) break | |
} | |
if (differenceCount === 1) { | |
return replaceCharAt(differingIndex, currentBoxId, '') | |
} | |
} | |
} | |
} | |
// ⭐: 4 (With ES6 destructuring and recursion) | |
const findPrototypeFabricR = ([currentBoxId, ...otherBoxIds]) => { | |
if (!currentBoxId) return null | |
return prototypeFabricFound(currentBoxId, otherBoxIds) || findPrototypeFabricR(otherBoxIds) | |
} | |
// ⭐: 5 | |
const countOverlappingClaims = claims => { | |
const matrix = addAllClaimsToMatrix(claims) | |
const overlappingCoords = Object.values(matrix).filter(coord => coord.length > 1) | |
return overlappingCoords.length | |
} | |
// ⭐: 6 | |
const findFirstNonOverlappingClaim = claims => { | |
const matrix = addAllClaimsToMatrix(claims) | |
for (const claim of claims) { | |
if (claimDoesntOverlap(claim, matrix)) return claim | |
} | |
} | |
/******** HELPERS ********/ | |
// get day 1 data ready to operate on | |
const getDay1Data = () => | |
fetch('https://adventofcode.com/2018/day/1/input') | |
.then(resp => resp.text()) | |
.then(text => text.split('\n').slice(0, -1)) | |
.then(arr => arr.map(n => parseInt(n))) | |
// get day 2 data ready to operate on | |
const getDay2Data = () => | |
fetch('https://adventofcode.com/2018/day/2/input') | |
.then(resp => resp.text()) | |
.then(text => text.split('\n').slice(0, -1)) | |
// get day 3 data ready to operate on | |
const getDay3Data = () => | |
fetch('https://adventofcode.com/2018/day/3/input') | |
.then(resp => resp.text()) | |
.then(text => text.split('\n').slice(0, -1)) | |
.then(data => data.map(parseClaim) | |
// check if any char in a string appears a given number of times | |
const anyCharAppearsNTimes = (string, times) => { | |
const charSet = new Set(string) | |
for (const char of charSet) { | |
const match = string.match(new RegExp(char, 'g')) | |
if (match && match.length === times) return true | |
} | |
return false | |
} | |
// return a copy of a string with a char replaced at a given index | |
const replaceCharAt = (index, string, replacement) => | |
string.slice(0, index) + replacement + string.slice(index + 1) | |
// check if prototype fabric is found in a single loop | |
const prototypeFabricFound = (currentBoxId, boxIds) => { | |
for (const boxId of boxIds) { | |
let differenceCount = 0 | |
let differingIndex | |
for (const index in currentBoxId) { | |
if (currentBoxId[index] !== boxId[index]) { | |
differenceCount++ | |
differingIndex = parseInt(index) | |
} | |
if (differenceCount > 1) break | |
} | |
if (differenceCount === 1) { | |
return replaceCharAt(differingIndex, currentBoxId, '') | |
} | |
} | |
} | |
// convert a claim string into a claim object | |
const parseClaim = claim => { | |
const match = claim.match(/#(\d+)\s@\s(\d+),(\d+):\s(\d+)x(\d+)/) | |
return { | |
id: parseInt(match[1]), | |
x: parseInt(match[2]), | |
y: parseInt(match[3]), | |
w: parseInt(match[4]), | |
h: parseInt(match[5]) | |
} | |
} | |
// add all coords for a single claim into an object "matrix" | |
const addClaimToMatrix = (claim, matrix) => { | |
for (let i = 0; i < claim.w; i++) { | |
const x = claim.x + 1 + i | |
for (let i = 0; i < claim.h; i++) { | |
const y = claim.y + 1 + i | |
const tile = `${x},${y}` | |
matrix[tile] = matrix[tile] ? [...matrix[tile], claim.id] : [claim.id] | |
} | |
} | |
return matrix | |
} | |
// take a list of claims and add them all to a new object | |
const addAllClaimsToMatrix = claims => | |
claims.reduce((matrix, claim) => addClaimToMatrix(claim, matrix), {}) | |
// check if a single claim overlaps | |
const claimDoesntOverlap = (claim, matrix) => | |
Object.values(matrix) | |
.filter(tile => tile.includes(claim.id)) | |
.every(tile => tile.length === 1) |
@stephencweiss Alright I yield, my second answer is using a Set now 👍
@MinimumViablePerson - Super cool. I actually didn't know that feature about Sets. I knew they forced uniqueness, but didn't realize it was because they didn't need values. Looking at MDN, they can have values though, right?
@stephencweiss Yeah, they only have values in a sense. There's no key/value pair to them, and they are unique. They can have a much faster add and look up performance.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@stephencweiss Technically, a Set would be the ideal data structure for this, since an object is not quite needed as I don't need a key/value pair, only a key. I thought about using a Set, but ¯_(ツ)_/¯