gago/slice.go
2021-09-11 12:47:32 +02:00

227 lines
4.7 KiB
Go

package gago
import "errors"
// A Slice is a genome with a list-like structure.
type Slice interface {
At(i int) interface{}
Set(i int, v interface{})
Len() int
Swap(i, j int)
Slice(a, b int) Slice
Split(k int) (Slice, Slice)
Append(Slice) Slice
Replace(Slice)
Copy() Slice
}
// Search for the first index of an element in a Slice.
func search(v interface{}, s Slice) (int, error) {
for i := 0; i < s.Len(); i++ {
if s.At(i) == v {
return i, nil
}
}
// Element not in slice
return 0, errors.New("Value not contained in slice")
}
// Make a lookup table from a slice, mapping values to indexes.
func newIndexLookup(s Slice) map[interface{}]int {
var lookup = make(map[interface{}]int)
for i := 0; i < s.Len(); i++ {
lookup[s.At(i)] = i
}
return lookup
}
// getCycles determines the cycles that exist between two slices. A cycle is a
// list of indexes indicating mirroring values between each slice.
func getCycles(s1, s2 Slice) (cycles [][]int) {
var (
s1Lookup = newIndexLookup(s1) // Matches values to indexes for quick lookup
visited = make(map[int]bool) // Indicates if an index is already in a cycle or not
)
for i := 0; i < s1.Len(); i++ {
if !visited[i] {
visited[i] = true
var (
cycle = []int{i}
j = s1Lookup[s2.At(i)]
)
// Continue building the cycle until it closes in on itself
for j != cycle[0] {
cycle = append(cycle, j)
visited[j] = true
j = s1Lookup[s2.At(j)]
}
cycles = append(cycles, cycle)
}
}
return
}
// getNeighbours converts a slice into an adjacency map mapping values to left
// and right neighbours. The values of the map are sets.
func getNeighbours(s Slice) map[interface{}]set {
var (
neighbours = make(map[interface{}]set)
n = s.Len()
)
neighbours[s.At(0)] = set{s.At(n - 1): true, s.At(1): true}
for i := 1; i < n-1; i++ {
neighbours[s.At(i)] = set{s.At(i - 1): true, s.At(i + 1): true}
}
neighbours[s.At(n-1)] = set{s.At(n - 2): true, s.At(0): true}
return neighbours
}
// IntSlice attaches the methods of Slice to []float64
type IntSlice []int
// At method from Slice
func (s IntSlice) At(i int) interface{} {
return s[i]
}
// Set method from Slice
func (s IntSlice) Set(i int, v interface{}) {
s[i] = v.(int)
}
// Len method from Slice
func (s IntSlice) Len() int {
return len(s)
}
// Swap method from Slice
func (s IntSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Slice method from Slice
func (s IntSlice) Slice(a, b int) Slice {
return s[a:b]
}
// Split method from Slice
func (s IntSlice) Split(k int) (Slice, Slice) {
return s[:k], s[k:]
}
// Append method from Slice
func (s IntSlice) Append(t Slice) Slice {
return append(s, t.(IntSlice)...)
}
// Replace method from Slice
func (s IntSlice) Replace(t Slice) {
copy(s, t.(IntSlice))
}
// Copy method from Slice
func (s IntSlice) Copy() Slice {
var t = make(IntSlice, len(s))
copy(t, s)
return t
}
// Float64Slice attaches the methods of Slice to []float64
type Float64Slice []float64
// At method from Slice
func (s Float64Slice) At(i int) interface{} {
return s[i]
}
// Set method from Slice
func (s Float64Slice) Set(i int, v interface{}) {
s[i] = v.(float64)
}
// Len method from Slice
func (s Float64Slice) Len() int {
return len(s)
}
// Swap method from Slice
func (s Float64Slice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Slice method from Slice
func (s Float64Slice) Slice(a, b int) Slice {
return s[a:b]
}
// Split method from Slice
func (s Float64Slice) Split(k int) (Slice, Slice) {
return s[:k], s[k:]
}
// Append method from Slice
func (s Float64Slice) Append(t Slice) Slice {
return append(s, t.(Float64Slice)...)
}
// Replace method from Slice
func (s Float64Slice) Replace(t Slice) {
copy(s, t.(Float64Slice))
}
// Copy method from Slice
func (s Float64Slice) Copy() Slice {
var t = make(Float64Slice, len(s))
copy(t, s)
return t
}
// StringSlice attaches the methods of Slice to []float64
type StringSlice []string
// At method from Slice
func (s StringSlice) At(i int) interface{} {
return s[i]
}
// Set method from Slice
func (s StringSlice) Set(i int, v interface{}) {
s[i] = v.(string)
}
// Len method from Slice
func (s StringSlice) Len() int {
return len(s)
}
// Swap method from Slice
func (s StringSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Slice method from Slice
func (s StringSlice) Slice(a, b int) Slice {
return s[a:b]
}
// Split method from Slice
func (s StringSlice) Split(k int) (Slice, Slice) {
return s[:k], s[k:]
}
// Append method from Slice
func (s StringSlice) Append(t Slice) Slice {
return append(s, t.(StringSlice)...)
}
// Replace method from Slice
func (s StringSlice) Replace(t Slice) {
copy(s, t.(StringSlice))
}
// Copy method from Slice
func (s StringSlice) Copy() Slice {
var t = make(StringSlice, len(s))
copy(t, s)
return t
}