Created
September 7, 2017 18:22
-
-
Save danehammer/eaad56b4f5a8055696c55cfedc2e8c9f to your computer and use it in GitHub Desktop.
Equilibrium indices in go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package equilib | |
// Indices returns any of the equilibrium indices, -1 if there is not one | |
func Indices(nums []int) int { | |
if len(nums) > 10 { | |
return -2 | |
} | |
for i := 0; i < len(nums); i++ { | |
left := sum(nums[0:i]) | |
right := sum(nums[i+1:]) | |
if left == right { | |
return i | |
} | |
} | |
return -1 | |
} | |
func sum(nums []int) int { | |
total := 0 | |
for i := 0; i < len(nums); i++ { | |
total += nums[i] | |
} | |
return total | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package equilib | |
import ( | |
"fmt" | |
"testing" | |
"github.com/leanovate/gopter" | |
"github.com/leanovate/gopter/prop" | |
) | |
func TestExample(t *testing.T) { | |
// A[0] = -1 | |
// A[1] = 3 | |
// A[2] = -4 | |
// A[3] = 5 | |
// A[4] = 1 | |
// A[5] = -6 | |
// A[6] = 2 | |
// A[7] = 1 | |
input := []int{-1, 3, -4, 5, 1, -6, 2, 1} | |
p := Indices(input) | |
leftSum := 0 | |
rightSum := 0 | |
for i := 0; i < p; i++ { | |
leftSum += input[i] | |
} | |
for j := p + 1; j < len(input); j++ { | |
rightSum += input[j] | |
} | |
if leftSum != rightSum { | |
t.Errorf("P did not yield equal sides, got left %d and right %d", leftSum, rightSum) | |
} | |
} | |
func TestForNoAnswer(t *testing.T) { | |
input := []int{1, 2} | |
p := Indices(input) | |
if p != -1 { | |
t.Errorf("Should have gotten -1 for no solution, got %d", p) | |
} | |
} | |
func TestPropertyBased(t *testing.T) { | |
parameters := gopter.DefaultTestParameters() | |
parameters.MinSuccessfulTests = 10000 | |
fmt.Println(parameters) // FIXME | |
properties := gopter.NewProperties(parameters) | |
nextInt := func(p *gopter.GenParameters) int { | |
v := p.Rng.Int() | |
if p.NextBool() { | |
return -v | |
} | |
return v | |
} | |
nextSlice := func(p *gopter.GenParameters) []int { | |
fmt.Println(p.MaxSize) // FIXME | |
len := p.Rng.Intn(p.MaxSize) | |
slice := make([]int, len, len) | |
equilibPos := p.Rng.Intn(len) | |
leftSum := 0 | |
for i := 0; i < equilibPos; i++ { | |
n := nextInt(p) | |
slice[i] = n | |
leftSum += n | |
} | |
slice[equilibPos] = nextInt(p) | |
// Know we need right of equilibPos to add up to leftSum, so we'll add and | |
// subtract every other to keep our sum | |
for i := equilibPos + 1; i < len; i += 2 { | |
n := nextInt(p) | |
slice[i] = n | |
slice[i+1] = -n | |
} | |
return slice | |
} | |
sliceGen := func(p *gopter.GenParameters) *gopter.GenResult { | |
fmt.Println(*p) // FIXME | |
return gopter.NewGenResult(nextSlice(p), gopter.NoShrinker) | |
// OR | |
// result := g(genParams) | |
// value, ok := result.Retrieve() | |
// if ok { | |
// return f(value)(genParams) | |
// } | |
// return &GenResult{ | |
// Shrinker: NoShrinker, | |
// result: nil, | |
// Labels: result.Labels, | |
// ResultType: resultType, | |
// } | |
} | |
properties.Property("When equilibrium exists", prop.ForAllNoShrink( | |
func(nums []int) bool { | |
p := Indices(nums) | |
leftSum := 0 | |
rightSum := 0 | |
for i := 0; i < p; i++ { | |
leftSum += nums[i] | |
} | |
for j := p + 1; j < len(nums); j++ { | |
rightSum += nums[j] | |
} | |
return leftSum == rightSum | |
}, | |
sliceGen, | |
)) | |
properties.TestingRun(t) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment