I have a problem with sequentially searching, this is the exercise:
You are testing the physical endurance of a type of brick. The test is made to find the max height the brick can fall without breaking from and N stories building. You have k bricks and two cases:
Case 1. When k = 1 the tries begin from the current floor upwards, sequentially, until the brick breaks.
Case 2. For k > 1 one brick is dropped from floor N/2. If it breaks, case 2 is applied again between floors 1 and N/2 -1. If the brick does not break, case 2 is applied again between floors N/2 + 1 and N.
I have a problem with the CASE 1 cause as I don't know how to approach it:
Initially you call dropBricks(k,1,N); Being k, and N introduced by the User(Keyboard).
public static boolean breakingFloor(int floor){
boolean breaks;
Random r =new Random();
int breakingFloor= r.nextInt(floor)+1;
if(floor>=breakingFloor){
breaks=true;
}else{
breaks=false;
}
return breaks;
}
dropBricks receives k(number of remaining bricks, first (first floor),last (last floor = N)) and the output would be the breakingFloor
public static int dropBricks(int k,int first,int last){
int result=0;
if (k==1){//CASE 1
//I KNOW THIS CODE IS WRONG, IS JUST O NOT LEAVE IT IN EMPTY
do{
dropBricks(k,first,last);
first++;
}while(breakingFloor(first));
System.out.println("Floor brick broke "+floor);
}else{//CASE 2
if(last-first<=1){
if(last==first){
result=first;
System.out.println("Floor brick broke "+result);
}else{
if(breakingFloor(first)){
result=first;
k--;
System.out.println("Floor brick broke "+result);
}else{
result=last;
k--;
System.out.println("Floor brick broke "+result);
}
}
}else{
int mid=((first+last)/2);
if(breakingFloor(mid)){
result=dropBricks(k-1,first,mid);
System.out.println("Floor brick broke "+result);
}else{
result=dropBricks(k,mid,last);
System.out.println("Floor brick broke "+result);
}
}
}
return result;
}
Your issue - or at least one of them - is that every time you go around this loop...
do{
dropBricks(k,first,last);
first++;
} while( breakingFloor(first) );
... you are choosing a new random floor at which it will break (which happens in the breakingFloor method):
Random r =new Random();
int breakingFloor= r.nextInt(floor)+1;
This will definitely give you very inconsistent behaviour. It may actually work some of the time by a fluke.
You want to choose the floor at which it will break at the start and for it to remain constant.
A sensible way to test your application might be to hard-code a breaking floor to start with and then introduce the randomness later.
Your first issue is here:
int breakingFloor= r.nextInt(floor)+1;
That simply doesn't make sense. The floor number on which a brick will break is not random.
In other words: you want to assign a random number once for that brick. And then your algorithm has to find that number! Your code changes that "breaking floor number" while your algorithm tries to find that number. This makes the whole process useless (and of course; "random"; as all kinds of things can happen).
So the first step on your side: step back, and re-think the problem, and what "solving" the problem really asks you to do.
Related
public static int score(int[][] array, int win, int turn) {
int score = 0;
if (GamePrinciples.gameEnd(array, win)) {
if (GamePrinciples.draw(array)) {
score = 0;
} else if (GamePrinciples.winningBoard(array, win)[0] == 1) {
score = 1;
} else {
score = -1;
}
} else {
for (int[][] i : children(array, win, turn)) {
score += score(i, win, GamePrinciples.nextPlayer(turn));
}
}
return score;
}
briefly this program is part of my minimax algorithm. So the problem is that I get a stack over flow. Where am I going wrong?
if an array is in ending mode then if it is a draw it gives a score of zero if player one wins then a score of one and if player two wins it gives a score of two.
if the array is however not in the ending state we get the children of the array (immediate children that is the boards that result from the current board with only one move). The score of the board will be the sum of the score of each of its children. The logic seems okay and the other methods such as children, nextPlayer, winningBoard, draw all work fine with testing. So I am guessing there is problem with this kind of recursive implementation. Can anyone help? Thanks in advance
Your code seems wrong in the loop:
for (int[][] i : children(array, win, turn)) {
I haven’t tested, but you should call the method children() outside the for.
By calling the method within the for clause, you are always returning the initial array instead of iterating through it.
So try putting the children() method return to a variable and iterate through this variable.
Something like:
… c = children(…)
for(int[][] i : c) {
…
I'm trying to solve the sailors, monkey and coconuts problem by using a recursive algorithm. I want my program to state true or false if it is possible to solve the problem with the values given. In short, the problem is there are s sailors that are stranded on an island with a monkey and y coconuts. Throughout the night, one sailor will wake up, take the y coconuts and sort into s even piles, with one coconut left for the monkey. The sailor then buries one of the piles, and puts the other two piles back together. The next sailor wakes up, and does the same (creates s even piles with one left for the monkey, buries one of the piles, and puts back the other piles).
I also know that 2 sailors requires 7 coconuts, 3 sailors require 79 coconuts and 4 sailors require 1021 coconuts.
I'm having difficulty with my base cases. If I have a case where I have 4 sailors and 81 coconuts for example, my program will say it's possible since 4%81=1. However once the second sailor goes to sort the coconuts in this example, there aren't enough to sort.
Any help or suggestions would be greatly appreciated. Thank you so much!
public class test2 {
public static void main(String[] args) {
int sailors=4, sailorsRemaining=sailors, coconuts=81;
testCoconuts(sailors, sailorsRemaining, coconuts);
}//end main method
public static boolean testCoconuts(int sailors, int sailorsRemaining, int coconutsRemaining){
int s = sailors;
int sr = sailorsRemaining;
int cr = coconutsRemaining;
if (cr%s==1 && sr==0) { //if there are enough coconuts to sort, but no sailors
System.out.println("false1");
return false;
}
else if (cr%s==1 && sr!=0) { //if there are enough coconuts and enough sailors to sort
System.out.print("true1");
return true;
}
if (cr%s!=1) { //if there are not enough coconuts to sort
System.out.println("false2");
return false;
}
else return testCoconuts(s, cr - ((cr-1)/s)-1, sr-1); //recursive step
}
}//end class
Your method takes in (sailors, sailors remaining, coconut count) but your return method sends (sailors, coconut count, sailors remaining). You swapped the order. That still didn't fix it though. I rewrote the if statements and now it works, I think. I did it by answering the following:
What criteria must be met if I can stop recursing and return true?
What criteria must be met if I can continue recursing?.
Answer these 2 and it should be a breeze to complete. And debugging was key to solving it for me.
This problem is somewhat related to number theory. For any number of sailors there is an infinite number of solutions. The idea is to find the smallest one (number of coconuts).
The end result is a power series that results in one equation and two unknowns. Fortunately it is easy to solve visually because the two large components are relatively prime to each other. So the answer boils down to the following:
The smallest number of coconuts to satisfy the solution for N sailors is N(N+1) - (N-1).
So for 3 coconuts 34 = 81 - 2 =79
So all that is needed is a single method to calculate that value and return true or false appropriately.
// all the following print true;
System.out.println(check(7,2));
System.out.println(check(79,3));
System.out.println(check(15621,5));
public static boolean check(int coconuts, int sailors) {
return (int)Math.pow(sailors, sailors+1) - (sailors - 1) == coconuts;
}
Note that there is variation of this problem where when the sailors all get together to do the final division, there is no remainder (i.e. the monkey doesn't get one). In this case the solution is NN - (N-1).
The requirements of the program are:
Antonia and David are playing a game.
Each player starts with 100 points.
The game uses standard six-sided dice and is played in rounds. During one round, each player rolls one die. The player with the lower roll loses the number of points shown on the higher die. If both players roll the same number, no points are lost by either player.
Write a program to determine the final scores.
I came up with the following code:
import java.util.*;
public class prob3
{
public static void main(String[]args)
{
Random g=new Random();
int a,b,c;
int rounds;
int antonio=100;
int david=100;
Scanner s=new Scanner(System.in);
System.out.println("Please enter the no. of rounds you want to play(1-15): ");
rounds=s.nextInt();
for(int d=1;d<=rounds;d++)
{
a=g.nextInt(6)+1;
b=g.nextInt(6)+1;
System.out.println("Round "+d+":"+a+" "+b);
if(a<b)
antonio=100-b;
else if(a>b)
david=100-a;
}
System.out.println("Total for Antonio: "+antonio);
System.out.println("Total for David: "+david);
}
}
The program fails to calculate the right sum at the end.
What am I doing wrong?
Any help would be appreciated.
Thanks.
You are doing this.
antonio=100-b;
When you probably want
antonio = antonio - b;
The first code simply subtracts the dice roll from 100 every time, which is pointless. You want to subtract the dice roll from the players totals. Do this for both players.
As stated above the "100 - b" was your main problem. But there is no reason in your problem statement to set a number of rounds.
I whould rather use a loop like this:
while(antonio >= 0 && david >= 0){
//do the same stuff here
}
System.out.println...
Since it looks as some exercise for some java course.. This may sound useless but:
Format always your code.. Spaces, brakets and tabs
Use descriptive variable mames. a b c d are not quite intuitive in a larger program.
Remover unused variables
Y mucha suerte tío!
Ok, so I have a 3 x 3 jig saw puzzle game that I am writing and I am stuck on the solution method.
public Piece[][] solve(int r, int c) {
if (isSolved())
return board;
board[r][c] = null;
for (Piece p : pieces) {
if (tryInsert(p, r, c)) {
pieces.remove(p);
break;
}
}
if (getPieceAt(r, c) != null)
return solve(nextLoc(r, c).x, nextLoc(r, c).y);
else {
pieces.add(getPieceAt(prevLoc(r, c).x, prevLoc(r, c).y));
return solve(prevLoc(r, c).x, prevLoc(r, c).y);
}
}
I know I haven't provided much info on the puzzle, but my algorithm should work regardless of the specifics. I've tested all helper methods, pieces is a List of all the unused Pieces, tryInsert attempts to insert the piece in all possible orientations, and if the piece can be inserted, it will be. Unfortunately, when I test it, I get StackOverflow Error.
Your DFS-style solution algorithm never re-adds Piece objects to the pieces variable. This is not sound, and can easily lead to infinite recursion.
Suppose, for example, that you have a simple 2-piece puzzle, a 2x1 grid, where the only valid arrangement of pieces is [2, 1]. This is what your algorithm does:
1) Put piece 1 in slot 1
2) It fits! Remove this piece, pieces now = {2}. Solve on nextLoc()
3) Now try to fit piece 2 in slot 2... doesn't work
4) Solve on prevLoc()
5) Put piece 2 in slot 1
6) It fits! Remove this piece, pieces is now empty. Solve on nextLoc()
7) No pieces to try, so we fail. Solve on prevLoc()
8) No pieces to try, so we fail. Solve on prevLoc()
9) No pieces to try, so we fail. Solve on prevLoc()
Repeat ad infinitum...
As commenters have mentioned, though, this may only be part of the issue. A lot of critical code is missing from your post, and their may be errors there as well.
I think you need to structure your recursion differently. I'm also not sure adding and removing pieces from different places of the list is safe; much as I'd rather avoid allocation in the recursion it might be safest to create a list copy, or scan the board
so far for instances of the same piece to avoid re-use.
public Piece[][] solve(int r, int c, List<Piece> piecesLeft) {
// Note that this check is equivalent to
// 'have r and c gone past the last square on the board?'
// or 'are there no pieces left?'
if (isSolved())
return board;
// Try each remaining piece in this square
for (Piece p : piecesLeft) {
// in each rotation
for(int orientation = 0; orientation < 4; ++orientation) {
if (tryInsert(p, r, c, orientation)) {
// It fits: recurse to try the next square
// Create the new list of pieces left
List<Piece> piecesLeft2 = new ArrayList<Piece>(piecesLeft);
piecesLeft2.remove(p);
// (can stop here and return success if piecesLeft2 is empty)
// Find the next point
Point next = nextLoc(r, c);
// (could also stop here if this is past end of board)
// Recurse to try next square
Piece[][] solution = solve(next.x, next.y, piecesLeft2);
if (solution != null) {
// This sequence worked - success!
return solution;
}
}
}
}
// no solution with this piece
return null;
}
StackOverflowError with recursive functions means that you're either lacking a valid recursion stop condition or you're trying to solve too big problem and should try an iterated algorithm instead. Puzzle containing 9 pieces isn't too big problem so the first thing must be the case.
The condition for ending recursion is board completion. You're only trying to insert a piece in the for loop, so the problem is probably either that the tryInsert() method doesn't insert the piece or it doesn't get invoked. As you're sure that this method works fine, I'd suggest removing break; from
if (p.equals(prev[r][c]))
{
System.out.println("Hello");
break;
}
because it's the only thing that may prevent the piece from being inserted. I'm still unsure if I understand the prev role though.
I'm writing code to automate simulate the actions of both Theseus and the Minoutaur as shown in this logic game; http://www.logicmazes.com/theseus.html
For each maze I provide it with the positions of the maze, and which positions are available eg from position 0 the next states are 1,2 or stay on 0. I run a QLearning instantiation which calculates the best path for theseus to escape the maze assuming no minotaur. then the minotaur is introduced. Theseus makes his first move towards the exit and is inevitably caught, resulting in reweighting of the best path. using maze 3 in the game as a test, this approach led to theseus moving up and down on the middle line indefinatly as this was the only moves that didnt get it killed.
As per a suggestion recieved here within the last few days i adjusted my code to consider state to be both the position of thesesus and the minotaur at a given time. when theseus would move the state would be added to a list of "visited states".By comparing the state resulting from the suggested move to the list of visited states, I am able to ensure that theseus would not make a move that would result in a previous state.
The problem is i need to be able to revisit in some cases. Eg using maze 3 as example and minotaur moving 2x for every theseus move.
Theseus move 4 -> 5, state added(t5, m1). mino move 1->5. Theseus caught, reset. 4-> 5 is a bad move so theseus moves 4->3, mino catches on his turn. now both(t5, m1) and (t3 m1) are on the visited list
what happens is all possible states from the initial state get added to the dont visit list, meaning that my code loops indefinitly and cannot provide a solution.
public void move()
{
int randomness =10;
State tempState = new State();
boolean rejectMove = true;
int keepCurrent = currentPosition;
int keepMinotaur = minotaurPosition;
previousPosition = currentPosition;
do
{
minotaurPosition = keepMinotaur;
currentPosition = keepCurrent;
rejectMove = false;
if (states.size() > 10)
{
states.clear();
}
if(this.policy(currentPosition) == this.minotaurPosition )
{
randomness = 100;
}
if(Math.random()*100 <= randomness)
{
System.out.println("Random move");
int[] actionsFromState = actions[currentPosition];
int max = actionsFromState.length;
Random r = new Random();
int s = r.nextInt(max);
previousPosition = currentPosition;
currentPosition = actions[currentPosition][s];
}
else
{
previousPosition = currentPosition;
currentPosition = policy(currentPosition);
}
tempState.setAttributes(minotaurPosition, currentPosition);
randomness = 10;
for(int i=0; i<states.size(); i++)
{
if(states.get(i).getMinotaurPosition() == tempState.getMinotaurPosition() && states.get(i).theseusPosition == tempState.getTheseusPosition())
{
rejectMove = true;
changeReward(100);
}
}
}
while(rejectMove == true);
states.add(tempState);
}
above is the move method of theseus; showing it occasionally suggesting a random move
The problem here is a discrepancy between the "never visit a state you've previously been in" approach and your "reinforcement learning" approach. When I recommended the "never visit a state you've previously been in" approach, I was making the assumption that you were using backtracking: once Theseus got caught, you would unwind the stack to the last place where he made an unforced choice, and then try a different option. (That is, I assumed you were using a simple depth-first-search of the state-space.) In that sort of approach, there's never any reason to visit a state you've previously visited.
For your "reinforcement learning" approach, where you're completely resetting the maze every time Theseus gets caught, you'll need to change that. I suppose you can change the "never visit a state you've previously been in" rule to a two-pronged rule:
never visit a state you've been in during this run of the maze. (This is to prevent infinite loops.)
disprefer visiting a state you've been in during a run of the maze where Theseus got caught. (This is the "learning" part: if a choice has previously worked out poorly, it should be made less often.)
For what is worth, the simplest way to solve this problem optimally is to use ALPHA-BETA, which is a search algorithm for deterministic two-player games (like tic-tac-toe, checkers, chess). Here's a summary of how to implement it for your case:
Create a class that represents the current state of the game, which
should include: Thesesus's position, the Minoutaur's position and
whose turn is it. Say you call this class GameState
Create a heuristic function that takes an instance of GameState as paraemter, and returns a double that's calculated as follows:
Let Dt be the Manhattan distance (number of squares) that Theseus is from the exit.
Let Dm be the Manhattan distance (number of squares) that the Minotaur is from Theseus.
Let T be 1 if it's Theseus turn and -1 if it's the Minotaur's.
If Dm is not zero and Dt is not zero, return Dm + (Dt/2) * T
If Dm is zero, return -Infinity * T
If Dt is zero, return Infinity * T
The heuristic function above returns the value that Wikipedia refers to as "the heuristic value of node" for a given GameState (node) in the pseudocode of the algorithm.
You now have all the elements to code it in Java.