I have been trying to make a word puzzle(without using any library functions)like you would find in a newspaper like the following:
15 rows 12 colums
X T Z M Q Y K C E C F H -->12 chars
S H O U T E X O E A P I
X G T L Q B E L T N F K
'
'
'
as you can see in the second row there is the word SHOUT. Now the puzzle is designed so that the user can input any sort of char set they want line by line.
What I want to do is when a word is searched (like SHOUT) I would return its starting index. The index I imagined will start at 0 and end at 180, as 12*15=180 like this to be clear:
X T Z M Q Y K C E C F H
0 1 2 3 4 5 6 7 8 9 10 11
S H O U T E X O E A P I
12 13 14 15 16 17 18 19 20 21 22 23
'
'
'
'''''''''''''''''''179
Its hard to explain it without a picture, I hope you understand.
Now the tricky thing is words can be in every direction (up to down, down to up, left to right, right to left). I have written most of the code but keep getting errors and it only can check if the word exists from left to right.
#include <stdio.h>
#define COLUNM 12
#define ROW 15
int computeLength (char str[50]) {
int i;
for (i = 0; str[i] != '\0'; ++i) {
}
return i;
}
int findString(char matrix[ROW][COLUNM], char string[], int length) {
int i = 0, j, k = 0, searchlenght = 0;
length = computeLength(string);
for (j = 0; j < ROW; j++) {
if (matrix[j][k] == string[k]) {
searchlenght++;
}
}
i++;
if (searchlength == length) {
return i;
}
}
int main() {
int i, j = 0;
char matrix[ROW][COLUNM];
char string[50];
int b = 1;
for (i = 0; i < ROW; i++) {
printf("Enter line %d of the puzzle :\n", i + 1);
scanf("%s", &matrix[j][i]);
j++;
}
while (b > 0) {
printf("Enter the string to be searched in the puzzle:\n");
scanf("%s", &string[50]);
if ((string[0] != 'q') || (string[0] != 'Q')) {
b = 0;
}
}
return 0;
}
I don't think this is so hard to implement with python but I'm so unfamiliar with C that I keep getting errors and warnings.
Only part that needs work is findString function. Don't bother with input as I will test it myself.
Could you please help?
**The only part that does not work is length=computeLength(str1); thşs when I enter computeLength("Shout") it returns 5 but in this piece of code it returns 2 which messes up the result **
int findString(char matrix[ROW][COLUNM],char str1[],int length){
int i,j,wordcounting;
int true=1;
length=computeLength(str1);
printf("%d",length);
for(j=0;j<ROW;j++){
if(matrix[i][j]==str1[0]){
for(wordcounting=1;wordcounting<length;wordcounting++){
if((matrix[i][j+wordcounting]!=str1[wordcounting])){
true=0;
break;
}
}
}
i++;}
if(true==1){return (i-length);}
}
When I say printf("%d",computeLength(string)); even before ı input a string it becomes 2
Here is a loooooooog answer where I explain the more I can your problems, how to solve them, and finally how to implement the search step by step up to a final solution.
Have a good reading !
There a lot of problems in your code, first it cannot be compiled.
The line 29 is invalid, replace
int findString(char matrix[ROW][COLUNM],char string[15],int computeLength(string[15])){
by
int findString(char matrix[ROW][COLUNM], char string[15])
Note also the size 15 is useless you can use char string[] or char * string for the parameter string
The line 39 is invalid, replace
if(count==computeLength(string[15])){
by
if(count==computeLength(string)){
Now you can compile your program, but this not enough.
Some problems in main.
You exchanged the indexes in the line
scanf("%s",&matrix[j][i]);
It can be replaced by
scanf("%s",&matrix[i][0]);
(I used 0 rather than j because it is more clear, that does not ask us to check j values 0)
But this is not enough, scanf can read more than COLUNM characters if the input is invalid, and even the input is 12 characters as you expect you forget scanf will also write the null character finishing the string, so it writes 13 characters.
A way is to read in string which is longer than COLUMN more 2 and check the length of the input string. So your for can be replaced by :
for(i = 0 ; i < ROW ; i++)
{
printf("Enter line %d of the puzzle :\n",i+1);
if ((scanf("%49s", string) != 1) ||
(strlen(string) != COLUMN)) {
puts("invalid line");
return -1;
}
memcpy(&matrix[i][0], string, COLUMN);
i++;
}
Note also at the end i is incremented rather than j.
In the while loop
scanf("%s",&string[50]);
is invalid because it will place the result after string, the index must be 0 and in fact you can just give string.
As before if the input as more than 49 characters scanf will write out of string, so do
scanf("%49s", string);
If you want to allow to search a string of 50 characters without counting the final null character you have to size it with 51 and replace 49 by 50.
Out of printing and reading the while loop does nothing, it is very probable you wanted to call findString in it and to write the returned value, until the first read character is q or Q. For instance :
for (;;) {
puts("Enter the string to be searched in the puzzle:");
if ((scanf("%49s", string) != 1) || (string[0] =='q') || (string[0] == 'Q'))
break;
printf("position in the puzzle: %d\n", findString(matrix, string));
}
At the end of main the interest of that line is obscure :
printf("%d",computeLength("küfür"));
In printPuzzle you missed to introduce a newline after you print PUZZLE, you can just replace printf by puts. Note it is useless to ask printf to search for % etc while you know there is none.
In findString
A first problem is you only return a value if count==computeLength(string) is true, you need to always to return a value. Typically you can return -1 if the string is not in the puzzle, so
return (count==computeLength(string)) ? i : -1;
but this is wrong too, and for two reasons :
when you reach the test i always value 180, not the position where the string was
this is not because count==computeLength(string) is true that the string was found because of the way you used to increment count and the next error :
You do not search correctly the string in the puzzle because your first loop on i goes though the string (string[i]), and worst will access to 180 characters in it while its length is only 49 (without the final null character). You also do not stop to search even you find the string. And in your algorithm you forget the characters of string must be placed consecutively in the matrix, you each time you (wrongly) find a character of the string anywhere in the matrix you increment count.
Just considering you search the string horizontally from left to right :
The loop on string must be the more embedded loop to check its characters are consecutive in the matrix.
You have one loop on the row an one on the column, this is useless and just make the job complex for nothing. Because matrix is an array the character at matrix[r][COLUMN] is the character at matrix[r+1][0], that means you can go through matrix like it is a string of ROW*COLUMN characters.
I let you rewrite findString, it is like strstr except you return the index or -1 rather than the address of the substring or NULL
[edit with proposal for the search functions]
To explain I will use that small matrix more easy to look at :
#define COLUMN 3
#define ROW 5
char Matrix[ROW][COLUMN] = { { 'a', 'b' , 'c' },
{ 'd', 'e' , 'f' },
{ 'g', 'h' , 'i' },
{ 'j', 'k' , 'l' },
{ 'm', 'n' , 'o' } };
Let start with searching from left to right, this is similar to the classic strstr function except the return value and there is a rollback at the end of the matrix. Let decide the value is -1 if the string is not found else the position of its first character times 1000 more the position of its last character. The definition can be :
int search_left2right(char * matrix, char * word)
{
int i;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
char * w = word;
while (*w == matrix[j]) {
if (!*++w)
return i * 1000 + j;
if (++j == ROW*COLUMN)
j = 0;
}
}
return -1;
}
Compilation and execution with that main :
int main()
{
printf("%d\n", search_left2right((char *) Matrix, "cde"));
printf("%d\n", search_left2right((char *) Matrix, "noa"));
printf("%d\n", search_left2right((char *) Matrix, "cdf"));
return 0;
}
pi#raspberrypi:/tmp $ ./a.out
2004
13000
-1
pi#raspberrypi:/tmp $
2004 if for 2 and 4, 13000 if for 13 and 0, the string is not found in the last case, this is ok
Searching from right to left.
A first obvious way is to reuse the previous function and to reverse the string before to search it. In case the string is found in the result the position of the first and last characters are just reversed too.
An other way is to iterate on the string to search in the reverse order, let choose that way.
Searching from right to left or from left to right.
To indicate the direction the parameter wstep is added and values 1 for left to right, else -1. The definition can be :
/* manual strlen, you want to define all string functions */
int strLen(char * s)
{
char * p = s;
while (*p)
p += 1;
return p - s;
}
int search_horiz(char * matrix, char * word, int wstep)
{
int i;
int wbegin = (wstep == 1) ? 0 : strLen(word) - 1;
int wend = (wstep == 1) ? strLen(word) - 1 : 0;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
int k = wbegin;
while (word[k] == matrix[j]) {
if (k == wend)
return (wstep == 1) ? i * 1000 + j : j * 1000 + i;
k += wstep;
if (++j == ROW*COLUMN)
j = 0;
}
}
return -1;
}
Compilation and execution with that main :
int main()
{
printf("%d\n", search_horiz((char *) Matrix, "cde", 1));
printf("%d\n", search_horiz((char *) Matrix, "edc", -1));
printf("%d\n", search_horiz((char *) Matrix, "noa", 1));
printf("%d\n", search_horiz((char *) Matrix, "aon", -1));
printf("%d\n", search_horiz((char *) Matrix, "cdf", 1));
printf("%d\n", search_horiz((char *) Matrix, "fdc", -1));
return 0;
}
pi#raspberrypi:/tmp $ gcc -g -Wall m.c
pi#raspberrypi:/tmp $ ./a.out
2004
4002
13000
13
-1
-1
pi#raspberrypi:/tmp $
Searching from top to bottom.
When we search from left to right we compare the characters from to string with the consecutive characters in the matrix (step is 1), more the roll back.
To search from top to bottom we do not have to look consecutive characters in the matrix, we want to stay in the same vertical so the step is COLUMN. Of course this is not the case when we are on the last line, in that case we go back on the first line and move to the right, except from the last character of the matrix where we have to rollback to the first character. The definition can be :
int search_top2down(char * matrix, char * word)
{
int i;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
char * w = word;
while (*w == matrix[j]) {
if (!*++w)
return i * 1000 + j;
if ((j += COLUMN) >= ROW*COLUMN)
j = (j - ROW*COLUMN + 1) % COLUMN;
}
}
return -1;
}
Compilation and execution with that main :
int main()
{
printf("%d\n", search_top2down((char *) Matrix, "dgj"));
printf("%d\n", search_top2down((char *) Matrix, "knc"));
printf("%d\n", search_top2down((char *) Matrix, "oad"));
return 0;
}
pi#raspberrypi:/tmp $ gcc -g -Wall m.c
pi#raspberrypi:/tmp $ ./a.out
3009
10002
14003
pi#raspberrypi:/tmp $
Searching from left to right or from top to bottom
But comparing search_left2right and search_top2down we can see they have almost the same definition, the only change is the value of the step in the matrix and the correction when the step cannot be applied alone. So it is possible to have:
int search_left2right_top2down(char * matrix, char * word, int step, int correct)
{
int i;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
char * w = word;
while (*w == matrix[j]) {
if (!*++w)
return i*100 + j;
if ((j += step) >= ROW*COLUMN)
j = (j - ROW*COLUMN + correct) % COLUMN;
}
}
return -1;
}
To do left to right step is 1 and correct is 0, to do top to bottom step is COLUMN and correct is 1.
Searching in all the four directions
The needed modification to search from bottom to top from top to bottom are like it was to search right to left from left to right.
That means we can have easily only one search function managing left to right, right to left, top to bottom and bottom to top. For instance :
int search(char * matrix, char * word, int wstep, int step, int correct)
{
int i;
int wbegin = (wstep == 1) ? 0 : strLen(word) - 1;
int wend = (wstep == 1) ? strLen(word) - 1 : 0;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
int k = wbegin;
while (word[k] == matrix[j]) {
if (k == wend)
return (wstep == 1) ? i * 1000 + j : j * 1000 + i;
k += wstep;
if ((j += step) >= ROW*COLUMN)
j = (j - ROW*COLUMN + correct) % COLUMN;
}
}
return -1;
}
With that main compilation and execution :
int main()
{
printf("%d\n", search((char *) Matrix, "cde", 1, 1, 0));
printf("%d\n", search((char *) Matrix, "noa", 1, 1, 0));
printf("%d\n", search((char *) Matrix, "cdf", 1, 1, 0));
putchar('\n');
printf("%d\n", search((char *) Matrix, "edc", -1, 1, 0));
printf("%d\n", search((char *) Matrix, "aon", -1, 1, 0));
printf("%d\n", search((char *) Matrix, "fdc", -1, 1, 0));
putchar('\n');
printf("%d\n", search((char *) Matrix, "dgj", 1, COLUMN, 1));
printf("%d\n", search((char *) Matrix, "knc", 1, COLUMN, 1));
printf("%d\n", search((char *) Matrix, "oad", 1, COLUMN, 1));
putchar('\n');
printf("%d\n", search((char *) Matrix, "jgd", -1, COLUMN, 1));
printf("%d\n", search((char *) Matrix, "cnk", -1, COLUMN, 1));
printf("%d\n", search((char *) Matrix, "dao", -1, COLUMN, 1));
return 0;
}
pi#raspberrypi:/tmp $ gcc -Wall m.c
pi#raspberrypi:/tmp $ ./a.out
2004
13000
-1
4002
13
-1
3009
10002
14003
9003
2010
3014
pi#raspberrypi:/tmp $
Let notice to give the 3 parameters to indicate how to process is not a pretty way, I used them because I considered it was better to have them to explain, but because there are always the same it is easy to improve :
#include <stdio.h>
#define COLUMN 3
#define ROW 5
/* manual strlen, you want to define all string functions */
int strLen(const char * s)
{
const char * p = s;
while (*p)
p += 1;
return p - s;
}
typedef struct SearchParameters {
int wstep;
int step;
int correct;
} SearchParameters;
const SearchParameters Left2Right = { 1, 1, 0 };
const SearchParameters Right2Left = { -1, 1, 0 };
const SearchParameters Top2Bottom = { 1, COLUMN, 1 };
const SearchParameters Bottom2Top = { -1, COLUMN, 1 };
int search(const char * matrix, const char * word, SearchParameters how)
{
int i;
int wbegin = (how.wstep == 1) ? 0 : strLen(word) - 1;
int wend = (how.wstep == 1) ? strLen(word) - 1 : 0;
for (i = 0; i != ROW*COLUMN; ++i) {
int j = i;
int k = wbegin;
while (word[k] == matrix[j]) {
if (k == wend)
return (how.wstep == 1) ? i * 1000 + j : j * 1000 + i;
k += how.wstep;
if ((j += how.step) >= ROW*COLUMN)
j = (j - ROW*COLUMN + how.correct) % COLUMN;
}
}
return -1;
}
/* */
typedef struct TestCase {
const char * str;
const SearchParameters * how;
const char * strHow;
} TestCase;
void test(const char (*m)[3], const TestCase * tc)
{
int r = search((char *) m, tc->str, *(tc->how));
if (r == -1)
printf("cannot found '%s' in '%s'\n", tc->str, tc->strHow);
else
printf("'%s' found in '%s', start at %d, end at %d\n",
tc->str, tc->strHow, r / 1000, r % 1000);
}
int main()
{
static const char matrix[ROW][COLUMN] = { { 'a', 'b' , 'c' },
{ 'd', 'e' , 'f' },
{ 'g', 'h' , 'i' },
{ 'j', 'k' , 'l' },
{ 'm', 'n' , 'o' } };
static const TestCase tests[] = {
{ "cde", &Left2Right, "Left2Right" },
{ "noa", &Left2Right, "Left2Right" },
{ "cdf", &Left2Right, "Left2Right" },
{ "edc", &Right2Left, "Right2Left" },
{ "aon", &Right2Left, "Right2Left" },
{ "fdc", &Right2Left, "Right2Left" },
{ "dgj", &Top2Bottom, "Top2Bottom" },
{ "knc", &Top2Bottom, "Top2Bottom" },
{ "oad", &Top2Bottom, "Top2Bottom" },
{ "jgd", &Bottom2Top, "Bottom2Top" },
{ "cnk", &Bottom2Top, "Bottom2Top" },
{ "dao", &Bottom2Top, "Bottom2Top" }
};
int t;
for (t = 0; t != sizeof(tests) / sizeof(TestCase); t += 1)
test(matrix, &tests[t]);
return 0;
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -Wall mm.c
pi#raspberrypi:/tmp $ ./a.out
'cde' found in 'Left2Right', start at 2, end at 4
'noa' found in 'Left2Right', start at 13, end at 0
cannot found 'cdf' in 'Left2Right'
'edc' found in 'Right2Left', start at 4, end at 2
'aon' found in 'Right2Left', start at 0, end at 13
cannot found 'fdc' in 'Right2Left'
'dgj' found in 'Top2Bottom', start at 3, end at 9
'knc' found in 'Top2Bottom', start at 10, end at 2
'oad' found in 'Top2Bottom', start at 14, end at 3
'jgd' found in 'Bottom2Top', start at 9, end at 3
'cnk' found in 'Bottom2Top', start at 2, end at 10
'dao' found in 'Bottom2Top', start at 3, end at 14
pi#raspberrypi:/tmp $
Just looking at the compile error mentioned (and only the compile error), I suggest you do something like this:
int findString(char matrix[ROW][COLUNM],char string[15])
{
int length = computeLength(string);
...
}
You can't have the way you declared the function like what you did. Now slight further recommendation...
There is already a C function that can compute C string lengths:
#include <string.h>
...
const char* string = "hello";
int length = strlen(string);
...
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I had a quiz and I wrote this code:
Print Fizz if it is divisible by 3 and it prints Buzz if it is
divisible by 5. It prints FizzBuss if it is
divisible by both. Otherwise, it will print the numbers between 1 and 100.
But after I arrived home, I wondered if could have
writen it with less code. However, I could not come out
with a shorter code.
Can I do it with a shorter code? Thanks.
This is what I wrote and I think it works well. But can I have done it
with less code.
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=100; i++)
{
if(((i%3)||(i%5))== 0)
printf("number= %d FizzBuzz\n", i);
else if((i%3)==0)
printf("number= %d Fizz\n", i);
else if((i%5)==0)
printf("number= %d Buzz\n", i);
else
printf("number= %d\n",i);
}
return 0;
}
You could also do:
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=100; ++i)
{
if (i % 3 == 0)
printf("Fizz");
if (i % 5 == 0)
printf("Buzz");
if ((i % 3 != 0) && (i % 5 != 0))
printf("number=%d", i);
printf("\n");
}
return 0;
}
A few lines shorter, and a lot easier to read.
I'm not sure when you'd start calling it unreadable, but there's this.
#include <stdio.h>
int main(void)
{
int i = 1;
for (; i<=100; ++i) {
printf("number= %d %s%s\n", i, i%3?"":"Fizz", i%5?"":"Buzz");
}
return 0;
}
If a number is divisible by both 3 and 5, then it's divisible by 15, so:
for each number 1 to 100:
if number % 15 == 0:
print number, "fizzbuzz"
else if number % 5 == 0:
print number, "buzz"
else if number % 3 == 0:
print number, "fizz"
else:
print number
Other than that, you probably won't get it much shorter, at least in a conventional language like C (and I'm assuming you don't want the normal code-golf style modifications that make your code unreadable).
You could also get the whole thing into two lines if you packed the entire main function onto a single large line, but I would hope you wouldn't be after that sort of trickery either.
You can possibly get it faster (though you should check all performance claims for yourself) with something like:
static const char *xyzzy[] = {
"", "", "fizz", "", "buzz",
"fizz", "", "", "fizz", "buzz",
"", "fizz", "", "buzz", "fizzbuzz",
// Duplicate those last three lines to have seven copies (7x15=105).
};
for (int i = 1; i <= 100; i++)
printf ("%d %s\n", i, xyzzy[i-1]);
As an aside, that array of char pointers is likely to be less space-expensive than you think, thanks to constant amalgamation - in other words, it will be likely that there will only be one of each C string.
As I say, whether it's faster should be tested. In addition, your original specs only called for the shortest code so it may be irrelevant.
#include <stdio.h>
char const * template[] = {
"%i",
"Buzz",
"Fizz",
"FizzBuzz"
};
const int __donotuseme3[] = { 2, 0, 0 };
const int __donotuseme5[] = { 1, 0, 0, 0, 0 };
#define TEMPLATE(x) (template[__donotuseme3[(x) % 3] | __donotuseme5[(x) % 5]])
int
main(void) {
int i;
for (i = 1; i <= 100; i++) {
printf(TEMPLATE(i), i);
putchar('\n');
}
return 0;
}
I would say that modulo is expensive while comparisons are cheap so only perform the modulo once. That would yield something like this.
int i;
for( i = 0; i!=100; ++i ) {
bool bModThree = !(i % 3);
bool bModFive = !(i % 5);
if( bModThree || bModFive ) {
if( bModThree ) {
printf( "Fizz" );
}
if( bModFive ) {
printf( "Buzz" );
}
} else {
printf( "%d", i );
}
printf( "\n" );
}
This one avoids some code repetition but requires a temporary variable char t
void FizzBuzz( ) {
char t = 0;
for (unsigned char i = 1; i <= 100; ++i, t = 2) {
(i % 3) ? --t : printf("Fizz");
(i % 5) ? --t : printf("Buzz");
if (!t) printf("%d", i);
printf("\n");
}
}
i would write something like that
main(){
if (i % 3 == 0){
cout<<"Fizz";
}
if (i % 5 == 0){
cout<<"Buzz";
}
// So if both are true, it will print “FizzBuzz” and augment the two strings
}
I'd go with a helper function :-)
#include <stdio.h>
int fbindex(int n) {
int i = 0;
if (n % 3 == 0) i += 1;
if (n % 5 == 0) i += 2;
return i;
}
int main(void) {
const char *fb[] = {"%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n"};
for (int i = 1; i <= 100; i++) printf(fb[fbindex(i)], i);
}
void main()
{
int i = 0;
char h[4];
while (++i <= 100)
{
sprintf(h, "%d", i);
printf("%s%s%s\n", i%3 ? "" : "fizz", i%5 ? "" : "buzz", (i%3 && i%5) ? h: "");
}
}
You can do it using a String:
String s="";
if(num%3==0)
s+="fizz";
if(num%5==0)
s+="buzz";
if(s.length()==0)
s+=num+"";
Obfuscated form of Mr Lister's answer
main(int i){while(i++<100){printf("number= %d %s%s",i,i%3?"":"Fizz",i%5?"":"Buzz");}}