May 21st, 2020
This is a quick one, but while converting my old cellular automata posts from Jupyter Notebooks to HTML I came across this function I wrote five years ago.
def make_rule(rule_name, k): rule_name = int(rule_name) rule_len = 2 ** k rule = [*map(int, bin(rule_name)[2:])] rule = [0] * (rule_len - len(rule)) + rule rule = rule[::-1] return rule
This is just meant to return a list with the \(2^k\) binary digits of the
integer rule_name
, reversed. So we get something like
print(make_rule(123, 3))
#[stdout] [1, 1, 0, 1, 1, 1, 1, 0]
I purposefully did not use bit-shifting operations, yet still I don't like this code a lot. It has wonky things like
bin(rule_name)[2:]
Which is there to remove the '0b'
that the function
bin
prefixes to its output. If I were writing that today I'd
make use of the string format parameter b
x = 123 print(f"{x:b}")
#[stdout] 1111011
It's cleaner in my opinion, though admittedly a bit more cryptic if you're not used to string formating.
Then there's this line, which is meant to left pad the resulting string with zeros
[0] * (rule_len - len(rule)) + rule
I knew you could set the minimum number of digits n
of a number
using the formating parameter 0n
x = 123 print(f"{x:08}")
#[stdout] 00000123
but I didn't know if you could use both parameters in conjunction before writing this post. Turns out you can.
x = 123 print(f"{x:08b}")
#[stdout] 01111011
However in my case the number of digits is variable. I wonder if I'm allowed to...
k = 3 x = 123 print(f"{x:0{2 ** k}b}")
#[stdout] 01111011
Oh. So I could have written the function more succinctly.
def make_rule(rule_name, k): n_digits = 2 ** k as_binary = f"{rule_name:0{n_digits}b}" return [int(i) for i in reversed(as_binary)] print(make_rule(123, 3))
#[stdout] [1, 1, 0, 1, 1, 1, 1, 0]
Which I think is a bit nicer.
❦