diff --git a/experiments/go/shuffle-elements/shuffle.go b/experiments/go/shuffle-elements/shuffle.go index 5db67b8..6491ef5 100644 --- a/experiments/go/shuffle-elements/shuffle.go +++ b/experiments/go/shuffle-elements/shuffle.go @@ -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 } diff --git a/experiments/go/shuffle-elements/shuffle_test.go b/experiments/go/shuffle-elements/shuffle_test.go index 55ef074..6d89d1e 100644 --- a/experiments/go/shuffle-elements/shuffle_test.go +++ b/experiments/go/shuffle-elements/shuffle_test.go @@ -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 +}