From a92aa4495f1c4416dd9544367f251ede57a8ca9e Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Fri, 15 Aug 2025 15:26:20 +0300 Subject: [PATCH 01/15] Add solution for Challenge 1 by grozdovk --- .../submissions/grozdovk/solution-template.go | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 challenge-1/submissions/grozdovk/solution-template.go diff --git a/challenge-1/submissions/grozdovk/solution-template.go b/challenge-1/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..aab16ac4 --- /dev/null +++ b/challenge-1/submissions/grozdovk/solution-template.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" +) + +func main() { + var a, b int + // Read two integers from standard input + _, err := fmt.Scanf("%d, %d", &a, &b) + if err != nil { + fmt.Println("Error reading input:", err) + return + } + + // Call the Sum function and print the result + result := Sum(a, b) + fmt.Println(result) +} + +// Sum returns the sum of a and b. +func Sum(a int, b int) int { + // TODO: Implement the function + return a+b +} From 1c8ec8616579532d5cc24552bbc724dd9811071e Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Fri, 15 Aug 2025 15:33:35 +0300 Subject: [PATCH 02/15] Add solution for Challenge 18 by grozdovk --- .../submissions/grozdovk/solution-template.go | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 challenge-18/submissions/grozdovk/solution-template.go diff --git a/challenge-18/submissions/grozdovk/solution-template.go b/challenge-18/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..6fbbf468 --- /dev/null +++ b/challenge-18/submissions/grozdovk/solution-template.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "math" +) + +func main() { + // Example usage + celsius := 25.0 + fahrenheit := CelsiusToFahrenheit(celsius) + fmt.Printf("%.2f°C is equal to %.2f°F\n", celsius, fahrenheit) + + fahrenheit = 68.0 + celsius = FahrenheitToCelsius(fahrenheit) + fmt.Printf("%.2f°F is equal to %.2f°C\n", fahrenheit, celsius) +} + +// CelsiusToFahrenheit converts a temperature from Celsius to Fahrenheit +// Formula: F = C × 9/5 + 32 +func CelsiusToFahrenheit(celsius float64) float64 { + // TODO: Implement this function + // Remember to round to 2 decimal places + return Round(celsius*9/5+32 , 2) +} + +// FahrenheitToCelsius converts a temperature from Fahrenheit to Celsius +// Formula: C = (F - 32) × 5/9 +func FahrenheitToCelsius(fahrenheit float64) float64 { + // TODO: Implement this function + // Remember to round to 2 decimal places + return Round((fahrenheit-32)*5/9 , 2) +} + +// Round rounds a float64 value to the specified number of decimal places +func Round(value float64, decimals int) float64 { + precision := math.Pow10(decimals) + return math.Round(value*precision) / precision +} From b4d80a1da3869c4d27019467c968267a561961e4 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Fri, 15 Aug 2025 21:58:42 +0300 Subject: [PATCH 03/15] Add solution for Challenge 6 by grozdovk --- .../submissions/grozdovk/solution-template.go | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 challenge-6/submissions/grozdovk/solution-template.go diff --git a/challenge-6/submissions/grozdovk/solution-template.go b/challenge-6/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..3a375194 --- /dev/null +++ b/challenge-6/submissions/grozdovk/solution-template.go @@ -0,0 +1,37 @@ +// Package challenge6 contains the solution for Challenge 6. +package challenge6 + +import ( + "strings" + "regexp" +) + +// CountWordFrequency takes a string containing multiple words and returns +// a map where each key is a word and the value is the number of times that +// word appears in the string. The comparison is case-insensitive. +// +// Words are defined as sequences of letters and digits. +// All words are converted to lowercase before counting. +// All punctuation, spaces, and other non-alphanumeric characters are ignored. +// +// For example: +// Input: "The quick brown fox jumps over the lazy dog." +// Output: map[string]int{"the": 2, "quick": 1, "brown": 1, "fox": 1, "jumps": 1, "over": 1, "lazy": 1, "dog": 1} +func CountWordFrequency(text string) map[string]int { + var result = make(map[string]int) + re := regexp.MustCompile(`[^a-zA-Z0-9]+`) + lowercase := strings.ToLower(text) + replaced := strings.ReplaceAll(lowercase, "'", "") + words := re.Split(replaced , -1) + for _, word := range words { + count , exists := result[word] + if exists { + result[word]++ + count++ + } else{ + result[word] = 1 + } + } + delete(result, "") + return result +} \ No newline at end of file From 7356770611436017a6f27311bf45c21ecef69dc5 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Wed, 20 Aug 2025 22:18:04 +0300 Subject: [PATCH 04/15] Add solution for Challenge 22 by grozdovk --- .../submissions/grozdovk/solution-template.go | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 challenge-22/submissions/grozdovk/solution-template.go diff --git a/challenge-22/submissions/grozdovk/solution-template.go b/challenge-22/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..c8d58eba --- /dev/null +++ b/challenge-22/submissions/grozdovk/solution-template.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "sort" +) + +func main() { + // Standard U.S. coin denominations in cents + denominations := []int{1, 5, 10, 25, 50} + + // Test amounts + amounts := []int{87, 42, 99, 33, 7} + + for _, amount := range amounts { + // Find minimum number of coins + minCoins := MinCoins(amount, denominations) + + // Find coin combination + coinCombo := CoinCombination(amount, denominations) + + // Print results + fmt.Printf("Amount: %d cents\n", amount) + fmt.Printf("Minimum coins needed: %d\n", minCoins) + fmt.Printf("Coin combination: %v\n", coinCombo) + fmt.Println("---------------------------") + } +} + +// MinCoins returns the minimum number of coins needed to make the given amount. +// If the amount cannot be made with the given denominations, return -1. +func MinCoins(amount int, denominations []int) int { + if ok := validateDenominations(denominations); !ok || amount < 0 { + return -1 + } + // TODO: Implement this function + sort.Sort(sort.Reverse(sort.IntSlice(denominations))) + + coinCount := 0 + for _, value := range denominations { + coinCount += amount / value + amount = amount % value + } + if amount != 0 { + return -1 + } + return coinCount +} +func validateDenominations(denominations []int) bool { + for _, value := range denominations { + if value <= 0 { + return false + } + } + return true +} + +// CoinCombination returns a map with the specific combination of coins that gives +// the minimum number. The keys are coin denominations and values are the number of +// coins used for each denomination. +// If the amount cannot be made with the given denominations, return an empty map. +func CoinCombination(amount int, denominations []int) map[int]int { + result := make(map[int]int) + if ok := validateDenominations(denominations); !ok || amount <= 0 { + return result + } + sort.Sort(sort.Reverse(sort.IntSlice(denominations))) + // TODO: Implement this function + for _, value := range denominations { + if temp := amount / value; temp > 0 { + result[value] = temp + } + amount = amount % value + } + return result +} From 621b0dfebe9a80346297bead296204ead8789fc3 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Wed, 3 Sep 2025 16:18:47 +0300 Subject: [PATCH 05/15] Add solution for Challenge 3 by grozdovk --- .../submissions/grozdovk/solution-template.go | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 challenge-3/submissions/grozdovk/solution-template.go diff --git a/challenge-3/submissions/grozdovk/solution-template.go b/challenge-3/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..2492cf43 --- /dev/null +++ b/challenge-3/submissions/grozdovk/solution-template.go @@ -0,0 +1,71 @@ +package main + +import "fmt" + +type Employee struct { + ID int + Name string + Age int + Salary float64 +} + +type Manager struct { + Employees []Employee +} + +// AddEmployee adds a new employee to the manager's list. +func (m *Manager) AddEmployee(e Employee) { + // TODO: Implement this method + m.Employees = append(m.Employees, e) +} + +// RemoveEmployee removes an employee by ID from the manager's list. +func (m *Manager) RemoveEmployee(id int) { + // TODO: Implement this method + for i,emp:=range m.Employees{ + if emp.ID==id{ + m.Employees = append(m.Employees[:i], m.Employees[i+1:]...) + return + } + } +} + +// GetAverageSalary calculates the average salary of all employees. +func (m *Manager) GetAverageSalary() float64 { + // TODO: Implement this method + var sumSalary float64 + var count float64 + for _,emp:= range m.Employees{ + sumSalary+=emp.Salary + count+=1 + } + if count==0{ + return 0 + } + return sumSalary/count +} + +// FindEmployeeByID finds and returns an employee by their ID. +func (m *Manager) FindEmployeeByID(id int) *Employee { + // TODO: Implement this method + for i,emp:=range m.Employees{ + if emp.ID == id{ + return &m.Employees[i] + } + } + return nil +} + +func main() { + manager := Manager{} + manager.AddEmployee(Employee{ID: 1, Name: "Alice", Age: 30, Salary: 70000}) + manager.AddEmployee(Employee{ID: 2, Name: "Bob", Age: 25, Salary: 65000}) + manager.RemoveEmployee(1) + averageSalary := manager.GetAverageSalary() + employee := manager.FindEmployeeByID(2) + + fmt.Printf("Average Salary: %f\n", averageSalary) + if employee != nil { + fmt.Printf("Employee found: %+v\n", *employee) + } +} From 8eee71d546b86d5c990776bf5b2496d46e18edfa Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Tue, 16 Sep 2025 22:52:22 +0300 Subject: [PATCH 06/15] Add solution for Challenge 21 by grozdovk --- .../submissions/grozdovk/solution-template.go | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 challenge-21/submissions/grozdovk/solution-template.go diff --git a/challenge-21/submissions/grozdovk/solution-template.go b/challenge-21/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..9cabee10 --- /dev/null +++ b/challenge-21/submissions/grozdovk/solution-template.go @@ -0,0 +1,81 @@ +package main + +import ( + "fmt" +) + +func main() { + // Example sorted array for testing + arr := []int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19} + + // Test binary search + target := 7 + index := BinarySearch(arr, target) + fmt.Printf("BinarySearch: %d found at index %d\n", target, index) + + // Test recursive binary search + recursiveIndex := BinarySearchRecursive(arr, target, 0, len(arr)-1) + fmt.Printf("BinarySearchRecursive: %d found at index %d\n", target, recursiveIndex) + + // Test find insert position + insertTarget := 8 + insertPos := FindInsertPosition(arr, insertTarget) + fmt.Printf("FindInsertPosition: %d should be inserted at index %d\n", insertTarget, insertPos) +} + +// BinarySearch performs a standard binary search to find the target in the sorted array. +// Returns the index of the target if found, or -1 if not found. +func BinarySearch(arr []int, target int) int { + if len(arr) == 0 { + return -1 + } + left, right := 0, len(arr)-1 + + for left <= right { + mid := left + (right-left)/2 + if arr[mid] == target { + return mid + } + if arr[mid] < target { + left = mid + 1 + } else { + right = mid - 1 + } + } + return -1 +} +func BinarySearchRecursive(arr []int, target, left, right int) int { + var search func(left, right int) int + search = func(left, right int) int { + if left > right { + return -1 + } + + mid := left + (right-left)/2 + if arr[mid] == target { + return mid + } + if arr[mid] < target { + return search(mid+1, right) + } + return search(left, mid-1) + } + + if len(arr) == 0 { + return -1 + } + return search(0, len(arr)-1) +} +func FindInsertPosition(arr []int, target int) int { + left, right := 0, len(arr) + + for left < right { + mid := left + (right-left)/2 + if arr[mid] < target { + left = mid + 1 + } else { + right = mid + } + } + return left +} \ No newline at end of file From a73672598f2f685ba1e4bf55bec7da65d3caf2c1 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Tue, 16 Sep 2025 23:08:41 +0300 Subject: [PATCH 07/15] Add solution for Challenege 2 by grozdovk --- .../submissions/grozdovk/solution-template.go | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 challenge-2/submissions/grozdovk/solution-template.go diff --git a/challenge-2/submissions/grozdovk/solution-template.go b/challenge-2/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..58edadc7 --- /dev/null +++ b/challenge-2/submissions/grozdovk/solution-template.go @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +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) + } +} + +// ReverseString returns the reversed string of s. +func ReverseString(s string) string { + left,right:= 0,len(s)-1 + if len(s)==-1{ + return "" + } + runes := []rune(s) + result:= make([]rune, right+1) + for left<=right{ + result[left] =runes[right] + result[right] = runes[left] + left++ + right-- + } + + return string(result) +} From 309dbfbd1b31773dc79781b5032008996a906291 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Wed, 17 Sep 2025 19:05:43 +0300 Subject: [PATCH 08/15] Add solution for Challenge 13 by grozdovk --- .../submissions/grozdovk/solution-template.go | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 challenge-13/submissions/grozdovk/solution-template.go diff --git a/challenge-13/submissions/grozdovk/solution-template.go b/challenge-13/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..bf954bfc --- /dev/null +++ b/challenge-13/submissions/grozdovk/solution-template.go @@ -0,0 +1,188 @@ +package main + +import ( + "database/sql" + "errors" + "fmt" + + _ "modernc.org/sqlite" +) + +// Product represents a product in the inventory system +type Product struct { + ID int64 + Name string + Price float64 + Quantity int + Category string +} + +// ProductStore manages product operations +type ProductStore struct { + db *sql.DB +} + +// NewProductStore creates a new ProductStore with the given database connection +func NewProductStore(db *sql.DB) *ProductStore { + return &ProductStore{db: db} +} + +// InitDB sets up a new SQLite database and creates the products table +func InitDB(dbPath string) (*sql.DB, error) { + // TODO: Open a SQLite database connection + db, err := sql.Open("sqlite", dbPath) + if err!=nil{ + return nil, err + } + err = db.Ping() + if err!=nil{ + return nil, err + } + // TODO: Create the products table if it doesn't exist + _, err = db.Exec("CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY, name TEXT, price REAL, quantity INTEGER, category TEXT)") + if err!=nil{ + return nil,err + } + // The table should have columns: id, name, price, quantity, category + return db ,err +} + +// CreateProduct adds a new product to the database +func (ps *ProductStore) CreateProduct(product *Product) error { + // TODO: Insert the product into the database + result, err:= ps.db.Exec("INSERT INTO products (name, price, quantity, category) VALUES (?,?,?,?)", + product.Name, product.Price, product.Quantity, product.Category) + if err!= nil { + return err + } + // TODO: Update the product.ID with the database-generated ID + id, err := result.LastInsertId() + if err!= nil{ + return err + } + product.ID = id + return err +} + +// GetProduct retrieves a product by ID +func (ps *ProductStore) GetProduct(id int64) (*Product, error) { + // TODO: Query the database for a product with the given ID + row:= ps.db.QueryRow("SELECT id, name, price, quantity, category FROM products WHERE ID = ?", id) + p:= &Product{} + err:= row.Scan(&p.ID, &p.Name, &p.Price, &p.Quantity, &p.Category) + if err!= nil { + if err== sql.ErrNoRows{ + return &Product{} ,fmt.Errorf("product not found") + } + return &Product{}, err + } + // TODO: Return a Product struct populated with the data or an error if not found + return p, err +} + +// UpdateProduct updates an existing product +func (ps *ProductStore) UpdateProduct(product *Product) error { + // TODO: Update the product in the database + result, err:= ps.db.Exec("UPDATE products SET name = ?, price = ?, quantity = ?, category = ? WHERE ID = ?", + product.Name, product.Price,product.Quantity, product.Category, product.ID) + if err!=nil{ + return err + } + affRows, err:= result.RowsAffected() + if err!=nil{ + return err + } + if affRows==0{ + return errors.New("product not found") + } + // TODO: Return an error if the product doesn't exist + return err +} + +// DeleteProduct removes a product by ID +func (ps *ProductStore) DeleteProduct(id int64) error { + // TODO: Delete the product from the database + result, err:= ps.db.Exec("DELETE FROM products WHERE ID = ?", id) + if err!=nil{ + return err + } + deletedRows, err:= result.RowsAffected() + if err!=nil{ + return err + } + if deletedRows==0{ + return errors.New("product not found") + } + // TODO: Return an error if the product doesn't exist + return err +} + +// ListProducts returns all products with optional filtering by category +func (ps *ProductStore) ListProducts(category string) ([]*Product, error) { + // TODO: Query the database for products + var rows *sql.Rows + var err error + if category ==""{ + rows,err = ps.db.Query("SELECT id, name, price, quantity, category FROM products") + } else{ + rows, err = ps.db.Query("SELECT id, name, price, quantity, category FROM products WHERE category = ?", category) + } + if err!=nil{ + return nil,err + } + // TODO: If category is not empty, filter by category + defer rows.Close() + var products []*Product + for rows.Next(){ + p:= &Product{} + err:= rows.Scan(&p.ID, &p.Name, &p.Price, &p.Quantity, &p.Category) + if err!=nil{ + return nil,err + } + products = append(products, p) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("error during rows iteration: %w", err) + } + // TODO: Return a slice of Product pointers + return products, nil +} + +// BatchUpdateInventory updates the quantity of multiple products in a single transaction +func (ps *ProductStore) BatchUpdateInventory(updates map[int64]int) error { + // TODO: Start a transaction + tx, err := ps.db.Begin() + if err != nil { + return err + } + defer func() { + if err != nil { + tx.Rollback() + } + }() + stmt, err := tx.Prepare("UPDATE products SET quantity = ? WHERE id = ?") + if err!=nil{ + return err + } + defer stmt.Close() + // TODO: For each product ID in the updates map, update its quantity + for id, quantity := range updates { + result,err := stmt.Exec(quantity, id) + if err!= nil { + return err + } + rowsAffected,err:= result.RowsAffected() + if err!= nil{ + return err + } + if rowsAffected==0{ + return fmt.Errorf("Product with id %d not found", id) + } + } + // TODO: If any update fails, roll back the transaction + return tx.Commit() +} + +func main() { + // Optional: you can write code here to test your implementation +} From b90977dabcb376698828c92633d983e22598ddfb Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Wed, 17 Sep 2025 19:41:11 +0300 Subject: [PATCH 09/15] Add solution for challenge 19 by grozdovk --- .../submissions/grozdovk/solution-template.go | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 challenge-19/submissions/grozdovk/solution-template.go diff --git a/challenge-19/submissions/grozdovk/solution-template.go b/challenge-19/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..f7927b63 --- /dev/null +++ b/challenge-19/submissions/grozdovk/solution-template.go @@ -0,0 +1,88 @@ +package main + +import ( + "fmt" +) + +func main() { + // Example slice for testing + numbers := []int{3, 1, 4, 1, 5, 9, 2, 6} + + // Test FindMax + max := FindMax(numbers) + fmt.Printf("Maximum value: %d\n", max) + + // Test RemoveDuplicates + unique := RemoveDuplicates(numbers) + fmt.Printf("After removing duplicates: %v\n", unique) + + // Test ReverseSlice + reversed := ReverseSlice(numbers) + fmt.Printf("Reversed: %v\n", reversed) + + // Test FilterEven + evenOnly := FilterEven(numbers) + fmt.Printf("Even numbers only: %v\n", evenOnly) +} + +// FindMax returns the maximum value in a slice of integers. +// If the slice is empty, it returns 0. +func FindMax(numbers []int) int { + // TODO: Implement this function + if len(numbers) == 0{ + return 0 + } + max := numbers[0] + for _,value:= range numbers{ + if value>max{ + max = value + } + } + return max +} + +// RemoveDuplicates returns a new slice with duplicate values removed, +// preserving the original order of elements. +func RemoveDuplicates(numbers []int) []int { + // TODO: Implement this function + if len(numbers) == 0 { + return numbers + } + seen := make(map[int]bool) + result:= make([]int,0, len(numbers)) + for _,value:= range numbers{ + if !seen[value]{ + result = append(result, value) + seen[value] = true + } + } + return result +} + +// ReverseSlice returns a new slice with elements in reverse order. +func ReverseSlice(slice []int) []int { + // TODO: Implement this function + if len(slice) == 0{ + return slice + } + result:= make([]int, len(slice)) + for i,v:= range slice{ + result[len(slice)-1-i]= v + } + return result +} + +// FilterEven returns a new slice containing only the even numbers +// from the original slice. +func FilterEven(numbers []int) []int { + if len(numbers) == 0{ + return numbers + } + result:= make([]int, 0 , len(numbers)) + for _,v := range numbers{ + if (v%2==0){ + result = append(result,v ) + } + } + return result +} From eae324002848e89ab192268639531db8e0c05447 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Thu, 25 Sep 2025 17:34:03 +0300 Subject: [PATCH 10/15] Add solution for Challenge 5 by grozdovk --- .../submissions/grozdovk/solution-template.go | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 challenge-5/submissions/grozdovk/solution-template.go diff --git a/challenge-5/submissions/grozdovk/solution-template.go b/challenge-5/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..1a048426 --- /dev/null +++ b/challenge-5/submissions/grozdovk/solution-template.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "net/http" +) + +const validToken = "secret" + +// AuthMiddleware checks the "X-Auth-Token" header. +// If it's "secret", call the next handler. +// Otherwise, respond with 401 Unauthorized. +func AuthMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // TODO: Implement the logic: + // 1) Grab the "X-Auth-Token" header + authHeader := r.Header.Get("X-Auth-Token") + // 2) Compare against validToken + // 3) If mismatch or missing, respond with 401 + if authHeader != validToken { + w.WriteHeader(http.StatusUnauthorized) + return + } + // 4) Otherwise pass to next handler + next.ServeHTTP(w, r) + }) +} + +// helloHandler returns "Hello!" on GET /hello +func helloHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello!") +} + +// secureHandler returns "You are authorized!" on GET /secure +func secureHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "You are authorized!") +} + +// SetupServer configures the HTTP routes with the authentication middleware. +func SetupServer() http.Handler { + mux := http.NewServeMux() + + // Public route: /hello (no auth required) + mux.HandleFunc("/hello", helloHandler) + + // Secure route: /secure + // Wrap with AuthMiddleware + secureRoute := http.HandlerFunc(secureHandler) + mux.Handle("/secure", AuthMiddleware(secureRoute)) + + return mux +} + +func main() { + // Optional: you can run a real server for local testing + // http.ListenAndServe(":8080", SetupServer()) +} \ No newline at end of file From ac5a3541b8308cfc6271bb0b0b8d93b515716f61 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Fri, 26 Sep 2025 00:49:32 +0300 Subject: [PATCH 11/15] Add solution for Challenge 7 by grozdovk --- .../submissions/grozdovk/solution-template.go | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 challenge-7/submissions/grozdovk/solution-template.go diff --git a/challenge-7/submissions/grozdovk/solution-template.go b/challenge-7/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..c954f524 --- /dev/null +++ b/challenge-7/submissions/grozdovk/solution-template.go @@ -0,0 +1,178 @@ +// Package challenge7 contains the solution for Challenge 7: Bank Account with Error Handling. +package challenge7 + +import ( + "fmt" + "sync" + // Add any other necessary imports +) + +// BankAccount represents a bank account with balance management and minimum balance requirements. +type BankAccount struct { + ID string + Owner string + Balance float64 + MinBalance float64 + mu sync.Mutex // For thread safety +} + +// Constants for account operations +const ( + MaxTransactionAmount = 10000.0 // Example limit for deposits/withdrawals +) + +// Custom error types + +// AccountError is a general error type for bank account operations. +type AccountError struct { + // Implement this error type + msg string +} + +func (e *AccountError) Error() string { + // Implement error message + return e.msg +} + +// InsufficientFundsError occurs when a withdrawal or transfer would bring the balance below minimum. +type InsufficientFundsError struct { + // Implement this error type + Balance float64 + MinBalance float64 +} + +func (e *InsufficientFundsError) Error() string { + // Implement error message + return fmt.Sprintf("Your balance is %f , it can't be less than %f ", e.Balance, e.MinBalance) +} + +// NegativeAmountError occurs when an amount for deposit, withdrawal, or transfer is negative. +type NegativeAmountError struct { + // Implement this error type + Amount float64 +} + +func (e *NegativeAmountError) Error() string { + // Implement error message + return fmt.Sprintf("excepted positive amount , got %f", e.Amount) +} + +// ExceedsLimitError occurs when a deposit or withdrawal amount exceeds the defined limit. +type ExceedsLimitError struct { + // Implement this error type + Amount float64 +} + +func (e *ExceedsLimitError) Error() string { + // Implement error message + return fmt.Sprintf("%f exceeds defined limit of operation", e.Amount) +} + +// NewBankAccount creates a new bank account with the given parameters. +// It returns an error if any of the parameters are invalid. +func NewBankAccount(id, owner string, initialBalance, minBalance float64) (*BankAccount, error) { + // Implement account creation with validation + if id == "" || owner == "" { + return nil, &AccountError{ + msg: "ID and Owner fields required", + } + } + if minBalance < 0 { + return nil, &NegativeAmountError{ + Amount: minBalance, + } + } + if initialBalance < 0 { + return nil, &NegativeAmountError{ + Amount: initialBalance, + } + } + if initialBalance < minBalance { + return nil, &InsufficientFundsError{ + Balance: initialBalance, + MinBalance: minBalance, + } + } + bankAccount := &BankAccount{ + ID: id, + Owner: owner, + Balance: initialBalance, + MinBalance: minBalance, + } + return bankAccount, nil +} + +// Deposit adds the specified amount to the account balance. +// It returns an error if the amount is invalid or exceeds the transaction limit. +func (a *BankAccount) Deposit(amount float64) error { + a.mu.Lock() + defer a.mu.Unlock() + // Implement deposit functionality with proper error handling + if amount < 0 { + return &NegativeAmountError{ + Amount: amount, + } + } + if amount > MaxTransactionAmount { + return &ExceedsLimitError{ + Amount: amount, + } + } + a.Balance += amount + return nil +} + +// Withdraw removes the specified amount from the account balance. +// It returns an error if the amount is invalid, exceeds the transaction limit, +// or would bring the balance below the minimum required balance. +func (a *BankAccount) Withdraw(amount float64) error { + a.mu.Lock() + defer a.mu.Unlock() + if amount < 0 { + return &NegativeAmountError{ + Amount: amount, + } + } + if amount > MaxTransactionAmount { + return &ExceedsLimitError{ + Amount: amount, + } + } + if a.Balance-amount < a.MinBalance { + return &InsufficientFundsError{ + Balance: a.Balance, + MinBalance: a.MinBalance, + } + } + // Implement withdrawal functionality with proper error handling + a.Balance -= amount + return nil +} + +// Transfer moves the specified amount from this account to the target account. +// It returns an error if the amount is invalid, exceeds the transaction limit, +// or would bring the balance below the minimum required balance. +func (a *BankAccount) Transfer(amount float64, target *BankAccount) error { + // Implement transfer functionality with proper error handling + a.mu.Lock() + defer a.mu.Unlock() + if amount < 0 { + return &NegativeAmountError{ + Amount: amount, + } + } + if amount > MaxTransactionAmount { + return &ExceedsLimitError{ + Amount: amount, + } + } + if a.Balance-amount < a.MinBalance { + return &InsufficientFundsError{ + Balance: a.Balance, + MinBalance: a.MinBalance, + } + } + a.Balance -= amount + target.Balance += amount + return nil +} From 54a8d8e052185d70c465cc1c16b3de212fb4735c Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Sun, 28 Sep 2025 22:57:57 +0300 Subject: [PATCH 12/15] Add solution for Challenge 10 by grozdovk --- .../submissions/grozdovk/solution-template.go | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 challenge-10/submissions/grozdovk/solution-template.go diff --git a/challenge-10/submissions/grozdovk/solution-template.go b/challenge-10/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..8287f1a0 --- /dev/null +++ b/challenge-10/submissions/grozdovk/solution-template.go @@ -0,0 +1,190 @@ +// Package challenge10 contains the solution for Challenge 10. +package challenge10 + +import ( + "errors" + "fmt" + "math" + "sort" + // Add any necessary imports here +) + +// Shape interface defines methods that all shapes must implement +type Shape interface { + Area() float64 + Perimeter() float64 + fmt.Stringer // Includes String() string method +} + +// Rectangle represents a four-sided shape with perpendicular sides +type Rectangle struct { + Width float64 + Height float64 +} + +// NewRectangle creates a new Rectangle with validation +func NewRectangle(width, height float64) (*Rectangle, error) { + // TODO: Implement validation and construction + if width <= 0 || height <= 0 { + return nil, errors.New("width and height must be greater than 0") + } + return &Rectangle{ + Width: width, + Height: height, + }, nil +} + +// Area calculates the area of the rectangle +func (r *Rectangle) Area() float64 { + // TODO: Implement area calculation + return r.Height*r.Width +} + +// Perimeter calculates the perimeter of the rectangle +func (r *Rectangle) Perimeter() float64 { + // TODO: Implement perimeter calculation + return (r.Height+r.Width)*2 +} + +// String returns a string representation of the rectangle +func (r *Rectangle) String() string { + // TODO: Implement string representation + return fmt.Sprintf("Rectangle with width = %f, height = %f", r.Width, r.Height) +} + +// Circle represents a perfectly round shape +type Circle struct { + Radius float64 +} + +// NewCircle creates a new Circle with validation +func NewCircle(radius float64) (*Circle, error) { + // TODO: Implement validation and construction + if radius<=0{ + return nil,errors.New("radius must be greater than 0") + } + return &Circle{ + Radius: radius, + }, nil +} + +// Area calculates the area of the circle +func (c *Circle) Area() float64 { + // TODO: Implement area calculation + return c.Radius*c.Radius*math.Pi +} + +// Perimeter calculates the circumference of the circle +func (c *Circle) Perimeter() float64 { + // TODO: Implement perimeter calculation + return c.Radius*2*math.Pi +} + +// String returns a string representation of the circle +func (c *Circle) String() string { + // TODO: Implement string representation + return fmt.Sprintf("Circle with radius = %f", c.Radius) +} + +// Triangle represents a three-sided polygon +type Triangle struct { + SideA float64 + SideB float64 + SideC float64 +} + +// NewTriangle creates a new Triangle with validation +func NewTriangle(a, b, c float64) (*Triangle, error) { + // TODO: Implement validation and construction + if (a+b<=c)||(a+c<=b)||(b+c<=a){ + return nil, errors.New("One side cant be greater then two other sides summary") + } + return &Triangle{ + SideA: a, + SideB: b, + SideC: c, + }, nil +} + +// Area calculates the area of the triangle using Heron's formula +func (t *Triangle) Area() float64 { + // TODO: Implement area calculation using Heron's formula + p:= (t.SideA+t.SideB+t.SideC)/2 + return math.Sqrt(p*(p-t.SideA)*(p-t.SideB)*(p-t.SideC)) +} + +// Perimeter calculates the perimeter of the triangle +func (t *Triangle) Perimeter() float64 { + // TODO: Implement perimeter calculation + return t.SideA+t.SideB+t.SideC +} + +// String returns a string representation of the triangle +func (t *Triangle) String() string { + // TODO: Implement string representation + return fmt.Sprintf("Triangle with sides : %f, %f, %f", t.SideA, t.SideB, t.SideC) +} + +// ShapeCalculator provides utility functions for shapes +type ShapeCalculator struct{} + +// NewShapeCalculator creates a new ShapeCalculator +func NewShapeCalculator() *ShapeCalculator { + // TODO: Implement constructor + return &ShapeCalculator{} +} + +// PrintProperties prints the properties of a shape +func (sc *ShapeCalculator) PrintProperties(s Shape) { + // TODO: Implement printing shape properties + fmt.Println(s) +} + +// TotalArea calculates the sum of areas of all shapes +func (sc *ShapeCalculator) TotalArea(shapes []Shape) float64 { + // TODO: Implement total area calculation + if len(shapes)==0{ + return 0 + } + var result float64 + for _, shape := range shapes{ + result+= shape.Area() + } + return result +} + +// LargestShape finds the shape with the largest area +func (sc *ShapeCalculator) LargestShape(shapes []Shape) Shape { + // TODO: Implement finding largest shape + if len(shapes)==0{ + return nil + } + shapeAreas := make(map[float64]Shape) + var largestArea float64 + for _,shape:= range shapes { + shapeArea := shape.Area() + if shapeArea>largestArea{ + largestArea = shapeArea + shapeAreas[largestArea] = shape + } + } + return shapeAreas[largestArea] +} + +// SortByArea sorts shapes by area in ascending or descending order +func (sc *ShapeCalculator) SortByArea(shapes []Shape, ascending bool) []Shape { + // TODO: Implement sorting shapes by area + if len(shapes)==0{ + return []Shape{} + } + sortedShapes := make([]Shape, len(shapes)) + copy(sortedShapes, shapes) + sort.Slice(sortedShapes, func(i, j int) bool { + if ascending{ + return sortedShapes[i].Area()sortedShapes[j].Area() +}) + + return sortedShapes +} From 0fa107cfaab82e81b89f1296d20894a5debab2b7 Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Mon, 29 Sep 2025 20:51:01 +0300 Subject: [PATCH 13/15] Add solution for Challenge 27 by grozdovk --- .../submissions/grozdovk/solution-template.go | 325 ++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 challenge-27/submissions/grozdovk/solution-template.go diff --git a/challenge-27/submissions/grozdovk/solution-template.go b/challenge-27/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..309adc42 --- /dev/null +++ b/challenge-27/submissions/grozdovk/solution-template.go @@ -0,0 +1,325 @@ +package generics + +import "errors" + +// ErrEmptyCollection is returned when an operation cannot be performed on an empty collection +var ErrEmptyCollection = errors.New("collection is empty") + +// +// 1. Generic Pair +// + +// Pair represents a generic pair of values of potentially different types +type Pair[T, U any] struct { + First T + Second U +} + +// NewPair creates a new pair with the given values +func NewPair[T, U any](first T, second U) Pair[T, U] { + // TODO: Implement this function + return Pair[T, U]{ + First: first, + Second: second, + } +} + +// Swap returns a new pair with the elements swapped +func (p Pair[T, U]) Swap() Pair[U, T] { + // TODO: Implement this method + return Pair[U, T]{ + First: p.Second, + Second: p.First, + } +} + +// +// 2. Generic Stack +// + +// Stack is a generic Last-In-First-Out (LIFO) data structure +type Stack[T any] struct { + // TODO: Add necessary fields + elements []T +} + +// NewStack creates a new empty stack +func NewStack[T any]() *Stack[T] { + // TODO: Implement this function + return &Stack[T]{ + elements: make([]T, 0), + } +} + +// Push adds an element to the top of the stack +func (s *Stack[T]) Push(value T) { + // TODO: Implement this method + s.elements = append(s.elements, value) +} + +// Pop removes and returns the top element from the stack +// Returns an error if the stack is empty +func (s *Stack[T]) Pop() (T, error) { + // TODO: Implement this method + var zero T + if len(s.elements)==0{ + return zero, ErrEmptyCollection + } + lastIndex:= len(s.elements)-1 + element:= s.elements[lastIndex] + s.elements = s.elements[:lastIndex] + return element, nil +} + +// Peek returns the top element without removing it +// Returns an error if the stack is empty +func (s *Stack[T]) Peek() (T, error) { + // TODO: Implement this method + var zero T + if len(s.elements)==0{ + return zero, ErrEmptyCollection + } + lastIndex:= len(s.elements)-1 + element:= s.elements[lastIndex] + return element, nil +} + +// Size returns the number of elements in the stack +func (s *Stack[T]) Size() int { + // TODO: Implement this method + return len(s.elements) +} + +// IsEmpty returns true if the stack contains no elements +func (s *Stack[T]) IsEmpty() bool { + // TODO: Implement this method + return len(s.elements)==0 +} + +// +// 3. Generic Queue +// + +// Queue is a generic First-In-First-Out (FIFO) data structure +type Queue[T any] struct { + // TODO: Add necessary fields + elements []T +} + +// NewQueue creates a new empty queue +func NewQueue[T any]() *Queue[T] { + // TODO: Implement this function + return &Queue[T]{ + elements: make([]T, 0), + } +} + +// Enqueue adds an element to the end of the queue +func (q *Queue[T]) Enqueue(value T) { + // TODO: Implement this method + q.elements = append(q.elements, value) +} + +// Dequeue removes and returns the front element from the queue +// Returns an error if the queue is empty +func (q *Queue[T]) Dequeue() (T, error) { + // TODO: Implement this method + var zero T + if len(q.elements) == 0{ + return zero, ErrEmptyCollection + } + element:= q.elements[0] + q.elements = q.elements[1:] + return element, nil +} + +// Front returns the front element without removing it +// Returns an error if the queue is empty +func (q *Queue[T]) Front() (T, error) { + // TODO: Implement this method + var zero T + if len(q.elements) == 0{ + return zero, ErrEmptyCollection + } + element:= q.elements[0] + return element, nil +} + +// Size returns the number of elements in the queue +func (q *Queue[T]) Size() int { + // TODO: Implement this method + return len(q.elements) +} + +// IsEmpty returns true if the queue contains no elements +func (q *Queue[T]) IsEmpty() bool { + // TODO: Implement this method + return len(q.elements)==0 +} + +// +// 4. Generic Set +// + +// Set is a generic collection of unique elements +type Set[T comparable] struct { + // TODO: Add necessary fields + elements map[T]any +} + +// NewSet creates a new empty set +func NewSet[T comparable]() *Set[T] { + // TODO: Implement this function + return &Set[T]{ + make(map[T]any), + } +} + +// Add adds an element to the set if it's not already present +func (s *Set[T]) Add(value T) { + // TODO: Implement this method + s.elements[value] = nil +} + +// Remove removes an element from the set if it exists +func (s *Set[T]) Remove(value T) { + // TODO: Implement this method + delete(s.elements, value) +} + +// Contains returns true if the set contains the given element +func (s *Set[T]) Contains(value T) bool { + // TODO: Implement this method + _,ok := s.elements[value] + return ok +} + +// Size returns the number of elements in the set +func (s *Set[T]) Size() int { + // TODO: Implement this method + return len(s.elements) +} + +// Elements returns a slice containing all elements in the set +func (s *Set[T]) Elements() []T { + // TODO: Implement this method + var slice = make([]T,0) + for key := range s.elements{ + slice = append(slice, key) + } + return slice +} + +// Union returns a new set containing all elements from both sets +func Union[T comparable](s1, s2 *Set[T]) *Set[T] { + // TODO: Implement this function + result := make(map[T]any) + for key := range s1.elements{ + result[key] = nil + } + for key := range s2.elements{ + result[key] = nil + } + return &Set[T]{ + elements: result, + } +} + +// Intersection returns a new set containing only elements that exist in both sets +func Intersection[T comparable](s1, s2 *Set[T]) *Set[T] { + // TODO: Implement this function + result:= make(map[T]any) + for key:= range s1.elements{ + if _,ok := s2.elements[key]; ok{ + result[key] = nil + } + } + return &Set[T]{ + elements: result, + } +} + +// Difference returns a new set with elements in s1 that are not in s2 +func Difference[T comparable](s1, s2 *Set[T]) *Set[T] { + // TODO: Implement this function + result:= make(map[T]any) + for key:= range s1.elements{ + if _,ok := s2.elements[key]; !ok{ + result[key] = nil + } + } + return &Set[T]{ + elements: result, + } +} + +// +// 5. Generic Utility Functions +// + +// Filter returns a new slice containing only the elements for which the predicate returns true +func Filter[T any](slice []T, predicate func(T) bool) []T { + // TODO: Implement this function + result:= make([]T, 0) + for _,element:= range slice{ + if predicate(element){ + result = append(result, element) + } + } + return result +} + +// Map applies a function to each element in a slice and returns a new slice with the results +func Map[T, U any](slice []T, mapper func(T) U) []U { + // TODO: Implement this function + result:= make([]U, 0) + for _, element:= range slice{ + result = append(result, mapper(element)) + } + return result +} + +// Reduce reduces a slice to a single value by applying a function to each element +func Reduce[T, U any](slice []T, initial U, reducer func(U, T) U) U { + // TODO: Implement this function + for _, element:= range slice{ + initial= reducer(initial, element) + } + return initial +} + +// Contains returns true if the slice contains the given element +func Contains[T comparable](slice []T, element T) bool { + // TODO: Implement this function + for _,sliceElement:= range slice{ + if element==sliceElement{ + return true + } + } + return false +} + +// FindIndex returns the index of the first occurrence of the given element or -1 if not found +func FindIndex[T comparable](slice []T, element T) int { + // TODO: Implement this function + for index,sliceElement:= range slice{ + if sliceElement==element{ + return index + } + } + return -1 +} + +// RemoveDuplicates returns a new slice with duplicate elements removed, preserving order +func RemoveDuplicates[T comparable](slice []T) []T { + // TODO: Implement this function + seen := make(map[T]bool) + result:= make([]T, 0) + for _,element:= range slice{ + if !seen[element]{ + result = append(result, element) + seen[element] = true + } + } + return result +} \ No newline at end of file From 7b6adfb24047c8117a392efe4deb822e5a9497cf Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Tue, 30 Sep 2025 22:32:31 +0300 Subject: [PATCH 14/15] Add solution for Challenge 17 by grozdovk --- .../submissions/grozdovk/solution-template.go | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 challenge-17/submissions/grozdovk/solution-template.go diff --git a/challenge-17/submissions/grozdovk/solution-template.go b/challenge-17/submissions/grozdovk/solution-template.go new file mode 100644 index 00000000..1a7614a6 --- /dev/null +++ b/challenge-17/submissions/grozdovk/solution-template.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "strings" +) + +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) + + // Call the IsPalindrome function and print the result + result := IsPalindrome(input) + if result { + fmt.Println("The string is a palindrome.") + } else { + fmt.Println("The string is not a palindrome.") + } +} + +// IsPalindrome checks if a string is a palindrome. +// A palindrome reads the same backward as forward, ignoring case, spaces, and punctuation. +func IsPalindrome(s string) bool { + // TODO: Implement this function + // 1. Clean the string (remove spaces, punctuation, and convert to lowercase) + lower := strings.ToLower(s) + var result strings.Builder + for _, r := range lower { + if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') { + result.WriteRune(r) + } + } + cleanedString := result.String() + runes := []rune(cleanedString) + for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { + runes[i], runes[j] = runes[j], runes[i] + } + // 2. Check if the cleaned string is the same forwards and backwards + return string(runes) == cleanedString +} + From eb540d65d062fff9b48cfe9328a0525d6ed0aa8b Mon Sep 17 00:00:00 2001 From: GrozdovKirill Date: Fri, 21 Nov 2025 18:34:13 +0300 Subject: [PATCH 15/15] Add solution for gorm challenge-1-crud-operations by grozdovk --- .../submissions/grozdovk/solution.go | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 packages/gorm/challenge-1-crud-operations/submissions/grozdovk/solution.go diff --git a/packages/gorm/challenge-1-crud-operations/submissions/grozdovk/solution.go b/packages/gorm/challenge-1-crud-operations/submissions/grozdovk/solution.go new file mode 100644 index 00000000..a7a53cd3 --- /dev/null +++ b/packages/gorm/challenge-1-crud-operations/submissions/grozdovk/solution.go @@ -0,0 +1,84 @@ +package main + +import ( + "time" + "database/sql" + + "gorm.io/gorm" + "gorm.io/driver/sqlite" + _ "modernc.org/sqlite" +) + +// User represents a user in the system +type User struct { + ID uint `gorm:"primaryKey"` + Name string `gorm:"not null"` + Email string `gorm:"unique;not null"` + Age int `gorm:"check:age > 0"` + CreatedAt time.Time + UpdatedAt time.Time +} + +// ConnectDB establishes a connection to the SQLite database +func ConnectDB() (*gorm.DB, error) { + sqlDB, err := sql.Open("sqlite", "test.db") + if err != nil { + return nil, err + } + + db, err := gorm.Open(sqlite.Dialector{Conn: sqlDB}, &gorm.Config{}) + if err != nil { + return nil, err + } + + err = db.AutoMigrate(&User{}) + return db, err +} + +// CreateUser creates a new user in the database +func CreateUser(db *gorm.DB, user *User) error { + result := db.Create(user) + return result.Error +} + +// GetUserByID retrieves a user by their ID +func GetUserByID(db *gorm.DB, id uint) (*User, error) { + var user User + result:= db.First(&user, id) + if result.Error!= nil{ + return nil, result.Error + } + return &user, nil +} + +// GetAllUsers retrieves all users from the database +func GetAllUsers(db *gorm.DB) ([]User, error) { + var users []User + result:= db.Find(&users) + if result.Error!= nil{ + return nil, result.Error + } + return users, nil +} + +// UpdateUser updates an existing user's information +func UpdateUser(db *gorm.DB, user *User) error { + var existingUser User + result := db.First(&existingUser, user.ID) + if result.Error != nil { + return result.Error + } + result = db.Save(user) + return result.Error +} + +// DeleteUser removes a user from the database +func DeleteUser(db *gorm.DB, id uint) error { + var existingUser User + result := db.First(&existingUser, id) + if result.Error != nil { + return result.Error + } + result = db.Delete(&User{}, id ) + return result.Error +}