The task involves analyzing a bunch of lines containing lines of text. Each line represents a calibration value that needs to be recovered by extracting the first and last digits and combining them into a two-digit number. The goal is to find the sum of all these calibration values. Note: sometimes there is only 1 digit, it will count both as the first and last digit.
// ==UserScript==
// @name Advent of Code, day 1
// @namespace Violentmonkey Scripts
// @match https://adventofcode.com/2023/day/1/input
// @grant none
// @version 1.0
// @author -
// @description 12/7/2023, 9:26:24 AM
// ==/UserScript==
const lines = document.body.textContent.split('\n');
let sum = 0;
for(line of lines){
const matches = [...line.matchAll(/\d/g)];
const first = matches[0][0]*10;
const last = matches.slice(-1)[0][0]*1;
sum += first + last;
}
console.log(sum);
1 Answer 1
Use functions
ALways encapsulate code in a function at the very minimum.
Example It should look something like...
function sumText(text) {
"use strict";
const lines = text.split('\n');
let sum = 0;
for (line of lines) { // << warning
const matches = [...line.matchAll(/\d/g)];
const first = matches[0][0] * 10;
const last = matches.slice(-1)[0][0] * 1;
sum += first + last;
}
return sum;
}
console.log(sumText(document.body.textContent));
Strict mode
However that the above code will not run. Why?
The line "use strict";
is a directive that tells the JS engine to run the function in strict mode. Which you should always do.
However the line for(line of lines){
tries to use an undeclared variable line
. When not in strict mode the JS engine will declare the variable for you in global scope. This is very dangerous and can break unrelated code.
Because undeclared variables are so dangerous strict mode will consider it an error and not run the code.
To fix you MUST declare all variables. Thus the line becomes for (const line of lines) {
or for (let line of lines) {
Be efficient
Do not add redundant code. It makes the source code more complex and thus harder to read and maintain.
Example converting an array to an array in the line
const matches = [...line.matchAll(/\d/g)];
There is no need as it is identical to
const matches = line.matchAll(/\d/g);
Avoid single use variables
const first = matches[0][0]*10; const last = matches.slice(-1)[0][0]*1; sum += first + last;
Can be
sum += matches[0][0] * 10;
sum += matches.slice(-1)[0][0] * 1;
Or
sum += matches[0][0] * 10;
sum += matches.pop()[0] * 1;
Or
sum += matches[0][0] * 10;
sum += Number(matches[matches.length - 1][0]);
The last line is slightly better than multiplying by * 1
as multiplying requires converting to a number (internal call to Number()
) and then multiplying.
Using Number
avoids the need to multiply by 1 (Note the optimizer may ignore the * 1
depending on browser/JS engine and version)
Performance
Without the strict mode directive and the undeclared variable line, the performance will be adversely affected as using a global scoped variable is much slower than a locally scoped variable.
Overall not the fastest possible solution, but a single fast solution is not possible as the length of the input string and each line will affect the type of search you should use for the quickest solution.
As you don't mention performance in the question I only bring it up as the undeclared variable has many problems, not just global scope name clashing.
-
\$\begingroup\$ for me
document.body.textContent
pulled too many lines, assuming this is just my issue and you add a return to the function; you could also simplify the summation tosum += Number(line.replace(/^\D*(\d).*(\d)\D*$|^\D*(\d)\D*$/,"1ドル2ドル3ドル3ドル"));
\$\endgroup\$Gregor y– Gregor y2023年12月07日 22:28:22 +00:00Commented Dec 7, 2023 at 22:28 -
\$\begingroup\$ Oh dear, I knew I had to add the return but totally forgot to add it. Thanks for the heads up. Personally I think that regExp should be considered magic unreadable unmaintainable expressions, akin to golf with the language brainf**k. I am sure your expression works, but with a causal look in a sea of code I would have no idea what its intent was. \$\endgroup\$Blindman67– Blindman672023年12月07日 23:03:36 +00:00Commented Dec 7, 2023 at 23:03
-
\$\begingroup\$ fair point, I guess I assumed that since the OP had regex they knew how to read it. jsfiddle.net/59soetka \$\endgroup\$Gregor y– Gregor y2023年12月07日 23:09:30 +00:00Commented Dec 7, 2023 at 23:09
-
\$\begingroup\$
matchAll
does not return an array, but an iterator, which I convert to an array. Good call online
\$\endgroup\$konijn– konijn2023年12月08日 07:54:44 +00:00Commented Dec 8, 2023 at 7:54 -
\$\begingroup\$ @konijn IMHO If it looks, talks, and walks like a??? Javascript is full of
is like
eg1 typeof === "number"
is true and1 instanceof Number
is false. 1 is like a Number, it's only when we need to access member properties that we make the distinction. How pedantic do we need to get? \$\endgroup\$Blindman67– Blindman672023年12月08日 18:01:57 +00:00Commented Dec 8, 2023 at 18:01