Here's what I'm trying to accomplish with this program: a recursive method that checks if the number of instances of a substring matches a specified amount of instances, returning a boolean.
Here's the issue I'm having with this particular recursive method: I'd like to be able to move the counter inside the recursive method body, however, I ran into the issue that the counter resets at each recursive call when it is in the method body. The only way I have been able to make it work is through the use of a static counter variable declared outside of the function body. Is there any other technique I can marshall in order to be able to situate the counter of the method in the method body so that this method may act as a "black box"?
Thanks for any advice or insights you can provide.
public class strCopies {
//count instances of part and whole equality
static int count = 0;
public static boolean copies(String whole, String part, int check)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(count == check)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check);
}
public static void main(String[] args)
{
System.out.println(copies("dogcatdog", "cat", 2));
}
}
You are almost there: you should change the meaning of the check variable to the remaining number of matches, rather than the original number requested. Then you can rewrite the method without keeping an additional count at all, as follows:
public static boolean copies(String whole, String part, int check)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(check == 0)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
check--;
}
return return copies(whole.substring(1), part, check);
}
You can pass the count as an argument to the recursive function, this way it will not be "reset" when the method is called.
public static boolean copies(String whole, String part, int check, int count)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(count == check)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
public int countRecursive(String whole, String part){
if(whole.length() < part.length()) return 0;
if(part.length()==0) return -1; // ints can't express "Infinity"
// maybe you want to return -1 only if whole is not null, and something else if it is.
int count = 0;
if(whole.substring(0, part.length()).equals(part))
count = 1;
return countRecursive(whole.substring(1), part) + count;
}
public boolean count(String whole, String part, int check){
return countRecursive(whole, part) == check;
}
Note that this does away with the counter at the expense of creating a whole bunch of strings for each state. (You replace a single int with the length of each string given.) But then again, if you want performance then you shouldn't be using recursion for something like this. A simple for loop would do much nicer.
You could add the counter to the method parameters as follows:
public class strCopies {
public static boolean copies(String whole, String pargs, int check){
return copies(whole, pargs, check, 0);
}
public static boolean copies(String whole, String part, int check, int count)
{
//check if current string length is valid
if(whole.length() < part.length()) {
//check if check parameter equals part instances
if(count == check) {
return true;
}
else {
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part)) {
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
public static void main(String[] args) {
System.out.println(copies("dogcatdog", "dog", 2));
}
}
The simple version:
Create a class that contain the counter.
Initialize it on your main.
Pass its reference to the function.
Another idea:
Create a singleton class with a static counter and your function X.
Inside its constructor add one to its counter and call function X.
Then instead of running your function like you did before, "create" that class, thus increasing the counter and calling the function.
The neat thing is you can inherit that class and redefine X to whatever you choose at a latter stage, so you get this general class that counts on each activation of a function.
Not sure what is your recursive method doing. However, to maintain a counter, you can pass it as an argument to your recursive method.
public boolean copies(String whole, String part, int check, int count) {
// your code here....
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
When you make first call to your copies method, you'll need to pass 0 to your count.
Related
Hi I'm a complete newbie on programming and I try to search for a certain String in an array. When it's found the method should return the index but if the String is not found it should return -1.
public int poitionOfWord(String testWord) {
for (int i = 0; i < wordArray.length; i++) {
if (wordArray[i].equals(testWord)) {
return i;
}
}
return -1;
}
would this method return always -1 or would it actually terminate when finding a word and would return i.
Your method is correct and it will return the index in case it finds a match else if it doesn't find the match, it will come out of loop and return -1.
Just to make code crisp and concise, you can use something like this,
public static String[] wordArray = new String[]{"a", "b"};
public static int poitionOfWord(String testWord) {
return Arrays.asList(wordArray).indexOf(testWord);
}
Then test it with some code,
public static void main(String args[]) {
System.out.println(poitionOfWord("a"));
System.out.println(poitionOfWord("z"));
}
This prints,
1
-1
In general, when your function reaches a return statement, it will terminate and return the given value.
public class Interpolation_search {
public static void main(String...s) {
int rr[]= {1,2,3,4,9,10,15,80};
System.out.println(search(rr,0,7,3));
}
static int search(int ar[], int lo, int hi,int X) {
if(lo<hi&&ar[lo]!=ar[hi]) {
int mid=lo + ((hi-lo)/(ar[hi]-ar[lo]))*(X-ar[lo]);
if(X==ar[mid])
return 1; //l1
else if(X>ar[mid])
search(ar,mid+1,hi,X);
else search(ar,lo,mid-1,X);
}
return 0; //l2
}
}
return is executing twice first at l1 and second at l2.
It seems that you have difficulties understanding recursion.
Your method search() is supposed to return an int result. And the method itself calls itself (using different arguments) repeatedly. Thing is: you are all ignoring these recursive calls.
In other words: the real answer is for you to step back and understand what recursion is meant to be, and how to properly use it. As a starter, you could try to change
search(ar,mid+1,hi,X);
to
return search(ar,mid+1,hi,X);
I am new here and I am somehow stuck.
I created an recursive algorithm that uses an global variable for remembering the Position he made the recursive call and I am trying to get rid of this variable as for me it seems to be not a good solution.
Is there any chance to get rid of this global variable? I cannot adjust the method-head so therefore the Interface of the method is fixed.
Here you can see my Code:
static int pos = -1;
static boolean writeInfix(char[] expr) {
boolean result;
pos++;
int printpos = pos;
if(expr[pos]=='+'||expr[pos]=='-'||expr[pos]=='/'||expr[pos]=='*'){
System.out.print("(");
writeInfix(expr);
System.out.print(expr[printpos]);
result = writeInfix(expr);
System.out.print(")");
return result;
}else if(expr[pos] >= 'a' && expr[pos] <= 'z'){
System.out.print(expr[pos]);
return true;
}else{
return false;
}
}
Thank you for your help :)
You can add a new auxiliary method, where you control its variables, and let writeInfix(char[]) be only a wrapper, that does nothing but calling the "real" method.
In this new method, pos is an arument.
This also ensures you can call your API method (writeInfix) twice (independently) without worrying from the side effects (pos is initialized with wrong value after first call).
You should be able to write another method with the position as additional argument:
private static boolean writeInfix(char[] expr, int pos) {
boolean result;
int printpos = pos;
if(expr[pos]=='+'||expr[pos]=='-'||expr[pos]=='/'||expr[pos]=='*'){
System.out.print("(");
writeInfix(expr);
System.out.print(expr[printpos]);
result = writeInfix(expr, pos + 1);
System.out.print(")");
return result;
}else if(expr[pos] >= 'a' && expr[pos] <= 'z'){
System.out.print(expr[pos]);
return true;
}else{
return false;
}
}
and in the method you already have, you just need to call
static boolean writeInfix(char[] expr) {
return writeInfix(expr, -1);
}
You can add pos as an argument to the writeInfix function.
static boolean writeInfix(char[] expr, int pos);
Whereever you are returning false, return -1. Whereever you are returning true, return the current pos value.
So I'm trying to write recursive method indexOf which returns the starting index of the first occurrence of the second String inside the first String (or -1 if not found).For example, the call of indexOf (“Barack Obama”, “bam”) would return 8. Also I know that String class has method IndexOf, but I don't want to use it.
So far this is my code:
public class MyClass {
public static void main(String[] args) {
}
public static int indexOf(String s, String t) {
return abc(s, t, 0);
}
public static int abc(String a, String b, int c) {
if ((a.length() - c) < b.length()) {
return -1;
} else if (b.equals(a.substring(c, c + 3))) {
return c;
} else {
}
}
}
It depends how much of the library you want to use.
One option is:
int indexOf(String container, String text, int index) {
//Too short container
if (container.length() < text.length()) return -1;
//found
else if (container.startsWith(text)) return index;
//keep searching
else return indexOf(container.substring(1), text, index+1);
}
indexOf("banana", "nana", 0) == 2;
If you don't want to use .startsWith, then you need to implement your own version. A very good exercise would be to try and do this without ever using the .substring method, which is terrible (as it creates a copy of the string, O(n) space/time performance), and which is not needed for this task (use .charAt)
You can also split the official method indexOf from its recursive call that includes the index for more clarity).
You should think carefully about edge cases too :)
First of all this is not homework. Just me practicing.
I'm trying to recursively determine the number of times "hi" appears in the given string, but in every case it skips to the last else if statement and things the string is empty. Any ideas?
Basically,
if(string starts with "hi")
increment count by 1 and recurse with the string after the 2nd index to skip over the "hi" it just counted
else if(string does not start with "hi" and string is not empty)
recurse with the string after its 1st index to see if it starts with "hi" the next time around.
else if(string is empty)
Print("End of text reached")
return count;
public class Practice {
public int recur(String str, int counter){
int count=counter;
if(str.startsWith("hi")){
count++;
recur(str.substring(2),count);
}
else if((!str.isEmpty())&&(!str.startsWith("hi"))){
recur(str.substring(1),count);
}
else if(str.isEmpty()){
System.out.println("End of text reached");
return count;
}
return count;
}
public static void main(String args[]){
String str="xxhixhixx";
Practice p=new Practice();
System.out.println(p.recur(str, 0));
}
}
This is a good opportunity to practice debugging recursive functions calls -- actually quite difficult. Suggestions:
use strategically placed print-statements to ensure that the arguments are being changed correctly from one recursive invocation to the next
refactor the order of case-analysis in the if-statement to make it more clear. For example, 1) check if the string is empty (base case), 2) check if the string starts with "hi", 3) catch-all -- not empty and doesn't start with "hi"
As #Steve mentioned, you have to use the return value that recur returns.
See below for a modified version of your code, I also simplified your if/else statements:
public int recur(String str, int counter) {
if (str.startsWith("hi")) {
return recur(str.substring(2), counter+1);
} else if (!str.isEmpty()) {
return recur(str.substring(1), counter);
} else {
System.out.println("End of text reached");
return counter;
}
}
public static void main(String args[]) {
String str = "xxhixhixx";
Practice p = new Practice();
System.out.println(p.recur(str, 0));
}
You aren't using the value returned from recur.
public int countHi(String str) {
if (str.length() <= 1) {
return 0;
}
int count = 0;
if (str.substring(0, 2).equals("hi")) {
count = 1;
}
return count + countHi(str.substring(1)); //substring off
}
All this does is recursively count the number of the String "hi" inside a larger String. The rest of the implementations should be a piece of cake, happy Coding!
Your program printing 'End of text' is correct as finally as per the logic it will reach there, reason for count always coming as 0 is that in every iteration they change there own copy and finally when the termination condition is reached(String is empty) the result is popped out of the stack, hence final outcome that you receive is the pop of the first iteration where count was 0, so you have to return the value returned by recur at every step instead of returning count.
public static int recursive(String givenStr) {
int count =0 ;
Pattern pattern = Pattern.compile("hi");
Matcher match = pattern.matcher(givenStr);
while(match.find()){
System.out.println(match);
count++;
}
return count;
}
This Will return number of times "hi" has appeared into the String