Related
I am using this program to check a number if prime or not.
Use algorithm - Sieve :
#include<bits/stdc++.h>
//#define _max 2000000001
#define _max 20000001
using namespace std;
bool sieve[_max];
void init()
{
memset(sieve,true,sizeof(sieve));
sieve[0]=sieve[1]=false;
for(int i=2;i<_max;i+=2)
{
sieve[i]=false;
}
}
void go_sieve(int n)
{
n++;
for(int i=3;i<n;i+=2)
{
if(sieve[i]==false)
continue;
for(int j=2*i;j<n;j+=i)
sieve[j]=false;
}
}
void print(int n)
{
n++;
printf("-------------\n");
for(int i=0;i<n;i++)
{
if(sieve[i])
cout << i << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
go_sieve(x);
//print(x);
if(sieve[x])
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Now it works upto 2e7 and pretty smoothly, but I want to check upto 2e9, if I change my _max to 2000000001 it gives me segmentation error and exits with an error code.
How can I resolve this problem ?
I have tried a new approach with set :
#include<bits/stdc++.h>
//#define _max 200001
//#define _max 20000001
#define _max 2000000001
using namespace std;
set<int>prime;
set<int>nprime;
void init()
{
prime.insert(2);
}
void go_sieve()
{
for(int i=3;i<_max;i+=2)
{
if(prime.find(i)==prime.end() && nprime.find(i)==nprime.end())
{
prime.insert(i);
//cout << i << endl;
for(int j=2*i;j<_max;j+=i)
nprime.insert(j);
}
if(nprime.find(i)!=nprime.end())
nprime.erase(nprime.find(i));
}
}
void print()
{
set<int> ::iterator itt;
printf("-------------\n");
for(itt=prime.begin();itt!=prime.end();itt++)
{
cout << *itt << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
go_sieve();
//print();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(prime.find(x)!=prime.end())
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Target is to execute it within 512MB~1GB memory.
If you want to enumerate large ranges of prime numbers, you should use a segmented Sieve of Eratosthenes; it will be faster (due to caching effects) and use less memory.
If you only want to determine if one number is prime, or a few numbers, sieving is a horrible way to do it. Sieving should only be used when you are interested in an entire range of numbers. For n up to a billion, trial division is simple and probably fast enough. For larger numbers, a Miller-Rabin test or Baillie-Wagstaff test is probably better.
I can't reproduce this on my system. My guess is that this has to do with a system dependant limitation.
You declare sieve as a global array (static storage duration) and it's huge (i.e. 2000000001 * sizeof(bool) - could be 2-8G depending on sizeof bool). Maybe your system can't handle that.
Instead of a global array, try using dynamic allocation:
// bool sieve[_max]; comment out this
bool* sieve = NULL;
...
...
int main()
{
sieve = (bool*)malloc(_max * sizeof *sieve);
if (sieve == NULL)
{
// out of memory
exit(1);
}
...
That said:
Your code is C++ but your style is more C like.
In C++ you would probably use a std::vector instead. That would make everything much easier.
BTW: Also avoid globals. Instead define the vector (or dynamic array) in main and pass it by-reference to the functions.
You probably hit some memory limit on your system which causes the segmentation fault.
However, you don't need such a big array. Using Sieve of Eratosthenes, you need to calculate numbers up to x. Instead of an array you can use std::vector and increase its size as you calculate more numbers. This should allow you to calculate some numbers, but with large numbers you will hit the memory limit again.
You could also use some algorithm which requires you to store fewer numbers. To determine whether x is prime, you only need to compare against prime numbers that are smaller than the square root of x. You don't have to store numbers that are not primes. With x = 1e10, you would only need to store 5e8 numbers.
Here is some example with vector (probably not optimal):
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
std::vector<int> primes = {2};
void calculate(int x) {
const int largest_prime = primes.back();
if (largest_prime >= x) {
// Already calculated
return;
}
for (size_t i = largest_prime + 1; i <= x; i++) {
bool not_prime = false;
for (size_t j = 0; j < primes.size(); j++) {
if (i % primes[j] == 0) {
not_prime = true;
break;
}
}
if (!not_prime) {
primes.push_back(i);
}
}
}
bool check(int x) {
calculate(x);
return std::find(primes.begin(), primes.end(), x) != primes.end();
}
int main() {
std::cout << check(15) << std::endl;
std::cout << check(256699) << std::endl;
}
TL;DR: My code is "fast" in Java but slow as hell in C++. Why?
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int read(string data, int depth, int pos, vector<long>& wantedList) {
// 91 = [
if (data.at(pos) == 91) {
pos++;
// Get first part
pos = read(data, depth + 1, pos, wantedList);
// Get second part
pos = read(data, depth + 1, pos, wantedList);
} else {
// Get the weight
long weight = 0;
while (data.length() > pos && isdigit(data.at(pos))) {
weight = 10 * weight + data.at(pos++) - 48;
}
weight *= 2 << depth;
wantedList.push_back(weight);
}
return ++pos;
}
int doStuff(string data) {
typedef map<long, int> Map;
vector<long> wantedList;
Map map;
read(data, 0, 0, wantedList);
for (long i : wantedList) {
if (map.find(i) != map.end()) {
map[i] = map[i] + 1;
} else {
map[i] = 1;
}
}
vector<int> list;
for (Map::iterator it = map.begin(); it != map.end(); ++it) {
list.push_back(it->second);
}
sort(list.begin(), list.begin() + list.size());
cout << wantedList.size() - list.back() << "\n";
return 0;
}
int main() {
string data;
int i;
cin >> i;
for (int j = 0; j < i ; ++j) {
cin >> data;
doStuff(data);
}
return 0;
}
I have just tried my first C++ project, and it's re-written code from Java.
The original task was to calculate how many numbers that needed to be changed in order to "balance" the input, given that each level above something weighs double the lower
eg [1,2] would need 1 change (either 1->2 or 2->1 in order to be equal on both sides and [8,[4,2]] would need 1 change (2->4) in order for the "lower level" to become 8 and therefore be of equal weight on the higher level. The problem can be found here for those who are interested:
Problem link
And for those who wonder, this is a school assignment regarding algorithms, but I'm not asking for help with that, since I have already completed it in Java. The problem is that my algorithm seem to be pretty shit when it comes to C++.
In Java I get times around 0.6 seconds, and in C++, the "same" code gives >2 seconds (time limit exceeded).
Anyone care to give me a pointer as to why this is? I was under the impression that C++ is supposedly faster than Java when it comes to these type of problems.
One of possible reasons is copying.
Whenever you pass something by value in C++ a copy is created. For tings like double, int or a pointer, that's not a problem.
But for objects like std::string copying may be expensive. Since you don't modify data it makes sense to pass it by const reference:
int read(const string &data, int depth, int pos, vector<long>& wantedList)
I've stumbled upon this problem: I can't seem to select the item at the index' position in a normal std::set. Is this a bug in STD?
Below a simple example:
#include <iostream>
#include <set>
int main()
{
std::set<int> my_set;
my_set.insert(0x4A);
my_set.insert(0x4F);
my_set.insert(0x4B);
my_set.insert(0x45);
for (std::set<int>::iterator it=my_set.begin(); it!=my_set.end(); ++it)
std::cout << ' ' << char(*it); // ups the ordering
//int x = my_set[0]; // this causes a crash!
}
Anything I can do to fix the issue?
It doesn't cause a crash, it just doesn't compile. set doesn't have access by index.
You can get the nth element like this:
std::set<int>::iterator it = my_set.begin();
std::advance(it, n);
int x = *it;
Assuming my_set.size() > n, of course. You should be aware that this operation takes time approximately proportional to n. In C++11 there's a nicer way of writing it:
int x = *std::next(my_set.begin(), n);
Again, you have to know that n is in bounds first.
Try this you will be able to use set in another way namely ordered_set
This is very much used in CP
Hope this is diff from all and will help you/someone!
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>
Now you can use
order_of_key (k) : Number of items strictly smaller than k .
find_by_order(k) : K-th element in a set (counting from zero). //This is what you need
[https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/][1]
A usual implementation of std::set is to use binary search trees, notably self-balancing binary search trees such as red-black trees
They don't give you constant time access to the n-th element. However, you seems to want the first. So try in C++11:
auto it = my_set.begin();
int first=0;
if (it != my_set.end()) first = *it;
There is no way you can access it in constant time.
But you can reach to any element in O(n) time.
E.g.
std::set<int>::iterator it;
it=my_set.begin();
advance(it,n);
cout<<*it;
I don't think std::set has any methods of doing this in better than O(n) time, but I recently made this data structure using a set and a Binary Index Tree that can do most things the std::set can do, but it can also get the index of an element in O(log n) time, as well as the element at a specific index in O((log n) * (log n)) time:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <math.h>
#include <vector>
#include <queue>
#include <bitset>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef long long ll;
typedef pair<ll, ll> pll;
#define max(n, m) ((n>m)?n:m)
#define min(n, m) ((n<m)?n:m)
#define f first
#define s second
struct ss
{
// binary index tree (to mark elements)
int bit[1000010]; // set this number to the max you will use
// set (to store the numbers in order)
set<int> nums;
// the maximum element in the set (NOTE: this data structure works with marking in the BIT array, but you can make this better by using an unordered set to store all values that could appear inside of the set, but this will increase runtime by a high constant factor)
int mx;
// constructor
ss(int maxEl)
{
mx = maxEl + 5;
}
int sum(int arr[], int idx)
{
int ans = 0;
idx ++;
if(idx > mx + 5) return -1;
while(idx > 0)
{
ans += arr[idx];
idx -= idx & (-idx);
}
return ans;
}
void update(int arr[], int idx, int val, int size)
{
idx ++;
while(idx <= size)
{
arr[idx] += val;
idx += idx & (-idx);
}
}
int bs(int l, int r, int idx)
{
int mid = (l + r) / 2;
if(l == r) return mid + 1;
if(l == r - 1)
{
if(sum(bit, r) == idx) return r + 1;
return r;
}
if(sum(bit, mid) <= idx) return bs(mid, r, idx);
return bs(l, mid - 1, idx);
}
// regular set functions
set<int>::iterator find(int num) { return nums.find(num); }
set<int>::iterator lower_bound(int num) { return nums.lower_bound(num); }
set<int>::iterator upper_bound(int num) { return nums.upper_bound(num); }
int size() { return (int)nums.size(); }
set<int>::iterator begin() { return nums.begin(); }
set<int>::iterator end() { return nums.end(); }
bool empty() { return nums.empty(); }
// slightly modified insert and erase functions to also mark stuff in BIT (still O(log n) though)
void insert(int num)
{
if(nums.find(num) == nums.end())
update(bit, num, 1, mx); // marks the element in the BIT if it doesn't already exist
nums.insert(num);
}
void erase(int num)
{
if(nums.find(num) != nums.end())
update(bit, num, -1, mx); // unmarks the element in the BIT if it exists in the set
nums.erase(num);
}
// gets index (0-indexed) of a specific element in O(log n), returns -1 if element not in set
int idx(int num)
{
if(nums.find(num) == nums.end())
return -1;
return sum(bit, num - 1);
}
// gets the iterator of the element at a specific index (0-indexed) in O((log n) * (log n)), returns end of set if idx is invalid
set<int>::iterator at(int idx)
{
if(idx < 0 || idx >= nums.size())
return nums.end();
return nums.find(bs(0, mx, idx));
}
};
int main()
{
ss test = ss(1000);
test.insert(1);
test.insert(3);
test.insert(5);
test.insert(1);
test.insert(9);
test.insert(1000);
cout << *test.at(1) << "\n";
test.erase(3);
cout << *test.at(1) << "\n";
cout << test.idx(1) << "\n";
cout << *test.at(-1) << "\n";
}
This set does have some flaws since it marks elements in the Binary Indexed Tree, so the elements cannot be negative or really big without some extra modifications, but it can still be helpful in some cases. Also, using an std::map or some other type of map could make the set work with negative numbers, big numbers, as well as other data types, but this would increase the runtime by a factor of O(log n) and I think you would have to know all the elements that could appear in the set beforehand so that you can store them in the correct order inside of the map.
EDIT: I just realized there is already a policy-based data structure called ordered-set that has the same functions as a set but can do the two operations (get element at index and get index of element) in O(log n). Read more here: https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/. This might not work in all compilers though
This is not a bug in the STD. There is no random access in a std::set. If you need random access by index, you can use std::vector
Sometimes there's a good reason for needing a set you can index into. I had to implement this functionality recently to support a legacy API which has functions to return the number of items, and the item at an index, so that the caller can enumerate the items.
My way of solving the problem is to use std::vector, and use std::equal_range to find and insert or delete items in the set. For example, inserting a new item into the set looks like this:
std:vector<std::string> my_set;
...
std::string new_item("test");
auto range = std::equal_range(my_set.begin(),my_set.end(),new_item);
if (range.first == range.second)
my_set.insert(range.first,new_item);
Deleting is very similar: use equal_range to find the item, and if range.first is not equal to range.second, delete that range.
i believe the most optimal way, especially if this indexing happens in a loop, is to convert to a vector.
auto my_vect = std::vector(my_set.begin(), my_set.end()); // O[n]
int output = my_vect[n]; // O[1]
std::set<int> my_set;
my_set.insert(0x4A);
my_set.insert(0x4F);
my_set.insert(0x4B);
my_set.insert(0x45);
int arr[my_set.size()];
set<int>::iterator it = my_set.begin();
for (int i = 0; i < my_set.size(); i++) {
arr[i] = *it;
it++;
}
cout << arr[0];
Edit: Edited code. You can't access set using index but the above method would provide an "index" i if you want to copy the elements from set into an array, provided you have created an array of sufficient size before hand.
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;
}
I've written a loop in C++ to give me 6 random numbers and store them in an array.
What I would like to do is to sum the elements of the array until I get a value larger than a number, "x", but I would like to do this without necessarily adding all the elements. The objective is to find the first elements which sum to the value of x.
For example, array is [1,2,3,4,5,6], and x = 6, so what I would be looking for are the elements [1,2,3].
I've looked at the standard library and have tried using the sum function from "valarray" but this just gives the sum of all the elements. Any ideas on how to code this successfully would be greatly appreciated.
Write a functor that does the addition.
#include <algorithm>
struct SumToo
{
SumToo(int val):m_val(val),m_sum(0) {}
int m_val;
int m_sum;
bool operator()(int next)
{
m_sum += next;
return m_sum >= m_val;
}
};
int main()
{
int data[] = {1,2,3,4,5,6};
int* find = std::find_if(data,data+6,SumToo(6));
}
I'm assuming you just want the first X elements in the array, up until their sum meets or exceeds a threshold (the question was a little vague there).
If so, I don't know how to do that without your own loop:
int sum = 0;
int i = 0;
for( ; i < len; ++i ) {
sum += array[i];
if( sum >= 6 ) {
break;
}
}
Now "i" contains the index at which the sum met or exceeded your threshold.
Avoid the answers that suggest using find_if with a stateful predicate. Stateful predicates are dangerous as the STL algorithms assume it is safe to copy predicates. In this case, if copies are made of the predicate then each will have a different 'running total' and will not necessarily act on all values, or in the correct order.
Especially avoid the solution that implements its predicate's operator() member as a const member function but labels its members as mutable as this is fooling you into thinking it is not a stateful predicate, which is bad.
I'd suggest using either one of the answers that simply loops to find the answer, or the answer that uses an accumulator, as that is the most correct way to do it (even if the code looks a little unwieldy.
Note that the warnings may well not apply to C arrays and find_if; I just don't want you to learn that stateful predicates are the right way to solve your problem since you may end up using that incorrect solution in a situation where it is dangerous in future.
Reference: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices, Item 87
Here's a slightly more generic version:
#include <iostream>
#include <algorithm>
// return an iterator _Last such that sum
// of all elements in the range [_First, _Last)
// satisfies the predicate Func
template<class InIt,
class Ty,
class Fn> inline
InIt accumulate_if(InIt First, InIt Last, Ty Val, Fn Func)
{
for (; Func(Val) && First != Last; ++First)
Val = Val + *First;
return (First);
}
int main() {
int num[] = {1, 2, 3, 4, 5, 6};
int *last = accumulate_if(num, num + sizeof num / sizeof num[ 0 ],
0, std::bind2nd(std::less<int>(), 6));
std::copy(num, last, std::ostream_iterator<int>(std::cout, "\n"));
return 0;
}
Substract the numbers from x one by one, until you reach 0 or lower.
No additions, as you wished :)
Here's hoping this works:
/* Returns an index i, given array valarray[0,1..n] and number x where i is an index to valarry such that sum over j of valarray[j] for j = 0 to i > x */
int getFirstSum(int *valarray, int n, int x)
{
int i = 0;
int sum = x;
while(sum > x && i < n)
{
i++;
sum -= valarray[i];
}
return i;
}
would be something like:
struct StopAtValue{
StopAtValue(int sum) : m_sum(sum), m_accumulated(0){}
bool operator()(int val){
m_accumulated += val;
return m_accumulated >= sum;
}
int m_sum;
int m_accumulated;
}
int* pos = std::find_if(&array[0], &array[n], StopAtValue(6));
Well, i would use a vector
T addUntil(T array[],size_t len,T thres){
vector<T> vec = vector_from_array(array,len)
T sum;
for (size_t i=0;i< vec.size(),sum<thresh;i++){
sum+= vec[i];
}
return sum;
}
T would need operator+ and operator< to be defined.
You could use std::find_if() along with a functor that maintains a running total, and only returtn true from the functor when you have found the element that puts you at or over the top.
For example:
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
using namespace std;
// functor returns true when the running total >= findVal
struct running_total : public unary_function<int, bool>
{
running_total(int findVal) : findVal_(findVal), runningTtl_(0) {};
bool operator()(int rhs) const
{
runningTtl_ += rhs;
if( runningTtl_ >= findVal_ )
return true;
else
return false;
}
private:
mutable int runningTtl_;
const int findVal_;
};
int main()
{
int nums[] = {1, 2, 3, 4, 5, 6};
size_t count = sizeof(nums)/sizeof(nums[0]);
const int scanTtl = 6; // running total to scan to
int * pos = find_if(&nums[0], &nums[0]+count, running_total(scanTtl));
cout << "Elements Totaling " << scanTtl << " : ";
copy(&nums[0], pos+1, ostream_iterator<int>(cout, ", "));
return 0;
}