MaxHalford/eaopt

View on GitHub
slice.go

Summary

Maintainability
A
0 mins
Test Coverage
package eaopt

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
}