feat: add a third solution for shuffle experiment

Add the third solution to the shuffle experiment which happens to be the
most performant solution according to the basic benchmark test.
This commit is contained in:
Dan Anglin 2024-01-24 23:33:37 +00:00
parent 3c9afeb1b9
commit 1b9c390ce6
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
2 changed files with 86 additions and 18 deletions

View file

@ -10,7 +10,7 @@ const (
// shuffleFuncOne creates a new list where an element in one position is repositioned
// to the index of another element. All affected elements then shuffleFuncOne one place to the left
// or right depending on the direction of the move.
func shuffleFuncOne(list []any, oldPos, newPos int) []any {
func shuffleFuncOne(input []any, oldPos, newPos int) []any {
var direction shuffleDirection
if newPos < oldPos {
@ -19,54 +19,73 @@ func shuffleFuncOne(list []any, oldPos, newPos int) []any {
direction = left
}
newList := make([]any, len(list))
output := make([]any, len(input))
for i := range list {
for i := range input {
switch {
case (direction == right) && (i < newPos || i > oldPos):
newList[i] = list[i]
output[i] = input[i]
case (direction == right) && (i == oldPos):
newList[newPos] = list[i]
output[newPos] = input[i]
case (direction == right):
newList[i+1] = list[i]
output[i+1] = input[i]
case (direction == left) && (i < oldPos || i > newPos):
newList[i] = list[i]
output[i] = input[i]
case (direction == left) && (i == oldPos):
newList[newPos] = list[i]
output[newPos] = input[i]
case (direction == left):
newList[i-1] = list[i]
output[i-1] = input[i]
}
}
return newList
return output
}
// shuffleFuncTwo produces the same output as shuffleFuncOne using a slightly different method.
// The original slice is copied into a new slice and the element is immediately placed in the new
// position. The for loop then only focuses on the elements in range between the two positions and
// are shuffled left or right as required.
func shuffleFuncTwo(list []any, oldPos, newPos int) []any {
newList := make([]any, len(list))
func shuffleFuncTwo(input []any, oldPos, newPos int) []any {
output := make([]any, len(input))
copy(newList, list)
copy(output, input)
newList[newPos] = list[oldPos]
output[newPos] = input[oldPos]
if newPos < oldPos {
for i := newPos; i <= oldPos; i++ {
if i != oldPos {
newList[i+1] = list[i]
output[i+1] = input[i]
}
}
return newList
return output
}
for i := oldPos; i <= newPos; i++ {
if i != oldPos {
newList[i-1] = list[i]
output[i-1] = input[i]
}
}
return newList
return output
}
// shuffleFuncThree produces the same output as the above two functions by simply swapping
// the target element with the element one above or below in the list until that element reaches
// the desired index.
func shuffleFuncThree(list []any, oldPos, newPos int) []any {
if newPos < oldPos {
for i := oldPos; i > newPos; i-- {
list[i], list[i-1] = list[i-1], list[i]
}
return list
}
for i := oldPos; i < newPos; i++ {
list[i], list[i+1] = list[i+1], list[i]
}
return list
}

View file

@ -39,6 +39,8 @@ var cases = []Cases{
},
}
var gout []any
func TestShuffleFuncOne(t *testing.T) {
for i := range cases {
t.Logf("Input list: %v", cases[i].list)
@ -66,3 +68,50 @@ func TestShuffleFuncTwo(t *testing.T) {
}
}
}
func TestShuffleFuncThree(t *testing.T) {
for i := range cases {
t.Logf("Input list: %v", cases[i].list)
t.Logf("We want '%v' to move to position %d", cases[i].list[cases[i].oldPosition], cases[i].newPosition)
got := shuffleFuncThree(cases[i].list, cases[i].oldPosition, cases[i].newPosition)
if !reflect.DeepEqual(cases[i].want, got) {
t.Errorf("TEST FAILED: want: %v, got %v", cases[i].want, got)
} else {
t.Logf("TEST PASSED: got %v", got)
}
}
}
func BenchmarkShuffleFuncThree(b *testing.B) {
var out []any
var benchmarkCase = []any{-183, -34, -118, -51, 161, -39, 60, -170, -15, -148, 70, 176, -101, -81, 156, -43, -130, 193, 64, 127, 49, 133, 199, -92, 178, -24, -139, 48, -171, 65, 187, -20, 124, 76, 68, -100, 43, 22, -21, 36, -46, 129, 40, 100, 171, 105, -165, 71, -192, -72, -93, -132, 34, 67, 55, -129, -41, 158, 46, 138}
for i := 0; i < b.N; i++ {
out = shuffleFuncThree(benchmarkCase, 47, 16)
}
gout = out
}
func BenchmarkShuffleFuncTwo(b *testing.B) {
var out []any
var benchmarkCase = []any{-183, -34, -118, -51, 161, -39, 60, -170, -15, -148, 70, 176, -101, -81, 156, -43, -130, 193, 64, 127, 49, 133, 199, -92, 178, -24, -139, 48, -171, 65, 187, -20, 124, 76, 68, -100, 43, 22, -21, 36, -46, 129, 40, 100, 171, 105, -165, 71, -192, -72, -93, -132, 34, 67, 55, -129, -41, 158, 46, 138}
for i := 0; i < b.N; i++ {
out = shuffleFuncTwo(benchmarkCase, 47, 16)
}
gout = out
}
func BenchmarkShuffleFuncOne(b *testing.B) {
var out []any
var benchmarkCase = []any{-183, -34, -118, -51, 161, -39, 60, -170, -15, -148, 70, 176, -101, -81, 156, -43, -130, 193, 64, 127, 49, 133, 199, -92, 178, -24, -139, 48, -171, 65, 187, -20, 124, 76, 68, -100, 43, 22, -21, 36, -46, 129, 40, 100, 171, 105, -165, 71, -192, -72, -93, -132, 34, 67, 55, -129, -41, 158, 46, 138}
for i := 0; i < b.N; i++ {
out = shuffleFuncOne(benchmarkCase, 47, 16)
}
gout = out
}