Day 1
JavaScriptmas
const panic = str => `${str.toUpperCase().split(' ').join(' 😱 ')}!`
console.log(panic("I'm almost out of coffee"))
console.log(panic("winter is coming"))
Advent of Code
const elves = input.split('\n\n').map(e => Number(e.split('\n').reduce((a, c) => Number(a) + Number(c))))
console.log(Math.max(...elves))
elves.sort((a, b) => b - a)
console.log(elves.slice(0, 3).reduce((a, c) => a + c))
Day 2
JavaScriptmas
const transformData = d => d.map(e => ({
fullName: `${e.name.first} ${e.name.last}`,
birthday: new Date(e.dob.date).toDateString()
}))
Advent of Code
/**
* Rock: A, X. Worth: 1. Beats: Scissors
* Paper: B, Y. Worth: 2. Beats: Rock
* Scissors: C, Z. Worth: 3. Beats: Paper
* 0 if you lost,
* 3 if the round was a draw
* and 6 if you won
*/
console.log(input.split('\n').reduce((a, c) => {
const [them, me] = c.split(' ')
if(them === 'A'){
if(me === 'X'){
a += 3 + 1
}
if(me === 'Y'){
a += 6 + 2
}
if(me === 'Z'){
a += 0 + 3
}
}
if(them === 'B'){
if(me === 'X'){
a += 0 + 1
}
if(me === 'Y'){
a += 3 + 2
}
if(me === 'Z'){
a += 6 + 3
}
}
if(them === 'C'){
if(me === 'X'){
a += 6 + 1
}
if(me === 'Y'){
a += 0 + 2
}
if(me === 'Z'){
a += 3 + 3
}
}
return a
}, 0))
/**
* Rock: A, X. Worth: 1. Beats: Scissors
* Paper: B, Y. Worth: 2. Beats: Rock
* Scissors: C, Z. Worth: 3. Beats: Paper
* 0 if you lost,
* 3 if the round was a draw
* and 6 if you won
* X: Lose
* Y: Draw
* Z: Win
*/
console.log(input.split('\n').reduce((a, c) => {
const [them, me] = c.split(' ')
if(them === 'A'){ // They've played Rock
if(me === 'X'){ // I need to lose
a += 0 + 3 // I play Scissors
}
if(me === 'Y'){ // I need to draw
a += 3 + 1 // I play Rock
}
if(me === 'Z'){ // I need to win
a += 6 + 2 // I play Paper
}
}
if(them === 'B'){ // They've played Paper
if(me === 'X'){ // I need to lose
a += 0 + 1 // I play Rock
}
if(me === 'Y'){ // I need to draw
a += 3 + 2 // I play Paper
}
if(me === 'Z'){ // I need to win
a += 6 + 3 // I play Scissors
}
}
if(them === 'C'){ // They've played Scissors
if(me === 'X'){ // I need to lose
a += 0 + 2 // I play Paper
}
if(me === 'Y'){ // I need to draw
a += 3 + 3 // I play Scissors
}
if(me === 'Z'){ // I need to win
a += 6 + 1 // I play Rock
}
}
return a
}, 0))
Day 3
JavaScriptmas
const faveFoods = {
breakfast: 'croissants',
lunch: 'pasta',
supper: 'pizza'
}
const {breakfast, lunch, supper} = faveFoods
document.getElementById('meals').innerHTML = `
For breakfast, I only like ${breakfast}. For lunch, I love ${lunch}, and for supper I want usually want ${supper}.`
Advent of Code
// drop 96 for lowercase
// drop 38 for uppercase
const getCodeValue = letter => letter === letter.toLowerCase()
? letter.charCodeAt(0) - 96
: letter.charCodeAt(0) - 38
const getIntersection = (a, b) => {
for(let i in a){
if(b.includes(a[i])){
return a[i]
}
}
}
const getIntersectionThree = (a, b, c) => {
for(let i in a){
if(b.includes(a[i]) && c.includes(a[i])){
return a[i]
}
}
}
console.log(input.split('\n').reduce((a, c) => a + getCodeValue(getIntersection(...[c.slice(0, Math.ceil(c.length / 2)).split(''), c.slice(Math.ceil(c.length / 2)).split('')]))
, 0))
let total = 0
const lines = input.split('\n')
for (let i = 0; i < lines.length; i += 3) {
const chunk = lines.slice(i, i + 3);
total += getCodeValue(getIntersectionThree(...chunk))
}
console.log(total)
console.log(input.split('\n').reduce((p, _, i, a) => !(i%3)
? p + getCodeValue(getIntersectionThree(...a.slice(i, i + 3)))
: p, 0))
Day 4
JavaScriptmas
const whisper = s => `shh... ${s.endsWith('!')
? s.toLowerCase().slice(0, -1)
: s.toLowerCase()}`
Advent of Code
const range = (start, stop) => Array.from({ length: stop - start + 1 }, (_, i) => start + i)
const contains = (a, b) => a.every(e => b.includes(e)) || b.every(e => a.includes(e))
const overlaps = (a, b) => a.some(e => b.includes(e))
console.log(input.split('\n').reduce((a, line) => {
const [firstArea, secondArea] = line.split(',').map(elf => range(...elf.split('-').map(e => Number(e))))
a.contains += contains(firstArea, secondArea) ? 1 : 0
a.overlaps += overlaps(firstArea, secondArea) ? 1 : 0
return a
}, {
contains: 0,
overlaps: 0
}))
// let containedWithin = 0
// let overlaps = 0
// input.split('\n').forEach(line => {
// const [firstArea, secondArea] = line.split(',').map(elf => range(...elf.split('-').map(e => Number(e))))
// if(secondArea.every(e => firstArea.includes(e)) || firstArea.every(e => secondArea.includes(e))){
// containedWithin += 1
// }
// if(secondArea.some(e => firstArea.includes(e))){
// overlaps += 1
// }
// })
// console.log(containedWithin, overlaps)
Day 5
JavaScriptmas
const getSaleItems = d => d.filter(e => e.type === "sweet").map(e => ({item: e.item, price: e.price}))
Advent of Code
const chunk = (str, size) => {
const numChunks = Math.ceil(str.length / size)
const chunks = new Array(numChunks)
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
chunks[i] = str.substr(o, size)
}
return chunks
}
const [initialState, instructions] = input.split('\n\n')
const initialStateLines = initialState.split('\n').reverse()
const positions = chunk(initialStateLines.shift(), 4).reduce((a, c) => {
a[Number(c.trim())] = []
return a
}, {})
initialStateLines.forEach(line => {
chunk(line, 4).forEach((position, index) => {
if (position.trim().length) {
const { groups: { letter } } = /\s*\[(?<letter>[A-Z])\]\s*/.exec(position)
positions[Object.keys(positions)[index]].push(letter)
}
})
})
/**
* Part 1
*/
// instructions.split('\n').forEach(instruction => {
// const {groups: {num, from, to}} = /move (?<num>[0-9]+) from (?<from>[0-9]+) to (?<to>[0-9]+)/.exec(instruction)
// for(let i = 0; i < Number(num); i++){
// positions[Number(to)].push(positions[Number(from)].pop())
// }
// })
/**
* Part 2
*/
instructions.split('\n').forEach(instruction => {
const { groups: { num, from, to } } = /move (?<num>[0-9]+) from (?<from>[0-9]+) to (?<to>[0-9]+)/.exec(instruction)
positions[Number(to)].push(...positions[Number(from)].slice(-Math.abs(Number(num))))
positions[Number(from)].splice(positions[Number(from)].length - Number(num), Number(num) )
})
console.log(Object.keys(positions).reduce((a, c, i) => {
return a + positions[c].at(-1)
}, ''))
Day 6
JavaScriptmas
const getRandomNumberOfTacos = () => new Array(Math.floor(Math.random() * (10 - 1) + 1)).fill('🌮')
Advent of Code
const test_input_1 = `mjqjpqmgbljsphdztnvjfqwrcgsmlb`
const test_input_2 = `bvwbjplbgvbhsrlpgdmjqwftvncz`
const test_input_3 = `nppdvjthqldpwncqszvftbrmjlhg`
const test_input_4 = `nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg`
const test_input_5 = `zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw`
const findPacket = stream => {
for(let i = 3; i <= stream.length; i++){
if(new Set(Array.from({length: 4}, (_, a) => stream.charAt(i - a))).size === 4){
return i + 1
}
}
}
const findMessage = stream => {
for(let i = 13; i <= stream.length; i++){
if(new Set(Array.from({length: 14}, (_, a) => stream.charAt(i - a))).size === 14){
return i + 1
}
}
}
console.log(findPacket(test_input_1))
console.log(findPacket(test_input_2))
console.log(findPacket(test_input_3))
console.log(findPacket(test_input_4))
console.log(findPacket(test_input_5))
console.log(findPacket(input))
console.log(findMessage(test_input_1))
console.log(findMessage(test_input_2))
console.log(findMessage(test_input_3))
console.log(findMessage(test_input_4))
console.log(findMessage(test_input_5))
console.log(findMessage(input))
Day 7
JavaScriptmas
const altCaps = str => str.split('').map((c, i) => i % 2 ? c : str.charCodeAt(i) > 96 || str.charCodeAt(i) < 123 ? c.toUpperCase() : c).join('')
Advent of Code
// import { Tree } from './Tree.js'
// import { TreeNode } from './TreeNode.js'
class TreeNode {
constructor(key, value = key, parent = null) {
this.key = key;
this.value = value;
this.parent = parent;
this.children = [];
}
get isLeaf() {
return this.children.length === 0;
}
get hasChildren() {
return !this.isLeaf;
}
}
class Tree {
constructor(key, value = key) {
this.root = new TreeNode(key, value);
}
*preOrderTraversal(node = this.root) {
yield node;
if (node.children.length) {
for (let child of node.children) {
yield* this.preOrderTraversal(child);
}
}
}
*postOrderTraversal(node = this.root) {
if (node.children.length) {
for (let child of node.children) {
yield* this.postOrderTraversal(child);
}
}
yield node;
}
insert(parentNodeKey, key, value = key) {
for (let node of this.preOrderTraversal()) {
if (node.key === parentNodeKey) {
node.children.push(new TreeNode(key, value, node));
return true;
}
}
return false;
}
remove(key) {
for (let node of this.preOrderTraversal()) {
const filtered = node.children.filter(c => c.key !== key);
if (filtered.length !== node.children.length) {
node.children = filtered;
return true;
}
}
return false;
}
find(key) {
for (let node of this.preOrderTraversal()) {
if (node.key === key) return node;
}
return undefined;
}
}
/*
* https://www.30secondsofcode.org/articles/s/js-data-structures-tree
*/
addEventListener('DOMContentLoaded', async () => {
//const res = await fetch("./test.txt")
const res = await fetch("./input.txt")
const text = await res.text()
const input = text.split('\n')
let target = null
let tree = null
let lineParts
input.forEach((line, index) => {
if (!index) {
tree = new Tree('/', 0)
target = tree.root
} else {
if (line.charAt(0) === '$') {
lineParts = line.split(' ')
if (lineParts.length === 3) {
if (lineParts[2] === '..') {
target = target.parent
} else if (lineParts[2] === '/') {
target = tree.root
} else {
target = target.children.find(ch => ch.key === lineParts[2])
}
}
} else {
lineParts = line.split(' ')
if (lineParts[0] === 'dir') {
target.children.push(new TreeNode(lineParts[1], 0, target))
} else {
const value = Number(lineParts[0])
target.children.push(new TreeNode(lineParts[1], value, target))
target.value += value
let parent = target.parent
while (parent) {
parent.value += value
parent = parent.parent
}
}
}
}
})
const dirs = [...tree.postOrderTraversal()].filter(x => x.hasChildren)
console.log('Part 1:', dirs.reduce((a, c) => {
if (c.value <= 100000) {
a += c.value
}
return a
}, 0))
const spaceRequired = 30000000 - (70000000 - tree.root.value)
console.log('Space required: ', spaceRequired)
console.log('Part 2:', dirs.filter(dir => {
if (dir.value >= spaceRequired) {
console.log(dir.key, dir.value)
return true
}
return false
}).sort((a, b) => a.value - b.value)[0].value)
})
Day 8
JavaScriptmas
const validTime = str => {
const [hours, minutes] = str.split(':').map(n => Number(n))
return hours >= 1 && hours <= 24 && minutes >= 0 && minutes < 60
}
Day 9
JavaScriptmas
const capitalizeWord = w => `${w.charAt(0).toUpperCase()}${w.slice(1, w.length)}`
const toTitleCase = s => s.split(' ').map(w => capitalizeWord(w)).join(' ')
Day 10
JavaScriptmas
const sortByLength = s => s.sort((a, b) => a.length - b.length)
Day 11
JavaScriptmas
const reverseString = arr => arr.split('').reverse().join('')
const reverseStringsInArray = arr => arr.map(a => reverseString(a))
Day 12
JavaScriptmas
class MenuItem extends HTMLElement{
static get observedAttributes() {
return [
'food'
]
}
constructor() {
super()
}
render() {
this.innerHTML = this.html
}
get html() {
return `<div class="food">${this.food}</div>`
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.render()
}
}
set food(v){
this.setAttribute('food', v)
}
get food() {
return this.getAttribute('food')
}
}
window.customElements.define('menu-item', MenuItem)
const menu = document.getElementById('menu')
const dinnerFoods = ['🍝','🍔','🌮']
menu.innerHTML = dinnerFoods.map(food => `<menu-item food="${food}"/></menu-item>`).join('')
Day 13
JavaScriptmas
const emojifyWord = w => w.charAt(0) === ':' && w.charAt(w.length - 1) === ':' ? emojis[w.slice(1, -1)] ? emojis[w.slice(1, -1)] : w.slice(1, -1) : w
const emojifyPhrase = phrase => phrase.split(' ').map(word => emojifyWord(word)).join(' ')
Day 14
JavaScriptmas
const countVowelConsonant = str => str.split('').reduce((a, c) => a += ['a','e','i','o','u'].includes(c) ? 1 : 2, 0)
Day 15
JavaScriptmas
const isPalindrome = str => str === str.split('').reverse().join('')
Day 16
JavaScriptmas
const insertDashes = arr => arr.split(' ').map(w => w.split('').join('-')).join(' ')
Day 17
JavaScriptmas
const flatten = arr => arr.flat()
const flatten = arr => Array.prototype.concat.apply([], arr)
const flatten = arr => arr.toString().split(',')
Day 18
JavaScriptmas
const candies = (ch, ca) => Math.floor(ca/ch) * ch
Day 19
JavaScriptmas
const centuryFromYear = num => num % 100 === 0 ? num / 100 : Math.floor(num / 100) + 1
Day 20
JavaScriptmas
const getFreePodcasts = data => podcasts.filter(p => !p.paid).map(({title, rating, paid}) => ({title, rating, paid}))
Day 21
JavaScriptmas
const awardBonuses = num => Array.from({length: num}, (_, i) => i + 1).forEach(i => console.log(`${i} - ${!(i%3) && !(i%5) ? 'JACKPOT! 1 Million and a Yacht!' : !(i%3) ? 'Vacation!' : !(i%5) ? '$100,000 bonus!' : ':('}`))
awardBonuses(100)
Day 22
JavaScriptmas
function getReadyTables() {
const readyTables = []
for (let i = 0; i < 2; i++) {
readyTables.push(Math.round(Math.random()*20) + 1)
}
return readyTables
}
const displayTables = () => getReadyTables().map(el => {
const table = document.createElement('div')
table.classList.add('table')
table.innerText = el
return table
})
document.getElementById('tables').append(...displayTables())
Day 23
JavaScriptmas
const sortProducts = data => data.sort((a, b) => a.price - b.price)
Day 24
JavaScriptmas
const player = document.getElementById("player")
const playSong = id => player.src = `https://www.youtube.com/embed/${id}?autoplay=1`