-
-
Notifications
You must be signed in to change notification settings - Fork 687
Add solution for Challenge 1 #646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds new Go solution files across multiple challenges: Challenge 1 adds Sum(a, b) and a main that reads two comma-separated ints; Challenge 2 adds ReverseString(s) and a main that reads and prints a reversed line; Challenge 3 adds Employee and Manager types with management methods (in both a submission and a top-level file); Challenge 22 adds greedy MinCoins and CoinCombination for coin-change. Changes
Sequence Diagram(s)sequenceDiagram
participant Main1 as Challenge1 Main
participant Stdin1 as Standard Input
participant Sum as Sum(a,b)
participant Stdout1 as Standard Output
Main1->>Stdin1: Read two ints with fmt.Scanf("%d, %d")
alt Read Success
Stdin1-->>Main1: a, b
Main1->>Sum: Call Sum(a,b)
Sum-->>Main1: Return a + b
Main1->>Stdout1: Print result
else Read Error
Stdin1-->>Main1: Error
Main1->>Stdout1: Print error message
end
sequenceDiagram
participant Main2 as Challenge2 Main
participant Stdin2 as Standard Input
participant Rev as ReverseString(s)
participant Stdout2 as Standard Output
Main2->>Stdin2: Read line from stdin
alt Input Present
Stdin2-->>Main2: line
Main2->>Rev: Call ReverseString(line)
Rev-->>Main2: Return reversed string
Main2->>Stdout2: Print reversed string
else No Input
Stdin2-->>Main2: EOF/none
Main2->>Stdout2: (no output)
end
sequenceDiagram
participant Main3 as Challenge3 Main
participant Manager as Manager
participant EmployeeDB as Employees slice
participant Stdout3 as Standard Output
Main3->>Manager: Instantiate Manager
Main3->>Manager: AddEmployee(e1)
Manager->>EmployeeDB: append e1
Main3->>Manager: AddEmployee(e2)
Manager->>EmployeeDB: append e2
Main3->>Manager: RemoveEmployee(id)
Manager->>EmployeeDB: filter out id
Main3->>Manager: GetAverageSalary()
Manager->>EmployeeDB: iterate salaries
Manager-->>Main3: average (float64)
Main3->>Manager: FindEmployeeByID(id)
Manager->>EmployeeDB: search by ID
alt Found
Manager-->>Main3: *Employee
else Not Found
Manager-->>Main3: nil
end
Main3->>Stdout3: Print results
sequenceDiagram
participant MainC as Challenge22 Main
participant Algo as Greedy Algorithm
participant StdoutC as Standard Output
MainC->>Algo: For each amount call MinCoins(amount, denoms)
Algo-->>MainC: Return coin count (greedy)
MainC->>Algo: Call CoinCombination(amount, denoms)
Algo-->>MainC: Return map[denom]count
MainC->>StdoutC: Print amount, min coins, and coin mix
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Pre-merge checks❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
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. Comment |
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
challenge-1/submissions/Gorbushka3000/solution-template.go(1 hunks)
🔇 Additional comments (1)
challenge-1/submissions/Gorbushka3000/solution-template.go (1)
7-19: LGTM!The main function correctly reads two comma-separated integers from stdin, handles input errors appropriately, and prints the sum result.
| // Sum returns the sum of a and b. | ||
| func Sum(a int, b int) int { | ||
| // TODO: Implement the function | ||
| return a+b | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the TODO comment or the implementation.
The TODO comment indicates the function needs to be implemented, but the implementation already exists. This creates confusion about whether the function is complete.
Additionally, consider using the more idiomatic Go function signature style:
// Sum returns the sum of a and b.
-func Sum(a int, b int) int {
- // TODO: Implement the function
- return a+b
+func Sum(a, b int) int {
+ return a + b
}🤖 Prompt for AI Agents
In challenge-1/submissions/Gorbushka3000/solution-template.go around lines 21 to
25, remove the outdated TODO comment because the function is already
implemented, and optionally change the function signature to the idiomatic Go
form by combining parameter types (e.g., func Sum(a, b int) int) to improve
readability; keep the existing return implementation intact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
challenge-2/submissions/Gorbushka3000/solution-template.go (2)
9-21: Consider adding error handling for scanner errors.The code doesn't check
scanner.Err()afterscanner.Scan()returns false. While this works for simple cases, scanner errors (if any occur) will be silently ignored.Apply this diff to add error handling:
func main() { // Read input from standard input scanner := bufio.NewScanner(os.Stdin) if scanner.Scan() { input := scanner.Text() // Call the ReverseString function output := ReverseString(input) // Print the result fmt.Println(output) } + if err := scanner.Err(); err != nil { + fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err) + os.Exit(1) + } }
23-29: Consider usingstrings.Builderor[]runefor better performance.The current implementation correctly handles Unicode characters by iterating over runes. However, string concatenation inside the loop is O(n²) because each
string(c) + resultallocates a new string and copies all existing content.Solution 1 (recommended): Use
[]runefor O(n) complexity:// ReverseString returns the reversed string of s. -func ReverseString(s string) (result string) { - for _, c := range s{ - result = string(c) + result - } - return result +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) }Solution 2 (alternative): Use
strings.Builder:Add import at the top:
import ( "bufio" "fmt" "os" + "strings" )Then update the function:
// ReverseString returns the reversed string of s. -func ReverseString(s string) (result string) { - for _, c := range s{ - result = string(c) + result - } - return result +func ReverseString(s string) string { + runes := []rune(s) + var builder strings.Builder + builder.Grow(len(s)) + for i := len(runes) - 1; i >= 0; i-- { + builder.WriteRune(runes[i]) + } + return builder.String() }
There was a problem hiding this 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
🧹 Nitpick comments (2)
challenge-3/submissions/Gorbushka3000/solution-template.go (2)
34-44: LGTM! Correct average calculation.The method correctly handles the empty employee list and computes the average salary.
For more idiomatic Go, consider using range-based iteration:
func (m *Manager) GetAverageSalary() float64 { if len(m.Employees) == 0 { return 0 } var aveSal float64 - for i := 0; i < len(m.Employees); i++ { - aveSal += m.Employees[i].Salary + for _, emp := range m.Employees { + aveSal += emp.Salary } return aveSal / float64(len(m.Employees)) }
46-54: Verify pointer validity after slice modifications.The method correctly finds and returns a pointer to the employee. Note that if the Manager's Employees slice is later modified (e.g., by append causing reallocation), the returned pointer could become invalid. For this learning exercise, the current usage in main is safe.
For more idiomatic Go, consider using range-based iteration:
func (m *Manager) FindEmployeeByID(id int) *Employee { - for i := 0; i < len(m.Employees); i++ { - if m.Employees[i].ID == id { - return &m.Employees[i] + for i := range m.Employees { + if m.Employees[i].ID == id { + return &m.Employees[i] } } return nil }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
challenge-3/submissions/Gorbushka3000/solution-template.go(1 hunks)
🔇 Additional comments (3)
challenge-3/submissions/Gorbushka3000/solution-template.go (3)
5-14: LGTM! Clean struct definitions.The Employee and Manager structs are well-defined with appropriate field types and exported names.
16-19: LGTM! Correct implementation.The AddEmployee method correctly appends the new employee to the manager's list using a pointer receiver.
56-68: LGTM! Good demonstration of the API.The main function clearly demonstrates all Manager methods with appropriate nil checking when dereferencing the employee pointer.
| func (m *Manager) RemoveEmployee(id int) { | ||
| var removeValue []Employee | ||
| for i := 0; i < len(m.Employees); i++ { | ||
| if m.Employees[i].ID == id { | ||
| continue | ||
| } else { | ||
| removeValue = append(removeValue, m.Employees[i]) | ||
| } | ||
| m.Employees = removeValue | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical bug: assignment inside loop causes incorrect removal.
Line 30 assigns m.Employees = removeValue inside the loop, which executes on every iteration. This corrupts the employee list during traversal and produces incorrect results.
Apply this diff to move the assignment outside the loop:
func (m *Manager) RemoveEmployee(id int) {
var removeValue []Employee
for i := 0; i < len(m.Employees); i++ {
if m.Employees[i].ID == id {
continue
- } else {
- removeValue = append(removeValue, m.Employees[i])
}
- m.Employees = removeValue
+ removeValue = append(removeValue, m.Employees[i])
}
+ m.Employees = removeValue
}🤖 Prompt for AI Agents
In challenge-3/submissions/Gorbushka3000/solution-template.go around lines 22 to
32, the code assigns m.Employees = removeValue inside the for loop which mutates
the slice while iterating and corrupts traversal; move the assignment so it runs
once after the loop completes (declare removeValue, append non-matching
employees during iteration, then set m.Employees = removeValue after the loop)
so the original slice is not modified mid-iteration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
challenge-22/submissions/Gorbushka3000/solution-template.go(1 hunks)challenge-3/solution-template.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
challenge-3/solution-template.go (1)
challenge-3/submissions/RezaSi/solution-template.go (2)
Manager(12-14)Employee(5-10)
🔇 Additional comments (3)
challenge-3/solution-template.go (1)
17-19: LGTM!The AddEmployee implementation correctly appends the new employee to the slice.
challenge-22/submissions/Gorbushka3000/solution-template.go (2)
7-27: LGTM!The main function correctly demonstrates the coin change functions with several test cases.
31-45: The review comment is incorrect about the core issue.This challenge explicitly requires a greedy implementation (Requirement #4 in README.md: "Your solution should implement the greedy approach, which always chooses the largest coin possible."). The challenge is specifically named "Greedy Coin Change" and works with standard U.S. denominations where greedy is optimal—not arbitrary coin sets. The README even acknowledges this distinction, noting that greedy doesn't work for all denominations but does for standard U.S. coins.
The minor valid observation is that the error checks at lines 39-43 are redundant: since denominations include 1, the amount will always reach exactly 0 after the loops, making those conditions unreachable. However, this doesn't affect correctness.
Likely an incorrect or invalid review comment.
| func CoinCombination(amount int, denominations []int) map[int]int { | ||
| coinCombination := make(map[int]int) | ||
| for i := len(denominations); i > 0; i-- { | ||
| for amount-denominations[i-1] >= 0 { | ||
| amount = amount - denominations[i-1] | ||
| coinCombination[denominations[i-1]]++ | ||
| } | ||
| } | ||
| if amount < 0 { | ||
| combination := make(map[int]int) | ||
| return combination | ||
| } | ||
| return coinCombination | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same greedy algorithm limitation applies.
This function has the same greedy algorithm issue as MinCoins - it won't produce optimal results for arbitrary denominations. The core logic (lines 53-58) is nearly identical to lines 33-37 in MinCoins, suggesting an opportunity to refactor and share the logic.
Consider extracting the shared greedy logic into a helper function, or having MinCoins call CoinCombination and sum the values:
func MinCoins(amount int, denominations []int) int {
combo := CoinCombination(amount, denominations)
total := 0
for _, count := range combo {
total += count
}
if len(combo) == 0 && amount > 0 {
return -1
}
return total
}| func (m *Manager) RemoveEmployee(id int) { | ||
| // TODO: Implement this method | ||
| var removeValue []Employee | ||
| for i := 0; i < len(m.Employees); i++ { | ||
| if m.Employees[i].ID == id { | ||
| continue | ||
| } else { | ||
| removeValue = append(removeValue, m.Employees[i]) | ||
| } | ||
| m.Employees = removeValue | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the slice assignment inside the loop.
Line 30 assigns m.Employees = removeValue inside the loop, which means it gets executed on every iteration. This will corrupt the employee list and cause incorrect behavior.
Apply this diff to move the assignment outside the loop and simplify the logic:
func (m *Manager) RemoveEmployee(id int) {
var removeValue []Employee
for i := 0; i < len(m.Employees); i++ {
if m.Employees[i].ID == id {
continue
- } else {
- removeValue = append(removeValue, m.Employees[i])
}
- m.Employees = removeValue
+ removeValue = append(removeValue, m.Employees[i])
}
+ m.Employees = removeValue
}📝 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.
| func (m *Manager) RemoveEmployee(id int) { | |
| // TODO: Implement this method | |
| var removeValue []Employee | |
| for i := 0; i < len(m.Employees); i++ { | |
| if m.Employees[i].ID == id { | |
| continue | |
| } else { | |
| removeValue = append(removeValue, m.Employees[i]) | |
| } | |
| m.Employees = removeValue | |
| } | |
| } | |
| func (m *Manager) RemoveEmployee(id int) { | |
| var removeValue []Employee | |
| for i := 0; i < len(m.Employees); i++ { | |
| if m.Employees[i].ID == id { | |
| continue | |
| } | |
| removeValue = append(removeValue, m.Employees[i]) | |
| } | |
| m.Employees = removeValue | |
| } |
🤖 Prompt for AI Agents
In challenge-3/solution-template.go around lines 22 to 32, the code assigns
m.Employees = removeValue inside the loop which mutates the slice on every
iteration causing incorrect results; move the assignment so that m.Employees =
removeValue is executed only once after the loop completes and keep the loop
body to simply append non-matching employees to removeValue (remove the
else/continue complexity), ensuring the final filtered slice replaces
m.Employees after the loop.
| func (m *Manager) GetAverageSalary() float64 { | ||
| // TODO: Implement this method | ||
| return 0 | ||
| var aveSal float64 | ||
| for i := 0; i < len(m.Employees); i++ { | ||
| aveSal += m.Employees[i].Salary | ||
| } | ||
| return aveSal / float64(len(m.Employees)) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add division by zero check.
If there are no employees, line 40 will panic due to division by zero.
Apply this diff to add a guard:
func (m *Manager) GetAverageSalary() float64 {
+ if len(m.Employees) == 0 {
+ return 0
+ }
var aveSal float64
for i := 0; i < len(m.Employees); i++ {
aveSal += m.Employees[i].Salary
}
return aveSal / float64(len(m.Employees))
}📝 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.
| func (m *Manager) GetAverageSalary() float64 { | |
| // TODO: Implement this method | |
| return 0 | |
| var aveSal float64 | |
| for i := 0; i < len(m.Employees); i++ { | |
| aveSal += m.Employees[i].Salary | |
| } | |
| return aveSal / float64(len(m.Employees)) | |
| } | |
| func (m *Manager) GetAverageSalary() float64 { | |
| if len(m.Employees) == 0 { | |
| return 0 | |
| } | |
| var aveSal float64 | |
| for i := 0; i < len(m.Employees); i++ { | |
| aveSal += m.Employees[i].Salary | |
| } | |
| return aveSal / float64(len(m.Employees)) | |
| } |
🤖 Prompt for AI Agents
In challenge-3/solution-template.go around lines 35 to 41, the function
GetAverageSalary divides by float64(len(m.Employees)) and will panic when
len(m.Employees) == 0; add a guard at the start of the function that returns 0
(or another sensible default) when len(m.Employees) == 0 to avoid division by
zero, then proceed to sum salaries and divide by float64(len(m.Employees)).
| func (m *Manager) FindEmployeeByID(id int) *Employee { | ||
| // TODO: Implement this method | ||
| for i := 0; i < len(m.Employees); i++ { | ||
| if m.Employees[i].ID == id { | ||
| return &m.Employees[i] | ||
| } | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid returning pointers to slice elements.
Line 47 returns &m.Employees[i], a pointer to a slice element. This pointer can become invalid if the slice is modified later (e.g., via RemoveEmployee or when the slice grows and reallocates). Consider returning a copy of the Employee value instead.
Apply this diff to return a copy:
-func (m *Manager) FindEmployeeByID(id int) *Employee {
+func (m *Manager) FindEmployeeByID(id int) (Employee, bool) {
for i := 0; i < len(m.Employees); i++ {
if m.Employees[i].ID == id {
- return &m.Employees[i]
+ return m.Employees[i], true
}
}
- return nil
+ return Employee{}, false
}Then update the caller in main:
- employee := manager.FindEmployeeByID(2)
+ employee, found := manager.FindEmployeeByID(2)
fmt.Printf("Average Salary: %f\n", averageSalary)
- if employee != nil {
- fmt.Printf("Employee found: %+v\n", *employee)
+ if found {
+ fmt.Printf("Employee found: %+v\n", employee)
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In challenge-3/solution-template.go around lines 44 to 51, the function
currently returns a pointer to a slice element (&m.Employees[i]) which can
become invalid if the slice is modified or reallocated; change the function to
return an Employee (a copy) instead of *Employee and return m.Employees[i] (the
value) when found; update the function signature and all call sites (e.g., in
main) to accept an Employee return value or a (Employee, bool) pattern for
not-found handling, and adjust callers to use the value semantics accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
challenge-18/submissions/Gorbushka3000/solution-template.go (2)
21-23: Remove redundant variable assignment.The intermediate variable
con line 22 is unnecessary sincecelsiusis only used once.Apply this diff to simplify:
func CelsiusToFahrenheit(celsius float64) float64 { - c := celsius - return Round(c*1.8+32, 2) + return Round(celsius*1.8+32, 2) }
28-30: Remove redundant variable assignment.The intermediate variable
fis only used once and can be eliminated.Apply this diff to simplify:
func FahrenheitToCelsius(fahrenheit float64) float64 { - f := (fahrenheit - 32) * 5 / 9 - return Round(f, 2) + return Round((fahrenheit-32)*5/9, 2) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
challenge-18/submissions/Gorbushka3000/solution-template.go(1 hunks)
🔇 Additional comments (3)
challenge-18/submissions/Gorbushka3000/solution-template.go (3)
8-17: LGTM! Clear demonstration of temperature conversions.The example usage correctly demonstrates both conversion functions with appropriate formatting.
33-37: LGTM! Standard implementation for decimal rounding.The
Roundfunction correctly implements rounding to a specified number of decimal places using the standard approach.
1-37: Verify PR title matches the challenge number.The PR title states "Add solution for Challenge 1" but this file is located in the
challenge-18directory. Please confirm whether this is intentional or if the PR title needs updating.
No description provided.