Does someone know of an algorithm to make a simple recursion to a tail one?
More specificaly, how would you apply the algorithm to the following code?
namespace Testing
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(match("?**", "aaa"));
Console.WriteLine(match("*#*?", "aa1$a1a1"));
Console.WriteLine(match("*#*", "aa11"));
Console.WriteLine(match("??*", "0110"));
Console.WriteLine(match("", "abc"));
Console.WriteLine(match("???", ""));
Console.ReadLine();
}
public static bool match(string p, string s)
{
if (p.Length == 0)
return true;
if (p.Length > s.Length)
return false;
bool firstLetterMatches = false;
char nextCharInStr = s[0];
switch (p[0])
{
case '*':
firstLetterMatches = 'a'<= nextCharInStr && nextCharInStr <= 'z';
break;
case '#':
firstLetterMatches = '0'<= nextCharInStr && nextCharInStr <= '9';
break;
case '?':
firstLetterMatches = ('a'<= nextCharInStr && nextCharInStr <= 'z') ||
('0'<= nextCharInStr && nextCharInStr <= '9');
break;
default:
return false;
}
return match(p,s.Substring(1)) ||
(firstLetterMatches && match(p.Substring(1),s.Substring(1)));
}
}
}
Thanks!
Sort of. You can make any recursive algorithm tail-recursive, awkwardly, by converting it into continuation-passing style. The effect is just to take the call stack and pass it around explicitly. But that won’t give you the benefit you’re probably thinking of, which is to be able to discard prior state after recursive calls to save space. You’re just putting the state somewhere else.
The real question might be: Can you change any recursive algorithm to require only constant space, potentially by way of using tail recursion? The answer, of course, is maybe. Typically, recursive functions that use tree recursion (where recursive calls branch into multiple deeper recursive calls) might be hard to transform this way. Your algorithm fits this description.
(I initially suggested memoizing
matchor using DP for this problem, which would speed it up, but I guess that wouldn’t actually save you space. Oh well.)