Get all N consecutive characters in string using stringstream in C++ - c++

I would like something that can window a std::string object into partitions of length N - for example (using a function update):
int main() {
std::string s = "abcdefg";
update<2>(s);
return 0;
}
Calling the above should result in:
ab
bc
cd
ef
fg
I have the following version of the update function:
template<std::size_t size>
void update(std::string s) {
std::string result(size, '\0');
std::stringstream ss{s};
int iterations = s.length() - size;
for (int i = 0; i<iterations; i++) {
ss.read(&result[0], result.size());
std::cout << result << std::endl;
}
return;
}
but this skips out combinations where the initial character lies at an odd index (the number of combinations is correct in my case, even though there is a repeat)
ab
cd
ef
gf
gf
A side note is that if there are any trailing characters then these should be omitted from the printed values (although I think this would be covered by the parameters of the for loop)
A final note is that I would like this to be as optimised as possible since I would typically be using strings of a very large length (>5M characters long) - my current solution may not be best for this so I am open to suggestions of alternative strategies.

With C++17 you can do it like this, which is way more readable:
void update(std::string_view s, int size) {
const int iterations = s.size() - size;
for (int i = 0; i <= iterations; i++) {
std::cout << s.substr(i, size) << "\n";
}
}
string_view is made exactly for this purpose, for fast read access to a string. string_view::substr is const complexity while string::substr is linear.
As a side note, besides what Nick mentioned, your code has few other small problems:
std::endl fflushes the stream, it heavily impacts performance. Here you could just use '\n' to make a newline.
the return at the end is absolutely redundant, void functions do not require returns
what is the purpose of templating this? This will easily bloat your code without any measurable performance increase. Just pass the N as a parameter.
also your main is declared as void and should be int (even more so as you do return a value at the end)

With range-v3, you might use sliding view:
std::string s = "abcdefg";
for (auto r : s | ranges::views::sliding(2)) {
std::cout << r << std::endl;
}
Demo

Your call to ss.read will always read two characters, and then advance the ptr in the string stream 2 characters. So you never read/repeat the previous character at the start of each line.
If you want to do it "your way" then you have to keep track of the last character seperately.
#include <iostream>
#include <sstream>
template<std::size_t size>
void update(std::string s) {
std::string result(size, '\0');
char lastChar;
std::stringstream ss{s};
int iterations = s.length() - size;
int read = 0;
if (ss.readsome(&result[0], 1)) {
lastChar = result[0];
}
for (int i = 0; i < iterations; i++) {
if (read = ss.readsome(&result[0], size - 1)) {
std::cout << lastChar << result << std::endl;
lastChar = result[read - 1];
}
}
}
That being said, the above is definitely not the best approach performance wise. You should be able to do all of this without any string streams or read function, just iterating the string. Something like this
#include <iostream>
void update(std::string s, size_t size) {
int len = s.length();
for (int i = 1; i < len; i+=size-1) {
fwrite(&s[i-1], size, 1, stdout);
putchar('\n');
}
}

Related

std::copy doesn't copy vector in C++

To find all sequences of fixed length which contain only 0 and 1 I use this code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void print_array(vector<string> arr) {
cout << '[';
int n = arr.size();
for (size_t i = 0; i < n; i++) {
cout << arr[i];
if (i < (n - 1)) {
cout << ", ";
}
}
cout << ']' << endl;
}
vector<string> get_variants(int n) {
vector<string> result = {"0", "1"};
vector<string> temp;
temp.reserve(2);
result.reserve(2);
for (int i=0; i < (n - 1); ++i) {
copy(result.begin(), result.end(), temp.end()); // [1]
for (int j=0; j < result.size(); ++j) {
temp[j] += "0";
result[j] += "1";
}
copy(temp.begin(),temp.end(), result.end());
temp.clear();
}
return result;
}
int main(int argc, char const *argv[]) {
int n;
cin >> n;
vector<string> maybe = get_variants(n);
print_array(maybe);
return 0;
}
But vector temp is empty, before copying in line which I marked [1] and after. So, my program's output was [0111, 1111]. What I'm doing wrong?
A more straightforward way than using std::copy is the use of .insert():
temp.insert(temp.end(), result.begin(), result.end()); //1
...
result.insert(result.end(), temp.begin(), temp.end()); // 2nd copy
You are writing to temp.end() and result.end(). These iterators represent "one past the end", and therefore writing to these iterators is Undefined Behavior.
You seem to be looking for std::back_inserter. This will create an iterator that will insert a new element to your container when it is written through.
std::copy(result.begin(), result.end(), std::back_inserter(temp));
While this answers the posted question, there remain other errors in your code leading to Undefined Behavior.
Trying to compile your program with a C++ compiler will not work, because you include #include <bits/stdc++.h>which is a non tC++ standard compliant header.
You should never include this file.
You are using typical competitive programming stuff, but including all C++ headers and not use them will eat up Compile time for no good reason.
Then, you typedef the typical competitive programming abbreviations. 2 of them, you do not use. Then there is no reason to define them.
I recommend to not do this any longer. And in C++, please use the using statement.
Then, although you want to be fast, you pass arr by value to your print function. This will copy the whole vector.
You assign/compare a lot of int with unsigned int values. This you should not do.
Additionally: Please use meaningful variable names and write comments. The more the better.
Regarding your specific bug. Both std::copy statements use end iterator as target. End is end. It is past the end of the vector. Please use std::back_inserter instead.
Regarding the algorithm. I took a while for me to realize that you basically want to create binary numbers. Nothing else. Unfortunately you translated that in a very complicated way.
Normally, you just would count from 0 to 2^n-1 and then show the data. Thats all. Becuase the numbers may be of arbitraty length, we will use manual addition of digits like in scholl on a peice of paper. Very simple.
Everthing then biols down to some lines of code.
Please see:
#include <iostream>
#include <vector>
int main() {
// Read length of binary number to create and validate input
if (int numberOfDigits{}; (std::cin >> numberOfDigits and numberOfDigits > 0)) {
// Here we will store the binary digits, so 0s or 1s
std::vector<int> digits(numberOfDigits,0);
// Som printing helper
std::cout << '[';
bool printComma{};
// We need to print 2^n possible combinations
for (int i = 0; i < (1 << numberOfDigits); ++i) {
// Print comma, if need
if (printComma) std::cout << ','; printComma = true;
// Print all digits of the binary number
for (const int d : digits) std::cout << d;
// Calculate next binary number
int carry = 0;
for (int index=numberOfDigits -1; index >=0; --index) {
const int sum = digits[index] + ((index == (numberOfDigits - 1)?1:0)) + carry;
carry = sum / 2;
digits[index] = sum % 2;
}
}
std::cout << ']';
}
}
If there should be questions, then I am happy to answer.

Creating strings by splitting a char array

As part of my homework assignment, I have to split a char[] by its indices. So for example, the main function looks like:
int main()
{
char str[] = "A string to be split into given number of parts";
int split_size;
cout << "Enter the size of the part: ";
cin >> split_size;
int size = sizeof(str) / sizeof(str[0]);
SplitString(str, split_size, size);
int wait;
cin >> wait;
return 0;
}
Then using the function SplitString, the first x elements are printed, new line, then the next.
My first idea, was to use two for loops. One loops through the splits (i.e. if there are 4 splits, the range on this loop is 0 to 3), then the second loops through the split itself, iterating over the array elements.
My SplitString() function looks like this:
void SplitString(char str[], int split_size, int size) {
int parts = size / split_size;
for (int i = 0; i < parts; i++) {
for (int j = 0; j < split_size; j++) {
j = split_size * i;
cout << str[j];
}
cout << endl;
}
}
Is there an easier way to do this? I know in Python, you can use the arr[1:] to grab a range of elements from the array. Is there anything similar in C++? Is there some flaw in my logic? Is there something wrong with my code?
cout comes with a write function that takes a pointer and a size argument.
for (int i = 0; i < parts; i++) {
cout.write (str+i*split_size, split_size)
cout << endl;
}
Note that the code above does not check if the string is actually long enough. If the total size is not equal the split_size times a whole number, you will have to add an additional check.
Also, note that this:
int size = sizeof(str) / sizeof(str[0]);
can be written as:
int size = sizeof(str);
instead because the size of a char is always 1.
You can use std::string for this. Alternatively, if your compiler supports C++17, you can use std::string_view as the first argument of SplitString to avoid unnecessary copying.
#include <algorithm>
#include <iostream>
#include <string>
void SplitString(std::string s, std::size_t split_size)
{
while(!s.empty())
{
auto size = std::min(split_size, s.size());
std::cout << s.substr(0, size) << '\n';
s = s.substr(size, std::string::npos);
}
}
int main()
{
char str[] = "A string to be split into given number of parts";
int split_size = 5;
SplitString(str, split_size);
return 0;
}
Live example.

cin strings into a vector and quicksort them

Write a void function called string_list_sort() that reads in any number of strings (duplicates are allowed) from cin, stores them in a vector, and then sorts them. Don’t use the standard C++ sort function here — use the version of quicksort that you created.
My problem is I tried to use strcmp() but I got a lot of errors, so I tried this method, but I have a problem with char val = v[end]. I am not sure how to compare two std::string values.
I changed char to string and it works. Now my problem is for example v = {" apple", "car", "fox", " soap", "foz"}; the result I get is apple, soap, car, fox, foz which is not in alphabetical order
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <vector>
#include "error.h"
using namespace std;
void string_list_sort(vector<string> v){
string line;
while (getline(cin, line)){
if (line.empty()){
break;
}
v.push_back(line);
}
}
int partition(vector<string>&v, int begin, int end)
{
char val = v[end];
char temp;
int j = end;
int i = begin - 1;
while (true)
{
while (v[++i] < val)
while (v[--j] > val)
{
if (j == begin)
break;
}
if (i >= j)
break;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
temp = v[i];
v[i] = v[end];
v[end] = temp;
return i;
}
void quicksort(vector<string>& v, int begin, int end)
{
if (begin < end)
{
int p = partition(v, begin, end);
quicksort(v, begin, p - 1);
quicksort(v, p + 1, end);
}
}
void quick_sort(vector<string>& v)
{
quicksort(v, 0, v.size() - 1);
}
int main()
{
vector<string> v;
v =
{ " this is a test string,.,!"};
string word;
while (cin >> word)
{
v.push_back(word);
}
quick_sort(v);
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
}
OP almost has a sorting function. Two mistakes in particular stand out:
char val = v[end];
char temp;
v is a vector<string> so v[end] will return a string.
string val = v[end];
string temp;
Takes care of that and makes the program compile and successfully sort. There is no need to go inside the strings to compare character by character. string does that work for you.
The second problem: Quicksort's partition function is supposed to look like (Looting from wikipedia here)
algorithm partition(A, lo, hi) is
pivot := A[lo]
i := lo – 1
j := hi + 1
loop forever
do
i := i + 1
while A[i] < pivot
do
j := j – 1
while A[j] > pivot
if i >= j then
return j
swap A[i] with A[j]
and OP's partition function has picked up a bunch of extra baggage that needs to be removed to get an optimal mark from their instructor. Take a look at the above pseudo implementation and compare it with yours. You may see the mistakes right way, but if not, stand on the shoulders of giants and translate it into C++ (hints: := is plain old = in C++, and you'll need to add some ;s and braces). Debug the result as required. I won't translate it because that would almost totally defeat the point of the assignment.
Side notes (gathering a few important comments):
When writing a test driver don't take in user input until you know the algorithm works. Start with preloaded input that is easy to visualize like
int main()
{
vector<string> v{"C","B","A"};
quick_sort(v);
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
}
When the output is "A B C ", change the input to something more complicated, but still easy to visualize
vector<string> v{"A","C","Q","B","A"};
And when that works go nuts and feed it something nasty. I like the Major General's Song from the Pirates of Penzance.
You can compare strings using std::string::compare() or relational operators.
It looks like you've tried using relational operators here, but as #user4581301 pointed out, in partition() on the first line, you have
char val = v[end];
However, v[end] is of type 'string', not 'char'. If you declare val and temp as string instead of char, you can sort them with the relational operators you have, and I think you'll be fine.
compare() documentation: fttp://www.cplusplus.com/reference/string/string/compare/
Relational operators: http://www.cplusplus.com/reference/string/string/operators/

Number of characters matching between two strings in C++

I am building a small project for spelling correction, this is not homework.
Given two strings str1 and str2. One has to find out the number of characters matching between two strings.
For example if str1 = "assign" and str2 = "assingn", then the output should be 6.
In str2, characters, "a", "s", "s", "i", "g", "n" are there in str1, "assign". Thus output should be 6.
If str1 = "sisdirturn" and str2 = "disturb", then output should be 6.
In the str2, characters, "d", "i", "s", "t", "u", "r" are there in string str1, "sisdirturn". Thus output should be 6.
I've tried many attempts, however I am unable to get the answer. Kindly help to sort this out and if there is any idea to improve upon this, do tell.
Here is my attempt so far:
int char_match (string str1, string str2)
{
//Take two strings, split them into vector of characters and sort them.
int i, j, value = 0;
vector <char> size1, size2;
char* cstr1 = new char[str1.length() + 1];
strcpy(cstr1, str1.c_str());
char* cstr2 = new char[str2.length() + 1];
strcpy(cstr2, str2.c_str());
for(i = 0, j = 0 ; i < strlen(cstr1), j < strlen(cstr2); i++, j++)
{
size1.push_back( cstr1[i] );
size2.push_back( cstr2[j] );
}
sort (size1.begin(), size1.end() );
sort (size2.begin(), size2.end() );
//Start from beginning of two vectors. If characters are matched, pop them and reset the counters.
i = 0;
j = 0;
while ( !size1.empty() )
{
out :
while ( !size2.empty() )
{
if (size1[i] == size2[j])
{
value++;
pop_front(size1);
pop_front(size2);
i = 0;
j = 0;
goto out;
}
j++;
}
i++;
}
return value;
}
#include <iostream>
#include <algorithm> // sort, set_intersection
std::string::size_type matching_characters(std::string s1, std::string s2) {
sort(begin(s1), end(s1));
sort(begin(s2), end(s2));
std::string intersection;
std::set_intersection(begin(s1), end(s1), begin(s2), end(s2),
back_inserter(intersection));
return intersection.size();
}
int main() {
std::cout << matching_characters("assign", "assingn") << '\n'; // 6
std::cout << matching_characters("sisdirturn", "disturb") << '\n'; // 6
}
The above uses sort and so it has O(N*log N) performance, if that matters. If all your inputs are small then this may be faster than the second solution:
Sora's solution has better complexity, and can also be implemented concisely using standard <algorithm>s:
#include <iostream>
#include <algorithm> // for_each
#include <numeric> // inner_product
int matching_characters(std::string const &s1, std::string const &s2) {
int s1_char_frequencies[256] = {};
int s2_char_frequencies[256] = {};
for_each(begin(s1), end(s1),
[&](unsigned char c) { ++s1_char_frequencies[c]; });
for_each(begin(s2), end(s2),
[&](unsigned char c) { ++s2_char_frequencies[c]; });
return std::inner_product(std::begin(s1_char_frequencies),
std::end(s1_char_frequencies),
std::begin(s2_char_frequencies), 0, std::plus<>(),
[](auto l, auto r) { return std::min(l, r); });
}
int main() {
std::cout << matching_characters("assign", "assingn") << '\n'; // 6
std::cout << matching_characters("sisdirturn", "disturb") << '\n'; // 6
}
I'm using C++14 features, such as generic lambdas, for convenience. You may have to make some modifications if your compiler doesn't support C++14.
For me the solution using sort and set_intersection takes about 1/4th the time as the other solution for these inputs. That's because sorting and iterating over arrays of 6 or 7 elements can be faster than having to walk over arrays of 256 elements.
sort/set_intersection (3667ns) vs. for_each/inner_product (16,363ns)
Once the input is large enough the speed advantage will tip the other way. Furthermore, at the point where the input is too large to take advantage of the small-string optimization then the sort/set_intersection method will start doing expensive memory allocations.
Of course this performance result is highly implementation dependent, so if the performance of this routine matters you'll have to test it yourself on your target implementation with real input. If it doesn't matter then the O(N) solution is the better choice.
I am not 100% on what it is you are actually trying to achieve, but in the case of trying to see how many characters that match in the words, it would be a simple case of just running a loop through them and adding 1 every time you found a match, like this
int char_match (string str1, string str2)
{
//Take two strings, split them into vector of characters and sort them.
unsigned int matches = 0;
unsigned int stringLength = (str1.length > str2.length) ? str2.length : str1.length;
for(unsigned int i = 0; i < stringLength; ++i)
{
if(str1[i] == str2[i])
{
++matches;
}
}
return matches;
}
but from your code it looks like you want to find out exactly how many of the same characters they have that is to say ignoring the actual position of each character then it would be a rather different process. Something along the lines of this
int char_match (string str1, string str2)
{
unsigned int str1CharCount[256] = {0};
unsigned int str2CharCount[256] = {0};
unsigned int matches = 0;
for(unsigned int i = 0; i < str1.length; ++i)
{
++str1CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = 0; i < str2.length; ++i)
{
++str2CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = 0; i < 256; ++i)
{
matches += (str1CharCount[i] > str1CharCount[i]) ? str1CharCount[i] - (str1CharCount[i] - str2CharCount[i]) : str2CharCount[i] - (str2CharCount[i] - str1CharCount[i]);
}
return matches;
}
please note that for this second function there are probably a lot more efficient ways of doing it, but it should work all the same
EDIT:
This code should do what you wanted, main difference being it checks the ascii value to make sure it is a valid character
int char_match (string str1, string str2)
{
unsigned int str1CharCount[256] = {0};
unsigned int str2CharCount[256] = {0};
unsigned int matches = 0;
for(unsigned int i = 0; i < str1.length; ++i)
{
unsigned short aValue = static_cast<unsigned short>(str1[i]);
if(aValue >= static_cast<unsigned short>('a') && aValue <= static_cast<unsigned short>('z'))
{
++str1CharCount[static_cast<unsigned short>(str1[i]) - 32];
}
else if(aValue >= static_cast<unsigned short>('A') && aValue <= static_cast<unsigned short>('Z'))
{
++str1CharCount[static_cast<unsigned short>(str1[i])];
}
}
for(unsigned int i = 0; i < str2.length; ++i)
{
++str2CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = static_cast<unsigned short>('a'); i <= static_cast<unsigned short>('Z'); ++i)
{
matches += (str1CharCount[i] > str1CharCount[i]) ? str1CharCount[i] - (str1CharCount[i] - str2CharCount[i]) : str2CharCount[i] - (str2CharCount[i] - str1CharCount[i]);
}
return matches;
}

Are there any better methods to do permutation of string?

void permute(string elems, int mid, int end)
{
static int count;
if (mid == end) {
cout << ++count << " : " << elems << endl;
return ;
}
else {
for (int i = mid; i <= end; i++) {
swap(elems, mid, i);
permute(elems, mid + 1, end);
swap(elems, mid, i);
}
}
}
The above function shows the permutations of str(with str[0..mid-1] as a steady prefix, and str[mid..end] as a permutable suffix). So we can use permute(str, 0, str.size() - 1) to show all the permutations of one string.
But the function uses a recursive algorithm; maybe its performance could be improved?
Are there any better methods to permute a string?
Here is a non-recursive algorithm in C++ from the Wikipedia entry for unordered generation of permutations. For the string s of length n, for any k from 0 to n! - 1 inclusive, the following modifies s to provide a unique permutation (that is, different from those generated for any other k value on that range). To generate all permutations, run it for all n! k values on the original value of s.
#include <algorithm>
void permutation(int k, string &s)
{
for(int j = 1; j < s.size(); ++j)
{
std::swap(s[k % (j + 1)], s[j]);
k = k / (j + 1);
}
}
Here swap(s, i, j) swaps position i and j of the string s.
Why dont you try std::next_permutation() or std::prev_permutation()
?
Links:
std::next_permutation()
std::prev_permutation()
A simple example:
#include<string>
#include<iostream>
#include<algorithm>
int main()
{
std::string s="123";
do
{
std::cout<<s<<std::endl;
}while(std::next_permutation(s.begin(),s.end()));
}
Output:
123
132
213
231
312
321
I'd like to second Permaquid's answer. The algorithm he cites works in a fundamentally different way from the various permutation enumeration algorithms that have been offered. It doesn't generate all of the permutations of n objects, it generates a distinct specific permutation, given an integer between 0 and n!-1. If you need only a specific permutation, it's much faster than enumerating them all and then selecting one.
Even if you do need all permutations, it provides options that a single permutation enumeration algorithm does not. I once wrote a brute-force cryptarithm cracker, that tried every possible assignment of letters to digits. For base-10 problems, it was adequate, since there are only 10! permutations to try. But for base-11 problems took a couple of minutes and base-12 problems took nearly an hour.
I replaced the permutation enumeration algorithm that I had been using with a simple i=0--to--N-1 for-loop, using the algorithm Permaquid cited. The result was only slightly slower. But then I split the integer range in quarters, and ran four for-loops simultaneously, each in a separate thread. On my quad-core processor, the resulting program ran nearly four times as fast.
Just as finding an individual permutation using the permutation enumeration algorithms is difficult, generating delineated subsets of the set of all permutations is also difficult. The algorithm that Permaquid cited makes both of these very easy
In particular, you want std::next_permutation.
void permute(string elems, int mid, int end)
{
int count = 0;
while(next_permutation(elems.begin()+mid, elems.end()))
cout << << ++count << " : " << elems << endl;
}
... or something like that...
Any algorithm for generating permutations is going to run in polynomial time, because the number of permutations for characters within an n-length string is (n!). That said, there are some pretty simple in-place algorithms for generating permutations. Check out the Johnson-Trotter algorithm.
The Knuth random shuffle algorithm is worth looking into.
// In-place shuffle of char array
void shuffle(char array[], int n)
{
for ( ; n > 1; n--)
{
// Pick a random element to move to the end
int k = rand() % n; // 0 <= k <= n-1
// Simple swap of variables
char tmp = array[k];
array[k] = array[n-1];
array[n-1] = tmp;
}
}
Any algorithm that makes use of or generates all permutations will take O(N!*N) time, O(N!) at the least to generate all permutations and O(N) to use the result, and that's really slow. Note that printing the string is also O(N) afaik.
In a second you can realistically only handle strings up to a maximum of 10 or 11 characters, no matter what method you use. Since 11!*11 = 439084800 iterations (doing this many in a second on most machines is pushing it) and 12!*12 = 5748019200 iterations. So even the fastest implementation would take about 30 to 60 seconds on 12 characters.
Factorial just grows too fast for you to hope to gain anything by writing a faster implementation, you'd at most gain one character. So I'd suggest Prasoon's recommendation. It's easy to code and it's quite fast. Though sticking with your code is completely fine as well.
I'd just recommend that you take care that you don't inadvertantly have extra characters in your string such as the null character. Since that will make your code a factor of N slower.
I've written a permutation algorithm recently. It uses a vector of type T (template) instead of a string, and it's not super-fast because it uses recursion and there's a lot of copying. But perhaps you can draw some inspiration for the code. You can find the code here.
The only way to significantly improve performance is to find a way to avoid iterating through all the permutations in the first place!
Permuting is an unavoidably slow operation (O(n!), or worse, depending on what you do with each permutation), unfortunately nothing you can do will change this fact.
Also, note that any modern compiler will flatten out your recursion when optimisations are enabled, so the (small) performance gains from hand-optimising are reduced even further.
Do you want to run through all the permutations, or count the number of permutations?
For the former, use std::next_permutation as suggested by others. Each permutation takes O(N) time (but less amortized time) and no memory except its callframe, vs O(N) time and O(N) memory for your recursive function. The whole process is O(N!) and you can't do better than this, as others said, because you can't get more than O(X) results from a program in less than O(X) time! Without a quantum computer, anyway.
For the latter, you just need to know how many unique elements are in the string.
big_int count_permutations( string s ) {
big_int divisor = 1;
sort( s.begin(), s.end() );
for ( string::iterator pen = s.begin(); pen != s.end(); ) {
size_t cnt = 0;
char value = * pen;
while ( pen != s.end() && * pen == value ) ++ cnt, ++ pen;
divisor *= big_int::factorial( cnt );
}
return big_int::factorial( s.size() ) / divisor;
}
Speed is bounded by the operation of finding duplicate elements, which for chars can be done in O(N) time with a lookup table.
I don't think this is better, but it does work and does not use recursion:
#include <iostream>
#include <stdexcept>
#include <tr1/cstdint>
::std::uint64_t fact(unsigned int v)
{
::std::uint64_t output = 1;
for (unsigned int i = 2; i <= v; ++i) {
output *= i;
}
return output;
}
void permute(const ::std::string &s)
{
using ::std::cout;
using ::std::uint64_t;
typedef ::std::string::size_type size_t;
static unsigned int max_size = 20; // 21! > 2^64
const size_t strsize = s.size();
if (strsize > max_size) {
throw ::std::overflow_error("This function can only permute strings of size 20 or less.");
} else if (strsize < 1) {
return;
} else if (strsize == 1) {
cout << "0 : " << s << '\n';
} else {
const uint64_t num_perms = fact(s.size());
// Go through each permutation one-by-one
for (uint64_t perm = 0; perm < num_perms; ++perm) {
// The indexes of the original characters in the new permutation
size_t idxs[max_size];
// The indexes of the original characters in the new permutation in
// terms of the list remaining after the first n characters are pulled
// out.
size_t residuals[max_size];
// We use div to pull our permutation number apart into a set of
// indexes. This holds what's left of the permutation number.
uint64_t permleft = perm;
// For a given permutation figure out which character from the original
// goes in each slot in the new permutation. We start assuming that
// any character could go in any slot, then narrow it down to the
// remaining characters with each step.
for (unsigned int i = strsize; i > 0; permleft /= i, --i) {
uint64_t taken_char = permleft % i;
residuals[strsize - i] = taken_char;
// Translate indexes in terms of the list of remaining characters
// into indexes in terms of the original string.
for (unsigned int o = (strsize - i); o > 0; --o) {
if (taken_char >= residuals[o - 1]) {
++taken_char;
}
}
idxs[strsize - i] = taken_char;
}
cout << perm << " : ";
for (unsigned int i = 0; i < strsize; ++i) {
cout << s[idxs[i]];
}
cout << '\n';
}
}
}
The fun thing about this is that the only state it uses from permutation to permutation is the number of the permutation, the total number of permutations, and the original string. That means it can be easily encapsulated in an iterator or something like that without having to carefully preserve the exact correct state. It can even be a random access iterator.
Of course ::std::next_permutation stores the state in the relationships between elements, but that means it can't work on unordered things, and I would really wonder what it does if you have two equal things in the sequence. You can solve that by permuting indexes of course, but that adds slightly more complication.
Mine will work with any random access iterator range provided it's short enough. And if it isn't, you'll never get through all the permutations anyway.
The basic idea of this algorithm is that every permutation of N items can be enumerated. The total number is N! or fact(N). And any given permutation can be thought of as a mapping of source indices from the original sequence into a set of destination indices in the new sequence. Once you have an enumeration of all permutations the only thing left to do is map each permutation number into an actual permutation.
The first element in the permuted list can be any of the N elements from the original list. The second element can be any of the N - 1 remaining elements, and so on. The algorithm uses the % operator to pull apart the permutation number into a set of selections of this nature. First it modulo's the permutation number by N to get a number from [0,N). It discards the remainder by dividing by N, then it modulo's it by the size of the list - 1 to get a number from [0,N-1) and so on. That is what the for (i = loop is doing.
The second step is translating each number into an index into the original list. The first number is easy because it's just a straight index. The second number is an index into a list that contains every element but the one removed at the first index, and so on. That is what the for (o = loop is doing.
residuals is a list of indices into the successively smaller lists. idxs is a list of indices into the original list. There is a one-one mapping between values in residuals and idxs. They each represent the same value in different 'coordinate spaces'.
The answer pointed to by the answer you picked has the same basic idea, but has a much more elegant way of accomplishing the mapping than my rather literal and brute force method. That way will be slightly faster than my method, but they are both about the same speed and they both have the same advantage of random access into permutation space which makes a whole number of things easier, including (as the answer you picked pointed out) parallel algorithms.
Actually you can do it using Knuth shuffling algo!
// find all the permutations of a string
// using Knuth radnom shuffling algorithm!
#include <iostream>
#include <string>
template <typename T, class Func>
void permutation(T array, std::size_t N, Func func)
{
func(array);
for (std::size_t n = N-1; n > 0; --n)
{
for (std::size_t k = 0; k <= n; ++k)
{
if (array[k] == array[n]) continue;
using std::swap;
swap(array[k], array[n]);
func(array);
}
}
}
int main()
{
while (std::cin.good())
{
std::string str;
std::cin >> str;
permutation(str, str.length(), [](std::string const &s){
std::cout << s << std::endl; });
}
}
This post: http://cplusplus.co.il/2009/11/14/enumerating-permutations/ deals with permuting just about anything, not only strings. The post itself and the comments below are pretty informative and I wouldn't want to copy&paste..
If you are interested in permutation generation I did a research paper on it a while back : http://www.oriontransfer.co.nz/research/permutation-generation
It comes complete with source code, and there are 5 or so different methods implemented.
Even I found it difficult to understand that recursive version of the first time and it took me some time to search for a berre way.Better method to find (that I can think of) is to use the algorithm proposed by Narayana Pandita. The basic idea is:
First sort the given string in no-decreasing order and then find the index of the first element from the end that is less than its next character lexicigraphically. Call this element index the 'firstIndex'.
Now find the smallest character which is greater thn the element at the 'firstIndex'. Call this element index the 'ceilIndex'.
Now swap the elements at 'firstIndex' and 'ceilIndex'.
Reverse the part of the string starting from index 'firstIndex+1' to the end of the string.
(Instead of point 4) You can also sort the part of the string from index 'firstIndex+1' to the end of the string.
Point 4 and 5 do the same thing but the time complexity in case of point 4 is O(n*n!) and that in case of point 5 is O(n^2*n!).
The above algorithm can even be applied to the case when we have duplicate characters in the string. :
The code for displaying all the permutation of a string :
#include <iostream>
using namespace std;
void swap(char *a, char *b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
int partition(char arr[], int start, int end)
{
int x = arr[end];
int i = start - 1;
for(int j = start; j <= end-1; j++)
{
if(arr[j] <= x)
{
i = i + 1;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[end]);
return i+1;
}
void quickSort(char arr[], int start, int end)
{
if(start<end)
{
int q = partition(arr, start, end);
quickSort(arr, start, q-1);
quickSort(arr, q+1, end);
}
}
int findCeilIndex(char *str, int firstIndex, int n)
{
int ceilIndex;
ceilIndex = firstIndex+1;
for (int i = ceilIndex+1; i < n; i++)
{
if(str[i] >= str[firstIndex] && str[i] <= str[ceilIndex])
ceilIndex = i;
}
return ceilIndex;
}
void reverse(char *str, int start, int end)
{
while(start<=end)
{
char tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
}
void permutate(char *str, int n)
{
quickSort(str, 0, n-1);
cout << str << endl;
bool done = false;
while(!done)
{
int firstIndex;
for(firstIndex = n-2; firstIndex >=0; firstIndex--)
{
if(str[firstIndex] < str[firstIndex+1])
break;
}
if(firstIndex<0)
done = true;
if(!done)
{
int ceilIndex;
ceilIndex = findCeilIndex(str, firstIndex, n);
swap(&str[firstIndex], &str[ceilIndex]);
reverse(str, firstIndex+1, n-1);
cout << str << endl;
}
}
}
int main()
{
char str[] = "mmd";
permutate(str, 3);
return 0;
}
Here's one I just rustled up!!
void permute(const char* str, int level=0, bool print=true) {
if (print) std::cout << str << std::endl;
char temp[30];
for (int i = level; i<strlen(str); i++) {
strcpy(temp, str);
temp[level] = str[i];
temp[i] = str[level];
permute(temp, level+1, level!=i);
}
}
int main() {
permute("1234");
return 0;
}
This is not the best logic, but then, i am a beginner. I'll be quite happy and obliged if anyone gives me suggestions on this code
#include<iostream.h>
#include<conio.h>
#include<string.h>
int c=1,j=1;
int fact(int p,int l)
{
int f=1;
for(j=1;j<=l;j++)
{
f=f*j;
if(f==p)
return 1;
}
return 0;
}
void rev(char *a,int q)
{
int l=strlen(a);
int m=l-q;
char t;
for(int x=m,y=0;x<q/2+m;x++,y++)
{
t=a[x];
a[x]=a[l-y-1];
a[l-y-1]=t;
}
c++;
cout<<a<<" ";
}
int perm(char *a,int f,int cd)
{
if(c!=f)
{
int l=strlen(a);
rev(a,2);
cd++;
if(c==f)return 0;
if(cd*2==6)
{
for(int i=1;i<=c;i++)
{
if(fact(c/i,l)==1)
{
rev(a,j+1);
rev(a,2);
break;
}
}
cd=1;
}
rev(a,3);
perm(a,f,cd);
}
return 0;
}
void main()
{
clrscr();
char *a;
cout<<"\n\tEnter a Word";
cin>>a;
int f=1;
for(int o=1;o<=strlen(a);o++)
f=f*o;
perm(a,f,0);
getch();
}
**// Prints all permutation of a string**
#include<bits/stdc++.h>
using namespace std;
void printPermutations(string input, string output){
if(input.length() == 0){
cout<<output <<endl;
return;
}
for(int i=0; i<=output.length(); i++){
printPermutations(input.substr(1), output.substr(0,i) + input[0] + output.substr(i));
}
}
int main(){
string s = "ABC";
printPermutations(s, "");
return 0;
}
Here yet another recursive function for string permutations:
void permute(string prefix, string suffix, vector<string> &res) {
if (suffix.size() < 1) {
res.push_back(prefix);
return;
}
for (size_t i = 0; i < suffix.size(); i++) {
permute(prefix + suffix[i], suffix.substr(0,i) + suffix.substr(i + 1), res);
}
}
int main(){
string str = "123";
vector<string> res;
permute("", str, res);
}
The function collects all permutations in vector res.
The idea can be generalized for different type of containers using templates and iterators:
template <typename Cont1_t, typename Cont2_t>
void permute(typename Cont1_t prefix,
typename Cont1_t::iterator beg, typename Cont1_t::iterator end,
Cont2_t &result)
{
if (beg == end) {
result.insert(result.end(), prefix);
return;
}
for (auto it = beg; it != end; ++it) {
prefix.insert(prefix.end(), *it);
Cont1_t tmp;
for (auto i = beg; i != end; ++i)
if (i != it)
tmp.insert(tmp.end(), *i);
permute(prefix, tmp.begin(), tmp.end(), result);
prefix.erase(std::prev(prefix.end()));
}
}
int main()
{
string str = "123";
vector<string> rStr;
permute<string, vector<string>>("", str.begin(), str.end(), rStr);
vector<int>vint = { 1,2,3 };
vector<vector<int>> rInt;
permute<vector<int>, vector<vector<int>>>({}, vint.begin(), vint.end(), rInt);
list<long> ll = { 1,2,3 };
vector<list<long>> vlist;
permute<list<long>, vector<list<long>>>({}, ll.begin(), ll.end(), vlist);
}
This may be an interesting programming exercise, but in production code you should use a non recusrive version of permutation , like next_permutation.
//***************anagrams**************//
//************************************** this code works only when there are no
repeatations in the original string*************//
#include<iostream>
using namespace std;
int counter=0;
void print(char empty[],int size)
{
for(int i=0;i<size;i++)
{
cout<<empty[i];
}
cout<<endl;
}
void makecombination(char original[],char empty[],char comb[],int k,int& nc,int size)
{
nc=0;
int flag=0;
for(int i=0;i<size;i++)
{
flag=0; // {
for(int j=0;j<k;j++)
{
if(empty[j]==original[i]) // remove this code fragment
{ // to print permutations with repeatation
flag=1;
break;
}
}
if(flag==0) // }
{
comb[nc++]=original[i];
}
}
//cout<<"checks ";
// print(comb,nc);
}
void recurse(char original[],char empty[],int k,int size)
{
char *comb=new char[size];
int nc;
if(k==size)
{
counter++;
print(empty,size);
//cout<<counter<<endl;
}
else
{
makecombination(original,empty,comb,k,nc,size);
k=k+1;
for(int i=0;i<nc;i++)
{
empty[k-1]=comb[i];
cout<<"k = "<<k<<" nc = "<<nc<<" empty[k-1] = "<<empty[k-1]<<endl;//checks the value of k , nc, empty[k-1] for proper understanding
recurse(original,empty,k,size);
}
}
}
int main()
{
const int size=3;
int k=0;
char original[]="ABC";
char empty[size];
for(int f=0;f<size;f++)
empty[f]='*';
recurse(original,empty,k,size);
cout<<endl<<counter<<endl;
return 0;
}