I want to write a program that will take an input T
. In the next T
lines, each line will take a string as an input. The output would be how many ways the string can be reordered.
#include <stdio.h>
#include <stdlib.h>
int main() {
int T, i, l, count = 1, test = 0, word = 0, ans;
char line[200];
scanf("%d", &T);
for (i = 0; i < T; i++) {
scanf(" %[^\n]", line);
l = strlen(line);
for (int q = 0; q < l; q++) {
if (line[q] == ' ') {
word++;
}
}
ans = fact(word + 1);
word = 0;
for (int j = 0; j < l; j++) {
for (int k = j + 1; k < l; k++) {
if (line[k] == ' ' && line[k + 1] == line[j]) {
int m = j;
int n = k + 1;
for (;;) {
if (line[m] != line[n]) {
break;
} else
if (line[m] == ' ' && line[n] == ' ') {
test = 1;
break;
} else {
m++;
n++;
}
}
if (test == 1) {
count++;
ans = ans / fact(count);
count = 0;
test = 0;
}
}
}
}
printf("%d\n", ans);
}
}
int fact(int n) {
if (n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
Now, in my program,
my output is like this:
2
no way no good
12
yes no yes yes no
120
if T = 2
and the 1st string is no way no good
, it gives the right output that is 12
(4./2,). That means, it has identified that there are two similar words.
But in the 2nd input, the string is yes no yes yes no
. that means 3 yes
and 2 no
s. So the and should be 5!/(3!2!) = 10
. But why is the answer 120
? and why can't it recognize the similar words?
The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ')
but this test fails to identify a duplicate that occurs with the last word because line[n]
is '\0'
, not ' '
.
Note these further problems:
you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count);
only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans
to be divided by 2 3 = 8, instead of 3. = 6.
you should protect against buffer overflow and detect invalid input with:
if (scanf(" %199[^\n]", line);= 1) break;
the range of type int
for ans
is too small for a moderately large number of words: 13, is 6227020800, larger than INT_MAX
on most systems.
The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.
Here is a modified version using this approach:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmpstr(const void *p1, const void *p2) {
char * const *pp1 = p1;
char * const *pp2 = p2;
return strcmp(*pp1, *pp2);
}
unsigned long long factorial(int n) {
unsigned long long res = 1;
while (n > 1)
res *= n--;
return res;
}
int main() {
int T, i, n, begin, count;
unsigned long long ans;
char line[200];
char *words[100];
if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
return 1;
while (T --> 0) {
if (!fgets(line, sizeof line, stdin))
break;
n = 0;
begin = 1;
for (char *p = line; *p; p++) {
if (isspace((unsigned char)*p)) {
*p = '\0';
begin = 1;
} else {
if (begin) {
words[n++] = p;
begin = 0;
}
}
}
qsort(words, n, sizeof(*words), cmpstr);
ans = factorial(n);
for (i = 0; i < n; i += count) {
for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
continue;
ans /= factorial(count);
}
printf("%llu\n", ans);
}
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.