Can I use Sieve method without using Array and Boolean? [duplicate] - java

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

How can a recursive Java method be memoized?

So I've built this program to build different stair cases. Essentially the problem is: Given an integer N, how many different ways can you build the staircase. N is guaranteed to be larger than 3 and smaller than 200. Any previous step can not be larger than its following step otherwise it defeats the purpose of the staircase.
So given N = 3
You can build one staircase: 2 steps and then 1 step following that
Given N = 4
You can build one staircase: 3 steps and then 1 step following that
Given N = 5
You can build two staircases: 3 steps and then 2 steps OR 4 steps and then 1 step.
My method is below and it works, except its runtime is far too slow. So I was thinking of trying to make a memoization for the method, but to be honest I do not fully understand how to implement this. If I could get some help on how to do so that'd be great.
public static void main(String [] args)
{
System.out.println(answer(200));
}
public static int answer(int n) {
return bricks(1,n) -1;
}
public static int bricks(int height, int bricksLeft)
{
if(bricksLeft == 0)
{
return 1;
}
else if(bricksLeft < height)
{
return 0;
}
else
{
return bricks(height +1, bricksLeft - height) + bricks(height +1, bricksLeft);
}
}
Overview
So what you have here is a recursive solution. That works well for this type of problem. In this particular recursive solution, your recursive step will be called with the same arguments many times.
One really common optimization pattern for recursive solutions where the same calculation is being made many times is Dynamic Programming. The idea is that instead of doing the same calculation many times, we just cache each calculation the first time we do it. Then every following time, if we need to calculate the exact same value, we can just read the result from the cache.
Solution
With that in mind, this solution should work. It uses exactly the same logic as your original version, it just caches all results for the recursive step in a HashMap so that it never needs to calculate the same thing twice. It also uses a Staircase object to track pairs of (bricks, height). This is because we cannot insert pairs into a HashMap, we can only insert single objects.
Just change the variable bricks to whatever value you want to solve for.
public class Staircase {
private static HashMap<Staircase, Integer> cache;
public static void main(String[] args) {
cache = new HashMap<>();
int bricks = 6;
Staircase toBuild = new Staircase(1, bricks);
System.out.println(toBuild.waysToBuild() - 1);
}
public final int height;
public final int bricksLeft;
public Staircase(int height, int bricksLeft) {
this.height = height;
this.bricksLeft = bricksLeft;
}
public int waysToBuild() {
if (cache.containsKey(this)) {
return cache.get(this);
}
int toReturn;
if (bricksLeft == 0) {
toReturn = 1;
} else if (bricksLeft < height) {
toReturn = 0;
} else {
Staircase component1 = new Staircase(height + 1, bricksLeft - height);
Staircase component2 = new Staircase(height + 1, bricksLeft);
toReturn = component1.waysToBuild() + component2.waysToBuild();
}
cache.put(this, toReturn);
return toReturn;
}
#Override
public boolean equals(Object other) {
if (other instanceof Staircase) {
if (height != ((Staircase) other).height) {
return false;
}
if (bricksLeft != ((Staircase) other).bricksLeft) {
return false;
}
return true;
}
return false;
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + this.height;
hash = 73 * hash + this.bricksLeft;
return hash;
}
}
Analysis
I tested it out and the performance is much faster than your previous version. It computes values up to 200 instantly.
Your original function was O(2^n). That is because we make 2 recursive calls for each value from 1 to n, so the total number of calls is doubled for each time n is incremented.
The Dynamic Programming solution is O(n) since at most it will need to calculate the number of ways to make a staircase out of n bricks once for each value of n.
Additional Reading
Here is some more reading about Dynamic Programming: https://en.wikipedia.org/wiki/Dynamic_programming
Use a small class to hold the pairs (height, bricks), say:
private static class Stairs {
private int height;
private int bricks;
Stairs(int height, int bricks) {
this.height = height; this.bricks = bricks;
}
}
Then use a global HashMap<Stairs, Integer>, initialized in the main():
map = new HashMap<Stairs, Integer>();
In the bricks() function, check if the solution for a particular (height, bricks) pair is in the map. If yes, just return it from the map via a call to the get() method. Otherwise, do the computation:
Stairs stairsObj = new Stairs(height, bricks);
if(map.get(stairsObj) == null) {
// Put your compute code here
}
Before every return statement in the function, add two additional statements. Something like:
int result = <whatever you are returning right now>;
map.put(stairsObj, result);
return result;

Time Limit Exceeded

For problem (SPOJ.com - Problem FARIDA ). I am using same approach as given on (https://codinghangover.wordpress.com/2014/01/15/spojfarida-princess-farida/).
Following is my solution ==>
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
class FARIDA {
public static long maxC(Map<String, Long> map, long c[], int s, int e)
{
if(s>e)
return 0;
if(map.containsKey(s+"|"+e))
return map.get(s+"|"+e);
if(s==e)
map.put(s+"|"+e, c[s]);
else
map.put(s+"|"+e, Math.max(c[s]+ maxC(map,c,s+2,e),maxC(map,c,s+1,e)));
return map.get(s+"|"+e);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int j=1;j<=t;j++)
{
int n=in.nextInt();
long c[]= new long[n];
for(int i=0; i<n; i++)
c[i]=in.nextLong();
Map<String, Long> map = new HashMap<String, Long>();
System.out.println("Case "+j+": "+maxC(map,c,0,n-1));
}
in.close();
}
}
Why am i getting TLE in java ? What kind of optimization does it need? Is there any problem with HashMap ?
I think that the only possible reason you get a TLE, is that you use a HashMap which uses a string as the key. So, you are wasting some time, when you try to access the HashMap, and the HashMap matches the string you entered to all the keys already in the HashMap. There is no need to use a HashMap. You can simply achieve all this with an array, with the index of the array as the key. I have changed map from a HashMap to a long array.
Something like this ::
public static long maxC(long map[], long coins[], int n) // n is the total number of monsters
{
if(n == 0) // If there are no monsters in the path
return 0;
if(n == 1) // Just in case there is only one monster in the way
return coins[0];
map[0] = coins[0];
map[1] = Math.max(map[0], coins[1]);
for(int i = 2; i < n; i++) {
map[i] = Math.max(map[i-2] + coins[i], map[i-1]);
}
return map[n - 1];
}
In the for loop I start by considering if there are only 2 monsters in the way, and use this solution in case there are 3 monsters, so on.
This significantly reduces the complexity of your program, since now you do not have to match strings. Moreover, here I have used the bottom-up approach here, you can definitely modify the above approach and use the top-bottom approach. Though I prefer bottom-up approach, since we do not make any recursive calls here, which I believe saves some time since we are not pushing and poping the function states from the stack.
EDIT ::
The top-bottom approach::
public static long maxC(long map[], long coins[], int n)
{
if(n-1 < 0)
return 0;
if(map[n - 1] != 0) {
return map[n - 1];
}
map[n - 1] = Math.max(maxC(map, coins, n-2) + coins[n - 1], maxC(map, coins, n-1));
return map[n - 1];
}
Here, I return 0 in case there are no monsters, and return map[n-1] case I already have a solution which I computed before.
Your initial call to the function looks something like this (from the main) ::
maxC(map, c, n);
We do not need the lower index in any case, so I removed it.
You can try any of the above approaches and you will get an AC, I believe. :D
I think that there is a much better and simpler approach to this.
Let us say we have an array of positive integers. All we have to do is maximise the sum as said in the question. To do that
Find the maximum value in the array(as long as it is not -1)
Add it to sum, and change its value and the two adjacent(i+1 and
i-1) to -1(so that they are not taken in consideration again).
Store the count of the -1s in the array and continue the loop till
countOfNegOnes==(n-1) or countOfNegOnes==(n).
Output sum

Given a stream of number, like 1,3,5,4,6,9, I was asked to print them like 1,3-6,9

Given a stream of number, like 1,3,5,4,6,9, I was asked to print them like 1,3-6,9. My approach was to hold min 2 numbers in a maxHeap and max 2 numbers in a minHeap. And I have come up with a following solution. Do you have any suggestion to make it more optimized? Its time complexity is O(nlogn).
public static ArrayList<Integer> mergingMiddleNums (int[] arr){
if (arr == null || arr.length < 3){
throw new IllegalArgumentException();
}
ArrayList<Integer> result = new ArrayList<>();
Queue<Integer> minHeap = new PriorityQueue<>();
Queue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
#Override
public int compare(Integer num1, Integer num2) {
return num2-num1;
}
});
for (int i = 0 ; i < 2 ; i++){
minHeap.add(arr[i]);
}
for (int i = 0 ; i < 2 ; i++){
maxHeap.add(arr[i]);
}
for (int i = 2 ; i <arr.length; i++){
if(arr[i] > minHeap.peek()){
minHeap.poll();
minHeap.add(arr[i]);
}
}
result.add(minHeap.poll());
result.add(minHeap.poll());
for (int i = 2 ; i <arr.length; i++){
if(arr[i] < maxHeap.peek()){
maxHeap.poll();
maxHeap.add(arr[i]);
}
}
result.add(maxHeap.poll());
result.add(maxHeap.poll());
Collections.sort(result);
return result;
}
It depends on whether your output needs to stream or not. Let's start with non-streaming output, because your current implementation addresses this.
Your code's overall complexity will be, at best, O(nLog(n)), but you can radically simplify your implementation by storing every incoming number in a collection, converting it to an array, and sorting it, before scanning over the items sequentially to identify continuous ranges. The most expensive operation here would be the sort, which would define your runtime. To save space, you could use a set or heap collection to avoid storing duplicates (the formation of which will be somewhere near O(nLog(n)) - which being the same runtime, remains collapsed at a total runtime of O(nLog(n))
If your code is expected to stream the printing along with output, that is, to print ranges as they are formed and move to the next range whenever the next number encountered is not directly adjacent to the current range, you can do it in O(n) by storing the numeric bounds of the current range as you go and either printing and resetting them if the currently-examined number is not adjacent or inside the bounds, or by expanding the bounds if it is.
A possible implementation would be to use a hashtable to store wether each integer was present in the input values or not. Then, it's simply a matter of iterating from the min value to the max and use the hashtable to find out where are the number clusters.
Such implementation would basically be O(n) with n=max-min (and not number of items in list). So if you have many numbers within a reasonably small range of values, then you could be better than a sort-based approach.
import java.util.HashMap;
import java.util.Map;
class Test {
private int min=0, max=-1;
private Map<Integer,Integer> map=new HashMap<Integer,Integer>();
public static void main(String args[]) {
int[] input={1,3,5,4,6,9};
Test t = new Test();
t.readNumbers(input);
t.outputRanges();
}
public void readNumbers(int[] values) {
// Get min and max values, and store all existing values in map
for(int v:values) {
if(first || v<min) min=v;
if(first || v>max) max=v;
first=false;
map.put(v, 1);
}
}
public void outputRanges() {
// Iterate from min to max and use map to find out existing
// values
int last=min-2;
boolean inRange=false;
first=true;
for(int i=min;i<=max;++i) {
if(map.get(i)==null) continue;
if(i==last+1) {
inRange=true;
} else {
if(inRange) {
closeRange(last);
inRange=false;
}
output(i);
}
last=i;
}
if(inRange) closeRange(last);
}
private boolean first;
private void commaUnlessFirst() {
if(!first) System.out.printf(",");
first=false;
}
private void output(int i) {
commaUnlessFirst();
System.out.printf("%d", i);
}
private void closeRange(int i) {
System.out.printf("-%d", i);
}
}

Parallel prime factorization [duplicate]

This question already has an answer here:
Parallel Algorithms for Generating Prime Numbers (possibly using Hadoop's map reduce)
(1 answer)
Closed 9 years ago.
Does anyone have any idea what's the approach for parallel prime factorization algorithm ?
I can't figure out at which stage of the algorithm I should divide it into threads ..
How can I think about Prime factorization in a parallel way ?
consider the following one thread code:
public static void primeFactorization(ArrayList<Integer> factors, int num){
//factors is an array to save the factorization elements
//num is the number to be factorized
int limit = num/2+1;
if(isPrime(num))
factors.add(num);
else{
while(num%2==0){
factors.add(2);
num=num/2;
}
for (int i=3; i<limit; i+=2){
while (isPrime(i) && num%i==0){
factors.add(i);
num = num/i;
}
}
}
}
private static boolean isPrime(int x) {
int top = (int)Math.sqrt(x);
for (int i = 2; i <= top; i++)
if ( x % i == 0 )
return false;
return true;
}
It seems like this could be a really good use for the Fork/Join Framework. It seems like you should be able to use this by recursively passing in the new factors that you find. Try taking a look at RecursiveAction as well. In pseudo code you should be able to do something like the following:
public void getFactors(List<Integer> factors, int num){
if(you can find a factor){
add the two factors to the pool to be factored further
}
else{
factors.add(num);
}
}
As a side note, it might have better performance if you started in the middle (num/2) and went from there opposed to starting at one.

Algorithm that takes an integer and returns all possible format of addition

I need to write an algorithm that takes an integer and returns all possible format of addition
e.g.
If I eneter: 6
it would return the following String:
0+6=6
1+1+1+1+1+1=6
1+1+1+1+2=6
1+1+1+3=6
1+1+4=6
1+5=6
2+1+1+1+1=6
2+1+1+2=6
2+1+3=6
2+4=6
3+1+1+1=6
3+1+2=6
3+3=6
4+1+1=6
4+2=6
5+1=6
6+0=6
Here is my try:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Enter an integer? ");
int num = in.nextInt();
System.out.println();
calculate(num);
}
private static void calculate(int n)
{
int[] arInt = new int[n];
for(int i = 0; i <= n; i++)
{
for(int j = 0; j <= n; j++)
{
arInt[j] = i;
}
// ...
}
}
}
I agree with Brad. The best way to complete this would probably be through recursion. In fact, I was working on something related to this last night. I solved my problem using a recursive backtracking algorithm. Check out the Wikipedia page: Backtracking
Now, I make no guarantees that there aren't better, less complex ways to solve this. However, with recursive backtracking you will find all the solutions.
One thing to watch out for though, that 0. You can throw any amount of zeros into an addition/subtraction and it will come out the same.
If you asked the question, you are probably stuck... so i give you a hint :
Usually, in this kind of problem, you do not consider the same combinations with different permutations as different counts, and you do not consider addtion by 0: see Partition.
However, in your example, you seem to be distinguishing different permutations and counting 0. I am pertty much sure that you are not supposed to include 0 because that will give you infinitely many examples to any n. (By the way the answer you gave does not include all counts.) So I assume that you distinguish different permutations but not allow segment into 0. That actually makes the problem much easier.
Suppose you have n = 6.
O O O O O O
^ ^ ^ ^ ^
Think about the n - 1 = 5 positions between the six objects above. For each position, you can decide to either segment at the point or not. For example,
O|O O O|O O
^ ^ ^ ^ ^
is one possible segmentation. Interpret this as: 1+3+2, taking the consecutive objects not segmented by '|'. You should be able to get all possible ways in this way. Namely, for n-1 positions, either segment it or not. For any n, your list should be of 2^(n-1) examples.
E.g. for n = 3:
1+1+1, 2+1, 1+2, 3 => 4 different ways = 2^(3-1)
for n = 6, you should have 2^(6-1) = 32 examples, but you only have 17, which immediately tells that your list is not complete.
Finally note that, as I wrote at the beginning, your question is different from the partion question which is much more standard.
It looks like a homework, so I won't try to write it for you. But I will give you a hint about the solution. You have fixed quantity, imagine e.g. marbles. You are trying to find all possible numbers that add up to that quantity. This means you have to divide the marbles into groups somehow. If you know basic combinatorics, you can easily count the possibilities and enumerate them using an algorithm. Good luck!
Possible solution in Java using recursion:
public void run(int n)
{
List<StringBuilder> combos = showAdditionsFor(n);
for (StringBuilder s : combos)
{
if (s.indexOf("+") < 0)
{
System.out.println(s + " + 0 = " + n);
System.out.println("0 + " + s + " = " + n);
}
else
{
System.out.println(s + " = " + n);
}
}
}
List<StringBuilder> showAdditionsFor(int n)
{
List<StringBuilder> list = new ArrayList<StringBuilder>();
if (n == 0)
list.add(new StringBuilder(""));
else if (n == 1)
list.add(new StringBuilder(String.valueOf(1)));
else
{
for (int i = 1; i <=n; i++)
{
//get n-i list
List<StringBuilder> tempList = showAdditionsFor(n-i);
appendToEachListElement(String.valueOf(i),tempList);
list.addAll(tempList);
}
}
return list;
}
private void appendToEachListElement(String x, List<StringBuilder>l)
{
for (StringBuilder s : l)
{
if (s.length() == 0)
s.append(x);
else
s.append("+" + x);
}
}

Categories

Resources