This is an exercise.
A perfect number is a number whose sum of divisors without itself is equal to that number
6 is a perfect number because its divisors are: 1,2,3,6 and 1 + 2 + 3 = 6
28 is a perfect number because its divisors are: 1,2,4,7,28 and 1 + 2 + 4 + 7 = 28
Task: write the body of findNPerfectNumbers, which will find n prime perfect numbers and return them as a list
I must use this program:
import java.util.ArrayList;
public class Exercise {
public static ArrayList<Integer> findNPerfectNumbers(int n)
{
return new ArrayList<>();
}
public static void main(String[] args)
{
System.out.println(findNPerfectNumbers(4));
}
}
I create this code to resolve this problem, but I have a problem to return an ArrayList. I don't know how. It should look like this example: 6 = 1,2,3,6 ///// 28 = 1, 2, 4, 7
My idea:
import java.util.ArrayList;
public class Main
{
public static ArrayList<Integer> findNPerfectNumbers(int n)
{
int sum = 0;
ArrayList<Integer> perfectList = new ArrayList<>();
ArrayList<Integer> factorList = new ArrayList<>();
for (int i = 6; i < n; i++)
{
factorList.clear();
for (int j = 1; j <= i / 2; j++)
{
if (i % j == 0)
{
factorList.add(j);
}
}
sum = 0;
for (int h = 0; h < factorList.size(); h++)
{
sum = sum + factorList.get(h);
}
if (sum == i)
{
perfectList.add(i);
}
}
return perfectList;
}
public static void main(String[] args)
{
System.out.println(findNPerfectNumbers(28));
}
}
Anyone have an idea?
The question is as simple as to have the findNPerfectNumbers function return the first N perfect numbers.
The main part for the exercise is probably to do this as efficiently as possible. For example limiting divider check by half like you do in for (int j = 1; j <= i / 2; j++) is one of many options.
The reason your function doesn't return anything though is because your outer for loop is incorrect with the given input of 4 what you'r doing is for (int i = 6; i < 4; i++) which doesn't do any loops because 4 is smaller than 6.
what you probably intended to do issomething like for (int i = 6; perfectList.size() < n; i++) which would loop aslong as you have fewer than N perfect numbers.
example working code:
import java.util.ArrayList;
public class Exercise {
public static ArrayList<Integer> findNPerfectNumbers(int n) {
int sum = 0;
ArrayList<Integer> perfectList = new ArrayList<>();
for (int i = 6; perfectList.size() < n; i++) {
ArrayList<Integer> factorList = new ArrayList<>();
for (int j = 1; j <= i / 2; j++) {
if (i % j == 0) {
factorList.add(j);
}
}
sum = 0;
for (Integer factor : factorList) {
sum += factor;
}
if (sum == i) {
System.out.println("Found perfect number " + i + " with factors " + factorList);
perfectList.add(i);
}
}
return perfectList;
}
public static void main(String[] args) {
System.out.println(findNPerfectNumbers(4));
}
}
If number is less than 10^1500 you can use Euclid's method
public static List<Long> findPerfect(int n){
List<Long> perfectList=new ArrayList<>();
int x=0;
long sum=0;
long last;
while(perfectList.size()!=n){
last= (long) Math.pow(2,x);
sum+=last;
if(isPrime(sum))
perfectList.add(sum*last);
x++;
}
return perfectList;
}
public static boolean isPrime(long x){
if(x==1)
return false;
for (int i = 2; i <= Math.sqrt(x); i++) {
if(x%i==0)
return false;
}
return true;
}
Related
I got some problem someone of with really helped me but I got program source code who print all of divisor from array, but I tried to print a number with most divisor for ex. array[1,2,3,4,5] and I want to print that the number with most divisor is 4 (1,2,4)
public static class Main {
public static void main(String[] args) {
System.out.println(getNumWithMaxDivisors(numbers));
}
static int getNumDivisors(int n) {
int noOfDivisors = 0;
for (int i = 1; i <= n / 2; i++) {
if (n % i == 0) {
System.out.print(i + " ");
noOfDivisors++;
}
}
return noOfDivisors;
}
static int getNumWithMaxDivisors(int[] numbers) {
int currentMaxDivisors = 0;
int numWithMaxDivisors = numbers[0];
for (int i = 0; i < numbers.length; i++) {
int numDivisors = getNumDivisors(numbers[i]);
if (numDivisors > currentMaxDivisors) {
numWithMaxDivisors = numbers[i];
}
}
return numWithMaxDivisors;
}
}
Code looks that, do you know where is a problem ?
The problem is that inside of your getNumWithMaxDivisors() method, you are not redefining the current number of max divisors. To fix this, you can update it inside of the if statement as so:
static int getNumWithMaxDivisors(int[] numbers) {
int currentMaxDivisors = 0;
int numWithMaxDivisors = numbers[0];
for (int i = 0; i < numbers.length; i++) {
int numDivisors = getNumDivisors(numbers[i]);
if (numDivisors > currentMaxDivisors) {
currentMaxDivisors = numDivisors; //ADD THIS LINE
numWithMaxDivisors = numbers[i];
}
}
return numWithMaxDivisors;
}
Input:
int[] numbers = {1,2,3,4,5};
System.out.println(getNumWithMaxDivisors(numbers));
Output:
4
Side Note: You could just as well start your for loop at i = 2 in your getNumDivisors() method, since every number is divisible by 1, so there is no point in checking it. This just saves you a bit of time!
add this line of code currentMaxDivisors = numDivisors; inside your if-statement like so:
static int getNumWithMaxDivisors(int[] numbers) {
int currentMaxDivisors = 0;
int numWithMaxDivisors = numbers[0];
for (int i = 0; i < numbers.length; i++) {
int numDivisors = getNumDivisors(numbers[i]);
if (numDivisors > currentMaxDivisors) {
currentMaxDivisors = numDivisors; //here this is missing
numWithMaxDivisors = numbers[i];
}
}
return numWithMaxDivisors;
}
I encountered a problem that I need to find the mirror of the prime numbers within the range of 1 to N. A mirror is like 13 and 31, 17 and 71, etc. I write the solution provided below,
/*
* find prime numbers within 1 to N that is a mirror to each other
*/
public static List<Integer> solution(int N) {
List<Integer> primes = findPrimes(N);
Set<Integer> set = new LinkedHashSet<>();
for (int i = 0; i < primes.size(); i++) {
int prime = primes.get(i);
int mirror = hasMirror(prime, primes);
if (mirror == 0) {
continue;
}
set.add(prime);
set.add(mirror);
}
return new ArrayList<>(set);
}
/*
* find the mirror of a number
* */
private static int findMirror(int P) {
int R = 0;
while (P != 0) {
int D = P % 10;
R = R * 10 + D;
P /= 10;
}
return R;
}
private static int hasMirror(int P, List<Integer> B) {
Integer[] A = B.toArray(new Integer[0]);
int N = A.length;
int R = findMirror(P);
for (int i = N - 1; i >= 0; i--) {
if (A[i] == R) {
return R;
}
}
return 0;
}
public static List<Integer> findPrimes(int N) {
int[] F = new int[N + 1];
List<Integer> result = new ArrayList<>();
for (int i = 2; i <= N; i++) {
if (F[i] == 0) {
// the prime value need to be 2 digit for the mirror image
if (i < 10 || i == findMirror(i)) {
continue;
}
result.add(i);
for (int k = i * i; k <= N; k += i) {
if (F[k] == 0) {
F[k] = 1;
}
}
}
}
return result;
}
}
The solution works, but, is there an option to improve the performance?
One thing you can do to improve performance is, not invoking the hasMirror() for already identified mirrors.
For example, let's say you checked 17 and identified that it has a mirror 71. Then when you reach 71 later on your loop, you can skip checking its mirrors as you have already identified it.
List<Integer> primes = findPrimes(N);
Set<Integer> set = new LinkedHashSet<>();
for (int i = 0; i < primes.size(); i++) {
int prime = primes.get(i);
if (!set.contains(prime)) {
int mirror = hasMirror(prime, primes);
if (mirror == 0) {
continue;
}
set.add(prime);
set.add(mirror);
}
}
So I'm trying to do what I thought would be a simple problem in Java. I don't know if it's because I'm new to Java, or that I'm just making a silly mistake, but I'm getting 3341, which is the wrong answer.
Link to Question: https://projecteuler.net/problem=53
import java.math.BigInteger;
public class Main {
public static BigInteger[] factorial = new BigInteger[101];
static public void main(String[] args)
{
factorial[0] = BigInteger.ONE;
for(int i = 1; i <= 100; i++)
factorial[i] = factorial[i-1].multiply( BigInteger.valueOf(i) );
int count = 0;
for(int n = 1; n <= 100; n++)
{
for(int r = 0; r <= n; r++)
{
if( choose(n, r) > 1000000)
{
count++;
}
}
}
System.out.println("There are " + count + " values > 1,000,000 ");
}
static public long choose(int n, int r)
{
return ( factorial[n].divide( ( factorial[r].multiply(factorial[n-r]) ) ) ).longValue();
}
}
Some of those numbers are pretty large. Certainly larger than would fit into a long value.
Try doing all the calculations, including the comparisons, as BigInteger.
public static BigInteger choose(int n, int r)
{
return factorial[n].divide(factorial[r].multiply(factorial[n - r]));
}
And then in the main code, something like:
final BigInteger max = BigInteger.valueOf(1000000);
for (int n = 1; n <= 100; n++)
{
for (int r = 0; r <= n; r++)
{
if (choose(n, r).compareTo(max) > 0)
{
count++;
}
}
}
I need to find all the permutations for a given n(user input) without backtracking.
What i tried is:
import java.util.Scanner;
import java.util.Vector;
class Main {
private static int n;
private static Vector<Vector<Integer>> permutations = new Vector<>();
private static void get_n() {
Scanner user = new Scanner(System.in);
System.out.print("n = ");
n = user.nextInt();
}
private static void display(Vector<Vector<Integer>> permutations) {
for (int i = 0; i < factorial(n) - 1; ++i) {
for (int j = 0; j < n; ++j) {
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
}
System.out.println();
}
}
private static int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
private static int max(Vector<Integer> permutation) {
int max = permutation.elementAt(0);
for (int i = 1; i < permutation.size(); ++i)
if (permutation.elementAt(i) > max)
max = permutation.elementAt(i);
return max;
}
// CHECKS FOR ELEMENT COUNT AND 0 - (n-1) APPARITION
public static int validate_permutation(Vector<Integer> permutation) {
// GOOD NUMBER OF ELEMENTS
if (max(permutation) != permutation.size() - 1)
return 0;
// PROPER ELEMENTS APPEAR
for (int i = 0; i < permutation.size(); ++i)
if (!permutation.contains(i))
return 0;
return 1;
}
private static Vector<Integer> next_permutation(Vector<Integer> permutation) {
int i;
do {
i = 1;
// INCREMENT LAST ELEMENT
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
// IN A P(n-1) PERMUTATION FOUND n. "OVERFLOW"
while (permutation.elementAt(permutation.size() - i) == permutation.size()) {
// RESET CURRENT POSITION
permutation.set(permutation.size() - i, 0);
// INCREMENT THE NEXT ONE
++i;
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
}
} while (validate_permutation(permutation) == 0);
// OUTPUT
System.out.print("output of next_permutation:\t\t");
for (int j = 0; j < permutation.size(); ++j)
System.out.print(permutation.elementAt(j) + " ");
System.out.println();
return permutation;
}
private static Vector<Vector<Integer>> permutations_of(int n) {
Vector<Vector<Integer>> permutations = new Vector<>();
// INITIALIZE PERMUTATION SET WITH 0
for (int i = 0; i < factorial(n); ++i) {
permutations.addElement(new Vector<>());
for(int j = 0; j < n; ++j)
permutations.elementAt(i).addElement(0);
}
for (int i = 0; i < n; ++i)
permutations.elementAt(0).set(i, i);
for (int i = 1; i < factorial(n); ++i) {
// ADD THE NEXT PERMUTATION TO THE SET
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
System.out.print("values set by permutations_of:\t");
for (int j = 0; j < permutations.elementAt(i).size(); ++j)
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
System.out.println("\n");
}
System.out.print("\nFinal output of permutations_of:\n\n");
display(permutations);
return permutations;
}
public static void main(String[] args) {
get_n();
permutations.addAll(permutations_of(n));
}
}
Now, the problem is obvious when running the code. next_permutation outputs the correct permutations when called, the values are set correctly to the corresponding the vector of permutations, but the end result is a mass copy of the last permutation, which leads me to believe that every time a new permutation is outputted by next_permutation and set into the permutations vector, somehow that permutation is also copied over all of the other permutations. And I can't figure out why for the life of me.
I tried both set, setElementAt, and an implementation where I don't initialize the permutations vector fist, but add the permutations as they are outputted by next_permutation with add() and I hit the exact same problem. Is there some weird way in which Java handles memory? Or what would be the cause of this?
Thank you in advance!
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
This is literally setting the vector at permutations(i) to be the same object as permutations[i-1]. Not the same value - the exact same object. I think this the source of your problems. You instead need to copy the values in the vector.
I tried to implement the Fenwick Tree in Java, but I am not getting the desired result.
Here is my code:
import java.io.*;
import java.util.*;
import java.math.*;
class fenwick1 {
public static int N;
public static long[] a;
public static void main(String[] args)throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
a = new long[N];
String[] str = br.readLine().split(" ");
for (int i = 0; i < N; i++) {
a[i] = Long.parseLong(str[i]);
}
increment(2, 10);
System.out.println(a[2]);
System.out.println(query(4));
}
public static void increment(int at, int by) {
while (at < a.length) {
a[at] += by;
at |= (at + 1);
}
}
public static int query(int at) {
int res = 0;
while (at >= 0) {
res += a[at];
at = (at & (at + 1)) - 1;
}
return res;
}
}
When I give input:
10
1 2 3 4 5 6 7 8 9 10
I get:
13
19
So the increment function works fine. But query(4) should give the cumulative sum up to index 4 i.e.
(1 + 2 + 13 + 4 + 5) = 25
You do not initialize it properly.
Instead of:
for (int i = 0; i < N; i++) {
a[i] = Long.parseLong(str[i]);
}
It should be:
for (int i = 0; i < N; i++) {
increment(i, (int)Long.parseLong(str[i]));
}
because a[i] should store a cumulative sum, not a single element.
If you want to store the initial array elements too, you can just create one more array:
long[] initA = new long[N];
for (int i = 0; i < N; i++) {
initA[i] = Long.parseLong(str[i]);
increment(i, (int)initA[i]);
}