I have to write a java code for the 'sieve of eratosthenes' algorithm to print out primes up to a given max value on the console but I'm not allowed to use arrays. Our professor told us it is possible to do only with the help of loops.
So I thought a lot and googled a lot about this topic and couldn't find an answer. I dont think it's possible at all because you have store the information which digits are already crossed out somewhere.
my code until now:
public static void main(String[] args) {
int n = 100;
int mark = 2;
System.out.print("Primes from 1 to "+n+": 2, ");
for (int i = 2; i <= n; i++) {
if(i % mark != 0){
System.out.print(i+", ");
mark = i;
}
}
}
-> So, i'm not allowed to do the "i % mark != 0" command with numbers which are multiples of the numbers i already printed but how am i supposed to make that clear without an array where i can delete numbers on indexes?
BUT if there is a solution I would be glad if someone could share it with me! :)
The solution can be in other programming languages, i can translate it to java myself if its possible.
Thank you in advance and best regards
Update: Thank you very much all of you, i really appreciate your help but I don't think it can be done with the basic structures. All the algorithms i have seen yet which print out primes by using basic structures are no sieve of eratosthenes. :(
The Sieve is about remembering the primes you found already. As far as I know there is no way to do this without arrays or lists and only with loops.
I checked some of the examples at RosettaCode at random and did not find one without an array and only loops.
If you add Classes and Methods as options you can come up with a recursive design:
public class Sieve
{
private int current;
private int max;
private Sieve parent;
public Sieve(int current, int max, Sieve parent )
{
this.current = current;
this.max = max;
this.parent = parent;
}
public static void main(String[] args)
{
int n = 100;
System.out.print("Primes from 1 to " + n + ":\n");
printPrimes(n);
}
private static void printPrimes(int i)
{
new Sieve(2,i,null).start();
}
private void start()
{
if(current <2 || max <2)
{
return;
}
if(this.current > max)
{
parent.print();
return;
}
for(int i = this.current+1;current<=max+1;i++)
{
if(this.testPrime(i))
{
new Sieve(i,this.max,this).start();
return;
}
}
}
private boolean testPrime(int i)
{
if(i%this.current != 0)
{
if(this.parent == null)
{
return true;
}
else
{
return this.parent.testPrime(i);
}
}
return false;
}
private void print()
{
if(this.parent != null)
{
this.parent.print();
}
System.out.print(" "+this.current);
}
}
This removes the array but uses Objects to store the Prime (each Sieve holds one prime)
I'm taking back what I said earlier. Here it is, the "sieve" without arrays, in Haskell:
sieve limit = [n | n <- [2..limit], null [i | i <- [2..n-1], j <- [0,i..n], j==n]]
It is a forgetful sieve, and it is very very inefficient. Uses only additions, and integer comparisons. The list comprehensions in it can be re-coded as loops, in an imperative language. Or to put it differently, it moves counts like a sieve would, but without marking anything, and thus uses no arrays.
Of course whether you'd consider it a "true" sieve or not depends on what is your definition of a sieve. This one constantly recreates and abandons them. Or you could say it reimplements the rem function. Which is the same thing to say, actually, and goes to the essence of why the sieve suddenly becomes so efficient when reuse - via arrays usually - becomes possible.
Related
I was writing a recursive algorithm to calculate Fibonacci numbers in Java as part of a programming 101 course. This is the code:
public class Fib {
public static void main(String[] args) {
Fib fib = new Fib();
}
public Fib() {
int end = 9;
long[] nums = new long[2];
printFib(0, end, nums);
}
private void printFib(int i, int end, long[] nums) {
while(i < end) {
if(i == 0 || i == 1) {
nums[i] = 1;
System.out.println("1");
} else {
long fib;
fib = 0;
fib += (nums[0] + nums[1]);
nums[0] = nums[1];
nums[1] = fib;
System.out.println(fib);
}
i++;
printFib(i, end, nums);
}
}
}
As I was stepping through the program it was working as intended until i became equal to end, the variable telling the printFib method how many Fibonacci numbers it should print out. When ì was equal to end while(i < 1) returns false as expected and the program go to the last }, now you'd(me)
expect the program to return the constructor from which I initially called the function and the program should exit, this not the case. The program goes back to the while statement and somehow evaluates to false again. Then it does the same thing again except the second time it decreases i by 1(what?!) and then proceeds to the else clause when it reaches the if statement. It then does the same thing over and over alternating the amount it subtracts from i between 1 and 2. I've asked my teacher about this and he was unable to explain it.
The program works fully like I intended if I replace the while with an if so maybe there is something about while that I don't know.
Edit
So I realize now that each time the method is called i has a different value which is stored and when the method exits and i = end the program goes back to the previous calls where i had a different value.
You implemented an iterative algorithm to calculate Fibonacci series. That's what the while loop does. There is no point in making the recursive call - printFib(i, end, nums) - at the end.
If you intended a recursive implementation, the entire while loop is not needed.
This code doesn't look right to me.
I would recommend that you not print from your method. Return a value to the main and let it print.
Your recursive method should not have a while loop in it. That's iteration - exactly what you're trying to avoid here.
Your method should have a stopping condition and a call to itself. That's not what you're doing.
Think about it like this:
/**
* Recursive Fibonnaci
* User: mduffy
* Date: 2/11/2015
* Time: 8:50 AM
* #link http://stackoverflow.com/questions/28455798/strange-behavior-in-recursive-algorithm/28455863#28455863
*/
public class Math {
private static Map<Integer, Integer> memo = new ConcurrentHashMap<Integer, Integer>();
public static void main(String [] args) {
for (String arg : args) {
int n = Integer.valueOf(arg);
System.out.println(String.format("n: %d fib(n): %d", n, fibonnaci(n)));
}
}
public static int fibonnaci(int n) {
if (n < 0) throw new IllegalArgumentException("index cannot be negative");
int value = 0;
if (memo.containsKey(n)) {
value = memo.get(n);
} else {
if (n <= 1) {
value = n;
} else {
value = fibonnaci(n-1)+fibonnaci(n-2);
}
memo.put(n, value);
}
return value;
}
}
Basicly this is happening because i would guess that you are thinking of i as an reference which will influence the basic callings of the Fibunacci method calling the sub Fibunacci method. This will finally lead way to many calls of the fibunacci method.
in my eyes the loop doesn´t make sense in your recursive way of solving it.
Alright guys, I've been stuck on this problem for a while now and have not been able to get past it. This is for Java. I'd appreciate any help at this point. Here are the details: Please note, we must do this in O(n) running time. We are given an array of numbers and must go through it to determine if there are any 3 numbers that sum to a specific number. HOWEVER, we are allowed to reuse any number in the array up to 3 times because we need a total of 3 numbers. We also have to output which 3 numbers gave the sum. Returning true or false.
Below is what I've got:
Do you guys have any suggestions?
You can make a for loop inside of a for loop inside of a for loop. This is for school, so I wont give you the code, but I'll give you the pseudo.
Edit: missed the O(n) part, sorry. This way should work.
public static void main(String[] args)
{
int[] test = {1,8,2,3,11,4};
System.out.println(threeSumTo(test, 6));
}
//check if 3 numbs in an array add up to int x
public static boolean threeSumTo(int[] array, int x)
{
//loop through the array
for (int i = 0; i < array.length; i++) {
boolean result = twoSumTo(array, x - array[i], i);
if (result) {
return result;
}
}
return false;
}
private static boolean twoSumTo(int[] array, int x, int low) {
int high = array.length - 1;
while (low < high) {
if (array[low] + array[high] == x) {
return true;
}
if (array[low] + array[high] > x) {
high--;
} else {
low++;
}
}
return false;
}
}
This seems to be a variation of the 3SUM problem and should obey the same restrictions.
Computing the 3SUM problem in less than O(n^2) is still a unsvoled problem.
Did your teacher ask a trick question or is that some kind of competition?
This is called a 3 sum problem and solving this problem in O(N) is impossible till now. The best you can do is O(N^2).
Check this article out.
Today, my teacher asked us to implement the next expression using recursion in Java (where n is a value asked to the user):
It is possible? I can't find a proper solution for this problem, but I think I will need two recursive methods.
UPDATE
So far I have done this:
public static double sumatorio(int n){
if(n==1)
return 1;
else{
return (1 + ((n-1) * segundoSumatorio(n))) + sumatorio(n-1);
}
}
public static double segundoSumatorio(int n){
if(n==1)
return 1;
else
return 1/(double)n + segundoSumatorio(n-1);
}
It looks like it's correct, but when n=3 or greater, the result is not exact. Someone knows why?
Maybe there is an error related with losing precision.
I really appreciate any help you can provide.
Hints:
Yes. One possible solution does involve two recursive methods.
(And it is a good solution ... )
Factor the problem (and the solution) into two parts; e.g. the complete "sigma" and the embedded "sigma".
Here is your code fixed. Note how the 2nd sumatorio needs 2 parameters,
and how I don't change the second parameter while calling it recursively.
This is what your formula says and not what you implemented.
This is not a precision error, you could have figured that out
because this error sounds too big for a precision error for such
small values of n.
public class Test {
public static void main(String a[]) throws Exception {
System.out.println(sumatorio(1));
System.out.println(sumatorio(2));
System.out.println(sumatorio(3));
System.out.println(sumatorio(4));
}
public static double sumatorio(int n){
return sumatorio(n ,n);
}
public static double sumatorio(int n, int m){
if(n==1)
return 1;
else{
return (1 + ((n-1) * segundoSumatorio(m))) + sumatorio(n-1, m);
}
}
public static double segundoSumatorio(int n){
if(n==1)
return 1;
else
return 1/(double)n + segundoSumatorio(n-1);
}
}
If this task is too hard for you, try splitting it in smaller chunks. The question asks for a summation, implemented by recurse. I am confident you can do summation by implementing a loop. Something like:
int sum = 0;
for(int i = 1; i < n; i++){
sum = sum+i;
}
This will sum all numbers from 1 to (n-1).
You can convert the loop into recursion by writing a simple adding method:
int sum = 0;
int doSum(int n){
if(n <= 1){
return 1;
}
else{
return n + doSum(n - 1);
}
}
sum = doSum(n);
From here on I think you should be able to catch up.
Splitting the problem into smaller subproblems is a technique used by ALL programmers. Start small and easy, adding complexity as you go.
My goal is to give the program a few items(Strings), a range, and target percent and let it give me all possible percentages of each item. For example, Imagine you go to the grocery store and have a basket of Apples & Pears you want to know all the percentages you could have using ALL items(not a full solution, I'm doing this by hand):
{Apple:50, Pears:50}, {Apple:75, Pears:25}, {Apple:90, Pears:10},etc.
If I do the same thing with a range of 20-50(meaning the highest value a single item can have is 50% and the lowest 20%) then the only result is:
{Apple:50, Pears:50} (since there are only 2 items and it cannot exceed 50% weight)
I thought it had similar traits as an knapsack problem with a few big differences since there are no values/weights associated with the items(but like knapsack problem trying to fit items in a knapsack I’m trying to fit values within a target_percent, 100%). I’m also having trouble applying general dynamic programming ideas as well since I can’t figure out how to break the problem down(typical knapsack problems build up results and then ‘cache’ results to reuse but if if I have a list of X items, I need all X items to be used within a range).
I can do this via brute force but I don’t feel like its efficient because it just tries everything so the bounds that I’m using aren’t being used to make it efficient at all(for example if apple is 75% then there’s no reason Pear should exceed 25%..bounds are size of list, range, and target_percent..I might have 20-30 list items with a range of 5-20 or maybe 50 items with a range from 1-5..or anything in between I want to play around with how many complete results I can get as fast as possible. I have not shown the target_percent part in the question because I can set it up that once I understand how to solve the problem, but basically all the examples assume 100% max, but sometimes you may already have 20% oranges in your basket and see how you can use Apples/Pears to fill up the rest 80%).
My questions are, How can I approach this(any ideas logic to use, examples or proxy problems I can look up)? Is dynamic programming appropriate for this problem or the fact that I cannot break this into smaller chucks a problem(remember because its always includes all items in the list, its not building up)? If someone can point me to the right direction, I’m willing to study any topics that might help(After spending 2 days trying to figure this out,I’m just not sure if the Dynamic programming route is correct). Also is there a name for this type of problem(I looked up knapsack problems, integer partitioning, combinatorics but none of them seemed to fit)?
Here's my(broken) brute force approach(its not actually working as expected but maybe gives you an idea of the brute force method):
import java.util.ArrayList;
import java.util.Arrays;
public class brute_force_percent_returner {
static String[] data = new String[]{"Apple", "Pears"};
static int[] coeff = new int[data.length];
static ArrayList<int[]> queue = new ArrayList<int[]>();
public static void main(String[] args) {
System.out.println("Starting");
recursion(0,data);
for (int[] item : queue) {
for (int item2 = 0; item2<data.length; item2++) {
System.out.print(data[item2] + " = " + item[item2] + " ");
}
System.out.println();
}
}
private static void recursion(int k, String[] data2) {
// this is not exactly working
for (String item: data2) {
for (int x = 0; x<5;x++) {
int[] coeff_temp = Arrays.copyOf(coeff, coeff.length);
coeff_temp[k] = x;
queue.add(coeff_temp);
}
}
if (k == data.length-1) {
return;
} else {
recursion(k+1, data2);
}
}
}
If it helps the solution I was trying to create was somewhat based on this one(its a knapsack problem but seems to be super quick for large number of variables but in this care the items its processing are the items in the list whereas in my case the list is just strings):
public class TurboAdder {
private static final int[] data = new int[] { 5, 10, 20, 25, 40, 50 };
private static class Node {
public final int index;
public final int count;
public final Node prevInList;
public final int prevSum;
public Node(int index, int count, Node prevInList, int prevSum) {
this.index = index;
this.count = count;
this.prevInList = prevInList;
this.prevSum = prevSum;
}
}
private static int target = 100;
private static Node sums[] = new Node[target+1];
// Only for use by printString.
private static boolean forbiddenValues[] = new boolean[data.length];
public static void printString(String prev, Node n) {
if (n == null) {
System.out.println(prev);
} else {
while (n != null) {
int idx = n.index;
// We prevent recursion on a value already seen.
if (!forbiddenValues[idx]) {
forbiddenValues[idx] = true;
printString((prev == null ? "" : (prev+" + "))+data[idx]+"*"+n.count, sums[n.prevSum]);
forbiddenValues[idx] = false;
}
n = n.prevInList;
}
}
}
public static void main(String[] args) {
for (int i = 0; i < data.length; i++) {
int value = data[i];
for (int count = 1, sum = value; count <= 100 && sum <= target; count++, sum += value) {
for (int newsum = sum+1; newsum <= target; newsum++) {
if (sums[newsum - sum] != null) {
sums[newsum] = new Node(i, count, sums[newsum], newsum - sum);
}
}
}
for (int count = 1, sum = value; count <= 100 && sum <= target; count++, sum += value) {
sums[sum] = new Node(i, count, sums[sum], 0);
}
}
printString(null, sums[target]);
}
}
This sounds like homework so I'm extra reluctant to help you too much, but here's an approach.
to define the ranges, make a couple hash maps, like
lower bounds = {apples => 20, pears => 40, oranges => 0}
upper bounds = {apples => 50, pears => 100, oranges => 30}
if you think about it, every final (valid) combination would at the very least, have the contents defined by the lower bound map. so call that the base combination.
next, figure out the theoretical max of each type you can potentially add to the base combination. this is just another map
{apples => 30, pears => 60, oranges => 30}
figure how many total items you can add to the base map, which is 100 - the sum of all the lower bound values, in the example its 40.
now, you need to generate the combinations. You'll probably find recursion the easiest way to do it. ill demonstrate the remaining algorithm with pseudo code and hardcoded stuff to improve clarity, although you'll need to write a generic, recursive version of it.
totalItemsToAdd = 40 //as calculated via baseCombo.sumOfEntries()
for (i=0; i<maxApples; i++) {
combo = clone the base combination
combo.apples += i;
remainingItemsToAdd = totalItemsToAdd - i;
if (remainingItemsToAdd > 0) {
for (j=0; j<maxPears; j++) {
combo.pears += j;
// and so on, recursively
}
}
results.append(combo)
}
notice how it only generates valid combinations by keeping track of how many more items are possible for each of the combinations. So, this wouldnt be brute force, and it would actually do the minimum work needed to generate the set of combinations.
I'm pretty confident that the brute-force approach is the best way to go - at least, that's the way I would do it (which is by no means the same thing...).
Here's an attempt to work with the recursive approach that I've got working (although I haven't tested it with high values for weightsNo. This works on the basis that you're interested in the combinations of weights, rather than the permutations of weights - although the switch is relatively straightforward.
public static Set<int[]> getPossiblePercentageWeights(int weightsNo, int min, int max){
return recusiveFixWeight(weightsNo, 100, min, max);
}
private static Set<int[]> recusiveFixWeight(int weightsNo, int sum, int min, int max){
Set<int[]> weightsSet = new LinkedHashSet<int[]>();
if (weightsNo>2){
for (int iWeight=min; iWeight<=max; iWeight++){
Set<int[]> subSet = recusiveFixWeight(weightsNo-1, sum-iWeight, min, iWeight);
for (int[] subWeights : subSet){
int[] weights = new int[weightsNo];
weights[0] = iWeight;
System.arraycopy(subWeights, 0, weights, 1, subWeights.length);
weightsSet.add(weights);
}
}
} else {
int iMax = Math.min(max, sum/weightsNo);
for (int iWeight=min; iWeight<=iMax; iWeight++){
int jWeight = sum-iWeight;
if (jWeight>=min && jWeight<=max){
weightsSet.add(new int[]{iWeight,jWeight});
}
}
}
return weightsSet;
}
That said, having looked at the results, it looks like there should be an algorithm to determine how many weightSets there given a weightsNo, min and max, and from there it should be fairly straightforward to fill those in with possible values. That said, I can't quite figure it out at the moment. (Or indeed, whether it would be any quicker than the brute-force approach...)
Hi I'm doing the Collatz sequence problem in project Euler (problem 14). My code works with numbers below 100000 but with numbers bigger I get stack over-flow error.
Is there a way I can re-factor the code to use tail recursion, or prevent the stack overflow. The code is below:
import java.util.*;
public class v4
{
// use a HashMap to store computed number, and chain size
static HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
public static void main(String[] args)
{
hm.put(1, 1);
final int CEILING_MAX=Integer.parseInt(args[0]);
int len=1;
int max_count=1;
int max_seed=1;
for(int i=2; i<CEILING_MAX; i++)
{
len = seqCount(i);
if(len > max_count)
{
max_count = len;
max_seed = i;
}
}
System.out.println(max_seed+"\t"+max_count);
}
// find the size of the hailstone sequence for N
public static int seqCount(int n)
{
if(hm.get(n) != null)
{
return hm.get(n);
}
if(n ==1)
{
return 1;
}
else
{
int length = 1 + seqCount(nextSeq(n));
hm.put(n, length);
return length;
}
}
// Find the next element in the sequence
public static int nextSeq(int n)
{
if(n%2 == 0)
{
return n/2;
}
else
{
return n*3+1;
}
}
}
Your problem is not with the size of the stack (you're already memoizing the values), but with
the size of some of the numbers in the sequences, and
the upper limits of a 32-bit integer.
Hint:
public static int seqCount(int n)
{
if(hm.get(n) != null) {
return hm.get(n);
}
if (n < 1) {
// this should never happen, right? ;)
} ...
...
That should hopefully be enough :)
P.S. you'll run into a need for BigNums in a lot of project euler problems...
If you change from integer to long it will give you enough room to solve the problem.
Here was the code that I used to answer this one:
for(int i=1;i<=1000000;i+=2)
{
steps=1;
int n=i;
long current=i;
while(current!=1)
{
if(current%2==0)
{
current=current/2;
}else{
current=(current*3)+1;
}
steps++;
}
if(steps>best)
{
best=steps;
answer=n;
}
}
Brute forcing it, takes about 9 seconds to run
Side note (as it seems that you don't actually need tail call optimization for this problem): tail call optimization is not available in Java, and as far as I have heard, it is not even supported by the JVM bytecode. This means that any deep recursion is not possible, and you have to refactor it to use some other loop construct.
If you are counting the size of the Collatz sequence for numbers upto 1,000,000
you should re-consider using Integer type. I suggest using BigInteger or possible a long.
This should alleviate the problems encountered, but be warned you may still run out of heap-space depending on your JVM.
I think you need these 2 hints :
Don't use Integer because at some starting number, the sequence will fly into some numbers greater than Integer.Max_VALUE which is 2147483647. Use Long instead.
Try not to use recursion to solve this problem, even with memoization. As i mentioned earlier some numbers will fly high and produce a great deal of stacks which will lead into stack overflow. Try using "regular" iteration like do-while or for. Of course you can still use some ingredient like memoization in "regular" loop.
Oh i forget something. Perhaps the stack overflow occurs because of arithmetic overflow. Since you use Integer, maybe Java "change" those "flying numbers" into a negative number when arithmetic overflow occurs. And as seen in method seqCount(int), you don't check invariant n > 0.
You can solve this problem not only with recursion but also with a single loop. there is overflow if you write int. because it generates long while chaning and the recursion never ends because never equal to 1 and you probably get stackoverflow error
Here is my solution with loop and recursion:
public class Collatz {
public int getChainLength(long i) {
int count = 1;
while (i != 1) {
count++;
if (i % 2 == 0) {
i /= 2;
} else {
i = 3 * i + 1;
}
}
return count;
}
public static int getChainLength(long i, int count) {
if (i == 1) {
return count;
} else if (i % 2 == 0) {
return getChainLength(i / 2, count + 1);
} else {
return getChainLength(3 * i + 1, count + 1);
}
}
public int getLongestChain(int number) {
int longestChain[] = { 0, 0 };
for (int i = 1; i < number; i++) {
int chain = getChainLength(i);
if (longestChain[1] < chain) {
longestChain[0] = i;
longestChain[1] = chain;
}
}
return longestChain[0];
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(new Collatz().getLongestChain(1000000));
}
}
Here you can have a look at my recursive implementation of problem 14:
http://chmu.bplaced.net/?p=265
import java .util.*;
public class file
{
public static void main(String [] args)
{
long largest=0;
long number=0;
for( long i=106239;i<1000000;i=i+2)
{
long k=1;
long z=i;
while(z!=1)
{
if(z%2==0)
{
k++;
z=z/2;
} else{
k++;
z=3*z+1;
}
}
if(k>largest)
{
number=i;
largest=k;
System.out.println(number+" "+largest);
}
}//for loop
}//main
}