diff options
Diffstat (limited to 'post/programming-as-art.typ')
| -rw-r--r-- | post/programming-as-art.typ | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/post/programming-as-art.typ b/post/programming-as-art.typ new file mode 100644 index 0000000..ef80e33 --- /dev/null +++ b/post/programming-as-art.typ @@ -0,0 +1,98 @@ +#import "/global/common.typ": * + +#let doc = [ +Why there is art in programming. + +During my early days as a CS student, one of the first mind-blowing moments was +watching `Hello World!` getting printed out to the console thousands of times +in just two functional lines of code. + +```python +for _ in range(1, 1001): + print("Hello World!") +``` + +At the time it felt like having the +#extlink("https://harry-potter-compendium.fandom.com/wiki/Elder_Wand")[Elder Wand]. + +#fig("programming-as-art/wand.png", alt: "Dumbledore with Elder Wand pic") + +But there was more to our lesson. The TA then asks us to put our newly found +power to use by computing the sum of 1 to 100. Of course, it was a natural +application of what we had just done earlier: + +```python +sum = 0 +for i in range(1, 100+1): + sum = sum + i +``` + +Sure enough we saw the answer `5050` in the console. But then the TA reminds us +that we are making our computers *work too hard*. In other words, the computer +needs to do one-hundred ADD instructions in order to make this computation +happen. + +What if the number was a million? How well would our method scale? + +Well then it would take a million ADD instructions. We call this scaling +_linearly_ with the input size. Later we would formalize this to $cal(O)(n)$ +(pronounced: _Big Oh of N_). + +The TA hinted that there is a better way, and that we already know of the +better way in math. + +#fig("programming-as-art/teaching.png", alt: "Teaching meme") + +$ S_n = sum_(i=1)^n i = 1 + 2 + ... + n = (n (n + 1)) / 2 $ + +With this we are no longer using loops, but a known mathematical fact about +sequences. If you don't belive me, see the +#extlink("https://letstalkscience.ca/educational-resources/backgrounders/gauss-summation")[proof]. + +Written as code: + +```python +sum = n (n + 1) / 2 +``` + +This one-liner solves our problem with just 3 (ADD, MULTIPLY, DIVIDE) +instructions. Crucially, it does not depend on the size of the input like our +previous solution, thus *no matter the input, it always takes 3 instructions to +compute!* This is a HUGE win! + +#fig("programming-as-art/math.png", alt: "Math meme") + +Later we would formalize this to $cal(O)(1)$, or _constant_ scaling. + +#quote(block: true)[ + Yes, yes I know IRL the complier would optimize the loop solution such + that it does not take N instructions but for the purposes of learning we + were not allowed to depend on that. +] + +Looking back at it now, both solutions are equally correct, and modern +compilers would optimize the first solution in the final instructions sent to +the cpu, such that any performance differences would be negligible. In other +words, the computer wouldn't acutally be _working so hard_. + +Objectively, the first solution is more readable, and friendly to a new +observer than the second. + +_Why then am I still so drawn to the second solution?_ + +The first solution reminds me of the saying "to a hammer, eveything looks like +a nail". Its a brute force approach. In comparison, the second solution is +using the exact tool for our particular problem. It somehow feels personalized +and dare I say _romantic_. + +When I reflect on moments like this, it reminds me that there is emergent +elegance and beauty even in the seemingly arbitrary sequence of symbols that is +`code`. + +#fig("programming-as-art/code.png", alt: "The Matrix code going by image") + +Programming is not quite as _objective_ as people would have you believe. There +are trade-offs to each solution, and which solution you prefer relect on the +trade-offs you are willing to accept, which varies by the observer: much like +_art_. +] |
