Finding the first primitive root of a number over 100,000,000 - java

Here is my code:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import java.security.SecureRandom;
public class Solution {
static BigDecimal result;
static Double y = 0.0;
static int o;
static int[] factors = new int[1];
static int current = 0;
public static void main(String[] args) {
Scanner a1 = new Scanner(System.in);
int b = a1.nextInt();
o = b;
result = new BigDecimal(Integer.valueOf(b));
BigInteger N = new BigInteger(Integer.toString(b - 1));
factor(N);
boolean isPrimitive = true;
for (int i1 = 2; i1 < 10000;i1++) {
isPrimitive = true;
//System.out.println("Enter the value of a large prime no");
BigInteger value = new BigInteger(String.valueOf(o-1));
//System.out.println("\nEnter the value of alpha");
BigInteger checking = new BigInteger(String.valueOf(i1));
BigInteger bigValue = new BigInteger(String.valueOf(o));
for(int i=0;i<factors.length;i++)
{
BigInteger temp = checking.pow(factors[i]);
// System.out.println("checking "+i1+": "+temp+" mod "+o+" = " + (temp.mod(new BigInteger(String.valueOf(o)))));
if ((temp.mod(bigValue)).equals(BigInteger.ONE)) {
isPrimitive = false;
break;
}
}
if(isPrimitive) {
System.out.print(i1+" ");
break;
}
else{
//System.out.println("not primitive roots");
}
}
System.out.println(result.toBigInteger());
}
private final static BigInteger ZERO = new BigInteger("0");
private final static BigInteger ONE = new BigInteger("1");
private final static BigInteger TWO = new BigInteger("2");
private final static SecureRandom random = new SecureRandom();
public static BigInteger rho(BigInteger N) {
BigInteger divisor;
BigInteger c = new BigInteger(N.bitLength(), random);
BigInteger x = new BigInteger(N.bitLength(), random);
BigInteger xx = x;
// check divisibility by 2
if (N.mod(TWO).compareTo(ZERO) == 0) return TWO;
do {
x = x.multiply(x).mod(N).add(c).mod(N);
xx = xx.multiply(xx).mod(N).add(c).mod(N);
xx = xx.multiply(xx).mod(N).add(c).mod(N);
divisor = x.subtract(xx).gcd(N);
} while ((divisor.compareTo(ONE)) == 0);
return divisor;
}
public static void factor(BigInteger N) {
//System.out.println("result = "+result);
if (N.compareTo(ONE) == 0) return;
if (N.isProbablePrime(20)) {
// System.out.println("n = "+N);
if ((N.doubleValue() != (y)) &&N.doubleValue() != (1.0) ) {
// System.out.println("j = "+String.valueOf(1.0 - (1.0/(N.doubleValue()))));
BigDecimal j = new BigDecimal(String.valueOf(1.0 - (1.0/(N.doubleValue()))));
//System.out.println("result = " +result+" * "+j);
result = new BigDecimal(String.valueOf(result.doubleValue() * j.doubleValue()));
//System.out.println(result.multiply(j));
//System.out.println((String.valueOf(1.0 - (1.0/(N.doubleValue())))));
y = N.doubleValue();
if (current == factors.length) {
int[] temp = new int[factors.length+1];
for (int i = 0; i < factors.length;i++) {
temp[i] = factors[i];
}
factors = temp;
}
factors[current] = o/y.intValue();
// System.out.println(o+"/"+y.intValue());
current++;
//System.out.println("result = "+result);
}
return;
}
BigInteger divisor = rho(N);
factor(divisor);
factor(N.divide(divisor));
}
}
I am trying to find the first primitive root of a prime number, then the amount of primitive roots it has. Finding the amount is no problem for any number, but finding the first number is supposed to work for any number up to 1 billion on a certain system for on which other people have been successful. It works for all values up to around a million, but it doesn't work for 999994267. I don't know how I can possibly optimize this further. I have spent maybe 18 hours on this. I honestly can't figure this out. Any suggestions?
Math Explanation:
It takes the factors of the given number o, and tests every number from 2 if it's o/factor[1,2,...] is = 1, if none of o's factors are, it breaks and prints the number.
PS. It is possible, as many other people have done it on the same system.

Ok so thanks to #IgorNikolaev above in the comments of my question I have figured out my problem and solved it. To fully optimize a modPow operation you need to use modular arithmetic.
Here are some links he provided which greatly helped:
en.wikipedia.org/wiki/Modular_arithmetic
en.wikipedia.org/wiki/Modular_exponentiation
And here is the code I wrote based on those links:
private static BigInteger fastModPow(BigInteger base, BigInteger exponent, final BigInteger modulo) {
BigInteger result = BigInteger.ONE;
while (exponent.compareTo(BigInteger.ZERO) > 0) {
if (exponent.testBit(0))
result = (result.multiply(base)).mod(modulo);
exponent = exponent.shiftRight(1);
base = (base.multiply(base)).mod(modulo);
}
return result.mod(modulo);
}
As you will see in the first link, it sort-of "wraps around" to find the mod of a power.
Thanks for everyones help.

Related

How to brute force a math equation in a way that does not slow down an Android app

I am building a math game for Android using Java. It includes a 3x3 grid of numbers that the user has to solve using mathematical operations. Before the start of the game, three random numbers 1-6 are rolled.
However, during my testing, I have discovered that some of the numbers are not solvable, say 4, with 1, 1, 1. (These numbers would never be rolled, but you get the point.)
I am using MxParser to find if the generated equation is correct, but the help I need is on how to create valid math equations.
I have decided to take the brute-force approach, but I am unsure as how to create valid mathematical equations with that method. It would have to generate equations like:
(Our numbers are: 1, 2, 3)
12^03^0 = 1 (True) Next number #1
12^03^0 = 2 (True) Next number #2
12^23^2 = 13 (False) Try again. #3
And so on.
I have tried brute-forcing already, but am unsure exactly how to do so.
`
import org.mariuszgromada.math.mxparser.Expression;
import java.util.ArrayList;
public class GridParser {
public String num1String = "";
public String num2String = "";
public String num3String = "";
private static String l;
private static String q;
private static String a;
private static int p;
private static char[] w;
private static char[] c;
public void parseGrid(int num1, int num2, int num3, int gridID) {
num1String = String.valueOf(num1);
num2String = String.valueOf(num2);
num3String = String.valueOf(num3);
String operator1 = "+";
String operator2 = "-";
String operator3 = "/";
String operator4 = "*";
String operator5 = "^";
ArrayList solutions3x3 = new ArrayList();
ArrayList solutions4x4 = new ArrayList();
ArrayList solutions6x6 = new ArrayList();
String currentSolution = "";
double NumberOnGrid = 0.0;
int currentPOS = 0;
if (gridID == 3) {
NumberOnGrid = 3.0;
String l = "1234567890-()=+√*/^";
q = "";
p = 0;
w = a.toCharArray();
c = l.toCharArray();
while (!q.equals(a)) {
for (int i = 0; i < l.length(); i++) {
System.out.println("[❕] Trying: " + c[i]);
if (c[i] == w[p]) {
q += c[i];
p++;
System.out.println("[✔️] Found: " + c[i]);
Expression targetExpression = new Expression(q);
double expressonResult = targetExpression.calculate();
if(expressonResult == NumberOnGrid){
}
}
if (q.equals(a)) {
System.out.println("\n[✔️] Equation Found!");
}
}
}
}
}
}
I apologize for my code, it is still in "Rough Draft" state. =)
Additionally, it would be great if this could run on a background thread so it would not slow down my Android app.
Thanks
Someone PLZZZ help!

Find amount of happy numbers in a given range

I need to find all happy numbers in a given range (input)
A happy number is a number which eventually reaches 1 when replaced by the sum of the square of each digit. 13 is a happy number because 1^2 + 3^2 = 10 And 1^2 + 0^2 = 1, thus 13 is a happy number.
So far I have this:
import java.util.HashSet;
import java.util.Set;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String wrd = scan.nextLine().trim();
String wrd2 = scan.nextLine().trim();
int nieuwnummer = Integer.parseInt(wrd);
int nieuwnummer2 = Integer.parseInt(wrd2);
// int count = 0
Set<Integer> numbers = new HashSet<Integer>();
for (int i = nieuwnummer; i <= nieuwnummer2; i++) { while(nieuwnummer>0) {
nieuwnummer2 += (nieuwnummer % 10)*(nieuwnummer % 10);
nieuwnummer /=10; };
}
nieuwnummer = nieuwnummer2;
}
//System.out.println(count)
}
I think the range isn't working yet and I need a way to actually count the happy number. Please help :)
Here is some working example.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String st1 = scan.nextLine().trim();
String st2 = scan.nextLine().trim();
int min = Integer.parseInt(st1);
int max = Integer.parseInt(st2);
Set<Integer> happyNumbers = getHappyNumbers(min, max);
System.out.println(happyNumbers.size());
}
public static Set<Integer> getHappyNumbers(int min, int max) {
Set<Integer> out = new HashSet<>();
for (int i = min; i < max; i++) {
if (isHappy(i)) {
out.add(i);
}
}
return out;
}
private static boolean isHappy(int i) {
int sum = 0;
while (i != 0) {
sum += Math.pow((i % 10), 2);
i /= 10;
}
if (sum == 1) return true;
else if (sum >= 10) {return isHappy(sum);}
else return false;
}
}
I don't know if I understand you correctly but:
You have while(nieuwnummer > 0) which is some number on start but after first loop it is changing to 0 [ eg. if range is from 1 to 16] so it will go one time and then skip.
For that kind of problem I would use something like this:
https://www.geeksforgeeks.org/lucky-numbers/
and iterate over the loop

Converting decimal to fraction

I have a method that is converting a decimal (double value) into a fraction and putting the numerator and denominator values into an int[] of size 2.
Testing it works out fine for most values except when I hit 0.0001. Then the return value is 1.0/1.0.
The method:
private static int[] toFractionPos(double x){
String[] parts = Double.toString(x).split("\\.");
double den = Math.pow(10, parts[1].length()); //denominator
double num = Double.parseDouble(parts[0]) * den + Double.parseDouble(parts[1]); //numerator
return reduceFraction((int)num, (int)den);
}
reduceFraction() method:
public static int[] reduceFraction(int num, int den){
int gcf = GCF(num, den); //greatest common factor
int[] rf = {num/gcf, den/gcf};
return rf;
}
Thanks!
The algorithm seems fine. However, using double is not suitable for this kind of problem, because precision decreases as the scale grows.
You should use BigDecimal and BigInteger instead. I've roughly modified your example so that it works with them, but I haven't taken care of details, i.e. parsing the String shouldn't be necessary since scale can be retrieved from a BigDecimal with a getter, you can configure different rounding modes, etc:
import java.math.BigDecimal;
import java.math.BigInteger;
public class Sample {
static int[] toFractionPos(BigDecimal x) {
String[] parts = x.toString().split("\\.");
BigDecimal den = BigDecimal.TEN.pow(parts[1].length()); // denominator
BigDecimal num = (new BigDecimal(parts[0]).multiply(den)).add(new BigDecimal(parts[1])); // numerator
return reduceFraction(num.intValue(), den.intValue());
}
static int[] reduceFraction(int num, int den) {
int gcd = BigInteger.valueOf(num).gcd(BigInteger.valueOf(den)).intValue(); // greatest
// common
// divisor
int[] rf = { num / gcd, den / gcd };
return rf;
}
public static void main(String[] args) {
int[] fraction = toFractionPos(new BigDecimal("0.0001"));
System.out.println(fraction[0] + "/" + fraction[1]); // 1/10000
}
}
Note: optimizations left as an excercise ;)
You shouldn't work with doubles as you are losing precision and this can lead to serious errors. But in the case of 1.0001 the problem is that:
Double.toString(1.0001) == "1.0E-4"
Then you try to parse "0E-4" and you get 0 instead of 1. You could do the following if you expect at most 10 decimal points:
DecimalFormat df = new DecimalFormat("0",
DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(10);
String[] parts = df.format(x).split("\\.");
How about this?
private static int[] toFractionPos(double x){
int den = (int)Math.pow(10,(int)Math.log10(Integer.MAX_VALUE));
int num = (int)(x*den);
return reduceFraction(num, den);//this came from your code
}
I think this will work,
public int[] Fraction(double n) {
BigDecimal p = BigDecimal.ONE;
BigDecimal dn = BigDecimal.valueOf(n);
while(true){
dn = dn.multiply(p);
if( dn.compareTo(new BigDecimal(dn.toBigInteger()))==0 )
break;
else
p = p.multiply(BigDecimal.TEN);
}
BigInteger num=dn.toBigInteger(), den=p.toBigInteger(), g=num.gcd(den);
num = num.divide(g);
den = den.divide(g);
int[] res = new int[2];
res[0] = num.intValue();
res[0] = den.intValue();
return res;
}

Recursive function not working java

I am trying to find out 2 to the power n. I used recursive function for this.
My Code:
class TwoPowerN
{
static BigInteger twoPowern(BigInteger x, long y)
{
BigInteger temp = new BigInteger("1");
if( y == 0)
return new BigInteger("1");
temp.equals(twoPowern(x, y/2));
if (y%2 == 0)
return temp.multiply(temp);
else
return x.multiply(temp.multiply(temp));
}
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int t = Integer.parseInt(br.readLine());
while(t>0)
{
long r = Long.parseLong(br.readLine());
BigInteger a = new BigInteger("2");
BigInteger ans=twoPowern(a,r);
pw.println(ans);
t--;
}
pw.close();
}
}
But I don't get the required result.
For cases 1 2 3 4 5 I am getting 2 1 2 1 2. A similar program(using similar function but with int) in 'C' works fine.
Can anyone explain what is the mistake?
I think that you need to assign the recursive result, rather than test for equality:
temp.equals(twoPowern(x, y/2)); // This is checking for equality
Should be
temp = twoPowern(x, y/2); // This is assigning the value
temp.equals(twoPowern(x, y/2));
is a conditional statement in java, not an assignment, so you aren't
storing the recursive value.
This is a lot simpler:
public class power2 {
public static long power2( int power)
{
if(power <= 0)
return 1;
return 2 * power2(power-1);
}
static BigInteger twoPowern(long y)
{
if( y == 0) {
return BigInteger.ONE;
}
return new BigInteger("2").multiply(twoPowern(y-1));
}
public static void main(String[] args)
{
for(int i = 0; i < 10; i++)
{
System.out.println("2^" + i + "," + power2(i));
System.out.println("2^" + i + "," + twoPowern(i));
}
}
}
Using regular longs, or BigInteger.

Java: Summing all digits of 2^1000

I'm trying to solve Project Euler problem #16, where I need to sum all the digits of 2^1000. I've gotten stuck dealing with such a big number. My program worked for any number below 10^16, but failed afterwards. This told me that my logic was correct. I went ahead and converted all variables and methods to BigDecimal, but now the program does not run properly. It compiles as it is and there is no error; it just does not terminate. Does anyone have an idea on where I went wrong here?
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Powerdigitsum {
private static final BigDecimal one = new BigDecimal("1");
private static final BigDecimal ten = new BigDecimal("10");
private static BigDecimal sumofDigits(BigDecimal n){
BigDecimal sum = new BigDecimal("0");
while(n.compareTo(one) == 1 || n.compareTo(one) == 0){
sum.add(n.remainder(ten));
n.divide(ten);
n = n.setScale(0, RoundingMode.FLOOR);
}
return sum;
}
public static void main(String[] args) {
final double the_number = Math.pow(2,1000);
final double test = 15;
final BigDecimal two_to_the_thousandth_power = new BigDecimal(test);
System.out.println(sumofDigits(two_to_the_thousandth_power));
}
}
Just use BigInteger properly:
BigInteger a = new BigInteger("2").pow(1000);
The whole method is kinda wrong. See this:
private static BigInteger sumOfDigits(BigInteger n) {
BigInteger sum = BigInteger.ZERO;
while (n.compareTo(BigInteger.ZERO) == 1) {
sum = sum.add(n.remainder(ten));
n = n.divide(ten);
}
return sum;
}
You needed to compare to zero, not one. And you need to assign the values for BigIntegers and BigDecimals, their methods do nothing on their own, the instances of those classes are immutable.
For integers, it's generally better to use BigInteger. The decimal part (that gets there from dividing) is just thrown away.
final double the_number = Math.pow(2,1000);
This won't work because the_number is not large enought to take the result. You need to convert the pow call to BigInteger:
BigInteger result = new BigInteger("2").pow(1000);
But be aware.. this can take some time..
Don't use the BigDecimal(double) constructor: it is limited by the double primitive type, which cannot represent 2^1000.
You can use a BigInteger. Something along these lines should work (probably suboptimal, but...):
public static void main(final String... args)
{
// 2^1000
final BigInteger oneTo2000 = BigInteger.ONE.shiftLeft(1000);
BigInteger digitSum = BigInteger.ZERO;
// We don't want to split against the empty string, the first element would be ""
for (final String digit: oneTo2000.toString().split("(?<=.)"))
digitSum = digitSum.add(new BigInteger(digit));
System.out.println(digitSum);
}
public class SumofDigitsPow {
public static void main(String[] args) {
//2(2^1000)
String temp = BigInteger.ONE.shiftLeft(1000).toString();
int sum = 0;
for(int i=0;i<temp.length();i++){
sum+= temp.charAt(i) - '0';
}
System.out.println(Integer.toString(sum));
}
}
java.math.BigInteger.shiftLeft(int n) method returns a BigInteger whose value is (this << n),So you can get the answer by using BigInteger and LeftShift Method
import java.math.BigInteger;
public class Problem16 {
public static void main(String[] args) {
BigInteger number2 = new BigInteger("2");
BigInteger number3 = new BigInteger("0");
number3 =number2.pow(1000);
String str = number3.toString();
BigInteger sum = new BigInteger("0");
for(int i=0; i<str.length(); i++)
{
char c= str.charAt(i);
int value = Character.getNumericValue(c);
BigInteger value2 = new BigInteger(Integer.toString(value));
sum =sum.add(value2) ;
}
System.out.println(sum);
}
}
IF YOU THINK BIGINTEGER IS CHEATING AND/OR don't feel like using it/learning how to use it, this algorithm is the way to go.
Think about how you would calculate 2^1000 by hand. You'd start with 2^1 and multiply by two repeatedly. Now notice that the number of digits of powers of two increase by 1 for AT LEAST every 3 powers (could be after 4 powers like with 1024 to 8192). So make a jagged 2D array like this
int a[][]= new int[1000][];
for(int i=0;i<1000;i++)
{
a[i]= new int[1+(i/3)];
}
Then initialize a[0][0] to 2. After this, you want to write a for loop such that each row is filled from the rightmost spot. So make two variables "digit" and "carry". Digit is the number that you will input into the row you're working on, and the carry is the one you're going to take to the next calculation and add to the product of 2 and whatever digit you're multiplying it with. Be careful with the order you update digit and carry and reinitialize them to zero after every calculation. I think the hardest part is coming up with the limits for the for loop, so that it fits with the every 3 powers thing. You can make this simpler by just making a triangular jagged array that increments by one every row. I did it like this though. Here's my whole code.
import java.util.*;
public class ProjectEuler16
{
public static void main(String[] args)
{
long t1=System.currentTimeMillis();
ProjectEuler16 obj = new ProjectEuler16();
System.out.println(obj.bigNumHandler());
long t2= System.currentTimeMillis();
System.out.println(t2-t1);
}
int bigNumHandler()
{
int a[][] = new int[1000][];
for(int i=0;i<1000;i++)
{
a[i]= new int[1+(i/3)];
}
a[0][0]=2;
for(int i=1;i<1000;i++)
{
int carry=0;
int digit=0;
int f=0;
if(i%3==0)
{
f=1;
}
for(int j=a[i-1].length-1+f;j>=0;j--)
{
if(j==0&f==1)
{
a[i][0]=carry;
}
else
{
digit=((2*a[i-1][j-f])+carry)%10;
carry=((2*a[i-1][j-f])+carry)/10;
a[i][j]=digit;
}
}
}
int sum=0;
for(int k=0;k<a[999].length;k++)
{
sum=sum+a[999][k];
}
return sum;
}
}
Note that the last row lists the digits for 2^1000.I think you can figure out how to sum the digits. The program took about 5 seconds to come up with the answer.
solution::::
import java.math.BigInteger;
public class PR9 {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BigInteger zero=BigInteger.valueOf(0);
BigInteger ten=BigInteger.valueOf(10);
BigInteger sum=zero;
BigInteger a = new BigInteger("2").pow(1000);
while(a.compareTo(zero)>0){
sum=sum.add(a.mod(ten));
a=a.divide(ten);
}
System.out.println(sum);
}
}
output:::::
1366
import java.math.BigInteger;
public class P16 {
public static BigInteger digitSum(int n) {
BigInteger sum = BigInteger.ZERO;
BigInteger number = new BigInteger("2").pow(n);
while (number.compareTo(BigInteger.ZERO) == 1) {
BigInteger remainder = number.remainder(BigInteger.TEN);
sum = sum.add(remainder);
number = number.divide(BigInteger.TEN);
}
return sum;
}
public static void main(String[] args) {
final double START = System.nanoTime();
System.out.println(digitSum(Integer.parseInt(args[0])));
final double DURATION = System.nanoTime() - START;
System.out.println("Duration: " + DURATION / 1000000 + "ms.");
}
}
While there maybe a way of solving this problem without the use of BigIntegers, it is clear that they make the code run way faster.
Mine only took about 4ms to find an answer.

Categories

Resources