From fd2b1768e650a83ae99f785a2bff8791ad7ed2e7 Mon Sep 17 00:00:00 2001 From: rahulc29 Date: Mon, 25 Oct 2021 15:37:46 +0530 Subject: [PATCH 1/3] Add Implementation of extended Euclidean algorithm --- Maths/LinearDiophantineEquationsSolver.java | 141 ++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 Maths/LinearDiophantineEquationsSolver.java diff --git a/Maths/LinearDiophantineEquationsSolver.java b/Maths/LinearDiophantineEquationsSolver.java new file mode 100644 index 000000000000..f155e585ef5e --- /dev/null +++ b/Maths/LinearDiophantineEquationsSolver.java @@ -0,0 +1,141 @@ +package Maths; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public final class LinearDiophantineEquationsSolver { + public static final class Solution { + private int x; + private int y; + + public Solution(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (Solution) obj; + return this.x == that.x && + this.y == that.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + + @Override + public String toString() { + return "Solution[" + + "x=" + x + ", " + + "y=" + y + ']'; + } + + } + public record Equation(int a, int b, int c) { + } + public static List solve(final Equation equation) { + if (equation.a() == 0 && equation.b() == 0 && equation.c() == 0) { + return List.of(new Solution(0, 0)); + } + if (equation.a() == 0 && equation.b() == 0) { + return Collections.emptyList(); + } + final var toReturn = new ArrayList(); + final int gcd = gcd(equation.a(), equation.b()); + return toReturn; + } + private static int gcd(final int a, final int b) { + if (b == 0) { + return a; + } + return gcd(b, a % b); + } + + public static final class GcdSolutionWrapper { + private int gcd; + private Solution solution; + + public GcdSolutionWrapper(int gcd, Solution solution) { + this.gcd = gcd; + this.solution = solution; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (GcdSolutionWrapper) obj; + return this.gcd == that.gcd && + Objects.equals(this.solution, that.solution); + } + + public int getGcd() { + return gcd; + } + + public void setGcd(int gcd) { + this.gcd = gcd; + } + + public Solution getSolution() { + return solution; + } + + public void setSolution(Solution solution) { + this.solution = solution; + } + + @Override + public int hashCode() { + return Objects.hash(gcd, solution); + } + + @Override + public String toString() { + return "GcdSolutionWrapper[" + + "gcd=" + gcd + ", " + + "solution=" + solution + ']'; + } + + } + + private static GcdSolutionWrapper gcd(final int a, final int b, final GcdSolutionWrapper previous) { + if (b == 0) { + return new GcdSolutionWrapper(a, new Solution(1, 0)); + } + // stub wrapper becomes the `previous` of the next recursive call + final var stubWrapper = new GcdSolutionWrapper(0, new Solution(0, 0)); + final var next = /* recursive call */ gcd(b, a % b, stubWrapper); + previous.getSolution().setX(next.getSolution().getY()); + previous.getSolution().setY(next.getSolution().getX() - (a / b) * (next.getSolution().getY())); + previous.setGcd(next.getGcd()); + return new GcdSolutionWrapper(next.getGcd(), previous.getSolution()); + } + + public static void main(String[] args) { + final var initial = new GcdSolutionWrapper(0, new Solution(0, 0)); + System.out.println(gcd(5, 6, initial)); + } +} From 04a9d099dfe26c95155c4056ee471f4f27b21d05 Mon Sep 17 00:00:00 2001 From: rahulc29 Date: Tue, 26 Oct 2021 13:37:01 +0530 Subject: [PATCH 2/3] Add method `findAnySolution` to find primordial solution --- Maths/LinearDiophantineEquationsSolver.java | 27 ++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Maths/LinearDiophantineEquationsSolver.java b/Maths/LinearDiophantineEquationsSolver.java index f155e585ef5e..d0649e7959f2 100644 --- a/Maths/LinearDiophantineEquationsSolver.java +++ b/Maths/LinearDiophantineEquationsSolver.java @@ -7,6 +7,8 @@ public final class LinearDiophantineEquationsSolver { public static final class Solution { + public static final Solution NO_SOLUTION = new Solution(Integer.MAX_VALUE, Integer.MAX_VALUE); + public static final Solution INFINITE_SOLUTIONS = new Solution(Integer.MIN_VALUE, Integer.MIN_VALUE); private int x; private int y; @@ -55,23 +57,26 @@ public String toString() { } public record Equation(int a, int b, int c) { } - public static List solve(final Equation equation) { - if (equation.a() == 0 && equation.b() == 0 && equation.c() == 0) { - return List.of(new Solution(0, 0)); - } - if (equation.a() == 0 && equation.b() == 0) { - return Collections.emptyList(); - } - final var toReturn = new ArrayList(); - final int gcd = gcd(equation.a(), equation.b()); - return toReturn; - } + private static int gcd(final int a, final int b) { if (b == 0) { return a; } return gcd(b, a % b); } + public static Solution findAnySolution(final Equation equation) { + final var stub = new GcdSolutionWrapper(0, new Solution(0, 0)); + final var gcdSolution = gcd(equation.a(), equation.b(), stub); + if (equation.c() % gcdSolution.getGcd() != 0) { + return Solution.NO_SOLUTION; + } + final var toReturn = new Solution(0, 0); + var xToSet = stub.getSolution().getX() * (equation.c() / stub.getGcd()); + var yToSet = stub.getSolution().getY() * (equation.c() / stub.getGcd()); + toReturn.setX(xToSet); + toReturn.setY(yToSet); + return toReturn; + } public static final class GcdSolutionWrapper { private int gcd; From 8b95b0f6f48417d797f0c6ce6a1e2dd9d1f35591 Mon Sep 17 00:00:00 2001 From: rahulc29 Date: Tue, 26 Oct 2021 22:57:02 +0530 Subject: [PATCH 3/3] Reformat code --- Maths/LinearDiophantineEquationsSolver.java | 79 ++++++++++----------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/Maths/LinearDiophantineEquationsSolver.java b/Maths/LinearDiophantineEquationsSolver.java index d0649e7959f2..09837cc9037c 100644 --- a/Maths/LinearDiophantineEquationsSolver.java +++ b/Maths/LinearDiophantineEquationsSolver.java @@ -1,11 +1,45 @@ package Maths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Objects; public final class LinearDiophantineEquationsSolver { + + public static void main(String[] args) { + // 3x + 4y = 7 + final var toSolve = new Equation(3, 4, 7); + System.out.println(findAnySolution(toSolve)); + } + + public static Solution findAnySolution(final Equation equation) { + if (equation.a() == 0 && equation.b() == 0 && equation.c() == 0) { + return Solution.INFINITE_SOLUTIONS; + } + final var stub = new GcdSolutionWrapper(0, new Solution(0, 0)); + final var gcdSolution = gcd(equation.a(), equation.b(), stub); + if (equation.c() % gcdSolution.getGcd() != 0) { + return Solution.NO_SOLUTION; + } + final var toReturn = new Solution(0, 0); + var xToSet = stub.getSolution().getX() * (equation.c() / stub.getGcd()); + var yToSet = stub.getSolution().getY() * (equation.c() / stub.getGcd()); + toReturn.setX(xToSet); + toReturn.setY(yToSet); + return toReturn; + } + + private static GcdSolutionWrapper gcd(final int a, final int b, final GcdSolutionWrapper previous) { + if (b == 0) { + return new GcdSolutionWrapper(a, new Solution(1, 0)); + } + // stub wrapper becomes the `previous` of the next recursive call + final var stubWrapper = new GcdSolutionWrapper(0, new Solution(0, 0)); + final var next = /* recursive call */ gcd(b, a % b, stubWrapper); + previous.getSolution().setX(next.getSolution().getY()); + previous.getSolution().setY(next.getSolution().getX() - (a / b) * (next.getSolution().getY())); + previous.setGcd(next.getGcd()); + return new GcdSolutionWrapper(next.getGcd(), previous.getSolution()); + } + public static final class Solution { public static final Solution NO_SOLUTION = new Solution(Integer.MAX_VALUE, Integer.MAX_VALUE); public static final Solution INFINITE_SOLUTIONS = new Solution(Integer.MIN_VALUE, Integer.MIN_VALUE); @@ -55,27 +89,8 @@ public String toString() { } } - public record Equation(int a, int b, int c) { - } - private static int gcd(final int a, final int b) { - if (b == 0) { - return a; - } - return gcd(b, a % b); - } - public static Solution findAnySolution(final Equation equation) { - final var stub = new GcdSolutionWrapper(0, new Solution(0, 0)); - final var gcdSolution = gcd(equation.a(), equation.b(), stub); - if (equation.c() % gcdSolution.getGcd() != 0) { - return Solution.NO_SOLUTION; - } - final var toReturn = new Solution(0, 0); - var xToSet = stub.getSolution().getX() * (equation.c() / stub.getGcd()); - var yToSet = stub.getSolution().getY() * (equation.c() / stub.getGcd()); - toReturn.setX(xToSet); - toReturn.setY(yToSet); - return toReturn; + public record Equation(int a, int b, int c) { } public static final class GcdSolutionWrapper { @@ -125,22 +140,4 @@ public String toString() { } } - - private static GcdSolutionWrapper gcd(final int a, final int b, final GcdSolutionWrapper previous) { - if (b == 0) { - return new GcdSolutionWrapper(a, new Solution(1, 0)); - } - // stub wrapper becomes the `previous` of the next recursive call - final var stubWrapper = new GcdSolutionWrapper(0, new Solution(0, 0)); - final var next = /* recursive call */ gcd(b, a % b, stubWrapper); - previous.getSolution().setX(next.getSolution().getY()); - previous.getSolution().setY(next.getSolution().getX() - (a / b) * (next.getSolution().getY())); - previous.setGcd(next.getGcd()); - return new GcdSolutionWrapper(next.getGcd(), previous.getSolution()); - } - - public static void main(String[] args) { - final var initial = new GcdSolutionWrapper(0, new Solution(0, 0)); - System.out.println(gcd(5, 6, initial)); - } }