This is my code. My point is to take string input and count how many of each letter occurs
#include <stdio.h>
#include <ctype.h>
int main()
{
int c1;
int a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0, i=0, j=0, k=0, l=0, m=0, n=0, o=0, p=0, q=0, r=0, s=0, t=0, u=0, v=0, w=0, x=0 , y=0, z=0;
while (( c1=getchar()) != EOF)
if (isalpha(tolower(c1)) != 0) {
if (tolower(c1) == 97) { // Character = 'a'
a += 1;
}
else if (tolower(c1) == 98) { // Character = 'b'
b += 1;
}
else if (tolower(c1) == 99) { // Character = 'c'
c += 1;
}
.
.
.
}
return 0;
}
Next I want to printf result in vertical. Could you give me some hints. For example,
input: ABC---Ddhhh
output:
*
* *
**** *
abcdefghijklmnopqrstuvwxyz
While it may be a struggle learning, it's important to spend time learning and not simply copy/pasting lines of code to have a big program. The best code is the briefest code that achieves the objective.
As others have said, the contiguous alphabet should cause you to use a contiguous array of counters, not individual variables. (One typo and your results will be wrong.) Nesting isalpha(tolower(c)) is not needed. And, you've shown how you might count, but not shown code that would output the desired results.
This is for you to study, learn and grow as a coder.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Try to write functions; blocks of code that do what you want in compartments
void countAndGraph( char *str ) {
int max = 0, cnt[26] = { 0 }; // initialises 'max' and 26 counters
for( char *p = str; *p; p++ ) // as long as there is a character
if( isalpha( *p ) ) { // if it is alphabetic
int i = tolower( *p ) - 'a'; // convert ASCII character to value 0-25
if( ++cnt[ i ] > max ) // increment the right counter and test against max
max = cnt[ i ]; // 'max' - the ceiling - keeps getting higher
}
for( ; max; max-- ) { // lower the ceiling
for( int i = 0; i < 26; i++ ) // for 26 alphabetic characters
putchar( " *"[cnt[i]>=max] ); // output ' ' or '*' if count at/above ceiling
putchar( '\n' ); // newline
}
puts( "abcdefghijklmnopqrstuvwxyz" ); // reference alphabet string
puts( str ); // the string that's been analysed
puts( "" );
}
int main() {
char *tst[] = { // three test strings to demonstrate
"The quick brown fox jumps over the lazy dogs",
"Sally sells seashells by the sea shore",
"I wish I was what I was when I wished I was what I am now",
};
const size_t nTst = sizeof tst/sizeof tst[0];
for( size_t i = 0; i < nTst; i++ ) // count and graph each of the strings
countAndGraph( tst[i] );
return 0;
}
*
* *
* * * ****
**************************
abcdefghijklmnopqrstuvwxyz
The quick brown fox jumps over the lazy dogs
*
*
* * *
* * *
* * *
* * * * *
* * * * * *
** * * * * *** *
abcdefghijklmnopqrstuvwxyz
Sally sells seashells by the sea shore
*
* *
* *
* * *
* ** * *
* ** * *
* ** * *
* * ** * ** *
* ** ** *** ** *
abcdefghijklmnopqrstuvwxyz
I wish I was what I was when I wished I was what I am now
Now that you have this code, an exercise would be to print the bar graph in ascending/descending order. Don't stop with this one version; push it to a new educational experience.
*
*
*
*
**
***
****
*********
*************
**************
****************
*****************
******************
fzcxqpjkuvywnbmdgrloshiate
'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
Any time you have more than one or two variables that do the same thing, it is time to use a data structure; in this case, an array. You will want something like
int counts[26];
instead of twenty six different variables, and only have one statement instead of 26 different if clauses. Then you can say
counts[lower(c1) - 97]
instead of a, b... z (after checking that lower(c1) is one of the letters).
The way to print the output is based on these insights:
The number of lines above the alphabet is the highest number in counts (let's call it maxcount). It would be 3 in your example.
For each line, there is a * if that letter's count is at least maxcount - line (i.e. in 0th line, there is a * if there is at least 3 - 0 counts of that character), otherwise there's a space.
I think you can just print one at a time.
#include <stdio.h>
#include <ctype.h>
int main()
{
int c1;
int a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0, i=0, j=0, k=0, l=0, m=0, n=0, o=0, p=0, q=0, r=0, s=0, t=0, u=0, v=0, w=0, x=0 , y=0, z=0;
// I might do an array here, so you can loop through later.
int letters[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
while (( c1=getchar()) != EOF) {
if (isalpha(tolower(c1)) != 0) {
if (tolower(c1) == 97) { // Character = 'a'
a += 1;
letters[0]++;
}
else if (tolower(c1) == 98) { // Character = 'b'
b += 1;
letters[1]++;
}
else if (tolower(c1) == 99) { // Character = 'c'
c += 1;
letters[2]++;
}
.
.
.
}
}
int ii;
for (ii = 0; ii < 26; ii++) {
printf("%d\n", letters[ii]);
}
return 0;
}
Related
I have a problem question and a snippet code below. The snippet is filled already because I found out the solution but I do not understand why it is like that. Could you help me explain how the codes work?
Problem: Ten tiles each have strings of in between 1 and 4 letters on them (hardcoded in the code below). The goal of this problem is to complete the code below so it counts the number of different orders in which all of the tiles can be placed such that the string they form creates a palindrome (a word that reads the same forwards and backwards). All of main, as well as the function eval which determines if a particular ordering of the tiles forms a palindrome. You may call this function in the function go. Complete the recursive function (named go) to complete the solution.
Snippet code:
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
int go(int perm[], int used[], int k, char tiles[N][MAXLEN]);
int eval(int perm[], char tiles[N][MAXLEN]);
char MYTILES[N][MAXLEN] = {
"at", "ta", "g", "cc", "ccac", "ca", "cc", "gag", "cga", "gc"
};
int
main(void)
{
int perm[N];
int used[N];
for (int i = 0; i < N; i++)
used[i] = 0;
int res = go(perm, used, 0, MYTILES);
printf("Number of tile orderings that create palindromes is %d\n", res);
return 0;
}
int
go(int perm[], int used[], int k, char tiles[N][MAXLEN])
{
if (k == N)
return eval(perm, tiles);
int res = 0;
for (int i = 0; i < N; i++) {
if (used[i])
continue;
used[i] = 1;
perm[k] = i;
res += go(perm, used, k + 1, tiles);
used[i] = 0;
}
return res;
}
int
eval(int perm[], char tiles[N][MAXLEN])
{
char tmp[N * MAXLEN];
int idx = 0;
for (int i = 0; i < N; i++) {
int len = strlen(tiles[perm[i]]);
for (int j = 0; j < len; j++)
tmp[idx++] = tiles[perm[i]][j];
}
tmp[idx] = '\0';
for (int i = 0; i < idx / 2; i++)
if (tmp[i] != tmp[idx - 1 - i])
return 0;
return 1;
}
Thank you. I appreciate all help!!
To understand this code, add the following line to the start of eval():
for( int j = 0; j < N; j++ ) printf( "%d ", perm[j] ); putchar('\n');
The for() loop in go() causes a recursion that is 10 levels deep, ultimately generating 10! (~3.6 million) permutations of the 10 indices from 0 to 9. In sequence, each of those permutations is used to concatenate the 'tokens' (the short ACTG variations) into a single string that is then tested for being palindromic by `eval()'
This is called a "brute force" search through the possibility space.
Below I've revised the code to be slightly more compact, adding two "printf debugging" lines (marked "/**/") that report what the program is doing. You'll need some patience if you wish to watch millions of permutations of 0 to 9 scroll by, or simply comment out that line and recompile. I also shuffled things around and made the two interesting arrays global instead of "whacking the stack" by passing them up/down the recursion. Less code is better. This program is "single purpose". The clarity gained justifies using global variables in this instance, imho.
More interesting is the additional puts() line that reports the palindromic sequences.
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
char MYTILES[N][MAXLEN] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
int perm[N], used[N] = { 0 };
int go( int k ) {
if (k == N) {
// At extent of recursion here.
/**/ for( int j = 0; j < k; j++ ) printf( "%d ", perm[j] ); putchar('\n');
// Make a string in this sequence
char tmp[N*MAXLEN] = {0};
for( int i = 0; i < N; i++ )
strcat( tmp, MYTILES[ perm[ i ] ] );
// Test string for being palidromic
for( int l = 0, r = strlen( tmp ) - 1; l <= r; l++, r-- )
if( tmp[l] != tmp[r] )
return 0; // Not palidrome
/**/ puts( tmp );
return 1; // Is palidrome
}
// recursively generate permutations here
int res = 0;
for( int i = 0; i < N; i++ )
if( !used[i] ) {
used[i] = 1;
perm[k] = i;
res += go( k+1 );
used[i] = 0;
}
return res;
}
int main( void ) {
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}
An immediate 'speed-up' would be to test that the first letter of the 0th string to be permuted matches the last letter of the 9th string... Don't bother concatenating if a palindrome is impossible from the get-go. Other optimisations are left as an exercise for the reader...
BTW: It's okay to make a copy of code and add your own print statements so that the program reports what it is doing when... Or, you could single-step through a debugger...
UPDATE
Having added a preliminary generation of a 10x10 matrix to 'gate' the workload of generating strings to be checked as palindromic, with the 10 OP supplied strings, it turns out that 72% of those operations were doomed to fail from the start. Of the 3.6 million "brute force" attempts, a quick reference to this pre-generated matrix prevented about 2.6 million of them.
It's worthwhile trying to make code efficient.
UPDATE #2:
Bothered that there was still a lot of 'fat' in the execution after trying to improve on the "brute force" in a simple way, I've redone some of the code.
Using a few extra global variables (the state of processing), the following now does some "preparation" in main(), then enters the recursion. In this version, once the string being assembled from fragments is over half complete (in length), it is checked from the "middle out" if it qualifies as being palindromic. If so, each appended fragment causes a re-test. If the string would never become a palindrome, the recursion 'backs-up' and tries another 'flavour' of permutation. This trims the possibility space immensely (and really speeds up the execution.)
char *Tiles[] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char buildBuf[ 1024 ], *cntrL, *cntrR; // A big buffer and 2 pointers.
int fullLen;
int cntTested, goCalls; // some counters to report iterations
uint32_t factorial( uint32_t n ) { // calc n! (max 12! to fit uint32_t)
uint32_t f = 1;
while( n ) f *= n--;
return f;
}
int hope() { // center outward testing for palindromic characteristics
int i;
for( i = 0; cntrL[ 0 - i ] == cntrR[ 0 + i ]; i++ ) ; // looping
return cntrR[ 0 + i ] == '\0';
}
int go( int k ) {
goCalls++;
if( k == nTiles ) { // at full extent of recursion here
// test string being palindromic (from ends toward middle for fun)
cntTested++;
for( int l = 0, r = fullLen - 1; l <= r; l++, r-- )
if( buildBuf[l] != buildBuf[r] )
return 0; // Not palindrome
/**/ puts( buildBuf );
return 1; // Is palindrome
}
// recursively generate permutations here
// instead of building from sequence of indices
// this builds the (global) sequence string right here
int res = 0;
char *at = buildBuf + strlen( buildBuf );
for( int i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
// keep recursing until > half assembled and hope persists
if( at < cntrL || hope() ) {
used[i] = 1;
res += go( k+1 ); // go 'deeper' in the recursion
used[i] = 0;
}
}
return res;
}
int main( void ) {
for( int i = 0; i < nTiles; i++ )
fullLen += strlen( Tiles[i] );
if( fullLen % 2 == 0 ) // even count
cntrR = (cntrL = buildBuf + fullLen/2 - 1) + 1; // 24 ==> 0-11 & 12->23
else
cntrR = cntrL = buildBuf + fullLen/2; // 25 ==> 0-12 & 12->24
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
printf( "Potential: %d\n", factorial( nTiles ) );
printf( "Calls to go(): %d\n", goCalls );
printf( "Actual: %d\n", cntTested );
return 0;
}
ATCCACGAGCCGCCGAGCACCTA
ATCCACGAGCCGCCGAGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
TACCACGAGCCGCCGAGCACCAT
TACCACGAGCCGCCGAGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
CCACATGAGCCGCCGAGTACACC
CCACATGAGCCGCCGAGTACACC
CCACATGCCGAGAGCCGTACACC
CCACATGCCGAGAGCCGTACACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGCCGAGAGCCGATCACC
CCACTAGCCGAGAGCCGATCACC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
Palindromic tile orderings: 32
Potential: 3628800
Calls to go(): 96712
Actual: 32
UPDATE #3 (having fun)
When there's too much code, and an inefficient algorithm, it's easy to get lost and struggle to work out what is happening.
Below produces exactly the same results as above, but shaves a few more operations from the execution. In short, go() is called recursively until at least 1/2 of the candidate string has been built-up. At that point, hope() is asked to evaluate the string "from the middle, out." As long as the conditions of being palindromic (from the centre, outward) are being met, that evaluation is repeated as the string grows (via recursion) toward its fullest extent. It is the "bailing-out early" that makes this version far more efficient than the OP version.
One further 'refinement' is that the bottom of the recursion is found without an extra call to \0. Once one has the concepts of recursion and permutation, this should all be straight forward...
char *Tiles[] = { "AT", "TA", "G", "CC", "CCAC", "CA", "CC", "GAG", "CGA", "GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char out[ 1024 ], *cntrL, *cntrR;
int hope() { // center outward testing for palidromic characteristics
char *pL = cntrL, *pR = cntrR;
while( *pL == *pR ) pL--, pR++;
return *pR == '\0';
}
int go( int k ) {
int res = 0;
char *at = out + strlen( out );
for( size_t i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
if( at >= cntrL && !hope() ) // abandon this string?
continue;
if( k+1 == nTiles ) { // At extent of recursion here.
puts( out );
return 1;
}
used[i] = 1, res += go( k+1 ), used[i] = 0;
}
return res;
}
int main( void ) {
int need = 0;
for( size_t i = 0; i < nTiles; i++ )
need += strlen( Tiles[ i ] );
cntrL = cntrR = out + need/2; // odd eg: 25 ==> 0-12 & 12->24
cntrL -= (need % 2 == 0 ); // but, if even eg: 24 ==> 0-11 & 12->23
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}
I am working on a string search and replace project. I can only change 1 of the target pattern in the sentence. But I can find both.
Example: just do it. you will do it.
find: do
replace: think
expected---> just think it. you will think it.
what actually happened ---> just do it. you will think it.
How can I replace both of them?
I read the sentence from file input.txt
# include <limits.h>
# include <string.h>
# include <stdio.h>
#include <sys/time.h>
# define NO_OF_CHARS 256
# define MAX 10000
int sum = 0;
int control = 0;
// A utility function to get maximum of two integers
int max (int a, int b) { return (a > b)? a: b; }
// The preprocessing function for Boyer Moore's bad character heuristic
void badCharHeuristic( char *str, int size, int badchar[NO_OF_CHARS]) {
int i;
// Initialize all occurrences as -1
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
// Fill the actual value of last occurrence of a character
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
/* A pattern searching function that uses Bad Character Heuristic of Boyer Moore Algorithm */
void search( char *txt, char *pat,char temp3[MAX],int k,char*r) {
int m = strlen(pat);
int n = strlen(txt);
char src[MAX],p[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int badchar[NO_OF_CHARS],i,leng,l,count;
char v;
/* Fill the bad character array by calling the preprocessing function badCharHeuristic() for given pattern */
badCharHeuristic(pat, m, badchar);
leng = strlen(pat);
strcpy(tempP,r);
//strcat(tempP,"</mark>");
leng = strlen(pat);
l = strlen(txt);
int s = 0; // s is shift of the pattern with respect to text
while(s <= (n - m)) {
int j = m-1;
/* Keep reducing index j of pattern while characters of pattern and text are matching at this shift s */
while(j >= 0 && pat[j] == txt[s+j]) {
count++;
j--;
}
/* If the pattern is present at current shift, then index j will become -1 after the above loop */
if (j < 0) {
//printf("pattern occurs at shift = %d\n", s);
/* Shift the pattern so that the next character in text
aligns with the last occurrence of it in pattern.
The condition s+m < n is necessary for the case when
pattern occurs at the end of text */
printf("The desired pattern was found starting from %d. line at position %d\n",k,s+1);
strncpy(temp, txt, s);
temp[s] = '\0';
//strcat(temp,"<mark>");
control++;
strcat(temp,tempP);
for(i=0;i<MAX;i++) {
if((s+leng+i)<strlen(txt))
temp2[i] = txt[s+leng+i];
else
temp2[i] = v;
}
strcat(temp,temp2);
strcpy(temp3,temp);
s += (s+m < n)? m-badchar[txt[s+m]] : 1;
}
else
/* Shift the pattern so that the bad character in text
aligns with the last occurrence of it in pattern. The
max function is used to make sure that we get a positive
shift. We may get a negative shift if the last occurrence
of bad character in pattern is on the right side of the
current character. */
s += max(1, j - badchar[txt[s+j]]);
}
sum +=count;
}
/* Driver program to test above funtion */
int main() {
char txt[MAX],p[MAX],r[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int k = 1;
FILE *input = fopen("input.txt","r");
FILE *output = fopen("output.txt","w");
printf("Enter the text in which pattern is to be searched:");
fgets(p, MAX, stdin);
printf("Enter the text in which pattern is to be replaced:");
fgets(r, MAX, stdin);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
p[strlen(p)-1]='\0';
temp[1]='a';
while(!feof(input)){
if(fgets (txt, MAX, input)!=NULL) {
txt[strlen(txt)-1] = '\0';
search(txt, p,temp,k,r);
if(temp[1]!='a') {
fprintf(output,"%s\n",temp);
temp[1]='a';
}
else
fprintf(output,"%s\n",txt);
}
k++;
}
if(control==0) {
printf("\nThe pattern was not found in the given text\n\n");
}
gettimeofday(&tv2, NULL);
printf ("Total time = %f seconds\n", (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 + (double) (tv2.tv_sec - tv1.tv_sec));
fclose(input);
fclose(output);
printf("The number of character comparison: %d\n",sum);
return 0;
}
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);
...
What am I doing right? I am trying to learn a function.
This should be like this output:
*
***
*****
*******
My code:
#include <stdio.h>
#include <stdlib.h>
void pyramid (int n)
{
int width = 0;
if ( n )
{
++width;
pyramid( f, n - 1 );
for ( unsigned int i = 0; i < 2 * n - 1; i++ )
{
fprintf( f, "%*c", i == 0 ? width : 1, '*' );
}
fputc( '\n', f );
--width;
}
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
printf ("usage: h4 <number>\n");
return 1;
}
pyramid (atoi (argv[1]));
return 0;
}
OUTPUT:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
Traceback (most recent call last):
File "python", line 4
void pyramid (int n) {
^
SyntaxError: invalid syntax
Why is this problem? Please help me and explain. Thank you. I'm deaf C programmer beginner.
Another way to approach outputting the pyramid (centered) would be to use the field width modifier for your printf format string for the padding rather than the fill character itself. Then you can simply loop outputting the number of characters needed per line (which increases by 2 each line, e.g. 1, 3, 5, ...).
For example, taking the number of lines of output as the first argument to your program, (or using 4 by default if no argument is given), you could do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#define FILL '*'
void pyramid (int n)
{
if (n < 1) /* validate positive value */
return;
int l = 1, /* initial length of fill chars */
max = n * 2 - 1, /* max number of fill chars */
pad = max / 2; /* initial padding to center */
for (int i = 0; i < n; i++) { /* loop for each line */
if (pad) /* if pad remains */
printf ("%*s", pad--, " "); /* output pad spaces */
for (int j = 0; j < l; j++) /* output fill chars */
putchar (FILL);
putchar ('\n'); /* output newline */
l += 2; /* increment fill by 2 */
}
}
int main (int argc, char **argv) {
int n = argc > 1 ? (int)strtol (argv[1], NULL, 0) : 4;
pyramid (n);
return 0;
}
(note: you can use unsigned types throughout to insure positive values, or you can simply validate you have positive values. You should also include errno.h and validate the strtol conversion, though it will return 0 if no digits are provided)
It also helps to #define your fill character at the top of the code, so you have a convenient place for change should you want another character. It prevents digging through your function to find the constant later on.
Example Use/Output
$ ./bin/pyramidtop 1
*
$ ./bin/pyramidtop 5
*
***
*****
*******
*********
$ ./bin/pyramidtop 10
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
Disregarding for a minute how you seem to be running it with python, you are recursively calling the funtion here:
pyramid( f, n - 1 );
However, you only have it defined with one parameter, not with two.
Also, f is undefined.
Your file is a C file, try to compile it with gcc, not executing it with python
And you have some f variable that is not declared used, you can correct this:
#include <stdio.h>
#include <stdlib.h>
void pyramid (FILE *f, int n) {
int width = 0;
if ( n )
{
++width;
pyramid(f, n - 1 );
for ( unsigned int i = 0; i < 2 * n - 1; i++ )
{
fprintf( f, "%*c", i == 0 ? width : 1, '*' );
}
fputc( '\n', f );
--width;
}
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
printf ("usage: h4 <number>\n");
return 1;
}
pyramid (stdout, atoi (argv[1]));
return 0;
}
Will give
*
***
*****
Your code can be updated to add spaces before stars and simplified:
Use clear variable names (stars instead of n)
2. Do not use fprintf where a simple fputc is enough
One variable is used to count stars, use one other to count spaces.
Will this consideration, your code should look like:
#include <stdio.h>
#include <stdlib.h>
/* use clear variable names */
void pyramid (FILE *f, int stars, int spaces) {
if ( stars>0 )
{
pyramid(f, stars -2, spaces + 1 );
for ( unsigned int i = 0; i < spaces; i++ )
{
/* use fputc when enough */
fputc(' ', f );
}
for ( unsigned int i = 0; i < stars; i++ )
{
fputc('*', f );
}
fputc( '\n', f );
}
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
printf ("usage: h4 <number>\n");
return 1;
}
pyramid (stdout, atoi (argv[1]), 0);
return 0;
}
It gives:
*
***
*****
I wrote a much shorter, simpler version, using the formatting features of printf
#include <stdio.h>
int main(void) {
int height = 15;
char s[2*height-1];
memset(s,'*',2*height-1);
for(int i = 0; i<height; ++i)
{
printf("%*.*s\n", height+i,2*i+1,s);
}
return 0;
}
Output
Success #stdin #stdout 0s 9424KB
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*********************
***********************
*************************
***************************
*****************************
I don't know what is the matter.. it works great when I run on my pc but when I submit in uva OJ it says time limit exceeded please help
Here is my solution:
#include <stdio.h>
int main()
{
long int i,j,c,t,k,u,r;
scanf("%d %d",&i,&j);
printf("%d %d",i,j);
r = 0;
if(i>j){
t = i;
i = j;
j = t;
}
for(k = i; k<=j;k++){
c = 1;
u = k;
while(u>1){
if(u%2 == 0)
u = u/2;
else
u = 3*u+1;
c++;
if(c>=r)
r = c;
}
}
printf (" %d",r);
return 0;
}
The following code, on my ubuntu Linux 14.04 takes about 1 second to run, when invoked via:
./untitled > outfile.txt
so perhaps this could be useful.
Note: this will have to be modified significantly for the euler problem
Note: the problem says "UNDER" 1 million, but this code starts at 1 million rather than starting at 999999
// Longest Collatz sequence
// Problem 14
/*
* criteria
* The following iterative sequence is defined for the set of positive integers:
* n → n/2 (n is even)
* n → 3n + 1 (n is odd)
*
* example:
* Using the rule above and starting with 13, we generate the following sequence:
* 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
* It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms.
* Although it has not been proved yet (Collatz Problem),
* it is thought that all starting numbers finish at 1.
*
* the question:
* Which starting number, under one million, produces the longest chain?
*
* Note:
* Once the chain starts the terms are allowed to go above one million.
*/
#include <stdio.h>
// prototypes
void fastWrite( size_t a );
int main( void )
{
#define MAX_START_VALUE (1000000)
size_t LongestChain = 0;
size_t LongestStartValue = 0;
for( size_t i=MAX_START_VALUE; i; i--)
{
size_t chainLength = 0;
size_t result = i;
// for debug
char buffer[] = "current start value:";
for( size_t j=0; buffer[j]; j++) putchar_unlocked( buffer[j] );
putchar_unlocked( ' ');
fastWrite( i );
// end debug
while( result != 1 )
{
chainLength++;
if( result&1 )
{ // then odd
result = 3*result +1;
}
else
{ // else even
result >>= 1;
}
// for debug
//./fastWrite( result );
// end debug
}
chainLength++;
// for debug
char buffer2[] = "chain length: ";
for( size_t k=0; buffer2[k]; k++) putchar_unlocked( buffer2[k] );
fastWrite( chainLength );
putchar_unlocked( '\n' );
// end debug
if ( chainLength > LongestChain )
{
LongestChain = chainLength;
LongestStartValue = i;
}
}
fastWrite( LongestStartValue );
putchar_unlocked('\n');
//putchar_unlocked('\n');
} // end function: main
inline void fastWrite(size_t a)
{
char snum[20];
//printf( "%s, %lu\n", __func__, a );
int i=0;
do
{
// 48 is numeric character 0
snum[i++] = (char)((a%10)+(size_t)48);
a=a/10;
}while(a>0);
i=i-1; // correction for overincrement from prior 'while' loop
while(i>=0)
{
putchar_unlocked(snum[i--]);
}
putchar_unlocked('\n');
} // end function: fastWrite
Just to be helpful with the time taken:
the following are good ways to speed up the I/O
#include <stdio.h>
void fastRead( size_t *a );
void fastWrite( size_t a );
inline void fastRead(size_t *a)
{
int c=0;
// note: 32 is space character
while (c<33) c=getchar_unlocked();
// initialize result value
*a=0;
// punctuation parens, etc are show stoppers
while (c>47 && c<58)
{
*a = (*a)*10 + (size_t)(c-48);
c=getchar_unlocked();
}
//printf( "%s, value: %lu\n", __func__, *a );
} // end function: fastRead
inline void fastWrite(size_t a)
{
char snum[20];
//printf( "%s, %lu\n", __func__, a );
int i=0;
do
{
// 48 is numeric character 0
snum[i++] = (char)((a%10)+(size_t)48);
a=a/10;
}while(a>0);
i=i-1; // correction for overincrement from prior 'while' loop
while(i>=0)
{
putchar_unlocked(snum[i--]);
}
putchar_unlocked('\n');
} // end function: fastWrite
and output characters via:
putchar_unlocked( char );
and always have a final, at end of each test case, the following line:
putchar_unlocked( '\n' );
to input a string of characters, call the following in a loop until a space or newline is encountered
char = getchar_unlocked()
and a final hint: most such problems are easily solved using size_t numeric values, which allows values to 4gig or more. (same as a unsigned long int)
For the current problem. as soon as a chain is calculated, save the chain, perhaps in an array, so you do not have to calculate it again.
Your could pre-calculate the first 'x' chains, say the first 10 for instance, to help with shortening the execution time.