Find total number of possible combination of letters in a given word in C language - arrays

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);

Related

Why am I getting some random values after the output?

#include <stdio.h>
int main()
{
int k;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
char num[10];
scanf("%s",&num);
int x = num[0]-'0';
int sum;
int y;
for(int i=0;i<10;i++)
{
if(num[i]=='\0')
{
y = num[i-1]-'0';
sum = x+y;
printf("%d\n",sum);
}
}
}
return 0;
}
This program is to obtain the sum of first and last digit of a given number. I am getting some random values after the output. Can anyone please explain me this and how do I eliminate it?enter image description here
You have an inner loop that looks for the terminating null byte in the array. You find it, but then you keep looping through the array looking for more null bytes. If you happen to find one, it takes whatever the prior byte is and treats it as the last digit.
You can fix this by breaking out of the loop when you find the null terminator:
for(int i=0;i<10;i++)
{
if(num[i]=='\0')
{
y = num[i-1]-'0';
sum = x+y;
printf("%d\n",sum);
break;
}
}
Or by simply using strlen to find the end of the string.
y = num[strlen(num)-1]-'0';
sum = x+y;
printf("%d\n",sum);
The code also doesn't handle reading too many characters, which can overflow the buffer, or reading an empty string, in which case num[strlen(num)-1] is off the start of the array. You can address the former by putting a field width in the scanf format, and the latter with an explicit check:
char num[10];
scanf("%9s",num);
int sum;
if (num[0] == 0) {
sum = 0;
} else {
int x = num[0]-'0';
int y = num[strlen(num)-1]-'0';
sum = x + y;
}
printf("%d\n",sum);
The problem is that you don't stop the inner loop once you print the sum. You continue and use the indeterminate elements in the array num beyond the string terminator. That leads to undefined behavior.
You could solve it either by not having the inner loop (by using index 0 and strlen(num) - 1), or by using break to break out of the loop once you printed the sum.

Bubble sort takes a long time then segfaults

Given an integer n, write a C program to count the number of digits that are in the same position after forming an integer m with the digits in n but in ascending order of digits. For example, if the value of n is 351462987 then value of m will be 123456789 and digits 4 and 8 will be in the same position.
This is my code:
#include<stdio.h>
void bubble(int a[],int length)
{
for (int i=0;i<length;i++)
{
for (int j=0;j<length;j++)
{
if (a[j]>a[j+1])
{
int t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
int check(int a[],int b[],int length)
{
int count=0;
for (int i=0;i<length;i++)
{
if (a[i]==b[i])
{
count=i;
break;
}
}
return count;
}
int length(int n)
{
int l;
while (n!=0)
{
n=n/10;
l++;
}
return l;
}
void main()
{
int n,arrn[100],temp[100];
scanf("%d",&n);
int l=length(n);
for (int i=0;i<l;i++)
{
arrn[l-i-1]=n%10;
temp[l-i-1]=arrn[l-i-1];
n=n/10;
}
bubble(temp,l);
int c=check(arrn,temp,l);
printf("%d",c);
}
I am able to compile the code but when I execute it it takes a long time only to show segmentation fault.
Easy answer, use a debugger.
Here are some problem with your code:
In length function, l is not initialized and as such can have an arbitrary initial value. In your case, you probably want to start at 0.
int l = 0;
Your check function probably don't do what you want. As written count is not a count but the index of a position where numbers match. As there is a break statement in the block, the loop will exit after the first match so the return value would be the position of the first match or 0 if no match was found.
Your bubble function goes one item too far when i is equal to length - 1 as you access item a[j + 1] in the inner loop which is out of bound. In that case, it is simpler to start at 1 instead of 0 and compare item at index i - 1 with item at index i.
Some extra notes:
It is recommended to add whitespace around operators and after a comma separating multiple declarations to improve readability. Here are some example of lines with improved readability.
int n, arrn[100], temp[100];
int count = 0;
for (int i = 0; i < length; i++)…
if (a[i] == b[i])…
arrn[l - i - 1] =n % 10;
temp[l - i - 1] = arrn[l - i - 1];
int check(int a[], int b[], int length)
Instead of writing multiple functions at once, you should write one function and ensure it works properly. By the way, the loop that split a number into digits could also be a function.
Try the function with small number (ex. 12 or 21)
Use better name for your variable. arrn and temp are not very clear. original and sorted might be better.
Your length function has a very obvious bug in it. What value does l start with? You don't initialise it so it could start with any value and cause undefined behaviour. You should set it to 0.
int length(int n)
{
int l = 0;
while (n!=0)
{
n=n/10;
l++;
}
return l;
}
Personally, I wouldn't be sorting or reading it into an int - to enable handling leading zeros in the digit string. For example:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXNUMLEN 200
int main(void)
{
int i, j, l, x=0;
char numin[MAXNUMLEN], numout[MAXNUMLEN];
int digits[10]={0};
printf("enter a string of digits: " );
fgets(numin, sizeof(numin), stdin);
printf("\nsaw : %s", numin );
// walk string once, counting num of each digit present
l=strlen(numin);
for(i=0; i<l; i++) {
if( isdigit(numin[i]) ) {
int d = numin[i] - '0'; // char digit to int digit
digits[d]++;
}
}
// for each digit present, write the number of instances of the digit to numout
for( i=0; i<10; i++ ) {
for(j=0; j<digits[i]; j++)
numout[x++] = '0'+i; // int digit back to char digit
}
numout[x]='\0'; // terminate string
printf("sorted: %s\n", numout );
}
Sample run:
watson:digsort john$ ./ds
enter a string of digits: 002342123492738234610
saw : 002342123492738234610
sorted: 000112222233334446789
watson:digsort john$

C Programming: How to determine an exact match between 2 numbers

I am trying to find the exact match between two numbers and have my counter stop at the first instance when they are not a match. However the code I have written counts the entire string length of my numbers. Is there an alternative way to do this?
Since my counter is starting from the first decimal place and not 0. , it counts to 15 but should stop at 10.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
int main(){
char str[100];
char buf[100];
double l,m,a,b;
int c,d,t,u,r,q;
int count =0;
l=59874.141715197809000;
m=59874.141715197817000;
a= (l - (int)l);
b= (m -(int)m);
sprintf(str,"%.15f",a);
sprintf(buf,"%.15f",b);
c = strlen(str);
d = strlen(buf);
for(t=3;t<c;t++){
for(u=3;u<d;u++){
if(str[t]==buf[u]){
count++;
break;
}
}
}
printf("matching decimal places = %d \n",count);
return 0;
}
First, when comparing two strings, you only need to iterate to the length of the smallest string if the two strings differ in length.. That is, if you want to count the amount of sequential character matches in a string.
For example:
A = 0.99997552
B = 0.9999753
would need one for loop to compare.. You would only iterate up to the length of B to determine that 6 decimals match. Why? Because going any further is irrelevant since none of the extra digits would exist in B. Iterating past the end of an array is undefined behaviour anyway.
In your case both buffers are the same length so no worries there, but again, the shorter string won't have the extra digits found in the longer string.. Hence: Iterate up to the smallest length.
The solution can be done as follows:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main() {
//Create large enough buffer to hold 100 digits/characters..
char str[100] = {0};
char buf[100] = {0};
//Two doubles to be compared..
double l = 59874.141715197809000;
double m = 59874.141715197817000;
//Counter keeps track of matching digits..
int count = 0;
//Get rid of the base and keep only the decimals..
double a = (l - (int)l);
double b = (m - (int)m);
//Copy a maximum of 15 decimal places to `str` and `buf`
sprintf(str, "%.15f", a);
sprintf(buf,"%.15f", b);
//Get the length of both strings..
int c = strlen(str);
int d = strlen(buf);
//If C is smaller, iterate to length(c) else iterate to length(d).
for (int i = 2; i < (c < d ? c : d); ++i)
{
//If the two characters match, increment the count..
if (str[i] == buf[i])
{
++count;
}
}
//Print the amount of matching decimals..
printf("matching decimal places = %d \n", count);
return 0;
}
This may not be the answer, but do
if (number1 == number2)
{
// do something to stop it
}

Reverse two numbers and obtain the reverse of the sum

I am coming to SO as a last resort. Been trying to debug this code for the past 2 hours. If the question is suited to some other SE site, please do tell me before downvoting.
Here it goes:
#include <stdio.h>
#include<math.h>
int reverse(int n) {
int count = 0, r, i;
int k = (int)log(n * 1.0);
for(i = k; i >= 0; i--)
{
r = (n % 10);
n = (n / 10);
count = count + (r * pow(10, k));
}
return count;
}
int main(void) {
int t;
scanf("%d", &t);
while(t--)
{
int m, n, res;
scanf("%d %d", &m, &n);
res = reverse(m) + reverse(n);
printf("%d", reverse(res));
}
return 0;
}
My objective is to get 2 numbers as input, reverse them, add the reversed numbers and then reverse the resultant as well.I have to do this for 't' test cases.
The problem: http://www.spoj.com/problems/ADDREV/
Any questions, if the code is unclear, please ask me in the comments.
Thank you.
EDIT:
The program gets compiled successfully.
I am getting a vague output everytime.
suppose the 2 numbers as input are 24 and 1, I get an output of 699998.
If I try 21 and 1, I get 399998.
Okay, if you had properly debugged your code you would have notices strange values of k. This is because you use log which
Computes the natural (base e) logarithm of arg.
(took from linked reference, emphasis mine).
So as you are trying to obtain the 'length' of the number you should use log10 or a convertion (look at wiki about change of base for logarithms) like this: log(x)/log(10) which equal to log10(x)
And now let's look here: pow(10, k) <-- you always compute 10^k but you need 10^i, so it should be pow(10, i) instead.
Edit 1: Thanks to #DavidBowling for pointing out a bug with negative numbers.
I don't know how exactly you have to deal with negative numbers but here's one of possible solutions:
before computing k:
bool isNegative = n < 0;
n = abs(n);
Now your n is positive due to abs() returning absolute value. Go on with the same way.
After for loop let's see if n was negative and change count accordingly:
if (isNegative)
{
count = -count;
}
return count;
Note: Using this solution we reverse the number itself and leave the sign as it is.
It looks like Yuri already found your problem, but might I suggest a shorter version of your program? It avoids using stuff like log which might be desirable.
#include <stdio.h>
int rev (int n) {
int r = 0;
do {
r *= 10;
r += n % 10;
} while (n /= 10);
return r;
}
int main (void) {
int i,a,b;
scanf("%d",&i);
while (i--) {
scanf("%d %d",&a,&b);
printf("%d\n",rev(rev(a) + rev(b)));
}
return 0;
}
Hopefully you can find something useful to borrow! It seems to work okay for negative numbers too.
Under the hood you get char string, reverse it to numeric, than reverse it to char. Since is more comfortable work with chars than let's char:
char * reverse (char *s,size_t len) //carefull it does it in place
{
if (!len) return s;
char swp, *end=s+len-1;
while(s<end)
{
swp =*s;
*s++=*end;
*end--=swp;
}
return s;
}
void get_num(char *curs)
{
char c;
while((c=getchar())!='\n')
*curs++=c;
*curs=0;
}
int main()
{
double a,b,res;
char sa[20],sb[20],sres[20],*curs;
get_num( sa);
get_num(sb);
reverse(sa,strlen(sa));
reverse(sb,strlen(sb));
sscanf(sa,"%f",&a);
sscanf(sb,"%f",&b);
res=a+b;
sprintf(sres,"%f",res);
reverse(sres);
printf(sres);
}

Can't find the logical bug

I have solved this programming problem and when I submitted my code, the judge said it was wrong. I tried and I couldn't figure out the bug. Can someone give me a hint please?
Because stack overflow won't accept my question if I don't specify more details, I am copying the question here
A sequence of n > 0 integers is called a jolly jumper if the absolute values of the
differences between successive elements take on all possible values 1 through n − 1. For
instance,
1 4 2 3
is a jolly jumper, because the absolute differences are 3, 2, and 1, respectively. The
definition implies that any sequence of a single integer is a jolly jumper. Write a program
to determine whether each of a number of sequences is a jolly jumper.
Input
Each line of input contains an integer n < 3, 000 followed by n integers representing the
sequence.
Output
For each line of input generate a line of output saying “Jolly” or “Not jolly”.
The code
#include <stdio.h>
#define SEQ_SIZE 3000
static char stack[SEQ_SIZE];
void initStack(int count)
{
for(int i=0;i<count; ++i)
stack[i]=0;
}
int absDiff(int a, int b)
{
return (a-b)>=0?((a-b)%SEQ_SIZE):(((a-b)*-1)%SEQ_SIZE);
}
int main()
{
int n,prev,curr;
/*FILE *sample=fopen("SampleInput","r");
if(!sample)
return 0;*/
while(scanf("%d",&n)!=EOF)
{
scanf("%d",&prev);
if(n<1)
break;
else if(n==1)
printf("Jolly\n");
else
{
int i;
for(i=1; i<n; ++i)
{
scanf("%d",&curr);
stack[absDiff(curr,prev)-1]=1;
prev=curr;
}
for(i=0; i<(n-1); ++i)
{
if(stack[i]==0)
break;
}
if(i<n-1)
printf("Not jolly\n");
else
printf("Jolly\n");
initStack(n);
}
}
}
I think your solution is fine except the line
return (a-b)>=0?((a-b)%SEQ_SIZE):(((a-b)*-1)%SEQ_SIZE);
No need to use % here. It should be
return (a-b)>=0?((a-b)): (a-b)*(-1));
To limit n below 3000 you can do as
if(n<1 || n >= 3000) // I merged it with n<1 condition
break;

Resources