2
\$\begingroup\$

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);
asked Dec 7, 2023 at 12:45
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

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.

answered Dec 7, 2023 at 19:24
\$\endgroup\$
7
  • \$\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 to sum += Number(line.replace(/^\D*(\d).*(\d)\D*$|^\D*(\d)\D*$/,"1ドル2ドル3ドル3ドル")); \$\endgroup\$ Commented 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\$ Commented 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\$ Commented Dec 7, 2023 at 23:09
  • \$\begingroup\$ matchAll does not return an array, but an iterator, which I convert to an array. Good call on line \$\endgroup\$ Commented Dec 8, 2023 at 7:54
  • \$\begingroup\$ @konijn IMHO If it looks, talks, and walks like a??? Javascript is full of is like eg 1 typeof === "number" is true and 1 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\$ Commented Dec 8, 2023 at 18:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.