Euler Challenge 1 in Java - I'm doing something wrong? - java

http://projecteuler.net/problem=1
Hey. I'm a high schooler trying to get a good grasp on programming problems, so I visited Project Euler. For Problem 1, I wrote up some code in Java that would of solved it, but something is evidently going wrong. Can I get some insight as to what?
Explanation:
I stop everything at the index value of 332 because Java counts from 0, and 333 * 3 is 999 which is below 1,000. Apples is a seperate class with pretty much the same code, although it counts for 5. At the end, I manually add together the two answers, but it wasn't right. What am I doing wrong?
The two final sums are:
Three: 164838
Five: 97515
public class Learning {
public static void main(String[] args){
int three[] = new int[333];
int counter = 0;
three[332] = 0;
int totalthree = 0;
int threeincrementer = 1;
int grandtotal;
boolean run = true;
boolean runagain = true;
for (counter = 1; counter<=332; counter++){
three[counter] = 3 * counter;
if (!(three[332] == 0)){
System.out.println("Finished three.");
while (run == true){
totalthree = totalthree + three[threeincrementer];
threeincrementer++;
if (threeincrementer >= 332){
run = false;
System.out.println("Three final is: " + totalthree);
}
}
}
if (runagain == true){
apples ApplesObject = new apples();
ApplesObject.rerun(0);
runagain = false;
}
}
}
}

Some numbers are at the same time multiplication of 3 AND 5 like 15 so you shouldn't separately calculate sum of all multiplications of 3 and multiplications of 5 and than add them because you will end up doing something like
sum3 = 3,6,9,12,15,...
sum5 = 5,10,15,...
so first sum3 will include 15, and sum5 will also include it which means you will add 15 two times. Now to balance your calculations you will need to subtract from your sum3+sum5 sum which will add all multiplications of 15
sum15 = 15,30,45,...
So using your approach your final formula should look like sum3+sum5-sum15.
But simpler solution for this problem can look like
sum = 0
for each X in 1...999
if (X is multiplication of 3) OR (X is multiplication of 5)
add X to sum
To check if some number X is multiplication of number Y you can use modulo operator % (example reminder = X % Y) which finds the remainder of division of one number by another.
You can find more Java operators here

Related

I have a program that calculates the first 200 prime numbers, but I do not understand a formula in it

I need to write a code which should calculate the first 200 prime numbers, but I can't hand it in as long as I can't explain everything. I used a piece of code from the internet as reference (http://crab.rutgers.edu/~dhong/cs325/chapter3/PrimeNumber.java).
Whole code:
public class Opdracht3 {
public static void main(String[] args) {
int limiet = 200;
int counter = 1;
int testpriem = 3;
boolean isPriem;
while (counter <= limiet) {
isPriem = true;
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
if (isPriem) {
System.out.println(counter + ": " + testpriem);
counter++;
}
testpriem++;
}
}
}
Below part of code verifies if the number is a composite. If testpriem is composite, then comes out of the loop and starts over. Otherwise, it continues and prints the prime number testpriem.
The problem is here:
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
I tested what happens to i, and one way or another it recognizes the divisor needed to calculate the composite. (With 4 divisor is 2, with 9 divisor is 3, with 221 divisor is 13) But I am flabbergasted as of why.
Any ideas?.
the % or ("remainder") operator in Java divides one operand by another and returns the remainder as its result. And of course if integer x is evenly divisible by another integer y (meaning x/y = some integer z with a remainder of zero), then x can not be prime.
First remember every number able to divide by its half or less. Consider number 7 it is possible divided by 1,2,3 because after 3, if try to divide number by 4 means 4x2 = 8 that is greater than 7. so it is optimum way to find divisor in this way. One more thing every number divided by 1 and number itself. so if number number is divided by 1 or itself then it is called prime so i starts from 2.
now consider testpriem =7 so you will get loop like
for (int i = 2; i <= 7 / 2(i.e 3); i++)
{
if(7 % i == 0)
{
isPriem = false;
break;
}
so first time it checks 7%2=1 so condition false. again check for 7%3 = 1 again condition false. and now this condition full fills here i <= 7 / 2(i.e 3) so loop stopped and it result 7 number is prime
Well, if testpriem % i == 0, it means that i divides testpriem, which means that testpriem is not a prime a number and i, is its first divider. % is the modulo operation, which is the rest of the division.
https://en.wikipedia.org/wiki/Modulo_operation
The break stops the for loop and moves to the next position in the while loop. So it does not restart the for loop for the current tested number.
The break is used for efficiency reasons. You could remove it and the algorithm would still work correctly but slower.

ProjectEuler's distinct prime factors of a given number

folks, I've been struggling to figure out the algorithm to get the list of all of the prime factors of the given number (in my case, the given number is myNumber = 14). For example,
14 = 2 × 7
15 = 3 × 5
645 = 3 × 5 × 43
646 = 2 × 17 × 19
But my code is running infinitely and I'm not pretty sure if my algorithm works fine. Could smb take a look or give me a hand how to see the problem? Thanks in advance!
import java.util.*;
public class DistinctFactors {
public static final List<Integer> myList = new ArrayList<>();
public static void main(String[] args){
int result = 1;
int myNumber = 14;
int i = 2;
while(result != myNumber){
if(isPrime(i)){
myList.add(i);
result *= i;
}
i++;
}
for(int j = 0; i < myList.size(); j++){
System.out.print(myList.get(j) + " ");
}
}
private static boolean isPrime(int number){
for(int i = 2; i < number; i++){
if(number % 2 == 0){
return false;
}
}
return true;
}
}
I mean, let's look at what the values of result and i will be.
Pass 1: r = 1, i = 2
Pass 2: r = 2, i = 3
Pass 3: r = 6, i = 4
Pass 4: r = 6, i = 5
Pass 5: r = 30, i = 6
From this point on, r will only increase, and it's already greater than 14. So of course this loop will never terminate.
Your method is also extremely wrong. I have no idea why you chose this way to try and get prime factors.
Not to mention, even your isPrime method is kind of dumb. It checks all the way up to the number you're checking, which is extremely wasteful.
To check if a number n is prime, you should instead compute the square root; if it is an integer, then the number is obviously not prime. Otherwise, take the floor of that sqrt(n) - let's call it k - and run the loop up to k. If n is not prime, you will find a divisor in that range; if you find none, n is prime.
(That is an O(log(n)) method. The best method is the one that involves checking whether the number satisfies Fermat's Little Theorem for random values, which is constant time).
EDIT: Well, not exactly constant time if you don't consider certain operations O(1). For huge numbers it's much better than the other method
Your current loop just checks whether the number is even a bunch of times...

Method to find a factor of a number

I am trying to write a simple program that takes a non-prime number and returns the first factor of it. I have to use a method to do this. I think that I am really close to the correct code, but I keep running into variable definition issues in my method. Here is my (currently incorrect) code:
public class testing {
public static void main(String[] args) {
int a;
a = 42;
System.out.println(factor(a));
}
//This method finds a factor of the non-prime number
public static int factor(int m) {
for(int y=2 ; y <= m/2 ; y++) {
if(m%y==0) {
return y;
continue;
}
}
return y;
}
}
Please let me know what's incorrect!
Regarding your code:
public static int factor(int m) {
for(int y=2 ; y <= m/2 ; y++) {
if(m%y==0) {
return y;
continue;
}
}
return y;
}
At the point of that final return y, y does not exist. Its scope is limited to the inside of the for statement since that is where you create it. That's why you're getting undefined variables.
In any case, returning y when you can't find a factor is exactly the wrong thing to do since, if you pass in (for example) 47, it will give you back 24 (47 / 2 + 1) despite the fact it's not a factor.
There's also little point in attempting to continue the loop after you return :-) And, for efficiency, you only need to go up to the square root of m rather than half of it.
Hence I'd be looking at this for a starting point:
public static int factor (int num) {
for (int tst = 2 ; tst * tst <= num ; tst++)
if (num % tst == 0)
return tst;
return num;
}
This has the advantage of working with prime numbers as well since the first factor of a prime is the prime itself. And, if you foolishly pass in a negative number (or something less than two, you'll also get back the number you passed in. You may want to add some extra checks to the code if you want different behaviour.
And you can make it even faster, with something like:
public static int factor (int num) {
if (num % 2 == 0) return 2;
for (int tst = 3 ; tst * tst <= num ; tst += 2)
if (num % tst == 0)
return tst;
return num;
}
This runs a check against 2 up front then simply uses the odd numbers for remainder checking. Because you've already checked 2 you know it cannot be a multiple of any even number so you can roughly double the speed by only checking odd numbers.
If you want to make it even faster (potentially, though you should check it and keep in mind the code may be harder to understand), you can use a clever scheme pointed out by Will in a comment.
If you think about the odd numbers used by my loop above with some annotation, you can see that you periodically get a multiple of three:
5
7
9 = 3 x 3
11
13
15 = 3 x 5
17
19
21 = 3 x 7
23
25
27 = 3 x 9
That's mathematically evident when you realise that each annotated number is six (3 x 2) more than the previous annotated number.
Hence, if you start at five and alternately add two and four, you will skip the multiples of three as well as those of two:
5, +2=7, +4=11, +2=13, +4=17, +2=19, +4=23, ...
That can be done with the following code:
public static long factor (long num) {
if (num % 2 == 0) return 2;
if (num % 3 == 0) return 3;
for (int tst = 5, add = 2 ; tst * tst <= num ; tst += add, add = 6 - add)
if (num % tst == 0)
return tst;
return num;
}
You have to add testing against 3 up front since it violates the 2, 4, 2 rule (the sequence 3, 5, 7 has two consecutive gaps of two) but that may be a small price to pay for getting roughly another 25% reduction from the original search space (over and above the 50% already achieved by skipping all even numbers).
Setting add to 2 and then updating it with add = 6 - add is a way to have it alternate between 2 and 4:
6 - 2 -> 4
6 - 4 -> 2
As I said, this may increase the speed, especially in an environment where modulus is more expensive than simple subtraction, but you would want to actually benchmark it to be certain. I just provide it as another possible optimisation.
This is what you probably want to do:
public static void main(String[] args) {
int a;
a = 42;
System.out.println(factor(a));
}
public static int factor(int m) {
int y = 0;
for (y = 2; y <= m / 2; y++) {
if (m % y == 0) {
return y;
}
}
return y;
}
And the output will be 2.
we need just a simple for loop like,
public static void finfFactor(int z) {
for(int x=1; x <= z; x++) {
if(z % x == 0) {
System.out.println(x);
}
}

Why is my solution to project euler 1 not working?

I decided to just try and get the small example of only going to 10 like the example shown.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 >and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
public class project1 {
public static void main(String[] args) {
int three=0;
int tot3=0;
int five=0;
int tot5=0;
int total;
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
while (tot5<10) {
five+=5;
tot5=tot5+five;
};
total=tot3+tot5;
System.out.println("Three's: " + tot3);
System.out.println("Five's: " + tot5);
System.out.println("Combined: " + total);
}
}
My output is as show:
Three's: 18
Five's: 15
Combined: 33
Numbers that are both multiples of 3 and 5 (like 15 for instance), are counted twice - once in each loop.
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
I think you mean
while (tot3<10) {
three += tot3; // Add this multiple of 3 to the total.
tot3+=3; // increment the "next multiple"
}
(same for 5)
Lone nebula also makes a good point - you'd need to add logic to the "5" loop to check it's not already counted in the 3 loop. The mod (%) operator can help there.
First,
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
while (tot5<10) {
five+=5;
tot5=tot5+five;
};
This should be
while (three<10) {
three+=3;
tot3=tot3+three;
};
while (five<10) {
five+=5;
tot5=tot5+five;
};
Because you're concerned about when you start counting numbers above 10, not when your TOTAL of those numbers is above 10.
Secondly, your solution will count numbers that are a multiple of three and of five twice. For example, 15 will be added twice. Learn about the modulo operator, %, to come up with a solution to this (for example, not adding five to the tot5 count if five % 3 == 0)
I would recommend looking into using the modular operator to solve this problem. In java % will allow you to perform modular arithmetic. For example any multiple of 3 such as 9 % 3 = 0 while 9 % 2 = 1. It can be thought of as what remains after you divide the first number by the second. All multiples of a number modded by that number will return zero.
Keep track of your variables through the loop and you'll see the problem:
for tot3
=3
=9
=18
=30
You're keeping track of the sum, instead of tracking the multiples. This problem is partially solved in by
while(three<10)
Again, keeping track of the variable through the loop you'll see that this is wrong- it stops at 12, not 9 as you want it. Change it to
While(three<9)
//ie the last divisible number before the limit, or that limit if its divisible (in the case of 5)
All said, an infinitely more elegant solution would involve modulus and a nice little if statement. I hope this helps!
public class project1 {
public static void main(String[] args) {
int number = 0;
int total = 0;
while (number < 10) {
System.out.println(number);
if ((number % 3) == 0) {
System.out.println(number + " is a multiple of 3");
total = total + number;
}
else if ((number % 5) == 0) {
System.out.println(number + " is a multiple of 5");
total = total+number;
}
number++;
}
System.out.println("total = "+ total);
}
}
Looking at how slow I was, I did roughly the same thing as everyone else but swapped to a modulus function. The modulus function gives you the remainder(int) of dividing the first number by the second number, and can be compared to another integer. Here I have used it to check if the current number is directly divisible by 3 or 5, and add it to the total if the value is true.
Try this
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong()-1;
System.out.println((n-n%3)*(n/3+1)/2 + (n-n%5)*(n/5+1)/2 - (n-n%15)*(n/15+1)/2);
}
}
}

Tips to solve problem #41 of project euler

I'm trying to solve Problem 41of project Euler in Java, by counting the number from 99888888 to 80000000(which took very long time :( ), I got 98765431 as an answer, but I'm getting that answer not correct. Could anyone please tell me the reason of not getting the correct answer and how can I speed my program?
A pandigital number doesn't needs to contain all numbers from 1 to 9, but all from 1 to length.
So, you'll need to try all permutations from 1 to 9 starting with 1 digit and going up, filtering all prime numbers and, then, taking largest one.
The only possible prime pandigital numbers are those with length 1, 4, & 7 because every other pandigital number has the sum of its digits divisible by 3.
So, you'd only need to test for 7! = 5040 permutations.
To obtain a solution in a "reasonable" time, you need the following observations based on the special property that a number is divisible by 3 if the sum of its digits is divisible by 3:
divisible by
1+2+3+4 = 10 -
1+2+3+4+5 = 15 3
1+2+3+4+5+6 = 21 3
1+2+3+4+5+6+7 = 28 -
1+2+3+4+5+6+7+8 = 36 3
1+2+3+4+5+6+7+8+9 = 45 3
So, a "big" prime pandigital number has 4 or 7 digits. (a prime number bigger than 3 is not divisible by 3)
Because you want to obtain the biggest number, it's better to start with the 7-digit numbers and continue to check the 4-digit numbers only if the number was not found. For sure, a 4-digit number exists, because it is specified: 2143.
Now, a possible solution looks like this:
public class P41 {
public static void main(String[] args) {
boolean wasFound = false;
for (int nr = 7654321; nr >= 1234567; nr -= 2) { // even != prime
if (isPandigital(nr) && isOddPrime(nr)) {
System.out.println(nr);
wasFound = true;
break;
}
}
if (!wasFound) {
/* not <=, because 1234 is even */
for (int nr = 4321; nr > 1234; nr -= 2) {
if (isPandigital(nr) && isOddPrime(nr)) {
System.out.println(nr);
break;
}
}
}
}
private static boolean isOddPrime(int x) {
int sqrt = (int) Math.sqrt(x);
for (int i = 3; i <= sqrt; i += 2) {
if (x % i == 0) {
return false;
}
}
return true;
}
private static int getNumberOfDigits(int x) {
int count = 0;
while (x > 0) {
count++;
x /= 10;
}
return count;
}
private static boolean isPandigital(int x) {
int numberOfDigits = getNumberOfDigits(x);
Set<Integer> digits = new HashSet<Integer>();
for (int i = 1; i <= numberOfDigits; i++) {
digits.add(i);
}
for (int i = 1; i <= numberOfDigits; i++) {
digits.remove(x % 10);
x /= 10;
}
if (digits.size() == 0) {
return true;
} else {
return false;
}
}
}
Time: 8 ms.
Here is the problem statement:
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime. What is the largest n-digit pandigital prime that exists?
I wrote a program that started with 987654321 and counted down. I checked that the number was pandigital, and if it was, checked if it was prime.
It took 66 seconds on my Windows 8.1 computer to find the largest prime pandigital.
When I tested the other way around, first prime, then pandigital, the program took way longer than 66 seconds. I cancelled it.
When I applied GregS' tip about discounting all 9 digit and 8 digit pandigital numbers, and started counting down from 7654321, my brute force algorithm took 13 milliseconds.

Categories

Resources