# Algorithm
Package algorithm implements some basic algorithm. eg. sort, search.
# Source
- https://github.com/duke-git/lancet/blob/main/algorithm/sort.go (opens new window)
 - https://github.com/duke-git/lancet/blob/main/algorithm/search.go (opens new window)
 - https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go (opens new window)
 
# Usage
import (
    "github.com/duke-git/lancet/v2/algorithm"
)
# Documentation
# BubbleSort
Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.BubbleSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# InsertionSort
Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type people struct {
        Name string
        Age  int
    }
    // PeopleAageComparator sort people slice by age field
    type peopleAgeComparator struct{}
    // Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
    func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
        p1, _ := v1.(people)
        p2, _ := v2.(people)
        //ascending order
        if p1.Age < p2.Age {
            return -1
        } else if p1.Age > p2.Age {
            return 1
        }
        return 0
        //decending order
        // if p1.Age > p2.Age {
        // 	return -1
        // } else if p1.Age < p2.Age {
        // 	return 1
        // }
    }
    var peoples = []people{
        {Name: "a", Age: 20},
        {Name: "b", Age: 10},
        {Name: "c", Age: 17},
        {Name: "d", Age: 8},
        {Name: "e", Age: 28},
    }
    comparator := &peopleAgeComparator{}
    algorithm.InsertionSort(peoples, comparator)
    fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
}
# SelectionSort
Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.SelectionSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# ShellSort
Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.ShellSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# QuickSort
Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.QuickSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# HeapSort
Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.HeapSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# MergeSort
Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    algorithm.MergeSort(intSlice, comparator)
    fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# CountSort
Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.
Signature:
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    sortedSlice := algorithm.CountSort(intSlice, comparator)
    fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
# BinarySearch
BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.
Signature:
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
    comparator := &intComparator{}
    foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
    fmt.Println(foundIndex) //4
    notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
    fmt.Println(notFoundIndex) //-1
}
# BinaryIterativeSearch
BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.
Signature:
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
    comparator := &intComparator{}
    foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
    fmt.Println(foundIndex) //4
    notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
    fmt.Println(notFoundIndex) //-1
}
# LinearSearch
LinearSearch Simple linear search algorithm that iterates over all elements of an slice. If a target is found, the index of the target is returned. Else the function return -1.
Signature:
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    type intComparator struct{}
    func (c *intComparator) Compare(v1 any, v2 any) int {
        val1, _ := v1.(int)
        val2, _ := v2.(int)
        //ascending order
        if val1 < val2 {
            return -1
        } else if val1 > val2 {
            return 1
        }
        return 0
    }
    intSlice := []int{2, 1, 5, 3, 6, 4}
    comparator := &intComparator{}
    foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
    fmt.Println(foundIndex) //2
    notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
    fmt.Println(notFoundIndex) //-1
}
# LRUCache
LRUCache implements mem cache with lru.
Signature:
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
Example:
package main
import (
    "fmt"
    "github.com/duke-git/lancet/v2/algorithm"
)
func main() {
    cache := algorithm.NewLRUCache[int, int](2)
    cache.Put(1, 1)
    cache.Put(2, 2)
    _, ok := cache.Get(0) // ok -> false
    v, ok := cache.Get(1) // v->1, ok->true
}