Input format: The first line of input gives the number the input strings (without spaces and of maximum 100 length
and in lowercase). Then there is following n lines, each containing a string.
Output format: N lines of output, each line has either YES or NO following by newline. (YES if string is a magic square palindrome otherwise NO)
Sample Input:
4
satorarepotenetoperarotas
aba
abba
abcabacba
Sample Output:
YES
NO
YES
NO
So i have written the following code.But in my program the output gets displayed immediately after the input and it takes only one input at a time.
PS:If you have any suggestions on how to make the code more efficient,please add them in your answer.Thanks
#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{ int num_input,l;
scanf("%d",&num_input);
for(l=0;l<num_input;l++)
{
char str[100];
char i = 0;
int sq,j,k;
scanf("%s", str);
while(str[i]!='\0')
{
++i;
}
sq = sqrt(i);
if(i== sq*sq)
{
if(i%2==0)
{
for(j=0;j<=i/2;j++)
{
if((str[j]==str[i-j-1])&&(str[j+sq]==str[i-j-sq-1]))
{
if(j==i/2)
{
printf("YES\n");
}
}
else
{ if(j==i/2)
{
printf("NO\n");
}
}
}
}
if(i%2!=0)
{
for(k=0;k<=i/2;k++)
{
if((str[k]==str[i-k-1])&&(str[k+sq]==str[i-k-sq-1]))
{ if(k==i/2)
{
printf("YES\n");
}}
else
{if(j==i/2)
{
printf("NO\n");
}}
}
}
}
else
{
printf("NO\n");
}
}
return 0;
}
The problem of 'mixed' output and input is caused by the fact, that you take one string per calculation. If you want to scan the whole input, then display the output, you should... do exactly that. Simple approach how to do it, given that you know how many strings will be typed:
After you scan the number of strings with int num_input; scanf("%d",&num_input);, you can create a two-dimensional array of characters sized as [num_input][max_str_length]. From your code, I assume that maximal length of each individual string is 100 (given char str[100];).
Then, in a for loop, that loops num_input times, you should scan all your strings and place them in the proper places in your 2D array. This way, your input is stored and ready to be checked by an algorithm. I would encourage you to, instead of writing plain algorith inside of main function, create a function that will take an array and it's size as arguments and return true or 1 when given array contains a string that is a "magic square palindrome" or return false / 0 when it's not. If you do that, you can just loop num_input times again and call your function on currently checked array. Each time the fucntion returns true, you output "YES", otherwise "NO"/
If you don't know anything about 2D arrays and/or making functions yourself, I encourage you to either buy a good C book, or simple google some tutorials, because that stuff is pretty basic and fairly easy to understand.
Related
I made a program that reads the output from a text file line by line and puts it into an array. So I got an array of strings.
The problem arises when I go through that array of strings and check if those strings meet certain conditions. When I form an array of strings that meet a certain condition, I get empty lines as array elements.
For Example:
Expressions in a text file:
X&Y
X|Y
!X
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
(X&Y)|Z&(A|B
((X|Y)|Z)&((A|B)|(C&D))
(X&Y)|(Z&(A|B))
(A|B)&(!C)
A|(B&(C&(D|E)))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))
(A|B)|(C&D)&(D|E)
!A&(B|C)
(A|B)|(C|D)&(D
!A|(B&C)
When I print a new array of strings whose elements meet a certain condition, I get empty lines as elements.
X&Y
X|Y
!X
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
//Here
((X|Y)|Z)&((A|B)|(C&D))
(X&Y)|(Z&(A|B))
(A|B)&(!C)
A|(B&(C&(D|E)))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))
(A|B)|(C&D)&(D|E)
!A&(B|C)
//Here
Some elements that should be printed are not printed because of those empty lines? Can someone help me remove these empty lines?
Here's code:
int main()
{
FILE *dat;
int number_of_elements;
char str[MAX][MAXLEN];
int NumberOfRightBracket=0;
int NumberOFLeftBracket=0;
int NumberOfOperators=0;
int Number=0;
int i=0;
char g[200][MAXLEN];
dat=fopen("dat.txt","r");
if(dat==NULL)
{
printf("Error");
}
while(!feof(dat) && !ferror(dat))
{
if(fgets(str[i],100,dat)!=NULL)
str[i][strcspn(str[i],"\n")] = 0;
char p[100];
strcpy(p,str[i]);
for(int o=0;o<strlen(p);o++)
{
if(p[o]=='(')
NumberOfLeftBracket++;
else if(p[o]==')')
NumberOfRightBracket++;
else if(p[o]=='*' || p[o]=='|' || p[o]=='&' || p[o]=='!')
NumberOfOperators++;
}
if(NumberOfRightBracket!=0 && NumberOfLeftBracket!=0 && NumberOfRightBracket==NumberOfLeftBracket)
{
strcpy(g[i],p);
Number++;
}
else if(NumberOfRightBracket==0 && NumberOfLeftBracket==0 && NumberOfOperators==1)
{
strcpy(g[i],p);
Number++;
}
NumberOfRightBracket=0;
NumberOfLeftBracket=0;
NumberOfOperators=0;
i++;
}
for(int k=0;k<Number;k++)
{
printf("%s\n",g[k];
}
}
You use i to decide where in g to store each line from the input, and i is incremented in every iteration, but you use Number to count the number of retained strings, and you only increment Number when retaining a string.
The result is various g[i] where you decided not to retain a string never get updated with data from a line, but you do print them.
You do not need both i and Number. Use just one variable to keep track of both how many lines you have so far and where to put the next line in g.
(You also do not need g if the program is only supposed to do what it appears to be currently attempting.)
I've been asked to find the number of characters that are compared during naive string matching. This was the function we were asked to implement:
// Count the number of characters compared while finding all occurences of the pattern in the given text
// Characters must be matched from left to right
int charactersCompared(char *pattern, char *text);
So if the text is:"ABCEDF" and the pattern is: "EF" the number of characters I would compare using the brute force method would be 6 (comparing the first letter of text with the first letter of the pattern. If it does not match, compare the second letter of the text with the first letter of the pattern again.
If it matches, continue with the comparing the next letters of both text and pattern and so on)
After figuring out a logic with many example cases, I implemented the above function this way:
int charactersCompared(char *pattern, char *text)
{
int i,j,comp=0;
int flag;
for(i=0;text[i]!='\0';i++) //iterating through all the letters of text
{
for(j=0;pattern[j]!='\0';j++)
{
comp++; //to count one comparision.
if(text[i+j]==pattern[j]) //to check if similar to pattern
{
flag=1;
continue;
}
else
{
if(flag==1)
{
flag=0;
comp--;
}
break;
}
}
}
//printf("VALUE OF C=%d\n",comp);
return comp;
}
This works fine for the pair(ABCDEF,EF) (where the count is 6) but not for other test cases which include multiple occurrences of the pattern in text such as:
Text: ABCDEFGHEIEF
Pattern: EF
I'm supposed to get 14 comparisions whereas my output is 12. I don't understand where I am missing out.
If anyone can point out what is the faulty logic, it'd be of great help. Or if there is an easier way to do this, suggestions appreciated. The only constraint is that the method has to be a brute force method (i.e I can't really change the part where i compare each character of each string).
Thank you for your time!
Please note that in worse case is n(m-n+1) , where n is length of pattern and m is length of text. Now, Since you only want to compute comparisons, there's no need for variable flag. Prefer KISS principle.
for(i=0;text[i]!='\0';i++) //iterating through all the letters of text
{
for(j=0;pattern[j]!='\0';j++)
{
comp++; //to count one comparison.
if(text[i+j]==pattern[j]) //to check if similar to pattern
continue;
break;
}
}
printf("VALUE OF C=%d\n",comp);
So i figured out why my program incremented comp extra number of times in the answer posted by #E.N.D . It was because the outer for loop continued until each letter in the text was not compared. But when we do it manually, it's only until the the number of letters remaining in text while comparision are equal to or more than the number of letters in pattern. So i changed a condition
int charactersCompared(char *pattern, char *text)
{
int i,j,comp=0; //int flag;
int lenp=length(pattern),lent=length(text);
for(i=0;i<=lent-lenp;i++)
{
for(j=0;pattern[j]!='\0';j++)
{
comp++;
if(text[i+j]==pattern[j])
{
continue;
}
break;
}
}
//printf("VALUE OF C=%d\n",c);
return comp;
}
This makes sense and works! Thanks for those who tried to answer!
I was doing a programming question and one of the sample output is 64197148392731290. My code for that question is correct as it is giving me the right answers for other test cases (output for those test cases are in single digit).
I understand that there will be too many iterations for the test case which has 64197148392731290 as output. So what should I do to get correct answer for that test case too.
Here is the code :
#include<stdio.h>
#include<string.h>
int main() {
int test_case;long long int i, j, count, n, k, k1;
scanf("%d", &test_case);
while(test_case--) {
scanf("%lld%lld", &n, &k);
char a[n];
count=0;
k1=k;
scanf("%s", a);
while(k1--) {
strcat(a,a);
}
for(i=0;i<(n*k);i++) {
if(a[i]=='a') {
for(j=(i+1);j<(n*k);j++) {
if(a[j]=='b') {
count++;
}
}
}
}
printf("%lld\n", count);
}
return 0;
}
Sample Input and Output :
Input:
3
4 2
abcb
7 1
aayzbaa
12 80123123
abzbabzbazab
Output:
6
2
64197148392731290
My task is to count the number of subsequences "ab" (not necessarily consecutive) in the new string. The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains two integers N and K, denoting the length of the initial string S and the number of repetitions respectively.
The second line contains a string S. Its length is exactly N, and each of its characters is a lowercase English letter.
If you are trying to store input in "int" that wont work coz this number its out of range, change it to "long long int"
Well the previous answer was sure wrong. Thanks for the code.
Sorry don't have time for detailed study but preliminary analysis tells me that maybe the error is because you are trying to store a sting of length 2n in a[n]. It works for smaller values since when you declare
char a[n];
^
variable known at runtime
it actually allocates a large block so that any value of n within range is possible. For large values strcat(a,a) will probably fail.
Basically somewhere down the line the string becomes corrupt. Most probably that is because of strcat. I suggest remove strcat, do something else to a similar effect.
What am I supposed to do in order to print only the duplicated words in a file. I'm a beginner in C.
Here's my code:
#include <stdio.h>
#define max 100
main(){
FILE *fpointer;
char ch[max],str[max][max];
int i = 0,j = 0,count = 0;
int a,b;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," ");
count++;
}
for(a=0;a<count*2;a=a+2){
for(b=0;b<count*2;b=b+2){
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
fclose(fpointer);
return 0;
}
An example of input is "shine little star shine bright in the dark star"
and the output of this program is "shine shine little star star shine shine bright in the dark star star". Please help me to print
only duplicate words. Tnx
In your inner loop, instead of starting at the beginning of the list, start one element after the current one. That way you're not comparing an element against itself or comparing any two elements twice.
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ // b=a+2 instead of b=0
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
Output:
shine
star
Since you wrote duplicate words, i am guessing the words in the file will be repeated twice only.
So you second nested for loop is starting from the beginning every time, and thats where the problem is. You have to make sure that the word already checked is not iterated over again. For that you can change your second for loop a little
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ //notice b=a+2
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
Note
For cases when the words are repeating more then twice, my suggestion would be to use some hashing technique to store if a word has already occurred or not. And then compare and print accordingly.
You have a couple of problems here.
Go through and write some comments. For example, put these where they belong:
// Open the file
// Read in the strings
// Compare the strings
If you do this you will notice you have some problems. For instance, what is this line for?
strcat(str[i++]," ");
It's not reading in a string. So what is it doing?
In your final loop, you want to compare each string with all the others. So obviously, you start with the first string, and you compare it to all the others:
for (a=1; a<count; a++)
if(strcmp(str[0],str[a])==0)
{
printf("%s\n",str[0]);
break;
}
Now we can compare the first string with each following string and print it out if it is duplicated. The "break" is there so we only print it once.
But this only compares the first string with the others. How do we compare all of them? Another loop, of course.
// Compare each string against all the ones after it
for (target=0; target<count; target++)
for (a=target+1; a<count; a++)
// If the strings match AND they are not both null
// (why print out copies of null strings? - nobody wants that)
if(strcmp(str[target],str[a])==0) && strlen(str[a])
{
// Print it
printf("%s\n",str[target]);
// Why is this here?
strcpy(str[a],"");
for (copies=a+1; copies<count; copies++)
if(strcmp(str[copies],str[target])==0)
strcpy(str[copies],"");
// We got a match, stop checking for this string
break;
}
See how we've got one big loop that steps through each string, and a smaller loop that steps through all the remaining strings (no point in stepping through the ones we already looked at).
Now a question for you: why is "strcpy(str[a],"") and the next for loop in there? What purpose do they serve?
This is one way to do it. Please enable warnings - you left out a library header. I've also checked array limits. You need to find a better way to limit the string input too, than just guess a large array size.
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // included header
#define MAX 100
int main(void){ // correct function
FILE *fpointer;
int reported [MAX];
char ch[MAX], str[MAX][MAX];
int index = 0, a;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch) == 1){ // testing for 1 item read
for(a=0; a<index; a++){
if(strcmp(ch, str[a])==0){
if (reported[a] == 0) // don't report twice
printf("%s ",ch);
reported[a]++;
break;
}
}
if(a >= index) { // check if loop completed
if (index >= MAX) { // check if array is full
printf("\nToo many words read\n");
exit(1);
}
strcpy(str[index], ch); // word was not found
reported[index] = 0;
index++; // keep tabs on array length
}
}
printf("\n",ch);
fclose(fpointer);
return 0;
}
Program output:
shine star
One issue is that you are storing every word, regardless of whether it has already been seen:
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," "); // ??? what is this for
count++;
}
Ideally, you'd only like to store each word once, and maintain a count of how often that word appears in the file:
while ( fscanf( fpointer, "%s", ch ) != EOF ) // whitespace is your friend, use it
{
if ( ch_is_not_already_in_str )
{
strcpy( str[count++], ch );
}
else
{
update_count_for_that_string;
}
}
Then at the end, you just loop through ch and print each string that has a count greater than 1.
for ( i = 0; i < count; i++ )
{
if ( str[i]_occurs_more_than_once )
printf( "%s ", str[i] );
}
The bits you need to figure out are ch_is_not_already_in_str, update_count_for_that_string, and str[i]_occurs_more_than_once. How would you go about searching your str array for an occurence of the string in ch? How would you maintain a counter for each string?
I a a beginner at this, so if this is obvious, take it easy on me.
I am using C.
I am using cbreak(); from curses.h to take input realtime from the Linux terminal.
I am using getch(); to catch one input at a time up to two, and using those inputs to address a 2D array.
What i would LIKE it to be doing is printing data at the array location directly after receiving the two digit address.
As it is, it is taking the first set of two digits, then printing the first array location as it receives the first number of the address of the second location.
Here is what i have:
int northsouth[2]; //array to hold input
int nschoice; //counter for for below
int loopOn = 1;
int northSave; //(confused me) places to save value of northSouth[] in attempt
int southSave; //to print only after receiving two digits.
while(loopOn != 0)
{
for(nschoice = 0; nschoice < 2; ++nschoice)
{
northsouth[nschoice] = getch();
if(nschoice == 1 && northsouth[0] != northSave && northsouth[1] != southSave)
{
strcat(input, l[northsouth[0] -= 48][northsouth[1] -= 48]);
printf("\033[2J\033[1;1H");
printf("%s", input);
northSave = northsouth[0];
southSave = northsouth[1];
}
}
}
If I understood you, you want to print after you read two digits. (not after every one).
If so, you should get the if and its whole block out of the for loop, so the for loop will read 2 digits, and the if will print.