Skip to content

Instantly share code, notes, and snippets.

@marz619
Created December 23, 2016 21:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save marz619/7d5c5b79b3c5703e9b077db9d5fc09f8 to your computer and use it in GitHub Desktop.
Save marz619/7d5c5b79b3c5703e9b077db9d5fc09f8 to your computer and use it in GitHub Desktop.
Rotate a slice
package aoc
import (
"errors"
"reflect"
)
// rotate rotates the values of a slice by rotate positions, preserving the
// rotated values by wrapping them around the slice
func rotate(slice interface{}, rotate int) error {
// check slice is not nil
if slice == nil {
return errors.New("non-nil slice interface required")
}
// get the slice value
sliceV := reflect.ValueOf(slice)
if sliceV.Kind() != reflect.Slice {
return errors.New("slice kind required")
}
// check slice value is not nil
if sliceV.IsNil() {
return errors.New("non-nil slice value required")
}
// slice length
sLen := sliceV.Len()
// shortcut when empty slice
if sLen == 0 {
return nil
}
// limit rotates via modulo
rotate %= sLen
// Go's % operator returns the remainder and thus can return negative
// values. More detail can be found under the `Integer operators` section
// here: https://golang.org/ref/spec#Arithmetic_operators
if rotate < 0 {
rotate += sLen
}
// shortcut when shift == 0
if rotate == 0 {
return nil
}
// get gcd to determine number of juggles
gcd := GCD(rotate, sLen)
// do the shifting
for i := 0; i < gcd; i++ {
// remember the first value
temp := reflect.ValueOf(sliceV.Index(i).Interface())
j := i
for {
k := j + rotate
// wrap around slice
if k >= sLen {
k -= sLen
}
// end when we're back to where we started
if k == i {
break
}
// slice[j] = slice[k]
sliceV.Index(j).Set(sliceV.Index(k))
j = k
}
// slice[j] = slice
sliceV.Index(j).Set(temp)
// elemJ.Set(temp)
}
// success
return nil
}
// RotateRight is the analogue to RotateLeft
func RotateRight(slice interface{}, by int) error {
return rotate(slice, -by)
}
// RotateLeft is an alias for Rotate
func RotateLeft(slice interface{}, by int) error {
return rotate(slice, by)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment