I am trying to implement Heap's algorithm in C++.
However, the algorithm starts to repeat if the string it's permuting gets to a length of 4. Here's the code:
void permute(int n, string str, int *total,string array[]){
if (n==0){
array[*total] = str;
*total += 1;
}
else{
for(int c=0; c<=n;c++){
permute(n-1,str,total, array);
if (n % 2 == 0){
char tmpstr=str[c];
str[c]=str[n];
str[n]=tmpstr;
}
else{
char tmpstr=str[0];
str[0]=str[n];
str[n]=tmpstr;
}
}
}
}
int main() {
int total = 0;
string array[24];
permute(3,"abcd",&total, array);
cout << total << endl;
return 0;
}
And here is the output. It repeats at the 13th line
24
abcd
bacd
cbad
bcad
cabd
acbd
dbca
bdca
cbda
bcda
cdba
dcba
abcd <-- right here
bacd
cbad
bcad
cabd
acbd
dbca
bdca
cbda
bcda
cdba
dcba
Thank you guys and any help is welcome!
While it is always an excellent idea to use the standard function recommended by PaulMcKenzie, you have posted a code with a question about why it doesn't work.
In your for loop, get rid of the line if (n%2 ==0) and its else part:
for(int c=0; c<=n;c++){
permute(n-1,str,total, array);
char tmpstr=str[c];
str[c]=str[n];
str[n]=tmpstr;
}
It should then work.
It looks like you are trying to implement the recursive version of the Heap's algorithm for permutation generation stated in wikipedia and originally given in here. If you want to stay close to it (for example, to have the same order when generating the permutations), all you have to do is pass the str parameter as a reference (you'll have to change the line calling the permute() function to pass a mutable string instead a string constant, tough) and keep the if-then-else clause originally in your program.
Nevertheless, it is interesting the version given by #Christophe. I've tried it with up to n=6 (permutations of 7 elements), and still give all permutations. It'd be interesting to know if this can be proved to hold for any natural number. This point may be moot, however, since the recursive version given in the two references I cited does not implement the original version given by Heap, either, and, as far as I know, hasn't been proved to give all permutations either. The original version given by Heap, written in 1963, did not even use structured programming. It was given as a flowgraph to be implemented with goto's.
Here, have my implementations of recursive and iterative versions:
//recursive
int perm_num = 0;
void heappermute(int v[], int n) {
int i;
if (n == 1) {
//print(v);
++perm_num;
}
else {
for (i = 0; i < n; i++) {
heappermute(v, n - 1);
if (n % 2 == 1) {
swap(&v[0], &v[n - 1]);
}
else {
swap(&v[i], &v[n - 1]);
}
}
}
}
int perm_num_iter = 0;
void heappermuteiterative(int v[], int n) {
int c[30];
for (int i = 0; i <= n; ++i) {
c[i] = 0;
}
++perm_num_iter;
//print(v);
int i = 1;
while (i < n) {
if (c[i] < i) {
if (i % 2 == 0) {
swap(&v[0], &v[i]); // or i-1
}
else {
swap(&v[c[i]], &v[i]); // or i-1
}
++perm_num_iter;
//print(v);
++c[i];
i = 1;
}
else {
c[i] = 0;
++i;
}
}
}
I copied the recursive one from somewhere on the net, and the iterative one is the Wikipedia's one written in C.
Related
How to count comparisons in selectionsort?
terms:
when the statements you perform to find the maximum value is 'true'
then count comparison.
The value to get the maximum value is held at the first element in the array, not at random.
I try with C
variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
#include <stdio.h>
int main() {
int sort[10000], i, n, MAX, temp, count;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &sort[i]);
}
for (MAX = 0; MAX < n; MAX++)
for (i = MAX + 1; i < n; i++) {
if (sort[MAX] > sort[i]) {
count++;
temp = sort[MAX];
sort[MAX] = sort[i];
sort[i] = temp;
}
}
printf("%d ", count);
return 0;
}
Sample Input
10
0 7 1 6 7 7 6 6 5 4
Sample Output
17
EDIT: new code:
#include <stdio.h>
#define SWAP(x, y, temp) ( (temp)=(x), (x)=(y), (y)=(temp) )
int count = 0;
void selection_sort(int list[], int n) {
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
if (list[j] < list[least]) {
least = j;
count++;
}
}
SWAP(list[i], list[least], temp);
}
}
int main() {
int list[10000], i, n;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &list[i]);
};
selection_sort(list, n);
printf("%d", count);
}
how about this? why this code didn't move too?
You aren't counting the right thing, this code
if(sort[MAX]>sort[i])
{
count++;
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
counts the times that two numbers are swapped. But you want to count comparisons so it should be this
count++;
if(sort[MAX]>sort[i]) // this is what we are counting
{
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
Another problem is that you don't give count an initial value of zero
int sort[10000],i,n,MAX,temp,count;
should be
int sort[10000],i,n,MAX,temp,count = 0;
how to count comparison selectionsort?
Your definition of the term is oddly worded, but it seems to be intended to focus on the essential comparisons of the algorithm, as opposed to comparisons performed incidentally for other purposes, or inside library functions. That is, in the implementation you present (whose correctness I do not evaluate), you're to count each evaluation of sort[MAX]>first, but not MAX<n or i<n.
You appear to be using variable count for that purpose, but you are counting only comparisons that evaluate to true. My interpretation of the problem, based both on the wording presented and on my general expectations for such a problem, is that every evaluation of sort[MAX]>first should be counted, regardless of the result. That would be achieved by lifting the expression count++ out of the if block, but leaving it inside the inner enclosing for loop.
Of course, as #john observes, you do need to initialize count to 0 before beginning to sort. You might luck into getting that by accident, but the initial value of a local variables without an initializer is indeterminate (at least) until a value is assigned.
i try with c variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
Even with the misplacement of your increment to count, if your sort were in fact working then you would expect to see some counts for most inputs. That you don't is a good sign that your sort in fact does not work correctly. I would suggest outputting also the the sorted results so that you can debug the details of the sort algorithm.
You could abstract out the comparison into a function or macro that also increments a counter. The macro approach could be
#define GT(x,y,counter) (counter++, (x) > (y) ? 1 : 0)
...
if ( GT( sort[MAX], sort[i], count ) == 1 )
{
// perform swap
}
whereas the function approach would be
int gt( int x, int y, int *counter )
{
(*counter)++;
if ( x > y )
return 1;
return 0;
}
...
if ( gt( sort[MAX], sort[i], &count ) == 1 )
{
// perform swap
}
You are counting the number of swaps, not the number of comparisons.
Here is a corrected without a global variable and a few extra checks:
#include <stdio.h>
#define SWAP(x, y, temp) ((temp) = (x), (x) = (y), (y) = (temp))
int selection_sort(int list[], int n) {
int count = 0;
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
count++;
if (list[j] < list[least]) {
least = j;
}
}
SWAP(list[i], list[least], temp);
}
return count;
}
int main() {
int list[10000], i, n, count;
if (scanf("%d", &n) != 1 || n > 10000)
return 1;
for (i = 0; i < n; i++) {
if (scanf("%d", &list[i]) != 1)
return 1;
}
count = selection_sort(list, n);
printf("%d\n", count);
return 0;
}
Not however that your algorithm will always perform the same number of comparisons for any set of n values: n * (n - 1) / 2 comparisons, and since you do not test of i != least, it will perform n - 1 swaps.
Basically i want to write a function that takes values from 0 to 6 and gives back a random assortment such as 2,3,4,5,0,1,6. Here is the code that i came up with. However the problem is that the integer prev (meaning previous) does not store all the old values of r (random number) and thus some values end up being repeated. How might i fix this?
int s(int b)
{
// b is 7
int h = b-1;
int prev = -1;// to store the previous r value
srand(time(0));
for (int i = 0; i < b; i++)
{
int r = rand()%(h - 0 + 1) + 0;
if (r != prev)
{
cout << r << endl;
prev = r;
}
else if (r == prev)
{
s(b);
}
}
return 0;
}
From the comments, this sounds more like a homework problem than a practical problem because you said "No arrays allowed". But I suppose it is an interesting problem.
Here's some code, in Java with only loops, if statements, and with no arrays, as required.
It outputs a random permutation of the set 0, 1, ..., N, shuffled with the Fisher-Yates algorithm.
void printRandom(int N) {
long used = 0;
for (int i = 0; i < N; i++) {
int randomIndex = ThreadLocalRandom.current().nextInt(N - Long.bitCount(used));
for (int j = 0; j < N; j++) {
if ((used & (1L << j)) == 0) {
if (randomIndex-- == 0) {
System.out.print(j + " ");
used = used | (1L << j);
break;
}
}
}
}
}
It is unfortunately limited to the size of a long on your system :)
I think the best way to solve this problem is by using an aux funtion that stores in a variable all the numbers printed until the moment, check if the new number is in the used numbers variable, if not add it to the variable (you can use strings? I know that they are arrays of char's but maybe you can)
Something like this:
function aux(int b, char *variables_printed, int iterations_left)
if (b = 0) then print variables_printed
else
int n = generate_random_number() %b
while (n in variables_printed)
n= (n+random_number) % b
variables_printed += n
aux(b, variables_printed, iterations_left-1)
And your other function:
function s(b)
if b < 0 return 0
else
char *variables_to_print
aux(b, variables_to_print, b)
If you can not use strings, you can do it with long as konsolas said.
I'm trying to solve a problem from Codeforces (http://codeforces.com/problemset/problem/189/A)
Here's the problem statement:
Polycarpus has a ribbon, its length is n. He wants to cut the ribbon in a way that fulfils the following two conditions:
After the cutting each ribbon piece should have length a, b or c.
After the cutting the number of ribbon pieces should be maximum.
Help Polycarpus and find the number of ribbon pieces after the required
cutting.
Input
The first line contains four space-separated integers n, a, b and c (1 ≤ n, a, b, c ≤ 4000) — the length of the original ribbon and the acceptable lengths of the ribbon pieces after the cutting, correspondingly. The numbers a, b and c can coincide.
Output
Print a single number — the maximum possible number of ribbon pieces. It is guaranteed that at least one correct ribbon cutting exists.
Sample Input
5 5 3 2
Sample Output
2
I tried to solve this problem using Dynamic Programming (Topdown approach). But I'm not able to get the correct answer. There might be something wrong with the recursive function. Here's my code:
#include<bits/stdc++.h>
using namespace std;
int n,s;
int a[3];
int val,m=-1;
int dp(int n)
{
if(n==0)
return 0;
for(int i=0;i<3;i++)
{
if(n>=a[i])
{
val=1+dp(n-a[i]);
}
}
if(val>m)
m=val;
return m;
}
int main()
{
scanf("%d %d %d %d",&n,&a[0],&a[1],&a[2]);
cout<<dp(n)<<endl;
return 0;
}
What is the problem in the above approach?
There are several problems:
Wrong Search
In your lines
for(int i=0;i<3;i++)
{
if(n>=a[i])
{
val=1+dp(n-a[i]);
}
}
if(val>m)
m=val;
You should be checking for the maximum of the different vals obtained for the different choices of i.
Wrong Termination
If the length is not 0 and no ribbon can be cut, you should return something like minus infinity. You currently return m which is initially -1 (more on this later). This is wrong, and for long ribbons will essentially ensure that you just choose the minimum of a, b, and c.
Use of Globals
Some globals, e.g., m are initialized once but are modified by the recursion. It's not "just" bad programming habits - it's not doing what you want.
No Reuse
By calling the recursion unconditionally, and not reusing previous calls, your running time is needlessly high.
int main() {
int n, a, b, c;
scanf("%d %d %d %d", &n, &cuts[0], &cuts[1], &cuts[2]);
sort(cuts, cuts + 3);
for (int i = 0; i <= n; i++) {
max_cuts[i] = INT_MIN;
}
max_cuts[0] = 0;
max_cuts[cuts[0]] = 1;
max_cuts[cuts[1]] = 1;
max_cuts[cuts[2]] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 3; j++) {
if (cuts[j] > i) break;
max_cuts[i] = max(max_cuts[i - cuts[j]] + 1, max_cuts[i]);
}
}
printf("%d\n", max_cuts[n]);
return 0;
}
#Ami Tavory correctly suggested the problems with your recursive approach. May be my solution below can help you understand better how to form states and check bounds:
int main()
{
int n, a, b, c;
cin >> n >> a >> b >> c;
const int l = n + 1;
int sum[l];
fill(sum, sum+l, INT_MIN);
sum[0] = 0;
for(int i=1; i<=n; i++)
{
if(i - a >= 0)
{
sum[i] = sum[i-a] + 1;
}
if(i - b >= 0 && sum[i-b] + 1 > sum[i])
{
sum[i] = sum[i-b] + 1;
}
if(i - c >= 0 && sum[i-c] + 1 > sum[i])
{
sum[i] = sum[i-c] + 1;
}
}
cout << sum[n] << endl;
return 0;
}
Simply at each sum[i], we are maximizing the number of cuts. So, at sum[i], we are storing the max(sum[i-a]+1, sum[i-b]+1, sum[i-c]+1).
Other than this, there are just bound checks.
you can solve this problem through top down approach.A dp problem always check all the possible cases then gives us the optimal solution.so here is the code
#include<bits/stdc++.h>
using namespace std;
int a,b,c;
int DP[4001];
int solve(int n){
if(n == 0)return 0;
if(n<0) return INT_MIN;
if(DP[n] != -1)return DP[n];
else{
DP[n] = max(1+solve(n-a),max(1+solve(n-b),1+solve(n-c)));
return DP[n];
}
}
int main(){
int n,x;
cin>>n>>a>>b>>c;
for(int i = 0;i<4001;++i){
DP[i] = -1;
}
x = solve(n);
cout<<x;
}
I need to find the Lexicographically largest string out of the given input string.
So if the input is
enjoy
the o/p should be
yenjo
The code i tried was....
int n;
cout<<"Enter the number of strings";
cin>>n;
int len[n];
char str[n][1000];
for(int i=0;i<n;i++)
{
cin>>str[i];
len[i]=strlen(str[i]);
}
int num,pos[n];
for(int i=0;i<n;i++)
{
pos[i]=0;
num=int(str[i][0]);
for(int j=1;j<len[i];j++)
{
if(int(str[i][j])>num)
{
num=int(str[i][j]);
pos[i]=j;
}
}
}
int i,j,k;
char temp[1];
for(i=0;i<n;i++)
{
for(j=0;j<pos[i];j++)
{
temp[0]=str[i][0];
for(k=0;k<len[i];k++)
{
str[i][k]=str[i][k+1];
}
strcat(str[i],temp);
str[i][len[i]]='\0';
}
cout<<str[i]<<"\n";
}
return 0;
}
But this code only ckecks for the largest number and not for the number present next to it and hence fails for the i/p
blowhowler
The o/p should be wlerblowho but i get the o/p as whowlerblo.
How can i keep track of each element that preceeds the largest character so as to get the correct output?
For good performance on the average case (actually, O(N)), but still O^2 on the worst (and always correct), you can keep track of possibilities, and keep eliminating them as you go. Basically something like this.
struct PermSum
{
int sum;
int perm;
}
LinkedList<PermSum> L;
for(int i = 0; i != input.size(); ++i) L.append(PermSum{0,i});
int depth = 0;
int max = 0;
const int length = input.size()
while(L.size() > 1 && depth < length)
{
for(l in L)
{
l.sum += input[(l.perm + depth) % length]
if (l.sum > max) max = l.sum
}
for(l in L)
{
if (l.sum < max) L.delete(l)
}
depth ++;
}
if (L.size() == 1)
return L.front().perm
else
return -1
I got a bit lazy in some parts with the c++ code but I'm sure you can figure out for l in L. The key line is the first for loop. The idea is that its adding the lexicographical value at the depth-th letter of the l.perm-th permutation. In this way, it updates all the possibilities, while simultaneously keeping track of the level of the best possibility. You then do a second pass to delete any possibility falling short of the best. It's worth noting that the way I coded this up, it probably uses the reverse of the standard convention for circular permutations. That is, the perm field in my program represents how many spots LEFT you circular shift, whereas usually positive numbers are circular shifting right. You can fix this with a minus sign somewhere.
As for the running time analysis, it's basically the same argument as Quickselect. Each while loop iteration takes time proportional to the length of L. The first iteration, L will always have length = N (where N is the length of the string, the same as the variable length in the code). The next round, we typically only expect 1/26 of the data to get through, the round after that 1/26 again... so we have N(1 + 1/26 + 2/26^2...) which is O(N).
You can just:
1. generate rotations
2. put all rotations in map<>
3. find last element of the map.
Here is the implementation in C++.
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
int main() {
// your code goes here
string str;int len,i=0,j=0,k=0;char temp;
cin>>str;
len = str.length();
map<string,int>m;
while(i<len)
{
temp = str[0];
while(j<len-1)
{
str[j] = str[j+1];
j++;
}
str[j] = temp;
m[str] = k;
k++;
i++;j=0;
}
str = m.rbegin()->first;
cout<<str;
return 0;
}
The problem can be solved in O(n log n) time by appending the string to itself first and build the suffix array out of it. Find the corresponding entry and there your wanted result. Implementation left as an exercise.
//Here the index with greater value is selected,
//if the same char occurs again the next characters
// of prev and curr characters is checked:-Prev=maxIndex,curr=i
#include<bits/stdc++.h>
using namespace std;
int getIndex(char *str){
int max=INT_MIN,maxIndex;
int n=strlen(str);
int j,p;
for(int i=0;i<n;i++)
{
if(str[i]>max)
{
max=str[i];
maxIndex=i;
}
else if(str[i]==max)
{
j=maxIndex+1;
p=(i+1)%n;
while(j<n && p<n && str[j]==str[p]){
j++;
p=(p+1)%n;
}
maxIndex=str[p]>str[j]?i:maxIndex;
}
}
return maxIndex;
}
int main(void)
{
char str[4000008];
scanf("%s",str);
int i=getIndex(str);
for(int j=i;j<strlen(str);j++)
cout<<str[j];
for(int j=0;j<i;j++)
cout<<str[j];
}
Your algorithm, corrected, comes down to:
Set current best rotation to identity (start of rotated string is current index 0).
For each possible rotation (all other starting indices):
Compare to current-best-rotation with something like wrapcmp below.
Set the current-best-rotation if we had a better candidate.
Time-Complexity: O(n*n)
Space-Complexity: in-place
// Function to do ordinal-comparison on two rotations of a buffer
// buffer: The buffer containing the string
// n: The buffers size (string-length)
// a: Index where the first buffer starts pre-rotation
// b: Index where the second buffer starts pre-rotation
int wrapcmp(const void* buffer, size_t n, size_t a, size_t b) {
auto x = (const unsigned char*)buffer;
auto m = n - std::max(a, b);
int ret = memcmp(x+a, x+b, m);
if(ret) return ret;
auto left = n - m;
a = (a + m) % n;
b = (b + m) % n;
m = left - std::max(a, b);
ret = memcmp(x+a, x+b, m);
if(ret) return ret;
a = (a + m) % n;
b = (b + m) % n;
return memcmp(x+a, x+b, left - m);
}
Used on coliru: http://coliru.stacked-crooked.com/a/4b138a6394483447
Putting it into the general algo left as an exercise for the reader.
This was too tempting so I may as well post my effort. Not sure how it rates efficiency wize. It seems to work as far as I tested it:
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
std::string max_rot(const std::string& s)
{
std::string tmp;
std::string max;
std::string::const_iterator m = std::max_element(s.begin(), s.end());
if(m != s.end())
for(char c = *m; (m = std::find(m, s.end(), c)) != s.end(); ++m)
if(max < tmp.assign(m, s.end()).append(s.begin(), m))
max = tmp;
return max;
}
int main()
{
size_t times = 0;
std::string text;
do { std::cout << "\nHow many words? : "; }
while(std::getline(std::cin, text) && !(std::istringstream(text) >> times));
std::vector<std::string> words;
while(times-- && (std::cin >> text))
words.push_back(text);
for(const auto& s: words)
std::cout << max_rot(s) << '\n';
}
By way of explanation. It finds the highest character value in the string and rotates the string to make that character first. If then looks for duplicate highest characters in the remainder of the string keeping track of the highest attempt. There maybe room for optimization.
This challenge is used in an active contest, I request no answer to be provided till 18th Sep 9 PM IST. Because the code is visible, we might have to ban the user from participating in any of our contests going forward.
The program runs but it also spews out some other stuff and I am not too sure why. The very first output is correct but from there I am not sure what happens. Here is my code:
#include <iostream>
using namespace std;
const int MAX = 10;
int sum(int arrayNum[], int n)
{
int total = 0;
if (n <= 0)
return 0;
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0)
total += arrayNum[i];
}
cout << "Sum of odd integers in the array: " << total << endl;
return arrayNum[0] + sum(arrayNum+1,n-1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
sum(x,MAX);
system("pause");
return 0;
}
The term recursion means (in the simplest variation) solving a problem by reducing it to a simpler version of the same problem until becomes trivial. In your example...
To compute the num of the odd values in an array of n elements we have these cases:
the array is empty: the result is trivially 0
the first element is even: the result will be the sum of odd elements of the rest of the array
the first element is odd: the result will be this element added to the sum of odd elements of the rest of the array
In this problem the trivial case is computing the result for an empty array and the simpler version of the problem is working on a smaller array. It is important to understand that the simpler version must be "closer" to a trivial case for recursion to work.
Once the algorithm is clear translation to code is simple:
// Returns the sums of all odd numbers in
// the sequence of n elements pointed by p
int oddSum(int *p, int n) {
if (n == 0) {
// case 1
return 0;
} else if (p[0] % 2 == 0) {
// case 2
return oddSum(p + 1, n - 1);
} else {
// case 3
return p[0] + oddSum(p + 1, n - 1);
}
}
Recursion is a powerful tool to know and you should try to understand this example until it's 100% clear how it works. Try starting rewriting it from scratch (I'm not saying you should memorize it, just try rewriting it once you read and you think you understood the solution) and then try to solve small variations of this problem.
No amount of reading can compensate for writing code.
You are passing updated n to recursive function as argument but not using it inside.
change MAX to n in this statement
for(int i = 0; i < n; i ++)
so this doesnt really answer your question but it should help.
So, your code is not really recursive. If we run through your function
int total = 0; //Start a tally, good.
if (n <= 0)
return 0; //Check that we are not violating the array, good.
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0) //THIS PART IS WIERD
total += arrayNum[i];
}
And the reason it is wierd is because you are solving the problem right there. That for loop will run through the list and add all the odd numbers up anyway.
What you are doing by recursing could be to do this:
What is the sum of odd numbers in:
13,14,8,7,45,89,22,18,6,10
+
14,8,7,45,89,22,18,6
+
8,7,45,89,22,18
+
7,45,89,22 ... etc
And if so then you only need to change:
for(int i = 0; i < MAX; i ++)
to
for(int i = 0; i < n; i ++)
But otherwise you really need to rethink your approach to this problem.
It's not recursion if you use a loop.
It's also generally a good idea to separate computation and output.
int sum(int arrayNum[], int n)
{
if (n <= 0) // Base case: the sum of an empty array is 0.
return 0;
// Recursive case: If the first number is odd, add it to the sum of the rest of the array.
// Otherwise just return the sum of the rest of the array.
if(arrayNum[0] % 2 != 0)
return arrayNum[0] + sum(arrayNum + 1, n - 1);
else
return sum(arrayNum + 1, n - 1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
cout << sum(x,MAX);
}