diff --git a/Cargo.lock b/Cargo.lock
index 3950c47..e42b8f4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -533,10 +533,10 @@ dependencies = [
  "indicatif",
  "notify-debouncer-mini",
  "predicates",
- "regex",
  "serde",
  "serde_json",
  "toml",
+ "winnow",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 218b799..dd4c0c3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,10 +15,10 @@ glob = "0.3.0"
 home = "0.5.9"
 indicatif = "0.17.8"
 notify-debouncer-mini = "0.4.1"
-regex = "1.10.3"
 serde_json = "1.0.114"
 serde = { version = "1.0.197", features = ["derive"] }
 toml = "0.8.10"
+winnow = "0.6.5"
 
 [[bin]]
 name = "rustlings"
diff --git a/src/exercise.rs b/src/exercise.rs
index b112fe8..8f580d3 100644
--- a/src/exercise.rs
+++ b/src/exercise.rs
@@ -1,4 +1,3 @@
-use regex::Regex;
 use serde::Deserialize;
 use std::fmt::{self, Display, Formatter};
 use std::fs::{self, remove_file, File};
@@ -6,14 +5,34 @@ use std::io::{self, BufRead, BufReader};
 use std::path::PathBuf;
 use std::process::{self, Command};
 use std::{array, env, mem};
+use winnow::ascii::{space0, space1};
+use winnow::combinator::opt;
+use winnow::Parser;
 
 const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
 const RUSTC_EDITION_ARGS: &[&str] = &["--edition", "2021"];
 const RUSTC_NO_DEBUG_ARGS: &[&str] = &["-C", "strip=debuginfo"];
-const I_AM_DONE_REGEX: &str = r"^\s*///?\s*I\s+AM\s+NOT\s+DONE";
 const CONTEXT: usize = 2;
 const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/22_clippy/Cargo.toml";
 
+fn not_done(input: &str) -> bool {
+    (
+        space0::<_, ()>,
+        "//",
+        opt('/'),
+        space0,
+        'I',
+        space1,
+        "AM",
+        space1,
+        "NOT",
+        space1,
+        "DONE",
+    )
+        .parse_next(&mut &*input)
+        .is_ok()
+}
+
 // Get a temporary file name that is hopefully unique
 #[inline]
 fn temp_file() -> String {
@@ -223,7 +242,6 @@ path = "{}.rs""#,
             Ok(n)
         };
 
-        let re = Regex::new(I_AM_DONE_REGEX).unwrap();
         let mut matched_line_ind: usize = 0;
         let mut prev_lines: [_; CONTEXT] = array::from_fn(|_| String::with_capacity(256));
         let mut line = String::with_capacity(256);
@@ -232,7 +250,7 @@ path = "{}.rs""#,
             match read_line(&mut line) {
                 Ok(0) => break,
                 Ok(_) => {
-                    if re.is_match(&line) {
+                    if not_done(&line) {
                         let mut context = Vec::with_capacity(2 * CONTEXT + 1);
                         for (ind, prev_line) in prev_lines
                             .into_iter()
@@ -413,4 +431,22 @@ mod test {
         let out = exercise.compile().unwrap().run().unwrap();
         assert!(out.stdout.contains("THIS TEST TOO SHALL PASS"));
     }
+
+    #[test]
+    fn test_not_done() {
+        assert!(not_done("// I AM NOT DONE"));
+        assert!(not_done("/// I AM NOT DONE"));
+        assert!(not_done("//  I AM NOT DONE"));
+        assert!(not_done("///  I AM NOT DONE"));
+        assert!(not_done("// I  AM NOT DONE"));
+        assert!(not_done("// I AM  NOT DONE"));
+        assert!(not_done("// I AM NOT  DONE"));
+        assert!(not_done("// I AM NOT DONE "));
+        assert!(not_done("// I AM NOT DONE!"));
+
+        assert!(!not_done("I AM NOT DONE"));
+        assert!(!not_done("// NOT DONE"));
+        assert!(!not_done("DONE"));
+        assert!(!not_done("// i am not done"));
+    }
 }