From bc83ffccb2a391b2e4f82627a3f421d2f515f871 Mon Sep 17 00:00:00 2001 From: Arya Soni Date: Sun, 5 Oct 2025 13:10:32 +0530 Subject: [PATCH 1/3] [Concept] Regular Expressions-add exercise templates --- internal/exercises/catalog.yaml | 12 +++ .../exercises/templates/28_regex/regex.go | 37 +++++++ .../templates/28_regex/regex_test.go | 99 +++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 internal/exercises/templates/28_regex/regex.go create mode 100644 internal/exercises/templates/28_regex/regex_test.go diff --git a/internal/exercises/catalog.yaml b/internal/exercises/catalog.yaml index f60c3bd..3637cdb 100644 --- a/internal/exercises/catalog.yaml +++ b/internal/exercises/catalog.yaml @@ -134,6 +134,18 @@ concepts: test_regex: ".*" hints: - Define a custom error type and return it from a function. +- slug: 28_regex + title: Regular Expressions + test_regex: ".*" + hints: + - Use regexp.MustCompile to create compiled regular expressions. + - Use MatchString to test if a string matches a pattern. + - Use FindAllString to extract all matches from text. + - Use ReplaceAllString to replace matches with new text. + - "Email regex: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" + - "Phone regex: ^\\(\\d{3}\\) \\d{3}-\\d{4}$" + - "Number regex: \\d+\\.?\\d*" + - "Vowel regex: [aeiouAEIOU]" - slug: 37_xml title: XML Encoding and Decoding test_regex: ".*" diff --git a/internal/exercises/templates/28_regex/regex.go b/internal/exercises/templates/28_regex/regex.go new file mode 100644 index 0000000..d53b161 --- /dev/null +++ b/internal/exercises/templates/28_regex/regex.go @@ -0,0 +1,37 @@ +package regex + +// Task: +// Implement regular expression functions using Go's regexp package. +// +// 1. Implement IsValidEmail to validate email addresses using regex. +// 2. Implement ExtractNumbers to extract all numbers from a string. +// 3. Implement ReplaceVowels to replace all vowels with asterisks. +// 4. Implement IsPhoneNumber to validate phone numbers in format (XXX) XXX-XXXX. + +// IsValidEmail should return true if the email address is valid. +// A valid email should have the format: user@domain.com +func IsValidEmail(email string) bool { + // TODO: implement using regexp.MustCompile and MatchString + return false +} + +// ExtractNumbers should return all numbers found in the input string. +// Numbers can be integers or decimals (e.g., "123", "45.67"). +func ExtractNumbers(text string) []string { + // TODO: implement using regexp.FindAllString + return nil +} + +// ReplaceVowels should replace all vowels (a, e, i, o, u) with asterisks. +// Case-insensitive replacement. +func ReplaceVowels(text string) string { + // TODO: implement using regexp.MustCompile and ReplaceAllString + return "" +} + +// IsPhoneNumber should return true if the phone number matches format (XXX) XXX-XXXX. +// Example: (123) 456-7890 +func IsPhoneNumber(phone string) bool { + // TODO: implement using regexp.MustCompile and MatchString + return false +} diff --git a/internal/exercises/templates/28_regex/regex_test.go b/internal/exercises/templates/28_regex/regex_test.go new file mode 100644 index 0000000..087b45a --- /dev/null +++ b/internal/exercises/templates/28_regex/regex_test.go @@ -0,0 +1,99 @@ +package regex + +import "testing" + +func TestIsValidEmail(t *testing.T) { + tests := []struct { + email string + expected bool + }{ + {"user@domain.com", true}, + {"test.email@example.org", true}, + {"invalid-email", false}, + {"@domain.com", false}, + {"user@", false}, + {"user@domain", false}, + {"", false}, + } + + for _, test := range tests { + result := IsValidEmail(test.email) + if result != test.expected { + t.Errorf("IsValidEmail(%q) = %v, want %v", test.email, result, test.expected) + } + } +} + +func TestExtractNumbers(t *testing.T) { + tests := []struct { + text string + expected []string + }{ + {"I have 123 apples and 45.67 oranges", []string{"123", "45.67"}}, + {"The price is $99.99", []string{"99.99"}}, + {"No numbers here", []string{}}, + {"123", []string{"123"}}, + {"12.34.56", []string{"12.34", "56"}}, + {"", []string{}}, + } + + for _, test := range tests { + result := ExtractNumbers(test.text) + if len(result) != len(test.expected) { + t.Errorf("ExtractNumbers(%q) length = %d, want %d", test.text, len(result), len(test.expected)) + continue + } + for i, num := range result { + if num != test.expected[i] { + t.Errorf("ExtractNumbers(%q)[%d] = %q, want %q", test.text, i, num, test.expected[i]) + } + } + } +} + +func TestReplaceVowels(t *testing.T) { + tests := []struct { + text string + expected string + }{ + {"hello", "h*ll*"}, + {"HELLO", "H*LL*"}, + {"Hello World", "H*ll* W*rld"}, + {"bcdfg", "bcdfg"}, + {"", ""}, + {"aeiou", "*****"}, + {"AEIOU", "*****"}, + } + + for _, test := range tests { + result := ReplaceVowels(test.text) + if result != test.expected { + t.Errorf("ReplaceVowels(%q) = %q, want %q", test.text, result, test.expected) + } + } +} + +func TestIsPhoneNumber(t *testing.T) { + tests := []struct { + phone string + expected bool + }{ + {"(123) 456-7890", true}, + {"(555) 123-4567", true}, + {"(000) 000-0000", true}, + {"123-456-7890", false}, + {"(123)456-7890", false}, + {"(123) 4567890", false}, + {"123 456 7890", false}, + {"(123) 456-789", false}, + {"(12) 456-7890", false}, + {"", false}, + } + + for _, test := range tests { + result := IsPhoneNumber(test.phone) + if result != test.expected { + t.Errorf("IsPhoneNumber(%q) = %v, want %v", test.phone, result, test.expected) + } + } +} From 1d28a4bea4fc0f217d9541c771f39827267eb54a Mon Sep 17 00:00:00 2001 From: Arya Soni Date: Thu, 9 Oct 2025 12:36:59 +0530 Subject: [PATCH 2/3] docs: Update exercises.md to include new exercises 28-35 --- docs/exercises.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/exercises.md b/docs/exercises.md index 7a88f72..217cc94 100644 --- a/docs/exercises.md +++ b/docs/exercises.md @@ -49,6 +49,14 @@ title: Exercises
  • 25_range_iterators - Range over Iterators
  • 26_errors - Error Handling
  • 27_custom_errors - Custom Errors
  • +
  • 28_defer - Defer
  • +
  • 29_go_routines - Go Routines
  • +
  • 30_channels - Channels
  • +
  • 31_mutexes - Mutexes
  • +
  • 32_sorting - Sorting
  • +
  • 33_string_formatting - String Formatting
  • +
  • 34_channel_buffering - Channel Buffering
  • +
  • 35_regex - Regular Expressions
  • 36_json - JSON Processing
  • 37_xml - XML Processing
  • From a43b76ef554fd86732a045de5b368e39f0228df3 Mon Sep 17 00:00:00 2001 From: Arya Soni Date: Fri, 10 Oct 2025 11:28:26 +0530 Subject: [PATCH 3/3] [Concept] Regular Expressions-add exercise templates --- .../solutions/35_regex/regex_test.go | 99 ------------------- 1 file changed, 99 deletions(-) delete mode 100644 internal/exercises/solutions/35_regex/regex_test.go diff --git a/internal/exercises/solutions/35_regex/regex_test.go b/internal/exercises/solutions/35_regex/regex_test.go deleted file mode 100644 index 087b45a..0000000 --- a/internal/exercises/solutions/35_regex/regex_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package regex - -import "testing" - -func TestIsValidEmail(t *testing.T) { - tests := []struct { - email string - expected bool - }{ - {"user@domain.com", true}, - {"test.email@example.org", true}, - {"invalid-email", false}, - {"@domain.com", false}, - {"user@", false}, - {"user@domain", false}, - {"", false}, - } - - for _, test := range tests { - result := IsValidEmail(test.email) - if result != test.expected { - t.Errorf("IsValidEmail(%q) = %v, want %v", test.email, result, test.expected) - } - } -} - -func TestExtractNumbers(t *testing.T) { - tests := []struct { - text string - expected []string - }{ - {"I have 123 apples and 45.67 oranges", []string{"123", "45.67"}}, - {"The price is $99.99", []string{"99.99"}}, - {"No numbers here", []string{}}, - {"123", []string{"123"}}, - {"12.34.56", []string{"12.34", "56"}}, - {"", []string{}}, - } - - for _, test := range tests { - result := ExtractNumbers(test.text) - if len(result) != len(test.expected) { - t.Errorf("ExtractNumbers(%q) length = %d, want %d", test.text, len(result), len(test.expected)) - continue - } - for i, num := range result { - if num != test.expected[i] { - t.Errorf("ExtractNumbers(%q)[%d] = %q, want %q", test.text, i, num, test.expected[i]) - } - } - } -} - -func TestReplaceVowels(t *testing.T) { - tests := []struct { - text string - expected string - }{ - {"hello", "h*ll*"}, - {"HELLO", "H*LL*"}, - {"Hello World", "H*ll* W*rld"}, - {"bcdfg", "bcdfg"}, - {"", ""}, - {"aeiou", "*****"}, - {"AEIOU", "*****"}, - } - - for _, test := range tests { - result := ReplaceVowels(test.text) - if result != test.expected { - t.Errorf("ReplaceVowels(%q) = %q, want %q", test.text, result, test.expected) - } - } -} - -func TestIsPhoneNumber(t *testing.T) { - tests := []struct { - phone string - expected bool - }{ - {"(123) 456-7890", true}, - {"(555) 123-4567", true}, - {"(000) 000-0000", true}, - {"123-456-7890", false}, - {"(123)456-7890", false}, - {"(123) 4567890", false}, - {"123 456 7890", false}, - {"(123) 456-789", false}, - {"(12) 456-7890", false}, - {"", false}, - } - - for _, test := range tests { - result := IsPhoneNumber(test.phone) - if result != test.expected { - t.Errorf("IsPhoneNumber(%q) = %v, want %v", test.phone, result, test.expected) - } - } -}