From 184929408bf0bfca143ff3a787fabd2fd59358da Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 06:37:29 -0800 Subject: [PATCH 1/2] feat(2021-day-07): find fuel-cheap positions for crabs solves part 1 --- 2021/day-07/crabs.js | 20 ++++++++++++++++++++ 2021/day-07/crabs.test.js | 23 +++++++++++++++++++++++ 2021/day-07/index.js | 3 +++ 2021/day-07/input.txt | 1 + 2021/day-07/solution.js | 36 ++++++++++++++++++++++++++++++++++++ index.js | 2 +- 6 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 2021/day-07/crabs.js create mode 100644 2021/day-07/crabs.test.js create mode 100644 2021/day-07/index.js create mode 100644 2021/day-07/input.txt create mode 100644 2021/day-07/solution.js diff --git a/2021/day-07/crabs.js b/2021/day-07/crabs.js new file mode 100644 index 0000000..572aa9e --- /dev/null +++ b/2021/day-07/crabs.js @@ -0,0 +1,20 @@ +const sum = (x, y) => x + y + +const getFuel = (crabs, destination) => { + return crabs.map((crab) => Math.abs(crab - destination)) + .reduce(sum) +} + +const getLeastFuel = (crabs) => { + const positions = crabs + let fuel = crabs.length * crabs.length // assume a cluster of crabs super far away is the initial worst case + positions.forEach((position) => { + fuel = Math.min(fuel, getFuel(crabs, position)) + }) + return fuel +} + +module.exports = { + getFuel, + getLeastFuel +} diff --git a/2021/day-07/crabs.test.js b/2021/day-07/crabs.test.js new file mode 100644 index 0000000..67a3947 --- /dev/null +++ b/2021/day-07/crabs.test.js @@ -0,0 +1,23 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { getFuel, getLeastFuel } = require('./crabs') + +const testCrabs = [16, 1, 2, 0, 4, 2, 7, 1, 2, 14] + +describe('--- Day 7: The Treachery of Whales ---', () => { + describe('Part 1', () => { + describe('getFuel()', () => { + it('counts how much fuel is needed to position all the crabs', () => { + expect(getFuel(testCrabs, 2)).to.equal(37) + expect(getFuel(testCrabs, 1)).to.equal(41) + expect(getFuel(testCrabs, 3)).to.equal(39) + expect(getFuel(testCrabs, 10)).to.equal(71) + }) + }) + describe('getLeastFuel()', () => { + it('determine the fuel spent for the least costly position', () => { + expect(getLeastFuel(testCrabs)).to.equal(37) + }) + }) + }) +}) diff --git a/2021/day-07/index.js b/2021/day-07/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2021/day-07/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2021/day-07/input.txt b/2021/day-07/input.txt new file mode 100644 index 0000000..4005d0e --- /dev/null +++ b/2021/day-07/input.txt @@ -0,0 +1 @@ +1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,767,559,240,1779,740,550,84,819,108,728,212,650,264,899,1231,90,127,46,219,1494,192,473,163,1456,1048,22,4,1121,9,37,180,531,1167,395,456,952,1807,199,606,293,1003,236,235,1294,102,4,724,672,458,511,431,162,48,900,229,4,570,316,111,520,720,343,1064,314,261,1102,397,1585,610,509,1374,157,128,353,440,435,864,1489,425,762,320,1369,233,903,1181,1203,598,9,938,659,214,2,141,468,1485,631,265,156,165,987,2,856,564,120,325,16,743,849,822,51,18,1153,1100,143,301,402,717,126,937,391,36,802,1399,512,461,250,679,646,303,556,574,948,362,395,402,253,1631,1,203,76,48,246,115,117,15,953,926,210,1257,96,47,147,1058,1129,1166,183,375,1404,697,237,191,760,431,38,1778,159,698,411,160,289,23,836,554,841,289,892,276,877,216,751,1273,388,392,289,78,324,1142,896,767,416,780,373,117,1,71,235,302,307,906,321,480,991,1586,1491,1617,653,499,1323,156,455,19,669,169,415,284,743,439,705,980,1350,210,118,797,81,67,894,183,10,439,950,1126,576,828,85,681,517,19,872,119,164,882,31,244,195,640,41,313,888,303,224,433,462,389,329,254,488,570,286,945,1377,32,1101,206,457,584,662,1176,9,1164,227,467,239,1094,131,420,871,942,52,1276,14,72,7,1099,702,53,118,263,645,181,60,105,780,1102,550,85,225,1159,250,1424,8,1060,458,79,299,744,76,1513,338,68,179,323,644,65,293,66,153,699,819,966,678,207,538,372,284,101,224,305,103,1276,577,316,350,647,314,1256,595,1332,133,83,654,1072,63,446,46,5,92,939,608,940,257,851,1715,742,96,1497,240,1154,30,69,803,13,47,380,97,349,742,581,768,94,454,25,330,899,584,1425,447,207,1621,329,429,22,361,3,24,534,361,695,61,680,517,43,129,1686,301,1090,211,680,362,855,700,392,354,871,154,485,654,203,1417,208,1228,243,317,899,106,307,62,157,186,291,475,616,137,113,1367,24,778,431,1563,36,651,131,259,165,765,226,28,1410,456,1601,11,21,323,214,208,1444,11,108,49,1182,89,564,1266,478,1324,538,1572,488,1546,434,1168,615,285,507,561,100,1092,30,866,946,840,322,625,106,101,157,209,531,63,133,103,715,666,1655,81,1439,1016,32,441,86,1597,1273,443,732,160,162,528,727,150,107,21,111,10,502,302,1315,643,84,318,1488,315,150,5,248,675,167,691,101,412,584,992,1317,18,1046,164,359,111,1105,96,16,301,463,680,443,433,477,420,1141,362,1840,12,57,1094,806,23,708,243,1060,894,403,941,958,240,903,497,1342,1068,35,399,381,19,499,339,0,226,108,292,1607,281,72,283,316,182,224,33,488,786,1456,25,104,201,549,827,890,1520,931,70,763,25,633,464,822,751,327,144,62,1205,78,1007,216,324,316,289,682,1359,198,204,199,29,580,10,338,45,150,217,290,734,985,1654,201,934,0,793,956,549,230,1337,183,115,229,31,122,90,1264,122,1292,278,78,256,919,365,444,455,1235,484,45,1646,21,895,218,179,1311,141,238,1330,40,593,518,95,466,233,125,777,150,315,606,265,935,13,89,961,394,341,88,485,57,725,665,616,889,577,100,154,686,842,772,581,1311,604,41,62,1439,313,320,225,1115,279,176,995,12,70,739,96,4,2,37,252,1164,1243,899,856,10,219,233,1430,443,1011,30,378,81,39,167,1060,9,601,663,89,718,1192,1579,511,85,180,236,1079,556,496,215,192,718,300,1282,475,984,535,1760,1137,439,759,221,125,1298,542,1119,446,204,90,16,84,63,176,26,123,1157,140,518,1115,514,701,1207,547,39,970,240,584,77,66,44,858,560,21,648,309,1096,618,220,28,75,1442,233,1,86,325,244,161,218,6,229,1104,275,754,60,186,882,232,133,1288,42,697,152,252,396,345,38,672,980,1514,468,102,563,871,313,358,97,28,1018,830,182,32,1335,525,490,419,1182,946,362,57,496,799,194,504,1615,440,566,481,283,1422,133,919,185,695,871,1422,1372,250,96,438,743,954,1363,349,814,1235,642,461,160,135,131,61,250,188,125,698,346,470,603,1391,460,578,404,3,14,1715,1271,856,1334,28,739,274,628,70,456,393,5,326,382,70,244,101,560,424,1521,25,1441,147,851,1207,747,84,703,172,101,87,357,421,91,939,595,581,149,626,797,1485,419,192,828,1031,1283,333,614,479,1344,520,1434,1422,877 diff --git a/2021/day-07/solution.js b/2021/day-07/solution.js new file mode 100644 index 0000000..94c9ecb --- /dev/null +++ b/2021/day-07/solution.js @@ -0,0 +1,36 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { parseData } = require('../../2018/inputParser') +const { getLeastFuel } = require('./crabs') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = parseData(initData.trim()) + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + return JSON.parse(JSON.stringify(initData)) + } + + const part1 = () => { + const data = resetInput() + const result = getLeastFuel(data) + return result + } + + const part2 = () => { + const data = resetInput() + console.debug(data) + return 'No answer yet' + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/index.js b/index.js index 0d94d20..fe03a56 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2021/day-06/solution') +require('./2021/day-07/solution') From b3a27cc506c83ade89aa51f31bde68112bfd8af9 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 07:18:48 -0800 Subject: [PATCH 2/2] feat(2021-day-07): find least fuel usage using complex expenditure Crabs have an exponential (logarithmic?) cost for movement. Solves part 2 --- 2021/day-07/crabs.js | 38 +++++++++++++++++++++++++++++--------- 2021/day-07/crabs.test.js | 13 +++++++++++++ 2021/day-07/solution.js | 4 ++-- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/2021/day-07/crabs.js b/2021/day-07/crabs.js index 572aa9e..09c5339 100644 --- a/2021/day-07/crabs.js +++ b/2021/day-07/crabs.js @@ -1,16 +1,36 @@ const sum = (x, y) => x + y -const getFuel = (crabs, destination) => { - return crabs.map((crab) => Math.abs(crab - destination)) - .reduce(sum) +const getFuel = (crabs, destination, exponential = false) => { + const simpleCalc = (crab) => { + const distance = Math.abs(crab - destination) + return distance + } + + const expoCalc = (crab) => { + const distance = Math.abs(crab - destination) + let fuel = 0 + for (let x = 1; x <= distance; x++) { + fuel += x + } + return fuel + } + + if (exponential) { + return crabs.map(expoCalc).reduce(sum) + } + return crabs.map(simpleCalc).reduce(sum) } -const getLeastFuel = (crabs) => { - const positions = crabs - let fuel = crabs.length * crabs.length // assume a cluster of crabs super far away is the initial worst case - positions.forEach((position) => { - fuel = Math.min(fuel, getFuel(crabs, position)) - }) +const getLeastFuel = (crabs, exponential = false) => { + const positions = JSON.parse(JSON.stringify(crabs)) // Deep copy to ensure we aren't mutating the original data + let fuel = 100000000 // assume a stupid high fuel count to start + const highest = positions.sort((a, b) => b - a)[0] // Find the largest position + for (let x = 0; x <= highest; x++) { + console.debug(`Checking position ${x}`) + const proposed = getFuel(crabs, x, exponential) + console.debug(`Needed fuel would be ${proposed}`) + fuel = Math.min(fuel, proposed) + } return fuel } diff --git a/2021/day-07/crabs.test.js b/2021/day-07/crabs.test.js index 67a3947..3737e3f 100644 --- a/2021/day-07/crabs.test.js +++ b/2021/day-07/crabs.test.js @@ -20,4 +20,17 @@ describe('--- Day 7: The Treachery of Whales ---', () => { }) }) }) + describe('Part 2', () => { + describe('getFuel() exponentially', () => { + it('counts how much fuel is exponentially needed to position all the crabs', () => { + expect(getFuel(testCrabs, 5, true)).to.equal(168) + expect(getFuel(testCrabs, 2, true)).to.equal(206) + }) + }) + describe('getLeastFuel() exponentially', () => { + it('determine the fuel exponentially spent for the least costly position', () => { + expect(getLeastFuel(testCrabs, true)).to.equal(168) + }) + }) + }) }) diff --git a/2021/day-07/solution.js b/2021/day-07/solution.js index 94c9ecb..b2ab58e 100644 --- a/2021/day-07/solution.js +++ b/2021/day-07/solution.js @@ -22,8 +22,8 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { const part2 = () => { const data = resetInput() - console.debug(data) - return 'No answer yet' + const result = getLeastFuel(data, true) + return result } const answers = [] answers.push(part1()) 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