forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add extended gcd (TheAlgorithms#307)
Co-authored-by: Christian Clauss <[email protected]> Co-authored-by: Andrii Siriak <[email protected]>
- Loading branch information
1 parent
2ce0de8
commit a50e4a6
Showing
3 changed files
with
82 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package gcd | ||
|
||
// ExtendedRecursive finds and returns gcd(a, b), x, y satisfying a*x + b*y = gcd(a, b). | ||
func ExtendedRecursive(a, b int64) (int64, int64, int64) { | ||
if b > 0 { | ||
d, y, x := ExtendedRecursive(b, a%b) | ||
y -= (a / b) * x | ||
return d, x, y | ||
} | ||
|
||
return a, 1, 0 | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package gcd | ||
|
||
import "testing" | ||
|
||
type testExtendedFunction func(int64, int64) (int64, int64, int64) | ||
|
||
var testCasesExtended = []struct { | ||
name string | ||
a int64 | ||
b int64 | ||
gcd int64 | ||
x int64 | ||
y int64 | ||
}{ | ||
{"gcd of 10 and 0", 10, 0, 10, 1, 0}, | ||
{"gcd of 98 and 56", 98, 56, 14, -1, 2}, | ||
{"gcd of 0 and 10", 0, 10, 10, 0, 1}, | ||
} | ||
|
||
func TemplateTestExtendedGCD(t *testing.T, f testExtendedFunction) { | ||
for _, tc := range testCasesExtended { | ||
t.Run(tc.name, func(t *testing.T) { | ||
actualGcd, actualX, actualY := f(tc.a, tc.b) | ||
if actualGcd != tc.gcd { | ||
t.Errorf("Expected GCD of %d and %d to be: %v, but got: %d", tc.a, tc.b, tc.gcd, actualGcd) | ||
} | ||
if actualX != tc.x { | ||
t.Errorf("Expected x satisfying %d * x + %d * y = gcd to be: %v, but got: %d", tc.a, tc.b, tc.x, actualX) | ||
} | ||
if actualY != tc.y { | ||
t.Errorf("Expected y satisfying %d * x + %d * y = gcd to be: %v, but got: %d", tc.a, tc.b, tc.y, actualY) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestExtendedGCDRecursive(t *testing.T) { | ||
TemplateTestExtendedGCD(t, ExtendedRecursive) | ||
} | ||
|
||
func TestExtendedGCDIterative(t *testing.T) { | ||
TemplateTestExtendedGCD(t, ExtendedIterative) | ||
} | ||
|
||
func TemplateBenchmarkExtendedGCD(b *testing.B, f testExtendedFunction) { | ||
for i := 0; i < b.N; i++ { | ||
f(98, 56) | ||
} | ||
} | ||
|
||
func BenchmarkExtendedGCDRecursive(b *testing.B) { | ||
TemplateBenchmarkExtendedGCD(b, ExtendedRecursive) | ||
} | ||
|
||
func BenchmarkExtendedGCDIterative(b *testing.B) { | ||
TemplateBenchmarkExtendedGCD(b, ExtendedIterative) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package gcd | ||
|
||
// ExtendedIterative finds and returns gcd(a, b), x, y satisfying a*x + b*y = gcd(a, b). | ||
func ExtendedIterative(a, b int64) (int64, int64, int64) { | ||
var u, y, v, x int64 = 1, 1, 0, 0 | ||
for a > 0 { | ||
var q int64 = b / a | ||
x, u = u, x-q*u | ||
y, v = v, y-q*v | ||
b, a = a, b-q*a | ||
} | ||
return b, x, y | ||
} |