Optimize code to get following output in c - c

I had an interview last week. They asked me to write a code to print like this
input :5
0
101
21012
3210123
432101234
54321012345
i wrote the below code but he said i could optimize this more . i cant figure it out.
,
int main(){
int n,i,j,k,lim,num;
scanf("%d",&n);//getting input starting number of last row
lim=n;
int collen=n+2;//it denotes end of row
for(i=0;i<n+1;i++)
{
num=i;
k=0;
for(j=0;j<collen-1;j++){
if(j<lim)
printf(" ");
else if(num<0){
printf("%d",++k);
}
else{
printf("%d",num--);
}
}//j for
printf("\n");
collen++;
lim--;
}//i for
}// main end
I have different code at first attempt, I used flag to detect when num reaches for incrementing and decrementing, it was complex there was about 4 if inside second loop, so I optimized that code to the above one. He said can you optimize more? I have no idea to optimize it .
My question: can it be optimized? If it can be - please post the code

There are more for-loops than those comparing by <. for(i=0;i<n+1;i++) is much clearer written as for (i = 0; i <= n; i++).
If you initialize a value, in example int collen=n+2;, and later use it like collen-1, save the subtraction and initialize it adjusted.
Separate this complex inner loop with ifs into their own loops.
Use less variables.
Use more and consistent whitespace.
And now my solution, but as yours it can only handle inputs from 0 to 9:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n;
printf("input :");
if (scanf("%d", &n) != 1 || n < 0 || n > 9) {
printf("input not recognized or invalid\n");
return EXIT_FAILURE;
}
for (int i = 0; i <= n; ++i) {
printf("%*d", n - i + 1, i);
for (int j = i - 1; j >= 0; --j) {
printf("%d", j);
}
for (int j = 1; j <= i; ++j) {
printf("%d", j);
}
printf("\n");
}
return EXIT_SUCCESS;
}

This looks optimized to the brims:
int main( int argc, char **argv )
{
puts( "input :5");
puts( " 0");
puts( " 101");
puts( " 21012");
puts( " 3210123");
puts( " 432101234");
puts( "54321012345");
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Print a pyramid */
int
main(int argc, char **argv)
{
int size = argc > 1 ? strtol(argv[1],NULL,10) : 5;
if( size > 9 || size < 0) {
fprintf(stderr, "Invalid size\n");
return EXIT_FAILURE;
}
for(int line = 0; line <= size; line++) {
char template[]="9876543210123456789";
char *s = template + 9 - size;
template[10 + line] = '\0';
memset(s, ' ', size - line);
if(puts(s) == EOF) {
perror("puts");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

Related

C, dividing a string in half

I am trying to write a function to divide a string in half but after the initial input it does not output anything. My goal is to scan a year and save the first two number and the last two numbers. This is the code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char scan_year2() {
char year_number;
scanf("%s", year_number);
return year_number;
return 0;
}
// Function to print n equal parts of str
void divideString(char *str, int n) {
int str_size = strlen(str);
int i;
int part_size;
if (str_size % n != 0) {
printf("Invalid Input: String size");
printf(" is not divisible by n");
return;
}
part_size = str_size / 2;
for (i = 0; i < str_size; i++) {
if (i % part_size == 0)
printf("\n");
printf("%s", str[i]);
}
}
int main() {
char year_number;
scan_year2();
char str = year_number;
divideString(str, 2);
getchar();
return 0;
}
Assuming that a year is at least a 3-digit number, the best way to treat it is to treat it as a number, not as a string:
...
int year;
scanf("%d", &year);
int first = year / 100;
int last = year % 100;
printf("%d %d\n", first, last);
...
dont ignore compiler warnings, it must be complaining at you about this
char scan_year2() {
char year_number;
scanf("%s", year_number);
return year_number;
return 0;
}
you try to return twice.
Also
part_size = str_size / 2;
for (i = 0; i < str_size; i++) {
if (i % part_size == 0)
printf("\n");
printf("%s", str[i]);
}
is not going to give you the correct output. YOu are outputing the string each time. IE if str = "1923" then you will get
1923923
232
You should do
part_size = str_size / 2;
for (i = 0; i < str_size; i++) {
if (i % part_size == 0)
printf("\n");
printf("%c", str[i]);
}
to only output one char at a time

Find missing lower-case letters that are not in a series of words

As stated in the title I am trying to find all lower-case letters that are not in a series of words. There are no upper-case letters, digits, punctuation, or special symbols.
I need help fixing my code. I am stuck and do not know where to go from here.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int letters[26];
char words[50];
int i = 0, b = 0;
printf("Enter your input : ");
scanf("%s", words);
for(i = 0; i < 26; i++){
letters[i] = 0;
}
while(!feof(stdin)){
for(b = 0; b < strlen(words) - 1; b++){
letters[ words[b] - 'a']++;
scanf("%s", words);
}
}
printf("\nMissing letters : %c ", b + 97);
return 0;
}
My output is giving me some random letter that I do not know where it is coming from.
Here is a working first implementation.
As well as the comments that have already been made, you should use functions wherever possible to separate out the functionality of the program into logical steps. Your main function should then just call the appropriate functions in order to solve the problem. Each function should be something that is self contained and testable.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_INPUT 20 /* Max input to read from user. */
char *readinput(void);
void find_missing_lower_case(char *, int);
int main()
{
char *user_input = readinput();
int len_input = strlen(user_input);
printf("user input: %s\n", user_input);
printf("len input: %d\n", len_input);
find_missing_lower_case(user_input, len_input);
/* Free the memory allocated for 'user_input'. */
free(user_input);
return 0;
}
char *readinput()
{
char a;
char *result = (char *) malloc(MAX_INPUT);
int i;
for(i = 0; i < MAX_INPUT; ++i)
{
scanf("%c", &a);
if( a == '\n')
{
break;
}
*(result + i) = a;
}
*(result + i) = '\0';
return result;
}
void find_missing_lower_case(char *input, int len_input)
{
int a = 97; /* ASCII value of 'a' */
int z = 122; /* ASCII value of 'z' */
int lower_case_chars[26] = {0}; /* Initialise all to value of 0 */
/* Scan through input and if a lower case char is found, set the
* corresponding index of lower_case_chars to 1
*/
for(int i = 0; i < len_input; i++)
{
char c = *(input + i);
if(c >= a && c <= z)
{
lower_case_chars[c - a] = 1;
}
}
/* Iterate through lower_case_chars and print any values that were not set
* to 1 in the above for loop.
*/
printf("Missing lower case characters:\n");
for(int i = 0; i < 26; i++)
{
if(!lower_case_chars[i])
{
printf("%c ", i + a);
}
}
printf("\n");
}
I figured it out and this is the code I used.
int main(void)
{
int array[26];
char w;
int i=0;
for(i=0; i<26; i++) {
array[i]=0; }
printf("Enter your input: ");
scanf("%c", &w);
while(!feof(stdin)) {
array[w-97] = 1;
scanf("%c", &w); }
printf("Missing letters: ");
for(i=0; i<26; i++) {
if(array[i] == 0) {
printf("%c ", i+97); }
}
printf("\n");
return 0;
}

Integer array with whitespace characters output

I am trying to write a c program. It have to enter two arrays and input should be space seperated. I tried somehow to eliminate the '\n'.
#include <stdio.h>
int main()
{
char temp;
int alc[3]={0}, bob[3]={0}, i=0;
//enter alice
do
{
scanf("%d%c", &alc[i], &temp);
i++;
} while(temp != '\n');
i=0;
//enter bob
do
{
scanf("%d%c", &bob[i], &temp);
i++;
} while(temp != '\n');
//print alice
for(i = 0; i < 3 ; i++)
{
printf("%d ", alc[i]);
}
//print bob
for(i = 0; i < 3 ; i++)
{
printf("%d ", bob[i]);
}
return 0;
}
output ./a.out
5 6 7
3 6 10
5 6 7 3 6 10
Is there a better way to do same?
The idea is get the line as input and then parse it to get the integers using strtol etc. The line you will get using fgets. And then you will store it in array. There are two options now,
If you get more elements than you can hold in the array then you will show error when the array is full.
Or use dynamically allocated memory which will grow as the number you enter increase.
I am afraid, using scanf until you get integers is an option - but that is not the good idea and scanf is not the easy way to go about this.
the following proposed code:
cleanly compiles
follows the axiom: only one statement per line and (at most) one variable declaration per statement.
is consistently indented
eliminates unneeded variables
limits the scope of variables
performs the desired functionality
properly checks for error indications from system functions
documents why each header file was included
all 'magic' numbers given meaningful names (via #define statement)
and now the proposed code:
#include <stdio.h> // scanf(), fprintf(), stderr, printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#define MAX_NUMS_PER_PERSON 3
int main( void )
{
int alice[ MAX_NUMS_PER_PERSON ]={0};
int bob[ MAX_NUMS_PER_PERSON ]={0};
//enter alice
for( int i=0; i< MAX_NUMS_PER_PERSON; i++ )
{
if( 1 != scanf("%d", &alice[i]) )
{
fprintf( stderr, "failed to input nums for Alice\n" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
}
//enter bob
for( int i=0; i< MAX_NUMS_PER_PERSON; i++ )
{
if( 1 != scanf("%d", &bob[i]) )
{
fprintf( stderr, "failed to input nums for Bob\n" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
}
//print alice
for( int i = 0; i < MAX_NUMS_PER_PERSON; i++)
{
printf("%d ", alice[i]);
}
//print bob
for( int i = 0; i < MAX_NUMS_PER_PERSON; i++)
{
printf("%d ", bob[i]);
}
return 0;
}
Changed my C program according to this answer
Putting numbers separated by a space into an array
#include <stdio.h>
#include <ctype.h>
#define ARRAY_SIZE 3
#define BOB_SIZE 5
#define ALICE_SIZE 4
int main()
{
int tmp, i=0;
char follow;
int count;
int a[ALICE_SIZE]={0}, b[BOB_SIZE]={0};
if((ALICE_SIZE < ARRAY_SIZE) || (BOB_SIZE < ARRAY_SIZE))
{
printf("Not sufficient space in array, check the sizes.\n");
return -1;
}
while ((i < ARRAY_SIZE) && (count = scanf("%d%c", &tmp, &follow)) > 0)
{
if ((count == 2 && isspace(follow)) || (count == 1))
{
a[i++] = tmp;
}
else
{
printf ("Bad character detected: %c\n", follow);
break;
}
}
i=0;
while ((i < ARRAY_SIZE) && (count = scanf("%d%c", &tmp, &follow)) > 0)
{
if ((count == 2 && isspace(follow)) || (count == 1))
{
b[i++] = tmp;
}
else
{
printf ("Bad character detected: %c\n", follow);
break;
}
}
for(i = 0; i < ARRAY_SIZE ; i++)
printf("%d ", a[i]);
printf("\n");
for(i = 0; i < ARRAY_SIZE ; i++)
printf("%d ", b[i]);
return 0;
}
Tried to make input as general as possible while using scanf
looks like too much effort but its required to make it robust,and put corner cases and errors.
More problems with scanf comes with strings or %s specifier. So better get used to fgets, strtol and dynamic arrays in parsing while giving inputs.

String Sort and remove Duplicates

First I apologize for any mistype, for I am Brazilian and English is not my native language.
I am a freshman at my college and I got this algorithm to solve, from my teacher:
Make a program that creates a vector of n words, n being a size entered by the user (maximum 100). Your program should remove all duplicate words from the input vector and sort the words. Print the final vector without repeated and ordered words.
E.g. with 7 words to sort:
Input: 7 [enter]
hand ear leg hand hand leg foot
Output: ear foot hand leg
Note: Comment the program prints so that the output of the program is as shown in the example above (the numbers are separated by a spacebar, without space after last digit).
Note2: In case of invalid entry the program should print: "invalid entry" (all lower case).
Ok, I got it working but the I got confused with the notes and I can't find a way to fix the possible bugs, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[100][100], aux[100];
int i, j, num;
printf("Type how many words you want to order: ");
do
{
scanf("%d", &num);
}while (num>100 || num<=0);
for(i=0; i<num; i++)
scanf("%s",&word[i]);
for (i = 0; i < num; i++) //loop to sort alphabetically
{
for (j = i+1; j < num; j++)
{
if ((strcasecmp(word[i], word[j]) > 0)) //swapping words
{
strcpy(aux, word[j]);
strcpy(word[j], word[i]);
strcpy(word[i], aux);
}
}
}
for (i = 0; i < num; i++) //loop to remove duplicates
{
if ((strcasecmp(word[i], word[i+1]) == 0)) //finding the duplicates
{
for (j = i+1; j < num; j++) //loop to delete it
strcpy(word[j], word[j+1]);
num--;
i--;
}
}
printf("\nWords sorted and without duplicates:\n");
for(i=0; i<num-1; i++)
printf("%s ", word[i]); //output with spacebar
printf("%s", word[num-1]); //last output without spacebar
return 0;
}
When I type a word with more than 100 characters, the Code::Blocks closes with an error, else it works fine. What do you think I should change?
The teacher uses a Online Judge (Sharif Judge) to evaluate if the code is right, and I got error in 3 of the tests (that are not specified), all of them were "Time Limit Exceeded". Maybe it has do to with the size of the matrix, or the problem with words >100.
Thanks in advance, Vinicius.
I guess you input sanity check is causing the issue.
As mentioned in the comment section.
If n is always < 100. Definitely your sorting is not causing any time limit exceeded.
Looks like the n is given something greater than 100 and your scanf is waiting and causing the issue. Also, make sure your input numbers are taken properly. If the input is > 100 print 'invalid entry'.
Something like below should work.
scanf("%d", &num);
if (num > 100)
printf("invalid entry");
for (i = 0; i < num; i++) {
scanf("%s", word[i]);
if (strlen(word[i])>100)
printf("invalid entry");
}
Hope it helps!
of course you will get an error if you use woerds more than 100 length casue you
have this line: char word[100][50], aux[100];
that means that you word length limit is set to 50. use word[100][100];
also you may not delete duplicates, just skip them in output
lol of course if youre using judge , you should not output any symbols except the answer, this means you should delete all lines, like :
printf("Type how many words you want to order: ");
and check the input format, and check limitations, i mean max word length , max amounts of words
try smth like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max_word_length = 101;
#define max_amount_of_words = 101;
int main() {
char word[max_amount_of_words][max_word_length] = {};
char aux[max_word_length];
int i, j, num;
scanf("%d", &num);
if (num < 0 || num > 100) {
printf("invalid entry");
return 0;
}
for (i = 0; i < num; i++) {
scanf("%s", word[i]);
}
for (i = 0; i < num; i++) {//loop to sort alphabetically
for (j = i + 1; j < num; j++) {
if ((strcasecmp(word[i], word[j]) > 0)) { //swapping words
strcpy(aux, word[j]);
strcpy(word[j], word[i]);
strcpy(word[i], aux);
}
}
}
bool is_joint = false;
for (i = 0; i < num; i++) { //loop to skip duplicates
if ((strcasecmp(word[i], word[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
if(is_joint) printf(" ");
printf("%s ", word[i]);
is_joint = true;
}
}
return 0;
}
I got 100% on Judge, I fixed the code and looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char word[101][101],aux[101]; //a number higher than the limit to comparisons
int i,j,num;
scanf("%d",&num);
if(num<=0||num>100){ // if words < 0 or >100
printf("invalid input");
return 0;
}
for(i=0;i<num;i++){
scanf("%s",&word[i]); //read n words
if(strlen(word[i])>100){ //if word >100 caracters
printf("invalid input");
return 0;
}
for(j=0;j<strlen(word[i]);j++){
if (word[i][j]>=65&&word[i][j]<=90){
word[i][j]= word[i][j]+32; // if word is uppercase, make them lowcase
}
else if (word[i][j]>122||word[i][j]<97){// if word is different from alphabet lowercase
printf("invalid input");
return 0;
}
}
}
for(i=0;i<num;i++){
for(j=i+1;j<num;j++){
if((strcmp(word[i],word[j])>0)){ //loop to sort words
strcpy(aux,word[j]);
strcpy(word[j],word[i]);
strcpy(word[i],aux);
}
}
}
for(i=0;i<num-1;i++){
if((strcmp(word[i],word[i+1])!=0)){ // output words with spacebar, without the last one
printf("%s ",word[i]);
}
}
printf("%s",word[num-1]); // last word without spacebar
return 0;
}
Thank you everyone who tried to help, I've learned a lot with your suggestions!
This project is actually pretty tough assignment for a programmer who just
started in C.
Run this program in your computer.
Before running against the Judge, make sure you run many times with your manual inputs. Once you are happy with the tests, try against the Judge.
Like I said, the hardest part is storing the user's inputs according to spec (accepting space or newline characters in multiple lines).
#include <stdio.h>
#include <string.h>
int
main(void)
{
int iNumW, iIndex;
int iWCnt = 0;
int iC;
char caTemp[100];
char caWords[100][100];
char *cpDelimeter = " \n";
char *cpToken;
char *cp;
short sIsWord = 1;
char caGarbage[100];
scanf("%d", &iNumW );
fgets(caGarbage, sizeof caGarbage, stdin); //Remove newline char
//Get word inputs
while( iWCnt < iNumW )
{
fgets(caTemp, sizeof caTemp, stdin );
for( cpToken = strtok( caTemp, cpDelimeter ); cpToken != NULL; cpToken = strtok( NULL, cpDelimeter)){
cp = cpToken;
while( *cp ){
sIsWord = 1;
//Check if alphabet
if( !isalpha(*cp) ){
sIsWord = 0;
break;
}
cp++;
}
if( sIsWord ){
strcpy( caWords[iWCnt], cpToken );
//printf( "%s\n", caWords[iWCnt]);
iWCnt++;
if( iWCnt >= iNumW ) break;
} else {
printf("invalid entry.\n");
}
//printf("%d\n", iWCnt);
}
}
int i,j ;
for (i = 0; i < iWCnt; i++) {//loop to sort alphabetically
for (j = i + 1; j < iWCnt; j++) {
if ((strcasecmp(caWords[i], caWords[j]) > 0)) { //swapping words
strcpy(caTemp, caWords[j]);
strcpy(caWords[j], caWords[i]);
strcpy(caWords[i], caTemp);
}
}
}
for (i = 0; i < iWCnt; i++) { //loop to skip duplicates
if ((strcasecmp(caWords[i], caWords[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
printf("%s ", caWords[i]);
}
}
return 0;
}

concatinating even and odd places in a string

I'm learning basics in coding. Can any one say what went wrong with my code
Prob:Given a string, S, of length N that is indexed from 0 to N-1 , print its even-indexed and odd-indexed characters as 2 space-separated strings on a single line
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
char input[100], final[100];
int main()
{
int num, i, j;
char even[50], odd[50], space[] = " ";
scanf("%d", &num);
for (i = 0; i < num; i++)
{
int k = 0, p = 0;
scanf(" %[^\n]s", input);
for (j = 0; input[j] != '\0'; j++)
{
if (j % 2 == 0)
{
even[k] = input[j];
k++;
}
else
{
odd[p] = input[j];
p++;
}
}
strcat(final, even);
strcat(final, space);
strcat(final, odd);
}
printf("%s", final);
}

Resources