I learned to program in C.
Languages
“A language that doesn’t affect the way you think about programming, is not worth knowing” — Alan Perlis
I remember when using Emacs itself was a huge struggle for me. But now I have just sudo apt install emacs’d this vanilla install and I am already off to the races.
Anyways, I’ll probably slim down this prose at a later date when I find it cringe and too verbose; but for now I am having a terrific time thwacking away at a Drunkdeer A75 Pro (thanks Aarav).
I’ve opted to scribble here as opposed to in a README this time.
Data Types
| category | types |
|---|---|
| boolean | bool |
| integer | int, int8, int16, int32, int64 |
| unsigned | uint, uint8 (byte), uint16, uint32, uint64, uintptr |
| floating-point | float32, float64 |
| complex | complex64, complex128 |
| text / rune | string, rune (int32 Unicode code point) |
| aggregates | array, struct |
| reference | slice, map, chan, pointers (e.g. *T), func, interface |
| error / misc | error, user-defined named types (e.g. type ID int) |
Time Complexities 1
slices
Let n be len(s) and k the number of elements being appended or copied.
This site is running so much AI generated Javascript that you would puke as soon as you opened the browser console.
At least the functionality is there though.
I have been chipping away at learning the language, the first 10 days were supremely productive, and I intend to continue.

Unavoidably, I learned HTML and CSS too.
The repo contains the rest of the information.
LuaLateX and NeoVim use Lua. So do thousands of embedded systems. It is a language worth learning for sure. Here is a beautiful N-Queens solution:
N = 25 -- board size
-- check whether position (n, c) is free from attacks
function isplaceok (a, n, c)
for i = 1, n - 1 do
if (a[i] == c) or -- cumulative column
(a[i] - i == c - n) or -- ↘ diagonal (cumulative)
(a[i] + i == c + n) then -- ↙ diagonal (cumulative)
return false
end
end
return true
end
-- print a board
function printsolution (a)
for i = 1, N do -- for each row
for j = 1, N do -- and for each column
-- write "X" or "-" plus a space
io.write(a[i] == j and "X" or "-", " ")
end
io.write("\n")
end
io.write("\n")
end
-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
if n > N then -- all queens have been placed?
printsolution(a)
return true
else -- try to place n-th quen
for c = 1, N do
if isplaceok(a, n, c) then
a[n] = c -- place n-th queen at column 'c'
if addqueen(a, n + 1) then
return true
end
end
end
end
end
addqueen({},1)
--[[
this code is really quite confusing.
firstly it uses backtracking, secondly the table data structure is non-trivial.
the notation a[n] == c, checks if there is a queen at co-ordinate (n,c).
it works by not using subarrays, and just indexing the column of each queen!
the recursion is fine, the base case exists at the start of the addqueen function, and we
loop through all the rows, adding queens where you can, and then backtracking through the
tree when we've ended up in a non-solvable situation.
the confusion for me arose in the isplaceok function, where I thought we would loop over
the entire NxN board; how naive! instead if we are considering the nth queen, we have only
placed 1..n-1 queens, and only need to check those squares!
finally, the crux of the magic is in
if (a[i] == c) or -- cumulative column
(a[i] - 1 == c - n) or -- ↘ diagonal (cumulative)
(a[i] + 1 == c + n) then -- ↙ diagonal (cumulative)
where it took me some time to understand that the checks were cumulative and that indeed
the indexing wizardry checked the cumulative column / diagonal / anti-diagonal.
note that there are 92 solutions to the 8x8 problem.
furthermore, the alternatives are the brute-force approach, where 8^8 boards are spawned and we need to check all column / diagonal and anti-diagonal violations.
there is also the permutation approach where you can just eliminate the row and col the queen was placed on and then continue your permutations for the n-1 sized square board. this avoids some cases by construction.
the true brute-force approach is O(N^N), whilst permutation is O(N!) and lastly backtracking is O(N!) worst case (but this is much better in practice).
--]]
Data Types
| category | types |
|---|---|
| text | str |
| numeric | int, float, complex |
| sequence | list, tuple, range |
| mapping | dict |
| set | set, frozenset |
| boolean | bool |
| binary | bytes, bytearray, memoryview |
| none | NoneType |
Time Complexities 1
lists
| operation | time complexity |
|---|---|
sequence.append(item) | \(\mathcal{O}(1)\) |
sequence.pop(item) | \(\mathcal{O}(1)\) |
sequence.insert(0,item) | \(\mathcal{O}(n)\) |
sequence.pop(item,0) {{< mnote “slow because popping at start requires shifting all indices down” >}} | \(\mathcal{O}(n)\) |
sequence[index] | \(\mathcal{O}(1)\) |
sequence[index]=value | \(\mathcal{O}(1)\) |
item in sequence | \(\mathcal{O}(n)\) |
len(sequence) | \(\mathcal{O}(1)\) |
sequence.extend(iterable) | \(\mathcal{O}(k)\) |
sequence + other_sequence | \(\mathcal{O}(n+k)\) |
sequence[index:index+k] | \(\mathcal{O}(k)\) |
sequence.index(item) | \(\mathcal{O}(n)\) |
sequence.count(item) | \(\mathcal{O}(n)\) |
for item in sequence: | \(\mathcal{O}(n)\) |
double-ended queue (deque)
| operation | description | time complexity |
|---|---|---|
queue.append(item) | Add item to right end | \(\mathcal{O}(1)\) |
queue.appendleft(item) | Add item to left end | \(\mathcal{O}(1)\) |
queue.pop() | Remove and return item from right end | \(\mathcal{O}(1)\) |
queue.popleft() | Remove and return item from left end | \(\mathcal{O}(1)\) |
queue.extend(iterable) | Add all elements from iterable to right end | \(\mathcal{O}(k)\) |
queue.extendleft(iterable) | Add all elements from iterable to left (reversed) | \(\mathcal{O}(k)\) |
queue.remove(value) | Remove first occurrence of value | \(\mathcal{O}(n)\) |
queue.rotate(n) | Rotate n steps right (negative for left) | \(\mathcal{O}(k)\) |
queue.clear() | Remove all elements | \(\mathcal{O}(n)\) |
queue.count(value) | Count occurrences of value | \(\mathcal{O}(n)\) |
queue.index(value) | Find index of first occurrence of value | \(\mathcal{O}(n)\) |
queue.reverse() | Reverse elements in place | \(\mathcal{O}(n)\) |
item in queue | Check if item exists in queue | \(\mathcal{O}(n)\) |
queue[0] or queue[-1] | Access first or last element | \(\mathcal{O}(1)\) |
queue[i] | Access element at index i | \(\mathcal{O}(n)\) |
for item in queue | Iterate through all elements | \(\mathcal{O}(n)\) |
dictionary
| operation | time complexity |
|---|---|
mapping[key]=value | \(\mathcal{O}(1)\) |
mapping[key] | \(\mathcal{O}(1)\) |
mapping.get(key) | \(\mathcal{O}(1)\) |
mapping.pop(key) | \(\mathcal{O}(1)\) |
key in mapping | \(\mathcal{O}(1)\) |
for k, v in mapping.items() | \(\mathcal{O}(n)\) |
next(iter(mapping)) | \(\mathcal{O}(1)\) |
next(reversed(mapping)) | \(\mathcal{O}(1)\) |
value in mapping.values() | \(\mathcal{O}(n)\) |
mapping.update(iterable) | \(\mathcal{O}(k)\) |
set
| operation | time complexity |
|---|---|
my_set.add(item) | \(\mathcal{O}(1)\) |
my_set.remove(item) | \(\mathcal{O}(1)\) |
item in my_set | \(\mathcal{O}(1)\) |
for item in my_set | \(\mathcal{O}(n)\) |
set1 & set2 | \(\mathcal{O}(n)\) |
set1 | set2 | \(\mathcal{O}(n)\) |
set1 ^ set2 | \(\mathcal{O}(n)\) |
set1 - set2 | \(\mathcal{O}(n)\) |
counter
| operation | time complexity |
|---|---|
counter[item] | \(\mathcal{O}(1)\) |
counter.pop(item) | \(\mathcal{O}(1)\) |
for k, v in counter.items(): | \(\mathcal{O}(n)\) |
for k, v in counter.most_common(): | \(\mathcal{O}(n\log(n))\) |
for k, v in counter.most_common(k): | \(\mathcal{O}(n \log(k))\) |
counter.update(iterable) | \(\mathcal{O}(k)\) |
counter.subtract(iterable) | \(\mathcal{O}(k)\) |
counter.total() | \(\mathcal{O}(n)\) |
heap / priority queue
| operation | time complexity |
|---|---|
heapq.heapify(sequence) | \(\mathcal{O}(n)\) |
heapq.heappop(sequence) | \(\mathcal{O}(\log(n))\) |
heapq.heappush(sequence, item) | \(\mathcal{O}(\log(n))\) |
sequence[0] | \(\mathcal{O}(1)\) |
sorted list
| operation | time complexity |
|---|---|
sorted_sequence = sorted(sequence) | \(\mathcal{O}(n\log(n))\) |
sorted_sequence.index(item) | \(\mathcal{O}(n)\) |
bisect.bisect(sorted_sequence, item) | \(\mathcal{O}(\log(n))\) |
bisect.insort(sorted_sequence, item) | \(\mathcal{O}(n)\) |
general traversals:
| operation | time complexity |
|---|---|
min(iterable) | \(\mathcal{O}(n)\) |
max(iterable) | \(\mathcal{O}(n)\) |
sorted(iterable) | \(\mathcal{O}(n\log(n))\) |
heapq.nsmallest(k, iterable) | \(\mathcal{O}(n\log(k))\) |
statistics.multimode(iterable) | \(\mathcal{O}(n)\) |
information courtesy of https://www.pythonmorsels.com/time-complexities/ ↩︎