I am new to recursion and backtracking. How the code after the recursive call is being executed?
class Solution {
// str : Stores input string
// n : Length of str.
// curr : Stores current permutation
// index : Index in current permutation, curr
static void permuteRec(String str, int n,
int index, String curr)
{
// base case
if (index == n) {
return;
}
System.out.println(curr);
for (int i = index + 1; i < n; i++) {
curr += str.charAt(i);
permuteRec(str, n, i, curr);
// backtracking
curr = curr.substring(0, curr.length() - 1);
}
return;
}
// Generates power set in lexicographic
// order.
static void powerSet(String str)
{
char[] arr = str.toCharArray();
Arrays.sort(arr);
permuteRec(new String(arr), str.length(), -1, "");
}
// Driver code
public static void main(String[] args)
{
String str = "abc";
powerSet(str);
}
}
I cannot understand how the backtracking is going on inside the for loop?
The output is:
a ab b c ca cab cb
I have to create a vowel counter and sorter, where someone can input a word or phrase and the program picks out, counts, and sorts the vowels. I have the code to where it counts and sorts the variables and shows their counts to the user, but it doesn't say which vowel has which count and I have exhausted all of my resources. I am very new to coding and know very little, so if there's anything anyone can do to help, I would appreciate it endlessly.
int[] vowelcounter = {a, e, i, o, u}; //This is the count of the vowels after reading the input.
boolean hasswapped = true;
while(hasswapped)
{
hasswapped = false;
for(int j = 0; j<vowelcounter.length; j++)
{
for(int k = j+1; k<vowelcounter.length; k++)
{
if(vowelcounter[j] > vowelcounter[k])
{
int temp = vowelcounter[j];
vowelcounter[j] = vowelcounter[j+1];
vowelcounter[j+1] = temp;
hasswapped = true;
}
}
}
}
for(int j=0; j<vowelcounter.length; j++)
{
System.out.println(vowelcounter[j]);
}
Instead of int value to represent a counter, a class may be introduced to store and print both the vowel character and its count:
class VowelCount {
private final char vowel;
private int count = 0;
public VowelCount(char v) {
this.vowel = v;
}
public void add() { this.count++; }
public int getCount() { return this.count; }
public char getVowel() { return this.vowel; }
#Override
public String toString() { return "Vowel '" + vowel + "' count = " + count;}
}
Then instead of int[] count an array of VowelCount is created and sorted:
VowelCount[] vowelcounter = {
new VowelCount('a'), new VowelCount('e'), new VowelCount('i'),
new VowelCount('o'), new VowelCount('u')
};
Sorting may be implemented using standard method Arrays::sort with a custom comparator instead of home-made bubble sorting
Arrays.sort(vowelcounter, Comparator.comparingInt(VowelCount::getCount));
Then printing of the stats is as follows (using for-each loop along with the overriden toString):
for (VowelCount v: vowelcounter) {
System.out.println(v); // print sorted by count
}
More advanced ways of calculating the frequencies is to use a map of vowels to their frequencies and sort the map by counter value.
You can use something that is called HashMap
HashMap<String, Integer> vowelCounts = new HashMap<>();
To add data to it just do:
vowelCounts.put("a", 1); // The vowel "a" is once in the sentence
vowelCounts.put("e", 2); // The vowel "e" is 2 times in the sentence
To print to the console:
for(String vowel : vowelCounts.keySet() ) {
System.out.println(vowel + ": " + vowelCounts.get(vowel));
}
For more info: click me!
Have a char[] vowels = { 'a', 'e', 'i', 'o', 'u' }. Every time you swap the counters, make an identical swap in the vowels array.
int temp = vowelcounter[j];
vowelcounter[j] = vowelcounter[j+1];
vowelcounter[j+1] = temp;
char temp2 = vowel[j];
vowel[j] = vowel[j+1];
vowel[j+1] = temp2;
hasswapped = true;
At the end, print out vowel[j] next to vowelcounter[j];
So I have run into a problem where I have an ArrayList where the List is comprised of one letter strings. In this case (A,B,C,D,F,J,N) where the size of the list is 7.
Now I am trying to write code making all combinations of lettering that can be made where the order does not matter i.e. (I know it will be involving "n choose k") up to 5 letters long.
So for 7 choose 1 will be A,B,C,D,F,J,N
... 7 choose 2 ... etc.
... 7 choose 3 ... etc.
... etc.
I am then looking to store these string combinations into another list/hashmap (haven't decided on yet).
But my main focus is on the code that would generate such strings. If anyone can help that would be greatly appreciated. I also want to make it modular just in case i want to eventually form other combinations of 6,7 length. (Which is why I am not just doing it with 5 loops and incrementing for different indices).
What I have so far...
public class ReadFile {
public static void main(String[] args) throws IOException {
String file_name = "C:/Users/Shane/Documents/College/Classes/PurchaseTable.txt";
extract(file_name, 50);
}
private String path;
public ReadFile(String file_path) {
path= file_path;
}
public String[] OpenFile() throws IOException {
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines();
String[] textData = new String[numberOfLines];
int i;
for(i=0; i < numberOfLines; i++) {
textData[i] = textReader.readLine();
}
textReader.close();
return textData;
}
int readLines() throws IOException {
FileReader file_to_read = new FileReader(path);
BufferedReader bf = new BufferedReader(file_to_read);
String aLine;
int numberOfLines = 0;
while(( aLine = bf.readLine()) != null) {
numberOfLines++;
}
bf.close();
return numberOfLines;
}
public static void extract(String filename, int threshold) {
String file_name = filename;
ArrayList<String> temp = new ArrayList<String>();
ArrayList<String> products = new ArrayList<String>();
HashMap<Integer, String> productsPerDate = new HashMap<Integer, String>();
//HashMap<Integer, String> allCombinations = new HashMap<Integer, String>();
try {
ReadFile file = new ReadFile(file_name);
String[] aryLines = file.OpenFile();
int i;
for (i=1; i < aryLines.length; i++) { //excludes header section of any table as shown in assignment
temp.add(aryLines[i]);
}
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
System.out.println(temp);
System.out.println(temp.get(0));
System.out.println(temp.size());
int i; int j; int l;
for (i=0; i<temp.size(); i++) {
String str = temp.get(i);
StringBuilder sb = new StringBuilder(str);
int k =0;
for (j=0; j<=sb.length(); j++) {
if(sb.charAt(j) == '\"' && k==0) {
sb.delete(0, j+1);
k++;
}
if(sb.charAt(j) == '\"' && k!=0) {
sb.delete(j, sb.length());
String line = null;
System.out.println(sb);
for( l=0; l<sb.length(); l++) {
String string = Character.toString(sb.charAt(l));
if(string.equals(",")) {
}
else if (l ==0) {
products.add(string);
line = string;
}
else {
products.add(string);
line = line + string;
}
}
productsPerDate.put(i, line);
//System.out.println(products);
break;
}
}
}
System.out.println(products);
System.out.println(productsPerDate.entrySet()); //Hashmap set to string of 1 letter characters for products per date
Set<String> removeDup = new HashSet<>();
removeDup.addAll(products);
products.clear();
products.addAll(removeDup);
System.out.println(products);
int maxLength = productsPerDate.get(0).length();
for(int m = 0; m < productsPerDate.size(); m++) { //determine max length of string in hashmap
if(maxLength < productsPerDate.get(m).length()) {
maxLength = productsPerDate.get(m).length();
}
}
This probably isn't the most efficient way to do this but please bear with me and help in any way you can.
The output is shown below of what has been created in the above code:
1,"A,B,C,N",1/3/2013
4
A,B,C,N
B,C,D,A,F
A,C,V,N,J
A,C,J,D
[A, B, C, N, B, C, D, A, F, A, C, V, N, J, A, C, J, D]
[0=ABCN, 1=BCDAF, 2=ACVNJ, 3=ACJD]
[A, B, C, D, F, V, J, N]
So essentially I am trying to write the code to make all the possible combinations of length 5 string using the letter strings contained in the array list shown in last output.
Here is a little method that returns a list of all letter combinations of length k (order doesn't matter), given an input String of length n:
public static ArrayList<String> combinations(String nChars, int k) {
int n = nChars.length();
ArrayList<String> combos = new ArrayList<String>();
if (k == 0) {
combos.add("");
return combos;
}
if (n < k || n == 0)
return combos;
String last = nChars.substring(n-1);
combos.addAll(combinations(nChars.substring(0, n-1), k));
for (String subCombo : combinations(nChars.substring(0, n-1), k-1))
combos.add(subCombo + last);
return combos;
}
public static void main(String[] args) {
String nChars = "ABCDE";
System.out.println(combinations(nChars, 2));
}
output: [AB, AC, BC, AD, BD, CD, AE, BE, CE, DE]
I used Strings as input and output, since they are immutable and more well-behaved with regard to slicing than Lists. But if your List contains only 1-letter Strings, it should be easy to convert.
I don't know if this recursive implementation is performant, but it reflects nicely the mathematical property of the Pascal triangle: (n choose k) = (n-1 choose k-1) + (n-1 choose k)
Brute force, without recursion, with generics, not optimized, didactic.
If you want arrangements rather than combinaisons, just comment one line.
// COMBINAISONS
/**
* Return combinaisons of input
* #param _input
* #param _n how many to pick
* #return
*/
public static <T> Vector<Vector<T>> combinaisons (Vector<T> _input, int _n)
{
Vector<Vector<T>> output=new Vector<Vector<T>> ();
int size=_input.size();
// Current result
Object current[]=new Object[_n];
Arrays.fill(current,"");
// which element we take at each box (between 0 and size-1)
int current_indices[]=new int[_n];
Arrays.fill(current_indices,-1);
// inputs used
boolean used[]=new boolean [size];
Arrays.fill(used, false);
// Which box are we processing
int current_box=0;
// Next value for next position
int next_pos_value=0;
// ALGORITHM
while (true)
{
// Finished ?
if (current_box<0)
break;
// Last element ?
if (current_box>=_n)
{
// => save group
output.add(new Vector<T>((List<T>) Arrays.asList(current)));
current_box--;
continue;
}
// filling Current box > 0 && < _n
// next value available
int last_value=current_indices[current_box];
int next_value=-1;
// Where do we begin
int begin_test=0;
if (last_value>=0)
begin_test=last_value+1;
// bigger
// comment this for arrangement rather than combinaisons
if (begin_test<next_pos_value) begin_test=next_pos_value;
for (int test_value=begin_test; test_value < size; test_value++)
if (!used[test_value])
{
next_value=test_value;
break;
}
// VALUE AVAILABLE
if (next_value!=-1)
// valid value ?
{
// release
if (last_value!=-1)
used[last_value]=false;
used[next_value]=true;
current_indices[current_box]=next_value;
current[current_box]=_input.get(next_value);
// next position
current_box++;
// like arrangements, but next value always more
next_pos_value=next_value+1;
continue;
}
else
// invalid value (too big) ?
{
// release
if (last_value!=-1)
used[last_value]=false;
current_indices[current_box]=-1;
// back position
current_box--;
// like arrangements, but reset this
next_pos_value=-1;
continue;
}
}
return output;
}
// public static Vector<Vector<T>> combinaisons (Vector<T> _input)
The code works fine for words having length=6. But when i enter a word of 7 letters it throws this stack overflow error.Is there a way to resolve this?In this code the generator function swaps the "i'th" element of the word with the last element.example->car. In the first pass it will generate 'rac' and in the second 'cra'.Now these 2 new words are passed as parameters to the 'check' function. It is to be noted that when the 'generator' function is called for the first time, the input word is added to the arraylist. Thereafter,the words are added to the arraylist if and only if that word is not present in it i.e. the generator function is called only when a new word is generated. So now, wen 'rac' is generated and passed into 'check',it returns false.This means that the word is not present and generator function is called. Now 'rac' generates 'car' and 'rca'
But 'car' is already present. So it will not be passed as parameter to the 'generator' function.The presence of a word in the arraylist acts as the terminating condition.
import java.util.*;
import java.io.*;
class progx
{
static ArrayList<String> word = new ArrayList<String>();
public static void main(String[] args) throws IOException
{
progx ob = new progx();
ob.input();
}
void input() throws IOException // this function takes the input
{ // from user and calls "generator" function
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter word");
String s = in.readLine();
progx obj = new progx();
obj.generator(s); // call 'generator' function
}
void generator(String s) throws IOException
{
progx ob = new progx();
String output = "";
boolean c = false;
word.add(s); // adds the word to arraylist
int i, j, l = s.length(), l2 = l - 1;
char temp;
char[] b = new char[l];
for (i = 0; i < l; i++)
{
b[i] = s.charAt(i); // initializing each element in array
} // with the ith character of the input string
i = 0; // re-initializing 'i' for the while loop
while (i < l)
{
temp = b[i]; // swapping ith character with last element
b[i] = b[l2];
b[l2] = temp;
output = (ob.convertArray(b));// storing the new word in 'output'
c = ob.check(output);// checking whether the elemnt is present in
// arraylist
if (c == false)// if the word is not present, then call the 'generator'
// function
{
System.out.println(output);
ob.generator(output);
}
for (j = 0; j < l; j++) // re-initialising the array as the swapping
{
b[j] = s.charAt(j);
} // might change the position characters
i++; // of the original input String "s"
}
}
String convertArray(char[] s) // array converter- converts array to string
{
String n = "";
for (int i = 0; i < s.length; i++)
{
n = n + s[i];
}
return n;
}
boolean check(String output) // function that checks presence
{ // of the generated word in the array
boolean present = word.contains(output);
return present;
}
}
The way you are currently generating the anagrams is giving you the Stack Overflow error because your methods are nesting far too deep. In Java, you have a stack representing all your method calls and such. It has a limited amount of memory, and when you hit that cap it overflows.
Because your method calls are nested so deeply, (They are nested by like n! where n is the number of letters in the word) you're calling the methods over and over again, but because of the nesting, they can't be removed from the stack. Thus, you eventually hit a point where you run out of memory.
I would rethink the algorithm you are using to generate these anagrams (unless you're ok with it hitting a cap on some machines, mine broke at a length of 8).
import java.util.*;
public class rec
{
char a[] = {
'a',
'b',
'c',
'd'
};
char temp = ' ';
void Anagram(int i)
{
if (i < a.length)
{
temp = a[0];
a[0] = a[i];
a[i] = temp;
Anagram1(0);
Anagram(i + 1);
} else
return;
}
void Anagram1(int r)
{
if (r < a.length - 1)
{
Anagram2(1);
Anagram1(r + 1);
} else
return;
}
void Anagram2(int j)
{
if (j < a.length - 1)
{
temp = a[j + 1];
a[j + 1] = a[j];
a[j] = temp;
System.out.println(Arrays.toString(a));
Anagram2(j + 1);
} else
return;
}
public static void main(String args[])
{
rec r =new rec();
r.Anagram(0);
}
}
I was trying out this question :
Write a function using Recursion to display all anagrams of a string entered by the user, in such a way that all its vowels are located at the end of every anagram. (E.g.: Recursion => Rcrsneuio, cRsnroieu, etc.) Optimize it.
From this site :
http://erwnerve.tripod.com/prog/recursion/magic.htm
This is what i have done :
public static void permute(char[] pre,char[] suff) {
if (isEmpty(suff)) {
//result is a set of string. toString() method will return String representation of the array.
result.add(toString(moveVowelstoEnd(pre)));
return;
}
int sufflen = getLength(suff); //gets the length of the array
for(int i =0;i<sufflen;i++) {
char[] tempPre = pre.clone();
char[] tempSuf = suff.clone();
int nextindex = getNextIndex(pre); //find the next empty spot in the prefix array
tempPre[nextindex] = tempSuf[i];
tempSuf = removeElement(i,tempSuf); //removes the element at i and shifts array to the left
permute(tempPre,tempSuf);
}
}
public static char[] moveVowelstoEnd(char[] input) {
int c = 0;
for(int i =0;i<input.length;i++) {
if(c>=input.length)
break;
char ch = input[i];
if (vowels.contains(ch+"")) {
c++;
int j = i;
for(;j<input.length-1;j++)
input[j] = input[j+1];
input[j]=ch;
i--;
}
}
return input;
}
Last part of the question is 'Optimize it'. I am not sure how to optimize this. can any one help?
Group all the vowels into v
Group all consonants into w
For every pair of anagrams, concat the results