Learn Functional Programming by Building a Spreadsheet - Step 73

So i was really stuck on this task, because the instructions are very unclear and leave a lot of questions open for people who just handled a few regular expressions up to this point and dont really know the ins and outs of regex construction, and the error message is even less helpful.

This is the current task:

In your highPrecedence function, declare a regex variable. Assign it a regular expression that matches a number (including decimal numbers) followed by a * or / operator followed by another number.

Each number, and the operator, should be in separate capture groups.

And This was my solution, that, of my current knowledge, should complete this assignemtn just fine, or am i missing something?:

const highPrecedence = str => {
  const regex = /(\d*\.?\d+)([\/\*])(\d*\.?\d+)/;
}

I probably tried every imaginable adaptation to this regex, but it never rendered correctly, and the instructions really dont help in any way, as this is the error message i got:

Your first capture group should use a character class.

well, my first capture group uses a character class, what now?

I even went out and asked chat gpt what it thinks is the intended solution, but with instructions this unclear, even this fails, researching on stack overflow doesnt give the indeted result either…

So i know i can just skip to the next Task to see the solution, but i really dont like that im forced to so, just because of unclear instructions.

A better explanation of

  1. What is asked for, and
  2. What methods, regex rules is should follow

would be nice here for people who are just starting out in javascript.

And maybe give better hints when the code isnt working out for several tries…
This is also an issue with regular expressions in general, i stumbled very often creating them, never this long though, and in the previous tasks i always somehow managed to get to the right result.

This is the expected result:

const highPrecedence = str => {
  const regex = /([\d.]+)([*\/])([\d.]+)/;
}

So my suggestion is as follows:
Either, create a JavaScript Project that deals with heavy regex use to explain regex in more detail BEFORE tasks like this, OR make the instructions and error messages / hints for regex constructions clearer.

EDIT: So i think during writing this i know what i stumbled upon. Im being asked to “use” a character class. Not knowing what exactly character classes are, and searching for them online, leads first and foremost to this page:

There are all types of character classes listed. If im not mistaken, these represent already existing / predefined charcter classes within js regular expressions.

FCC is expecting us, to DEFINE a new character class (and also using the \d class), but tells us to “USE” them, which is the very thing i stumbled upon, since i though i escpeciallly should NOT define a character class, but use the pre-existing ones.

Some more insight on the proper terminology here would be also nice, since this seems utterly confusing in certain cases ^^

So thats bascially it…just my thoughts and experiences to maybe help improve the user experience here a bit…

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="./styles.css" />
    <title>Functional Programming Spreadsheet</title>
  </head>
  <body>
    <div id="container">
      <div></div>
    </div>
    <script src="./script.js"></script>
  </body>
</html>
/* file: styles.css */
#container {
  display: grid;
  grid-template-columns: 50px repeat(10, 200px);
  grid-template-rows: repeat(11, 30px);
}

.label {
  background-color: lightgray;
  text-align: center;
  vertical-align: middle;
  line-height: 30px;
}
/* file: script.js */
const infixToFunction = {
  "+": (x, y) => x + y,
  "-": (x, y) => x - y,
  "*": (x, y) => x * y,
  "/": (x, y) => x / y,
}

const infixEval = (str, regex) => str.replace(regex, (_match, arg1, operator, arg2) => infixToFunction[operator](parseFloat(arg1), parseFloat(arg2)));


// User Editable Region

const highPrecedence = str => {
  const regex = /(\d*\.?\d+)([\/\*])(\d*\.?\d+)/;
}

// User Editable Region


const isEven = num => num % 2 === 0;
const sum = nums => nums.reduce((acc, el) => acc + el, 0);
const average = nums => sum(nums) / nums.length;

const median = nums => {
  const sorted = nums.slice().sort((a, b) => a - b);
  const length = sorted.length;
  const middle = length / 2 - 1;
  return isEven(length)
    ? average([sorted[middle], sorted[middle + 1]])
    : sorted[Math.ceil(middle)];
}

const spreadsheetFunctions = {
  sum,
  average,
  median
}

const range = (start, end) => Array(end - start + 1).fill(start).map((element, index) => element + index);
const charRange = (start, end) => range(start.charCodeAt(0), end.charCodeAt(0)).map(code => String.fromCharCode(code));

const evalFormula = (x, cells) => {
  const idToText = id => cells.find(cell => cell.id === id).value;
  const rangeRegex = /([A-J])([1-9][0-9]?):([A-J])([1-9][0-9]?)/gi;
  const rangeFromString = (num1, num2) => range(parseInt(num1), parseInt(num2));
  const elemValue = num => character => idToText(character + num);
  const addCharacters = character1 => character2 => num => charRange(character1, character2).map(elemValue(num));
  const rangeExpanded = x.replace(rangeRegex, (_match, char1, num1, char2, num2) => rangeFromString(num1, num2).map(addCharacters(char1)(char2)));
  const cellRegex = /[A-J][1-9][0-9]?/gi;
  const cellExpanded = rangeExpanded.replace(cellRegex, match => idToText(match.toUpperCase()));
}

window.onload = () => {
  const container = document.getElementById("container");
  const createLabel = (name) => {
    const label = document.createElement("div");
    label.className = "label";
    label.textContent = name;
    container.appendChild(label);
  }
  const letters = charRange("A", "J");
  letters.forEach(createLabel);
  range(1, 99).forEach(number => {
    createLabel(number);
    letters.forEach(letter => {
      const input = document.createElement("input");
      input.type = "text";
      input.id = letter + number;
      input.ariaLabel = letter + number;
      input.onchange = update;
      container.appendChild(input);
    })
  })
}

const update = event => {
  const element = event.target;
  const value = element.value.replace(/\s/g, "");
  if (!value.includes(element.id) && value.startsWith('=')) {

  }
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36

Challenge Information:

Learn Functional Programming by Building a Spreadsheet - Step 73

Hi @salimo
quote=“salimo, post:1, topic:668714”]
const regex = /(\d*\.?\d+)([\/\*])(\d*\.?\d+)/;
[/quote]
image
I don’t see a character class.
The MDN article says that character classes use square brackets.

This is literally the first example the website has for a character class:

const regexpCoordinates = /\w\d/g;

Yes, the docs also mention square brackets, but this doesn’t change the fact that the instructions could be worded clearer.

Hi @Teller,
I also had trouble with this specific regex. What @salimo is saying here is that there is confusion with “character class”. In the MDN article, it lists specific character classes like \d and \w but also the square bracket notation . The confusion here is that \d is a named character class, so when the hint text says

“Your first capture group should use a character class”

it technically contains the character class of \d, but that’s not what the hint is asking for. What the hint should say to be more clear is something like:

“Your first capture group should use a custom character class with square bracket notation”

Also, to add on, I struggled with the 2nd capture group. The intended solution is ([*\/]), but my solution of ([\*\/]) also produces the same output. Check regexper [dot] com and put in both to see for yourself. But the hint does not make any mention as to why my solution is wrong and the intended is correct, when they both are technically correct.