forked from L3viathan/pyconde18-talk-codegolfing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
294 lines (277 loc) · 15.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=1024" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<title>Python Birdies | PyCon.DE 2018</title>
<meta name="description" content="Codegolfing Talk" />
<meta name="author" content="Jonathan Oberländer" />
<link href="cgtalk.css" rel="stylesheet" />
<link rel="shortcut icon" href="favicon.png" />
</head>
<body class="impress-not-supported">
<div class="fallback-message">
Waiting for browser support...
</div>
<div id="impress">
<div id="title" class="step slide" data-x="-1000" data-y="-1500">
<h1>Python birdies</h1>
<h4>Codegolfing for better understanding (and fun)</h4>
<span class="author">Jonathan Oberländer</span>
<span class="date">PyConDE 2018</span>
<img src="RGB_solute.svg">
<span class="notes">
name, company, title. What is codegolfing? <em>Wait...</em>
</span>
</div>
<div id="warning" class="step slide" data-x="0" data-y="-1500">
<h2>Warning</h2>
<span>Doing this at work will (hopefully) get you fired.</span>
<span class="notes">
...rightfully so.
</span>
</div>
<div id="what-is-codegolfing" class="step" data-x="1000" data-y="-1500">
<h2>What is Codegolfing?</h2>
<span class="notes">
Writing code that fulfills 3 requirements
</span>
</div>
<div id="technically-correct" class="step" data-y="-1300">
<h3>The Art of Writing Code that is</h3>
<em>(technically) correct</em>
</div>
<div id="as-short-as-possible" class="step" data-y="-1220" data-transition-duration="500">
<em>in as few bytes as possible</em>
</div>
<div id="no-step-three" class="step" data-y="-1160" data-transition-duration="500">
<em>there's no step 3</em>
<span class="notes">
<ul>
<li>No comments</li>
<li>No (unnecessary) whitespace/braces/...</li>
<li>Only one-letter variable names (except SPL, ...)</li>
<li>Terrible code</li>
<li>Fuck (asymptotic) complexity</li>
</ul>
</span>
</div>
<div id="fizzbuzz-1" class="step golf" data-rotate-y="90">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>, <span class="val">101</span>)<span class="op">:</span>
<span class="keyword">if</span> <span class="name">i</span> <span class="op">%</span> <span class="val">15</span> <span class="op">==</span> <span class="val">0</span><span class="op">:</span>
<span class="name">print</span>(<span class="val">"FizzBuzz"</span>)
<span class="keyword">elif</span> <span class="name">i</span> <span class="op">%</span> <span class="val">3</span> <span class="op">==</span> <span class="val">0</span><span class="op">:</span>
<span class="name">print</span>(<span class="val">"Fizz"</span>)
<span class="keyword">elif</span> <span class="name">i</span> <span class="op">%</span> <span class="val">5</span> <span class="op">==</span> <span class="val">0</span><span class="op">:</span>
<span class="name">print</span>(<span class="val">"Buzz"</span>)
<span class="keyword">else</span><span class="op">:</span>
<span class="name">print</span>(<span class="name">i</span>)
</code>
<span class="counter">182</span>
<span class="notes">
Straightforward implementation
<br>
Notice number on bottom left, => number of bytes
<br>
How far down do you think we can take it?
<br>
<em>Won't start with whitespace removal (for readability)</em>
</span>
</div>
<div id="fizzbuzz-2" class="step golf" data-rotate-y="90" data-z="-1000">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>, <span class="val">101</span>)<span class="op">:</span>
<span class="name">l</span> <span class="op">=</span> [<span class="name">i</span><span class="op">%</span><span class="val">15</span>, <span class="name">i</span><span class="op">%</span><span class="val">3</span>, <span class="name">i</span><span class="op">%</span><span class="val">5</span>]
<span class="keyword">try</span><span class="op">:</span>
<span class="name">print</span>([<span class="val">"FizzBuzz"</span>, <span class="val">"Fizz"</span>, <span class="val">"Buzz"</span>]<span class="op">[</span><span class="name">l</span><span class="op">.</span><span class="name">index</span>(<span class="val">0</span>)<span class="op">]</span>)
<span class="keyword">except</span><span class="op">:</span>
<span class="name">print</span>(<span class="name">i</span>)
</code>
<span class="counter">142</span>
<span class="notes">
No conditions; instead: Exception handling. <strong>often shorter</strong>
<br>
List of modoli of value to 15, 5, 3. Order matters (index returns first such index)
</span>
</div>
<div id="fizzbuzz-3" class="step golf" data-rotate-y="90" data-z="-2000">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>, <span class="val">101</span>)<span class="op">:</span>
<span class="keyword">try</span><span class="op">:</span>
<span class="name">print</span>([<span class="val">"FizzBuzz"</span>, <span class="val">"Fizz"</span>, <span class="val">"Buzz"</span>]<span class="op">[</span>[<span class="name">i</span><span class="op">%</span><span class="val">15</span>, <span class="name">i</span><span class="op">%</span><span class="val">3</span>, <span class="name">i</span><span class="op">%</span><span class="val">5</span>]<span class="op">.</span><span class="name">index</span>(<span class="val">0</span>)<span class="op">]</span>)
<span class="keyword">except</span><span class="op">:</span>
<span class="name">print</span>(<span class="name">i</span>)
</code>
<span class="counter">132</span>
<span class="notes">
zero-letter variable names!
<br>
No need for the list reference to be saved
<br><em>what is shorter than exception handling? (no exception handling)</em>
</span>
</div>
<div id="fizzbuzz-4" class="step golf" data-rotate-y="90" data-z="-3000">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>, <span class="val">101</span>)<span class="op">:</span>
<span class="name">print</span>([<span class="val">"FizzBuzz"</span>, <span class="val">"Fizz"</span>, <span class="val">"Buzz"</span>, <span class="name">i</span>]<span class="op">[</span>[<span class="name">i</span><span class="op">%</span><span class="val">15</span>, <span class="name">i</span><span class="op">%</span><span class="val">3</span>, <span class="name">i</span><span class="op">%</span><span class="val">5</span>, <span class="val">0</span>]<span class="op">.</span><span class="name">index</span>(<span class="val">0</span>)<span class="op">]</span>)
</code>
<span class="counter">96</span>
<span class="notes">
No exception handling.<br>
We put a zero as the last element, so we'll always find 0.<br>
<em>Now time for whitespace removal</em>
</span>
</div>
<div id="fizzbuzz-5" class="step golf" data-rotate-y="90" data-z="-4000">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>,<span class="val">101</span>)<span class="op">:</span><span class="name">print</span>(
[<span class="val">"FizzBuzz"</span>,<span class="val">"Fizz"</span>,<span class="val">"Buzz"</span>,<span class="name">i</span>]
<span class="op">[</span>[<span class="name">i</span><span class="op">%</span><span class="val">15</span>,<span class="name">i</span><span class="op">%</span><span class="val">3</span>,<span class="name">i</span><span class="op">%</span><span class="val">5</span>,<span class="val">0</span>]<span class="op">.</span><span class="name">index</span>(<span class="val">0</span>)<span class="op">]</span>)
</code>
<span class="counter">84</span>
<span class="notes">
No more unnecessary whitespace (one-line for-loop).<br>
Linebreaks are just wrap now!
</span>
</div>
<div id="fizzbuzz-6" class="step golf" data-rotate-y="90" data-z="-5000">
<code lang="python">
<span class="keyword">for</span> <span class="name">i</span> <span class="keyword">in</span> <span class="name">range</span>(<span class="val">1</span>,<span class="val">101</span>)<span class="op">:</span><span class="name">print</span>(
<span class="val">"Fizz"</span><span class="op">*</span>(<span class="name">i</span><span class="op">%</span><span class="val">3</span><span class="op"><</span><span class="val">1</span>)<span class="op">+</span><span class="val">"Buzz"</span><span class="op">*</span>(<span class="name">i</span><span class="op">%</span><span class="val">5</span><span class="op"><</span><span class="val">1</span>)<span class="keyword">or</span> <span class="name">i</span>)
</code>
<span class="counter">62</span>
<span class="notes">
Not by me!<br>
We put a Fizz if divisible by 3, a buzz if by 5, and _if there is nothing_ ("or"), the number itself.
<br>
Two interesting things: Using <1 saves at least a byte vs. equality comparison operators. <strong>Use special knowledge even when the resulting expression is "wrong"</strong>
<br>thing or other: a trick sometimes seen in the (non-codegolf) wild: or and and expressions equal their last evaluated argument.
<br>Who thinks we can shorten this? We can — by one byte.
</span>
</div>
<div id="fizzbuzz-7" class="step golf" data-rotate-y="90" data-z="-6000">
<code lang="python">
<span class="keyword">i</span><span class="op">=</span><span class="val">0</span><span class="op">;</span><span class="name">exec</span>(<span class="val">"</span><span class="name">print</span>(
<span class="val">i</span><span class="op">%</span><span class="val">3</span><span class="op">//</span><span class="val">2</span><span class="op">*</span><span class="val">'Fizz'</span>
<span class="op">+</span><span class="name">i</span><span class="op">%</span><span class="val">5</span><span class="op">//</span><span class="val">4</span><span class="op">*</span><span class="val">'Buzz'</span>
<span class="keyword">or</span><span class="op">-</span><span class="op">~</span><span class="name">i</span>)<span class="op">;</span><span class="name">i</span><span class="op">+=</span><span class="val">1</span><span class="op">;</span><span class="val">"</span><span class="op">*</span><span class="val">100</span>)
</code>
<span class="counter">61</span>
<span class="notes">
Not by me!<br>
This is the final number (suggestions welcome)
<br>
I cheated in the highlighting: Most of the code is actually a string
<br>
We generate a long line with 100 calls to print and 100 incrementations
<br>
The rest is slightly complicated, but not _too_ bad: We iterate over the numbers from 0 to 99, not 1 to 100.
That means we have modulo result 2 (or 4) when we should have a Fizz (or Buzz).<br>
Then integer division by 2 (4), which only then makes this a 1, otherwise a 0.<br>
-~i uses the obscure invert operator (show of hands: who knows what it does?) (solution: -x - 1)
<br>
==> i+1, without needing to paranthesize.
</span>
</div>
<div id="why-golf" class="step" data-rotate-x="70">
<h1>Why golf?</h1>
<span class="notes">You might be (rightfully) scared and/or disgusted now<br>
I still think codegolfing is good for you, because:</span>
</div>
<div id="because-brain" class="step" data-rotate-x="70" data-z="-5800">
<span class="brain">puzzles are good</span>
<span class="notes">
through restricting your vocabulary, you become more creative, and will more easily find good (!) solutions in the real world (compare: oulipo/poetry).
</span>
</div>
<div id="because-understanding" class="step" data-rotate-x="70" data-z="-5700">
<span class="brain">understanding is good</span>
<span class="notes">
you'll understand Python internals better: lexer, parser, precedence...
</span>
</div>
<div id="because-knowledge" class="step" data-rotate-x="70" data-z="-5600">
<span class="brain">knowledge is good</span>
<span class="notes">
same category as metaclasses, descriptors, `ast`, `inspect`, ...: Use considered (generally) harmful, but knowledge still helps you
</span>
</div>
<div id="credits" class="step slide" data-x="-2000" data-y="-1500" data-z="0" data-transition-duration="8000">
<h1>What now?</h1>
<span class="ppcg">codegolf.stackexchange.com</span>
<span class="xkcd">xkcd.com/1960</span>
<span class="cgio">code-golf.io</span>
<span class="github">github.com/l3viathan</span>
<span class="mastodon">@[email protected]</span>
</div>
</div>
<span class="counterpinned"></span>
<script src="impress.js"></script>
<script>impress().init();</script>
<script>
function setcounter(value) {
var j = 1;
for (var i=0; i<value.length; i++) {
(function(i){
// these immediately executed functions are necessary to make the
// closures "own" the variables — otherwise the i at the time of
// the timeout will be used, rather than the one in the current for
// loop step.
var t = value.charCodeAt(i);
var c = 48;
while (c<=t) {
(function(c){window.setTimeout(function(){
document.querySelector(".counterpinned").textContent = value.slice(0, i) + String.fromCharCode(c);
}, j*50)})(c);
console.log("Setting to " + value.slice(0, i) + String.fromCharCode(c) + " in " + j*100 + "ms");
c++;
j++;
}
})(i)
}
}
function delcounter() {
var value = document.querySelector(".counterpinned").textContent;
for (var i=0; i<value.length; i++) {
(function(i){
window.setTimeout(function(){
document.querySelector(".counterpinned").textContent = value.slice(0, (value.length-i-1));
}, i*100)
})(i)
}
}
window.document.addEventListener("impress:stepenter", function() {
var h = location.hash;
if(h === "#/fizzbuzz-1") {
setcounter("182");
}
else if(h === "#/fizzbuzz-2") {
setcounter("142");
}
else if(h === "#/fizzbuzz-3") {
setcounter("132");
}
else if(h === "#/fizzbuzz-4") {
setcounter("96");
}
else if(h === "#/fizzbuzz-5") {
setcounter("84");
}
else if(h === "#/fizzbuzz-6") {
setcounter("62");
}
else if(h === "#/fizzbuzz-7") {
setcounter("61");
}
// else if(h === "#/credits") {
// setcounter('for x in 0,1,2,3:print("h yoipcn"[x::4],end="")');
// }
});
window.document.addEventListener("impress:stepleave", function() {
delcounter();
});
</script>
</body>
</html>