I've been sitting on a code for almost ten days right now. I am writing a funtion that get two pointers for 2 different strings, and the function need to return 1 if there is the same number of words, or 0 if there isnt.
I am not allowed to use any lib, global or static int etc, no loops, only recursion, not allowed to change the signature of the function. what I wrote is the delta between the two sentences. First my code calculates the sum of words in the first sentence, when it gets to the '\0' of the first sentence, it starts to work on the second sentence, and substract each time there is a word. right now the output of my funtion is the delta, I want somehow to tell the function that if the delta ("the return") is 0 return 1, else return 1.
"
int same_num_words(char *s1, char *s2)
{
printf("%s\n", s1);
printf("%s\n", s2);
if(s1[0]=='\0' && s2[0] == '\0')
{
return 0;
}
if (s1[0] == '\0' ) // AFTER first sentence is complete, substract the second sentence count.
{
if(s2[0]!= ' ' && s2[1]== ' ')
{
return same_num_words(s1, s2+1) -1 ;
}
if(s2[0]!= ' ' && s2[1]== '\0')
{
return same_num_words(s1, s2+1)-1;
}
return same_num_words(s1, s2+1);
}
if(s1[0]!='\0') // first sentence
{
if((s1[0]!= ' ' && s1[1]== ' ') || (s1[0]!= ' ' && s1[1]== '\0') ) // first sentence
{
return same_num_words(s1+1, s2)+1;
}
}
return same_num_words(s1+1, s2);
}
"
any help?
Each character is either a letter or delimiter ('\0' or whitespace: space, \n \t, etc)
1 - Any leading whitespace is irrelevant, so skip over those.
2 - If code is at the end of either string, we are done.
3 - Since each string now begins with a letter, see it the next character is also a letter.
int same_num_words(const char *s1, const char *s2) {
// printf("'%s' ", s1);
// printf("'%s'\n", s2);
if (s1[0] == ' ') return same_num_words(s1 + 1, s2);
if (s2[0] == ' ') return same_num_words(s1, s2 + 1);
if (s1[0] == '\0' && s2[0] == '\0') return 1; // same
if (s1[0] == '\0') return 0; // differ
if (s2[0] == '\0') return 0;
// Both s1,s2 begin with a letter (non-delimiter)
// If the next character is also a letter, skip over the current one.
// as code is looking for the end-of-word.
if (!(s1[1] == '\0' || s1[1] == ' ')) return same_num_words(s1+1, s2);
if (!(s2[1] == '\0' || s2[1] == ' ')) return same_num_words(s1, s2+1);
return same_num_words(s1+1, s2+1);
}
Expand s1[0] == ' ' to s1[0] == ' ' || s1[0] == '\t' || ... as needed.
A key change from OP code was skipping leading spaces first as that consumes the string's leading and trailing spaces.
For fun, a cleaner looking implementation with typically fewer recursions.
int same_num_words(const char *s1, const char *s2) {
int sp1 = *s1 == ' ';
int sp2 = *s2 == ' ';
if (sp1 | sp2) return same_num_words(s1 + sp1, s2 + sp2);
int nc1 = *s1 == '\0';
int nc2 = *s2 == '\0';
if (nc1 | nc2) return nc1 & nc2;
// Both s1,s2 begin with a letter (non-delimiter)
// How about the next character?
int nxt_let1 = !(s1[1] == '\0' || s1[1] == ' ');
int nxt_let2 = !(s2[1] == '\0' || s2[1] == ' ');
if (nxt_let1 | nxt_let2) return same_num_words(s1 + nxt_let1, s2 + nxt_let2);
return same_num_words(s1 + 1, s2 + 1);
}
This solution obeys the letter of the rules (although I did add some const). It overloads the meaning of same_num_words to return the number of words in the string if either of the arguments is NULL. The second argument is NULL if the previous character read (if any) was space, and the first argument NULL if we've just read a word character.
int same_num_words(const char *s1, const char *s2) {
if (!s1 || !s2) {
const char *s = s1 ? s1 : s2;
if (*s == '\0') return !s1;
if (*s == ' ') return !s1 + same_num_words(s + 1, 0);
return same_num_words(0, s + 1);
}
return same_num_words(s1, 0) == same_num_words(s2, 0);
}
Here's some unit tests to check the implementation.
#include <assert.h>
#include <stdio.h>
int main(int argc, char **argv) {
struct {
const char *word1;
const char *word2;
int want;
} cases[] = {
{"This is a test", "one two three four", 1},
{"", "", 1},
{"one", "", 0},
{" one two three ", "one two three", 1},
{"one two three ", "one two three", 1},
{"one two three ", "one two three four", 0},
{" ", "", 1},
};
int failed = 0;
for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
int got = same_num_words(cases[i].word1, cases[i].word2);
if (got != cases[i].want) {
printf("same_num_words('%s', '%s') = %d, want %d\n", cases[i].word1, cases[i].word2, got, cases[i].want);
failed = 1;
}
got = same_num_words(cases[i].word2, cases[i].word1);
if (got != cases[i].want) {
printf("same_num_words('%s', '%s') = %d, want %d\n", cases[i].word2, cases[i].word1, got, cases[i].want);
failed = 1;
}
}
assert(!failed);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With