Monday, July 4, 2022

Day 19/100 FizzBuzz

Day 19/100 FizzBuzz

FizzBuzz Buzzineezz


Yeah, you know it's going to happen eventually. I Fizz the FizzBuzz Buzz. Lame, I know. But here it is...


FizzBuzz program basically prints out numbers from 1 to 100, except that if the number is evenly divisible by 3, it prints "Fizz" instead. If the number is evenly divisible by 5, it prints "Buzz" instead. And if the number is evenly divisible by 3 and 5, it prints "FizzBuzz" instead. This is LeetCode 412.


So, here is the first solution that comes to mind. This isn't a unique solution, by any means, just the one most readily comes to mind.


FB1

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



The problem here is that the solution isn't exactly clever. It works, but that's about it. Another thing to worry about is that the program isn't really easily extended. How about if you want to add "Bazz" for numbers evenly divisible by 7? And add "Bang" for numbers evenly divisible by 9? You can see that hard coding the solution like that doesn't bring any prestige point to the programmer. As a side note, failing at the task will certainly bring shame to the programmer.


So, let's improve the solution. Thinking about it, the problem is that it has different states to the solution. Especially important is that you don't want to show the number if the answer is "Fizz", "Buzz", or both! That's a failure point, so be careful!


The standard professional engineering way to solve this is via states. Something like this:


FB2

void FizzBuzz2() {
  int i;
  int s=0;
  for (s=0,i=1;i<=100;s=0,i++) {
    if (!(i%3)) s+=1;
    if (!(i%5)) s+=2;
    switch (s) {
      case 0: printf("%d\n",i); break;
      case 1: printf("Fizz\n"); break;
      case 2: printf("Buzz\n"); break;
      case 3: printf("FizzBuzz\n"); break;
    }
  }
}


And that works. But it's somewhat big, over engineered program, isn't it? In fact, that is the professsional way to do things. I guess now you know why I'm firmly at the side of amateur hobbyist side. I no longer have any patience in overbearing bureaucratic structures. Well, if the program needs it, I don't mind. Usually, they don't need it, though. Let's simplify that monstrosity.


FB3

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


So, in fact, we only need one state. Are we printing number? Or not? We don't need to get fancy! And that's a good solution, too, albeit less structured, and perhaps a little bit more difficult to read. Let's compact the program even more!


FB4

void FizzBuzz4() {
  int i;
  for (i=1;i<=100;i++) {
    printf("%d\r%s%s\n",i,
    (i%3)?"":"Fizz",
    (i%5)?"":"Buzz");
  }
}


It does look like it works and it's only one line, but there's a trick to it. The output depends on the fact that it uses '\r' carriage return character, which means that the number is always displayed, but hidden when FizzBuzz occur. Visually, it's the same thing, but if you check the output via program such as diff, then it will fail. Still, that's a neat hack that you can do to impress people!


FB5

void FizzBuzz5() {
  int i=0;
  while(100>i++){switch(p("%s%s",(i
  %3)?"":"Fizz",(i%5)?"":"Buzz")) {
  case 0:p("%d",i);default:p("\n");
}}}


FB6

void FizzBuzz6() {
  for(int i=0;100>i++;)
  switch(p("%s%s",(i%3)
  ?"": "Fizz",(i%5)?"":
  "Buzz")){case 0:p("%d"
  ,i);default :p("\n");
}}


Then again, there is impressive, and just plain old ridiculous! There's only a fine line between the two.


One more thing: If you're wondering what's p(), it's printf(). I simply define it in the beginning of the program.


No comments:

Post a Comment