This commit is contained in:
Miloslav Ciz 2023-12-10 15:25:44 +01:00
parent 81f15502ff
commit bdb97c9d9f
5 changed files with 123 additions and 12 deletions

View file

@ -1,6 +1,21 @@
# FizzBuzz
TODO
FizzBuzz is a relatively simple programming problem that's famous/infamous by having a number of different approach solutions and is often used e.g. in interviews to test the skills of to-be-hired programmers. It comes from a child game that teaches basic integer division in which kids are supposed to shout a specific word if a number is divisible by some other number -- what's of interest about the problem is not the solution itself (which is trivial) but rather how one should structure an [algorithm](algorithm.md) that solves the problem. The problem is stated as follows:
*Write a program that writes out numbers from 1 to 100 (including both); however if a number is divisible by 3, write "Fizz" instead of the number, if the number is divisible by 5, write "Buzz" instead of it and if it is divisible by both 3 and 5, write "FizzBuzz" instead of it.*
The statement may of course differ slightly, for example in saying how the output should be formatted or by specifying goals such as "make the program as short as possible" or "make the program as fast as possible". For the sake of this article let's consider the following the correct output of the algorithm:
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26,
Fizz, 28, 29, FizzBuzz, 31, 32, Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz, 41, Fizz, 43, 44, FizzBuzz, 46, 47, Fizz, 49, Buzz, Fizz, 52, 53, Fizz, Buzz, 56, Fizz, 58, 59, FizzBuzz, 61, 62, Fizz, 64, Buzz, Fizz, 67, 68, Fizz, Buzz, 71, Fizz, 73, 74, FizzBuzz, 76, 77, Fizz, 79, Buzz, Fizz, 82, 83, Fizz, Buzz, 86, Fizz, 88, 89, FizzBuzz, 91, 92, Fizz, 94, Buzz, Fizz, 97, 98, Fizz, Buzz
**Why the fuss around FizzBuzz?** Well, firstly it dodges an obvious single elegant solution that many similar problems usually have and it leads a beginner to a difficult situation that can reveal a lot about his experience and depth of his knowledge. The tricky part lies in having to check not only divisibility by 3 and 5, but also by BOTH at once, which when following basic programming instincts ("just if-then-else everything") leads to inefficiently checking the same divisibility twice and creating some extra ugly if branches and also things like reusing [magic constants](magic_constant.md) in multiple places, conflicting the "[DRY](dry.md)" principle etc. It can also show if the guy knows things usually unknown to beginners such as that the modulo operation with non-power-of-two is usually expensive and we want to minimize its use. However it is greatly useful even when an experienced programmer faces it because it can serve a good, deeper discussion about things like [optimization](optimization.md); while FizzBuzz itself has no use and optimizing algorithm that processes 100 numbers is completely pointless, the problem is similar to some problems in practice in which the approach to solution often becomes critical, considering [scalability](scalability.md). In practice we may very well encounter FizzBuzze's big brother, a problem in which we'll need to check not 100 numbers but 100 million numbers per second and check not only divisibility by 3 and 5, but by let's say all [prime numbers](prime.md). Problems like this come up e.g. in [cryptography](cryptography.md) all the time, so we really have to come to discussing [time complexity](time_complexity.md) classes, [instruction sets](isa.md) and hardware acceleration, [parallelism](parallelism.md), possibly even [quantum computing](quantum.md), different [paradigm](paradigm.md)s etc. So really FizzBuzz is like a kind of great conversation starter, a bag of topics, a good training example and so on.
## Implementations
Let's see how we can implement, improve and [optimize](optimization.md) FizzBuzz in [C](c.md). Keep in mind the question of scalability, i.e. try to imagine how the changes we make to the algorithm would manifest if the problem grew, i.e. if for example we wanted to check divisibility by many more numbers than just 1 and 5 etc. We will only focus on optimizing the core of the algorithm, i.e. the divisibility checking, without caring about other things like optimizing printing the commas between numbers and whatnot. Also we'll be supposing all compiler optimization are turned off so that you the excuse "compiler will optimize this" can't be used :)
For starters let us write a kind of vanilla, [naive](naive.md) solution that everyone will likely come up with as his first attempt. A complete noob will fail to produce even this basic version, a slightly advanced programmer (we might say a "[coder](coding.md)") may submit this as the [final solution](final_solution.md).
```
#include <stdio.h>
@ -8,14 +23,104 @@ TODO
int main(void)
{
for (int i = 1; i <= 100; ++i)
switch ((i % 3 == 0) + (i % 5 == 0) * 2)
{
case 1: printf("Fizz\n"); break;
case 2: printf("Buzz\n"); break;
case 3: printf("FizzBuzz\n"); break;
default: printf("%d\n",i); break;
}
{
if (i != 1)
printf(", ");
if (i % 3 == 0 && i % 5 == 0)
printf("FizzBuzz");
else if (i % 3 == 0) // checking divisibility by 3 again :/
printf("Fizz");
else if (i % 5 == 0) // checking divisibility by 5 again :/
printf("Buzz");
else
printf("%d",i);
}
putchar('\n');
return 0;
}
```
It [works](just_werks.md), however with a number of issues. Firstly we see that for every number we check we potentially test the divisibility by 3 and 5 twice, which is not good, considering division (and modulo) are one of the slowest instructions. We also reuse the magic constants 3 and 5 in different places, which would start to create a huge mess if we were dealing with many more divisors. There is also a lot of branching, in the main divisibility check we may jump up to three times for the checked number -- jump instruction are slow and we'd like to avoid them (again, consider we were checking e.g. divisibility by 1000 different numbers).
When asked to optimize the algorithm a bit one might come up with something like this:
```
#include <stdio.h>
int main(void)
{
for (int i = 1; i <= 100; ++i)
{
if (i != 1)
printf(", ");
int printNum = 1;
if (i % 3 == 0)
{
printf("Fizz");
printNum = 0;
}
if (i % 5 == 0)
{
printf("Buzz");
printNum = 0;
}
if (printNum)
printf("%d",i);
}
putchar('\n');
return 0;
}
```
Now we check the divisibility by 3 and 5 only once for each tested number, and also keep only one occurrence of each constant in a single place, that's good. But we still keep the slow branching.
A bit more experienced programmer may now come with something like this:
```
#include <stdio.h>
int main(void)
{
for (int i = 1; i <= 100; ++i)
{
if (i != 1)
printf(", ");
switch ((i % 3 == 0) + ((i % 5 == 0) << 1))
{
case 1: printf("Fizz"); break;
case 2: printf("Buzz"); break;
case 3: printf("FizzBuzz"); break;
default: printf("%d",i); break;
}
}
putchar('\n');
return 0;
}
```
This solution utilizes a [switch](switch.md) structure to only perform single branching in the divisibility check, based on a 2 bit value that in its upper bit records divisibility by 5 and in the lower bit divisibility by 3. This gives us 4 possible values: 0 (divisible by none), 1 (divisible by 3), 2 (divisible by 5) and 3 (divisible by both). The switch structure by default creates a jump table that branches right into the correct label in O(1).
TODO: optimize this further to no jump at all, just by offsetting the string to be printed
If the problem asks for shortest code, even on detriment of [readability](readability.md) and efficiency, we might try **the [code golfer](code_golf.md) approach**:
```
#include <stdio.h>
#define P printf
int i;int main(){while(i<100){if(i++)P(", ");int a=!(i%3)+!(i%5)*2;
if(a)P("FizzBuzz\0Fizz"+(4+(a==1)*5)*(a!=3));else P("%d",i);}P("\n");}
```
It's almost definitely not minimal but can be a good start.
TODO: comun

View file

@ -346,3 +346,7 @@ XX XX XX XX XX XX X
```
TODO: some example with noise
## See Also
- [algorithmic art](algorithmic_art.md)

View file

@ -4,6 +4,8 @@ Thrembo (also hidden or forbidden number) is allegedly a "fictional" whole numbe
How can there be an integer between 6 and 7? Well, that's what thrembologists research. Sure, normally there is no space on the number line to fit a number between 6 and 7 so that its distance is 1 to both its neighbors, however this only holds due to simplifications we naively assume because of our limited IQ; one may for example imagine a curved, non Euclidean number line (:'D) on which this is possible, just like we can draw a triangle with three right angles on a surface of a sphere. In history we've naysayer proven wrong in mathematics, for example those who claimed there is no solution to the equation *x^2 = -1*; some chad just came and threw at us a new number called [i](i.md) (he sneakily made it just a letter so that he doesn't actually have to say how much it ACTUALLY equals), he just said "THIS NUMBR IS HENCEFORTH THE SOLUTION BECAUSE I SAY SO" and everyone was just forced to admit defeat because no one actually had a bigger authority than this guy. That's how real mathematics is done kids. As we see e.g. with [political correctness](political_correctness.md), with enough propaganda anything can be force-made a fact, so if the number gets enough likes on twitter, it will just BE.
Some pressing questions about thrembo remaining to be researched are following. Is thrembo even of odd? Is it a [prime](prime.md)? If such number can exist between 6 and 7, can similar numbers exist between other "mainstream" numbers?
## See Also
- [schizophrenic number](schizo_number.md)

2
usa.md
View file

@ -1,6 +1,6 @@
# USA
United States of America (also United Shitholes of America, USA, US or just "murika") is a [dystopian](dystopia.md) country of fat, stupid dumbasses enslaved by [capitalism](capitalism.md), either rightist or [pseudoleftist](pseudoleft.md) [fascists](fascism.md) endlessly obsessed with [money](money.md), [wars](war.md), [fighting](fight_culture.md), shooting their presidents and shooting up their schools. USA consists of 50 states located in North America, a continent that ancestors of Americans invaded and have stolen from Indians, the natives whom Americans mass murdered. Americans are stupid idiots with guns who above all value constant societal conflict and make the world so that all people are dragged into such conflict.
United States of America (also United Shitholes of America, USA, US or just "murika") is a [dystopian](dystopia.md) imperialist country of fat, stupid dumbasses enslaved by [capitalism](capitalism.md), either rightist or [pseudoleftist](pseudoleft.md) [fascists](fascism.md) endlessly obsessed with [money](money.md), [wars](war.md), [fighting](fight_culture.md), shooting their presidents and shooting up their schools. USA consists of 50 states located in North America, a continent that ancestors of Americans invaded and have stolen from Indians, the natives whom Americans mass murdered. Americans are stupid idiots with guns who above all value constant societal conflict and make the world so that all people are dragged into such conflict.
USA is very similar to [North Korea](north_korea.md): in both countries the people are successfully led to believe their country is the best and have strong propaganda based on [cults of personality](cult_of_personality.md), which to outsiders seem very ridiculous but which is nevertheless very effective: for example North Korea officially proclaims their supreme leader Kim Jong-il was born atop a sacred mountain and a new star came to existence on the day of his birth, while Americans on the other hand believe one of their retarded leaders named George Washington was a divine god who was PHYSICALLY UNABLE TO TELL A LIE, which was actually taught at their schools. North Korea is ruled by a single political party, US is ruled by two practically same militant capitalist imperialist parties (democrats and republicans), i.e. de-facto one party as well. Both countries are obsessed with weapons (especially nuclear ones) and their military, both are highly and openly [fascist](fascism.md) (nationalist). Both countries are full of extreme [propaganda](propaganda.md), [censorship](censorship.md) and [hero culture](hero_culture.md), people worship dictators such as Kim Jong-un or [Steve Jobs](steve_jobs.md). US is even worse than North Korea because it exports its toxic [culture](culture.md) all over the whole world and constantly invades other countries, it is destroying all other cultures and leads the whole world to doom and destruction of all life, while North Korea basically only destroys itself.

View file

@ -36,7 +36,7 @@ Articles should be written to be somewhat readable and understandable to tech sa
These are some sources you can use for research and gathering information for articles:
- **paper [encyclopedias](encyclopedia.md)!** Consult these often, they are much better than any online resource, contain obscure, forgotten info and alternative points of view.
- **[Wikipedia](wikipedia.md)**: of course, but don't limit your search to it. Searching other language Wikipedias with machine translate can also help find extra info.
- **[Wikipedia](wikipedia.md)**: of course, but don't limit your search to it. Searching other language Wikipedias with machine translate can also help find extra info. If you know other languages than English, search that languages Wikipedia, it may have extra info. Also languages like Scots are understandable to English speakers, so try that as well.
- **[Citizendium](citizendium.md)**: can offer a different angle of view from Wikipedia.
- **non-SJW forks of Wikipedia**: to get past SWJ censorship/propaganda on Wikipedia try e.g. **[infogalactic](infogalactic.md)** or **[metapedia](metapedia.md)**.
- **Britannica online**: proprietary, but articles are nicely written, facts are in the public domain so we can steal them.