Project Euler #23 in Java - java

I've spent quite a while working on Problem #23 on Project Euler.
The answer the program below gives me is 4190428, and I can't figure out why.
I think it's probably a one or two character mistake somewhere.
public long problem23() {
ArrayList<Integer> abundantNumbers = new ArrayList<Integer>();
int limit = 28123;
for(int i = 2; i < limit; i++) {
if(isAbundantNum(i)) {
abundantNumbers.add(i);
}
}
boolean [] abundantSum = new boolean [limit+1];
for(int a = 0; a < abundantNumbers.size(); a++) {
for(int b = 1; b < abundantNumbers.size(); b++) {
int temp = abundantNumbers.get(a) + abundantNumbers.get(b);
if(temp <= limit) {
abundantSum[temp] = true;
} else {
break;
}
}
}
long sum = 0;
for(int i = 1; i <= limit; i++) {
if(!abundantSum[i]) {
sum += i;
}
}
return sum;
}
public boolean isAbundantNum(int n) {
int factorSum = 1;
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
if(factorSum > n) {
System.out.println(n);
return true;
}
return false;
}
Edit: Added isAbundantNum(int n) method.

You have 2 bugs...
for(int b = 1; b < abundantNumbers.size(); b++) {
'b' should start at zero not 1
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
Factoring like that gives you duplicates (like 2*2 = 4, you're getting both 2s).
Try something like:
for(int i = 2; i < n; i++) {
if(n%i == 0) {
factorSum += i;
}
}

Here is another implementation:
import java.util.ArrayList;
import java.util.List;
public class P23 {
final static int MIN = 12;
final static int MAX = 28123;
static boolean numbers[] = new boolean[MAX+1];
static List<Integer> abundantNumbers = new ArrayList();
public static void main(String args[]) {
generateAbundants(MIN, MAX);
int size = abundantNumbers.size();
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
int current = abundantNumbers.get(i) + abundantNumbers.get(j);
if (current <= MAX) {
numbers[current] = true;
} else {
break;
}
}
}
long sum = 0;
for (int i = 1 ; i <= MAX ; i++ ) {
if ( numbers[i] == false ) {
sum += i;
}
}
System.out.println(sum);
}
private static int sumOfProperDivisors(int x) {
int sum = 1;
int squareRoot = (int) Math.sqrt(x);
for (int i = 2; i <= squareRoot; i++) {
if (x % i == 0) {
sum += i;
sum += x / i;
}
}
// if x is a perfect square, it's square root was added twice
if (squareRoot * squareRoot == x) {
sum -= squareRoot;
}
return sum;
}
private static boolean isAbundant(int x) {
if (x < sumOfProperDivisors(x)) {
return true;
}
return false;
}
private static void generateAbundants(int min, int max) {
for (int i = min; i < max; i++) {
if (isAbundant(i)) {
abundantNumbers.add(i);
}
}
}
}
Time: 455 ms
Explanation:
The default value for j is i. You can take j = 0 ( as Ted Bigham said -> b in that case ), because it will work, but it will take into consideration every number twice ( 12+20 = 20+12 ). It's more efficient to start from i. Why isn't it good to start from 1? Because you can loose solutions: in my example 24 = 12 + 12.
Regarding the for loop containing the divisors part, you can use the approach containing sqrt because it's more efficient ( O(sqrt(n)) instead of O(n) ), but you have to adjust it. In my example you can see that I have <= squareRoot because if I don't use =, it will skip some values ( E.g.: 6 is divisor for 36, but you don't include it in your solution ). Because I counted 6 twice, I remove one of those roots. Of course that Ted's method is good, but sometimes it's better to have an improved performance, even if the simplicity is affected.

Related

Scramble each digit of the int a and print out the biggest possible integer

I’m stuck here. Do I just keep making new strings and turn them to int or us there a faster better way?
public void biggest(int a){
int random;
String aS = String.valueOf(a);
int ah=9;
if (a<10)
System.out.println(a);
for(int i= 0;i<aS.length();i++){
String firstNum = aS.substring(i,i+1);
for (int j = ah; j > Integer.parseInt(firstNum); j--){
System.out.println(ah);
}
}
} ```
public static int biggest(int num) {
if (num == 0)
return 0;
int res = 0;
if (num > 0) {
for (int i = 9; i >= 0; i--)
res = update(res, i, num);
} else {
for (int i = 0; i <= 9; i++)
res = update(res, i, num);
res *= -1;
}
return res;
}
private static int update(int res, int i, int n) {
n = Math.abs(n);
while (n > 0) {
if (n % 10 == i)
res = res * 10 + i;
n /= 10;
}
return res;
}
Output:
System.out.println(biggest(12341234)); // 44332211
System.out.println(biggest(-12341234)); // -11223344
There's no need to use conversion to String in this case, you can get the digits from the input number by getting a remainder by modulo 10, then dividing the input number by 10 and repeat it while the number > 0.
Each digit should be stored in an array or list.
To get the biggest number of these digits you should just sort them (standard facilities such as Arrays.sort or Collections.sort will do fine) and then "re-assemble" the biggest number from the lowest digit by multiplying it by 1, 10, 100, etc. and summing up.
So, plain implementation could be as follows:
public static int biggestPlain(int a) {
List<Integer> digits = new ArrayList<>();
while (a > 0) {
digits.add(a % 10);
a /= 10;
}
Collections.sort(digits);
int p = 1;
int num = 0;
for (int digit : digits) {
num += p * digit;
p *= 10;
}
return num;
}
Also, this task can be implemented using Stream API and lambda and applying the same approach:
public static int biggestStream(int a) {
AtomicInteger p = new AtomicInteger(1); // accumulate powers of 10
return IntStream.iterate(a, n -> n > 0, n -> n / 10) // divide input number by 10 while it > 0
.map(i -> (i % 10)) // get the digit
.sorted() // sort (the lower digits first)
.map(i -> p.getAndUpdate((x) -> x * 10) * i) // same as p * digit above
.sum(); // get the result number
}
Update
Iterate over digits from '9' till '0' and check if they are available in the string presentation of the input number.
String-based solution:
public static void biggest(int a) {
String aS = String.valueOf(a);
if (a < 10) {
System.out.println(a);
}
String num = "";
int count = 0;
out: for (char i = '9'; i >= '0'; i--) {
for (int j = 0; j < aS.length(); j++) {
char digit = aS.charAt(j);
if (digit == i) {
num += digit;
if (++count == aS.length()) {
break out;
}
}
}
}
System.out.println(num + " / " + Integer.parseInt(num));
}
Another option would be to count how many 0, 1, 2, ..., 9 values you have and then assemble them back together into a number knowing the digits will always be in descending order (9, 8, 7, ..., 0). The easy way to do this is with an array. Since this is a homework assignment the hard way (without using an array as per the requirement you added in a comment) is to use a variable counter per digit.
public class so64125767 {
public static int biggestBuckets(int a) {
int[] buckets = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
while (a > 0) {
buckets[a % 10]++;
a /= 10;
}
int num = 0;
for (int i = 9; i >= 0; i--) {
for (int j = 0; j < buckets[i]; j++) {
num *= 10;
num += i;
}
}
return num;
}
public static int biggestBucketsVar(int a) {
int zero = 0;
int one = 0;
int two = 0;
int three = 0;
int four = 0;
int five = 0;
int six = 0;
int seven = 0;
int eight = 0;
int nine = 0;
while (a > 0) {
switch (a % 10) {
case 0:
zero++;
break;
case 1:
one++;
break;
case 2:
two++;
break;
case 3:
three++;
break;
case 4:
four++;
break;
case 5:
five++;
break;
case 6:
six++;
break;
case 7:
seven++;
break;
case 8:
eight++;
break;
case 9:
nine++;
break;
}
a /= 10;
}
int num = 0;
for (int j = 0; j < nine; j++) {
num *= 10;
num += 9;
}
for (int j = 0; j < eight; j++) {
num *= 10;
num += 8;
}
for (int j = 0; j < seven; j++) {
num *= 10;
num += 7;
}
for (int j = 0; j < six; j++) {
num *= 10;
num += 6;
}
for (int j = 0; j < five; j++) {
num *= 10;
num += 5;
}
for (int j = 0; j < four; j++) {
num *= 10;
num += 4;
}
for (int j = 0; j < three; j++) {
num *= 10;
num += 3;
}
for (int j = 0; j < two; j++) {
num *= 10;
num += 2;
}
for (int j = 0; j < one; j++) {
num *= 10;
num += 1;
}
for (int j = 0; j < zero; j++) {
num *= 10;
// num += 0;
}
return num;
}
public static void main(String[] args) {
System.out.println(biggestBuckets(237428379));
System.out.println(biggestBucketsVar(237428379));
-- 987743322
}
}
I'm also going to bet if you benchmark these results along with the other suggestions (using String or Collections) you'll find this method scales the best (imagine if you accepted numbers beyond the size of an int).
String useMe = Integer.toString(argumentOne);
int rMe = argumentOne;
int x = 0;
while (x != 1000) {
int i = 0;
String returnMe = "";
String inUse = useMe;
while (i != useMe.length()) {
Random random = new Random();
int index = random.nextInt(inUse.length());
returnMe = returnMe + inUse.charAt(index);
inUse = inUse.substring(0, index) + inUse.substring(index + 1);
i++;
}
if (Integer.parseInt(returnMe) > rMe) {
rMe = Integer.parseInt(returnMe);
}
x++;
}
System.out.print( rMe );
}

"WAP a program to find prime numbers between between zero and 100"

I typed this piece of code for finding all the prime numbers between 0 and 100, but it gives output with multiples of other numbers. How can I rectify this?
public class PrimeNumbers {
public static void main(String[] args) {
int count = 0;
int n = 0;
for (n = 2; count <= 100; n++) {
for (int j = 2; j < n; j++) {
while (n % j == 0) {
j = 2;
n++;
}
}
count++;
System.out.println(n);
}
}
}
Make sure to read the other answers and understand the issue in your code. The error can be fixed with some minor changes:
public class PrimeNumbers{
public static void main(String[] args) {
for (int n = 2; n <= 100; n++) {
boolean isPrime = true;
for (int j = 2; j < n; j++) {
if (n % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
System.out.println(n);
}
}
}
}

Java: Sudoku- increase number of empty spaces causes my code to throw an exception

I'm trying to make a Sudoku game for my project but if i increase the number of empty spaces in the Sudoku Grid the code just throws an exception arrayoutofbounds but can't figure out where it's coming from. k is the number of empty spaces in the grid.
I haven't tried anything because can't figure out what can be done at this kind of problem
Here is the code:
package sudoku.puzzle;
import java.util.*;
public class SudokuPuzzle {
int[] mat[];
int N; // number of columns/rows.
int SRN; // square root of N
int K; // No. Of missing digits
// Constructor
SudokuPuzzle(int N, int K) {
this.N = N;
this.K = K;
// Compute square root of N
Double SRNd = Math.sqrt(N);
SRN = SRNd.intValue();
mat = new int[N][N];
}
// Driver code
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Select Level Of Difficulty \n 1.Easy\n 2.Medium\n 3.Hard");
String Choice = in .next(); in .close();
if ("1".equals(Choice) || "Easy".equals(Choice) || "easy".equals(Choice) || "e".equals(Choice) || "E".equals(Choice)) {
int N = 9, K = 40;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("2".equals(Choice) || "Medium".equals(Choice) || "medium".equals(Choice) || "m".equals(Choice) || "M".equals(Choice)) {
int N = 9, K = 60;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("3".equals(Choice) || "Hard".equals(Choice) || "hard".equals(Choice) || "h".equals(Choice) || "H".equals(Choice)) {
int N = 9, K = 72;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
}
// Sudoku Generator
public void fillValues() {
// Fill the diagonal of SRN x SRN matrices
fillDiagonal();
// Fill remaining blocks
fillRemaining(0, SRN);
// Remove Randomly K digits to make game
removeKDigits();
}
// Fill the diagonal SRN number of SRN x SRN matrices
void fillDiagonal() {
for (int i = 0; i < N; i = i + SRN)
// for diagonal box, start coordinates->i==j
fillBox(i, i);
}
// Returns false if given 3 x 3 block contains num.
boolean unUsedInBox(int rowStart, int colStart, int num) {
for (int i = 0; i < SRN; i++)
for (int j = 0; j < SRN; j++)
if (mat[rowStart + i][colStart + j] == num)
return false;
return true;
}
// Fill a 3 x 3 matrix.
void fillBox(int row, int col) {
int num;
for (int i = 0; i < SRN; i++) {
for (int j = 0; j < SRN; j++) {
do {
num = randomGenerator(N);
}
while (!unUsedInBox(row, col, num));
mat[row + i][col + j] = num;
}
}
}
// Random generator
int randomGenerator(int num) {
return (int) Math.floor((Math.random() * num + 1));
}
// Check if safe to put in cell
boolean CheckIfSafe(int i, int j, int num) {
return (unUsedInRow(i, num) &&
unUsedInCol(j, num) &&
unUsedInBox(i - i % SRN, j - j % SRN, num));
}
// check in the row for existence
boolean unUsedInRow(int i, int num) {
for (int j = 0; j < N; j++)
if (mat[i][j] == num)
return false;
return true;
}
// check in the row for existence
boolean unUsedInCol(int j, int num) {
for (int i = 0; i < N; i++)
if (mat[i][j] == num)
return false;
return true;
}
// A recursive function to fill remaining
// matrix
boolean fillRemaining(int i, int j) {
// System.out.println(i+" "+j);
if (j >= N && i < N - 1) {
i = i + 1;
j = 0;
}
if (i >= N && j >= N)
return true;
if (i < SRN) {
if (j < SRN)
j = SRN;
} else if (i < N - SRN) {
if (j == (int)(i / SRN) * SRN)
j = j + SRN;
} else {
if (j == N - SRN) {
i = i + 1;
j = 0;
if (i >= N)
return true;
}
}
for (int num = 1; num <= N; num++) {
if (CheckIfSafe(i, j, num)) {
mat[i][j] = num;
if (fillRemaining(i, j + 1))
return true;
mat[i][j] = 0;
}
}
return false;
}
// Remove the K no. of digits to
// complete game
public void removeKDigits() {
int count = K;
while (count != 0) {
int cellId = randomGenerator(N * N);
// System.out.println(cellId);
// extract coordinates i and j
int i = (cellId / N);
int j = cellId % 9;
if (j != 0)
j = j - 1;
// System.out.println(i+" "+j);
if (mat[i][j] != 0) {
count--;
mat[i][j] = 0;
}
}
}
// Print sudoku
public void printSudoku() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
System.out.print(mat[i][j] + " ");
System.out.println();
}
System.out.println();
}
}
What you got is probably a ArrayIndexOutOfBoundsException. That means at some point you try to access a field of an array outside its boundaries.
But I can´t see where K could be responsible for that. Can you provide more information about the error? E.g. at which value you get it or in which line.
EDIT: The variable i int the removeKDigits() function exceeds the boundaries of the array if the random generator spits out the value 81.

Prime Numbers: What is wrong in my code? It works fine for till int limits as I go for long the code is taking a lot time

public class PrimeNumbers {
public static void main(String[] args) {
int i = 1000000000;
int m=2;
int n=1;
for (int j = 2; j < i; j++) {
int l=0;
if(j%25==0)
{
if(j%100==0)
{
m++;
}
if(j%1000==0)
{
m++;
}
m++;
}
if (j % 2 != 0) {
for (int k = 2; k < j/m; k++) {
if (j % k == 0) {
l++;
}
}
if (l < 1) {
n++;
}
if(n==1001)
{
System.out.print(j);
}
}
}
}
}
It works fine for numbers till ~100 million but as I'm going for larger numbers the result is inconsistent. I've seen the algorithms for prime numbers, just thought of trying.
int's are limited to represent numbers to approx. 2.1 billion. Past that the integer will begin to wrap around. Use the long data type instead and you will be able to go much higher.
I dont know what you are trying to do exactly, but what i judge you want to identify the prime numbers until the number you have specified... if this is what you need, here is the code:
public class PrimeNumbers {
public static void main(String[] args) {
int number = 20000;
int i = 1;
int j = 0;
while (i <= number) {
j = 1;
int counter = 0;
while (j <= i){
int divide = i / j;
if (i % j == 0){
counter++;
}
j++;
}
if (counter <= 2) {
System.out.print(i + " ");
}
i++;
}
}
}

Prime numbers calculator takes too much time (JAVA)

When I run this code to find sum of prime numbers below 20 it works fine, but when try to find sum below 2500000 it takes too much time. It's been at least 20 minutes and it's still running. It seems like it's not working. How do I fix it?
class PrimeSummation {
public static void main(String[] args) {
int sum = 0;
for(int i = 1; i < 2500000; i++) {
int count = 0;
for(int j = 1; j < i + 1; j++) {
if((i%j) == 0) {
count++;
}
}
if(count == 2) {
sum += i;
}
}
System.out.println(sum);
}
}
sum cannot be an int because the answer is 219697708195 whereas Integer.MAX_VALUE is only 2147483647. You must use a long or a BigInteger instead.
Your algorithm is very slow, because for every one of the 2500000 numbers you are starting from scratch to decide whether it is prime or not, and your approach for testing whether a number is prime (try every possible factor) is not very efficient.
The following code produces the answer in about a tenth of a second on my machine.
int num = 2500000;
long sum = 0;
boolean[] arr = new boolean[num];
for (int p = 2; p < num; p++) {
if (!arr[p]) {
sum += p;
for (int k = p * 2; k < num; k += p)
arr[k] = true;
}
}
System.out.println(sum);
Keeping track of previously found primes seems to help:
BigInteger sum = BigInteger.ZERO;
List<Integer> primes = new ArrayList<>();
for(int i = 2; i < 2500000; i++) {
boolean isPrime = true;
for(int j = 0; j < primes.size() && primes.get(j)<= Math.sqrt(i); j++) {
int p = primes.get(j);
if((i%p) == 0) {
isPrime=false;
break;
}
}
if(isPrime) {
sum = sum.add(BigInteger.valueOf(i));
primes.add(i);
}
}
System.out.println(sum);
Came up with answer:
219697708195
If you want better performance for generating a large number prime number, you should use Sieve formula.
You can Learn Sieve_of_Eratosthenes formula for prime number generation.
According to Sieve_of_Eratosthenes:
import java.util.*;
public class Sieve
{
private BitSet sieve;
private Sieve() {}
private Sieve(int size) {
sieve = new BitSet((size+1)/2);
}
private boolean is_composite(int k)
{
assert k >= 3 && (k % 2) == 1;
return sieve.get((k-3)/2);
}
private void set_composite(int k)
{
assert k >= 3 && (k % 2) == 1;
sieve.set((k-3)/2);
}
public static List<Integer> sieve_of_eratosthenes(int max)
{
Sieve sieve = new Sieve(max + 1); // +1 to include max itself
for (int i = 3; i*i <= max; i += 2) {
if (sieve.is_composite(i))
continue;
// We increment by 2*i to skip even multiples of i
for (int multiple_i = i*i; multiple_i <= max; multiple_i += 2*i)
sieve.set_composite(multiple_i);
}
List<Integer> primes = new ArrayList<Integer>();
primes.add(2);
for (int i = 3; i <= max; i += 2)
if (!sieve.is_composite(i))
primes.add(i);
return primes;
}
}
Performance:

Categories