/^/

Lesson 26 of 28

Regex Challenges

How the graded Challenges section works, and a worked example to show what solving one actually feels like.

5 min read

Reading about regex gets you most of the way there, but the skill only really sticks once you’ve stared at a blank pattern field and made it work yourself. That’s what the Challenges section of this site is for — a growing library of hands-on problems, separate from these lessons, built specifically for practice rather than instruction.

How challenges are organized

Every challenge is tagged with one of four difficulty levels:

Difficulty What to expect
Easy Single concept — a character class, an anchor, a simple quantifier
Medium Combining two or three concepts, like groups plus alternation
Hard Multi-part patterns, lookaround, or subtle edge cases
Expert Real-world messiness — ambiguous input, performance constraints, or patterns that require genuine cleverness

Each individual challenge gives you:

  • A problem statement describing what the pattern needs to match (and, just as importantly, what it must not match)
  • A hint you can reveal if you get stuck, without spoiling the full answer
  • An embedded tester so you can write and try your pattern immediately, against the exact sample inputs the challenge cares about
  • A full solution and explanation once you’re ready — not just “here’s the regex,” but why it’s built that way

Tip

Try to resist opening the solution too early. Getting a pattern almost-right and then debugging why it fails on one input is where most of the actual learning happens — the solution is there to confirm your reasoning, not replace it.

A worked example

Here’s a taste of what a Medium challenge looks like, worked through end to end.

Challenge: Match a valid hex color code

Problem: Write a pattern that matches a CSS hex color — a # followed by either exactly 3 or exactly 6 hexadecimal digits (0-9, a-f, A-F) — and rejects anything else, including strings with the wrong digit count or non-hex characters.

Hint: You’ll need alternation to allow either length, and the whole thing needs to be anchored so a 5-digit code like #12345 can’t sneak through by matching just the first 3 characters.

#fff #A1B2C3 #12345 red #12
2 matches· capture groups: 1
Show solution
const hexColor = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;

Walking through it:

  • ^# — the string must start with a literal #
  • ([0-9a-fA-F]{3}|[0-9a-fA-F]{6}) — a group offering two alternatives: exactly 3 hex digits, or exactly 6
  • $ — nothing else is allowed to follow

Run it against the demo’s five test lines: #fff and #A1B2C3 match (3 and 6 digits respectively), while #12345 is rejected — it has 5 digits, which fits neither branch of the alternation — red is rejected for having no # at all, and #12 is rejected as too short for either alternative. The anchors are doing real work here: without $, a lazier version of this pattern would happily match the first 3 characters of #12345 and call it a valid color, which is exactly the kind of bug a real challenge is designed to catch.

Why a separate section

These lessons are built to teach one concept cleanly at a time, with a demo tuned to illustrate exactly that concept. Challenges are the opposite by design: messier, more open-ended, and often requiring you to combine ideas from several lessons at once — closer to what solving a real problem actually feels like. Working through both is what turns “I understand regex” into “I can sit down and write one that works.”

What’s next

The Challenges section keeps growing, and it’s the best place to spend time once you’ve finished this course — browse all challenges to see the full, graded set. The next lesson gives you a handful of standalone exercises right here, covering ideas from across the whole course.

Quick check

Which of these strings does NOT match ^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ ?

According to this lesson, what does each entry in the Challenges section include?