From 25e3b489e9a77980a5769983abfaca56d895ebbb Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Fri, 20 Mar 2020 22:35:25 +0000 Subject: [PATCH] add array-sum experimentation --- .gitlab-ci.yml | 5 ++ experiments/array-sum/.gitlab-ci.yml | 10 +++ experiments/array-sum/README.md | 9 +++ experiments/array-sum/array_sum.go | 45 ++++++++++++ experiments/array-sum/array_sum_test.go | 93 +++++++++++++++++++++++++ go.mod | 3 + 6 files changed, 165 insertions(+) create mode 100644 .gitlab-ci.yml create mode 100644 experiments/array-sum/.gitlab-ci.yml create mode 100644 experiments/array-sum/README.md create mode 100644 experiments/array-sum/array_sum.go create mode 100644 experiments/array-sum/array_sum_test.go create mode 100644 go.mod diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..6fc8e63 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,5 @@ +--- +image: golang:1.14.1-alpine + +include: +- local: '/experiments/array-sum/.gitlab-ci.yml' diff --git a/experiments/array-sum/.gitlab-ci.yml b/experiments/array-sum/.gitlab-ci.yml new file mode 100644 index 0000000..cd71206 --- /dev/null +++ b/experiments/array-sum/.gitlab-ci.yml @@ -0,0 +1,10 @@ +--- +test:arraysum: + only: + refs: + - merge_requests + changes: + - "experiments/array-sum/*.go" + - "experiments/array-sum/.gitlab-ci.yml" + script: + - go test -v ./experiments/array-sum diff --git a/experiments/array-sum/README.md b/experiments/array-sum/README.md new file mode 100644 index 0000000..af21586 --- /dev/null +++ b/experiments/array-sum/README.md @@ -0,0 +1,9 @@ +# Array Sum + +This package contains functions to return the sum of all elements of a slice. +There are three main functions which all return the same result but uses different methods. +These are: + +- `SumWithForLoop` - Uses a for loop to calculate the sum. +- `SumWithRecursion` - Uses recursion to calculate the sum. +- `SumWithTailRecursion` - Uses tail recursion to to calculate the sum. diff --git a/experiments/array-sum/array_sum.go b/experiments/array-sum/array_sum.go new file mode 100644 index 0000000..5c7cf19 --- /dev/null +++ b/experiments/array-sum/array_sum.go @@ -0,0 +1,45 @@ +package arraysum + +// SumWithForLoop uses a for loop to +// calculate the sum of the slice argument. +func SumWithForLoop(numbers []int) int { + output := 0 + for _, v := range numbers { + output += v + } + return output +} + +// SumWithRecursion uses recursion to +// calculate the sum of the slice argument. +func SumWithRecursion(numbers []int) int { + if len(numbers) == 0 { + return 0 + } + + return numbers[0] + SumWithRecursion(numbers[1:]) +} + +// SumWithRecursion uses tail recursion to +// calculate the sum of the slice argument. +func SumWithTailRecursion(numbers []int) int { + return SumWithSubTailCall(numbers, 0) +} + +// SumWithSubTailCall is a sub function of +// SumWithTailRecursion. This function takes the +// first element of the array and adds it to the +// running total. It then removes said element and +// calls itself with the updated slice and the current +// running total. +// Recursion ends when there are no more elements in the +// slice. It returns the total sum back to the SubWithTailRecursion +// function. +func SumWithSubTailCall(numbers []int, runningTotal int) int { + if len(numbers) == 0 { + return runningTotal + } + + runningTotal += numbers[0] + return SumWithSubTailCall(numbers[1:], runningTotal) +} diff --git a/experiments/array-sum/array_sum_test.go b/experiments/array-sum/array_sum_test.go new file mode 100644 index 0000000..cac4efb --- /dev/null +++ b/experiments/array-sum/array_sum_test.go @@ -0,0 +1,93 @@ +package arraysum + +import "testing" + +var testCases = []struct { + input []int + expected int +}{ + { + input: []int{1, 2, 3}, + expected: 6, + }, + { + input: []int{0, 0, 0, 0}, + expected: 0, + }, + { + input: []int{64, 1, -294, 5, 79, 9, 103, 15, 10, 41, 1, 0, -2}, + expected: 32, + }, + { + input: []int{-10238, 89, 73204, -13983, -78338, 5, 1897}, + expected: -27364, + }, +} + +var gout int + +// TestSumWithForLoop tests the correctness of SumWithForLoop +func TestSumWithForLoop(t *testing.T) { + for _, tc := range testCases { + actual := SumWithForLoop(tc.input) + if actual != tc.expected { + t.Errorf("Unexpected output received: actual: %d, expected: %d", actual, tc.expected) + } + } +} + +// TestSumWithRecursion tests the correctness of SumWithRecursion +func TestSumWithRecursion(t *testing.T) { + for _, tc := range testCases { + actual := SumWithRecursion(tc.input) + if actual != tc.expected { + t.Errorf("Unexpected output received: actual: %d, expected: %d", actual, tc.expected) + } + } +} + +// TestSumWithRecursion tests the correctness of SumWithTailRecursion +func TestSumWithTailRecursion(t *testing.T) { + for _, tc := range testCases { + actual := SumWithTailRecursion(tc.input) + if actual != tc.expected { + t.Errorf("Unexpected output received: actual: %d, expected: %d", actual, tc.expected) + } + } +} + +// BenchmarkSumWithForLoop tests the performance of the SumWithForLoop function. +func BenchmarkSumWithForLoop(b *testing.B) { + var out int + var benchmarkCase = []int{-485, 327, -865, 858, -58, 893, 74, 345, -467, 632, -557, -728, 749, 634, 451, -670, 799, 300, 115, 755} + + for i := 0; i < b.N; i++ { + out = SumWithForLoop(benchmarkCase) + } + + gout = out +} + +// BenchmarkSumWithRecursion tests the performance of the SumWithRecursion function. +func BenchmarkSumWithRecursion(b *testing.B) { + var out int + var benchmarkCase = []int{-485, 327, -865, 858, -58, 893, 74, 345, -467, 632, -557, -728, 749, 634, 451, -670, 799, 300, 115, 755} + + for i := 0; i < b.N; i++ { + out = SumWithRecursion(benchmarkCase) + } + + gout = out +} + +// BenchmarkSumWithTailRecursion tests the performance of the SumWithTailRecursion function. +func BenchmarkSumWithTailRecursion(b *testing.B) { + var out int + var benchmarkCase = []int{-485, 327, -865, 858, -58, 893, 74, 345, -467, 632, -557, -728, 749, 634, 451, -670, 799, 300, 115, 755} + + for i := 0; i < b.N; i++ { + out = SumWithTailRecursion(benchmarkCase) + } + + gout = out +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..726cea1 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gitlab.com/dananglin/go-laboratory + +go 1.13