The correct Recursive backtracking algorithm? - java

My assignment is to find a way to display all possible ways of giving back change for a predetermined value, the values being scanned in from a txt file. This must be accomplished by Recursive Backtracking otherwise my solution will not be given credit. I will be honest in saying I am completely lost on how to code in the appropriate algorithm. All I know is that the algorithm works something like this:
start with empty sets.
add a dime to one set.
subtract '10' from my amount.
This is a negative number, so I discard that set: it is invalid.
add a nickel to another (empty) set.
subtract '5' from my amount.
This equals 2; so I'll have to keep working on this set.
Now I'm working with sets that already include one nickel.
add a dime to one set.
subtract '10' from my amount.
This is a negative number, so I discard that set: it is invalid.
repeat this with a nickel; I discard this possibility because (2 - 5) is also negative.
repeat this with a penny; this is valid but I still have 1 left.
repeat this whole process again with a starting set of one nickel and one penny,
again discarding a dime and nickel,
and finally adding a penny to reach an amount of 0: this is a valid set.
Now I go back to empty sets and repeat starting with a nickel, then pennies.
The issue is I haven't the slightest clue on how or where to begin, only that that has to be accomplished, or if any other solutions are apparent.
This is my code thus far:
UPDATED
import java.io.*;
import java.util.*;
import java.lang.*;
public class homework5 {
public static int penny = 1;
public static int nickle = 5;
public static int dime = 10;
public static int quarter = 25;
public static int halfDollar = 50;
public static int dollar = 100;
public static int change;
public static void main(String[] args) throws FileNotFoundException {
ArrayList<Integer> coinTypes = new ArrayList<Integer>();
Integer i;
File f = new File (args[0]);
Scanner input = new Scanner(f);
input.nextLine();
while(input.hasNextInt()) {
i = input.nextInt();
coinTypes.add(i);
}
change = coinTypes.get(coinTypes.size()-1);
coinTypes.remove(coinTypes.size()-1);
System.out.println("Found change"); //used for debugging
System.out.println("Change: " + change);
System.out.println(coinTypes);
}
boolean findChange(int change, List<Integer> coinTypes,
List<Integer> answerCoins) {
if(change == 0) {
return true;
}
if(change < 0) {
return false;
} else {
for(Integer coin : coinTypes) {
if(findChange(change - coin, coinTypes, answerCoins)){
answerCoins.add(coin);
return true;
}
}
List<Integer> answer = new ArrayList<Integer>();
boolean canFindChange = findChange(change, coinTypes, answer);
if(canFindChange) {
System.out.println(answer);
} else { System.out.println("No change found");
}
return false;
}
}
Here is the input file that I scan in
java homework5 hwk5sample1.txt
// Coins available in the USA, given in cents. Change for $1.43?
1 5 10 25 50 100
143
OUTPUT
Found change
Change: 143
[1, 5, 10, 25, 50, 100]
So using the numbers in my coinTypes ArrayList, I need a generic code algorithm to show all possible ways of receiving, for example, 143 ($1.43) back in change using the coins in the file with all pennies being the last way to show it.
Please do not think I want you to write me the algorithm, I am simply wanting help writing one otherwise I will learn nothing. Thank you all for any answers or help you can give it means a lot to me! Please let me know if i missed anything or you need more info

The example that you walk through seems to be mostly correct. The only error is this: again discarding a dime and nickel, which should be again discarding a *penny* and nickel (but I think that's just a typo.)
To write a recursive backtracking algorithm, it is useful to think of the recursive call as solving a subproblem of the original problem. In one possible implementation of the solution, the pseudocode looks like this:
/**
* findChange returns true if it is possible to make *change* cents of change
* using the coins in coinTypes. It adds the solution to answerCoins.
* If it's impossible to make this amount of change, then it returns false.
*/
boolean findChange(int change, List<Integer> coinTypes, List<Integer> answerCoins) {
if change is exactly 0: then we're done making change for 0 cents! return true
if change is negative: we cannot make change for negative cents; return false
otherwise, for each coin in coinTypes {
// we solve the subproblem of finding change for (change - coin) cents
// using the recursive call.
if we can findChange(change - coin, coinTypes, answerCoins) {
// then we have a solution to the subproblem of
// making (change - coins) cents of change, so:
- we add coin to answerCoins, the list of coins that we have used
- we return true // because this is a solution for the original problem
}
}
//if we get to the next line, then we can't find change for any of our subproblems
return false
}
We would call this method with:
List<Integer> answer = new ArrayList<Integer>();
boolean canFindChange = findChange(change, coinTypes, answer);
if(canFindChange) {
System.out.println(answer); // your desired output.
}
else {
System.out.println("Can't find change!");
}

Related

How to pull numbers from an array

I currently have java homework that I would appreciate some help with. We are to calculate a team record scenario.
We are given the following numbers:
Team1 Points
{23,45,65,20}
Opponent Points
{20,30,20,18}
I threw these into an array. I also created a public boolean. Basically, you are to pull these points from the array to the boolean? And let the boolean decide which team won? Obviously team1 has won, but we are supposed to let the computer decide, not the human.
Here is my code:
public class TeamScore {
public static boolean Winner(int team1Points, int opponentPoints) {
if (team1Points > opponentPoints) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
// Scanner in = new Scanner(System.in);
int[] team1Points = { 23, 45, 65, 20 };
int[] opponentPoints = { 20, 30, 20, 18 };
int team1 = 1;
int opponent = 1;
for (int i = 0; i < 5; i++) {
if (Winner(team1Points[i], opponentPoints[1])) {
team1 += 1;
} else {
opponent += 1;
}
}
for (int i = 0; i < 5; i++) {
if (team1 > 0 && opponent == 0) {
System.out.println("Team 1 has the perfect record!");
} else {
System.out.println("Win" + Arrays.toString(team1Points));
System.out.println("Loss" + Arrays.toString(opponentPoints));
}
}
}
Could anyone possibly help me? I am currently in programming II, but I did not have the best teacher in programming I. Any help would be appreciated!
EDIT:
I do not think this is a duplicate question because I already can fix it by changing the variable i-->1. My problem is that the computer thinks that team1 has already won regardless of the score.
When I run the code I am getting an java.lang.ArrayIndexOutOfBoundsException error. However when I change team1Points[i] to team1Points[1] then it goes okay and tells me that "Team 1 has the perfect record!". However, if I change some of the array values for team1Points to be less than opponentPoints then it still says "Team 1 has the perfect record!".
Not sure why you have a method Winner (also as Kevin said, it should be winner because of naming conventions) which turns ´(a > b)´ into a large if-statement. Similar stuff appear elsewhere in your code.
Your variables ´team1, opponent = 1´ inexplicably start with the value 1, am I to understand this as a way for your code to imply to a reader that both teams initialize at a win? Using 0 would probably make more sense.
Your game ought to crash from an indexoutofboundsexception at ´team1Points[i]´, as you have arrays of length 4, but your loops runs 5 times (the currently used range is [0-4], inclusive). Changing your loops to i=1 won't help, as the issue is that you eventually encounter team1Points[4] due to the i < 5 statement.
I don't know what game you are modelling or how it works, but the comparison ´Winner(team1Points[i],opponentPoints[1])´ looks like a blatant error to me (you always look at the opponents score for their second round).
Why are you printing your results 5 times? If you want to print the first message only when team1 won all rounds and the point for each round otherwise, you would need to use the loops counter as an index to the arrays in second case. First case should break loop so its not written five times, in addition you don't need to check team1>0 && opponent==0 as it's enough to only check if ´opponent==0´ (speaking of this conditional, it only works if you initialize the variables at 0 as I mentioned before). You could have checked if team1 equals size of the array instead, but imo thats more of a hassle than opponent==0.
Lastly, please fix your indenting. use the preview system so you can make double sure before posting.
Edit: Kevin also brings up a good point that you should be using the length of the array in your loops second statement.

The below code wont execute with some inputs

Sorry for such a basic level question guys. But I'm starter in programming. Not a computers guy. So kindly help me.
In this code when I give input 1000000000, 1000000000, 999999999 the answer should be 4. But my answer is 1. I expect the if statement to execute but it is not executing here.
if you take m*n as a room and "a" as the side as a square tile. Then I want to count MINIMUM no. of tiles required to fill the floor of room. tiles may cover a bit more area but should not leave the room empty. this is my objective. It's working with inputs like 6,6,4 or 15,20,13 etc.
Now its working guys. I had posted the correct code with those minor changes below.
import java.util.Scanner;
public class TheatreSquare {
private static Scanner input;
public static void main(String[] args) {
input = new Scanner(System.in);
float m=input.nextFloat();
float n=input.nextFloat();
float a=input.nextFloat();
long i=(int)(m/a);
long j=(int)(n/a);
if((a*a*i*j)<m*n){
if(a*i<m){
//to check weather it is entering if()
System.out.println("true");
i+=1;
}
if(a*j<n){
System.out.println("false");
//to check weather it is entering if()
j+=1;
}
}
System.out.println((double)(i*j));
}
}
Your floats are overflowing when you multiply them. Defining m, n and a as doubles will solve the issue:
double m = input.nextDouble();
double n = input.nextDouble();
double a = input.nextDouble();
The int conversion loses precision.
Here in this case, a*a*i*j is equal to m*n Hence the if loop will not execute. Also a*i is equal to m and a*j is equal to n.
Hence i isi and j is 1, so i*j is 1.
You need to allow it to go if it is equal too.
Replace
if((a*a*i*j)<m*n){
if(a*i<m){
//to check weather it is entering if()
System.out.println("true");
i+=1;
}
if(a*j<n){
System.out.println("false");
//to check weather it is entering if()
j+=1;
}
}
with
if((a*a*i*j) <= m*n){
System.out.println("Entered if block");
if(a*i <= m){
//to check weather it is entering if()
System.out.println("true");
i+=1;
}
if(a*j <= n ){
System.out.println("false");
//to check weather it is entering if()
j+=1;
}
System.out.println("i is:"+ i +"j is:"+j);
}
thankyou #Mureinik, #Uma Lakshmi Kanth, #Diego Martinoia for helping to solve this. All your answers contributed to solve my question. this is working now. as #Mureinik said my floats are overflowing( though I dont know the meaning). I used Double instead of float and that's it. its working. :-)
import java.util.Scanner;
public class TheatreSquare {
private static Scanner input;
public static void main(String[] args) {
input = new Scanner(System.in);
double m=input.nextDouble();
double n=input.nextDouble();
double a=input.nextDouble();
long i=(long)(m/a);
long j=(long)(n/a);
if((a*a*i*j) <m*n){
if(a*i < m){
//to check weather it is entering if()
i+=1;
}
if(a*j < n ){
//to check weather it is entering if()
j+=1;
}
}
System.out.println((long)(i*j));
}
}
The reason for your behavior is that you are reading numbers as floats. Floats have limited precision, so your m n and a are the same value (at runtime). Reading them as long (and getting rid of all the decimal stuff) should help. But, as mentioned in the comment, we don't know what you wanted to achieve!
--- EDIT DUE TO NEW INFO ---
You have to cover an area of m times n square meters. You have an unit of computation of 1 tile, i.e. a times a square meters (both assumed to be decimal).
Assuming you can cut your tile with good-enough precision, your result will be:
Math.ceiling((m*n) / (a*a));
i.e., either your area is an exact multiple of your tiles (and you can always cut them in rectangles to match the shape of the room), or you'll have some "spare" space to fill in, thus you will need 1 more tile, a part of which you'll use to cover the remaining space, and a part of which you'll throw away.

how to prevent a number from repeating

Ok so i have looked about for an answer. I am using a random generator to generate numbers based on the user input. This will then select a random number from that and assign them a special position in the game. However the problem is i keep getting repeated values which isn't what i want. So could anyone help?
in
(blueprint class)
int getRoll()
{
roll=rand.nextInt(totalNum);
return roll;
}
(main class)
for(numberOfWerewolves=0;numberOfWerewolves!=wolves.werewolfNum;numberOfWerewolves++)
{
playerNumber++;
wolves.getRoll();
System.out.println(wolves.roll);
}
anyone can help me would be great thanks
It sounds like you want several random numbers within the same range, but you don't want any repeats. If so, what you want is called a "shuffle." Fill an array with the numbers from 1 to N (or 0 to N-1, or whatever), shuffle the array, and then start using the numbers from the beginning of the array.
A good description and implementation of shuffling is given here:
https://stackoverflow.com/a/1520212/1441122
Create a list to keep track of previous random numbers, and loop to keep recalculating the random number until it doesn't match any of them in the list:
public static boolean checkIfExists(ArrayList<Double> list, double x) {
for (double d : list) {
if (d == x) {
return false;
}
}
return true;
}
ArrayList<Double> list = new ArrayList<Double>();
int getRoll()
{
while (true) {
roll = rand.nextInt(totalNum);
if (checkIfExists(list, roll)) {
list.add(roll);
return roll;
}
}
return -100; // -100 means it couldn't generate a number
}
You should not keep the while condition to be true; you should modify it so that it only loops for until you're sure that a unique number can't be generated.

Java Palindrome, methods, and abstract classes?

I'm stuck on an assignment, largely due to an extreme lack of examples or even relevant diagrams from my textbook and class material.
The reason I structured the program the way I did is because I'm required to use 4 methods: a main method that executes all the other methods, a retrieve input method, a check method, and a display method. I love to hear about best practices, but I'm forced to code like this.
My main problem is the abstract classes I have. Any variables I write in one method won't be resolvable in another, I don't know how to make the variables global.
secondly, the code does not compile, the example I've found doesn't have a classic main, i don't really know how to make main implement methods, or make the compiler happy with abstraction.
also no clue on how to take my boolean result and use that to display the results in the display method. yes its asinine, I'd rather just do it in the check method.
all i know for sue is that my "logic" so far works. i think. any help to point me in the right direction would be very much appreciated. if thee is a way to do this without abstract classes i'd love to hear it, i think the abstraction is unnecessary.
well here's my monster so far:
import javax.swing.JOptionPane;
interface Palindrome {
void retrieveInput(String[] args);
boolean Check(String s);
void display();
}
abstract class Sub_Palindrome implements Palindrome {
public void retrieveInput(String[] args)
{
String Uinput;
int number1;
int digit1; // first digit
int digit2; // second digit
int digit3;
int digit4; // fourth digit
int digit5; // fifth digit
Uinput = JOptionPane.showInputDialog("Enter A 5 Digit Integer");
try { //Sanitize user input, make sure input entered is a number
number1 = Integer.parseInt(Uinput);
} catch (NumberFormatException String) {
JOptionPane.showMessageDialog(null, "Input invalid, please enter an integer",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
if (number1 < 10000 || number1 > 99999) { //Sanitize user input, make sure the given number is between 10000 and 99999
JOptionPane.showMessageDialog(null,
"The number entered must be between 10000 and 99999",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
}
public boolean Check(String s)
{
digit1 = number / 10000;
digit2 = number / 1000 % 10;
digit3 = number % 1000 / 100 % 10; // is the third digit even necessary?
digit4 = number % 10000 % 1000 % 100 / 10;
digit5 = number % 10000 % 1000 % 100 % 10;
if (digit1 == digit5 && digit2 == digit4)
return true;
else
return false;
}
public void display()
{
//display output text based upon result from IsPalinDrome
//after displaying result, start from the beginning and ask user to input data again
}
}
Move the variables outside methods and put directly in class scope
Writing main method is the first thing you learn in java. Look into your tutorial again
You can use a boolean variable boolean displayCheck = false; and set the same
And one question from my side: If your code doesn't compile what makes you feel that the logic is correct?

Trying to Make an Average Finder, Not Using ReadLine(), using Only Console

New to Java, basically started yesterday.
Okay, so here's the thing.
I'm trying to make an 'averager', if you wanna call it that, that accepts a random amount of numbers. I shouldn't have to define it in the program, it has to be arbitrary. I have to make it work on Console.
But I can't use Console.ReadLine() or Scanner or any of that. I have to input the data through the Console itself. So, when I call it, I'd type into the Console:
java AveragerConsole 1 4 82.4
which calls the program and gives the three arguments: 1, 4 and 82.4
I think that the problem I'm having is, I can't seem to tell it this:
If the next field in the array is empty, calculate the average (check Line 14 in code)
My code's below:
public class AveragerConsole
{
public static void main(String args[])
{
boolean stop = false;
int n = 0;
double x;
double total = 0;
while (stop == false)
{
if (args[n] == "") //Line 14
{
double average = total / (n-1);
System.out.println("Average is equal to: "+average);
stop = true;
}
else
{
x = Double.parseDouble(args[n]);
total = total + x;
n = n + 1;
}
}
}
}
The following error appears:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at AveragerConsole.main(AveragerConsole.java:14)
for(String number : args) {
// do something with one argument, your else branch mostly
}
Also, you don't need n, you already have the number of arguments, it's the args length.
This is the simplest way to do it.
For String value comparisons, you must use the equals() method.
if ("".equals(args[n]))
And next, the max valid index in an array is always array.length - 1. If you try to access the array.length index, it'll give you ArrayIndexOutOfBoundsException.
You've got this probably because your if did not evaluate properly, as you used == for String value comparison.
On a side note, I really doubt if this if condition of yours is ever gonna be evaluated, unless you manually enter a blank string after inputting all the numbers.
Change the condition in your while to this and your program seems to be working all fine for n numbers. (#SilviuBurcea's solution seems to be the best since you don't need to keep track of the n yourself)
while (n < args.length)
You gave 3 inputs and array start couting from 0. The array args as per your input is as follows.
args[0] = 1
args[1] = 4
args[2] = 82.4
and
args[3] = // Index out of bound
Better implementation would be like follows
double sum = 0.0;
// No fault tolerant checking implemented
for(String value: args)
sum += Double.parseDouble(value);
double average = sum/args.length;

Categories