Anagram - Minimum Number of deletion - failing certain test cases - c

This is a program that to solve the following question "Given two strings, and , that may or may not be of the same length, determine the minimum number of character deletions required to make and anagrams. Any characters can be deleted from either of the strings". In the end, both strings should have the same letters and same frequency of each letter. For e.g., String A = ccda String B = dcac
My logic is to replace the letter that are same in both strings with a dummy string say "0". So when I count the number of letter in each string that is not equal to "0", it gives me the number of deletion.
But I don't know why this fails for certain cases.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int main(){
int count =0;
const char dummy= '0';
int i =0, j=0;
char* a = (char *)malloc(512000 * sizeof(char));
scanf("%s",a);
char* b = (char *)malloc(512000 * sizeof(char));
scanf("%s",b);
for (i=0;a[i]!= '\0' ;i++){
for(j=0; b[j]!= '\0';j++){
if (a[i]==b[j]){
a[i]= dummy;
b[j]= dummy;
}
}
}
for (i=0;a[i]!= '\0' ;i++){
if(a[i]!= dummy){
count = count+1;
}
}
for (i=0;a[i]!= '\0' ;i++){
if(b[i]!= dummy){
count = count+1;
}
}
printf("%d",count);
return 0;
}
One of the test case it failed was
String A : fcrxzwscanmligyxyvym
String B : jxwtrhvujlmrpdoqbisbwhmgpmeoke
Result given : 22
Expected result : 30
Can anyone please point me the error here. Please, thanks in advance!

You've an error in your code - invalid condition in second loop.
for (i=0;a[i]!= '\0' ;i++){
if(a[i]!= dummy){
count = count+1;
}
}
for (i=0;a[i]!= '\0' ;i++){
^^^^
if(b[i]!= dummy){
count = count+1;
}
}
In marked point should be b[i] rather than a[i].
Minor nitpicking: since you're learning to code, try to get few useful habbits as you go. Code should be pretty (not very pretty, mind you, but ascethic) - it helps to ease reading for both you and everyone else. Consequence matters. If you do spaces around operators, do it everywhere. Layout matters. All of that would help you notice your (common to pros as well, they just find it sooner) mistake.
Also there's a better algorithm in terms of running performance. :)

Related

Why is this code producing an infinite loop?

#include <Stdio.h>
#include <string.h>
int main(){
char str[51];
int k = 1;
printf("Enter string\n");
scanf("%s", &str);
for(int i = 0; i < strlen(str); i++){
while(str[k] != '\0')){
if(str[i] == str[k]){
printf("%c", str[i]);
k++;
}
}
}
return 0;
}
It is simple C code that checks for duplicate characters in string and prints the characters. I am not understanding why it is producing an infinite loop. The inner while loop should stop when str[k] reaches the null terminator but the program continues infinitely.
Points to know
You don't need to pass the address of the variable str to scanf()
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Always check whether scanf() conversion was successful or not, by checking its return value
Always use size_t to iterator over any array
i < strlen(str), makes the loop's time complexity O(n3), instead of O(n2), which also isn't very good you should check whether str[i] != 0. But, many modern compilers of C will optimize it by the way.
#include <Stdio.h> it is very wrong, stdio.h != Stdio.h
Call to printf() can be optimized using puts() and putc() without any special formatting, here also modern compiler can optimize it
while(str[k] != '\0')){ has a bracket (')')
Initialize your variable str using {}, this will assign 0 to all the elements of str
Better Implementation
My implementation for this problem is that create a list of character (256 max) with 0 initialized, and then add 1 to ASCII value of the character (from str) in that list. After that print those character whose value was greater than 1.
Time Complexity = O(n), where n is the length of the string
Space Complexity = O(NO_OF_CHARACTERS), where NO_OF_CHARACTERS is 256
Final Code
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
static void print_dup(const char *str)
{
size_t *count = calloc(1 << CHAR_BIT, sizeof(size_t));
for(size_t i = 0; str[i]; i++)
{
count[(unsigned char)str[i]]++;
}
for (size_t i = 0; i < (1 << CHAR_BIT); i++)
{
if(count[i] > 1)
{
printf("`%c`, count = %zu\n", i, count[i]);
}
}
free(count);
}
int main(void) {
char str[51] = {};
puts("Enter string:");
if (scanf("%50s", str) != 1)
{
perror("bad input");
return EXIT_FAILURE;
}
print_dup(str);
return EXIT_SUCCESS;
}
Read your code in English: You only increment variable k if character at index k is equal to character at index i. For any string that has different first two characters you will encounter infinite loop: char at index i==0 is not equal to char at index k==1, so k is not incremented and while(str[k]!=0) loops forever.

working with methods to take in strings in C

I'm new to C and am having a lot of issues with arrays that keeps coming up. I'm trying to write a method that takes in a string ("1234") and returns the odd digits, however it keeps printing 49 and I don't know why? Does it have something to do with how I'm assigning the arrays?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int print_odd_digits(char number[100]) {
int size = sizeof(number[100]);
for (int i = 0; i < size; i++) {
if (number[i] % 2 == 1) {
printf("%d\n", number[i]);
}
}
return 0;
}
int main(void) {
print_odd_digits("1234");
}
sizeof(number[100]) is equivalent to sizeof(char), which is 1. What you want seems strlen(number).
Elements of number are not values of digits but character codes of digits. To convert number characters to values, you can subtract '0'. (character codes for 0 to 9 are defined to be continuous in C).
%d is for printing integer and 49 is ASCII code for the character 1. Use %c to print character corresponding to passed integer.
You may want newline only on end of the characters.
Try this:
#include <stdio.h>
#include <string.h> /* for using strlen() */
int print_odd_digits(char number[100]) {
int size = strlen(number);
for(int i = 0; i < size; i++){
if((number[i] - '0') % 2 == 1){
printf("%c",number[i]);
}
}
printf("\n");
return 0;
}
int main(void) {
print_odd_digits("1234");
}
You have a type error here. You are working with the ascii codes for the text characters for digits. You need to use the atoi(char* str)
function to convert the digits to a corresponding number and use math to determine a particular digit or loop over the characters and subtract -'0' the ascii code for the digit zero as digits are sequential.
#include <stdlib.h>
#include <stdio.h>
int main() {
char* digit_one_str = "1";
char digit_9 = '9';
printf("digit one ascii value: %d\n", digit_one_str[0]); // first char in string digit one
int number_one = atoi(digit_one_str);
printf("digit one parsed from sttring by atoi: %d\n", number_one);
printf("digit 9 as char converted with -'0' trick: %d", (int)(digit_9 - '0'));
}
Further it is better practice to take in a char* and a length than to work with fixed sized arrays or using strlen() where you don't actually have to. In C a string ends in a terminating '\0' character which might not even be present if the code calling your function is buggy or malicious.

I mixed up two programs in the cs50 sandbox in c?

I mixed up two programs in the cs50 sandbox, one was to find the the number of characters in an array and other was the print these characters. I know the program is garbage but could anyone explain me what is the compiler doing here?
When I ran this, the output starts printing alphanumeric text and never stops Thanks
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
int n = 0;
while (strlen(s) != '\0')
{
n++;
printf("%c", n);
}
}
You have multiple problems with the code you show, here's a couple of them:
strlen(s) will never be zero as you never modify or remove characters from the string, which means you have an infinite loop
n is an integer and not a character so should be printed with the %d format specifier
'\0' is (semantically) a character, representing the string terminator, it's not (semantically) the value 0
To fix the first problem I suspect you want to iterate over every character in the string? Then that could be done with e.g.
for (int i = 0; i < strlen(s); ++i)
{
printf("Current character is '%c'\n", s[i]);
}
But if all you want is to could the number of characters in the string, then that's what strlen is already gives you:
printf("The number of characters in the string is %zu\n", strlen(s));
If you want to count the length of the string without using strlen then you need to modify the loop to loop until you hit the terminator:
for (n = 0; s[n] != '\0'; ++n)
{
// Empty
}
// Here the value of n is the number of characters in the string s
All of this should be easy to figure out by reading any decent beginners book.
while (strlen(s) != '\0') is wrong. '\0' equals 0. There string length is never 0, so the loop keeps going on forever, printing integers interpreted as characters.
You can either use the indexes to go through the string characters by using the variable "n" or you can increment the pointer of the string that you have received from the standard input to go through all of its characters.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
/* First way using n to iterate */
int n = 0;
for (n = 0; n < strlen(s); ++n)
{
printf("%c", s[n]);
}
printf("\n");
/* Second way increment the string pointer*/
while (strlen(s) != '\0')
{
printf("%c", *s); //print the value of s
s++; // go to the next character from s
}
printf("\n");
return 0;
}

counting the number of brackets using array

I am new to coding and would really appreciate if you could help me with this question. I can't find out why my code does not give me the correct result. Thank you for your time!!
Q:
Using a first dimensional array, count the number of closing brackets and open brackets. Input must be in one line.
Ex. Input: (()))
Output: 3 2
I used an array to receive the input in one line and the for loop to count the number of opening/closing brackets.
#include <stdio.h>
int main(){
char str[1000]; int l=0;r=0;
printf("Enter:\t");
gets(str);
int length=sizeof(str)/sizeof(str[0]);
for(int i=0;i!=EOF && i<length;i++)
{
if(str[i]=='(')
l++;
else if(str[i]==')')
r++;
}
printf("%d %d",l,r);
}
Expected
Input: (())
Output: 2 2
What I get
Input: (())
Output: 6 2
i!=EOF is not needed as this is not a file
int length=sizeof(str)/sizeof(str[0]) doesnt give the length of the string strlen() from #include <string.h> does
your loop is wrong (actually your conditions)
for(size_t i = 0; i < strlen(str);i++)
{
if(str[i]=='(')
{
l++;
}
if(str[i]==')')
{
r++;
}
}
There are mistakes which are covered in basic C learning.
sizeof(str)/sizeof(str[0]); returns size of str array which is in your case 1000. To get length of user input, use strlen function: int length = strlen(str).
Later, use your for loop as for(int i=0;i<length;i++) or better:
//Include string.h on beginning of file
#include <string.h>
size_t length = strlen(str);
for (size_t i = 0; i < length; i++) {
//Do your if.
}
You also have a syntax error at the declaration of r.
You would either have int l=0,r=0;
Or
Int l=0;
Int r=0;
Although, the compiler should have warned you about this.

Having trouble reversing parts of a string

This seemed like a simple idea when I decided to try it out, but know it's driving me nuts.
I can reverse a whole string, but now I'm trying to reverse individual parts of a string.
Example:
"pizza is amazing" to "azzip si amazing"
Basically my program should reverse a string from point a to b, treating any words within it separately. My logic appears right (at least to me), but obviously something is wrong because my output is just the first word "pizza".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse(char *a, int i, int j){ //reverse the words
char temp;
while(i<j){
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
return a;
}
char *words(char *a, int i, int j){ // identify if there are any words from a-b
int count = i;
while(i<j){
if(a[i] == ' '){ // a space signifies the end of a word
reverse(a , i-count, i);
count = 0; //reset count for next word
}
i++;
count++;
}
return a;
}
int main(){
char a[50];
char *a2;
printf("Enter a string:\n); //string input
scanf("%s", a);
int strlength = strlen(a) + 1;
a2 = (char *)malloc(strlength*sizeof(char));
strcpy( a2, a);
printf("Reversed string:\n%s", words(a, 0, 4)); // create a-b range
return 0;
}
I realize my problem is most likely within words(). I am out of ideas.
Problem 1:
You should be more careful naming variables, understandable and meaningful names help the programmer and others reading your code. Keep in mind this is extremely important.
Problem 2:
When you pass the parameter %s to scanf(), it will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab).
You can use scanf("%[^\n]", a) to read all characters until a newline is found.
For further reference on scanf(), take a look here.
Problem 3:
Take a look at the words() function, you're not storing a base index (from where to start reversing). The call to reverse() is telling it to reverse a single character (nothing changes).
You didn't specified if a whole word must be inside the range in order to be reversed or even if it is on the edge (ex: half in, half out). I'll assume the whole word must be inside the range, check out this modified version of the words() function:
char *words(char *str, int fromIndex, int toIndex){
int i = fromIndex;
int wordStartingIndex = fromIndex;
/*
It is necessary to expand the final index by one in order
get words bounded by the specified range. (ex: pizza (0, 4)).
*/
toIndex += 1;
/* Loop through the string. */
while(i <= toIndex){
if(str[i] == ' ' || str[i] == '\0' || str[i] == '\n'){
reverse(str, wordStartingIndex, i-1);
wordStartingIndex = (i + 1);
}
i++;
}
return str;
}
This should get you started. The function it is not perfect, you'll need to modify it in order to handle some special cases, such as the one I've mentioned.

Resources