From 7858187d59c7189c05b5833162fda8a2c64b5bb4 Mon Sep 17 00:00:00 2001 From: Rahul Chhabra Date: Thu, 28 Oct 2021 22:35:44 +0530 Subject: [PATCH] Add Solver For Linear Diophantine Equations (#2744) --- Maths/LinearDiophantineEquationsSolver.java | 143 ++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 Maths/LinearDiophantineEquationsSolver.java diff --git a/Maths/LinearDiophantineEquationsSolver.java b/Maths/LinearDiophantineEquationsSolver.java new file mode 100644 index 00000000..09837cc9 --- /dev/null +++ b/Maths/LinearDiophantineEquationsSolver.java @@ -0,0 +1,143 @@ +package Maths; + +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); + 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 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 + ']'; + } + + } +}