Created the initial version
parent
2146ba3e57
commit
79a3989812
@ -0,0 +1,50 @@
|
||||
package container
|
||||
|
||||
type Queue[T any] struct {
|
||||
data []T
|
||||
len int
|
||||
}
|
||||
|
||||
// New creates an empty queue
|
||||
func NewQueue[T any]() Queue[T] {
|
||||
q := Queue[T]{
|
||||
[]T{},
|
||||
0,
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
// Enqueue adds an element to the end of the queue.
|
||||
// It appends the given value to the queue's data slice and increments the length of the queue.
|
||||
func (q *Queue[T]) Enqueue(v T) {
|
||||
q.data = append(q.data, v)
|
||||
q.len++
|
||||
}
|
||||
|
||||
// Dequeue removes and returns the element at the front of the queue.
|
||||
// It panics if the queue is empty.
|
||||
func (q *Queue[T]) Dequeue() T {
|
||||
if !q.HasElement() {
|
||||
panic("called Dequeue() on an empty queue")
|
||||
}
|
||||
|
||||
value := q.data[0]
|
||||
var zeroValue T
|
||||
q.data[0] = zeroValue
|
||||
q.data = q.data[1:]
|
||||
|
||||
q.len--
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// HasElement returns true if the queue has at least one element, otherwise false.
|
||||
func (q *Queue[T]) HasElement() bool {
|
||||
return q.len > 0
|
||||
}
|
||||
|
||||
// GetData returns the data stored in the queue.
|
||||
func (q *Queue[T]) GetData() []T {
|
||||
return q.data
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQueueDequeue(t *testing.T) {
|
||||
// Create a new queue
|
||||
q := NewQueue[int]()
|
||||
|
||||
// Enqueue some elements
|
||||
q.Enqueue(1)
|
||||
q.Enqueue(2)
|
||||
q.Enqueue(3)
|
||||
|
||||
// Dequeue the elements and check if they match the expected values
|
||||
value := q.Dequeue()
|
||||
if value != 1 {
|
||||
t.Errorf("Expected dequeued value to be 1, but got %v", value)
|
||||
}
|
||||
|
||||
value = q.Dequeue()
|
||||
if value != 2 {
|
||||
t.Errorf("Expected dequeued value to be 2, but got %v", value)
|
||||
}
|
||||
|
||||
value = q.Dequeue()
|
||||
if value != 3 {
|
||||
t.Errorf("Expected dequeued value to be 3, but got %v", value)
|
||||
}
|
||||
|
||||
// Try to dequeue from an empty queue and expect a panic
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("Expected Dequeue() to panic, but it didn't")
|
||||
}
|
||||
}()
|
||||
|
||||
q.Dequeue()
|
||||
}
|
||||
|
||||
func TestQueueHasElement(t *testing.T) {
|
||||
// Create a new queue
|
||||
q := NewQueue[int]()
|
||||
|
||||
// Check if the queue has elements, expect false
|
||||
if q.HasElement() {
|
||||
t.Errorf("Expected HasElement() to return false, but got true")
|
||||
}
|
||||
|
||||
// Enqueue an element
|
||||
q.Enqueue(1)
|
||||
|
||||
// Check if the queue has elements, expect true
|
||||
if !q.HasElement() {
|
||||
t.Errorf("Expected HasElement() to return true, but got false")
|
||||
}
|
||||
|
||||
// Dequeue the element
|
||||
q.Dequeue()
|
||||
|
||||
// Check if the queue has elements, expect false
|
||||
if q.HasElement() {
|
||||
t.Errorf("Expected HasElement() to return false, but got true")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2022 Olivier Abrivard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package container
|
||||
|
||||
type Stack[T any] struct {
|
||||
data []T
|
||||
}
|
||||
|
||||
// New creates an empty stack
|
||||
func NewStack[T any]() Stack[T] {
|
||||
result := Stack[T]{
|
||||
[]T{},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Push pushes the value v on top of stack s.
|
||||
func (s *Stack[T]) Push(v T) {
|
||||
s.data = append(s.data, v)
|
||||
}
|
||||
|
||||
// Pop removes the value v from the top of stack s and returns it.
|
||||
func (s *Stack[T]) Pop() T {
|
||||
if !s.HasElement() {
|
||||
panic("called Pop() on an empty stack")
|
||||
}
|
||||
|
||||
value := s.data[len(s.data)-1]
|
||||
s.data = s.data[0 : len(s.data)-1]
|
||||
return value
|
||||
}
|
||||
|
||||
// HasElement returns true if the stack s contains at least one element.
|
||||
func (s *Stack[T]) HasElement() bool {
|
||||
return len(s.data) > 0
|
||||
}
|
||||
|
||||
// Count returns the number of elements contained in s.
|
||||
func (s *Stack[T]) Count() int {
|
||||
return len(s.data)
|
||||
}
|
||||
|
||||
// Reversed returns a new stack built from stack s, with its elements in reverse order.
|
||||
// s will be emptied by this operation.
|
||||
func (s *Stack[T]) Reversed() Stack[T] {
|
||||
result := Stack[T]{
|
||||
make([]T, len(s.data)),
|
||||
}
|
||||
|
||||
for s.HasElement() {
|
||||
result.Push(s.Pop())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2022 Olivier Abrivard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package container
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
defer func() { _ = recover() }() // turn off the panic
|
||||
|
||||
s := NewStack[int]()
|
||||
s.Pop()
|
||||
|
||||
// Never reaches here if Pop() panics.
|
||||
t.Errorf("Pop() on empty stack should panic")
|
||||
}
|
||||
|
||||
func TestHasElements(t *testing.T) {
|
||||
s := NewStack[int]()
|
||||
|
||||
if s.HasElement() {
|
||||
t.Errorf("HasElement() should return false for empty stack")
|
||||
}
|
||||
|
||||
s.Push(1)
|
||||
|
||||
if !s.HasElement() {
|
||||
t.Errorf("HasElement() should return true for non empty stack")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
s := NewStack[int]()
|
||||
|
||||
if s.Count() != 0 {
|
||||
t.Errorf("Count() should be 0 for empty stack")
|
||||
}
|
||||
|
||||
s.Push(1)
|
||||
|
||||
if s.Count() != 1 {
|
||||
t.Errorf("Count() should be 1 for stack with as single element")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPushPop(t *testing.T) {
|
||||
s1 := NewStack[int]()
|
||||
s1.Push(1)
|
||||
s1.Push(2)
|
||||
s1.Push(3)
|
||||
|
||||
var expectedValues = []int{3, 2, 1}
|
||||
|
||||
for _, expected := range expectedValues {
|
||||
got := s1.Pop()
|
||||
|
||||
if expected != got {
|
||||
t.Errorf("got %d, want %d", got, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReversed(t *testing.T) {
|
||||
s1 := NewStack[int]()
|
||||
s1.Push(1)
|
||||
s1.Push(2)
|
||||
s1.Push(3)
|
||||
|
||||
s2 := s1.Reversed()
|
||||
|
||||
if s1.Count() != 0 {
|
||||
t.Errorf("Reversed() should emty the stack it is called upon")
|
||||
}
|
||||
|
||||
var expectedValues = []int{1, 2, 3}
|
||||
|
||||
for _, expected := range expectedValues {
|
||||
got := s2.Pop()
|
||||
|
||||
if expected != got {
|
||||
t.Errorf("got %d, want %d", got, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package container
|
||||
|
||||
type Vector[T any] []T
|
||||
|
||||
// PushBack adds an element to the end of the vector.
|
||||
// Complexity O(1) + array extesnion
|
||||
func (v *Vector[T]) PushBack(e T) {
|
||||
*v = append(*v, e)
|
||||
}
|
||||
|
||||
// PopBack removes and returns the last element from the vector.
|
||||
// If the vector is empty, it will panic.
|
||||
// Complexity O(1)
|
||||
func (v *Vector[T]) PopBack() T {
|
||||
if !v.HasElement() {
|
||||
panic("called PopBack() on an empty vector")
|
||||
}
|
||||
|
||||
value := (*v)[len(*v)-1]
|
||||
*v = (*v)[0 : len(*v)-1]
|
||||
return value
|
||||
}
|
||||
|
||||
// Len returns the length of the vector.
|
||||
// It returns an integer representing the number of elements in the vector.
|
||||
func (v Vector[T]) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
// HasElement returns true if the vector v contains at least one element.
|
||||
func (v Vector[T]) HasElement() bool {
|
||||
return v.Len() > 0
|
||||
}
|
||||
|
||||
// PushFront adds an element to the front of the vector.
|
||||
// Complexity O(n)
|
||||
func (v *Vector[T]) PushFront(e T) {
|
||||
newVect := make([]T, v.Len()+1)
|
||||
copy(newVect[1:], *v)
|
||||
newVect[0] = e
|
||||
*v = newVect
|
||||
}
|
||||
|
||||
// PopFront removes and returns the element at the front of the vector.
|
||||
// It panics if the vector is empty.
|
||||
// Complexity O(1)
|
||||
func (v *Vector[T]) PopFront() T {
|
||||
if !v.HasElement() {
|
||||
panic("called PopFront() on an empty vector")
|
||||
}
|
||||
|
||||
value := (*v)[0]
|
||||
var zeroValue T
|
||||
(*v)[0] = zeroValue
|
||||
*v = (*v)[1:]
|
||||
|
||||
return value
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVectorPushBack(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3}
|
||||
e := 4
|
||||
|
||||
v.PushBack(e)
|
||||
|
||||
expected := Vector[int]{1, 2, 3, 4}
|
||||
if !reflect.DeepEqual(v, expected) {
|
||||
t.Errorf("PushBack() failed, expected %v, got %v", expected, v)
|
||||
}
|
||||
|
||||
if v.Len() != 4 {
|
||||
t.Errorf("expected a length of 4, got %v", v.Len())
|
||||
}
|
||||
}
|
||||
|
||||
func TestVectorPopBack(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3, 4}
|
||||
expectedValue := 4
|
||||
|
||||
value := v.PopBack()
|
||||
|
||||
if value != expectedValue {
|
||||
t.Errorf("PopBack() failed, expected %v, got %v", expectedValue, value)
|
||||
}
|
||||
|
||||
expectedVector := Vector[int]{1, 2, 3}
|
||||
if !reflect.DeepEqual(v, expectedVector) {
|
||||
t.Errorf("PopBack() failed, expected vector %v, got %v", expectedVector, v)
|
||||
}
|
||||
|
||||
if v.Len() != 3 {
|
||||
t.Errorf("expected a length of 3, got %v", v.Len())
|
||||
}
|
||||
|
||||
// Test panic on empty vector
|
||||
emptyVector := Vector[int]{}
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("PopBack() did not panic on empty vector")
|
||||
}
|
||||
}()
|
||||
emptyVector.PopBack()
|
||||
}
|
||||
|
||||
func TestVectorLen(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3}
|
||||
|
||||
expected := 3
|
||||
result := v.Len()
|
||||
|
||||
if result != expected {
|
||||
t.Errorf("Len() failed, expected %d, got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVectorHasElement(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3}
|
||||
|
||||
hasElement := v.HasElement()
|
||||
|
||||
expected := true
|
||||
if hasElement != expected {
|
||||
t.Errorf("HasElement() failed, expected %v, got %v", expected, hasElement)
|
||||
}
|
||||
|
||||
v = Vector[int]{}
|
||||
|
||||
hasElement = v.HasElement()
|
||||
|
||||
expected = false
|
||||
if hasElement != expected {
|
||||
t.Errorf("HasElement() failed, expected %v, got %v", expected, hasElement)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVectorPushFront(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3}
|
||||
e := 4
|
||||
|
||||
v.PushFront(e)
|
||||
|
||||
expected := Vector[int]{4, 1, 2, 3}
|
||||
if !reflect.DeepEqual(v, expected) {
|
||||
t.Errorf("PushFront() failed, expected %v, got %v", expected, v)
|
||||
}
|
||||
|
||||
if v.Len() != 4 {
|
||||
t.Errorf("expected a length of 4, got %v", v.Len())
|
||||
}
|
||||
}
|
||||
|
||||
func TestVectorPopFront(t *testing.T) {
|
||||
v := Vector[int]{1, 2, 3, 4}
|
||||
expectedValue := 1
|
||||
expectedVector := Vector[int]{2, 3, 4}
|
||||
|
||||
value := v.PopFront()
|
||||
|
||||
if value != expectedValue {
|
||||
t.Errorf("PopFront() failed, expected value %v, got %v", expectedValue, value)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v, expectedVector) {
|
||||
t.Errorf("PopFront() failed, expected vector %v, got %v", expectedVector, v)
|
||||
}
|
||||
|
||||
if v.Len() != 3 {
|
||||
t.Errorf("expected a length of 3, got %v", v.Len())
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package fp
|
||||
|
||||
// Fold applies a function to each element in the slice and accumulates the result.
|
||||
// It takes a slice of type T, an initial value of type A, and a function that combines the accumulator value with each element of the slice.
|
||||
// The function returns the final accumulated value.
|
||||
func Fold[A any, T any](s []T, a A, f func(A, T) A) A {
|
||||
for i := range s {
|
||||
a = f(a, s[i])
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// Map applies the function f to each element of the slice s and returns a new slice
|
||||
// containing the results.
|
||||
//
|
||||
// The returned slice will contain elements of type M, which is the result
|
||||
// type of the function f.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// numbers := []int{1, 2, 3, 4, 5}
|
||||
// doubled := Map(numbers, func(n int) int {
|
||||
// return n * 2
|
||||
// })
|
||||
// // doubled is now []int{2, 4, 6, 8, 10}
|
||||
//
|
||||
// names := []string{"Alice", "Bob", "Charlie"}
|
||||
// lengths := Map(names, func(name string) int {
|
||||
// return len(name)
|
||||
// })
|
||||
// // lengths is now []int{5, 3, 7}
|
||||
//
|
||||
// Note: The input slice s is not modified by this function.
|
||||
func Map[T, M any](s []T, f func(T) M) []M {
|
||||
res := []M{}
|
||||
for i := range s {
|
||||
res = append(res, f(s[i]))
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package fp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []int
|
||||
function func(int) int
|
||||
want []int
|
||||
}{
|
||||
{
|
||||
name: "multiply by 2",
|
||||
input: []int{1, 2, 3},
|
||||
function: func(x int) int { return x * 2 },
|
||||
want: []int{2, 4, 6},
|
||||
},
|
||||
{
|
||||
name: "add 1",
|
||||
input: []int{1, 2, 3},
|
||||
function: func(x int) int { return x + 1 },
|
||||
want: []int{2, 3, 4},
|
||||
},
|
||||
{
|
||||
name: "subtract 5",
|
||||
input: []int{10, 15, 20},
|
||||
function: func(x int) int { return x - 5 },
|
||||
want: []int{5, 10, 15},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := Map(tt.input, tt.function)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Map() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFold(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []int
|
||||
accumulator int
|
||||
function func(int, int) int
|
||||
want int
|
||||
}{
|
||||
{
|
||||
name: "sum",
|
||||
input: []int{1, 2, 3},
|
||||
accumulator: 0,
|
||||
function: func(a, b int) int { return a + b },
|
||||
want: 6,
|
||||
},
|
||||
{
|
||||
name: "product",
|
||||
input: []int{1, 2, 3},
|
||||
accumulator: 1,
|
||||
function: func(a, b int) int { return a * b },
|
||||
want: 6,
|
||||
},
|
||||
{
|
||||
name: "maximum",
|
||||
input: []int{1, 2, 3},
|
||||
accumulator: 0,
|
||||
function: func(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
},
|
||||
want: 3,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := Fold(tt.input, tt.accumulator, tt.function)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Fold() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
module gitea.paas.celticinfo.fr/oabrivard/abrolgo
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
|
||||
@ -0,0 +1,2 @@
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
@ -0,0 +1,50 @@
|
||||
package math
|
||||
|
||||
import "math"
|
||||
|
||||
type Point struct {
|
||||
X, Y float64
|
||||
}
|
||||
|
||||
// ShoelaceArea calculates the area of a polygon using the Shoelace formula.
|
||||
// It takes a slice of Point structs representing the vertices of the polygon.
|
||||
// If the number of vertices is less than 3, it returns 0.0 indicating that it is not a valid polygon.
|
||||
func ShoelaceArea(polygon []Point) float64 {
|
||||
if len(polygon) < 3 {
|
||||
return 0.0 // Not a polygon
|
||||
}
|
||||
|
||||
var area float64 = 0.0
|
||||
j := len(polygon) - 1 // The last vertex is the 'previous' one to the first
|
||||
|
||||
for i := 0; i < len(polygon); i++ {
|
||||
area += (polygon[j].X + polygon[i].X) * (polygon[j].Y - polygon[i].Y)
|
||||
j = i // j is previous vertex to i
|
||||
}
|
||||
|
||||
return 0.5 * math.Abs(area)
|
||||
}
|
||||
|
||||
// floodFill performs a flood fill algorithm on the given matrix starting from the specified row and column.
|
||||
// It replaces all occurrences of the previous color with the new color.
|
||||
// The height and width parameters define the dimensions of the matrix.
|
||||
func floodFill(matrix Matrix[int64], row int, col int, prevColor int64, newColor int64, height int, width int) {
|
||||
if row < 0 || row >= height || col < 0 || col >= width {
|
||||
return
|
||||
}
|
||||
|
||||
if matrix[row][col] != prevColor {
|
||||
return
|
||||
}
|
||||
|
||||
if matrix[row][col] == newColor {
|
||||
return
|
||||
}
|
||||
|
||||
matrix[row][col] = newColor
|
||||
|
||||
floodFill(matrix, row+1, col, prevColor, newColor, height, width)
|
||||
floodFill(matrix, row-1, col, prevColor, newColor, height, width)
|
||||
floodFill(matrix, row, col+1, prevColor, newColor, height, width)
|
||||
floodFill(matrix, row, col-1, prevColor, newColor, height, width)
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package math
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestShoelaceArea(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
polygon []Point
|
||||
want float64
|
||||
}{
|
||||
{
|
||||
name: "Triangle",
|
||||
polygon: []Point{
|
||||
{X: 0, Y: 0},
|
||||
{X: 0, Y: 4},
|
||||
{X: 3, Y: 0},
|
||||
},
|
||||
want: 6.0,
|
||||
},
|
||||
{
|
||||
name: "Quadrilateral",
|
||||
polygon: []Point{
|
||||
{X: 0, Y: 0},
|
||||
{X: 0, Y: 4},
|
||||
{X: 3, Y: 4},
|
||||
{X: 3, Y: 0},
|
||||
},
|
||||
want: 12.0,
|
||||
},
|
||||
{
|
||||
name: "Invalid Polygon",
|
||||
polygon: []Point{
|
||||
{X: 0, Y: 0},
|
||||
{X: 0, Y: 4},
|
||||
},
|
||||
want: 0.0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ShoelaceArea(tt.polygon)
|
||||
if got != tt.want {
|
||||
t.Errorf("ShoelaceArea() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloodFill(t *testing.T) {
|
||||
matrix := Matrix[int64]{
|
||||
{1, 1, 1, 1},
|
||||
{1, 0, 0, 1},
|
||||
{1, 0, 0, 1},
|
||||
{1, 1, 1, 1},
|
||||
}
|
||||
row := 1
|
||||
col := 1
|
||||
prevColor := int64(0)
|
||||
newColor := int64(2)
|
||||
height := 4
|
||||
width := 4
|
||||
|
||||
floodFill(matrix, row, col, prevColor, newColor, height, width)
|
||||
|
||||
expectedMatrix := Matrix[int64]{
|
||||
{1, 1, 1, 1},
|
||||
{1, 2, 2, 1},
|
||||
{1, 2, 2, 1},
|
||||
{1, 1, 1, 1},
|
||||
}
|
||||
|
||||
if !matrix.Equal(expectedMatrix) {
|
||||
t.Errorf("FloodFill() failed, expected matrix: %v, got: %v", expectedMatrix, matrix)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
// IsPrime checks if the given number is prime.
|
||||
// It returns true if the number is prime, and false otherwise.
|
||||
func IsPrime[T constraints.Integer](n T) bool {
|
||||
if n <= 1 {
|
||||
return false
|
||||
}
|
||||
if n <= 3 {
|
||||
return true
|
||||
}
|
||||
if n%2 == 0 || n%3 == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := T(5); i*i <= n; i += 6 {
|
||||
if n%i == 0 || n%(i+2) == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IntPow calculates the power of an integer.
|
||||
// It takes two parameters, x and y, and returns the result of x raised to the power of y.
|
||||
// The type of x and y must be an integer type.
|
||||
func IntPow[T constraints.Integer](x, y T) T {
|
||||
result := T(1)
|
||||
|
||||
for i := T(0); i < y; i++ {
|
||||
result *= x
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Pow2 calculates the power of 2 for the given integer value.
|
||||
// It performs a bitwise left shift operation on the number 1 by the value of x.
|
||||
// The result is returned as an integer of the same type as the input.
|
||||
func Pow2[T constraints.Integer](x T) T {
|
||||
return 1 << x
|
||||
}
|
||||
|
||||
// GCD calculates the greatest common divisor (GCD) of two integers.
|
||||
// It uses the Euclidean algorithm to find the GCD.
|
||||
// The function takes two parameters, 'a' and 'b', which represent the integers.
|
||||
// It returns the GCD as the result.
|
||||
func GCD[T constraints.Integer](a, b T) T {
|
||||
for b != 0 {
|
||||
t := b
|
||||
b = a % b
|
||||
a = t
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// LCM calculates the least common multiple (LCM) of two or more integers.
|
||||
// It takes two integers, a and b, as the first two arguments, and an optional variadic parameter integers for additional integers.
|
||||
// The function uses the GCD (greatest common divisor) function to calculate the LCM.
|
||||
// It returns the LCM as the result.
|
||||
func LCM[T constraints.Integer](a, b T, integers ...T) T {
|
||||
result := a * b / GCD(a, b)
|
||||
|
||||
for i := 0; i < len(integers); i++ {
|
||||
result = LCM(result, integers[i])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// AbsInt returns the absolute value of an integer.
|
||||
// It takes an integer value x as input and returns the absolute value of x.
|
||||
func AbsInt[T constraints.Integer](x T) T {
|
||||
if x >= 0 {
|
||||
return x
|
||||
} else {
|
||||
return -x
|
||||
}
|
||||
}
|
||||
|
||||
// gaussianElimination performs Gaussian elimination on the given coefficients matrix and right-hand side vector.
|
||||
// It solves a system of linear equations by transforming the coefficients matrix into row-echelon form.
|
||||
// The function takes a square matrix of type Matrix[float64] and a vector of type []float64 as input.
|
||||
// The size of the matrix and the length of the vector should be the same.
|
||||
// The function modifies the coefficients matrix and the right-hand side vector in place.
|
||||
// The solution is stored into the rhs vector.
|
||||
func gaussianElimination(coefficients Matrix[float64], rhs []float64) {
|
||||
size := len(coefficients)
|
||||
for i := 0; i < size; i++ {
|
||||
// Select pivot
|
||||
pivot := coefficients[i][i]
|
||||
// Normalize row i
|
||||
for j := 0; j < size; j++ {
|
||||
coefficients[i][j] = coefficients[i][j] / pivot
|
||||
}
|
||||
rhs[i] = rhs[i] / pivot
|
||||
// Sweep using row i
|
||||
for k := 0; k < size; k++ {
|
||||
if k != i {
|
||||
factor := coefficients[k][i]
|
||||
for j := 0; j < size; j++ {
|
||||
coefficients[k][j] = coefficients[k][j] - factor*coefficients[i][j]
|
||||
}
|
||||
rhs[k] = rhs[k] - factor*rhs[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,271 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsPrime(t *testing.T) {
|
||||
tests := []struct {
|
||||
n int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
n: 0,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
n: 1,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
expected: false,
|
||||
},
|
||||
// Add more test cases as needed
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := IsPrime(tt.n)
|
||||
if result != tt.expected {
|
||||
t.Errorf("IsPrime(%d) = %v, expected %v", tt.n, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntPow(t *testing.T) {
|
||||
tests := []struct {
|
||||
x int
|
||||
y int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
x: 2,
|
||||
y: 3,
|
||||
expected: 8,
|
||||
},
|
||||
{
|
||||
x: 5,
|
||||
y: 0,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
x: 10,
|
||||
y: 1,
|
||||
expected: 10,
|
||||
},
|
||||
{
|
||||
x: 3,
|
||||
y: 4,
|
||||
expected: 81,
|
||||
},
|
||||
{
|
||||
x: 2,
|
||||
y: 0,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
x: 0,
|
||||
y: 5,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
x: -2,
|
||||
y: 3,
|
||||
expected: -8,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := IntPow(tt.x, tt.y)
|
||||
if result != tt.expected {
|
||||
t.Errorf("IntPow(%d, %d) = %d, expected %d", tt.x, tt.y, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
tests := []struct {
|
||||
x int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
x: 0,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
x: 1,
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
x: 2,
|
||||
expected: 4,
|
||||
},
|
||||
{
|
||||
x: 3,
|
||||
expected: 8,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := Pow2(tt.x)
|
||||
if result != tt.expected {
|
||||
t.Errorf("Pow2(%d) = %d, expected %d", tt.x, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGCD(t *testing.T) {
|
||||
tests := []struct {
|
||||
a int
|
||||
b int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
a: 0,
|
||||
b: 0,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
a: 0,
|
||||
b: 5,
|
||||
expected: 5,
|
||||
},
|
||||
{
|
||||
a: 10,
|
||||
b: 5,
|
||||
expected: 5,
|
||||
},
|
||||
{
|
||||
a: 12,
|
||||
b: 8,
|
||||
expected: 4,
|
||||
},
|
||||
{
|
||||
a: 15,
|
||||
b: 25,
|
||||
expected: 5,
|
||||
},
|
||||
{
|
||||
a: 21,
|
||||
b: 14,
|
||||
expected: 7,
|
||||
},
|
||||
{
|
||||
a: 100,
|
||||
b: 75,
|
||||
expected: 25,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := GCD(tt.a, tt.b)
|
||||
if result != tt.expected {
|
||||
t.Errorf("GCD(%d, %d) = %d, expected %d", tt.a, tt.b, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestLCM(t *testing.T) {
|
||||
tests := []struct {
|
||||
a int
|
||||
b int
|
||||
integers []int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
a: 2,
|
||||
b: 3,
|
||||
integers: []int{4, 5},
|
||||
expected: 60,
|
||||
},
|
||||
{
|
||||
a: 5,
|
||||
b: 7,
|
||||
integers: []int{10, 15},
|
||||
expected: 210,
|
||||
},
|
||||
{
|
||||
a: 12,
|
||||
b: 18,
|
||||
integers: []int{24, 36},
|
||||
expected: 72,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := LCM(tt.a, tt.b, tt.integers...)
|
||||
if result != tt.expected {
|
||||
t.Errorf("LCM(%d, %d, %v) = %d, expected %d", tt.a, tt.b, tt.integers, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbsInt(t *testing.T) {
|
||||
tests := []struct {
|
||||
x int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
x: 0,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
x: 5,
|
||||
expected: 5,
|
||||
},
|
||||
{
|
||||
x: -10,
|
||||
expected: 10,
|
||||
},
|
||||
{
|
||||
x: 100,
|
||||
expected: 100,
|
||||
},
|
||||
{
|
||||
x: -50,
|
||||
expected: 50,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := AbsInt(tt.x)
|
||||
if result != tt.expected {
|
||||
t.Errorf("AbsInt(%d) = %d, expected %d", tt.x, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaussianElimination(t *testing.T) {
|
||||
coefficients := [][]float64{
|
||||
{2, 1, -1},
|
||||
{-3, -1, 2},
|
||||
{-2, 1, 2},
|
||||
}
|
||||
rhs := []float64{8, -11, -3}
|
||||
|
||||
expected := []float64{2, 3, -1}
|
||||
|
||||
gaussianElimination(coefficients, rhs)
|
||||
|
||||
for i := 0; i < len(rhs); i++ {
|
||||
if rhs[i] != expected[i] {
|
||||
t.Errorf("GaussianElimination failed. Expected %v, got %v", expected, rhs)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package math
|
||||
|
||||
type Matrix[T comparable] [][]T
|
||||
|
||||
// Transpose returns the transpose of the matrix.
|
||||
func (m Matrix[T]) Transpose() Matrix[T] {
|
||||
xl := len(m[0])
|
||||
yl := len(m)
|
||||
result := make([][]T, xl)
|
||||
for i := range result {
|
||||
result[i] = make([]T, yl)
|
||||
}
|
||||
for i := 0; i < xl; i++ {
|
||||
for j := 0; j < yl; j++ {
|
||||
result[i][j] = m[j][i]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// RotateClockwise rotates the matrix clockwise by 90 degrees.
|
||||
// It returns a new matrix with the rotated values.
|
||||
func (m Matrix[T]) RotateClockwise() Matrix[T] {
|
||||
xl := len(m[0])
|
||||
yl := len(m)
|
||||
result := make([][]T, xl)
|
||||
for i := range result {
|
||||
result[i] = make([]T, yl)
|
||||
}
|
||||
|
||||
for row := 0; row < yl; row++ {
|
||||
for col := 0; col < xl; col++ {
|
||||
result[col][yl-1-row] = m[row][col]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Duplicate creates a duplicate of the matrix.
|
||||
// It returns a new matrix with the same values as the original matrix.
|
||||
func (m Matrix[T]) Duplicate() Matrix[T] {
|
||||
duplicate := make([][]T, len(m))
|
||||
for i := range m {
|
||||
duplicate[i] = make([]T, len(m[i]))
|
||||
copy(duplicate[i], m[i])
|
||||
}
|
||||
return duplicate
|
||||
}
|
||||
|
||||
// Equal checks if the current matrix is equal to the given matrix.
|
||||
// It returns true if the matrices are equal, and false otherwise.
|
||||
func (matrix1 Matrix[T]) Equal(matrix2 Matrix[T]) bool {
|
||||
if len(matrix1) != len(matrix2) || len(matrix1[0]) != len(matrix2[0]) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < len(matrix1); i++ {
|
||||
for j := 0; j < len(matrix1[0]); j++ {
|
||||
if matrix1[i][j] != matrix2[i][j] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRotateClockwise(t *testing.T) {
|
||||
matrix := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
expected := Matrix[int]{
|
||||
{7, 4, 1},
|
||||
{8, 5, 2},
|
||||
{9, 6, 3},
|
||||
}
|
||||
|
||||
result := matrix.RotateClockwise()
|
||||
|
||||
if !reflect.DeepEqual(result, expected) {
|
||||
t.Errorf("RotateClockwise() = %v, want %v", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranspose(t *testing.T) {
|
||||
matrix := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
expected := Matrix[int]{
|
||||
{1, 4, 7},
|
||||
{2, 5, 8},
|
||||
{3, 6, 9},
|
||||
}
|
||||
|
||||
result := matrix.Transpose()
|
||||
|
||||
if !reflect.DeepEqual(result, expected) {
|
||||
t.Errorf("Transpose() = %v, want %v", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicate(t *testing.T) {
|
||||
matrix := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
expected := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
result := matrix.Duplicate()
|
||||
|
||||
if !reflect.DeepEqual(result, expected) {
|
||||
t.Errorf("Duplicate() = %v, want %v", result, expected)
|
||||
}
|
||||
}
|
||||
func TestEqual(t *testing.T) {
|
||||
matrix1 := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
matrix2 := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
if !matrix1.Equal(matrix2) {
|
||||
t.Errorf("Equal() = false, want true")
|
||||
}
|
||||
|
||||
matrix3 := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9},
|
||||
}
|
||||
|
||||
matrix4 := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 0},
|
||||
}
|
||||
|
||||
if matrix3.Equal(matrix4) {
|
||||
t.Errorf("Equal() = true, want false")
|
||||
}
|
||||
|
||||
matrix5 := Matrix[int]{
|
||||
{1, 2},
|
||||
{3, 4},
|
||||
}
|
||||
|
||||
matrix6 := Matrix[int]{
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
}
|
||||
|
||||
if matrix5.Equal(matrix6) {
|
||||
t.Errorf("Equal() = true, want false")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
// Package parse provides utility functions for parsing and reading data from files.
|
||||
package parse
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
// ReadLines reads all lines from a file specified by fileName and returns them as a slice of strings.
|
||||
func ReadLines(fileName string) []string {
|
||||
result := []string{}
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
result = append(result, scanner.Text())
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ParseIntArray parses a string containing integer values separated by a specified separator and returns a slice of integers.
|
||||
func ParseIntArray[T constraints.Integer](s string, sep string) []T {
|
||||
result := []T{}
|
||||
|
||||
var vals []string
|
||||
if sep == " " {
|
||||
vals = strings.Fields(strings.TrimSpace(s))
|
||||
} else {
|
||||
vals = strings.Split(strings.TrimSpace(s), sep)
|
||||
}
|
||||
|
||||
for _, val := range vals {
|
||||
n, e := strconv.ParseInt(strings.TrimSpace(val), 10, 64)
|
||||
if e != nil {
|
||||
log.Fatal(e)
|
||||
}
|
||||
|
||||
result = append(result, T(n))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SplitNoBlank splits a string by a specified separator and returns a slice of the non-empty parts.
|
||||
func SplitNoBlank(s string, sep string) []string {
|
||||
splitted_line := strings.Split(s, sep)
|
||||
|
||||
result := []string{}
|
||||
|
||||
for _, part := range splitted_line {
|
||||
if part != "" {
|
||||
result = append(result, part)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadLines(t *testing.T) {
|
||||
// Create a temporary file and write some lines to it
|
||||
tmpFile, err := os.CreateTemp("", "testfile")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
lines := []string{
|
||||
"Line 1",
|
||||
"Line 2",
|
||||
"Line 3",
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
_, err := tmpFile.WriteString(line + "\n")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file before reading from it
|
||||
err = tmpFile.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fileName := tmpFile.Name()
|
||||
|
||||
// Call the ReadLines function
|
||||
result := ReadLines(fileName)
|
||||
|
||||
// Check if the lines read from file match the expected lines
|
||||
for i, line := range result {
|
||||
if line != lines[i] {
|
||||
t.Errorf("Expected line %d to be '%s', but got '%s'", i+1, lines[i], line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIntArray(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
separator string
|
||||
want []int64
|
||||
expectFail bool
|
||||
}{
|
||||
{
|
||||
name: "space separated",
|
||||
input: "1 2 3",
|
||||
separator: " ",
|
||||
want: []int64{1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "comma separated",
|
||||
input: "1,2,3",
|
||||
separator: ",",
|
||||
want: []int64{1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "with leading/trailing spaces",
|
||||
input: " 1, 2, 3 ",
|
||||
separator: ",",
|
||||
want: []int64{1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
separator: ",",
|
||||
want: []int64{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ParseIntArray[int64](tt.input, tt.separator)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseIntArray() = %v, want %v",
|
||||
got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitNoBlank(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
sep string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "no blank",
|
||||
input: "abc",
|
||||
sep: "",
|
||||
want: []string{"a", "b", "c"},
|
||||
},
|
||||
{
|
||||
name: "with blanks",
|
||||
input: "a b c",
|
||||
sep: " ",
|
||||
want: []string{"a", "b", "c"},
|
||||
},
|
||||
{
|
||||
name: "leading/trailing blanks",
|
||||
input: " a b c ",
|
||||
sep: " ",
|
||||
want: []string{"a", "b", "c"},
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
sep: " ",
|
||||
want: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := SplitNoBlank(tt.input, tt.sep)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SplitNoBlank() = %v, want %v",
|
||||
got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue