I have a programming assignment for an introductory level Java class (the subset sum problem) - for some reason, my recursive method isn't executing properly (it just goes straight to the end of the method and prints out the sorted list). Any help would be appreciated - I'm a newbie and recursive functions are really confusing to me.
package programmingassignment3;
import java.io.*;
import java.util.*;
public class ProgrammingAssignment3 {
static int TARGET = 10;
static ArrayList<Integer> list = new ArrayList<>();
static int SIZE = list.size();
public static void main(String[] args) {
populateSortSet();
sumInt(list);
recursiveSS(list);
}//main
public static void populateSortSet() {
try {
File f = new File("set0.txt");
Scanner input = new Scanner(f);
while (input.hasNext()) {
int ele = input.nextInt();
if (ele < TARGET && !list.contains(ele)) {
list.add(ele);
}//if
}//while
Collections.sort(list);
}//try
catch (IOException e) {
e.printStackTrace();
}//catch
}//populateSet
public static void recursiveSS(ArrayList<Integer> Alist) {
if (Alist.size() == SIZE) {
if (sumInt(Alist) == TARGET) {
System.out.println("The integers that equal " + TARGET + "are: " + Alist);
} //if==TARGET
}//if==SIZE
else {
for (int i = 0; i < SIZE; i++) {
ArrayList<Integer> list1 = new ArrayList<>(Alist);
ArrayList<Integer> list0 = new ArrayList<>(Alist);
list1.add(1);
list0.add(0);
if (sumInt(list0) < TARGET) {
recursiveSS(list0);
}//if
if (sumInt(list1) < TARGET) {
recursiveSS(list1);
}//if
}//for
}//else
System.out.println("echo" + Alist);
}//recursiveSS
public static int sumInt(ArrayList<Integer> Alist) {
int sum = 0;
for (int i = 0; i < SIZE - 1; i++) {
sum += Alist.get(i);
}//for
if (Alist.size() == TARGET) {
sum += Alist.get(Alist.size() - 1);
}//if
return sum;
}//sumInt
}//class
This thing that you do at class level:
static ArrayList<Integer> list = new ArrayList<>();
static int SIZE = list.size();
means that SIZE will be initiated to 0, and stay 0 (even if you add elements to the list.)
This means that the code inside the for-loop will be executed 0 times.
Try something like:
public class ProgrammingAssignment3 {
private static int initialSize;
//...
public static void populateSortSet() {
//populate the list
initialSize = list.size();
}
So you don't set the value of the size variable until the list is actually populated.
That being said, there a quite a few other strange things in your code, so I think you need to specify exactly what you are trying to solve here.
Here's how I'd do it. I hope it clarifies the stopping condition and the recursion. As you can see, static methods are not an issue:
import java.util.ArrayList;
import java.util.List;
/**
* Demo of recursion
* User: mduffy
* Date: 10/3/2014
* Time: 10:56 AM
* #link http://stackoverflow.com/questions/26179574/recursive-method-not-properly-executing?noredirect=1#comment41047653_26179574
*/
public class RecursionDemo {
public static void main(String[] args) {
List<Integer> values = new ArrayList<Integer>();
for (String arg : args) {
values.add(Integer.valueOf(arg));
}
System.out.println(String.format("input values : %s", values));
System.out.println(String.format("iterative sum: %d", getSumUsingIteration(values)));
System.out.println(String.format("recursive sum: %d", getSumUsingRecursion(values)));
}
public static int getSumUsingIteration(List<Integer> values) {
int sum = 0;
if (values != null) {
for (int value : values) {
sum += value;
}
}
return sum;
}
public static int getSumUsingRecursion(List<Integer> values) {
if ((values == null) || (values.size() == 0)) {
return 0;
} else {
if (values.size() == 1) { // This is the stopping condition
return values.get(0);
} else {
return values.get(0) + getSumUsingRecursion(values.subList(1, values.size())); // Here is recursion
}
}
}
}
Here is the case I used to test it:
input values : [1, 2, 3, 4, 5, 6]
iterative sum: 21
recursive sum: 21
Process finished with exit code 0
Thanks everyone. I really appreciate the help. I did figure out the problem and the solution is as follows (closing brace comments removed for the reading pleasure of #duffymo ):
public class ProgrammingAssignment3 {
static int TARGET = 6233;
static ArrayList<Integer> set = new ArrayList<>();
static int SIZE;
static int count = 0;
public static void populateSortSet() {
try {
File f = new File("set3.txt");
Scanner input = new Scanner(f);
while (input.hasNext()) {
int ele = input.nextInt();
if (ele < TARGET && !set.contains(ele)) {
set.add(ele);
}
}
Collections.sort(set);
SIZE = set.size();
System.out.println("The original sorted set: " + set + "\t subset sum = " + TARGET);
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void recursiveSS(ArrayList<Integer> list) {
if (list.size() == SIZE) {
if (sumInt(list) == TARGET) {
System.out.print("The Bit subset is: " + list + "\t");
System.out.println("The subset is: " + getSubset(list));
count++;
}
}
else {
ArrayList<Integer> list1 = new ArrayList<>(list);//instantiate list1
ArrayList<Integer> list0 = new ArrayList<>(list);//instantiate list0
list1.add(1);
list0.add(0);
if (sumInt(list0) <= TARGET) {
recursiveSS(list0);
}
if (sumInt(list1) <= TARGET) {
recursiveSS(list1);
}
}
}
public static int sumInt(ArrayList<Integer> list) {
int sum = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
sum += set.get(i);
}
}
return sum;
}
public static ArrayList<Integer> getSubset(ArrayList<Integer> list) {
ArrayList<Integer> l = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
l.add(set.get(i));
}
}
return l;
}
}
Related
//Whenever I run the code, it keeps giving me the same error. I don't understand why. The union array function's loop also isn't looping completely, likely a problem with the string index out of bound.
//I've tried to change the original function isNumberInArray, but still doesn't work.
package HW;
public class HW_5 {
public static boolean isNumberInArray(int number_check, int array[]) {
for (int value : array) {
value -= 1;
if (number_check == array[value]) {
return true;
}
}
return false;
}
public static int highestlength(int array_1[]) {
int max = array_1[0];
for (int counter = 1; counter < array_1.length; counter++) {
if (array_1[counter] > max) {
max = array_1[counter];
}
}
return max;
}
public static int [] unionArrays(int [] array_1, int [] array_2) {
int array_index_counter = 0;
int highest_1 = highestlength(array_1);
int highest_2 = highestlength(array_2);
int[] union_array = new int[array_1.length + array_2.length];
if (highest_1 > highest_2) {
for (int value_1 : array_1) {
if (isNumberInArray(value_1, array_1) && isNumberInArray(value_1, array_2)) {
union_array[array_index_counter] = value_1;
array_index_counter += 1;
} else {
for (int value_2 : array_2) {
if (isNumberInArray(value_2, array_1) && isNumberInArray(value_2, array_2)) {
union_array[array_index_counter] = value_2;
array_index_counter += 1;
}
}
}
}
}
printArray(union_array);
return union_array;
}
public static void printArray(int array[]) {
for (int value : array) {
System.out.print(value + " ");
}
System.out.println();
}
public static void main(String[] Args) {
int list_1[] = {1, 2, 3};
int list_2[] = {1, 3, 5};
System.out.println(isNumberInArray(0, list_1));
System.out.println(unionArrays(list_1, list_2));
}
}
I expected the output to be 1 2 3 5, but the actual output is 0 0 0 0.
For a start the looping in isNumberInArray is strange, try
public static boolean isNumberInArray(int number_check, int array[]) {
for (int value : array) {
if (number_check == value) {
return true;
}
}
return false;
}
Probably because of this your if statements in unionArrays are always false
I know similar questions have been asked before but I have found the answers confusing. I am trying to make a program that will find every combination of an array-list with no repetitions and only of the maximum size. If the list has 4 items it should print out only the combinations with all 4 items present. This is what I have so far:
public main(){
UI.initialise();
UI.addButton("Test", this::testCreate);
UI.addButton("Quit", UI::quit);
}
public void createCombinations(ArrayList<String> list, String s, int depth) {
if (depth == 0) {
return;
}
depth --;
for (int i = 0; i < list.size(); i++) {
if (this.constrain(s + "_" + list.get(i), list.size())) {
UI.println(s + "_" + list.get(i));
}
createCombinations(list, s + "_" + list.get(i), depth);
}
}
public void testCreate() {
ArrayList<String> n = new ArrayList<String>();
n.add("A"); n.add("B"); n.add("C"); n.add("D");
this.createCombinations(n , "", n.size());
}
public boolean constrain(String s, int size) {
// Constrain to only the maximum length
if ((s.length() != size*2)) {
return false;
}
// Constrain to only combinations without repeats
Scanner scan = new Scanner(s).useDelimiter("_");
ArrayList<String> usedTokens = new ArrayList<String>();
String token;
while (scan.hasNext()) {
token = scan.next();
if (usedTokens.contains(token)) {
return false;
} else {
usedTokens.add(token);
}
}
// If we fully iterate over the loop then there are no repitions
return true;
}
public static void main(String[] args){
main obj = new main();
}
This prints out the following which is correct:
_A_B_C_D
_A_B_D_C
_A_C_B_D
_A_C_D_B
_A_D_B_C
_A_D_C_B
_B_A_C_D
_B_A_D_C
_B_C_A_D
_B_C_D_A
_B_D_A_C
_B_D_C_A
_C_A_B_D
_C_A_D_B
_C_B_A_D
_C_B_D_A
_C_D_A_B
_C_D_B_A
_D_A_B_C
_D_A_C_B
_D_B_A_C
_D_B_C_A
_D_C_A_B
_D_C_B_A
This works for small lists but is very inefficient for larger ones. I am aware that what I have done is completely wrong but I want to learn the correct way. Any help is really appreciated. Thanks in advance.
P.S. This is not homework, just for interest although I am a new CS student (if it wasn't obvious).
Implementing Heap's algorithm in Java:
import java.util.Arrays;
public class Main {
public static void swap(final Object[] array, final int index1, final int index2) {
final Object tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
public static void printPermutations_HeapsAlgorithm(final int n, final Object[] array) {
final int[] c = new int[n];
for (int i = 0; i < c.length; ++i)
c[i] = 0;
System.out.println(Arrays.toString(array)); //Consume first permutation.
int i=0;
while (i < n) {
if (c[i] < i) {
if ((i & 1) == 0)
swap(array, 0, i);
else
swap(array, c[i], i);
System.out.println(Arrays.toString(array)); //Consume permutation.
++c[i];
i=0;
}
else
c[i++] = 0;
}
}
public static void main(final String[] args) {
printPermutations_HeapsAlgorithm(4, new Character[]{'A', 'B', 'C', 'D'});
}
}
Possible duplicate of this.
I have tried to print all the paths which give the given amount. But my code does not work properly. I think I am missing some points to print all possible combinations. For example;
if amount: 7 and startCoin = 25, the program needs to give me:
{5,1,1} and {1,1,1,1,1,1,1}.
Can you help me to fix these problem?
Note: Preferably Java Solutions
class Solution {
static int[] coinSet = {1,5,10,25};
static List<List<Integer>> possibleWays = new ArrayList<>();
static List<Integer> currentWay = new ArrayList<>();
private static int makeChange(int amount, int startCoin){
boolean flag = false;
for(int i =0 ; i < coinSet.length ; i++){
if(coinSet[i] == startCoin) {
flag =true;
}
}
if(!flag){
throw new IllegalArgumentException("startCoin has to be in the specified range");
}
int nextCoin = 0;
switch(startCoin) {
case 25:
nextCoin = 10;
break;
case 10:
nextCoin = 5;
break;
case 5:
nextCoin = 1;
break;
case 1:
possibleWays.add(currentWay);
currentWay = new ArrayList<>();
return 1;
}
int ways = 0;
for(int count = 0; count * startCoin <= amount; count++){
ways += makeChange(amount - (count * startCoin),nextCoin);
}
return ways;
}
public int calculateNumberOfWays(int amount, int startCoin) throws Exception {
if (amount == 0) {
throw new Exception(); }
return makeChange(amount, startCoin);
}
public static void main(String[] args) {
System.out.println(makeChange(5,25));
System.out.println(possibleWays);
}
}
This can be solved using backtracking but that is not very efficient, below is the working java code
/**
* Created by sumit sharma on 3/1/2016.
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
public class Main {
static int[] coinSet = {1,5,10,25};
static List<List<Integer>> possibleWays = new ArrayList<>();
static List<Integer> currentWay = new ArrayList<>();
public static void main(String[] args) {
List<Integer> countOfCoins = new ArrayList<>();
makeChange(7, 0, countOfCoins);
//System.out.print(possibleWays);
}
private static int makeChange(int amount, int startCoinIdx, List<Integer> coinsSoFar) {
if(startCoinIdx == coinSet.length){
if(amount == 0){
possibleWays.add(coinsSoFar);
System.out.println(coinsSoFar);
}
//System.out.println(coinsSoFar);
return 0;
}
for(int count = 0;(count*coinSet[startCoinIdx]) <= amount;count++){
List<Integer> temp = new ArrayList<>();
for(int i = 0;i < coinsSoFar.size();i++) temp.add(coinsSoFar.get(i));
for(int i = 0;i < count;i++) temp.add(coinSet[startCoinIdx]);
makeChange(amount - (count * coinSet[startCoinIdx]),startCoinIdx+1, temp);
temp.clear();
}
return 0;
}
}
Link to solution on Ideone : http://ideone.com/kIckmG
I am learning how to implement basic algorithms in Java, so i am a newbie in this environment. I am trying to implement Merge Sort algorithm using ArrayList where program will read data (Integer in each line) from file and produce sorting result using Merge Sort. However, my code is showing same result as it has not sorted anything out! I would be very glad if someone can identify where did I do my mistake. As i am a beginner, the code is very simple, not optimized and not very fast in performance probably.
Here is my code:
public class MergeSortExp1 {
public static void main(String[] args) {
ArrayList<Integer>number = new ArrayList<Integer>();
Scanner myScanner = null;
try {
myScanner = new Scanner(new File("/Users/Sabbir/Desktop/workload.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while(myScanner.hasNextInt()){
number.add(myScanner.nextInt());
}
System.out.println("Before sorting" +number);
number=mergeSort(number);
System.out.println("Sorted Array =" +number);
}
public static ArrayList<Integer> mergeSort( ArrayList<Integer> Input)
{
if (Input.size() ==1){
return Input;
}
else {
int mid= Input.size()/2;
ArrayList<Integer> left= new ArrayList<Integer>(mid);
ArrayList<Integer> right=new ArrayList<Integer>(Input.size()-mid);
for (int i = 0; i < mid; i++) {
left.add(Input.get(i));
}
for (int i = 0; i < Input.size()-mid; i++) {
right.add(Input.get(i));
}
left=mergeSort(left);
right=mergeSort(right);
merge(left,right,Input);
}
return Input;
}
public static void merge (ArrayList<Integer>left,ArrayList<Integer>right,ArrayList<Integer>Input)
{
int i1=0;// left Index
int i2=0;// right Index
int InputIndex=0;
for (int i = 0; i < Input.size(); i++) {
if (i2>=right.size() || (i1<left.size() && left.get(i)<=right.get(i)))
{
Input.set(InputIndex,left.get(i1));
InputIndex++;
}
else {
Input.set(InputIndex, right.get(i2));
InputIndex++;
}
}
}
}
If your merge method is Ok (I don't test it), you forget to merge left and right to input, edit your code as shown below and re-try:
// This is called recursion. Calling a method again within the
//method until the value of left and right becomes 1.
left=mergeSort(left);
right=mergeSort(right);
merge(left,right,Input);
hope helped you!
One more variant:
private static <T extends Comparable<T>> List<T> mergeSort(List<T> unsortedList) {
if (unsortedList.size() <= 1) {
return unsortedList;
}
List<T> sortedList = new ArrayList<>(unsortedList.size());
List<T> leftList = mergeSort(unsortedList.subList(0, unsortedList.size() / 2));
List<T> rightList = mergeSort(unsortedList.subList(unsortedList.size() / 2, unsortedList.size()));
int leftIdx = 0;
int rightIdx = 0;
int resultIdx = 0;
while (leftIdx < leftList.size() && rightIdx < rightList.size()) {
if (leftList.get(leftIdx).compareTo(rightList.get(rightIdx)) <= 0) {
sortedList.add(resultIdx, leftList.get(leftIdx));
leftIdx++;
} else {
sortedList.add(resultIdx, rightList.get(rightIdx));
rightIdx++;
}
resultIdx++;
}
while (leftIdx < leftList.size()) {
sortedList.add(resultIdx, leftList.get(leftIdx));
leftIdx++;
resultIdx++;
}
while (rightIdx < rightList.size()) {
sortedList.add(resultIdx, rightList.get(rightIdx));
rightIdx++;
resultIdx++;
}
return sortedList;
}
import java.util.ArrayList;
import java.io.*;
import java.util.*;
public class Mergesort1 {
public static void main(String[] args) {
ArrayList<Integer> values = new ArrayList<Integer>();
int zeilen = 0;
try{
FileInputStream in = new FileInputStream(args[0]);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while((line = reader.readLine()) != null){
values.add(Integer.parseInt(line));
zeilen++;
}
try{
FileOutputStream out = new FileOutputStream(args[1]);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
sort(values); //sortien array list
for (int i=0; i<values.size(); i++){
writer.write("" + values.get(i));
writer.newLine();
}
writer.close();
}
catch(Exception e){
System.out.println(e);
}
}
catch(Exception e){
System.out.println(e);
}
}
public static ArrayList<Integer> sort( ArrayList<Integer> values)
{
if (values.size() ==1){
return values;
}
else {
int mid= values.size()/2;
ArrayList<Integer> left= new ArrayList<Integer>(mid);
ArrayList<Integer> right=new ArrayList<Integer>(values.size()-mid);
for (int i = 0; i < mid; i++) {
left.add(values.get(i));
}
for (int i = mid; i < values.size(); i++) {
right.add(values.get(i));
}
left=sort(left);
right=sort(right);
merge(left,right,values);
}
return values;
}
public static void merge (ArrayList<Integer>left,ArrayList<Integer>right,ArrayList<Integer>values)
{
int i1=0;// left Index
int i2=0;// right Index
int InputIndex=0;
for (int i = 0; i < values.size(); i++) {
if(i1==left.size()){
values.set(i, right.get(i2));
i2++;
}
else{
if (i2==right.size()){
values.set(i,left.get(i1));
i1++;
}
else{
if (left.get(i1)<=right.get(i2)) {
values.set(i,left.get(i1));
i1++;
}
else {
if (left.get(i1)>=right.get(i2)) {
values.set(i, right.get(i2));
i2++;
}
}
}
}
}
}
}
I have this class and in the printVotes method I had to do the if statement every time to print each votes. Is there any way to combine both the if statements. Could I print all the names of the candidates and the number of votes they got at the same time?
public class TestCandidate {
public static void main(String[] args)
{
Canidate[] canidate = new Canidate[5];
// create canidate
canidate[0] = new Canidate("John Smith", 5000);
canidate[1] = new Canidate("Mary Miller", 4000);
canidate[2] = new Canidate("Michael Duffy", 6000);
canidate[3] = new Canidate("Tim Robinson", 2500);
canidate[4] = new Canidate("Joe Ashtony", 1800);
printVotes(canidate) ;
}
public static void printVotes(Canidate [] List)
{
double max;
int index;
if (List.length != 0)
{
index = 0;
for (int i = 1; i < List.length; i++)
{
}
System.out.println(List[index]);
}
if (List.length != 0)
{
index = 1;
for (int i = 1; i < List.length; i++)
{
}
System.out.println(List[index]);
return;
}
}
}
If you pass in a List<Candidate> candidates; and assuming that each candidate has a List<Integer> Votes:
List<Integer> votes= new ArrayList<Integer>() ;
for(Candidate c:candidates)
{
votes.add(c.GetVote()) ;
}
for(Integer v:votes)
{
System.out.println(v);
}
You could override the Candidate class's toString() method like so:
public String toString() {
return "Candidate Name: " + this.name + "\nVotes: " + this.votes;
}
Then your printVotes method would look something like this:
public static void printVotes(Candidate[] list) {
for(Candidate c : list) {
System.out.println(c);
}
}
As someone else mentioned, avoid using capital letters in variable names especially in cases where words such as List are used. List is a collection type and can be easily confused.