Hello! I was extremely bored and stumbled accross this website: Hackerrank
It's a website that contains lots of programming challenges of various types.
I signed up and looked at some of the challenges, lots of them are quite over my head since I'm not that skilled or any expert by any means so I thought I would try some of these challenges.

I stumbled across one called "FizzBuzz", the details are here: Click Here

So I program in D myself so I wrote my attempt in D but any feedback in C/C++ is also helpful because I know those as well.

So essentially the goal is to write the described goal in the shortest amount of characters possible which I attempted doing here:

import std.stdio;alias writeln w;void main(){int i;for(i=1;i<=100;i++){if(i%3==0&&i%5!=0)w("Fizz");if(i%3!=0&&i%5==0)w("Buzz");if(i%3==0&&i%5==0)w("FizzBuzz");if(i%3!=0&&i%5!=0)w(i);}}

I'm thinking you can't get it much shorter than this, I managed 184 characters and the site gave me a score of 0.08.
I peeked at the leader boards before I submitted only to see there are highscores of 15.20 which must be an extremely short program! Most of these people are writing in C/C++, I'm just curious if anyone has this mystical knowlege of minimizing the length of programs? This really surprises me a lot, I've never tried anything like this so any information would be appreciated, thanks everyone!

For a start, some compilers allow a declaration of a variable inside a for loop, eg for(int i=0;.... Also, you can cut out comparisons with 0 like if(i%3==0&&i%5!=0). If i%3 is 0, then it is effectively a boolean with value FALSE, otherwise it's a boolean TRUE. Also, you don't need three conditions, just two:

  • i%3 == 0 then printf("Fizz")
  • i%5 == 0 then printf"Buzz"
  • else printf("%d",i)
  • printf("\n")

This way you can cut the size down a wee bit

Edited 3 Years Ago by Assembly Guy

EDIT: Deleted because of buggy untested code

Edited 3 Years Ago by Assembly Guy: Deleted post's content because of buggy untested code

Great so with that brilliant advice I'm now down to 134 characters!

import std.stdio;alias write w;void main(){for(int i=1;i<=100;i++){if(i%3==0)w("Fizz");if(i%5==0)w("Buzz");if(i%3&&i%5)w(i);w("\n");}}

I don't really see anything else though...

Does D allow the use of int main(). That'd save one byte...

Instead of repeating sequences like ); and i%, see if making an alias for those could help. Also use <101 instead of <=100. Also, you've started to apply my thinking on the boolean logic, but you've not fully applied it, I can still see some comparisons with 0 in your code.

Edited 3 Years Ago by Assembly Guy

"Does D allow the use of int main()" Yes it does but the return declaration would be necessary and that would be more wasted space.

Would it simply not compile at all, or would there be a warning? While it's strictly 'illegal', a C compiler will sit there and frown at you for a bit, but end up compiling fine.

In that case, just go for other things I mentioned, such as if(!i%3) instead of if(i%3==0), as well as i<101 instead of i<=100. While its only a byte here or there, it'll soon add up...

Also, instead of repeating w(, could you alias w to equal write(? The same applies for ); - alias it for a letter you're not using, like q.

Edited 3 Years Ago by Assembly Guy

I guess I lied when I said it threw an error. It compiles fine but it doesn't work as expected, it doesn't return true ever. !i%3

I that a while after I wrote. It's performing the ! operation on i, then the modulo. It'd need brackets for example !(i%3). This puts it to the same length as i%3==0.

Oh! Good point! I never thought about that, especially tired at this time of night.

First, you should use i<101 instead of i<=100. Also, your for-loop could be like this for(int i=0;++i<101;). That's two characters saved. However, D allows for range-based for-loops too, so you could write foreach(i;1..101), that is 4 more characters saved.

Then, you can, in general, replace almost any sequence of if-statements with short-circuit logical OR or AND. For example, this code:

if(i%3==0) w("Fizz");

is equivalent to:

i%3||w("Fizz");

Then, you also forgot that you have the ternary ?: operator in your toolbox, you can use that to save the second comparison:

    i%3||w("Fizz");
    i%5?i%3&&w(i):w("Buzz");
    w("\n");

The final, indented version is this:

import std.stdio;
alias write w;
void main(){
  foreach(i;1..101){
    i%3||w("Fizz");
    i%5?i%3&&w(i):w("Buzz");
    w("\n");
  }
}

That takes the total down to 110 characters. And the score is 0.45.

Just for fun, I came up with this C90 version (C90, because C99 does not allow inferred-type main() function, in other words, a C90 compiler is required to tolerate this program, a C99 compiler will probably throw it out). And, it cannot be C++ because it relies on a tail-recursion on the main() function, which C++ does not allow, but C does.

C90:

#include<stdio.h>
#define w printf
main(i){
  i%3||w("Fizz");
  i%5?i%3&&w("%d",i):w("Buzz");
  w("\n");
  i<100&&main(i+1);
}

That's 110 characters, I don't know how it could possibly be much shorter. That gives me a score of 0.435.

Edited 3 Years Ago by mike_2000_17: some errors

The scores the preview/test mode gives are crap, I was being told I would get a 0.4-something, but upon submission, I got an 8.

Edited 3 Years Ago by Assembly Guy

Yeah, I think that the scores on the preview are normalized to 1. The maximum is 20 (with 0 characters), so, you take your number (e.g., 0.45) and multiply by 20 to get the real score (e.g., 9).

This article has been dead for over six months. Start a new discussion instead.