diff --git a/src/main/java/com/thealgorithms/others/ShorAlgorithm.java b/src/main/java/com/thealgorithms/others/ShorAlgorithm.java new file mode 100644 index 000000000000..fdc6ae7a62e4 --- /dev/null +++ b/src/main/java/com/thealgorithms/others/ShorAlgorithm.java @@ -0,0 +1,57 @@ +package com.thealgorithms.others; + +import java.math.BigInteger; +import java.util.Random; + +// The algorithm is referred from +// https://www.geeksforgeeks.org/shors-factorization-algorithm/ +public class ShorAlgorithm { + // trying to find the order of exponent given the base and the number + private int exponent(BigInteger base, BigInteger number) { + BigInteger result = BigInteger.ONE; + int increment = 0; + while (!result.equals(BigInteger.ONE) || increment == 0) { + result = result.multiply(base).mod(number); + increment++; + } + return increment; + } + + // implementing the shor algorithm + public BigInteger[] shorAlgorithm(BigInteger number) { + if (number.mod(new BigInteger("2")).equals(BigInteger.ZERO)) { + BigInteger p = number.divide(new BigInteger("2")); + BigInteger q = new BigInteger("2"); + return new BigInteger[] {p, q}; + } + + Random random = new Random(); + BigInteger base = BigInteger.ZERO; + do { + base = new BigInteger(number.bitLength(), random); + } while (base.compareTo(BigInteger.ZERO) <= 0 || base.compareTo(number) >= 0); + + BigInteger hcf = base.gcd(number); + if (hcf.compareTo(BigInteger.ONE) > 0) { + return new BigInteger[] {hcf, number.divide(hcf)}; + } + + int result = exponent(base, number); + if (result % 2 != 0) { + return null; + } + + BigInteger congruentResult = base.modPow(BigInteger.valueOf(result / 2), number); + if (congruentResult.equals(number.subtract(BigInteger.ONE))) { + return null; + } + + BigInteger p = congruentResult.add(BigInteger.ONE).gcd(number); + BigInteger q = congruentResult.subtract(BigInteger.ONE).gcd(number); + + if (!p.equals(BigInteger.ONE) && !q.equals(BigInteger.ONE)) { + return new BigInteger[] {p, q}; + } + return null; + } +} diff --git a/src/test/java/com/thealgorithms/others/ShorAlgorithmTest.java b/src/test/java/com/thealgorithms/others/ShorAlgorithmTest.java new file mode 100644 index 000000000000..47c3cabd5496 --- /dev/null +++ b/src/test/java/com/thealgorithms/others/ShorAlgorithmTest.java @@ -0,0 +1,49 @@ +package com.thealgorithms.others; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.math.BigInteger; +import org.junit.jupiter.api.Test; + +public class ShorAlgorithmTest { + @Test + public void testFactorizationOfEvenNumber() { + ShorAlgorithm shor = new ShorAlgorithm(); + BigInteger number = new BigInteger("15"); + BigInteger[] factors = shor.shorAlgorithm(number); + + assertNotNull(factors, "Factors should not be null for composite numbers."); + assertEquals(2, factors.length, "There should be two factors."); + + BigInteger p = factors[0]; + BigInteger q = factors[1]; + + assertEquals(number, p.multiply(q), "Factors should multiply to the original number."); + } + + @Test + public void testFactorizationOfPrimeNumber() { + ShorAlgorithm shor = new ShorAlgorithm(); + BigInteger number = new BigInteger("13"); + BigInteger[] factors = shor.shorAlgorithm(number); + + assertNull(factors, "Factors should be null for prime numbers."); + } + + @Test + public void testFactorizationOfEvenCompositeNumber() { + ShorAlgorithm shor = new ShorAlgorithm(); + BigInteger number = new BigInteger("20"); + BigInteger[] factors = shor.shorAlgorithm(number); + + assertNotNull(factors, "Factors should not be null for composite numbers."); + assertEquals(2, factors.length, "There should be two factors."); + + BigInteger p = factors[0]; + BigInteger q = factors[1]; + + assertEquals(number, p.multiply(q), "Factors should multiply to the original number."); + } +} \ No newline at end of file