Skip to content
Open
3 changes: 2 additions & 1 deletion docs/exercises.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ title: Exercises
<li>20_methods - Methods</li>
</ul>

<h3>Advanced (21-37)</h3>
<h3>Advanced (21-47)</h3>
<ul>
<li>21_interfaces - Interfaces</li>
<li>22_enums - Enums</li>
Expand All @@ -51,6 +51,7 @@ title: Exercises
<li>27_custom_errors - Custom Errors</li>
<li>36_json - JSON Processing</li>
<li>37_xml - XML Processing</li>
<li>47_string_functions - String Functions</li>
</ul>
</div>

Expand Down
158 changes: 80 additions & 78 deletions internal/exercises/catalog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,19 @@ concepts:
test_regex: ".*"
hints:
- Use `make(chan T, N)` to create a buffered channel and `<-` to send and receive on it.
- slug: 39_channel_directions
title: Channel Directions
test_regex: ".*"
hints:
- Create two channels, one for sending jobs and one for receiving results.
- Start 5 workers using go routines.
- Send 50 jobs to the worker pool.
- Receive results from the worker pool and store them in a `rs` slice.
- Enforce type safety by specifying the channel directions in worker function.
- slug: 35_channel_sync
title: Channel Synchronization
test_regex: ".*"
hints:
- Use a buffered boolean channel and wait till go routine completes.
- slug: 36_json
title: JSON
test_regex: ".*"
hints:
- Use the encoding/json package to work with JSON data.
- Implement MarshalPerson to convert a struct into JSON using json.Marshal.
- Implement UnmarshalPerson to convert a JSON string into a struct using json.Unmarshal.
- Handle and return errors properly in both functions.
- slug: 37_xml
title: XML Encoding and Decoding
test_regex: ".*"
Expand All @@ -191,6 +190,33 @@ concepts:
- Add XML struct tags using `xml:"fieldname"` to map struct fields to XML elements.
- Use xml.Marshal to convert structs to XML bytes.
- Use xml.Unmarshal to parse XML bytes into structs.
- slug: 48_sorting_by_functions
title: "Sorting by Functions"
difficulty: beginner
topics: ["slices", "sorting", "functions"]
hints:
- "Implement sort.Interface with Len(), Less(), and Swap() methods"
- "Create custom slice types like ByName and ByAge (e.g., type ByName []Person)"
- "Use sort.Sort() to sort slices with your custom comparison logic"
- "Remember to make copies of slices to avoid modifying the original"
- slug: 38_time_formatting
title: "Time Formatting"
difficulty: beginner
topics: ["time", "formatting", "parsing"]
hints:
- "Use time.Now().Format() to format current time with a specific layout"
- "Use time.Parse() to parse time strings with known layouts"
- "Use time.LoadLocation() to work with different timezones"
- "Extract time components using .Date() and .Clock() methods"
- slug: 39_channel_directions
title: Channel Directions
test_regex: ".*"
hints:
- Create two channels, one for sending jobs and one for receiving results.
- Start 5 workers using go routines.
- Send 50 jobs to the worker pool.
- Receive results from the worker pool and store them in a `rs` slice.
- Enforce type safety by specifying the channel directions in worker function.
- slug: 40_channel_select
title: Channel Select
test_regex: ".*"
Expand Down Expand Up @@ -247,7 +273,50 @@ concepts:
hints:
- Use `default` case in select to handle non-blocking channel operations.
- Safely increment `dropped` using mutex `Lock()` and `Unlock()`.

- slug: 47_string_functions
title: String Functions
test_regex: ".*"
hints:
- Use strings.Contains to check if a substring exists in a string.
- Use strings.HasPrefix and strings.HasSuffix for prefix/suffix checking.
- Use strings.Index to find the position of a substring.
- Use strings.ToUpper and strings.ToLower for case conversion.
- Use strings.TrimSpace to remove leading and trailing whitespace.
- slug: 49_panic
title: Panic and Recover
test_regex: ".*"
hints:
- "Use `panic()` to simulate runtime errors when appropriate."
- "Use `defer` with `recover()` to catch and handle panics."
- "Recovering from panics allows graceful handling of unexpected situations."
- "Remember: `recover()` only works inside a deferred function."
- slug: 50_timers
title: "Timers"
difficulty: medium
topics: ["time", "goroutines", "concurrency", "synchronization"]
test_regex: ".*"
hints:
- "Use a map[string]*time.Timer to track active timers by key."
- "Use a mutex to safely access the timers map concurrently."
- "Start a timer with time.AfterFunc(d, fn) to run a callback after duration d."
- "If Start is called again for an existing key, stop and replace the old timer."
- "Stop should remove the timer from the map and prevent the callback from firing."
- "Reset can call timer.Reset(d) to reschedule the same callback."
- "Remember to remove timers from the map after they fire to avoid memory leaks."
- "Write tests to verify Start, Stop, and Reset behavior, including concurrency scenarios."
- slug: 51_rate_limiting
title: Rate Limiting
test_regex: ".*"
difficulty: medium
topics: ["time", "concurrency", "maps"]
hints:
- "Implement a RateLimiter struct that tracks request timestamps per key using a map[string][]time.Time."
- "Use a mutex to safely handle concurrent access to the map."
- "In the Allow method, remove timestamps older than the interval and check if the number of recent requests exceeds the limit."
- "Reset should clear the request history for a key; if the key does not exist, do nothing."
- "Consider edge cases: multiple keys, concurrent access, and requests exactly at the interval boundary."
- "In tests, use time.Sleep with a small buffer above the interval to avoid flakiness."
- "Initialize the timestamps map in NewRateLimiter to prevent nil pointer errors."
projects:
- slug: 101_text_analyzer
title: Text Analyzer (Easy)
Expand Down Expand Up @@ -289,78 +358,11 @@ projects:
test_regex: ".*"
hints:
- Implement an in-memory key-value store with basic CRUD operations and optional persistence.
- slug: 36_json
title: JSON
test_regex: ".*"
hints:
- Use the encoding/json package to work with JSON data.
- Implement MarshalPerson to convert a struct into JSON using json.Marshal.
- Implement UnmarshalPerson to convert a JSON string into a struct using json.Unmarshal.
- Handle and return errors properly in both functions.

- slug: 109_epoch
title: "Epoch Conversion"
difficulty: beginner
topics: ["time", "epoch", "unix"]
hints:
- "Use Go's `time.Unix()` to convert an epoch to time."
- "Use `t.Unix()` to convert time back to epoch."
- "Remember Go’s `time.Parse` can help parse date strings."

- slug: 37_sorting_by_functions
title: "Sorting by Functions"
difficulty: beginner
topics: ["slices", "sorting", "functions"]
hints:
- "Implement sort.Interface with Len(), Less(), and Swap() methods"
- "Create custom slice types like ByName and ByAge (e.g., type ByName []Person)"
- "Use sort.Sort() to sort slices with your custom comparison logic"
- "Remember to make copies of slices to avoid modifying the original"

- slug: 38_time_formatting
title: "Time Formatting"
difficulty: beginner
topics: ["time", "formatting", "parsing"]
hints:
- "Use time.Now().Format() to format current time with a specific layout"
- "Use time.Parse() to parse time strings with known layouts"
- "Use time.LoadLocation() to work with different timezones"
- "Extract time components using .Date() and .Clock() methods"

- slug: 39_panic
title: Panic and Recover
test_regex: ".*"
hints:
- "Use `panic()` to simulate runtime errors when appropriate."
- "Use `defer` with `recover()` to catch and handle panics."
- "Recovering from panics allows graceful handling of unexpected situations."
- "Remember: `recover()` only works inside a deferred function."

- slug: 64_timers
title: "Timers"
difficulty: medium
topics: ["time", "goroutines", "concurrency", "synchronization"]
test_regex: ".*"
hints:
- "Use a map[string]*time.Timer to track active timers by key."
- "Use a mutex to safely access the timers map concurrently."
- "Start a timer with time.AfterFunc(d, fn) to run a callback after duration d."
- "If Start is called again for an existing key, stop and replace the old timer."
- "Stop should remove the timer from the map and prevent the callback from firing."
- "Reset can call timer.Reset(d) to reschedule the same callback."
- "Remember to remove timers from the map after they fire to avoid memory leaks."
- "Write tests to verify Start, Stop, and Reset behavior, including concurrency scenarios."

- slug: 68_rate_limiting
title: Rate Limiting
test_regex: ".*"
difficulty: medium
topics: ["time", "concurrency", "maps"]
hints:
- "Implement a RateLimiter struct that tracks request timestamps per key using a map[string][]time.Time."
- "Use a mutex to safely handle concurrent access to the map."
- "In the Allow method, remove timestamps older than the interval and check if the number of recent requests exceeds the limit."
- "Reset should clear the request history for a key; if the key does not exist, do nothing."
- "Consider edge cases: multiple keys, concurrent access, and requests exactly at the interval boundary."
- "In tests, use time.Sleep with a small buffer above the interval to avoid flakiness."
- "Initialize the timestamps map in NewRateLimiter to prevent nil pointer errors."
- "Remember Go's `time.Parse` can help parse date strings."
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package string_functions

import "strings"

// Contains checks if substr is within s
func Contains(s, substr string) bool {
return strings.Contains(s, substr)
}

// HasPrefix tests whether the string s begins with prefix
func HasPrefix(s, prefix string) bool {
return strings.HasPrefix(s, prefix)
}

// HasSuffix tests whether the string s ends with suffix
func HasSuffix(s, suffix string) bool {
return strings.HasSuffix(s, suffix)
}

// Index returns the index of the first instance of substr in s, or -1 if substr is not present in s
func Index(s, substr string) int {
return strings.Index(s, substr)
}

// ToUpper returns s with all Unicode letters mapped to their upper case
func ToUpper(s string) string {
return strings.ToUpper(s)
}

// ToLower returns s with all Unicode letters mapped to their lower case
func ToLower(s string) string {
return strings.ToLower(s)
}

// TrimSpace returns s with all leading and trailing white space removed
func TrimSpace(s string) string {
return strings.TrimSpace(s)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package string_functions

// TODO: Implement these functions using Go's strings package
// You'll need to import "strings" package when implementing the functions

// Contains checks if substr is within s
func Contains(s, substr string) bool {
// TODO: use strings.Contains
return false // Intentionally wrong to simulate failing exercise
}

// HasPrefix tests whether the string s begins with prefix
func HasPrefix(s, prefix string) bool {
// TODO: use strings.HasPrefix
return false // Intentionally wrong to simulate failing exercise
}

// HasSuffix tests whether the string s ends with suffix
func HasSuffix(s, suffix string) bool {
// TODO: use strings.HasSuffix
return false // Intentionally wrong to simulate failing exercise
}

// Index returns the index of the first instance of substr in s, or -1 if substr is not present in s
func Index(s, substr string) int {
// TODO: use strings.Index
return -1 // Intentionally wrong to simulate failing exercise
}

// ToUpper returns s with all Unicode letters mapped to their upper case
func ToUpper(s string) string {
// TODO: use strings.ToUpper
return "" // Intentionally wrong to simulate failing exercise
}

// ToLower returns s with all Unicode letters mapped to their lower case
func ToLower(s string) string {
// TODO: use strings.ToLower
return "" // Intentionally wrong to simulate failing exercise
}

// TrimSpace returns s with all leading and trailing white space removed
func TrimSpace(s string) string {
// TODO: use strings.TrimSpace
return "" // Intentionally wrong to simulate failing exercise
}
Loading
Loading