Comparing an array of item with two attributes - java

I met a question that I have problem solving in Java. The question goes like this:
John was asked to design a program that picks a bottle. The program has to decide from 4 bottles: Bottle A, B, C, D. There might be holes in some of the bottles. Therefore, the program must prevent picking bottles which have holes and also the largest bottle so as to carry as much water as possible.
Bottle A - has holes and can hold 5 litres of water
Bottle B - no holes and can hold 2 litres of water
Bottle C - no holes and can hold 3 litres of water
Bottle D - no holes and can hold 1 litre of water`
I have tried programming it in Java using a nested for loop. However, it does not give me the correct answers.
Bottle[] bottles = {a, b, c, d};
Bottle chosen = a;
for(int i=0; i<bottles.length; i++)
{
for(int j=i+1; j<bottles.length; j++)
{
if(bottles[i].capacity < bottles[j].capacity && bottles[j].noHoles())
{
chosen = bottles[j];
}
}
}
System.out.println(chosen.id);

First, since you are picking a single thing, all you need is a single loop. Second, since one of the properties (namely, noHoles()) is compared to a fixed value (i.e. it must be true) the only thing left for comparison is the capacity.
Hence, the algorithm looks like this:
Set the best bottle to null
Make a single loop that goes through bottles one by one
Check if the current bottle has no holes; if it does, continue the loop
Check if the best bottle is null. If it is, set best to current
Otherwise, compare the capacities of current and best, and set best to the bottle with larger capacity.

Your question is a little confusing so I am not sure if I answered what your asked. But if you only need to check if the Bottle has holes or not, you do not need to use nested for loops. I'd recommend use enhanced for loop. something like this:
for(Bottle bot : bottles){
if(bot.noHoles()) //i assume noHoles is bollean type
System.out.println(bot);
}

Try it as:
Bottle[] bottles = {a, b, c, d};
Bottle chosen = bottles[0];
for(int i=1; i<bottles.length; i++)
{
if(bottles[i].noHoles() && bottles[i].capacity > chosen.capacity)
chosen = bottles[i];
}
System.out.println(chosen.id);

Related

Using nested loops

I'm really struggling to do this! z is an array of gravitational fields. To find the total gravitational field acting on a planet, say earth, I want to add all the entries together, while excluding the entry for earth's gravitational field, because earth's gravity doesn't act on earth itself.
For example, say z = [earthGrav, sunGrav, marsGrav, moonGrav]. Then the total field on earth is sunGrav+ marsGrav + moonGrav. I could maybe deal with this by using s=i+1. But that doesn't work subsequently, for the sun, when sunGrav = earthGrav+marsGrav+moonGrav, because the first entry would be left out!
for(int i=0; i<planets.length;i++){
for(int s=0;s<z.length;s++){
if(i!=s){
sum1.increaseBy(z[s]);
newP[i] = planets[i].updatePosition(position[i], velocity[i], timeStep, sum1);
}
else{
sum1.scale(1);
}
}
}
Problem is, the way I've done it above means whenever I add 1 to i, 1 also gets added to s, so s and i are always the same and the if statement never gets executed! Can anyone think of a way to do this?

How to hard-code legal moves for fast lookup?

I have created a gameboard (5x5) and I now want to decide when a move is legal as fast as possible. For example a piece at (0,0) wants to go to (1,1), is that legal? First I tried to find this out with computations but that seemed bothersome. I would like to hard-code the possible moves based on a position on the board and then iterate through all the possible moves to see if they match the destinations of the piece. I have problems getting this on paper. This is what I would like:
//game piece is at 0,0 now, decide if 1,1 is legal
Point destination = new Point(1,1);
destination.findIn(legalMoves[0][0]);
The first problem I face is that I don't know how to put a list of possible moves in an array at for example index [0][0]. This must be fairly obvious but I am stuck at this for some time. I would like to create an array in which there is a list of Point objects. So in semi-code: legalMoves[0][0] = {Point(1,1),Point(0,1),Point(1,0)}
I am not sure if this is efficient but it makes logically move sense than maybe [[1,1],[0,1],[1,0]] but I am not sold on this.
The second problem I have is that instead of creating the object at every start of the game with an instance variable legalMoves, I would rather have it read from disk. I think that it should be quicker this way? Is the serializable class the way to go?
My 3rd small problem is that for the 25 positions the legal moves are unbalanced. Some have 8 possible legal moves, others have 3. Maybe this is not a problem at all.
You are looking for a structure that will give you the candidate for a given point, i.e. Point -> List<Point>.
Typically, I would go for a Map<Point, List<Point>>.
You can initialise this structure statically at program start or dynamically when needing. For instance, here I use 2 helpers arrays that contains the possible translations from a point, and these will yield the neighbours of the point.
// (-1 1) (0 1) (1 1)
// (-1 0) (----) (1 0)
// (-1 -1) (0 -1) (1 -1)
// from (1 0) anti-clockwise:
static int[] xOffset = {1,1,0,-1,-1,-1,0,1};
static int[] yOffset = {0,1,1,1,0,-1,-1,-1};
The following Map contains the actual neighbours for a Point with a function that compute, store and return these neighbours. You can choose to initialise all neighbours in one pass, but given the small numbers, I would not think this a problem performance wise.
static Map<Point, List<Point>> neighbours = new HashMap<>();
static List<Point> getNeighbours(Point a) {
List<Point> nb = neighbours.get(a);
if (nb == null) {
nb = new ArrayList<>(xOffset.length); // size the list
for (int i=0; i < xOffset.length; i++) {
int x = a.getX() + xOffset[i];
int y = a.getY() + yOffset[i];
if (x>=0 && y>=0 && x < 5 && y < 5) {
nb.add(new Point(x, y));
}
}
neighbours.put(a, nb);
}
return nb;
}
Now checking a legal move is a matter of finding the point in the neighbours:
static boolean isLegalMove(Point from, Point to) {
boolean legal = false;
for (Point p : getNeighbours(from)) {
if (p.equals(to)) {
legal = true;
break;
}
}
return legal;
}
Note: the class Point must define equals() and hashCode() for the map to behave as expected.
The first problem I face is that I don't know how to put a list of possible moves in an array at for example index [0][0]
Since the board is 2D, and the number of legal moves could generally be more than one, you would end up with a 3D data structure:
Point legalMoves[][][] = new legalMoves[5][5][];
legalMoves[0][0] = new Point[] {Point(1,1),Point(0,1),Point(1,0)};
instead of creating the object at every start of the game with an instance variable legalMoves, I would rather have it read from disk. I think that it should be quicker this way? Is the serializable class the way to go?
This cannot be answered without profiling. I cannot imagine that computing legal moves of any kind for a 5x5 board could be so intense computationally as to justify any kind of additional I/O operation.
for the 25 positions the legal moves are unbalanced. Some have 8 possible legal moves, others have 3. Maybe this is not a problem at all.
This can be handled nicely with a 3D "jagged array" described above, so it is not a problem at all.

Procedural World Generation

I am generating my world (random, infinite and 2d) in sections that are x by y, when I reach the end of x a new section is formed. If in section one I have hills, how can I make it so that in section two those hills will continue? Is there some kind of way that I could make this happen?
So it would look something like this
1221
1 = generated land
2 = non generated land that will fill in the two ones
I get this now:
Is there any way to make this flow better?
This seems like just an algorithm issue. Your generation mechanism needs a start point. On the initial call it would be say 0, on subsequent calls it would be the finishing position of the previous "chunk".
If I was doing this, I'd probably make the height of the next point plus of minus say 0-3 from the previous, using some sort of distribution - e.g. 10% of the time it's +/1 3, 25% of the time it is +/- 2, 25% of the time it is 0 and 40% of the time it is +/- 1.
If I understood your problem correctly, here is a solution:
If you generated the delta (difference) between the hills and capped at a fixed value (so changes are never too big), then you can carry over the value of the last hill from the previous section when generating the new one and apply the first randomly genenarted delta (of the new section) to the carried-over hill size.
If you're generating these "hills" sequentially, I would create an accessor method that provides the continuation of said hill with a value to begin the next section. It seems that you are creating a random height for the hill to be constrained by some value already when drawing a hill in a single section. Extend that functionality with this new accessor method.
My take on a possible implementation of this.
public class DrawHillSection {
private int index;
private int x[50];
public void drawHillSection() {
for( int i = 0; i < 50; i++) {
if (i == 0) {
getPreviousHillSectionHeight(index - 1)
}
else {
...
// Your current implementation to create random
// height with some delta-y limit.
...
}
}
}
public void getPreviousHillSectionHeight(int index)
{
return (x[49].height);
}
}

Java boolean if question

I am making a lottery program where I am asking if basically they would like a quick pick ticket. The numbers for their ticket of course would be random since it is a quick pick but the first four numbers range from 0-9 while the fifth number only goes up to 0-4. I am trying to ask them to input a button such as either "1" for no or "2" for yes if they don't want one then it would skip this step. But I am doing the boolean part incorrectly though. Could someone help me out?
Here is an example
System.out.println("Do you want Quick pick, 1 for no or 2 for yes? The first four numbers is from a separate set of 0 to 9 and the fifth number is from a set of 0 to 4.");
QuickPick=keyboard.nextInt();
if((QuickPick==1)){
return false;
}
if((QuickPick==2)){
return true;
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
}
I still haven't gotten around to making the line of code for the final number of 0-4, just the first four numbers, so I haven't forgotten that.
Your code for case 2 immediately does a return true; which ends the method (I assume this is in a method) right then and there. Your other lines don't get execute at all.
Consider using a switch() statement here, it'll make it easier to read:
switch(QuickPick)
{
case 1:
return false;
case 2:
int n = (int)(Math.random()*9+0); // Why is n here? You don't do anything with it?
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
return true;
default:
// Uh oh - someone did something bad maybe just return false?
return false;
}
Also your code for case 2 is definitely wrong, you need to generate a total of five numbers, using bounds 0-9 for the first 4 and 0-4 for the last one. You'll want to use Java's Random to do this (not Math.Random) something like:
Random rand = new Random();
int somethingRandom = rand.nextInt(10);
// Will give you an integer value where 0 < val < 10
// You can call rand.nextInt as many times as you want
To avoid doing your homework for you -- I'll follow the typical CS textbook line and say "Implementation left as an exercise."
The code after return true will not be executed - you need to put that prior to the return statement
Like Marvo said, you dropped a brace in your if.
But you also have faulty logic. I'm not quite sure what the purpose of the method you're in is (that returns a boolean value). But your last few lines will never be reached unless the user types in something like 3 or 42.
Assuming the method is supposed to a) Ask if the user wants a Quick Pick b) Calculate the Quick Pick, if desired c) Return true/false depending on whether the Quick Pick happened or not, you should have:
public boolean doQuickPick()
{
System.out.println("Do you want Quick pick, 1 for no or 2 for yes? The first four numbers is from a separate set of 0 to 9 and the fifth number is from a set of 0 to 4.");
QuickPick=keyboard.nextInt();
if((QuickPick==1)){
return false;
}
if((QuickPick==2)){
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
return true;
}
}
As a separate issue, it'd be much better style to break that into several methods. boolean yesNoPrompt(String message), generateQuickPick(), etc.
Your question is kind of unclear, so I'm afraid I can't be much more help than that. Do post any clarifications / further questions if you have them.
if((QuickPick==2)){
return true;
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
}
In the above copied code from your question, I see that you will be getting compilation errors in your IDE. Your IDE will complain about "Unreachable Code" for the line that is just below the return statement. So, you need to put the return statement at the end of the if block.

different for loops java

I'm having some difficulties with the following problem:
I'm making a little game where you're at a specific spot and each spot has each some possible directions.
The available directions are N(ord),E(ast),S,W . I use the function getPosDirections to get the possible directions of that spot. The function returns the directions into an ArrayList<String> e.g. for spot J3: [E,W]
Now the game goes like this: 2 dice will be rolled so you get a number between 2 and 12, this number represents the number of steps you can make.
What I want is an ArrayList of all the possible routes
clarification of all the possible routes:
When I'm at the current position I check what the possibilities are from there. Let's say that's go East and go West. So we get 2 new positions and from there on we need to check for the next possibilities again for both positions (until we took x directions)
(x equals the number thrown by the dice).
e.g.: I throw 3 and I'm currently at spot J3:
[[E,N,E],[E,N,S],[E,S,E],[E,S,S],[W,N,E],[W,N,S],[W,S,E],[W,S,S]]
How would obtain the last mentioned Array(list)?
First, you might wish to think about your approach some more. In the worst case (a 12 is rolled, and all 4 directions are possible at every location), there will be 4^12 ~= 160 million routes. Is it really necessary to iterate over them all? And is it necessary to fill about 1 GB of memory to store that list?
Next, it is probably a good idea to represent directions in a type-safe manner, for instance using an enum.
That being said, recursion is your friend:
private void iteratePaths(Location currentLoc, List<Direction> currentPath, List<List<Direction>> allPaths, int pathLength) {
if (currentPath.size() >= pathLength) {
allPaths.add(new ArrayList<Direction>(currentPath));
return;
}
for (Direction d : currentLoc.getPosDirections()) {
currentPath.add(d);
Location newLoc = currentLoc.walk(d);
iteratePaths(newLoc, currentPath, allPaths, pathLength);
currentPath.remove(currentPath.size() - 1);
}
}
public void List<List<Direction>> getAllPaths(Location loc, int length) {
List<List<Direction>> allPaths = new ArrayList<List<Direction>>();
List<Direction> currentPath = new ArrayList<Direction>();
iteratePaths(loc, currentPath, allPaths, length);
return allPaths;
}
You can assume that your field of spots is a complete graph. Then you need to implement BFS or DFS with saving pathes.
You can implement all logic in any of these algorithms (like getting a list of possible directions from a certain node).

Categories