I have implemented two algorithms in Java and when testing depth first search it seems to be taking an incredible amount of time when there are 12 nodes, when using A* it completes it in seconds, I was just wondering if this is to be expected or am I doing something wrong? Its running the search in the background now as I type this and has been going for a few minutes.
I wouldnt normally mind but ive got to test up to 500 nodes which could take days at this rate, is this something I should expect or am I doing something wrong?
Thanks!
import java.util.*;
#SuppressWarnings({ "rawtypes", "unchecked" })
public class DepthFirstSearch {
Routes distances;
static Routes routes;
int firstNode;
String result = new String();
ArrayList firstRoute, bestRoute;
int nodes = 0;
int routeCost = 0;
int bestCost = Integer.MAX_VALUE;
public DepthFirstSearch(Routes matrix, int firstNode) { //new instance
distances = matrix;
this.firstNode = firstNode;
}
public void run () { //run algorithm
long startTime = System.nanoTime();
firstRoute = new ArrayList();
firstRoute.add(firstNode);
bestRoute = new ArrayList();
nodes++;
long endTime = System.nanoTime();
System.out.println("Depth First Search\n");
search(firstNode, firstRoute);
System.out.println(result);
System.out.println("Visited Nodes: "+nodes);
System.out.println("\nBest solution: "+bestRoute.toString() + "\nCost: "+bestCost);
System.out.println("\nElapsed Time: "+(endTime-startTime)+" ns\n");
}
/**
* #param from node where we start the search.
* #param route followed route for arriving to node "from".
*/
public void search (int from, ArrayList chosenRoute) {
// we've found a new solution
if (chosenRoute.size() == distances.getCitiesCount()) {
chosenRoute.add(firstNode);
nodes++;
// update the route's cost
routeCost += distances.getCost(from, firstNode);
if (routeCost < bestCost) {
bestCost = routeCost;
bestRoute = (ArrayList)chosenRoute.clone();
}
result += chosenRoute.toString() + " - Cost: "+routeCost + "\n";
// update the route's cost (back to the previous value)
routeCost -= distances.getCost(from, firstNode);
}
else {
for (int to=0; to<distances.getCitiesCount(); to++){
if (!chosenRoute.contains(to)) {
ArrayList increasedRoute = (ArrayList)chosenRoute.clone();
increasedRoute.add(to);
nodes++;
// update the route's cost
routeCost += distances.getCost(from, to);
search(to, increasedRoute);
// update the route's cost (back to the previous value)
routeCost -= distances.getCost(from, to);
}
}
}
}
}
you are not updating chosenRoute correctly; you always add "firstNode" with the same value to your arraylist, I think you should add the visited node.
I will try to check that later
Related
My code involves me to calculate the amount of time required for a person in a certain position in a queue to buy burgers with the index of the burgers array showing an integer of the amount of burgers a person ordered. Each time a person at the head buys a burger they are taken to the tail and have one burger removed and 1 time value added. I have to find the amount of time it takes for the person at what position I inputted to find the time to buy all of their burgers.
Here is my code:
import java.util.Queue;
public class A4Q2 {
public int calcTimeReqToBuyBurgers(int[] burgers, int p)
{
Queue<Integer> q = new LinkedList<Integer>();
q.addAll(burgers);
int time = 0;
int i = 0;
numBurg = burgers[p];
while(numBurg > 0) {
int x = q.remove();
x--;
if(x != 0) {
q.add(x);
}
time +=1;
}
return time;
}
public static void main(String[] args) {
A4Q2 ex = new A4Q2();
}
}
I do not know where to go from here or if I am even doing this right. I know my question might look a little messy but I am still new to this website. Can someone help me?
You need not use queue for this, and also in your solution it seems that you are not reducing numBurg(which makes the queue run infinitely) and also you need to keep track of index of numBurg. Then I guess it would work. Below is my solution
int time = 0;
int p_value = burgers[p];
for(int i=0;i<burgers.length;i++){
if(burgers[p] > p_value) time+=p_value;
else time+=burgers[p];
if(i == p) p_value-=1;
}
return time;
Explanation: you need to reduce burgers[p] value from all the elements in array until you reach p but after that you can stop so the prior elements will have only p-1 reduced in them as we can stop after we reach p. and also if someone needs less burgers they will only participate until they reach 0. This would be O(n) with no extra space solution.
public int calcTimeReqToBuyBurgers(int[] burgers, int p)
{
Queue<Integer> q = new LinkedList<Integer>();
for (int burger : burgers){
q.add(burger);}
int time = 0;
int i = 0;
int numBurg = burgers[p];
while(numBurg > 0) {
int curr = q.remove();
if(curr == 1){time ++;}
if(curr > 1){
q.add(curr);
time ++;
}
if(curr == numBurg){
q.add(curr -- );
numBurg --;
time ++;
}
}
return time;
}
public static void main(String[] args) {
A4Q2 ex = new A4Q2 ();
int [] burgers= new int [] {3,2,4,1};
int time=ex.calcTimeReqToBuyBurgers(burgers,1);
System.out.println("time "+time);
}
Problem Description :
The travelling salesman problem (also called the travelling salesperson problem or TSP) asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city and returns to the origin city?"
My solution :
I used The Backtracking Method, and i used that Google Guava library to construct graphs the only problem is i my code don't return the initial city , by example if we have A , B , C , D cities and the shortest trajectory is A ,B , D, C we have to return to the initial city Like A ,B , D, C, A Here is the the code (or you can check the following github link to understand the problem better https://charlesreid1.github.io/solving-the-traveling-salesperson-problem-with-java-and-guava.html :
package com.Faissal;
import com.google.common.graph.ImmutableNetwork;
import com.google.common.graph.MutableNetwork;
import com.google.common.graph.NetworkBuilder;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
class TSP {
// The actual graph of cities
ImmutableNetwork<Node, Edge> graph;
int graphSize;
// Storage variables used when searching for a solution
String[] route; // store the route
double this_distance; // store the total distance
double min_distance; // store the shortest path found so far
/**
* Defaut constructor generates the graph and initializes storage variables
*/
public TSP() {
// Build the graph
this.graph = buildGraph();
this.graphSize = this.graph.nodes().size();
// Initialize route variable, shared across recursive method instances
this.route = new String[this.graphSize];
// Initialize distance variable, shared across recursive method instances
this.this_distance = 0.0;
this.min_distance = -1.0; // negative min means uninitialized
}
/**
* This method actually constructs the graph.
*/
public ImmutableNetwork<Node, Edge> buildGraph() {
// MutableNetwork is an interface requiring a type for nodes and a type for edges
MutableNetwork<Node, Edge> roads = NetworkBuilder.undirected().build();
// Construct Nodes for cities,
// and add them to a map
String[] cities = {"Wuhan", "shanghai", "Beijing", "Tianjin", "dalian"};
Map<String, Node> all_nodes = new TreeMap<String, Node>();
for (int i = 0; i < cities.length; i++) {
// Add nodes to map
Node node = new Node(cities[i]);
all_nodes.put(cities[i], node);
// Add nodes to network
roads.addNode(node);
}
// Construct Edges for roads,
// and add them to a map
String[] distances = {"Wuhan:shanghai:839", "Wuhan:Beijing:1153", "Wuhan:Tianjin:1162", "Wuhan:dalian:1423", "shanghai:Beijing:1214", "shanghai:Tianjin:20", "Beijing:Tianjin:4", "shanghai:dalian:1076", "Tianjin:dalian:802"};
Map<String, Edge> all_edges = new TreeMap<String, Edge>();
for (int j = 0; j < distances.length; j++) {
// Parse out (city1):(city2):(distance)
String[] splitresult = distances[j].split(":");
String left = splitresult[0];
String right = splitresult[1];
String label = left + ":" + right;
int value = Integer.parseInt(splitresult[2]);
// Add edges to map
Edge edge = new Edge(left, right, value);
all_edges.put(label, edge);
// Add edges to network
roads.addEdge(all_nodes.get(edge.left), all_nodes.get(edge.right), edge);
}
// Freeze the network
ImmutableNetwork<Node, Edge> frozen_roads = ImmutableNetwork.copyOf(roads);
return frozen_roads;
}
/**
/** Public solve method will call the recursive backtracking method to search for solutions on the graph */
public void solve() {
/** To solve the traveling salesman problem:
* Set up the graph, choose a starting node, then call the recursive backtracking method and pass it the starting node.
*/
// We need to pass a starting node to recursive backtracking method
Node startNode = null;
// Grab a node, any node...
for( Node n : graph.nodes() ) {
startNode = n;
break;
}
// Visit the first node
startNode.visit();
// Add first node to the route
this.route[0] = startNode.label;
// Pass the number of choices made
int nchoices = 1;
// Recursive backtracking
explore(startNode, nchoices);
}
/** Recursive backtracking method: explore possible solutions starting at this node, having made nchoices */
/**
* Recursive backtracking method: explore possible solutions starting at this node, having made nchoices
* #return
*/
public void explore(Node node, int nchoices) {
/**
* Solution strategy: recursive backtracking.
*/
if (nchoices == graphSize) {
//
// BASE CASE
//
if (this.this_distance < this.min_distance || this.min_distance < 0) {
// if this_distance < min_distance, this is our new minimum distance
// if min_distance < 0, this is our first minimium distance
this.min_distance = this.this_distance;
printSolution();
} else {
printFailure();
}
} else {
//
// RECURSIVE CASE
//
Set<Node> neighbors = graph.adjacentNodes(node);
for (Node neighbor : neighbors) {
if (neighbor.visited == false) {
int distance_btwn = 0;
for (Edge edge : graph.edgesConnecting(node, neighbor)) {
distance_btwn = edge.value;
}
// Make a choice
this.route[nchoices] = neighbor.label;
neighbor.visit();
this.this_distance += distance_btwn;
// Explore the consequences
explore(neighbor, nchoices + 1);
// Unmake the choice
this.route[nchoices] = null;
neighbor.unvisit();
this.this_distance -= distance_btwn;
}
// Move on to the next choice (continue loop)
}
} // End base/recursive case
}
public void printSolution() {
System.out.print("***********\tNEW SOLUTION\t");
System.out.println("Route: " + Arrays.toString(this.route)
+ "\tDistance: " + this.min_distance);
}
/**
* Do nothing with failed path
*/
public void printFailure() {
//
}
}
The Node Class is
```
class Node {
public String label;
public boolean visited; // Helps us to keep track of where we've been on the graph
public Node(String name){
this.label = name;
this.visited = false;
}
public void visit(){
this.visited = true;
}
public void unvisit() {
this.visited = false;
}
}
The Edge Class :
```
class Edge {
public int value;
public String left, right; // For convenience in construction process. Not necessary.
public Edge(String left, String right, int value) {
this.left = left;
this.right = right;
this.value = value;
}
}
The main class
```
public class Main {
public static void main(String[] args) {
TSP t = new TSP();
t.solve();
}
}
I will be very Thankful if someone helped me with this issue
You're almost there, you just have to move back to the origin.
For that you have to have a reference of the origin in TSP.explore. You could store it somewhere in this.startNode or make route an array of Nodes: Node[] route
Then you can check in TSP.explore, if the last node has the origin as its neighbor, add that distance to the total distance and go on like usual.
It basically comes down to this:
// Store Nodes instead of Strings. Edit this everywhere you use it.
Node[] route;
// ...
if (nchoices == graphSize) {
//
// BASE CASE: VISITED EACH NODE
//
Set<Node> neighbors = graph.adjacentNodes(node);
// It's only a solution, if there is a edge to the first node.
if(neighbors.contains(this.route[0])) {
// Same computation as in the else-block.
int distance_btwn = this.getDistanceBetween(node, neighbor);
// Add the distance to the start node.
int total_distance = this.this_distance + distance_btwn;
if (total_distance < this.min_distance || this.min_distance < 0) {
// if this_distance < min_distance, this is our new minimum distance
// if min_distance < 0, this is our first minimium distance
this.min_distance = total_distance;
// You have to tell printSolution to about total_distance somehow.
printSolution(total_distance);
return;
}
}
printFailure();
}
Recently I've been brushing up on my machine learning, and as such decided to implement a basic neural network in Java using the back propagation algorithm. I've gone over the maths and checked against various other tutorials, but am still having problems. Apologies for the size of this post.
I'll first let you know the problems I have been testing on, before going into more detail about the algorithm.
Test problem 1:
A single output neuron with linear activation, learning regression of the function x/2 + 2. This works pretty well, but doesn't really use back propagation yet.
Algorithm works, and converges to near zero error (no pic, since I can't post more than 2 links).
Test problem 2:
My next test was to learn the XOR problem. For this, I tried a simple network with 2 input nodes, 2 hidden nodes and 2 output nodes (input nodes only provide the input and are not trained).
Algorithm always gets stuck on an average of 0.5 error
It doesn't matter how many epochs I run the algorithm for, all errors seem to converge to this point, and the network performs poorly.
Implementation
To implement the algorithm, I represent nodes as objects, and also have objects to represent activation functions.
public class LogisticActivationFunction implements ActivationFunction {
#Override
public double apply(double in) {
return 1.0 / (1.0 + Math.exp(-in));
}
#Override
public double applyDerivative(double in) {
double sig = apply(in);
return sig * (1.0 - sig);
}
}
First, the feed forward process is run like so:
public List<Double> evaluate(List<Double> inputs, boolean training) {
// Set the weights in the first layer.
setInputWeights(inputs);
// Iterate through non-input layers one by one and evaluate.
NodeLayer previousLayer = layers.get(0);
for (int layerIndex = 1; layerIndex < layers.size(); layerIndex++) {
NodeLayer layer = layers.get(layerIndex);
for (int nodeIndex = 0; nodeIndex < layer.size(); nodeIndex++) {
Node node = layer.get(nodeIndex);
evaluateNode(node, previousLayer, training);
}
previousLayer = layer;
}
return getOutputWeights();
}
private void evaluateNode(Node node, NodeLayer previousLayer, boolean training) {
double sum = node.getBias();
// Create sum from all connected nodes.
for (int link : node.links()) {
if (training) {
previousLayer.get(link).registerDownstreamNode(node.getId());
}
sum += node.getUpstreamLinkStrength(link) * previousLayer.get(link).getOutput();
}
// apply the activation function.
double activation = node.getActivation().apply(sum);
node.setHiddenNode(sum, activation);
}
Next, error values are propagated backwards across the network:
protected void backPropogate(List<Double> correct) {
//float error = norm(correct, getOutputWeights());
// Final layer error.
NodeLayer outputLayer = getOutputLayer();
List<Double> output = getOutputWeights();
for (int i = 0; i < outputLayer.size(); i++) {
// Calculate error on the ith output.
double error = correct.get(i) - output.get(i);
System.out.println("error " + i + " = " + error + " = " + correct.get(i) + " - " + output.get(i));
// Set the delta to the error in dimension i multiplied by the activation derivative of the input.
Node node = outputLayer.get(i);
node.setDelta(error * node.getActivation().applyDerivative(node.getInput()));
}
NodeLayer layer = outputLayer.getUpstream(this);
while (layer != getInputLayer()) {
for (Node node : layer) {
double sum = 0;
for (Node downstream : node.downstreamNodes(this, layer)) {
sum += downstream.getDelta() * downstream.getUpstreamLinkStrength(node.getId());
}
node.setDelta(sum * node.getActivation().applyDerivative(node.getInput()));
}
layer = layer.getUpstream(this);
}
}
Finally, weights are updated using gradient descent. Note, I'm using the negative error, so this works by adding the delta * learning rate * output.
private void updateParameters(double learningRate) {
for (NodeLayer layer : this) {
if (layer == getInputLayer()) {
continue;
}
for (Node node : layer) {
double oldBias = node.getBias();
node.offsetBias(node.getDelta() * learningRate);
for (Node upstream : node.upstreamNodes(this, layer)) {
double oldW = node.getUpstreamLinkStrength(upstream);
node.offsetWeight(upstream.getId(), learningRate * node.getDelta() * upstream.getOutput());
}
}
}
}
To tie these all together, I use the train method:
public void trainExample(List<Double> inputs, List<Double> correct, double learningRate) {
System.out.println("training example... " + Data.toString(inputs) + " -> " + Data.toString(correct));
evaluate(inputs, true);
backPropogate(correct);
updateParameters(learningRate);
}
And to do this for a training set I use the following logic:
public List<Double> train(NodeNetwork network, List<List<Double>> trainingInput, List<List<Double>> trainingLabels, double learningRate, int epochs, boolean verbose) {
List<Double> errorLog = new ArrayList<>();
for (int i = 0; i < epochs; i++) {
for (int j = 0; j < trainingInput.size(); j++) {
int example = random.nextInt(trainingInput.size());
network.trainExample(trainingInput.get(example), trainingLabels.get(example), learningRate);
}
if (verbose) {
double error = network.checkErrorSet(trainingInput, trainingLabels);
errorLog.add(error);
System.out.println(i + " " + error);
}
}
return errorLog;
}
Does anyone have any ideas on how I might go about getting this to work? I've spent the last day doing various checks, and seem to be getting no closer to an answer.
Code is viewable on my github (sami016) which I cannot link due to URL restrictions.
I'd really appreciate if anyone could point me in the right direction. Thanks for your help!
So I have a program written so far that reads in a csv file of cities and distances in the following format:
Alaska Mileage Chart,Anchorage,Anderson,Cantwell,
Anchorage,0,284,210,
Anderson,284,0,74,
Cantwell,210,74,0,
So the algorithm works and outputs the cities in the order they should be visited following the shortest path using the nearest neighbor algorithm always starting with Anchorage as the city of origin or starting city.
Using this data, the example output for the algorithm is: 1,3,2. I have ran this with a 27 element chart and had good results as well. I am using this small one for writing and debugging purposes.
Ideally the output I am looking for is the Name of the City and a cumulative milage.
Right now I am having working on trying to get the cities into an array that I can print out. Help with both parts would be appreciated or help keeping in mind that is the end goal is appreciated as well.
My thought was that ultimately I may want to create an array of {string, int}
so my output would look something like this..
Anchorage 0
Cantwell 210
Anderson 284
I am able to set the first element of the array to 1, but can not get the 2nd and 3rd element of the new output array to correct
This is the code I am having a problem with:
public class TSPNearestNeighbor {
private int numberOfNodes;
private Stack<Integer> stack;
public TSPNearestNeighbor()
{
stack = new Stack<>();
}
public void tsp(int adjacencyMatrix[][])
{
numberOfNodes = adjacencyMatrix[1].length;
// System.out.print(numberOfNodes);
// System.out.print(Arrays.deepToString(adjacencyMatrix));
int[] visited = new int[numberOfNodes];
// System.out.print(Arrays.toString(visited));
visited[1] = 1;
// System.out.print(Arrays.toString(visited));
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\n");
//System.arraycopy(arr_cities, 0, arr_final, 0, 1); // Copies Anchorage to Pos 1 always
//System.out.print(Arrays.deepToString(arr_final)+ "\n");
while (!stack.isEmpty())
{
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes-1)
{
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0)
{
if (min > adjacencyMatrix[element][i])
{
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag)
{
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\n");
minFlag = false;
continue;
}
stack.pop();
}
}
Given the existing structure you are using, you can output the cities in the path using:
public void printCities(Stack<Integer> path, int[][] distances, List<String> names) {
int cumulativeDistance = 0;
int previous = -1;
for (int city: path) {
if (previous != -1)
cumulativeDistance += distances[previous][city];
System.out.println(names.get(city) + " " + cumulativeDistance);
previous = city;
}
}
I'd like to answer your question slightly indirectly. You are making life hard for yourself by using arrays of objects. They make the code difficult to read and are hard to access. Things would become easier if you create a City class with appropriate methods to help you with the output.
For example:
class City {
private final String name;
private final Map<City,Integer> connections = new HashMap<>();
public static addConnection(City from, City to, int distance) {
from.connections.put(to, distance);
to.connections.put(from, distance);
}
public int getDistanceTo(City other) {
if (connections.containsKey(other))
return connections.get(other);
else
throw new IllegalArgumentException("Non connection error");
}
}
I've left out constructor, getters, setters for clarity.
Now outputting your path becomes quite a bit simpler:
public void outputPath(List<City> cities) {
int cumulativeDistance = 0;
City previous = null;
for (City current: cities) {
if (previous != null)
cumulativeDistance += previous.getDistanceTo(current);
System.out.println(current.getName + " " + cumulativeDistance);
previous = current;
}
}
I have an algorithm that recursively makes change in the following manner:
public static int makeChange(int amount, int currentCoin) {
//if amount = zero, we are at the bottom of a successful recursion
if (amount == 0){
//return 1 to add this successful solution
return 1;
//check to see if we went too far
}else if(amount < 0){
//don't count this try if we went too far
return 0;
//if we have exhausted our list of coin values
}else if(currentCoin < 0){
return 0;
}else{
int firstWay = makeChange(amount, currentCoin-1);
int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);
return firstWay + secondWay;
}
}
However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?
CB
Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments
public static int makeChange(int amount, int currentCoin, List<Integer>results) {
// ....
if (valid_result) {
results.add(result);
makeChange(...);
}
// ....
}
And call the function like this
List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"
I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.
public class MakeChange {
private static int[] availableCoins = {
1, 2, 5, 10, 20, 25, 50, 100 };
public static void main(String[] args) {
Collection<CombinationResult> results = makeChange(5, 7);
for (CombinationResult r : results) {
System.out.println(
"firstWay=" + r.getFirstWay() + " : secondWay="
+ r.getSecondWay() + " --- Sum=" + r.getSum());
}
}
public static class CombinationResult {
int firstWay;
int secondWay;
CombinationResult(int firstWay, int secondWay) {
this.firstWay = firstWay;
this.secondWay = secondWay;
}
public int getFirstWay() {
return this.firstWay;
}
public int getSecondWay() {
return this.secondWay;
}
public int getSum() {
return this.firstWay + this.secondWay;
}
public boolean equals(Object o) {
boolean flag = false;
if (o instanceof CombinationResult) {
CombinationResult r = (CombinationResult) o;
flag = this.firstWay == r.firstWay
&& this.secondWay == r.secondWay;
}
return flag;
}
public int hashCode() {
return this.firstWay + this.secondWay;
}
}
public static Collection<CombinationResult> makeChange(
int amount, int currentCoin) {
Collection<CombinationResult> results =
new ArrayList<CombinationResult>();
makeChange(amount, currentCoin, results);
return results;
}
public static int makeChange(int amount, int currentCoin,
Collection<CombinationResult> results) {
// if amount = zero, we are at the bottom of a successful recursion
if (amount == 0) {
// return 1 to add this successful solution
return 1;
// check to see if we went too far
} else if (amount < 0) {
// don't count this try if we went too far
return 0;
// if we have exhausted our list of coin values
} else if (currentCoin < 0) {
return 0;
} else {
int firstWay = makeChange(
amount, currentCoin - 1, results);
int secondWay = makeChange(
amount - availableCoins[currentCoin],
currentCoin, results);
CombinationResult resultEntry = new CombinationResult(
firstWay, secondWay);
results.add(resultEntry);
return firstWay + secondWay;
}
}
}
I used the following:
/**
* This is a recursive method that calculates and displays the combinations of the coins included in
* coinAmounts that sum to amountToBeChanged.
*
* #param coinsUsed is a list of each coin used so far in the total. If this branch is successful, we will add another coin on it.
* #param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
* #param amountSoFar is used in the recursion to indicate what sum we are currently at.
* #param amountToChange is the original amount that we are making change for.
* #return the number of successful attempts that this branch has calculated.
*/private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
{
//if last added coin took us to the correct sum, we have a winner!
if (amountSoFar == amountToChange)
{
//output
System.out.print("Change for "+amountToChange+" = ");
//run through the list of coins that we have and display each.
for(Integer count: coinsUsed){
System.out.print(count + " ");
}
System.out.println();
//pass this back to be tallied
return 1;
}
/*
* Check to see if we overshot the amountToBeChanged
*/
if (amountSoFar > amountToChange)
{
//this branch was unsuccessful
return 0;
}
//this holds the sum of the branches that we send below it
int successes=0;
// Pass through each coin to be used
for (Integer coin:coinAmounts)
{
//we only want to work on currentCoin and the coins after it
if (coin >= currentCoin)
{
//copy the list so we can branch from it
List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);
//add on one of our current coins
copyOfCoinsUsed.add(coin);
//branch and then collect successful attempts
successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
}
}
//pass back the current
return successes;
}