Related
I am constructing a simulation of beehive and I make use of a 2D array called workerBee.
It has the following 6 fields: beeId, Age, Type(egg = 1, larva = 2, pupa = 3, worker = 4, drone = 5), PollenCollection, Eaten, Alive
Brief about the model: The Queen Bee lays eggs daily(10 to 50 eggs) and they are added to the hive.Each day, data about the bees are updated(their age and type).
For every day that passes, I print the beehive status which prints information about the number of bees, births, deaths etc..
For some days during the simulation(at the beginning, say day 6 to 10), the number of larva reported is around 800 to 900 for 1 day.
Here are the codes that deal with the printing and counting:
public static int layDailyEggs() {
Random randomEggs = new Random();
final int MAX_EGGS = 50;
final int MIN_EGGS = 10;
int x = randomEggs.nextInt((MAX_EGGS - MIN_EGGS) + 1) + MIN_EGGS;
eggsLaid = x;//eggsLaid as a global variable to be used in printBeehiveStatus
return x;//To pass as argument to addEggToHive
}
public static void addEggToHive(int eggsLaid) {
//Update the workerBee array with available slots
//Traverse the 2D array and while beeId != 0, add eggs and update
for (int i = 0; i < workerBee.length; i++) {
if (workerBee[i][0] == 0 && eggsLaid > 0) {
//Available space
workerBee[i][0] = i;//Update beeID
workerBee[i][1] = 1;//Update age
workerBee[i][2] = 1;//Update Type
eggsLaid--;
}
}
}
public static void countTypesOfBees() {
//Initialize for each day
totalEggsLaid = 0;
numberOfBirths = 0;
numberOfLarva = 0;
numberOfPupa = 0;
numberOfWorkerBees = 0;
numberOfDrones = 0;
//To call upon updating type of each bee
for (int i = 0; i < workerBee.length; i++) {
if(workerBee[i][2] == 1) {
totalEggsLaid++;
}else if(workerBee[i][2] == 2) {
numberOfLarva++;
numberOfBirths++;
}else if(workerBee[i][2] == 3) {
numberOfPupa++;
numberOfBirths++;
}else if(workerBee[i][2] == 4) {
numberOfWorkerBees++;
numberOfBirths++;
}else if(workerBee[i][2] == 5) {
numberOfDrones++;
numberOfBirths++;
}
}
}
//Method called once daily
public static void metamorphose() {
numberOfDeaths = 0;
Random random = new Random();
for (int i = 0; i < workerBee.length; i++) {
//Updating the type of bee based on age of Bee
if(workerBee[i][1] == 4) {
workerBee[i][2] = 2;
}else if (workerBee[i][1] == 10) {
workerBee[i][2] = 3;
}else if(workerBee[i][1] == 20){
//Probability for a drone to emerge is 10%(As per area under curve, should be less than or equal to 10%)
double probability = random.nextDouble();
if (probability <= 0.1) {
workerBee[i][2] = 5;//Drone Bee
}else{
workerBee[i][2] = 4;//Worker Bee
}
}
if (workerBee[i][1] == 35 || workerBee[i][1] == 56) {
//Call a funeral
funeral(i);
numberOfDeaths++;
}
}
countTypesOfBees();
}
//To be called at the end of the day
public static void printBeehiveStatus() {
System.out.print("Queen laid " + eggsLaid + " eggs!" +
"\nBeehive status\nEgg Count: "+ totalEggsLaid + "\nLarva Count: " + numberOfLarva + "\nPupa Count: " + numberOfPupa +
"\nWorker Count: "+ numberOfWorkerBees + "\nDrone Count: " + numberOfDrones +
"\nDeath Count: " + numberOfDeaths + "\nBirth Count: "+ numberOfBirths +
"\nHoney Stock: " + honeyStock +"\n");
printFlowerGarden();
}
The index of the fields of the workerBee array are in the order specified above.
The order which which they are executed each day are as follows(Note that they are not the complete set)
addEggToHive(layDailyEggs());
incrementAge();
metamorphose();
printBeehiveStatus();
Screenshot [1]: https://i.stack.imgur.com/qTeuo.png
Screenshot [2]: https://i.stack.imgur.com/eMsHq.png
Note
The eggs hatches into larva when it is 4 days old
If there is anything else that you think might be causing the problem, tell me I'll upload that part of the code.
Found the solution.
Actually, the method incrementAge() was supposed to increase the ages of all bees in the hive by 1 each day. However, I was simply incrementing all ages in the array without checking whether that particular row is an actual bee or not as I had initialized unused rows to 0
I have written some java code to determine the sum of what three cubes give you a given number. (Sorry I'm really not sure how to explain what it does, the code is rather simple though.) And the problem is, when searching for numbers between -100 and 100 the code runs very quick. But when searching a bigger area, (thousands or ten-thousands etc) It starts to run very slow, even when looking for small numbers. What I am asking are for ways to optimize it, and maybe ways to have it search more systematically, starting at small integers and working its way up to bigger ones, rather than how it does it now which is to pick random ones and check them with the answer.
Here is the code:
public class test{
public static void main(String[] args)
{
int want = -69;
double test;
boolean found = false;
int answer;
while(found == false)
{
int max = 100;
int min = max / 2;
int a = (int) (Math.random()*max - min);
int b = (int) (Math.random()*max - min);
int c = (int) (Math.random()*max - min);
test = Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3);
answer = (int) test;
if(answer == want) {
found = true;
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
}
}
}
}
This is generally not an easy problem. A more systematic way of doing this would be to test every possible combination of a,b and c within a given range of values for a,b and c. Like this:
public class Main{
static boolean foundSolution = false;
public static void main(String []args){
int limit = 10;
boolean[][][] alreadyChecked = new boolean[limit*2+1][limit*2+1][limit*2+1];
foundSolution = false;
printCubesOfNum(-69,limit,0,0,0,alreadyChecked);
}
public static void printCubesOfNum(int answer,int limit, int a, int b, int c,boolean[][][] alreadyChecked) {
if(!foundSolution && !alreadyChecked[a+limit][b+limit][c+limit] && a < limit && a > -limit && b < limit && b > -limit && c < limit && c > -limit) {
alreadyChecked[a+limit][b+limit][c+limit] = true;
int test = (int)Math.pow(a, 3) + (int)Math.pow(b, 3) + (int)Math.pow(c, 3);
if(test == answer) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
foundSolution = true;
}else{
printCubesOfNum(answer,limit,a+1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b+1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c+1,alreadyChecked);
printCubesOfNum(answer,limit,a-1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b-1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c-1,alreadyChecked);
}
}
}
}
Note that this code stops after it found a solution. There can be multiple solutions and there can also be no solutions.
You can check out a similar question on mathoverflow here.
What I am asking are for […] maybe ways to have it search more systematically, starting at small integers and working its way up to bigger ones, […]
Instead of a while-loop, you might consider using nested for-loops:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
for (int c = min; c < max; ++c) {
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
}
But you don't actually need to try each possible value for c; rather, you know that c3 = want − a3 − b3; so you can just calculate that directly, and see if it works out:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
// Note: the '0.1' is to be robust if there's some roundoff error:
int c = (int) (0.1 + Math.pow(want - Math.pow(a, 3) - Math.pow(b, 3), 1.0/3.0));
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want && c >= min && c <= max) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
And for that matter, the symmetry of the problem (the commutative law of addition) means that we only need to try values of b that are at least equal to a:
for (int b = a; b < max; ++b) {
Another optimization is to avoid Math.pow(..., 3), which is generally much less efficient than ... * ... * ... (because Math.pow has to support non-integer exponents, so it works by taking a logarithm and an exponentiation):
int c = (int) (0.1 + Math.pow(want - a * a * a - b * b * b, 1.0/3.0));
int answer = a * a * a + b * b * b + c * c * c;
Yet another optimization is to restrict the range of b, in the inner for-loop, to only include values that would put c in the range of [min, max): we know that if b is too small, then c would have to be too big, and vice versa:
int minB = (int) (0.1 + Math.pow(want - a * a * a - max * max * max, 1.0/3.0));
if (minB < a) {
minB = a;
}
int maxB = (int) (0.1 + Math.pow(want - a * a * a - min * min * min, 1.0/3.0)) + 1;
if (maxB > max) {
maxB = max;
}
for (int b = minB; b < maxB; ++b) {
Of course, these sorts of optimizations can only take you so far. If you want to search a large range of integers, that will necessary take a lot of time. But the above should still be a massive improvement over what you have now.
I have the following program to write:
An interesting (yet unsolved) question in mathematics is called "hailstone numbers". This series is produced by taking an initial integer and if the number is even, dividing it by 2. If the number is odd, multiply it by 3 and add 1. This process is the repeated.
For example: An initial number of 10 produces: 10, 5, 16, 8, 4, 2, 1, 4, 2, 1... An initial value of 23 produces: 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1...
Note that both numbers eventually reach the 4, 2, 1, 4, 2, 1... cycle.
Create an application that offers the user three different ways to run this program.
Option 1: Print the hailstone numbers for a single entry and its length
Example: Input> 10 10, 5, 16, 8, 4, 2, 1 Length 7
Option 2: Print all of the hailstone numbers from 4 to a given entry
Example: Input> 6 4, 2, 1 Length 3 5, 16, 8, 4, 2, 1 Length 6 6, 3, 10, 5, 16, 8, 4, 2, 1 Length 9
Option 3: Print out the number with the maximum number of iterations need to reach the cycle and which starting number produces this maximum from 4 to the number entered.
Example: Input> 6 Longest: 6 Length: 9
In writing this program you must implement the following method...
/**
*
* #param num Number that a hailstone chain will be generated
* #param showNumbers true if list of numbers is shown to screen
* #return Count of the numbers in the num hailstone chain.
*/
private static int hailStone(int num, boolean showNumbers) {
// your code
}
This is the code I've written so far:
public static void main(String[] args) {
int a = getInt("Give a number: ");
System.out.print("How would you like to run the program? Option 1 prints hailstone numbers for a single entry and its length." +
"Option 2 prints all the hailstone numbers from 4 to a given entry. Option 3 prints the number with the maximum number" +
"of iterations needed to reach the 4, 2, 1 cycle.");
int option = console.nextInt();
boolean showNumbers = (option == 1 || option == 2);
hailStone(a, showNumbers);
}
public static int getInt(String prompt) {
int input;
System.out.print(prompt);
input = console.nextInt();
return input;
}
private static void hailStone (int a, boolean showNumbers) {
if (showNumbers == true) {
if (a % 2 == 0) {
for (int i = 0; i < 50; i++) {
for (int j = 0; j <= i; j++)
a /= 2;
System.out.print(a + " ");
a *= 3;
a += 1;
System.out.print(a + " ");
}
} else {
for (int i = 0; i != a; i++) {
}
}
} else {
}
}
I feel like I've hit a brick wall because I have no idea how to implement all these options in the method my teacher is requiring us to use. Plus, I can't seem to get even the basic hailstone chain to print. Help?
The HailStone algorithm should not be hard to implement. It will actually be much easier if you make it a recursive function, since that is more natural Writing it as an iterative function is probably what is causing your issues.
This should be enough to get you started, this is a working HailStone implementation using a recursive function. You can implement the rest of the project requirements quite easily once you've got the algorithm working... but I'd like to challenge you to convert this into a working iterative function once you get the features correct and to write unit tests to test the program. (TDD dictates that you should write your tests BEFORE you write the actual implementation. This is a great practice that is often skipped due to time constraints and the perception that a strong test suite is overkill.)
HailStone.java
public class HailStone {
/* static variable to count calls to hailStone */
public static int iterCount = 0;
/* This variable is a senti */
public static boolean isRepeating = 0;
/* Simple main function */
public static void main(String[] args) {
// TODO:
// Either parse args or use a scanner to get input.
// Args = verbose, entryPoint
hailStone(10, true);
}
/* Recursive hailStone implementation */
private static void hailStone(int a, boolean showNumbers) {
// start off by printing the numbers if showNumbers is true
if (showNumbers) {
System.out.printf("Iteration #%d: %d\n", ++iterCount, a);
}
// base case: a = 1 => most important part of recursion
if (a == 1) {
if (isRepeating) {
return;
}
isRepeating = true;
}
// check if a is odd
// You can use modulo divison, but we'll use bitwise &
/* Explained: [ bitwise AND... bits that are set in a AND in 1 ]
**********************************************
Case 1: a is even =>
a = 10
10 in binary is 00001010
1 in binary is 00000001
------------------------------
10 & 1 in binary is 00000000
Case 2: a is odd =>
a = 10
11 in binary is 00001011
1 in binary is 00000001
------------------------------
11 & 1 in binary is 00000001
**********************************************
set(X) = set of all even numbers
set(Y) = set of all odd numbers
{
x is any arbitrary number in set X,
y is any arbitrary number in set Y
}
x & 1 will ALWAYS equal 0 -\
>- know this. bitwise hacks rock.
y & 1 will ALWAYS equal 1 -/
*/
if ((a & 1) == 1) {
a *= 3;
a += 1;
} else {
a /= 2;
}
// Tail recursion.
hailStone(a, showNumbers);
return;
}
}
without all the comments and extra stuff:
public class HailStone {
public static int iter_count = 0;
public static void main(String[] args) {
hailStone(10, true);
}
/* Recursive hailStone implementation */
private static void hailStone(int a, boolean showNumbers) {
if (showNumbers) {
System.out.printf("Iteration #%d: %d\n", ++iter_count, a);
}
// base case: a = 1
if (a == 1) {
return;
}
if ((a & 1) == 1) { // a is odd:
a *= 3;
a += 1;
} else {
a /= 2;
}
hailStone(a, showNumbers);
return;
}
}
private static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("How would you like to run the program?");
System.out.println(" [1] - print hailstone numbers for a single entry and its length.");
System.out.println(" [2] - print all hailstone numbers from 4 to a given entry.");
System.out.println(" [3] - print the number with the maximum number of iterations needed to reach the 4, 2, 1 cycle.");
int option = queryInt("Option: ", 1, 3);
switch (option) {
case 1: {
int seed = queryInt("INPUT> ", 1, Integer.MAX_VALUE);
hailStone(seed, true);
break;
}
case 2: {
int maxSeed = queryInt("INPUT> ", 4, Integer.MAX_VALUE);
for (int i = 4; i <= maxSeed; i++) {
hailStone(i, true);
}
break;
}
case 3: {
int maxSeed = queryInt("INPUT> ", 4, Integer.MAX_VALUE);
int longestChain = 0;
int longestChainLength = 0;
for (int i = 4; i <= maxSeed; i++) {
int length = hailStone(i, false);
if(length > longestChainLength) {
longestChain = i;
longestChainLength = length;
}
}
System.out.println("Longest: " + longestChain + " Length: " + longestChainLength);
break;
}
}
}
private static int queryInt(String prompt, int min, int max) {
while (true) {
System.out.print(prompt);
String input = console.nextLine();
try {
int result = Integer.parseInt(input);
if (result >= min && result <= max) {
return result;
} else {
System.err.print("Expected a number ");
if (min == Integer.MIN_VALUE) {
System.err.println(" less than or equal to " + max);
} else if (max == Integer.MAX_VALUE) {
System.err.println(" greater than or equal to " + min);
} else {
System.err.println(" between " + min + " and " + max);
}
}
} catch (NumberFormatException ex) {
System.err.println("Not a number: " + input);
}
}
}
private static int hailStone(int num, boolean showNumbers) {
int result = 1;
for (Iterator<Integer> chain = iterateHailStone(num); num != 1; num = chain.next(), result++) {
if (showNumbers) {
System.out.print(num + ", ");
}
}
if (showNumbers) {
System.out.print(num);
System.out.println(" (length=" + result + ")");
}
return result;
}
private static Iterator<Integer> iterateHailStone(int seed) {
return new Iterator<Integer>() {
int value = seed;
#Override
public boolean hasNext() {
return true;
}
#Override
public Integer next() {
if (value % 2 == 0) {
value /= 2;
} else {
value *= 3;
value++;
}
return value;
}
};
}
Example:
numbers are [1, 2, 3] and u have +, *
max value is 1+2*3
example [1, 1, 1] , ans is 1+1+1
I can think of a simple recursive algorithm:
private static double helper(double[] arr, int s, int e) {
System.out.println("s= " + s + " e= " + e);
//base case: if single elem, return that eleme
if (e==s) {
return arr[s];
} if (s+1==e) {
return Math.max(arr[s]+arr[e], arr[s]*arr[e]);
} else if (s>e) {
//this should never happen
throw new UnsupportedOperationException("invalid operation");
}
//int mid = s+ ((e-s)/2);
int mid=s;
double fMax = Double.MIN_VALUE;
for (mid=s;mid<e;mid++) {
//divide and conqr route
double lres = helperDQ(arr,s, mid);
double rres = helperDQ(arr,mid+1, e );
System.out.println("s= " + s + " e = " + e + " m = " + mid + " lres= " + lres + " rres= " + rres);
fMax = Math.max(fMax, Math.max(lres*rres, lres+rres));
}
return fMax;
}
private static double findMax(double[] arr) {
return helper(arr, 0, arr.length-1);
}
Is there a better way to do instead of this recursive way? We can prune the recursion by checking for s, e so we dont end up recursing same thing multiple times.
Can't think of an easy dynamic programming approach way.
Any suggestions?
This can actually be solved a lot easier, using some simple math. For any two numbers a and b, the following applies: unless either a = 1 or b = 1 is given, a * b >= a + b is given (assuming a >= 1 and b >= 1). This applies recursively to any set of numbers. Thus the maximum will always be achieved by
int maxNum(int[] nums){
int x = 0;
for(int n : nums)
if(n == 1)
x += n;
else
if(x == 0)
x = n;
else
x *= n;
return x;
}
If the set of numbers is order.
I am stuck on the coin denomination problem.
I am trying to find the lowest number of coins used to make up $5.70 (or 570 cents). For example, if the coin array is {100,5,2,5,1} (100 x 10c coins, 5 x 20c, 2 x 50c, 5 x $1, and 1 x $2 coin), then the result should be {0,1,1,3,1}
At the moment the coin array will consist of the same denominations ( $2, $1, 50c, 20c, 10c)
public static int[] makeChange(int change, int[] coins) {
// while you have coins of that denomination left and the total
// remaining amount exceeds that denomination, take a coin of that
// denomination (i.e add it to your result array, subtract it from the
// number of available coins, and update the total remainder). –
for(int i= 0; i< coins.length; i++){
while (coins[i] > 0) {
if (coins[i] > 0 & change - 200 >= 0) {
coins[4] = coins[4]--;
change = change - 200;
} else
if (coins[i] > 0 & change - 100 >= 0) {
coins[3] = coins[3]--;
change = change - 100;
} else
if (coins[i] > 0 & change - 50 >= 0) {
coins[2] = coins[2]--;
change = change - 50;
} else
if (coins[i] > 0 & change - 20 >= 0) {
coins[1] = coins[1]--;
change = change - 20;
} else
if (coins[i] > 0 & change - 10 >= 0) {
coins[0] = coins[0]--;
change = change - 10;
}
}
}
return coins;
}
I am stuck on how to deduct the values from coins array and return it.
EDIT: New code
The brute force solution is to try up to the available number of coins of the highest denomination (stopping when you run out or the amount would become negative) and for each of these recurse on solving the remaining amount with a shorter list that excludes that denomination, and pick the minimum of these. If the base case is 1c the problem can always be solved, and the base case is return n otherwise it is n/d0 (d0 representing the lowest denomination), but care must be taken to return a large value when not evenly divisible so the optimization can pick a different branch. Memoization is possible, and parameterized by the remaining amount and the next denomination to try. So the memo table size would be is O(n*d), where n is the starting amount and d is the number of denominations.
So the problem can be solved in pseudo-polynomial time.
The wikipedia link is sparse on details on how to decide if a greedy algorithm such as yours will work. A better reference is linked in this CS StackExchange question. Essentially, if the coin system is canonical, a greedy algorithm will provide an optimal solution. So, is [1, 2, 5, 10, 20] canonical? (using 10s of cents for units, so that the sequence starts in 1)
According to this article, a 5-coin system is non-canonical if and only if it satisfies exactly one of the following conditions:
[1, c2, c3] is non-canonical (false for [1, 2, 5])
it cannot be written as [1, 2, c3, c3+1, 2*c3] (true for [1, 2, 5, 10, 20])
the greedyAnswerSize((k+1) * c4) > k+1 with k*c4 < c5 < (k+1) * c4; in this case, this would require a k*10 < 20 < (k+1)*10; there is no integer k in that range, so this is false for [1, 2, 5, 10, 20].
Therefore, since the greedy algorithm will not provide optimal answers (and even if it did, I doubt that it would work with limited coins), you should try dynamic programming or some enlightened backtracking:
import java.util.HashSet;
import java.util.PriorityQueue;
public class Main {
public static class Answer implements Comparable<Answer> {
public static final int coins[] = {1, 2, 5, 10, 20};
private int availableCoins[] = new int[coins.length];
private int totalAvailable;
private int totalRemaining;
private int coinsUsed;
public Answer(int availableCoins[], int totalRemaining) {
for (int i=0; i<coins.length; i++) {
this.availableCoins[i] = availableCoins[i];
totalAvailable += coins[i] * availableCoins[i];
}
this.totalRemaining = totalRemaining;
}
public boolean hasCoin(int coinIndex) {
return availableCoins[coinIndex] > 0;
}
public boolean isPossibleBest(Answer oldBest) {
boolean r = totalRemaining >= 0
&& totalAvailable >= totalRemaining
&& (oldBest == null || oldBest.coinsUsed > coinsUsed);
return r;
}
public boolean isAnswer() {
return totalRemaining == 0;
}
public Answer useCoin(int coinIndex) {
Answer a = new Answer(availableCoins, totalRemaining - coins[coinIndex]);
a.availableCoins[coinIndex]--;
a.totalAvailable = totalAvailable - coins[coinIndex];
a.coinsUsed = coinsUsed+1;
return a;
}
public int getCoinsUsed() {
return coinsUsed;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
for (int c : availableCoins) sb.append(c + ",");
sb.setCharAt(sb.length()-1, '}');
return sb.toString();
}
// try to be greedy first
#Override
public int compareTo(Answer a) {
int r = totalRemaining - a.totalRemaining;
return (r==0) ? coinsUsed - a.coinsUsed : r;
}
}
// returns an minimal set of coins to solve
public static int makeChange(int change, int[] availableCoins) {
PriorityQueue<Answer> queue = new PriorityQueue<Answer>();
queue.add(new Answer(availableCoins, change));
HashSet<String> known = new HashSet<String>();
Answer best = null;
int expansions = 0;
while ( ! queue.isEmpty()) {
Answer current = queue.remove();
expansions ++;
String s = current.toString();
if (current.isPossibleBest(best) && ! known.contains(s)) {
known.add(s);
if (current.isAnswer()) {
best = current;
} else {
for (int i=0; i<Answer.coins.length; i++) {
if (current.hasCoin(i)) {
queue.add(current.useCoin(i));
}
}
}
}
}
// debug
System.out.println("After " + expansions + " expansions");
return (best != null) ? best.getCoinsUsed() : -1;
}
public static void main(String[] args) {
for (int i=0; i<100; i++) {
System.out.println("Solving for " + i + ":"
+ makeChange(i, new int[]{100,5,2,5,1}));
}
}
}
You are in wrong direction. This program will not give you an optimal solution. To get optimal solution go with dynamic algorithms implemented and discussed here. Please visit these few links:
link 1
link 2
link 3