Skip to content

Add solution for challenges 1,2,3,5,6,7,22 by AkifhanIlgaz#1249

Open
AkifhanIlgaz wants to merge 20 commits intoRezaSi:mainfrom
AkifhanIlgaz:main
Open

Add solution for challenges 1,2,3,5,6,7,22 by AkifhanIlgaz#1249
AkifhanIlgaz wants to merge 20 commits intoRezaSi:mainfrom
AkifhanIlgaz:main

Conversation

@AkifhanIlgaz
Copy link
Contributor

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 31, 2026

Caution

Review failed

Failed to post review comments

Walkthrough

Adds many new Go solution files across multiple challenge folders, introducing exported functions, types, and small demos (algorithms, data structures, generics, concurrency-safe BankAccount, HTTP server with auth middleware, and assorted utilities).

Changes

Cohort / File(s) Summary
Challenge 1
challenge-1/submissions/AkifhanIlgaz/solution-template.go
Adds Sum(a int, b int) int and main that reads two comma-separated ints ("%d, %d") and prints their sum.
Challenge 2
challenge-2/submissions/AkifhanIlgaz/solution-template.go
Adds ReverseString(s string) string and main that reverses an input string (byte-wise) and prints it.
Challenge 3
challenge-3/submissions/AkifhanIlgaz/solution-template.go
Adds Employee and Manager types with AddEmployee, RemoveEmployee, GetAverageSalary, FindEmployeeByID plus example main.
Challenge 5
challenge-5/submissions/AkifhanIlgaz/solution-template.go
Adds AuthMiddleware(next http.Handler) http.Handler, SetupServer() http.Handler, helloHandler, secureHandler and routing for /hello and token-protected /secure.
Challenge 6
challenge-6/submissions/AkifhanIlgaz/solution-template.go
Adds CountWordFrequency(text string) map[string]int implementing tokenization, normalization, trimming and counting.
Challenge 7
challenge-7/submissions/AkifhanIlgaz/solution-template.go
Adds exported BankAccount (with mutex), NewBankAccount, Deposit, Withdraw, Transfer, MaxTransactionAmount, and custom error types.
Challenge 10
challenge-10/submissions/AkifhanIlgaz/solution-template.go
Adds challenge10 package: Shape interface, Rectangle/Circle/Triangle types with constructors and Area/Perimeter/String methods, plus ShapeCalculator.
Challenge 16
challenge-16/submissions/AkifhanIlgaz/solution-template.go
Adds benchmarking/algorithm variants (SlowSort, OptimizedSort, string-builder variants, ExpensiveCalculation/OptimizedCalculation, HighAllocationSearch/OptimizedSearch, SimulateCPUWork).
Challenge 17
challenge-17/submissions/AkifhanIlgaz/solution-template.go
Adds IsPalindrome(s string) bool with helper cleanString and demo main.
Challenge 18
challenge-18/submissions/AkifhanIlgaz/solution-template.go
Adds CelsiusToFahrenheit, FahrenheitToCelsius, and Round utilities with example usage.
Challenge 19
challenge-19/submissions/AkifhanIlgaz/solution-template.go
Adds slice utilities: FindMax, RemoveDuplicates, ReverseSlice, FilterEven and demo main.
Challenge 21
challenge-21/submissions/AkifhanIlgaz/solution-template.go
Adds BinarySearch, BinarySearchRecursive, and FindInsertPosition with example main.
Challenge 22
challenge-22/submissions/AkifhanIlgaz/solution-template.go
Adds MinCoins(amount int, denominations []int) int and CoinCombination(amount int, denominations []int) map[int]int (greedy coin-change) and example outputs.
Challenge 23
challenge-23/submissions/AkifhanIlgaz/solution-template.go
Adds string-search algorithms: NaivePatternMatch, KMPSearch, RabinKarpSearch and a test harness.
Challenge 27
challenge-27/submissions/AkifhanIlgaz/solution-template.go
Adds generics utilities: ErrEmptyCollection, generic Pair, Stack, Queue, Set, set algebra, and helpers Filter, Map, Reduce, Contains, FindIndex, RemoveDuplicates.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server as SetupServer
    participant Middleware as AuthMiddleware
    participant Handler as SecureHandler

    Client->>Server: GET /secure with X-Auth-Token
    Server->>Middleware: dispatch request
    Middleware->>Middleware: validate X-Auth-Token == "secret"
    alt valid token
        Middleware->>Handler: forward to secure handler
        Handler->>Client: 200 OK ("You are authorized!")
    else missing/invalid
        Middleware->>Client: 401 Unauthorized
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether any description relates to the changeset. Add a description explaining the purpose and scope of these challenge solutions to provide context for reviewers.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically identifies the main change: adding solutions for multiple challenges (1,2,3,5,6,7,22) by a specific contributor, which aligns with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@challenge-2/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 25-34: The function ReverseString currently indexes bytes via
s[i], which corrupts multi-byte UTF-8 characters; change it to operate on runes
by converting the string to a []rune (or range over runes) and then build the
reversed string by iterating the rune slice in reverse and writing each rune to
strings.Builder using WriteRune (keep function name ReverseString and the
builder usage but replace byte writes with rune-safe operations).

In `@challenge-3/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 32-45: The GetAverageSalary method currently loses precision
because it casts e.Salary to int and performs integer division; change the
implementation in Manager.GetAverageSalary to use a float64 accumulator (e.g.,
total float64), add e.Salary directly (don't cast to int), and return total /
float64(employeeCount) so the division is done in floating point and fractional
cents are preserved when computing the average across m.Employees.
- Around line 47-56: The function Manager.FindEmployeeByID returns a pointer to
the loop variable copy (e) instead of the actual slice element; change the loop
to index into m.Employees (e.g., for i := range m.Employees { if
m.Employees[i].ID == id { return &m.Employees[i] } }) so you return a pointer to
the real slice element (Employee) rather than &e, and keep the nil return when
not found.

In `@challenge-6/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 27-35: The loop that tokenizes text using strings.FieldsFunc and
then trims non-alphanumeric runes can produce empty tokens (e.g., when word
becomes "" after strings.TrimFunc), which are being counted into frequencyMap;
update the loop in the function that uses strings.FieldsFunc/strings.TrimFunc to
skip empty tokens by checking the trimmed variable (word) for empty string and
continuing (i.e., if word == "" { continue }) before doing frequencyMap[word]++
so frequencyMap doesn't get an entry for the empty token.

In `@challenge-7/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 137-150: Transfer currently withdraws from the source via
BankAccount.Withdraw and then calls target.Deposit, which can fail and leave
funds missing; make Transfer atomic by either validating both sides before
mutating (e.g., check target.MaxTransactionAmount or a target.CanAccept(amount)
helper) or by performing the rollback path: after Withdraw succeeds, if
target.Deposit fails call a.Deposit(amount) to refund the source and return the
original deposit error (handle and surface any refund error as a wrapped error);
ensure you also acquire whatever account-level locks are used by
Withdraw/Deposit around the whole operation to avoid races.
🧹 Nitpick comments (4)
challenge-5/submissions/AkifhanIlgaz/solution-template.go (1)

14-26: Clean middleware implementation.

The authentication logic is correct. Consider removing the leftover template comment on line 24.

,

🧹 Remove leftover comment
 		next.ServeHTTP(w, r)
-		//  4) Otherwise pass to next handler
 	})
challenge-22/submissions/AkifhanIlgaz/solution-template.go (2)

31-51: Greedy algorithm assumes sorted denominations.

The implementation iterates from the last element assuming denominations are sorted ascending. If an unsorted slice is passed (e.g., []int{25, 1, 10}), the result will be incorrect. Consider documenting this precondition or sorting the slice at the start.

📝 Optional: Add defensive sort
+import "sort"
+
 func MinCoins(amount int, denominations []int) int {
 	if amount == 0 {
 		return 0
 	}
 
+	// Ensure denominations are sorted ascending
+	sorted := make([]int, len(denominations))
+	copy(sorted, denominations)
+	sort.Ints(sorted)
+
 	numOfCoins := 0
-	for i := len(denominations) - 1; i >= 0; i-- {
-		denomination := denominations[i]
+	for i := len(sorted) - 1; i >= 0; i-- {
+		denomination := sorted[i]

53-73: Same sorted-denominations assumption applies here.

CoinCombination shares the same assumption as MinCoins. If you add defensive sorting to one, apply it consistently to both.

challenge-7/submissions/AkifhanIlgaz/solution-template.go (1)

25-63: Error types return empty strings.

All Error() methods return "". While the comments indicate these need implementation, empty error messages make debugging difficult. Consider adding meaningful messages with relevant context.

💡 Example implementation for error messages
type InsufficientFundsError struct {
	Available float64
	Requested float64
}

func (e *InsufficientFundsError) Error() string {
	return fmt.Sprintf("insufficient funds: available %.2f, requested %.2f", e.Available, e.Requested)
}

Comment on lines 25 to 34
func ReverseString(s string) string {
var sb strings.Builder

for i := len(s) - 1; i >= 0; i-- {
ch := s[i]
sb.WriteByte(ch)
}

return sb.String()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Byte-wise reversal corrupts multi-byte UTF-8 characters.

Iterating over s[i] operates on bytes, not runes. Multi-byte characters (e.g., "héllo", "日本語", emojis) will be garbled. If the challenge only requires ASCII handling, this is fine; otherwise, iterate over runes.

🔧 Proposed fix for Unicode support
 func ReverseString(s string) string {
-	var sb strings.Builder
-
-	for i := len(s) - 1; i >= 0; i-- {
-		ch := s[i]
-		sb.WriteByte(ch)
-	}
-
-	return sb.String()
+	runes := []rune(s)
+	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
+		runes[i], runes[j] = runes[j], runes[i]
+	}
+	return string(runes)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func ReverseString(s string) string {
var sb strings.Builder
for i := len(s) - 1; i >= 0; i-- {
ch := s[i]
sb.WriteByte(ch)
}
return sb.String()
}
func ReverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
🤖 Prompt for AI Agents
In `@challenge-2/submissions/AkifhanIlgaz/solution-template.go` around lines 25 -
34, The function ReverseString currently indexes bytes via s[i], which corrupts
multi-byte UTF-8 characters; change it to operate on runes by converting the
string to a []rune (or range over runes) and then build the reversed string by
iterating the rune slice in reverse and writing each rune to strings.Builder
using WriteRune (keep function name ReverseString and the builder usage but
replace byte writes with rune-safe operations).

Comment on lines 47 to 56
// FindEmployeeByID finds and returns an employee by their ID.
func (m *Manager) FindEmployeeByID(id int) *Employee {
for _, e := range m.Employees {
if e.ID == id {
return &e
}
}

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Returns pointer to loop variable copy, not to slice element.

e is a copy of each Employee in the range loop. Returning &e gives a pointer to that local copy, which won't reflect or modify the actual slice element. The caller gets a valid but disconnected object.

🐛 Proposed fix to return pointer to actual slice element
 func (m *Manager) FindEmployeeByID(id int) *Employee {
-	for _, e := range m.Employees {
+	for i := range m.Employees {
+		e := &m.Employees[i]
 		if e.ID == id {
-			return &e
+			return e
 		}
 	}
 
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// FindEmployeeByID finds and returns an employee by their ID.
func (m *Manager) FindEmployeeByID(id int) *Employee {
for _, e := range m.Employees {
if e.ID == id {
return &e
}
}
return nil
}
// FindEmployeeByID finds and returns an employee by their ID.
func (m *Manager) FindEmployeeByID(id int) *Employee {
for i := range m.Employees {
e := &m.Employees[i]
if e.ID == id {
return e
}
}
return nil
}
🤖 Prompt for AI Agents
In `@challenge-3/submissions/AkifhanIlgaz/solution-template.go` around lines 47 -
56, The function Manager.FindEmployeeByID returns a pointer to the loop variable
copy (e) instead of the actual slice element; change the loop to index into
m.Employees (e.g., for i := range m.Employees { if m.Employees[i].ID == id {
return &m.Employees[i] } }) so you return a pointer to the real slice element
(Employee) rather than &e, and keep the nil return when not found.

Comment on lines 137 to 150
func (a *BankAccount) Transfer(amount float64, target *BankAccount) error {
err := a.Withdraw(amount)
if err != nil {
return err
}

err = target.Deposit(amount)
if err != nil {
return err
}

// Implement transfer functionality with proper error handling
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Transfer is not atomic—failed deposit loses funds.

If Withdraw succeeds but Deposit fails (e.g., amount exceeds MaxTransactionAmount on target), the money is deducted from the source but never credited to the target. This results in lost funds.

🐛 Proposed fix to rollback on deposit failure
 func (a *BankAccount) Transfer(amount float64, target *BankAccount) error {
 	err := a.Withdraw(amount)
 	if err != nil {
 		return err
 	}
 
 	err = target.Deposit(amount)
 	if err != nil {
+		// Rollback: re-deposit to source account
+		a.mu.Lock()
+		a.Balance += amount
+		a.mu.Unlock()
 		return err
 	}
-	
-	// Implement transfer functionality with proper error handling
+
 	return nil
 }

Alternatively, validate both operations before executing, or use a two-phase approach with held locks on both accounts.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (a *BankAccount) Transfer(amount float64, target *BankAccount) error {
err := a.Withdraw(amount)
if err != nil {
return err
}
err = target.Deposit(amount)
if err != nil {
return err
}
// Implement transfer functionality with proper error handling
return nil
}
func (a *BankAccount) Transfer(amount float64, target *BankAccount) error {
err := a.Withdraw(amount)
if err != nil {
return err
}
err = target.Deposit(amount)
if err != nil {
// Rollback: re-deposit to source account
a.mu.Lock()
a.Balance += amount
a.mu.Unlock()
return err
}
return nil
}
🤖 Prompt for AI Agents
In `@challenge-7/submissions/AkifhanIlgaz/solution-template.go` around lines 137 -
150, Transfer currently withdraws from the source via BankAccount.Withdraw and
then calls target.Deposit, which can fail and leave funds missing; make Transfer
atomic by either validating both sides before mutating (e.g., check
target.MaxTransactionAmount or a target.CanAccept(amount) helper) or by
performing the rollback path: after Withdraw succeeds, if target.Deposit fails
call a.Deposit(amount) to refund the source and return the original deposit
error (handle and surface any refund error as a wrapped error); ensure you also
acquire whatever account-level locks are used by Withdraw/Deposit around the
whole operation to avoid races.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@challenge-10/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 117-157: Add nil guards to prevent panics from nil Shape interface
values: in PrintProperties(s Shape) return early if s == nil; in
TotalArea(shapes []Shape) skip any nil shapes before calling Area(); in
LargestShape(shapes []Shape) initialize max as nil and track a maxArea (e.g.,
-Inf) while skipping nil entries so you never call Area() on nil and return nil
if no non-nil shapes found; in SortByArea(shapes []Shape, ascending bool) update
the sort.Slice comparator to handle nils deterministically (e.g., treat nil as
greater so nils end up at the end) before calling Area() on non-nil elements.
- Around line 93-97: The Area method (Triangle.Area) can return NaN for
nearly-degenerate triangles due to tiny negative rounding errors in Heron's
radicand; compute s as you already do, compute the radicand (s * (s - t.SideA) *
(s - t.SideB) * (s - t.SideC)), then if the radicand is negative but very close
to zero clamp it to 0 before calling math.Sqrt; update Triangle.Area to use this
clamped radicand to ensure a valid non-NaN result.

Comment on lines +93 to +97
// Area calculates the area of the triangle using Heron's formula
func (t *Triangle) Area() float64 {
s := (t.SideA + t.SideB + t.SideC) / 2
return math.Sqrt(s * (s - t.SideA) * (s - t.SideB) * (s - t.SideC))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n challenge-10/submissions/AkifhanIlgaz/solution-template.go | head -120

Repository: RezaSi/go-interview-practice

Length of output: 4050


🏁 Script executed:

find challenge-10 -name "*test*" -o -name "*_test.go" | head -20

Repository: RezaSi/go-interview-practice

Length of output: 136


🏁 Script executed:

cat -n challenge-10/solution-template_test.go

Repository: RezaSi/go-interview-practice

Length of output: 15854


Guard Heron's formula against tiny negative values to prevent NaN.

Floating-point rounding errors in nearly-degenerate triangles can cause the radicand to become slightly negative even when mathematically it should be non-negative, causing math.Sqrt to return NaN. Although the triangle validation enforces strict inequality, floating-point precision loss during intermediate calculations (s, s - SideA, etc.) can introduce negative values in edge cases. Clamp negative radicands to 0 as a defensive measure.

🛠️ Suggested fix
 func (t *Triangle) Area() float64 {
 	s := (t.SideA + t.SideB + t.SideC) / 2
-	return math.Sqrt(s * (s - t.SideA) * (s - t.SideB) * (s - t.SideC))
+	area := s * (s - t.SideA) * (s - t.SideB) * (s - t.SideC)
+	if area < 0 {
+		area = 0
+	}
+	return math.Sqrt(area)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Area calculates the area of the triangle using Heron's formula
func (t *Triangle) Area() float64 {
s := (t.SideA + t.SideB + t.SideC) / 2
return math.Sqrt(s * (s - t.SideA) * (s - t.SideB) * (s - t.SideC))
}
// Area calculates the area of the triangle using Heron's formula
func (t *Triangle) Area() float64 {
s := (t.SideA + t.SideB + t.SideC) / 2
area := s * (s - t.SideA) * (s - t.SideB) * (s - t.SideC)
if area < 0 {
area = 0
}
return math.Sqrt(area)
}
🤖 Prompt for AI Agents
In `@challenge-10/submissions/AkifhanIlgaz/solution-template.go` around lines 93 -
97, The Area method (Triangle.Area) can return NaN for nearly-degenerate
triangles due to tiny negative rounding errors in Heron's radicand; compute s as
you already do, compute the radicand (s * (s - t.SideA) * (s - t.SideB) * (s -
t.SideC)), then if the radicand is negative but very close to zero clamp it to 0
before calling math.Sqrt; update Triangle.Area to use this clamped radicand to
ensure a valid non-NaN result.

Comment on lines +117 to +157
// PrintProperties prints the properties of a shape
func (sc *ShapeCalculator) PrintProperties(s Shape) {
fmt.Println(s.String())
}

// TotalArea calculates the sum of areas of all shapes
func (sc *ShapeCalculator) TotalArea(shapes []Shape) float64 {
sum := 0.0
for _, shape := range shapes {
sum += shape.Area()
}

return sum
}

// LargestShape finds the shape with the largest area
func (sc *ShapeCalculator) LargestShape(shapes []Shape) Shape {
if len(shapes) == 0 {
return nil
}
max := shapes[0]
for _, shape := range shapes {
if shape.Area() > max.Area() {
max = shape
}
}
return max
}

// SortByArea sorts shapes by area in ascending or descending order
func (sc *ShapeCalculator) SortByArea(shapes []Shape, ascending bool) []Shape {
if len(shapes) == 0 {
return shapes
}

sort.Slice(shapes, func(i, j int) bool {
if ascending {
return shapes[i].Area() < shapes[j].Area()
}
return shapes[i].Area() > shapes[j].Area()
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "solution-template.go" | head -20

Repository: RezaSi/go-interview-practice

Length of output: 1213


🏁 Script executed:

ls -la challenge-10/submissions/AkifhanIlgaz/ 2>/dev/null || echo "Path not found"

Repository: RezaSi/go-interview-practice

Length of output: 255


🏁 Script executed:

git ls-files | grep -E "(challenge-10|solution)" | head -20

Repository: RezaSi/go-interview-practice

Length of output: 1154


🏁 Script executed:

cat -n challenge-10/submissions/AkifhanIlgaz/solution-template.go

Repository: RezaSi/go-interview-practice

Length of output: 5170


Add nil guards to prevent panics from nil Shape values.

Interface values in Go can be nil, and calling Area() or String() on a nil Shape will panic. The constructor functions validate inputs normally, but defensive checks in PrintProperties, TotalArea, LargestShape, and SortByArea will make these methods robust if nil values enter the slices:

  • PrintProperties: Return early if s == nil
  • TotalArea: Skip nil shapes with a nil check before calling Area()
  • LargestShape: Initialize max to nil, skip nil shapes, track the max area separately to avoid redundant Area() calls
  • SortByArea: Add nil comparisons to the sort function to place nil values consistently at one end
🤖 Prompt for AI Agents
In `@challenge-10/submissions/AkifhanIlgaz/solution-template.go` around lines 117
- 157, Add nil guards to prevent panics from nil Shape interface values: in
PrintProperties(s Shape) return early if s == nil; in TotalArea(shapes []Shape)
skip any nil shapes before calling Area(); in LargestShape(shapes []Shape)
initialize max as nil and track a maxArea (e.g., -Inf) while skipping nil
entries so you never call Area() on nil and return nil if no non-nil shapes
found; in SortByArea(shapes []Shape, ascending bool) update the sort.Slice
comparator to handle nils deterministically (e.g., treat nil as greater so nils
end up at the end) before calling Area() on non-nil elements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@challenge-17/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 29-32: The palindrome check indexes bytes (s[i]) which breaks for
multi-byte UTF‑8 characters; convert the cleaned string to a rune slice (e.g.,
runes := []rune(s)) and iterate using runes[len(runes)/2] and compare runes[i]
vs runes[len(runes)-i-1] instead of s[i] and s[len(s)-i-1] so non-ASCII
characters are handled correctly.
- Line 13: The use of fmt.Scanln(&input) only reads until the first whitespace
and fails on multi-word lines; replace it with a line-oriented reader (e.g., use
bufio.NewReader(os.Stdin).ReadString('\n') or a bufio.Scanner configured to
ScanLines) to read the full input line into the same variable (input) before
trimming newline/whitespace as needed; update any subsequent logic that expects
a full-line string (functions referencing input) accordingly.

// Get input from the user
var input string
fmt.Print("Enter a string to check if it's a palindrome: ")
fmt.Scanln(&input)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

fmt.Scanln stops at whitespace, preventing multi-word input.

fmt.Scanln reads only until the first space, so phrases like "A man a plan a canal Panama" won't be captured correctly. Consider using bufio.Scanner to read the full line.

Proposed fix
 import (
+	"bufio"
 	"fmt"
+	"os"
 	"strings"
 	"unicode"
 )

 func main() {
 	// Get input from the user
-	var input string
 	fmt.Print("Enter a string to check if it's a palindrome: ")
-	fmt.Scanln(&input)
+	scanner := bufio.NewScanner(os.Stdin)
+	scanner.Scan()
+	input := scanner.Text()

 	// Call the IsPalindrome function and print the result
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt.Scanln(&input)
import (
"bufio"
"fmt"
"os"
"strings"
"unicode"
)
func main() {
// Get input from the user
fmt.Print("Enter a string to check if it's a palindrome: ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
input := scanner.Text()
// Call the IsPalindrome function and print the result
if IsPalindrome(input) {
fmt.Println("The string is a palindrome!")
} else {
fmt.Println("The string is not a palindrome.")
}
}
🤖 Prompt for AI Agents
In `@challenge-17/submissions/AkifhanIlgaz/solution-template.go` at line 13, The
use of fmt.Scanln(&input) only reads until the first whitespace and fails on
multi-word lines; replace it with a line-oriented reader (e.g., use
bufio.NewReader(os.Stdin).ReadString('\n') or a bufio.Scanner configured to
ScanLines) to read the full input line into the same variable (input) before
trimming newline/whitespace as needed; update any subsequent logic that expects
a full-line string (functions referencing input) accordingly.

Comment on lines +29 to +32
for i := 0; i < len(s)/2; i++ {
if s[i] != s[len(s)-i-1] {
return false
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Byte indexing breaks palindrome check for non-ASCII characters.

s[i] accesses bytes, not runes. Since cleanString preserves non-ASCII letters (e.g., 'ä', 'é'), multi-byte UTF-8 characters will cause incorrect comparisons. For example, "Ää" would incorrectly return false.

Proposed fix using rune slice
 func IsPalindrome(s string) bool {
 	s = cleanString(s)
+	runes := []rune(s)

-	for i := 0; i < len(s)/2; i++ {
-		if s[i] != s[len(s)-i-1] {
+	for i := 0; i < len(runes)/2; i++ {
+		if runes[i] != runes[len(runes)-i-1] {
 			return false
 		}
 	}
 	return true
 }
🤖 Prompt for AI Agents
In `@challenge-17/submissions/AkifhanIlgaz/solution-template.go` around lines 29 -
32, The palindrome check indexes bytes (s[i]) which breaks for multi-byte UTF‑8
characters; convert the cleaned string to a rune slice (e.g., runes :=
[]rune(s)) and iterate using runes[len(runes)/2] and compare runes[i] vs
runes[len(runes)-i-1] instead of s[i] and s[len(s)-i-1] so non-ASCII characters
are handled correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@challenge-27/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 111-115: Update the error returned by Queue[T].Dequeue (and the
similar error in lines 124-128) so it no longer says "stack is empty" — return a
consistent sentinel error used across collections instead; locate the Dequeue
method on type Queue (func (q *Queue[T]) Dequeue()) and replace the literal
errors.New("stack is empty") with the shared sentinel error variable (the
package-level error used by other collections) and adjust the other empty-queue
check(s) referenced to use the same sentinel for consistency.
🧹 Nitpick comments (2)
challenge-27/submissions/AkifhanIlgaz/solution-template.go (2)

57-75: Use ErrEmptyCollection in stack operations for consistent error handling.

This enables callers to compare errors reliably without string matching.

♻️ Suggested refactor
 	if len(s.items) == 0 {
-		return zero, errors.New("stack is empty")
+		return zero, ErrEmptyCollection
 	}
@@
 	if len(s.items) == 0 {
-		return zero, errors.New("stack is empty")
+		return zero, ErrEmptyCollection
 	}

63-65: Clear removed elements to avoid holding references.

When T contains pointers, the backing array can keep removed elements live. Clearing slots before slicing helps GC.

♻️ Suggested refactor
-	popped := s.items[len(s.items)-1]
-	s.items = s.items[:len(s.items)-1]
+	idx := len(s.items) - 1
+	popped := s.items[idx]
+	s.items[idx] = zero
+	s.items = s.items[:idx]
@@
-	popped := q.items[0]
-	q.items = q.items[1:]
+	popped := q.items[0]
+	q.items[0] = zero
+	q.items = q.items[1:]

Also applies to: 117-118

Comment on lines +111 to +115
func (q *Queue[T]) Dequeue() (T, error) {
var zero T
if len(q.items) == 0 {
return zero, errors.New("stack is empty")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix empty-queue error message (currently says “stack”).

This is user-visible and misleading. Consider returning the shared sentinel error to keep behavior consistent across collections.

🔧 Suggested fix
 	if len(q.items) == 0 {
-		return zero, errors.New("stack is empty")
+		return zero, ErrEmptyCollection
 	}
@@
 	if len(q.items) == 0 {
-		return zero, errors.New("stack is empty")
+		return zero, ErrEmptyCollection
 	}

Also applies to: 124-128

🤖 Prompt for AI Agents
In `@challenge-27/submissions/AkifhanIlgaz/solution-template.go` around lines 111
- 115, Update the error returned by Queue[T].Dequeue (and the similar error in
lines 124-128) so it no longer says "stack is empty" — return a consistent
sentinel error used across collections instead; locate the Dequeue method on
type Queue (func (q *Queue[T]) Dequeue()) and replace the literal
errors.New("stack is empty") with the shared sentinel error variable (the
package-level error used by other collections) and adjust the other empty-queue
check(s) referenced to use the same sentinel for consistency.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@challenge-16/submissions/AkifhanIlgaz/solution-template.go`:
- Around line 67-72: OptimizedSort currently sorts the input slice in-place
(using slices.Sort) which mutates the caller's data whereas SlowSort makes and
sorts a copy; update OptimizedSort to first allocate/copy the input (e.g.,
create a new slice and copy elements from the incoming data), then call
slices.Sort on that copy and return the copy so behavior matches SlowSort and
the original slice remains unchanged.
- Around line 274-295: OptimizedSearch currently overcounts empty substrings and
mis-handles multi-byte UTF-8: add an explicit guard in OptimizedSearch for
substr=="" that returns exactly len(text) entries (loop i from 0 to i <
len(text) and set res[i] = "") to match HighAllocationSearch, and make matching
rune-aware by changing isMatch to operate on rune slices (or convert both text
and substr to []rune at the start of OptimizedSearch and pass those to isMatch)
so comparisons use unicode.ToLower on runes instead of casting individual bytes
to rune; update the isMatch signature and its callers (isMatch -> func
isMatch(textRunes []rune, substrRunes []rune, begin int) bool) accordingly.
- Around line 125-130: OptimizedStringBuilder must guard against negative
repeatCount to match InefficientStringBuilder behavior: before calling
strings.Repeat(strings.Join(parts, ""), repeatCount) check if repeatCount <= 0
and return "" for negative (and zero) counts to avoid the panic from
strings.Repeat; update the function OptimizedStringBuilder to perform that early
return so results and error semantics match the original implementation.

Comment on lines +67 to +72
// OptimizedSort is your optimized version of SlowSort
// It should produce identical results but perform better
func OptimizedSort(data []int) []int {
slices.Sort(data)
return data
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the SlowSort implementation in the same file
cat -n challenge-16/submissions/AkifhanIlgaz/solution-template.go

Repository: RezaSi/go-interview-practice

Length of output: 13346


🏁 Script executed:

# Also check if there are test files for this challenge
find challenge-16 -type f -name "*test*" -o -name "*_test.go" | head -20

Repository: RezaSi/go-interview-practice

Length of output: 136


🏁 Script executed:

# Look for the SlowSort function definition
rg "func SlowSort" challenge-16/submissions/AkifhanIlgaz/ -A 10

Repository: RezaSi/go-interview-practice

Length of output: 1052


🏁 Script executed:

cat -n challenge-16/solution-template_test.go

Repository: RezaSi/go-interview-practice

Length of output: 12270


OptimizedSort mutates the input slice, but SlowSort does not.

SlowSort explicitly copies the input before sorting (line 33-34), while OptimizedSort sorts in-place. This breaks semantic equivalence—callers expecting the input to remain unchanged will encounter unexpected mutations. The current test passes only because it doesn't verify mutation behavior.

🔧 Suggested fix
func OptimizedSort(data []int) []int {
-	slices.Sort(data)
-	return data
+	result := make([]int, len(data))
+	copy(result, data)
+	slices.Sort(result)
+	return result
}
🤖 Prompt for AI Agents
In `@challenge-16/submissions/AkifhanIlgaz/solution-template.go` around lines 67 -
72, OptimizedSort currently sorts the input slice in-place (using slices.Sort)
which mutates the caller's data whereas SlowSort makes and sorts a copy; update
OptimizedSort to first allocate/copy the input (e.g., create a new slice and
copy elements from the incoming data), then call slices.Sort on that copy and
return the copy so behavior matches SlowSort and the original slice remains
unchanged.

Comment on lines +125 to +130
// OptimizedStringBuilder is your optimized version of InefficientStringBuilder
// It should produce identical results but perform better
func OptimizedStringBuilder(parts []string, repeatCount int) string {
// Could be better if using a loop with strings.Builder, but this solution is shorter, and performs ok.
return strings.Repeat(strings.Join(parts, ""), repeatCount)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd challenge-16/submissions/AkifhanIlgaz && cat -n solution-template.go

Repository: RezaSi/go-interview-practice

Length of output: 13346


🏁 Script executed:

cat > /tmp/test_repeat.go << 'EOF'
package main

import (
	"fmt"
	"strings"
)

func main() {
	// Test strings.Repeat with zero
	result0 := strings.Repeat("abc", 0)
	fmt.Printf("strings.Repeat(\"abc\", 0) = %q\n", result0)

	// Test strings.Repeat with positive
	result1 := strings.Repeat("abc", 1)
	fmt.Printf("strings.Repeat(\"abc\", 1) = %q\n", result1)

	// Test strings.Repeat with negative - this should panic
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("strings.Repeat(\"abc\", -1) panics with: %v\n", r)
		}
	}()
	result_neg := strings.Repeat("abc", -1)
	fmt.Printf("strings.Repeat(\"abc\", -1) = %q\n", result_neg)
}
EOF
cd /tmp && go run test_repeat.go

Repository: RezaSi/go-interview-practice

Length of output: 204


Guard negative repeatCount to keep parity with InefficientStringBuilder.

strings.Repeat panics for negative counts, while the inefficient version returns "" (its loop condition prevents execution). Add a guard to handle negative inputs.

🔧 Suggested fix
func OptimizedStringBuilder(parts []string, repeatCount int) string {
	// Could be better if using a loop with strings.Builder, but this solution is shorter, and performs ok.
+	if repeatCount < 0 {
+		return ""
+	}
	return strings.Repeat(strings.Join(parts, ""), repeatCount)
}
🤖 Prompt for AI Agents
In `@challenge-16/submissions/AkifhanIlgaz/solution-template.go` around lines 125
- 130, OptimizedStringBuilder must guard against negative repeatCount to match
InefficientStringBuilder behavior: before calling
strings.Repeat(strings.Join(parts, ""), repeatCount) check if repeatCount <= 0
and return "" for negative (and zero) counts to avoid the panic from
strings.Repeat; update the function OptimizedStringBuilder to perform that early
return so results and error semantics match the original implementation.

Comment on lines +274 to +295
// OptimizedSearch is your optimized version of HighAllocationSearch
// It should produce identical results but perform better with fewer allocations
func OptimizedSearch(text, substr string) map[int]string {
if len(text) == 0 {
return map[int]string{}
}
res := map[int]string{}
for i := 0; i <= len(text)-len(substr); i++ {
if isMatch(text, substr, i) {
res[i] = text[i : i+len(substr)]
}
}
return res
}

func isMatch(text, substr string, begin int) bool {
for i := 0; i < len(substr); i++ {
if unicode.ToLower(rune(text[begin+i])) != unicode.ToLower(rune(substr[i])) {
return false
}
}
return true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n challenge-16/submissions/AkifhanIlgaz/solution-template.go | head -300

Repository: RezaSi/go-interview-practice

Length of output: 13155


Match HighAllocationSearch for empty substrings and non‑ASCII input.

OptimizedSearch returns len(text)+1 entries for empty substrings (loop condition is i <= len(text)-len(substr), which becomes i <= len(text) when substr is empty), whereas HighAllocationSearch returns len(text) entries. Additionally, the byte-wise isMatch function breaks on non-ASCII input—it converts individual bytes to runes rather than handling multi-byte UTF-8 sequences correctly like strings.ToLower() does. Add guards to match HighAllocationSearch behavior or document ASCII-only support.

🔧 Suggested fix (align behavior + ASCII fast-path)
func OptimizedSearch(text, substr string) map[int]string {
-	if len(text) == 0 {
-		return map[int]string{}
-	}
-	res := map[int]string{}
+	if len(substr) == 0 {
+		res := make(map[int]string, len(text))
+		for i := 0; i < len(text); i++ {
+			res[i] = ""
+		}
+		return res
+	}
+	if len(text) == 0 {
+		return map[int]string{}
+	}
+	if strings.IndexFunc(text, func(r rune) bool { return r > unicode.MaxASCII }) != -1 ||
+		strings.IndexFunc(substr, func(r rune) bool { return r > unicode.MaxASCII }) != -1 {
+		return HighAllocationSearch(text, substr)
+	}
+	res := map[int]string{}
 	for i := 0; i <= len(text)-len(substr); i++ {
 		if isMatch(text, substr, i) {
 			res[i] = text[i : i+len(substr)]
 		}
 	}
 	return res
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// OptimizedSearch is your optimized version of HighAllocationSearch
// It should produce identical results but perform better with fewer allocations
func OptimizedSearch(text, substr string) map[int]string {
if len(text) == 0 {
return map[int]string{}
}
res := map[int]string{}
for i := 0; i <= len(text)-len(substr); i++ {
if isMatch(text, substr, i) {
res[i] = text[i : i+len(substr)]
}
}
return res
}
func isMatch(text, substr string, begin int) bool {
for i := 0; i < len(substr); i++ {
if unicode.ToLower(rune(text[begin+i])) != unicode.ToLower(rune(substr[i])) {
return false
}
}
return true
// OptimizedSearch is your optimized version of HighAllocationSearch
// It should produce identical results but perform better with fewer allocations
func OptimizedSearch(text, substr string) map[int]string {
if len(substr) == 0 {
res := make(map[int]string, len(text))
for i := 0; i < len(text); i++ {
res[i] = ""
}
return res
}
if len(text) == 0 {
return map[int]string{}
}
if strings.IndexFunc(text, func(r rune) bool { return r > unicode.MaxASCII }) != -1 ||
strings.IndexFunc(substr, func(r rune) bool { return r > unicode.MaxASCII }) != -1 {
return HighAllocationSearch(text, substr)
}
res := map[int]string{}
for i := 0; i <= len(text)-len(substr); i++ {
if isMatch(text, substr, i) {
res[i] = text[i : i+len(substr)]
}
}
return res
}
func isMatch(text, substr string, begin int) bool {
for i := 0; i < len(substr); i++ {
if unicode.ToLower(rune(text[begin+i])) != unicode.ToLower(rune(substr[i])) {
return false
}
}
return true
}
🤖 Prompt for AI Agents
In `@challenge-16/submissions/AkifhanIlgaz/solution-template.go` around lines 274
- 295, OptimizedSearch currently overcounts empty substrings and mis-handles
multi-byte UTF-8: add an explicit guard in OptimizedSearch for substr=="" that
returns exactly len(text) entries (loop i from 0 to i < len(text) and set res[i]
= "") to match HighAllocationSearch, and make matching rune-aware by changing
isMatch to operate on rune slices (or convert both text and substr to []rune at
the start of OptimizedSearch and pass those to isMatch) so comparisons use
unicode.ToLower on runes instead of casting individual bytes to rune; update the
isMatch signature and its callers (isMatch -> func isMatch(textRunes []rune,
substrRunes []rune, begin int) bool) accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant