I already posted this question but I'm still struggling to get it properly working. Dreamlax tried to help me out by giving the following steps -
starting with n = 1, Take the first n characters from the string.
Compare it to the last n characters from the string
Do they match?
If yes, print out the first n characters as the suffix and stop processing.
If no, increment n and try again. Try until n is in the middle of the string.
Here's my code which doesn't work:
#include <stdio.h>
#include <string.h>
void main()
{
int i, T, flag, j, k, len = 0, n;
char W[20], X[20], A[20], B[20];
scanf("%d", &T);
for (i = 0; i < T; i++)
{
scanf("%s", W);
for (len = 0; W[len] != '\0'; len++)
X[len] = W[len];
X[len] = '\0';
len--;
n = 1;
while (n < len / 2)
{
for (k = 0; k < n; k++)
A[k] = W[k];
for (k = 0, j = len - n; W[j] != '\0'; j++, k++)
B[k] = W[j];
if (!strcmp(A, B))
{
printf("YES\n");
break;
}
else
{
n++;
}
}
printf("NO\n");
}
}
Help me in pin pointing the error please.
There are several things going on in your code:
You should null-terminate your auxiliary strings A and B. Alternatively, yopu could compare just then n first characters with strncmp instead of strcmp.
strcmp is a comparison function. It returns zero if the strings match. (Comparison function means it can be used in sorting to determine whether a string is lexically greater or smaller than another string. The nomenclature for such functions is to return a negative number for lexically smaller, a positive number for lexically greater and zero means equality.)
You don't use the auxiliary string X excapt to find the length. You can easily find the length of a string with strlen, which, like strcmp, is declared in <string.h>
The calculation of your index for the suffix is off. Your length len is one less than the actual length and W[len] is the last character. Don't subtract one from your length.
Here's your code, refactored into a function, so that input and program logic are separated as they ought to be:
int is_nice(const char *W)
{
char A[20], B[20];
int len = strlen(W);
int j, k, n = 1;
while (n < len / 2) {
for (k = 0; k < n; k++) A[k] = W[k];
A[k] = '\0';
for (k = 0, j = len - n; W[j] != '\0'; j++, k++) B[k] = W[j];
B[k] = '\0';
if (strcmp(A, B) == 0) return 1;
n++;
}
return 0;
}
Above, I've said that you could use strncmp to compare ony a certain number of characters in the string. If you think about it, you can omit the auxiliary strings A and B and compare just slices of your original string:
int is_nice(const char *W)
{
int len = strlen(W);
int n = 1;
while (n < len / 2) {
if (strncmp(W, W + len - n, n) == 0) return 1;
n++;
}
return 0;
}
This saves a lot of copying, some temporary variables and has one other significant benefit: Because the code doesn't have to guess a maximum size for the auxiliary buffers, it now works for strings of any size.
You have three errors in your code.
The first is when you compute the length of the input string. Subtracting 1 from len after the loop is not necessary (simulate this loop for a small n to see why).
In this line:
if (!strcmp(A, B))
you are comparing non null-terminated strings which is undefined behavior. You should either terminate strings A and B or use strncmp(A, B, n) to compare at most n characters.
The third error is a logical error. If a string is "nice", your program will output both YES and NO. But this one should be easy to fix.
Related
I have written the code in c language(for n factorial).
The code is-->
#include <stdio.h>
#include <string.h>
int main()
{
int n;
scanf("%d", &n);
char str[200];
str[0] = '1';
int k;
int t = 0;
int carry = 0;
for (int i = 1; i <= n; i++)
{
carry = 0;
for (int j = 0;; j++)
{
int arr = str[j] - 48;
k = arr * i + carry;
arr = k % 10;
str[j] = arr + 48;
carry = k / 10;
if (carry == 0 && str[j + 1] == '\0')
{
break;
}
if (carry != 0 && str[j + 1] == '\0')
{
for (int r = j;; r++)
{
str[r + 1] = (carry % 10) + 48;
carry = carry / 10;
if (carry == 0)
{
str[r + 2] = '\0';
t = 1;
break;
}
}
break;
}
}
}
int len = strlen(str);
// // printf("%d\n",len);
char prr[200];
for (int i = 0; i < len; i++)
{
int b = len - i - 1;
printf("%c", str[b]);
}
// printf(" %s\n", str);
return 0;
}
In other systems(including online c compilers) it is showing correct answer
Input=7
Output=5040
In my system(laptop):
Input=7
Output=+,*)'040
My laptop is hp envy 13-ab070TU
os:Windows 10 Home
system type:64-bit operating system, x64-based processor
I have also tried my code on virtual machine in my laptop on ubuntu and kali but the result is same that it is showing wrong output.
What is the reason for this and how I can rectify this issue?
You're filling digits in to your str array, but str is not necessarily a proper, null-terminated string.
At the end, you call strlen(str) to discover how many digits you computed in your result. But since str is not necessarily a null-terminated string, strlen doesn't necessarily get the right answer.
str is a local (stack allocated) variable, and you don't give it an initializer, so it starts out containing unpredictable garbage.
If str happens to start out containing zeroes (which it might), your program will happen to work. But if it contains one or more nonzero bytes, strlen might compute too long a length, so your digit-printing loop at the end might print some extra characters, as you saw on your laptop.
There are two or three ways to fix this.
Call memset(str, '\0', sizeof(str)); to fill the array with 0.
Initialize the array: char str[200] = "";. (It turns out that will fill the whole array with 0.)
Keep track of the number of digits some other way. I suspect it's the maximum value ever taken on by k or r, or something like that.
Below is the code where I have to check a specific character in substring of string. How can I decrease its complexity, as I use three for loops but want to do it in two or one loop?
int main(void) {
int i, j, k, t, n;
scanf("%d", &t);
while (t--) {
int count = 0;
scanf("%d", &n);
char a[n], ch;
scanf("%s %c", a, &ch);
for (i = 0; i < n; i++) {
for (j = i; j < n; j++) {
for (k = i; k <= j; k++) {
if (a[k] == ch) {
count++;
break;
}
}
}
}
printf("%d", count);
}
}
So what it looks like from your code is that your trying to generate a set of substrings, so if your array was abc then the substrings would be a, ab, abc, b, bc, c. You then try and count the number of times a character appears, so if ch = 'b' then the result would be 4. So you are counting the number of strings that contain ch.
So one way to solve this problem with fewer loops would be to recognise for each value of i you create the strings by adding a character to the last string, and if the previous string contained n copies of ch then the next string contains n or n+1 copies depending on the actual value.
Another possible approach to get down to just one loop would be loop through the array once and each time you find the character ch calculate how many sub-strings will contain the character at that position. So for the abc example 2 of the 3 strings starting at position 0 and 2 of the strings starting at position 1 will contain the value.
You can use memchr instead of the most inner loop.
Substitute
for (k = i; k <= j; k++) {
if (a[k] == ch) {
count++;
break;
}
}
for
if (memchr(&a[i], ch, j - i + 1) != NULL) {
count++;
}
This will make you use two loops in your code.
I'm learning C with the CS50 course problem set 2, using the crypt function to brute force guess a password. Currently writing a function that prints all possible strings of a certain length, eg:
aa
ab
...
az
ba
...
zy
zz
I've written a fairly simple recursive function to do so:
#include <cs50.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>
void stringcycler(int n, int passLength, char *pass)
// Scrolls through all lowercase letter combinations for a string of length passLength
// Expects an integer value of the length of the strng as both n and passLength
// Also expects a char* array of length passLength with all chars set to 'a' (and a null character)
{
if(n != 0)
{
for(pass[passLength - n] = 'a'; pass[passLength - n] < 'z'; pass[passLength - n]++)
{
stringcycler(n-1, passLength, pass);
printf("%s\n", pass);
// return 0;
}
}
}
int main()
{
// Initialise char *c, and scroll through letters
int passLength = 2; // The number of characters you want to brute force guess
char pass[passLength + 1]; // Add 1 for the null character
int i;
for(i = 0; i < passLength; i++) pass[i] = 'a'; // Set every char in pass to 'a'
pass[passLength] = '\0'; // Set null character at the end of string
stringcycler(passLength, passLength, pass);
return 0;
}
It works for the most part, but only goes to yz. Whenever it sees a z it basically skips, so it goes to yz, then never does za to zz. If I add an = to the for loop line:
pass[passLength - n] < 'z';
ie.
pass[passLength - n] <= 'z';
Then it prints '{' characters in the mix. Any help? And another question is, how can I change this to work for all combos of upper and lower case too, is there a neat way of doing it?
You print after you return from you recursion, but you should print when the recursion has reached the end (or beginning, in your case) of the string. In other words, printing should be an alternative branch to recursing:
void stringcycler(int n, int len, char *pass)
{
if (n != 0) {
for (pass[len - n] = 'a'; pass[len - n] <= 'z'; pass[len - n]++) {
stringcycler(n - 1, len, pass);
}
} else {
printf("%s ", pass);
}
}
The if part constructs the strings as it recurses further down. The else part does something with the constructed string. (Of course, you must include 'z' in your loop. Your original code only prints the z in the last place, because it prints after ther recursion returns, which means thet the char buffer is in a condition that wouldn't (re-)enter the loop.)
Below is a generic backtracking algorithm for generating the password. The idea here is to imagine filling the slots for a given char array a. We will be generating the possible candidates for the given position k for the array a. I have taken the candidates as lower case ascii letters a-z and upper case ASCII letters A-Z. If you want to include other ASCII characters, just modify the construct_candidates function accordingly.
Once the array is filled i.e. k becomes PASS_LEN, we know we have generated the password, we can process it however we like, I have just printed the password here.
The value of PASS_LEN macro can be adjusted to generate password of any desired length.
#include <stdio.h>
#include <stdlib.h>
#define PASS_LEN 2
static char* construct_candidates (char a[], int k, int *count)
{
/* Lower case ASCII */
int min1 = 97;
int max1 = 122;
/* Upper case ASCII */
int min2 = 65;
int max2 = 90;
*count = (max1 - min1 + 1) + (max2 - min2 + 1);
char *cand = calloc(*count, sizeof(char));
if (cand == NULL) {
printf("malloc failed\n");
return NULL;
}
int idx = 0;
for (int i = min1; i <= max1; i++) {
cand[idx] = i;
idx++;
}
for (int i = min2; i <= max2; i++) {
cand[idx] = i;
idx++;
}
return cand;
}
static void backtrack(char a[], int k)
{
int i;
if (k == PASS_LEN) {
for (i = 0; i < PASS_LEN; i++) {
printf("%c", a[i]);
}
printf("\n");
return;
}
int cand_count = 0;
char *cand = construct_candidates(a, k, &cand_count);
if (cand == NULL) {
printf("Failed to get candidates\n");
return;
}
for (i = 0; i < cand_count; i++) {
a[k] = cand[i];
backtrack(a, k + 1);
}
free(cand);
}
int main()
{
char a[PASS_LEN] = {'\0'};
backtrack(a, 0);
}
if (strlen(a) != strlen(b)) {
printf("Not anagram");
} else {
for (int i = 0; i < strlen(a); i++) {
for (int j = 0; j < strlen(b); j++) {
if (a[i] == b[j]) {
len++;
}
}
}
if (len != strlen(a))
printf("Not anagram");
else
printf("Anagram");
}
return 0;
This is a code snippet to check if 2 strings are anagrams. How can repeated characters be handled here? Also, could this program be made more optimized? And what would be the runtime complexity of this code?
An optimal solution would be probably based on calculating the number of characters in every string and then comparing both counts. Ideally, we should use a Dictionary data structure but for simplicity, I will demonstrate the algorithm on an array:
char *word1 = "word1";
char *word2 = "ordw1";
// C strings can have only 256 possible characters, therefore let's store counts in an array with 256 items.
int* letterCounts1 = calloc(256, sizeof(int));
int* letterCounts2 = calloc(256, sizeof(int));
size_t length1 = strlen(word1);
size_t length2 = strlen(word2);
for (size_t i = 0; i < length1; i++) {
int letterIndex = word1[i] & 0xFF;
letterCounts1[letterIndex] += 1;
}
for (size_t i = 0; i < length2; i++) {
int letterIndex = word2[i] & 0xFF;
letterCounts2[letterIndex] += 1;
}
bool isAnagram = true;
for (size_t i = 0; i < 256; i++) {
if (letterCounts1[i] != letterCounts2[i]) {
isAnagram = false;
break;
}
}
free(letterCounts1);
free(letterCounts2);
if (isAnagram) {
printf("Anagram");
} else {
printf("Not anagram");
}
This algorithm has linear (O(n)) complexity (iteration over the "dictionary" can be considered a constant).
Your original solution has quadratic complexity, however, you would also have to make sure to store result of strlen into variables because every call to strlen has to iterate over the whole string, increasing complexity to cubic.
First of all, this is not the right solution. Think in this 2 strings: "aabc" and "aade"
a[0] == b[0], a[0] == b[1], a[1] == b[0] and a[1] == b[1]. len would be 4 but they are not anagram. Complexity is O(n^2) being n the length of the string.
As #Sulthan has answered you, a better approach is to sort the strings which complexity is O(n*log(n)) and then compare both strings in one go O(n).
To order the strings in O(n * log(n)) you can not use a bubble method but you can use a merge-sort as described here: https://www.geeksforgeeks.org/merge-sort/
An even better approach is to create an array of integers in which you count the number of occurrences of each character in the first string and then you subtract one of the occurrences for each occurrence in the second array. In the end, all the positions of the auxiliary array must be 0.
Here a some answers:
Your algorithm does not handle duplicate letters, it may return false positives.
It is unclear if it is correct otherwise because you did not post a complete function definition with all declarations and definitions, especially whether len is initialized to 0.
It has O(N2) time complexity or even O(N3) if the compiler cannot optimize the numerous redundant calls to strlen().
Here is simple solution for systems with 8-bit characters with linear complexity:
#include <stdio.h>
#include <string.h>
int check_anagrams(const char *a, const char *b) {
size_t counters[256];
size_t len = strlen(a);
size_t i;
if (len != strlen(b)) {
printf("Not anagrams\n");
return 0;
}
for (i = 0; i < 256; i++) {
counters[i] = 0;
}
for (i = 0; i < len; i++) {
int c = (unsigned char)a[i];
counters[c] += 1;
}
for (i = 0; i < len; i++) {
int c = (unsigned char)b[i];
if (counters[c] == 0) {
printf("Not anagrams\n");
return 0;
}
counters[c] -= 1;
}
printf("Anagrams\n");
return 1;
}
I have written some code in C, what it does is take an input of 2 strings A, B Where A is a normal string and B is a Sub string inside B. The program will "cut" out all the appearances of the sub sting B inside the string A. For example: A = "asdLEONasd", B = "asd" => C(Result) = "LEON".
everything seems to be working fine except after the output stage where it prints out a few unwanted characters.
Here are 2 examples for this: (the unwanted characters are underlined with a red pen)
Example 1
Example 2
The code:
#include <stdio.h>
#include <string.h>
void main()
{
int len1, len2;
puts("Input a length for a");
scanf("%d",&len1);
// Initializing A
char a[len1 + 1];
puts("Input a");
scanf("%s" ,a);
puts("Input length for b");
scanf("%d",&len2);
//Initializing B
char b[len2 + 1];
puts("Input b");
scanf("%s" ,b);
int i, j , k, count1 = 0, count2;
for(i = 0; i < len1; i++) //Loop that goes over string a
{
count2 = 0, k = 0;
for(j = i; j < len2 + i; j++) //Loop that goes over a part of a (from i to i + len2)
{
if(a[j] == b[k])
{
count2++; //Counting how many characters match with the sub string B
}
k++;
}
if(count2 == len2) //If counted characters = len2 then we know that we found the Sub string B in A
{
count1++; //Counting each appearance of B in A
for(j = i; j < len2 + i; j++) //Loop that marks cells that represent the sub string B in A
{
a[j] = '0'; //Marking cells that are the sub string b
}
}
}
if(!count1) //If count1 remained as 0 then B does not appear in A, which means the result is A
{
puts(a);
}
else
{
j = 0;
int len3 = len1 - count1 * len2; //Determining resulting array size
char c[len3]; // Initializing array C
//Filling array C accordingly
for(i = 0; i < len1; i++)
{
if(a[i] != '0')
{
c[j] = a[i];
j++;
}
}
puts(c);
}
}
What I find most weird is when my output array has a size of 4 for example, and it still prints the extra characters regardless the size.
I'm very curious as of why this happening and how can it be fixed?
You should think of a dumb implementation of puts as follows:
void puts(char *s)
{
while (*s) //if the current character isn't 0
{
putchar(*s); //print the character
++s; //move to the next character
}
putchar('\n');
}
Therefore, if the last character in your array isn't 0, the above loop will continue until there happens to be a 0 somewhere in the memory that follows.
If you're unable to add this terminating zero (as already mentioned by Bathsheba and yourself), you could use printf.
When using the printf family of functions, you can use the %s specifier to format a string (such as padding and limiting it's length).
char x[] = {'a', 'b', 'c', 'd'};
//print just abc
printf("%.*s\n", 3, x);
//print just abc
printf("%.3s\n", x);
//print just bcd
printf("%.*s\n", 3, x+1);
The problem was in the array C.
Changing char c[len3]; to char c[len3 + 1]; and adding an initialization c[len3] = '\0'; fixed this.
Before the third lines in the reciprocal of the program,that's right in front of this statement puts(c), if you add c[j]='\0', the problem you said will be solved.