master
Miloslav Ciz 10 months ago
parent 59e56a6987
commit e89960bcfb

@ -9,6 +9,7 @@ Example of approximations:
- **[Distances](distance.md)**: instead of expensive **Euclidean** distance (`sqrt(dx^2 + dy^2)`) we may use **Chebyshev** distance (`dx + dy`) or **Taxicab** distance (`max(dx,dy)`).
- **Engineering approximations** ("guesstimations"): e.g. **sin(x) = x** for "small" values of *x* or **pi = 3** (integer instead of float).
- **Physics engines**: complex triangle meshes are approximated with simple analytical shapes such as **spheres**, **cuboids** and **capsules** or at least **convex hulls** which are much easier and faster to deal with. They also approximate **relativistic** physics with **Newtonian**.
- **Addition/subtraction** can sometimes be approximates with [OR](or.md)/[AND](and.md) operation, as they behave a bit similarly. This can be used e.g. for brightening/darkening of pixel colors in [332](rgb332.md) or [565](rgb565.md) format -- without the approximation addition of colors in these formats is very expensive (basically requires conversion to RGB, addition, clamping and a conversion back).
- **Real time graphics engines**, on the other hand, normally approximate all shapes with triangle meshes.
- **[Ray tracing](ray_tracing.md)** neglects indirect lighting. Computer graphics in general is about approximating the solution of the rendering equation.
- **Real numbers** are practically always approximated with [floating point](floating_point.md) or [fixed point](fixed_point.md) (rational numbers).

@ -1,6 +1,6 @@
# Bill Gate$
William "Bill" Gates (28.10.1955 -- TODO) is a [mass murderer and rapist](entrepreneur.md) (i.e. [capitalist](capitalism.md)) who established and led the terrorist organization [Micro$oft](microsoft.md). He is one of the most rich and evil individuals in history who took over the world by force establishing the [malware](malware.md) operating system [Window$](windows.md) as the common operating system, nowadays being dangerous especially by hiding behind his "charity organization" (see [charitywashing](charitywashing.md)) which has been widely criticized (see e.g. http://techrights.org/wiki/Gates_Foundation_Critique, even such mainstream media as [Wikipedia](wikipedia.md) present the criticism) but which nevertheless makes him look as someone doing "public good" in the eyes of the naive brainless [NPC](npc.md) masses.
William "Bill" Gates (28.10.1955 -- TODO) is a [mass murderer and rapist](entrepreneur.md) (i.e. [capitalist](capitalism.md)) who established and led the terrorist organization [Micro$oft](microsoft.md). He is one of the most rich and evil individuals in history who took over the world by force establishing the [malware](malware.md) "[operating system](os.md)" [Window$](windows.md) as the common operating system, nowadays being dangerous especially by hiding behind his "charity organization" (see [charitywashing](charitywashing.md)) which has been widely criticized (see e.g. http://techrights.org/wiki/Gates_Foundation_Critique, even such mainstream media as [Wikipedia](wikipedia.md) present the criticism) but which nevertheless makes him look as someone doing "public good" in the eyes of the naive brainless [NPC](npc.md) masses.
He is really dumb, only speaks one language and didn't even finish university. He also has no moral values, but that goes without saying for any rich businessman. He was owned pretty hard in [chess](chess.md) by Magnus Carlsen on some shitty TV show.

@ -68,7 +68,7 @@ TODO: more examples
## Compiler Optimizations
C compilers perform automatic optimizations and other transformations of the code, especially when you tell it to optimize aggressively (`-O3`) which is a standard practice to make programs run faster. However this makes compilers perform a lot of [magic](magic.md) and may lead to unexpected and unintuitive undesired behavior such as bugs or even the "unoptimization of code". { I've seen a code I've written have bigger size when I set the `-Os` flag (optimize for smaller size). ~drummyfish }
C compilers perform automatic optimizations and other transformations of the code, especially when you tell them to optimize aggressively (`-O3`) which is a standard practice to make programs run faster. However this makes compilers perform a lot of [magic](magic.md) and may lead to unexpected and unintuitive undesired behavior such as bugs or even the "unoptimization of code". { I've seen a code I've written have bigger size when I set the `-Os` flag (optimize for smaller size). ~drummyfish }
Aggressive optimization may firstly lead to tiny bugs in your code manifesting in very weird ways, it may happen that a line of code somewhere which may somehow trigger some tricky [undefined behavior](undefined_behavior.md) may cause your program to crash in some completely different place. Compilers exploit undefined behavior to make all kinds of big brain reasoning and when they see code that MAY lead to undefined behavior a lot of chain reasoning may lead to very weird compiled results. Remember that undefined behavior, such as overflow when adding signed integers, doesn't mean the result is undefined, it means that ANYTHING CAN HAPPEN, the program may just start printing nonsensical stuff on its own or your computer may explode. So it may happen that the line with undefined behavior will behave as you expect but somewhere later on the program will just shit itself. For these reasons if you encounter a very weird bug, try to disable optimizations and see if it goes away -- if it does, you may be dealing with this kind of stuff. Also check your program with tools like [cppcheck](cppcheck.md).

@ -14,4 +14,8 @@ For its simplicity there is no [bytecode](bytecode.md) which would allow for mor
TODO: example
{ I've been looking at the source and unfortunately there are some imperfections. The code uses [goto](goto.md) (may not be bad but I dunno). Also unfortunately stdlib, stdio, string and other standard libraries are used as well as [malloc](malloc.md). The code isn't really commented and I find the style kind of hard to read. }
{ I've been looking at the source and unfortunately there are some imperfections. The code uses [goto](goto.md) (may not be bad but I dunno). Also unfortunately stdlib, stdio, string and other standard libraries are used as well as [malloc](malloc.md). The code isn't really commented and I find the style kind of hard to read. }
## See Also
- [comun](comun.md)

@ -2,9 +2,9 @@
The question of how to make a living by making something that's to be given out for free and without limitations is one of the most common in the context of [FOSS](foss.md)/[free culture](free_culture.md). Noobs often avoid this area just because they think it can't be done, even though there are ways of doing this and there are many people making living on FOSS, albeit ways perhaps more challenging than those of [proprietary](proprietary.md) products.
One has to be aware that **money and commercialization always brings a high risk of profit becoming the highest priority** (which is a "feature" hard-wired in [capitalism](capitalism.md)) which will compromise the quality and ethics of the produced work. Profiting specifically requires abusing someone else, taking something away from them. Therefore **it is ideal to create [LRS](lrs.md) on a voluntary basis, for free, in the creator's spare time**. This may be difficult to do but one can choose a lifestyle that minimizes expenses and therefore also time needed to spend at [work](work.md), which will give more free time for the creation of [LRS](lrs.md). This includes living frugally, not consuming hardware and rather reusing old machines, making savings, not spending on unnecessary things such as smoking or fashion etc. And of course, if you can't make LRS full-time, you can still find relatively ethical ways of it supporting you and so, again, giving you a little more freedom and resources for creating it.
One has to be aware that **money and commercialization always brings a high risk of profit becoming the highest priority** (which is a "feature" hard-wired in [capitalism](capitalism.md)) which will compromise the quality and ethics of the produced work. Profiting specifically requires abusing someone else, taking something away from them. Therefore **it is ideal to create [LRS](lrs.md) on a voluntary basis, for free, in the creator's spare time**. This may be difficult to do but one can choose a lifestyle that minimizes expenses and therefore also time needed to spend at [work](work.md), which will give more free time for the creation of [LRS](lrs.md). This includes living frugally, not consuming hardware and rather reusing [old machines](ancientware.md), making savings, not spending on unnecessary things such as smoking or fashion etc. And of course, if you can't make LRS full-time, you can still find relatively ethical ways of it supporting you and so, again, giving you a little more freedom and resources for creating it.
Also if can somehow rip off a rich corporation and get some money for yourself, do it. Remember, corporations aren't people, they can't feel pain, they probably won't even notice their loss and even if you hurt them, you help the society by hurting a predator.
Also if you can somehow rip off a rich corporation and get some money for yourself, do it. Remember, corporations aren't people, they can't feel pain, they probably won't even notice their loss and even if you hurt them, you help the society by hurting a predator.
**Is programming software the only way to make money with LRS?** No, you can do anything related to LRS and you don't even have to know [programming](programming.md). You can create [free](free_culture.md) art such as [game](game.md) assets or writings, you can educate, write articles etc.
@ -20,7 +20,7 @@ Working for [free software](free_software.md) organizations such as the [FSF](fs
Considering all things mentioned above, here are some concrete things of making money on LRS. Keep in mind that a lot of services (PayPal, Patreon etc.) listed here may possibly be [proprietary](proprietary.md) and unethical, so always check them out and consider free alternatives such as [Liberapay](liberapay.md). The methods are following:
- **[donations](donation.md)**: You may ask for donations e.g. on your website or Patreon (people often ask for [cryptocurrencies](crypto.md) or traditional money via services like [Liberapay](liberapay.md), PayPal or Buy Me a Coffee). For significant earnings you need to be somewhat popular because people donate extremely rarely, but if your work is good, there sometimes appears a generous donor who sends you a lot of money ({Happened to me at least once. I hereby thank the person greatly. ~drummyfish}). It can help if you create "content" such as programming videos alongside your project to get some "following", but it may also distract you and take some of your energy. People like [Luke Smith](luke_smith.md) make quite some big money like this. A lot of [free culture](free_culture.md) artists are successful in creating free art this way.
- **[donations](donation.md)**: You may ask for donations e.g. on your website or Patreon (people often ask for [cryptocurrencies](crypto.md) or traditional money via services like [Liberapay](liberapay.md), PayPal or Buy Me a Coffee). For significant earnings you need to be somewhat popular because people donate extremely rarely, but if your work is good, there sometimes appears a generous donor who sends you a lot of money ({Happened to me a few times. I hereby thank all those kind people <3 ~drummyfish}). It can help if you create "content" such as programming videos alongside your project to get some "following", but it may also distract you and take some of your energy. People like [Luke Smith](luke_smith.md) make quite some big money like this. A lot of [free culture](free_culture.md) artists are successful in creating free art this way.
- **[crowd funding](crowd_funding.md)**: A method similar to donations but a little more "encouraging" for the donors. You set a financial goal and if enough people donate to reach that goal, you get the money and create the project. Patreon and Kickstarter are typically used for this.
- **[pay what you want](pay_what_you_want.md)**: Here you create the work and then offer a download with optional payment, typically with some suggested price. People who can't afford to pay don't have to. This method has the advantage of not putting you under deadline pressures like the crowd funding method. Sites like [itch.io](https://itch.io/) are friendly to this option.
- **selling physical products and [merchandise](merch.md)** ("merch"): This method makes use of the fact that selling physical items is considered less (even though not completely!) unethical, unlike selling copies of information. So you can e.g. create a [free](free_software.md) video [game](game.md) and then sell T-shirts or coffee mugs with that video game's themes. In the past some [GNU](gnu.md)/[Linux](linux.md) distros used to sell their systems on nice "officials" CDs, but nowadays CDs are kind of dead. [Open consoles](open_console.md) kind of do this as well, they create [FOSS](foss.md) games and tools and then sell hardware that runs these games.

@ -12,9 +12,9 @@ The definition here is not strict but rather fuzzy, it is in a form of ideas, st
[Software](software.md) is less retarded if it adheres, to a high-degree (not necessarily fully), to the following principles:
- Being made with a [**truly selfless**](selfless.md) goal of maximally helping all living beings who may use the software without any intent of taking advantage of them in any way.
- Being made with a [**truly selfless**](selflessness.md) goal of maximally helping all living beings who may use the software without any intent of taking advantage of them in any way.
- Trying to follow the [Unix philosophy](unix_philosophy.md) (do one thing well, use text interfaces, ...).
- Trying to follow the [suckless](suckless.md) philosophy (configs as source files, distributing in source form, ...).
- Trying to follow the [suckless](suckless.md) philosophy (configs as source files, distributing in source form, mods as patches, ...).
- Being [minimalist](minimalism.md) ([single compilation unit](single_compilation_unit.md), [header-only](header_only.md) libraries, no build systems, no [OOP](oop.md) languages, simple [version numbering](version_numbering.md), ...), [countercomplex](countercomplex.md), [KISS](kiss.md), [appropriate technology](appropriate_tech.md).
- Being [free software](free_software.md) legally but ALSO practically (well commented, not bloated and obscured etc., so as to truly and practically enable the freedoms to study, modify etc.). This may also include attributes such as [decentralization](decentralization.md).
- Being [free culture](free_culture.md), i.e. LRS programs are free as a whole, including art assets, data etc.

@ -1,8 +1,8 @@
# Mathematics
Mathematics (also math or maths) is the best [science](science.md) (yes, it is a formal science), which deals with numbers, abstract structures and [logic](logic.md) in as rigorous and objective way as possible. In fact it's the only true science that can actually prove things. It is immensely important in [programming](programming.md) and [computer science](compsci.md).
Mathematics (also math or maths) is the best [science](science.md) (yes, it is a formal science), which deals with [numbers](number.md), abstract structures and [logic](logic.md) in as rigorous and objective way as possible. In fact it's the only true science that can actually prove things. It is immensely important in [programming](programming.md) and [computer science](compsci.md).
Some see math not as a science but rather a discipline that develops formal tools for "true sciences". The reasoning is usually that a science has to use [scientific method](scientific_method.md), but that's a limited view as scientific method is not the only way of obtaining reliable knowledge. Besides that math can and does use the principles of scientific method -- mathematicians first perform "experiments" with numbers and generalize into [conjectures](conjecture.md), however this is not considered [good enough](good_enough.md) in math as it actually has the superior tool of [proof](proof.md) that is considered the ultimate goal of math. I.e. math relies on [deductive](deduction.md) reasoning (proof) rather than less reliable [inductive](induction.md) reasoning (scientific method) -- in this sense mathematics is more than a science.
Some see math not as a science but rather a discipline that develops formal tools for "true sciences". The reasoning is usually that a science has to use [scientific method](scientific_method.md), but that's a limited view as scientific method is not the only way of obtaining reliable knowledge. Besides that math can and does use the principles of scientific method -- mathematicians first perform "experiments" with numbers and generalize into [conjectures](conjecture.md) and later "strong beliefs", however this is not considered [good enough](good_enough.md) in math as it actually has the superior tool of [proof](proof.md) that is considered the ultimate goal of math. I.e. math relies on [deductive](deduction.md) reasoning (proof) rather than less reliable [inductive](induction.md) reasoning (scientific method) -- in this sense mathematics is more than a science.
[Soydevs](soydev.md), coding monkeys (such as webdevs) and just retards in general hate math because they can't understand it. They think they can do programming without math, which is just ridiculous. This delusion stems mostly from these people being highly incompetent and without proper education -- all they've ever seen was a shallow if-then-else [python](python.md) "[coding](coding.md)" of baby programs or point-and-click "coding" in gigantic [GUI](gui.md) frameworks such as [Unity](unity.md) where everything is already preprogrammed for them. By DunningKruger they can't even see how incompetent they are and what real programming is about. In reality, this is like thinking that being able to operate a calculator makes you a capable mathematician or being able to drive a car makes you a capable car engineer. Such people will be able to get jobs and do some repetitive tasks such as web development, [Unity](unity.md) game development or system administration, but they will never create anything innovative and all they will ever make will be ugly, [bloated](bloat.md) [spaghetti](spaghetti.md) solution that will likely do more harm than good.

@ -15,7 +15,7 @@ For start let's see which kinds of allocation (and their associated parts of mem
- **static allocation (code/data memory)**: Simplest kind of allocation happening at compile time: if the compiler can do so (i.e. if it knows enough things such as the size of the data in advance), it allocates space of concrete size at some specific address in the part of memory reserved for code or static data (code and data may be in the same or separate parts depending on platform, see e.g. [Harvard architecture](harvard.md)) -- this is straightforward, simple, automatic and poses no real dangers, bloat or burden of dependencies. This kind of allocation applies to:
- **global variables** (variables declared outside any function, i.e. even outside `main`)
- **static variables** (variables inside functions declared with `static` keyword)
- **constants/literals** (i.e. concrete numbers/strings in the source code such as `123` or `"abc"`)
- **constants/literals** (e.g. strings in the source code such as `"abc"`)
- **automatic allocation (stack memory)**: For local variables (variables inside functions) the memory is allocated in a special part of memory known as **call [stack](stack.md)** only at the time when the function is actually called and executed; i.e. this is similar to dynamic allocation (it happens at run time) but happens automatically, without needing any libraries or other explicit actions from the programmer. I.e. when a function is called at run time, a new *call frame* is created on stack which includes space for local variables of that function (along with e.g. return address from the function etc.). This is necessary e.g. to allow [recursion](recursion.md) (during which several instances of the same function may be active, each of which may have different values of its variables), and it also helps consume less RAM. This allows for creating variable sized arrays inside functions (e.g. `int array[x];` where `x` is variable) which is not possible to do with a global array (however variable size arrays aren't supported in old ANSI C!). The disadvantage over dynamic allocation is that stack memory is relatively small and overusing it may easily cause stack [overflow](overflow.md) (running out of memory). Still this kind of allocation is better than dynamic allocation as it doesn't need any libraries, it doesn't generate complex code and the only danger is that of stack overflow -- memory leaks can't happen (deallocation happens automatically when function is exited). Automatic allocation applies to:
- **local variables** (including function arguments and local **variable size arrays**)
- **dynamic allocation (heap memory)**: A kind of more complex manual allocation that happens at run time and is initiated by the programmer calling special functions such as `malloc` from the `stdlib` standard library, which return [pointers](pointer.md) to the allocated memory. This memory is taken from a special part of memory known as **[heap](heap.md)**. This allows to allocate, resize and deallocate potentially very big parts of memory, but requires caution as working with pointers is involved and there is a danger of **memory leaks** -- it is the responsibility of the programmer to free allocated memory with the `free` function once it is no longer needed, otherwise that memory will simply remain allocated and unusable by others (if this happens for example in a loop, the program may just start eating up more and more RAM and eventually run out of memory). Dynamic allocation is also pretty complex (it usually involves communicating with operating system and also keeping track of the structure of memory) and creates a [dependency](dependency.md) on the `stdlib` library. Some implementations of the allocation functions are also infamously slow (up to the point of some programmers resorting to program their own dynamic allocation systems). Therefore only use dynamic allocation when absolutely necessary! Dynamic allocation applies to:
@ -25,9 +25,6 @@ Rule of the thumb: use the simplest thing possible, i.e. static allocation if yo
For [pros](pro.md): you can also create your own kind of pseudo dynamic allocation in pure C if you really want to avoid using stdlib or can't use it for some reason. The idea is to allocate a big chunk of memory statically (e.g. global `unsigned char myHeap[MY_HEAP_SIZE];`) and then create functions for allocating and freeing blocks of this static memory (e.g. `myAlloc` and `myFree` with same signatures as `malloc` and `free`). This allows you to use memory more efficiently than if you just dumbly (is it a word?) preallocate everything statically, i.e. you may need less total memory; this may be useful e.g. on [embedded](embedded.md). Yet another uber [hack](hacking.md) to "improve" this may be to allocate the "personal heap" on the stack instead of statically, i.e. you create something like a global pointer `unsigned char *myHeapPointer;` and a global variable `unsigned int myHeapSize;`, then somewhere at the beginning of `main` you compute the size `myHeapSize` and then create a local array `myHeap[myHeapSize]`, then finally set the global pointer to it as `myHeapPointer = myHeap`; the rest remains the same (your allocation function will access the heap via the global pointer). Just watch out for reinventing wheels, bugs and that you actually don't end up with a worse mess that if you took a more simple approach. Hell, you might even try to write your own garbage collection and array bound checking and whatnot, but then why just not fuck it and use an already existing abomination like [Java](java.md)? :)
Finally let's see some simple code example:
```

@ -45,6 +45,7 @@ There are many terms that are very similar and are sometimes used interchangeabl
- **[directed acyclic graph](dag.md)** vs **[tree](tree.md)**
- **[directory](directory.md)** vs **[folder](folder.md)**
- **[discrete Fourier transform](dft.md)** vs **[discrete time Fourier transform](dtft.md)**
- **[emoticon](emoticon.md)** vs **[emoji](emoji.md)** vs **[smiley](smiley.md)**
- **[emulation](emulation.md)** vs **[simulation](simulation.md)**
- **[equation](equation.md)** vs **[expression](expression.md)** vs **[inequality](inequality.md)**
- **[equivalence](equivalence.md)** vs **[implication](implication.md)**

@ -56,44 +56,7 @@ The following is a general purpose 256 color palette made by [drummyfish](drummy
#200012 #400024 #600036 #800048 #a0005a #c0006c #e0007e #ff008f
```
Another generally usable 256 color palette is the [332](332.md) palette which can be used as an implicit palette -- it doesn't have to be stored in memory because in the 332 format the color index determines the color in the following way: the upper 3 bits encode the amount of red, the following 3 bits encode the amount of green and the remaining 2 bits encode the amount of blue (blue gets fewest bits because human eye is least sensitive to it). The RGB values of this palette are following.
```
#000000 #000055 #0000aa #0000ff #002400 #002455 #0024aa #0024ff
#004800 #004855 #0048aa #0048ff #006d00 #006d55 #006daa #006dff
#009100 #009155 #0091aa #0091ff #00b600 #00b655 #00b6aa #00b6ff
#00da00 #00da55 #00daaa #00daff #00ff00 #00ff55 #00ffaa #00ffff
#240000 #240055 #2400aa #2400ff #242400 #242455 #2424aa #2424ff
#244800 #244855 #2448aa #2448ff #246d00 #246d55 #246daa #246dff
#249100 #249155 #2491aa #2491ff #24b600 #24b655 #24b6aa #24b6ff
#24da00 #24da55 #24daaa #24daff #24ff00 #24ff55 #24ffaa #24ffff
#480000 #480055 #4800aa #4800ff #482400 #482455 #4824aa #4824ff
#484800 #484855 #4848aa #4848ff #486d00 #486d55 #486daa #486dff
#489100 #489155 #4891aa #4891ff #48b600 #48b655 #48b6aa #48b6ff
#48da00 #48da55 #48daaa #48daff #48ff00 #48ff55 #48ffaa #48ffff
#6d0000 #6d0055 #6d00aa #6d00ff #6d2400 #6d2455 #6d24aa #6d24ff
#6d4800 #6d4855 #6d48aa #6d48ff #6d6d00 #6d6d55 #6d6daa #6d6dff
#6d9100 #6d9155 #6d91aa #6d91ff #6db600 #6db655 #6db6aa #6db6ff
#6dda00 #6dda55 #6ddaaa #6ddaff #6dff00 #6dff55 #6dffaa #6dffff
#910000 #910055 #9100aa #9100ff #912400 #912455 #9124aa #9124ff
#914800 #914855 #9148aa #9148ff #916d00 #916d55 #916daa #916dff
#919100 #919155 #9191aa #9191ff #91b600 #91b655 #91b6aa #91b6ff
#91da00 #91da55 #91daaa #91daff #91ff00 #91ff55 #91ffaa #91ffff
#b60000 #b60055 #b600aa #b600ff #b62400 #b62455 #b624aa #b624ff
#b64800 #b64855 #b648aa #b648ff #b66d00 #b66d55 #b66daa #b66dff
#b69100 #b69155 #b691aa #b691ff #b6b600 #b6b655 #b6b6aa #b6b6ff
#b6da00 #b6da55 #b6daaa #b6daff #b6ff00 #b6ff55 #b6ffaa #b6ffff
#da0000 #da0055 #da00aa #da00ff #da2400 #da2455 #da24aa #da24ff
#da4800 #da4855 #da48aa #da48ff #da6d00 #da6d55 #da6daa #da6dff
#da9100 #da9155 #da91aa #da91ff #dab600 #dab655 #dab6aa #dab6ff
#dada00 #dada55 #dadaaa #dadaff #daff00 #daff55 #daffaa #daffff
#ff0000 #ff0055 #ff00aa #ff00ff #ff2400 #ff2455 #ff24aa #ff24ff
#ff4800 #ff4855 #ff48aa #ff48ff #ff6d00 #ff6d55 #ff6daa #ff6dff
#ff9100 #ff9155 #ff91aa #ff91ff #ffb600 #ffb655 #ffb6aa #ffb6ff
#ffda00 #ffda55 #ffdaaa #ffdaff #ffff00 #ffff55 #ffffaa #ffffff
```
A similar one is the [565](565.md) palette that uses 2 bytes to encode RGB with 5 bits for red, 6 for green and 5 for blue (most bits are allocated to green to which human eye is most sensitive).
Other common palettes include [RGB332](rgb332.md) (256 colors, one byte represents RGB with 3, 3 and 2 bits for R, G and B) and [RGB565](rgb565.md) (65536 colors, two bytes represent RGB with 5, 6 and 5 bits for R, G and B).
## See Also

@ -0,0 +1,55 @@
# RGB332
RGB332 is a general 256 color [palette](palette.md) that encodes one color with 1 byte (i.e. 8 bits): 3 bits for red, 3 bits for green and 2 bits for blue (human eye is least sensitive to blue). RGB332 is an implicit palette -- it doesn't have to be stored in memory because the color index itself determines the color and vice versa. Compared to the classic 24 bit RGB (which assigns 8 bits to each of the RGB components), RGB332 is very "[KISS](kiss.md)/[suckless](suckless.md)" and often [good enough](good_enough.md) (especially with [dithering](dithering.md)) as it saves memory, avoids headaches with [endianness](byte_sex.md) and represents each color with just a single number (as opposed to 3), so it is often used in simple and limited computers such as [embedded](embedded.md). It is also in the [public domain](public_domain.md), unlike some other palettes, so it's additionally a legally safe choice. RGB332 also has a "sister palette" called [RGB565](rgb565.md) which uses two bytes instead of one and so offers many more colors.
A disadvantage of plain 332 palette is the linearity of each component's intensity, i.e. lack of [gamma correction](gamma_correction.md), so there are too many almost indistinguishable bright colors while too few darker ones { TODO: does a gamma corrected 332 exist? make it? ~drummyfish }. Another disadvantage is the non-alignment of the blue component with red and green components, i.e. while R/G components have 8 levels of intensity and so step from 0 to 255 by 36.4, the B component only has 4 levels and steps by exactly 85, which makes it impossible to create exact shades of grey (which has to have all R, G and B components equal).
The RGB values of the 332 palette are following:
```
#000000 #000055 #0000aa #0000ff #002400 #002455 #0024aa #0024ff
#004800 #004855 #0048aa #0048ff #006d00 #006d55 #006daa #006dff
#009100 #009155 #0091aa #0091ff #00b600 #00b655 #00b6aa #00b6ff
#00da00 #00da55 #00daaa #00daff #00ff00 #00ff55 #00ffaa #00ffff
#240000 #240055 #2400aa #2400ff #242400 #242455 #2424aa #2424ff
#244800 #244855 #2448aa #2448ff #246d00 #246d55 #246daa #246dff
#249100 #249155 #2491aa #2491ff #24b600 #24b655 #24b6aa #24b6ff
#24da00 #24da55 #24daaa #24daff #24ff00 #24ff55 #24ffaa #24ffff
#480000 #480055 #4800aa #4800ff #482400 #482455 #4824aa #4824ff
#484800 #484855 #4848aa #4848ff #486d00 #486d55 #486daa #486dff
#489100 #489155 #4891aa #4891ff #48b600 #48b655 #48b6aa #48b6ff
#48da00 #48da55 #48daaa #48daff #48ff00 #48ff55 #48ffaa #48ffff
#6d0000 #6d0055 #6d00aa #6d00ff #6d2400 #6d2455 #6d24aa #6d24ff
#6d4800 #6d4855 #6d48aa #6d48ff #6d6d00 #6d6d55 #6d6daa #6d6dff
#6d9100 #6d9155 #6d91aa #6d91ff #6db600 #6db655 #6db6aa #6db6ff
#6dda00 #6dda55 #6ddaaa #6ddaff #6dff00 #6dff55 #6dffaa #6dffff
#910000 #910055 #9100aa #9100ff #912400 #912455 #9124aa #9124ff
#914800 #914855 #9148aa #9148ff #916d00 #916d55 #916daa #916dff
#919100 #919155 #9191aa #9191ff #91b600 #91b655 #91b6aa #91b6ff
#91da00 #91da55 #91daaa #91daff #91ff00 #91ff55 #91ffaa #91ffff
#b60000 #b60055 #b600aa #b600ff #b62400 #b62455 #b624aa #b624ff
#b64800 #b64855 #b648aa #b648ff #b66d00 #b66d55 #b66daa #b66dff
#b69100 #b69155 #b691aa #b691ff #b6b600 #b6b655 #b6b6aa #b6b6ff
#b6da00 #b6da55 #b6daaa #b6daff #b6ff00 #b6ff55 #b6ffaa #b6ffff
#da0000 #da0055 #da00aa #da00ff #da2400 #da2455 #da24aa #da24ff
#da4800 #da4855 #da48aa #da48ff #da6d00 #da6d55 #da6daa #da6dff
#da9100 #da9155 #da91aa #da91ff #dab600 #dab655 #dab6aa #dab6ff
#dada00 #dada55 #dadaaa #dadaff #daff00 #daff55 #daffaa #daffff
#ff0000 #ff0055 #ff00aa #ff00ff #ff2400 #ff2455 #ff24aa #ff24ff
#ff4800 #ff4855 #ff48aa #ff48ff #ff6d00 #ff6d55 #ff6daa #ff6dff
#ff9100 #ff9155 #ff91aa #ff91ff #ffb600 #ffb655 #ffb6aa #ffb6ff
#ffda00 #ffda55 #ffdaaa #ffdaff #ffff00 #ffff55 #ffffaa #ffffff
```
With RGB332 addition/subtraction of colors can be [approximated](approximation.md) in a very fast way using the [OR](or.md)/[AND](and.md) operation -- however this only works sometimes (check visually). For example if you need to quickly brighten/darken all pixels in a 332 image, you can just OR/AND each pixel with these values:
```
brighten by 3: | 0x6d (011 011 01)
brighten by 2: | 0x49 (010 010 01)
brighten by 1: | 0x24 (001 001 00)
darken by 1: & 0xdb (110 110 11)
darken by 2: & 0xb6 (101 101 10)
darken by 3: & 0x92 (100 100 10)
```
TODO: conversion to/from RGB24

@ -2,7 +2,7 @@
Sudoku is a puzzle that's based on filling a grid with numbers that is hugely popular even among [normies](normie.md) such as grandmas and grandpas who find this stuff in magazines for elderly people. The goal is to fill in all squares of a 9x9 grid, prefilled with a few clue digits, with digits 1 to 9 so that no digit repeats in any column, row and 3x3 subgrid. It is like a crosswords puzzle for people who lack general knowledge, but it's also pretty [suckless](suckless.md), pure logic-based puzzle whose generation and solving can be relatively easily automatized (unlike generating crosswords which requires some big databases). The puzzle is a pretty [fun](fun.md) singleplayer [game](game.md), posing opportunities for nice [mathematical](math.md) research and analysis as well as a comfy [programming](programming.md) exercise. Sudokus are a bit similar to [magic squares](magic_square.md). There also exist many similar kinds of puzzles that work on the principle of filling a grid so as to satisfy certain rules given initial clues, many of these are implemented e.g. in [Simon Tatham's Portable Puzzle Collection](stppc.md).
Curiously sudoku has its origins in agricultural designs in which people wanted to lay out fields of different plants in more or less uniform distributions (or something like that, there are some papers about this from 1950s). The puzzle itself became popular in Japan in about 1980s and experienced a boom of popularity in the western world some time after 2000.
Curiously sudoku has its origins in agricultural designs in which people wanted to lay out fields of different plants in more or less uniform distributions (or something like that, there are some papers about this from 1950s). The puzzle itself became popular in Japan in about 1980s and experienced a boom of popularity in the western world some time after 2000 (similar Asian puzzle boom was historically seen e.g. with [tangram](tangram.md)).
The following is an example of a sudoku puzzle with only the initial clues given:

Loading…
Cancel
Save