{"data":{"mdx":{"id":"340114e6-a536-57fb-bdb4-df1a93958b34","code":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"date\": \"2019-05-04\",\n  \"order\": 2,\n  \"title\": \"Computing, Fast and Slow\",\n  \"tags\": [\"education\", \"javascript\", \"Advent of Code\"]\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Part Two gets tougher.\"), mdx(\"h2\", null, \"The Problem\"), mdx(\"p\", null, \"The goal of Part Two is to use the same list of changes from Part One and find the first frequency that repeats. It may be necessary to go through the list of changes more than once.\"), mdx(\"p\", null, \"Using the list of Example Data from before\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"-19\\n+3\\n+7\\n-1\\n+21\\n\")), mdx(\"p\", null, \"starting from 0, applying the frequency changes one at a time, gets the following frequencies:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"0 - 19 = -19\\n-19 + 3 = -16\\n-16 + 7 = -9\\n-9 - 1 = -10\\n-10 + 21 = 11\\n(repeat the list)\\n11 - 19 = -8\\n-8 + 3 = 5\\n5 + 7 = 12\\n12 - 1 = 11\\n\")), mdx(\"p\", null, \"For this list, 11 is the first frequency that occurs twice.\"), mdx(\"p\", null, \"Naturally, the list in the Advent of Code problem is a lot bigger - over 1000 numbers, structured in a way that means the list has to be looped over many times to get a single frequency to repeat. We'll have to write code for this one.\"), mdx(\"h2\", null, \"Solution Steps\"), mdx(\"p\", null, \"The solution to this problem has to do the following:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"loop over the list an indefinite number of times\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"keep track of which frequencies occur\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"detect when a frequency occurs twice\")), mdx(\"h2\", null, \"Dealing with Data Storage, Take One\"), mdx(\"p\", null, \"If you're like me, the first thing you think of to store a bunch of data is an array. To find whether an array includes a value, you can use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".includes()\"), \" method. For this problem, with the amount of data involved, that works! But it's not the best. Here's a solution, with some timing code added so we can see how long it takes.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// sequence is defined as above\\nconsole.time('arraySolution')\\nlet currentFrequency = 0\\nlet allFrequencies = []\\nlet sequenceIndex = 0\\n// the while statement will loop until a frequency repeats\\nwhile (!allFrequencies.includes(currentFrequency)) {\\n  // push into the allFrequencies array to keep track\\n  // of which frequencies have occurred\\n  allFrequencies.push(currentFrequency)\\n  currentFrequency += sequence[sequenceIndex]\\n  sequenceIndex += 1\\n  if (sequenceIndex === sequence.length) {\\n    // restart the list of frequency changes\\n    // whe you reach the end of the changes array\\n    sequenceIndex = 0\\n  }\\n}\\nconsole.log(currentFrequency)\\nconsole.timeEnd('arraySolution')\\n\")), mdx(\"p\", null, \"The calls to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.time('arraySolution')\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.timeEnd('arraySolution')\"), \" provide benchmarking data, meaning at \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"timeEnd\"), \" what gets printed to the console is the time elapsed since \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.time\"), \". (The timer name argument is optional in this case; in more complicated code, multiple timers can be run all at once by giving each \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"time\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"timeEnd\"), \" pair its own name.)\"), mdx(\"p\", null, \"This solution is valid, but it's slow. On my 2014 MacBook Air, it takes about 14000ms. We can do better.\"), mdx(\"h2\", null, \"Dealing with Data Storage, Take Two\"), mdx(\"p\", null, \"Objects can be used to store data, too. Usually, objects have categorical keys and specific values, like\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"let computer = {\\n  manufacturer: 'Apple',\\n  operatingSystem: 'macOS Sierra',\\n}\\n\\nlet phone = {\\n  manufacturer: 'Motorola',\\n  operatingSystem: 'Android 8.1.0',\\n}\\n\")), mdx(\"p\", null, \"For this problem, there aren't any categories like \\\"manufacturer\\\" to associate with the frequencies we want to store. The solution is to use the frequencies themselves as the keys! Or at least the string versions of them - all keys in JavaScript objects are strings. The value associated with every key in the object can be simply \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"true\"), \", because the only thing of interest about a key in this object is that it exists in the object.\"), mdx(\"p\", null, \"The frequencies derived from the example data above (which were -19, -16, -9, etc) could be stored in an object like\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"let frequencies = { '-19': true, '-16': true, '-9': true }\\n\")), mdx(\"p\", null, \"Once we have an object with frequencies used for keys, looking for a frequency means accessing the key in the object:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"frequencies[-16] // true; -16 is a frequency in the object\\nfrequencies[42] // undefined; 42 is not a frequency in the object\\n\")), mdx(\"p\", null, \"Accessing a key in an object like that is much faster than searching through an array with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".includes\"), \". Here is the object-focused solution:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"console.time('objectSolution')\\nlet currentFrequency = 0\\nlet allFrequencies = {}\\nlet sequenceIndex = 0\\nwhile (!allFrequencies[currentFrequency]) {\\n  allFrequencies[currentFrequency] = true\\n  currentFrequency += sequence[sequenceIndex]\\n  sequenceIndex += 1\\n  if (sequenceIndex === sequence.length) {\\n    sequenceIndex = 0\\n  }\\n}\\nconsole.log(currentFrequency)\\nconsole.timeEnd('objectSolution')\\n\")), mdx(\"p\", null, \"More than half of this code is identical to the array solution. The only changes are\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"initializing \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"allFrequencies\"), \" to an empty object instead of an empty array\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"looking for \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"currentFrequency\"), \" in the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"while\"), \" condition with \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"!allFrequencies[currentFrequency]\"), \" instead of \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"!allFrequencies.includes(currentFrequency)\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"adding to the data collection with \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"allFrequencies[currentFrequency] = true\"), \" instead of \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"allFrequencies.push(currentFrequency)\"))), mdx(\"p\", null, \"Even so, using an object instead of an array reduces the algorithm's runtime from ~14000ms to \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"~20ms\"), \".\"), mdx(\"h2\", null, \"Dealing with Data, Take three\"), mdx(\"p\", null, \"A third option that didn't occur to me until months later is to use the new(-ish) \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Set\"), \" object, which is made for just this kind of thing.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"console.time('objectSolution')\\nlet currentFrequency = 0\\nlet allFrequencies = new Set()\\nlet sequenceIndex = 0\\nwhile (!allFrequencies.has(currentFrequency)) {\\n  allFrequencies.add(currentFrequency)\\n  currentFrequency += sequence[sequenceIndex]\\n  sequenceIndex += 1\\n  if (sequenceIndex === sequence.length) {\\n    sequenceIndex = 0\\n  }\\n}\\nconsole.log(currentFrequency)\\nconsole.timeEnd('objectSolution')\\n\")), mdx(\"p\", null, \"Once again, only three lines need to change compared to the other solutions. They are\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"initializing \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"allFrequencies\"), \" to a new Set\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"looking for \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"currentFrequency\"), \" in the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"while\"), \" condition with \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"!allFrequencies.has(currentFrequency)\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"adding to the data collection with \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"allFrequencies.add(currentFrequency)\"))), mdx(\"p\", null, \"I was surprised to see that even though this problem seems like a perfect use case for a Set, on my machine, the set-based solution took about twice as long as the object-based solution.\"));\n}\nMDXContent.isMDXComponent = true;"}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"id":"340114e6-a536-57fb-bdb4-df1a93958b34","slug":"/2018-advent-of-code-day-one-part-two/","timeToRead":2,"wordCount":613,"frontMatter":{"date":"2019-05-04","title":"Computing, Fast and Slow","tags":["education","javascript","Advent of Code"]},"prev":{"id":"b7118581-8cfd-5918-8049-7800ffaeba3c","parent":{"name":"2018-advent-of-code-day-one"},"excerpt":"2018 Advent of Code, Day One Advent of Code  is a series of software puzzles released every year during Advent ^advent . There's a cute…","fields":{"slug":"/2018-advent-of-code-day-one/"},"timeToRead":4,"wordCount":{"words":1158},"frontmatter":{"date":"2019-05-04","title":"Solving Problems with Code","tags":["education","javascript","Advent of Code"]}},"next":{"id":"f9259443-a8bc-5513-a25d-a9047bce322e","parent":{"name":"2018-advent-of-code-day-two"},"excerpt":"Day Two focuses on finding patterns in strings. The Problem For the first puzzle, we're asked to take a set of strings of letters referred…","fields":{"slug":"/2018-advent-of-code-day-two/"},"timeToRead":5,"wordCount":{"words":1310},"frontmatter":{"date":"2019-05-04","title":"Solve a Smaller Problem First","tags":["education","javascript","Advent of Code"]}}}}