9

I had a quiz and I wrote this code:

Print Fizz if it is divisible by 3 and it prints Buzz if it is divisible by 5. It prints FizzBuss if it is divisible by both. Otherwise, it will print the numbers between 1 and 100.

But after I arrived home, I wondered if could have writen it with less code. However, I could not come out with a shorter code. Can I do it with a shorter code? Thanks.

This is what I wrote and I think it works well. But can I have done it with less code.

#include <stdio.h>

int main(void)
{
    int i;
    for(i=1; i<=100; i++)
    {
        if(((i%3)||(i%5))== 0)
            printf("number= %d FizzBuzz\n", i);
        else if((i%3)==0)
            printf("number= %d Fizz\n", i);
        else if((i%5)==0)
            printf("number= %d Buzz\n", i);
        else
            printf("number= %d\n",i);

    }

    return 0;
}
ThomasW
  • 16,981
  • 4
  • 79
  • 106
leocod
  • 173
  • 1
  • 2
  • 7
  • Is this homework? (BTW, did you really intend to optimize the first if statement that much? :( – Francois Feb 27 '12 at 07:37
  • 1
    stack exchange has a codegolf site I do believe – David Heffernan Feb 27 '12 at 07:44
  • This question tends to defeat those who try to be clever. You can make it shorter, but then it's easy to get it wrong. What you did is the simple way to get it right. – ugoren Feb 27 '12 at 07:44
  • No, this is not a homework problem at all. I just was trying to learn if I could have done it in shorter way. And I learned something here from the user paxdiable, where if you need to test two conditions, sometimes you could reduce these two conditions to be just one and therefore your code will be shorter. When I wrote my code I did not think in that way. Now I will use his technique from now on. – leocod Feb 27 '12 at 07:57
  • 2
    `if(((i%3)||(i%5))== 0)` Don't try to be too clever, it just obscures what your code is intended to do. Also, it should print Fizz/Buzz *instead* of the number, so beware that some of the solutions given in the answers are wrong. – Secure Feb 27 '12 at 08:26
  • 1
    I'm voting to close this question as off-topic because review of functional code is off-topic for Stack Overflow. Your question may be on-topic for [codereview.se]. – Makyen Jun 13 '17 at 21:12
  • Totally weird that this was closed imho. How is it possibly not a programming question? – Agent Zebra Jun 08 '18 at 23:45

11 Answers11

17

You could also do:

#include <stdio.h>

int main(void)
{
    int i;
    for(i=1; i<=100; ++i)
    {
        if (i % 3 == 0)
            printf("Fizz");
        if (i % 5 == 0)
            printf("Buzz");
        if ((i % 3 != 0) && (i % 5 != 0))
            printf("number=%d", i);
        printf("\n");
    }

    return 0;
}

A few lines shorter, and a lot easier to read.

martiert
  • 741
  • 4
  • 13
  • If you always wan't the number you could also strip a line by doing printf("number=%d ", i) at the top and removing the last if. – martiert Feb 27 '12 at 08:09
  • `if ((i % 3 != 0) && (i % 5 != 0))` can actually just be written as `if (i % 3 && i % 5)`. `i % 3` and `i % 5` in this case will return non-zero numbers, which evaluate to true. – fbonetti Mar 10 '13 at 18:26
  • Sometimes it isn't easy for people to keep things simple. You did it. +1. – RBT Nov 22 '16 at 02:48
11

I'm not sure when you'd start calling it unreadable, but there's this.

#include <stdio.h>

int main(void)
{
   int i = 1;
   for (; i<=100; ++i) {
      printf("number= %d %s%s\n", i, i%3?"":"Fizz", i%5?"":"Buzz");
   }
   return 0;
}
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
  • It runs well, and it's shorter. Thanks. – leocod Feb 27 '12 at 08:26
  • I'm pretty sure paxdiablo's solution is faster though, and not even that much longer. – Mr Lister Feb 27 '12 at 08:30
  • 1
    Well, in all honesty, the question did ask for shorter rather than faster :-) If you declared `i` within the `for` statement and ditched the braces, it would be even shorter, without sacrificing readability. +1. – paxdiablo Feb 27 '12 at 13:28
  • @paxdiablo I could dispense with the braces, but I'm not sure about the i, since the OP didn't mention if this was C99 or not. There are no hints in the code either. – Mr Lister Feb 27 '12 at 14:10
  • 3
    It shouldn't print the number when it prints Fizz or Buzz. – Gnubie Feb 03 '16 at 18:29
  • Not the actual solution. You cant print the number before each line. – Sazzad Hissain Khan May 07 '19 at 17:49
  • @SazzadHissainKhan I know, but I moulded my answer on the OP's code rather than on description of what the program should do. The question was how to make their code shorter, not how to implement FizzBuzz correctly! – Mr Lister May 07 '19 at 19:48
8

If a number is divisible by both 3 and 5, then it's divisible by 15, so:

for each number 1 to 100:
    if number % 15 == 0:
        print number, "fizzbuzz"
    else if number % 5 == 0:
        print number, "buzz"
    else if number % 3 == 0:
        print number, "fizz"
    else:
        print number

Other than that, you probably won't get it much shorter, at least in a conventional language like C (and I'm assuming you don't want the normal code-golf style modifications that make your code unreadable).

You could also get the whole thing into two lines if you packed the entire main function onto a single large line, but I would hope you wouldn't be after that sort of trickery either.

You can possibly get it faster (though you should check all performance claims for yourself) with something like:

static const char *xyzzy[] = {
    "",     "",     "fizz", "",     "buzz",
    "fizz", "",     "",     "fizz", "buzz",
    "",     "fizz", "",     "buzz", "fizzbuzz",
    // Duplicate those last three lines to have seven copies (7x15=105).
};
for (int i = 1; i <= 100; i++)
    printf ("%d %s\n", i, xyzzy[i-1]);

As an aside, that array of char pointers is likely to be less space-expensive than you think, thanks to constant amalgamation - in other words, it will be likely that there will only be one of each C string.

As I say, whether it's faster should be tested. In addition, your original specs only called for the shortest code so it may be irrelevant.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Thanks. That's true. For the first test I could think of it in term of just one number. I will take that into account with future exercises. Thanks. – leocod Feb 27 '12 at 07:44
2
#include <stdio.h>

char const * template[] = {
  "%i",
  "Buzz",
  "Fizz",
  "FizzBuzz"
};
const int __donotuseme3[] = { 2, 0, 0 };
const int __donotuseme5[] = { 1, 0, 0, 0, 0 };
#define TEMPLATE(x) (template[__donotuseme3[(x) % 3] | __donotuseme5[(x) % 5]])

int
main(void) {
  int i;
  for (i = 1; i <= 100; i++) {
    printf(TEMPLATE(i), i);
    putchar('\n');
  }
  return 0;
}
2

This one avoids some code repetition but requires a temporary variable char t

void FizzBuzz( ) {
    char t = 0;
    for (unsigned char i = 1; i <= 100; ++i, t = 2) {
        (i % 3) ? --t : printf("Fizz");
        (i % 5) ? --t : printf("Buzz");
        if (!t) printf("%d", i);
        printf("\n");   
    }
}
Michele
  • 149
  • 1
  • 10
2

I would say that modulo is expensive while comparisons are cheap so only perform the modulo once. That would yield something like this.

int i;
for( i = 0; i!=100; ++i ) {
    bool bModThree = !(i % 3);
    bool bModFive = !(i % 5);

    if( bModThree || bModFive ) {
        if( bModThree ) {
            printf( "Fizz" );
        }
        if( bModFive ) {
            printf( "Buzz" );
        }
    } else {
        printf( "%d", i );
    }

    printf( "\n" );
}
Kenneth
  • 1,167
  • 1
  • 13
  • 26
1

i would write something like that

    main(){
  if (i % 3 == 0){
  cout<<"Fizz";
  }
  if (i % 5 == 0){
  cout<<"Buzz";
  }
  // So if both are true, it will print “FizzBuzz” and augment the two strings
    }
user889030
  • 4,353
  • 3
  • 48
  • 51
1

I'd go with a helper function :-)

#include <stdio.h>

int fbindex(int n) {
    int i = 0;
    if (n % 3 == 0) i += 1;
    if (n % 5 == 0) i += 2;
    return i;
}

int main(void) {                                 
    const char *fb[] = {"%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n"};
    for (int i = 1; i <= 100; i++) printf(fb[fbindex(i)], i);                
}
pmg
  • 106,608
  • 13
  • 126
  • 198
0
void main()
{
    int i = 0;
    char h[4];

    while (++i <= 100)
    {
        sprintf(h, "%d", i);
        printf("%s%s%s\n", i%3 ? "" : "fizz", i%5 ? "" : "buzz", (i%3 && i%5) ? h: "");
    }
}
Rotem
  • 30,366
  • 4
  • 32
  • 65
  • 3
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Mar 03 '17 at 12:07
0

You can do it using a String:

String s="";
if(num%3==0)
   s+="fizz";
if(num%5==0)
   s+="buzz";
if(s.length()==0)
   s+=num+"";
Arpit Gupta
  • 113
  • 1
  • 6
-2

Obfuscated form of Mr Lister's answer

main(int i){while(i++<100){printf("number= %d %s%s",i,i%3?"":"Fizz",i%5?"":"Buzz");}}

N20084753
  • 2,130
  • 2
  • 17
  • 12