Find if we can get palindrome - c++

Given a string S.We need to tell if we can make it to palindrome by removing exactly one letter from it or not.
I have a O(N^2) approach by modifying Edit Distance method.Is their any better way ?
My Approach :
int ModifiedEditDistance(const string& a, const string& b, int k) {
int i, j, n = a.size();
int dp[MAX][MAX];
memset(dp, 0x3f, sizeof dp);
for (i = 0 ; i < n; i++)
dp[i][0] = dp[0][i] = i;
for (i = 1; i <= n; i++) {
int from = max(1, i-k), to = min(i+k, n);
for (j = from; j <= to; j++) {
if (a[i-1] == b[j-1]) // same character
dp[i][j] = dp[i-1][j-1];
// note that we don't allow letter substitutions
dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]); // delete character j
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]); // insert character i
}
}
return dp[n][n];
}
How to improve space complexity as max size of string can go upto 10^5.
Please help.
Example : Let String be abc then answer is "NO" and if string is "abbcbba then answer is "YES"

The key observation is that if the first and last characters are the same then you needn't remove either of them; which is to say that xSTRINGx can be turned into a palindrome by removing a single letter if and only if STRING can (as long as STRING is at least one character long).
You want to define a method (excuse the Java syntax--I'm not a C++ coder):
boolean canMakePalindrome(String s, int startIndex, int endIndex, int toRemove);
which determines whether the part of the string from startIndex to endIndex-1 can be made into a palindrome by removing toRemove characters.
When you consider canMakePalindrome(s, i, j, r), then you can define it in terms of smaller problems like this:
If j-i is 1 then return true; if it's 0 then return true if and only if r is 0. The point here is that a 1-character string is a palindrome regardless of whether you remove a character; a 0-length string is a palindrome, but can't be made into one by removing a character (because there aren't any to remove).
If s[i] and s[j-1] are the same, then it's the same answer as canMakePalindrome(s, i+1, j-1, r).
If they're different, then either s[i] or s[j-1] needs removing. If toRemove is zero, then return false, because you haven't got any characters left to remove. If toRemove is 1, then return true if either canMakePalindrome(s, i+1, j, 0) or canMakePalindrome(s, i, j-1, 0). This is because you're now testing whether it's already a palindrome if you remove one of those two characters.
Now this can be coded up pretty easily, I think.
If you wanted to allow for removal of more than one character, you'd use the same idea, but using dynamic programming. With only one character to remove, dynamic programming will reduce the constant factor, but won't reduce the asymptotic time complexity (linear in the length of the string).

Psudocode (Something like this I havn't tested it at all).
It is based on detecting the conditions that you CAN remove a character, ie
There is exactly 1 wrong character
It is a palendrome (0 mismatch)
O(n) in time, O(1) in space.
bool foo(const std::string& s)
{
int i = 0;
int j = s.size()-1;
int mismatch_count = 0;
while (i < j)
{
if (s[i]==s[j])
{
i++; j--;
}
else
{
mismatch_count++;
if (mismatch_count > 1) break;
//override first preference if cannot find match for next character
if (s[i+1] == s[j] && ((i+2 >= j-1)||s[i+2]==s[j-1]))
{
i++;
}
else if (s[j-1]==s[i])
{
j--;
}
else
{
mismatch_count++; break;
}
}
}
//can only be a palendrome if you remove a character if there is exactly one mismatch
//or if a palendrome
return (mismatch_count == 1) || (mismatch_count == 0);
}

Here's a (slightly incomplete) solution which takes O(n) time and O(1) space.
// returns index to remove to make a palindrome; string::npos if not possible
size_t willYouBeMyPal(const string& str)
{
size_t toRemove = string::npos;
size_t len = str.length();
for (size_t c1 = 0, c2 = len - 1; c1 < c2; ++c1, --c2) {
if (str[c1] != str[c2]) {
if (toRemove != string::npos) {
return string::npos;
}
bool canRemove1 = str[c1 + 1] == str[c2];
bool canRemove2 = str[c1] == str[c2 - 1];
if (canRemove1 && canRemove2) {
abort(); // TODO: handle the case where both conditions are true
} else if (canRemove1) {
toRemove = c1++;
} else if (canRemove2) {
toRemove = c2--;
} else {
return string::npos;
}
}
}
// if str is a palindrome already, remove the middle char and it still is
if (toRemove == string::npos) {
toRemove = len / 2;
}
return toRemove;
}
Left as an exercise is what to do if you get this:
abxyxcxyba
The correct solution is:
ab_yxcxyba
But you might be led down a bad path:
abxyxcx_ba
So when you find the "next" character on both sides is a possible solution, you need to evaluate both possibilities.

I wrote a sample with O(n) complexity that works for the tests I threw at it. Not many though :D
The idea behind it is to ignore the first and last letters if they are the same, deleting one of them if they are not, and reasoning what happens when the string is small enough. The same result could be archived with a loop instead of the recursion, which would save some space (making it O(1)), but it's harder to understand and more error prone IMO.
bool palindrome_by_1(const string& word, int start, int end, bool removed = false) // Start includes, end excludes
{
if (end - start == 2){
if (!removed)
return true;
return word[start] == word[end - 1];
}
if (end - start == 1)
return true;
if (word[start] == word[end - 1])
return palindrome_by_1(word, start + 1, end - 1, removed);
// After this point we need to remove a letter
if (removed)
return false;
// When two letters don't match, try to eliminate one of them
return palindrome_by_1(word, start + 1, end, true) || palindrome_by_1(word, start, end - 1, true);
}

Checking if a single string is palindrome is O(n). You can implement a similar algorithm than moves two pointers, one from the start and another from the end. Move each pointer as long as the chars are the same, and on the first mismatch try to match which char you can skip, and keep moving both pointers as long as the rest chars are the same. Keep track of the first mismatch. This is O(n).

I hope my algorithm will pass without providing code.
If a word a1a2....an can be made a palindrome by removing ak, we can search for k as following:
If a1 != an, then the only possible k would be 1 or n. Just check if a1a2....an-1 or a2a3....an is a palindrome.
If a1 == an, next step is solving the same problem for a2....an-1. So we have a recursion here.

public static boolean pal(String s,int start,int end){
if(end-start==1||end==start)
return true;
if(s.charAt(start)==s.charAt(end))
return pal(s.substring(start+1, end),0,end-2);
else{
StringBuilder sb=new StringBuilder(s);
sb.deleteCharAt(start);
String x=new String(sb);
if(x.equals(sb.reverse().toString()))
return true;
StringBuilder sb2=new StringBuilder(s);
sb2.deleteCharAt(end);
String x2=new String(sb2);
if(x2.equals(sb2.reverse().toString()))
return true;
}
return false;
}

I tried the following,f and b are the indices at which characters do not match
int canwemakepal(char *str)//str input string
{
long int f,b,len,i,j;
int retval=0;
len=strlen(str);
f=0;b=len-1;
while(str[f]==str[b] && f<b)//continue matching till we dont get a mismatch
{
f++;b--;
}
if(f>=b)//if the index variable cross over each other, str is palindrome,answer is yes
{
retval=1;//true
}
else if(str[f+1]==str[b])//we get a mismatch,so check if removing character at str[f] will give us a palindrome
{
i=f+2;j=b-1;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else if(str[f]==str[b-1])//else check the same for str[b]
{
i=f+1;j=b-2;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else
retval=0;
return retval;
}

I created this solution,i tried with various input giving correct result,still not accepted as correct solution,Check it n let me know if m doing anything wrong!! Thanks in advance.
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int t = s.nextInt();
String result[] = new String[t];
short i = 0;
while(i < t)
{
String str1 = s.next();
int length = str1.length();
String str2 = reverseString(str1);
if(str1.equals(str2))
{
result[i] = "Yes";
}
else
{
if(length == 2)
{
result[i] = "Yes";
}
else
{
int x = 0,y = length-1;
int counter = 0;
while(x<y)
{
if(str1.charAt(x) == str1.charAt(y))
{
x++;
y--;
}
else
{
counter ++;
if(str1.charAt(x) == str1.charAt(y-1))
{
y--;
}
else if(str1.charAt(x+1) == str1.charAt(y))
{
x++;
}
else
{
counter ++;
break;
}
}
}
if(counter >= 2)
{
result[i] = "No";
}
else
result[i]="Yes";
}
}
i++;
} // Loop over
for(int j=0; j<i;j++)
{
System.out.println(result[j]);
}
}
public static String reverseString(String original)
{
int length = original.length();
String reverse = "";
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
return reverse;
}

Related

C++ Palindrome program always giving 0 (false) as an output problem; Where is my code wrong?

The problem is that it always outputs 0 (false) as a result. Probably the problem is in the isPalindrome function, but I cannot figure where exactly. Would be grateful if someone helped.
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
bool isPalindrome(string word)
{
bool result;
for (int i = 0; i <= word.length() - 1; i++)
{
if (word.at(i) == word.length() - 1)
{
result = true;
}
else
{
result = false;
}
return result;
}
}
int main()
{
string word1;
int count;
cout << "How many words do you want to check whether they are palindromes: " << flush;
cin >> count;
for (int i = 0; i < count; i++)
{
cout << "Please enter a word: " << flush;
cin >> word1;
cout << "The word you entered: " << isPalindrome(word1);
}
}
Try this one:
bool isPalindrome(string word)
{
bool result = true;
for (int i = 0; i < word.length() / 2; i++) //it is enough to iterate only the half of the word (since we take both from the front and from the back each time)
{
if (word[i] != word[word.length() - 1 - i]) //we compare left-most with right-most character (each time shifting index by 1 towards the center)
{
result = false;
break;
}
}
return result;
}
In this statement
if (word.at(i) == word.length() - 1)
the right side expression of the comparison operator is never changed and have the type std::string::size_type instead of the type char. You mean
if (word.at(i) == word.at( word.length() - 1 - i ))
However there is no sense to use the member function at. You could us the subscript operator. For example
if ( word[i] == word[word.length() - 1 - i ] )
And the loop should have word.length() / 2 iterations.
Also within the loop you are overwriting the variable result. So you are always returning the last value of the variable. It can be equal to true though a string is not a palindrome.
Also the parameter should be a referenced type. Otherwise a redundant copy of the passed argument is created.
The function can be defined the following way
bool isPalindrome( const std::string &word )
{
std::string::size_type i = 0;
std::string::size_type n = word.length();
while ( i < n / 2 && word[i] == word[n - i - 1] ) i++;
return i == n / 2;
}
Another approach is the following
bool isPalindrome( const std::string &word )
{
return word == std::string( word.rbegin(), word.rend() );
}
Though this approach requires to create a reverse copy of the original string.
The simplest way is to use the standard algorithm std::equal. Here is a demonstrative program
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
bool isPalindrome( const std::string &word )
{
return std::equal( std::begin( word ),
std::next( std::begin( word ), word.size() / 2 ),
std::rbegin( word ) );
}
int main()
{
std::cout << isPalindrome( "123454321" ) << '\n';
return 0;
}
I hope this one helps you also (corrected also warnings):
bool isPalindrome(string word)
{
bool result = false;
int lengthWord = (int)word.length();
for (int i = 0; i <= (lengthWord / 2); ++i)
{
if (word.at(i) == word.at(lengthWord - i -1))
{
result = true;
continue;
}
result = false;
}
return result;
}
Two possible problems.
You appear to be comparing a character to a number
if (word.at(i) == word.length() - 1)
shouldn't this be
if (word.at(i) == word.at(word.length() - i)) ?
There are 3 returns within the if statement, so no matter what the outcome it's only going to compare one character before returning to the calling function.
As a point of technique, repeated calls to .length inside the loop, which always returns the same value, wastes time and makes the code more difficult to understand.
You need to return as soon as you find a mismatch. If you are looking for a palindrome you only need to compare the first half of the word with the second half in reverse order. Something like
bool isPalindrome(string word)
{
for (int i = 0, j= word.length() - 1; i<j; i++, j--)
// i starts at the beginning of the string, j at the end.
// Once the i >= j you have reached the middle and are done.
// They step in opposite directions
{
if (word[i] != word[j])
{
return false;
}
}
return true;
}
The loop in the function isPalindrome will only execute once, because the return statement is unconditionally executed in the first iteration of the loop. I am sure that this is not intended.
To determine whether a string is a palindrome, the loop must be executed several times. Only after the last character has been evaluated (in the last iteration of the loop) will it be time to use the return statement, unless you determine beforehand that the string is not a palindrome.
Also, in the function isPalindrome, the following expression is nonsense, as you are comparing the ASCII Code of a letter with the length of the string:
word.at(i) == word.length() - 1
Therefore, I suggest the following code for the function:
bool isPalindrome(string word)
{
for (int i = 0; i < word.length() / 2; i++)
{
if (word.at(i) != word.at( word.length() - i - 1) ) return false;
}
return true;
}
As discussed in the comments under your question. You made some mistakes in the code.
Your function should more or less look like this:
bool isPalindrome(string word) {
bool result = true;
for (int i = 0; i <= word.length() - 1; i++)
{
if (word.at(i) != word.at(word.length() - 1 -i))
{
return false;
}
}
return result;
}

Search a string for all occurrences of a substring in C++

Write a function countMatches that searches the substring in the given string and returns how many times the substring appears in the string.
I've been stuck on this awhile now (6+ hours) and would really appreciate any help I can get. I would really like to understand this better.
int countMatches(string str, string comp)
{
int small = comp.length();
int large = str.length();
int count = 0;
// If string is empty
if (small == 0 || large == 0) {
return -1;
}
// Increment i over string length
for (int i = 0; i < small; i++) {
// Output substring stored in string
for (int j = 0; j < large; j++) {
if (comp.substr(i, small) == str.substr(j, large)) {
count++;
}
}
}
cout << count << endl;
return count;
}
When I call this function from main, with countMatches("Hello", "Hello"); I get the output of 5. Which is completely wrong as it should return 1. I just want to know what I'm doing wrong here so I don't repeat the mistake and actually understand what I am doing.
I figured it out. I did not need a nested for loop because I was only comparing the secondary string to that of the string. It also removed the need to take the substring of the first string. SOOO... For those interested, it should have looked like this:
int countMatches(string str, string comp)
{
int small = comp.length();
int large = str.length();
int count = 0;
// If string is empty
if (small == 0 || large == 0) {
return -1;
}
// Increment i over string length
for (int i = 0; i < large; i++) {
// Output substring stored in string
if (comp == str.substr(i, small)) {
count++;
}
}
cout << count << endl;
return count;
}
The usual approach is to search in place:
std::string::size_type pos = 0;
int count = 0;
for (;;) {
pos = large.find(small, pos);
if (pos == std::string::npos)
break;
++count;
++pos;
}
That can be tweaked if you're not concerned about overlapping matches (i.e., looking for all occurrences of "ll" in the string "llll", the answer could be 3, which the above algorithm will give, or it could be 2, if you don't allow the next match to overlap the first. To do that, just change ++pos to pos += small.size() to resume the search after the entire preceding match.
The problem with your function is that you are checking that:
Hello is substring of Hello
ello is substring of ello
llo is substring of llo
...
of course this matches 5 times in this case.
What you really need is:
For each position i of str
check if the substring of str starting at i and of length = comp.size() is exactly comp.
The following code should do exactly that:
size_t countMatches(const string& str, const string& comp)
{
size_t count = 0;
for (int j = 0; j < str.size()-comp.size()+1; j++)
if (comp == str.substr(j, comp.size()))
count++;
return count;
}

Breaking a given string into dictionary words

Am trying to break a given string into dictionary words from a given dictionary and find all such possible sets.
Ex.: if given word is “programmerit”, then output shall be:
{{pro, gram, merit}, {program, merit}, {programmer, it}}
My below solution, works in exponential time. O(c^n); where is c is some constant I haven't evaluated and n is the size (characters) of given word.
I am trying to reduce the complexity or maybe bring it down to a lower exponent, but to no avail. Looking for any suggestions in this regard.
PS: this is not a homework or assignment problem, I am a working professional and trying this out of curiosity.
Here is my code:
bool isContained(string word, string s) {
for (int i = 0; i < s.length(); i++) {
if (i >= word.length())
return false;
if (word[i] != s[i])
return false;
}
return true;
}
void getParts(vector<string> dict, string word, stack<string> s, vector<vector<string> > &parts) {
if (word.length() == 0) {
if (s.size() > 0) {
vector<string> part;
stack<string> t = s;
while(!t.empty()) {
part.push_back(t.top());
t.pop();
}
parts.push_back(part);
}
} else {
int j = find_starting_ind(dict, word[0]);
int ct = j;
while (dict[ct][0] == word[0]) {
if (isContained(word, dict[ct])) {
s.push(dict[ct]);
string nword = word-dict[ct];
getParts(dict, nword, s, parts);
s.pop();
}
ct++;
}
}
}

How to call a function within a function?

I am trying to determine if my code is a palindrome so I created a reverse function and then a palindrome function. I am trying to assign the reversed Character array into the new function but I can't seem to get it to compile.... any tips?
Here is my palindrome function
bool Palindrome(char Characters[], unsigned long length)
{
char tempstring[62];
tempstring[62] == reverse(Characters);
for(int i=0; i <= length; i++){
if(Characters[i] == tempstring[i])
return false;
else
return true;
}
}
Here is my reverse function
void reverse(char Characters[], unsigned long length)
{
char temp;
for(int i=0; i<length/2; i++){
temp = Characters[i];
Characters[i]=Characters[length-i-1];
Characters[length-i-1]=temp;
}
}
First things first, you have a typo; == is a compare equality, =. You ought to have written
tempstring[62] = reverse(Characters);
But this will still not work. For starters, reverse is a void function and so therefore it does not return a value.
The quickest fix will be to replace that line with
reverse(Characters, length);
(Note that I'm also passing the length parameter as required).
One final thing: if you have organised your file so that reverse appears after Palindrome, then you need to forward declare reverse using this statement:
void reverse(char Characters[], unsigned long length);
That fixes the compilation errors. I defer to you to check the runtime behaviour.
You are making this quite complicated.
Just find the end of the string (strlen). Read from both ends a character at a time and if they do not match then it is not a palindrome. If the indexes become the same or they cross then you are done. It is indeed a palindrome.
I.e
bool Palindrome(char *s) {
int left = 0, right = strlen(s) - 1;
while (left < right) {
if (s[left] != s[right] return false;
++left;
--right;
}
return true;
}
EDIT
Similar vain to construct the reverse
char *Reverse(char *s)
{
char *rev = new char[strlen(s) + 1];
int left = 0, right = strlen(s) - 1;
while (right > -1) {
rev[left] = s[right];
right--;
left++;
}
rev[left] = 0;
// Remember to use delete[]
return rev;
}
EDIT 2
Or
void Reverse(char[] s, int len) {
int left = 0; right = len;
while (right > -1) {
char t = s[left];
s[left] = s[right];
s[right] = t;
left++; right--;
}
}
Then make a copy of the string, reverse it and compare it.
Your error is the line tempstring[62] == reverse(Characters);. You don't need the double = sign. In the future, it would be helpful to post the error messages you get when compiling.
bool Palindrome(char Characters[], unsigned long length)
{
char tempstring[62];
tempstring[62] = reverse(Characters);
for(int i=0; i <= length; i++){
if(Characters[i] == tempstring[i])
return false;
else
return true;
}
}
Your error is here:
tempstring[62] == reverse(Characters);
You've wrote == means, a condition that returns true or false (for example: if (5 == 7) -> false)
But what you've actually wanted to do was tempstring[62] = reverse(Characters);
One = means equal (int a = 3)
Two == means to check a condition (for example if (a == b) (and thats why you dont write in ifs: if(a = 3) because it will assign a = 3 and allways get inside the if
First of all, your reverse function returns nothing, so attempting to assign its return value to anything is not going to work:
tempstring[62] == reverse(Characters); // won't work as it is attempting to compare a void
tempstring[62] = reverse(Characters); // won't work as it is attempting to assign a void
From a more fundamental level, testing for a palindrome is much less complex than you are making it:
bool Palindrome(char Characters[], unsigned long length)
{
bool result = true;
for(int i=0; i < length / 2; i++)
{
if (Characters[i] != Characters[length - i - 1])
{
result = false;
break;
}
}
return result;
}

Generating all n-letter permutations

I am attempting to calculate all the possible 3 letter permutations, using the 26 letters (Which amounts to only 26*25*24=15,600). The order of the letters matters, and I don't want repeating letters. (I wanted the permutations to be generated in lexicographical order, but that isn't necessary)
So far I attempted to nest for loops, but I ended up iterating through every combination possible. So there are repeating letters, which I do not want, and the for loops can become difficult to manage if I want more than 3 letters.
I can flip through the letters until I get a letter that has not been used, but it isn't in lexicographical order and it is much slower than using next_permutation (I cannot use this std method because I'm left calculating all of the subsets of the 26 letters).
Is there a more efficient way to do this?
To put in perspective of the inefficiency, next_permutation iterates through the first 6 digits instantaneously. However, it takes several seconds to get all the three letter permutations using this method, and next_permutation still quickly becomes inefficient with the 2^n subsets I must calculate.
Here is what I have for the nested for loops:
char key[] = {'a','b','c','d','e','f','g','h','i','j','k',
'l','m','n','o','p','r','s','t','u','v','w','x','y','z'};
bool used[25];
ZeroMemory( used, sizeof(bool)*25 );
for( int i = 0; i < 25; i++ )
{
while( used[i] == true )
i++;
if( i >= 25 )
break;
used[i] = true;
for( int j = 0; j < 25; j++ )
{
while( used[j] == true )
j++;
if( j >= 25 )
break;
used[j] = true;
for( int k = 0; k < 25; k++ )
{
while( used[k] == true )
k++;
if( k >= 25 )
break;
used[k] = true;
cout << key[i] << key[j] << key[k] << endl;
used[k] = false;
}
used[j] = false;
}
used[i] = false;
}
Make a root which represents the start of a combination, so it has no value.
calculate all the possible children (26 letter, 26 children...)
for each root child calculate possible children (so: remaining letters)
use a recursive limited-depth search to find your combinations.
This is a solution I would try if i just want a "simple" solution. I'm not sure how recource intensive this is so I suggest you start trying with a small set of letters.
a = {a...z}
b = {a...z}
c = {a...z}
for each(a)
{
for each(b)
{
for each(c)
{
echo a + b + c;
}
}
}
For a specific and small, n, manual loops like you have is the easiest way. However, your code can be highly simplified:
for(char a='a'; a<='z'; ++a) {
for(char b='a'; b<='z'; ++b) {
if (b==a) continue;
for(char c='a'; c<='z'; ++c) {
if (c==a) continue;
if (c==b) continue;
std::cout << a << b << c << '\n';
}
}
}
For a variable N, obviously we need a different strategy. And, it turns out, it needs an incredibly different strategy. This is based on DaMachk's answer, of using recursion to generate subsequent letters
template<class func_type>
void generate(std::string& word, int length, const func_type& func) {
for(char i='a'; i<='z'; ++i) {
bool used = false;
for(char c : word) {
if (c==i) {
used = true;
break;
}
}
if (used) continue;
word.push_back(i);
if (length==1) func(word);
else generate(word, length-1, func);
word.pop_back();
}
}
template<class func_type>
void generate(int length, const func_type& func) {
std::string word;
generate(word, length, func);
}
You can see it here
I also made an unrolled version, which turned out to be incredibly complicated, but is significantly faster. I have two helper functions: I have a function to "find the next letter" (called next_unused) which increases the letter at an index to the next unused letter, or returns false if it cannot. The third function, reset_range "resets" a range of letters from a given index to the end of the string to the first unused letter it can. First we use reset_range to find the first string. To find subsequent strings, we call next_unused on the last letter, and if that fails, the second to last letter, and if that fails the third to last letter, etc. When we find a letter we can properly increase, we then "reset" all the letters to the right of that to the smallest unused values. If we get all the way to the first letter and it cannot be increased, then we've reached the end, and we stop. The code is frightening, but it's the best I could figure out.
bool next_unused(char& dest, char begin, bool* used) {
used[dest] = false;
dest = 0;
if (begin > 'Z') return false;
while(used[begin]) {
if (++begin > 'Z')
return false;
}
dest = begin;
used[begin] = true;
return true;
}
void reset_range(std::string& word, int begin, bool* used) {
int count = word.size()-begin;
for(int i=0; i<count; ++i)
assert(next_unused(word[i+begin], 'A'+i, used));
}
template<class func_type>
void doit(int n, func_type func) {
bool used['Z'+1] = {};
std::string word(n, '\0');
reset_range(word, 0, used);
for(;;) {
func(word);
//find next word
int index = word.size()-1;
while(next_unused(word[index], word[index]+1, used) == false) {
if (--index < 0)
return; //no more permutations
}
reset_range(word, index+1, used);
}
}
Here it is at work.
And here it is running in a quarter of the time as the simple one
I was doing a similar thing in powershell. Generating all the possible combinations of 9 symbols. After a bit of trial and error this is what I came up with.
$S1=New-Object System.Collections.ArrayList
$S1.Add("a")
$S1.Add("b")
$S1.Add("c")
$S1.Add("d")
$S1.Add("e")
$S1.Add("f")
$S1.Add("g")
$S1.Add("h")
$S1.Add("i")
$S1 | % {$a = $_
$S2 = $S1.Clone()
$S2.Remove($_)
$S2 | % {$b = $_
$S3 = $S2.Clone()
$S3.Remove($_)
$S3 | % {$c = $_
$S4 = $S2.Clone()
$S4.Remove($_)
$S4 | % {$d = $_
$S5 = $S4.Clone()
$S5.Remove($_)
$S5 | % {$e = $_
$S6 = $S5.Clone()
$S6.Remove($_)
$S6 | % {$f = $_
$S7 = $S6.Clone()
$S7.Remove($_)
$S7 | % {$g = $_
$S8 = $S7.Clone()
$S8.Remove($_)
$S8 | % {$h = $_
$S9 = $S8.Clone()
$S9.Remove($_)
$S9 | % {$i = $_
($a+$b+$c+$d+$e+$f+$g+$h+$i)
}
}
}
}
}
}
}
}
}