I want to print the combination of any 3 letters without using nested for loop in C programming ?
Following is the code for the combination of 3 letters "ABC".
I can execute the program by using 3 for loops.
But I dont want that. I want to do it by only one for loop and in a non-recursive way.But I am not getting any logic.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i=0,j=0;
char b[10],a[] = "ABC";
strcpy(b,a);
while(i < 3)
{
b[j]=a[i];
if(i==0)
{
b[j+1]=a[i+1];
b[j+2]=a[i+2];
printf("\n%s",b);
b[j+1]=a[i+2];
b[j+2]=a[i+1];
printf("\n%s",b);
}else if(i==1)
{
b[j+1]=a[i+1];
b[j+2]=a[i-1];
printf("\n%s",b);
b[j+1]=a[i-1];
b[j+2]=a[i+1];
printf("\n%s",b);
}else
{
b[j+1]=a[i-1];
b[j+2]=a[i-2];
printf("\n%s",b);
b[j+1]=a[i-2];
b[j+2]=a[i-1];
printf("\n%s",b);
}
i++;
}
getch();
return 0;
}
If you know it's always going to be a length of three, you can use pre-generation to minimise complexity and/or code. Pre-generation is the act of moving complex calculations from run time to compile time or even before hand, and it can be very productive for complex calculations.
One example (though a little contrived) is to write a program to calculate all possible unsigned 64-bit factorials (there's only about ninety of them) then have that program generate the source code (lookup table and function) that can do the lookup to get them. The complexity of generating the table is done once, long before compilation of the program that will use it.
This means that a factorial operation in the program that uses it, changes from being a possibly time consuming series of multiplications to something more akin to one multiplication and an addition (the table lookup).
Applying that same method to permutations (though the generation of the lookup table was done in my head since it's not that complex) will give you code like:
#include <stdio.h>
// The permutations.
static int perm3[] = { 0,1,2, 0,2,1,
1,0,2, 1,2,0,
2,0,1, 2,1,0 };
int main (void) {
int i;
char x[] = {'a', 'b', 'c'};
// Permute using the table to get indexes.
for (i = 0; i < sizeof(perm3) / sizeof(perm3[0]); i += 3)
printf ("%c %c %c\n", x[perm3[i]], x[perm3[i+1]], x[perm3[i+2]]);
return 0;
}
Now, some people may consider that "cheating" but I'll be honest here, some of the fastest programs you can write will cheat in this manner :-)
The problem you are asking is based of algorithm concept Backtracking
Here is the function
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
call this from main()
int main()
{
char a[] = "ABC";
permute(a, 0, 2); // first param is array,2nd is starting index and 3rd is ending index
return 0;
}
Wolfram alpha is having mathematical concept behind these type of problem.Basically we try all the solutions one by one and then backtrack by reverting those changes to original one and then again try out different solution.To understand clearly check this.
http://mathworld.wolfram.com/Permutation.html
Related
I have a question that I am not able to solve.
Alex wants to test his child's ability of identifying correct spelling of a word from a group of jumbled words. To jumble the words they want to find out how many ways a word can be rearranged. For example if they want to rearrange a word "whats" where the letters are unique, the number of ways can be found by finding 5!. It the word is "hello" where letter 'l' alone is repeated twice, the number of ways a word can be rearranged can be found out by 5!/2!(no of letters!/number of repeated letter count!). If the word is "little" where two letters 'l' and 't' are repeated twice, then number of ways to arrange letters is 6!/(2!*2!). Write a recursive function to find factorial.
Input: String to rearrange.
Output: Integer denoting the number of ways a letter can be jumbled.
Sample Test:
Input: document
Output: 40320
I tried this code(C language):
#include<stdio.h>
#include<string.h>
int seq(char arr[], int len) {
int i, j, cnt[100], rf, nf, r;
for (i=0;i<len;i++) {
int ct=0;
for (j=i;i<len;j++) {
if (arr[i]==arr[j])
ct++;
}
cnt[i]=ct;
}
for (i=1;i<=len;i++)
nf *= i;
size_t size = sizeof(cnt)/sizeof(cnt[0]);
for (j=0;j<size;j++) {
for (i=1;i<cnt[j];i++)
rf *= i;
r *= rf;
}
return nf/r;
}
int main() {
char arr[100];
scanf("%s", arr);
printf("%d", seq(arr, strlen(arr)));
}
Expected:
Input: Whats
Output: 120
Actual:
Input: Whats
Output:
Run Error
Segmentation fault (core dumped)
There are several bugs. One is that almost all of the variables used to calculate factorials are uninitialized. Those need to be initialized to 1.
There are also some typos. For example, for (j=i;i<len;j++) should be for (j=i;j<len;j++) (the i in the comparison needs to be j).
And the loop for (i=1;i<cnt[j];i++), which calculates the factorials of the duplicated letters, needs to include the final count, i.e. it needs to be for (i=1;i<=cnt[j];i++).
Also, this part:
size_t size = sizeof(cnt)/sizeof(cnt[0]);
for (j=0;j<size;j++) {
always forces the loop to run from 0 to 99. It should run from 0 to len-1, i.e. those two lines need to be replaced with:
for (j=0;j<len;j++) {
Here's a version that fixes these problems:
#include<stdio.h>
#include<string.h>
int seq(char arr[], int len) {
int i, j, cnt[100], rf, nf, r;
for (i=0;i<len;i++) {
int ct=0;
for (j=i;j<len;j++) {
if (arr[i]==arr[j])
ct++;
}
cnt[i]=ct;
}
nf = 1;
for (i=1;i<=len;i++)
nf *= i;
r = 1;
for (j=0;j<len;j++) {
rf = 1;
for (i=1;i<=cnt[j];i++)
rf *= i;
r *= rf;
}
return nf/r;
}
int main() {
char arr[100];
scanf("%s", arr);
printf("%d\n", seq(arr, strlen(arr)));
}
I also added a newline to the end of the printf format string.
At least these problems:
Code compiled without all compiler warnings enable
At least 3 issues warned about.
Uninitialized variables
nf *= i;, r *= rf; used without nf, r, rf being assigned.
Loop count wrong
for (j=0;j<size;j++) { iterates size times even though cnt[j] only assigned len times.
Wrong test
Review for (j = i; i < len; j++) { stopping condition.
int overflow
Code like nf *= i readily overflows. Use a wider type for nf and check for overflow potential.
Buffer overflow
Input risks overflow without a width.
// scanf("%s", arr);
scanf("%99s", arr);
I recently faced this problem in a coding contest:
We have to form a skill squad with members such that no member has more skill than the sum of skills of any two other member in the squad.
Given an array of skills of n members, find the maximum sum of skills of a squad possible with above constraint.
I used a greedy algorithm:
-sort the array;
-use three pointers and choose indices such that the sum of the first two elements (smallest) is lesser than the last (largest element) of the considered subarray.
-Also keep moving the indices to check for all such subarrays and return the maximum sum among them.
But this passed half the cases and others failed. Can someone help me with what I am missing here? Following is my program:
//Author:: Satish Srinivas
#include<bits/stdc++.h>
using namespace std;
int solve(int arr[],int n)
{
sort(arr,arr+n);
int sum[n];
sum[0]=arr[0];
//precompute sums
for(int i=1;i<n;i++)
{
sum[i]=sum[i-1]+arr[i];
}
if(n<=2)
return sum[n-1];
int res=INT_MIN;
for(int i=0;i<=n-3;i++)
{
int min=arr[i]+arr[i+1];
int j=i+1;
while(j<=n-2 && arr[j+1]<=min)
j++;
if(j>i+1)
{
if(i==0)
{
if(res < sum[j]-sum[0])
res=sum[j]-sum[0];
}
else
{
if(res < sum[j]-sum[i-1])
res=sum[j]-sum[i-1];
}
}
}
return res;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
/*
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
*/
int arr1[]={10,4,4,5,4};
int n1=sizeof(arr1)/sizeof(arr1[0]);
cout<<solve(arr1,n1)<<endl;
int arr2[]={25,60,1,5,3,35};
int n2=sizeof(arr2)/sizeof(arr2[0]);
cout<<solve(arr2,n2)<<endl;
return 0;
}
//output:
//13
//120
A few things that look a little wrong:
If n is equal to 2, you return INT_MIN because your for loop never executes
More generally, you seem to consider a team of size 2 as being invalid
When i is equal to 0, you want to compute the score from adding up all numbers from i to j, this is equal to sum[j] but you compute res=sum[j]-sum[0]
As you have sorted the array, you actually don't need to reset j in each iteration (this only matters if you are failing due to a time-out)
I am starting to teach myself C and am trying to build a group of useful functions and programs for future reference. If relevant, this is C99.
Here is my most recent iteration of the program. At the output, I want to get the prime factorization of a number n. As is, however, I get a list of all factors, and no factors are repeated. I included some print statements to try and debug, and have found that the error is with the recursion, but can't figure out how to interpret it further. I previously tried making the recursive function of type int, but had difficulties getting it to work with the array p.
n is the number that I am trying to factor
p is an array for storing the found primes
j is an index for p
c is the number that I am testing as a divisor to n
I am aware that there are probably more efficient ways to declare p to save memory, but since this is mainly for reference, memory is not a huge concern.
I found these questions but don't think that they answer my question
finding greatest prime factor using recursion in c :This question is about crashing code. Mine compiles, runs, and produces reasonably sensible output, I'm just wondering why the output isn't what I expect.
is there ever a time you would not use recursion? [closed] :This indicates that recursion is not a good choice for prime factorization- I don't know, but suspect that this would also apply to C. Since this is for reference, I don't think it is a huge issue. If you disagree, please explain why.
My main questions are these:
Why does the output show all factors of n?
Why does it not repeat the prime factors?
What do I have to do to fix it?
#include <stdio.h>
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
void factors(int n, int p[], int j) {
/// if n is divisible by c, store c, and continue with n/c
int c;
for (c=2; c < n; c++) {
if (c > n) break;
if (n%c == 0) {
p[j] = c;
printf("%d has been added to p \t", c);
printf("n has been reduced to %d \t", n/c);
printf("j is %d \n", j);
j++;
if (n == c) break;
factors(n/c, p, j);
}
}
}
int main() {
/// set up number to factor, and array to hold factors
int n = 24;
int p[n/2];
int i=0;
for (i=0; i<NELEMS(p); i++) {
p[i]=0;
}
int j = 0;
factors(n, p, j);
printf("the prime factors of %d are:\n",n);
for (i=0; i<NELEMS(p); i++) {
printf("%d \n", p[i]);
}
}
You have already been told in comments that this algorythm is poor, which is an evidence here. And you really should learn to use a debugger: running this through a debugger immediately shows where the problems are.
That being said, your main problem here is what to do when the recursive functions return?. You failed to ask yourself this question which is a must in recursion, and simply continue in sequence, which is plain wrong because you will reuse a number that has already been processed in the recursive calls. So you must add a return line immediately after recursively calling factors.
Once this is done, there is another minor problem (that a debugger would make evident), you only search factors strictly lesser that n. So you miss the last prime factor...
With those 2 immediate fixes, your code becomes:
void factors(int n, int p[], int j) {
/// if n is divisible by c, store c, and continue with n/c
int c;
for (c=2; c <= n; c++) {
if (c > n) break;
if (n%c == 0) {
p[j] = c;
printf("%d has been added to p \t", c);
printf("n has been reduced to %d \t", n/c);
printf("j is %d \n", j);
j++;
if (n == c) break;
factors(n/c, p, j);
return;
}
}
}
But IMHO p[j] = c; should become *p = c; and factors(n/c, p, j); should become factors(n/c, p+1, j);. Said differently you pass directly a pointer to the next slot.
Edit It occurs to me that the smallest factor of n is guaranteed to be prime, so I have edited the answer accordingly.
Why does the output show all factors of n?
Because you test if c is a factor of n and add it to the array p whether c is prime or not. Then you carry on testing numbers above c, even multiples of c.
Why does it not repeat the prime factors?
Because when you find a number c that is a factor, you don't necessarily inspect it to find out if it is a compound number itself.
After adding c to p, you need to recursively call factor on (n / c) and then stop.
Here is roughly what you need (but not tested or even compiled)
int factorise(int n, int p[], int j)
{
int factorsFound = 0;
for (c = 2 ; c * c <= n && factorsFound == 0 ; ++ c)
{
if (n % c == 0)
{
p[j] = c;
factorsFound = factorise(n / c, p, j + 1) + 1;
}
}
if (factorsFound == 0) // n is prime
{
p[j] = n;
factorsFound = 1;
}
return factorsFound;
}
Also in a real solution, you probably want to pass the size of p so that you can detect if you run out of space.
Just for fun, since nobody else has posted it yet, here is a non recursive solution. It's actually the same as above but the recursion has been transformed into a loop.
int factorise(int number, int p[])
{
int j = 0;
for (int c = 2, int n = number ; n > 1 ; )
{
if (n % c = 0)
{
p[j++] = c;
n = n / c;
}
else
{
c++;
}
}
return j;
}
I disagree with some of Lundin's comments about recursion. Recursion is a natural way of breaking a problem down into easier subtasks but in C it is undeniably less efficient, especially in terms of stack space and in this particular case, the non recursive version is simpler.
From This answer:
why does recursion cause stackoverflow so much more than loops do
Because each recursive call uses some space on the stack. If your recursion is too deep, then it will result in StackOverflow, depending upon the maximum allowed depth in the stack.
When using recursion, you should be very careful and make sure that you provide a base case. A base case in recursion is the condition based on which the recursion ends, and the stack starts to unwind. This is the major reason of recursion causing StackOverflow error. If it doesn't find any base case, it will go into an infinite recursion, which will certainly result in error, as Stack is finite only.
-
It appears that your for is in the way, c will increment, and wont check that same value again.
For instance, if the input is 8, we want (2,2,2) and not (2,4).
I would recommend replacing your if (c%n ==0) by a while, don't forget to replace the value of n in that while, you don't want to loop in that.
This appears to be a good answer :
int primes(int nbr, int cur)
{
if (cur > nbr)
return (0);
else
{
if (nbr % cur == 0 && isprime(cur) == 1)
{
printf("%d\n", cur);
return (primes(nbr / cur, 2));
}
return (primes(nbr, cur + 1));
}
}
Call that function with cur = 2 in your main
I am making a small ANSI C application that uses pointers to sort int values using the bubble sort algorithm.
My main file:
#include "bubbleSort.h"
char Ar[] = "All Gaul is divided into three parts, one of which the Belgae inhabit, the Aquitani another, those who in their own language are called Celts, in our Gauls, the third. All these differ from each other in language, customs and laws. The river Garonne separates the Gauls from the Aquitani; the Marne and the Seine separate them from the Belgae. Of all these, the Belgae are the bravest, because they are furthest from the civilization and refinement of [our] Province, and merchants least frequently resort to them, and import those things which tend to effeminate the mind; and they are the nearest to the Germans, who dwell beyond the Rhine , with whom they are continually waging war; for which reason the Helvetii also surpass the rest of the Gauls in valor, as they contend with the Germans in almost daily battles, when they either repel them from their own territories, or themselves wage war on their frontiers. One part of these, which it has been said that the Gauls occupy, takes its beginning at the river Rhone ; it is bounded by the river Garonne, the ocean, and the territories of the Belgae; it borders, too, on the side of the Sequani and the Helvetii, upon the river Rhine , and stretches toward the north. From 'Caesar's Conquest of Gaul', Translator. W. A. McDevitte. Translator. W. S. Bohn. 1st Edition. New York. Harper & Brothers. 1869. Harper's New Classical Library. Published under creative commons and available at http://www.perseus.tufts.edu/hopper/text?doc=Perseus:text:1999.02.0001";
int main(void) {
int ABStats[ALPHABET_SIZE] = { 0 };
char chAlphabet[ALPHABET_SIZE] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
char *pAr = Ar;
char *pAlphabet = chAlphabet;
int *pABStats = ABStats;
GetFrequency(pAr, pABStats);
int i, j;
for (i = ALPHABET_SIZE-1; i >= 0; i--) {
for (j = 0; j <= i; j++) {
if (*(pABStats+j) < *(pABStats+j+1)) {
Swap(pABStats+j, pABStats+j-1);
}
}
}
DisplayVHist(pABStats, ALPHABET_SIZE);
return EXIT_SUCCESS;
}
My bubbleSort.c file:
#include "bubbleSort.h"
int GetFrequency(char *pAr, int *pABStats) {
int chNum = 0;
for (; *pAr != '\0'; pAr++) {
char ch = *pAr;
if (isalpha(ch))
chNum = (toupper(ch) - 'A');
pABStats[chNum]++;
}
return chNum;
}
void DisplayVHist(int *pABStats, int size) {
int i, j;
const float lengthAr = strlen(Ar);
for (i = 0; i < size; i++) {
float chPercent = 100 * (*pABStats / lengthAr);
printf("'%c' --> %6.3f percent --> %3d occurances --> ", (i + 'A'), chPercent, *pABStats);
for (j = 0; j < (*pABStats / 2); j++) {
printf("%c",'*');
}
printf("\n");
pABStats++;
}
}
void Swap(int *pA, int *pB) {
int temp;
temp = *pA;
*pA = *pB;
*pB = temp;
}
My header file:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define ALPHABET_SIZE 26
extern char Ar[];
int GetFrequency(char*, int*);
void DisplayVHist(int*, int);
void Swap(int*, int*);
I would like the application to iterate through the array ABStats using the pointer pABStats and use the Sort() function inside bubbleSort.c to sort the values inside ABStats from highest occurrence to lowest occurrence. Everything so far is functioning properly except for my Sort() algorithm.
I am required to use a Bubble Sort algorithm by using the function Sort() inside the bubbleSort.c file. I also have to use pointers to reference the array, as opposed to using ABStats[i].
Does anybody have any advice on how to get Sort() to work? I'm fairly new to C programming. Thanks!
This code:
for (j = 0; j <= i; j++)
if (*(pABStats+j) < *(pABStats+j+1))
Swap(pABStats+j, pABStats+j-1);
Should read:
for (j = 0; j < i; j++)
if (*(pABStats+j) < *(pABStats+j+1))
Swap(pABStats+j, pABStats+j+1);
Your for loop led to out of bounds array access. And you must swap the items that you compared.
I suspect there are other problems with the code but I don't have the energy to debug it all.
Some general points:
Sorting could should be de-coupled from the data it operates on. Your sort is inlined into your main. That's not ideal. Take a look at the standard library sorting function to see how it should be done.
Whilst your professor seems to think that *(a+i) is better than a[i] he/she is in a tiny minority. Try not to be misled by this advice. Prefer using the array indexing operator.
int GetFrequency(char *pAr, int *pABStats) {
int chNum = 0;
for (; *pAr != '\0'; pAr++) { /*check if at the end of the array*/
char ch = *pAr; /*store current letter as a char*/
if isalpha(ch) /*if character is a letter*/
chNum = (toupper(ch) - 'A'); /*return ascii code of specified letter*/
pABStats[chNum]++; /*store ascii value in array and increment array*/
}
return chNum;
}
this makes sense, but then you bubble sort the pABStats array, you are loosing all the information.
suppose there were 10A's and 5B's in your sentence so pABStats[0] = 10 and pABstats[1] = 5, when you bubble sort this from small to large, pABstats[0] = 5 and PabStats[1] = 10. So now your program thinks there were 5A's and 10B's ?
I assume the array subscript runs from 0-25, which translates to subscript 0 is the number of A's and subscript 1 number of B's and so on.
So all I'm trying to do is take an input from the user of how many cards to use and then randomly assign each card to a different index in an array. I'm having extensive issues getting the rand function to work properly. I've done enough reading to find multiple different ways of shuffling elements in an array to find this one to be the easiest in regards to avoiding duplicates. I'm using GCC and after I input the amount of cards I never get the values from the array back and if I do they're all obscenely large numbers. Any help would be appreciated.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void main(){
srand(time(NULL));
int d, c, i, z, l, r;
printf("Enter the deck length: ");
scanf("%d\n ", &c);
int deck[c];
int swap[c];
z = c;
for(l=0; l<c; l++){
swap[l] = l;
}
for(i=z; i=0; i--){
r = rand() / i
deck[i] = swap[r];
for(r; r=(c-1); r++){
swap[r] = swap[(r+1)];
}
}
for(d = 0; d < c; d++){
printf("%d ", deck[d]);
}
return;
}
I can spot one major problem here:
for(i=z; i=0; i--)
^^^
This loop will never execute since you are using assignment(=) and setting i to 0 therefore the condition will always be false, although using equality(==) will still be false in this case, you probably want:
for(i=z; i!=0; i--)
This means you will be using deck unitialized which is undefined behavior. Once you fix that you have a similar problems here:
for(r; r=(c-1); r++){
main has to return int and your return at the end needs to provide a value.
Turning on warning should have allowed you to find most of these issues, for example using -Wall with gcc gives me the following warning for both for loops:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Note, see How can I get random integers in a certain range? for guidelines on how to use rand properly.
You basically need to be able to generate 52 numbers pseudo-randomly, without repeating. Here is a way to do that...
First, loop a random number generator 52 times, with a method to ensure none of the random numbers repeat. Two functions in addition to the main() will help to do this:
#include <ansi_c.h>
int NotUsedRecently (int number);
int randomGenerator(int min, int max);
int main(void)
{
int i;
for(i=0;i<52;i++)
{
printf("Card %d :%d\n",i+1, randomGenerator(1, 52));
}
getchar();
return 0;
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
while(trying)
{
srand(clock());
random = (rand()/32767.0)*(max+1);
((random >= min)&&(NotUsedRecently(random))) ? (trying = 0) : (trying = 1);
}
return random;
}
int NotUsedRecently (int number)
{
static int recent[1000];//make sure this index is at least > the number of values in array you are trying to fill
int i,j;
int notUsed = 1;
for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++) (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
if(notUsed)
{
for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
{
recent[j-1] = recent[j-2];
}
recent[j-1] = number;
}
return notUsed;
}