“The more constraints one imposes, the more one frees oneself.”
Programming languages as built-in constraints
Same thing with serialization
Stravinsky for software engineers
The more constraints we embrace early on, the freer we are later.
Algorithms, Math Education, and the Art of Doing the Dishes
“The more constraints one imposes, the more one frees oneself.”
The more constraints we embrace early on, the freer we are later.
Famously, Heron's method of computing the square root of a some number x goes like this:
1. Guess the root, we'll denote the guess by g
2. Compute the quotient q = x/g
3. Update your next guess to be the arithmetic mean of q and g. So g := (x/g + g)/2
4. Goto 2
This can be viewed as a special case of the Newton–Raphson method, and indeed the results become very accurate very fast.
"Just as I cannot step in the same river twice, the person who created this bug and I are two separate beings in the fabric of the universe. Therefore, I will also not be the one who fixes it."
Heraclitus of Ephesus, a programmer
I don't like code manifests.
Rina Artstain once tweeted that we only think we know certain things about parenting because as luck would have it, we haven't had a child to whom all of them don't apply.
That's how I feel about code manifests.
However, I do have a manifest of my own, short though it may be, so I want to frame it differently. What follows are not the three rules I think everyone should follow to get a "cleaner" code or some other metric of goodness. Rather, these are three things I like when I see in other people's code and annoy me when I see blatantly disregarded.
Here we go.
"לֹא עָלֶיךָ הַמְּלָאכָה לִגְמוֹר, וְלֹא אַתָּה בֶן חוֹרִין לִבָּטֵל מִמֶּנָּה."
פרקי אבות, ב' טז'
"It is not incumbent upon you to finish the task, but neither are you free to absolve yourself from it."
Pirkei Avot 2:16
This is one of the greatest quotes I know and it sounds so much better in Hebrew.
"Entities should not be multiplied beyond necessity."
William of Ockham
Yes, this is the OG Ockham's razor. How amazing it is that a Franciscan friar who lived 700 years ago foresaw the harms of overusing OOP and polymorphism.
"Writing good code is superior to writing bad code.
Deleting code is superior to writing good code.
Superior to all is concluding that some code does not have to be written at all."Confucius
Well, not Confucius, but if one wants people to listen, one should attribute their thoughts to someone famous, preferably dead.
I'm pretty sure Oscar Wilde said that one.
class ZkMerkleTree: """ A Zero Knowledge Merkle tree implementation using SHA256 """ def __init__(self, data): self.data = data next_pow_of_2 = int(2**ceil(log2(len(data)))) self.data.extend([0] * (next_pow_of_2 - len(data))) # Intertwine with randomness to obtain zero knowledge. rand_list = [random.randint(0, 1 << 32) for x in self.data] self.data = [x for tup in zip(self.data, rand_list) for x in tup] # Create bottom level of the tree (i.e. leaves). self.tree = ["" for x in self.data] + \ [hash_string(str(x)) for x in self.data] for i in range(len(self.data) - 1, 0, -1): self.tree[i] = hash_string(self.tree[i * 2] + self.tree[i * 2 + 1]) def get_root(self): return self.tree[1] def get_val_and_path(self, id): # Because of the zk padding, the data is now at id * 2 id = id * 2 val = self.data[id] auth_path = [] id = id + len(self.data) while id > 1: auth_path += [self.tree[id ^ 1]] id = id // 2 return val, auth_path def verify_zk_merkle_path(root, data_size, value_id, value, path): cur = hash_string(str(value)) # Due to zk padding, data_size needs to be multiplied by 2, as does the value_id tree_node_id = value_id * 2 + int(2**ceil(log2(data_size * 2))) for sibling in path: assert tree_node_id > 1 if tree_node_id % 2 == 0: cur = hash_string(cur + sibling) else: cur = hash_string(sibling + cur) tree_node_id = tree_node_id // 2 assert tree_node_id == 1 return root == cur
def get_proof(problem, assignment, num_queries): proof = [] randomness_seed = problem[:] for i in range(num_queries): witness = get_witness(problem, assignment) tree = ZkMerkleTree(witness) random.seed(str(randomness_seed)) query_idx = random.randint(0, len(problem)) query_and_response = [tree.get_root()] query_and_response += [query_idx] query_and_response += tree.get_val_and_path(query_idx) query_and_response += tree.get_val_and_path((query_idx + 1) % len(witness)) proof += [query_and_response] randomness_seed += [query_and_response] return proof def verify_proof(problem, proof): proof_checks_out = True randomness_seed = problem[:] for query in proof: random.seed(str(randomness_seed)) query_idx = random.randint(0, len(problem)) merkle_root = query[0] proof_checks_out &= query_idx == query[1] # Test witness properties. if query_idx < len(problem): proof_checks_out &= abs(query[2] - query[4]) == abs(problem[query_idx]) else: proof_checks_out &= query[2] == query[4] # Authenticate paths proof_checks_out &= \ verify_zk_merkle_path(merkle_root, len(problem) + 1, query_idx, query[2], query[3]) proof_checks_out &= \ verify_zk_merkle_path(merkle_root, len(problem) + 1, \ (query_idx + 1) % (len(problem) + 1), query[4], query[5]) randomness_seed += [query] return proof_checks_out
def test(q): problem = [1, 2, 3, 6, 6, 6, 12] assignment = [1, 1, 1, -1, -1, -1, 1] proof = get_proof(problem, assignment, q) print(proof) return verify_proof(problem, proof)
[['f9f3b1e40626e906b03eb9fd5428b2f2f801e8f3c23627fe7e52a645c3f32632', 3, 1, ['1b7f5356d043c6336c6614fcc24cb77f8807cd2f443b1b77e0002be6b96c40b6', 'a412af57af0b88cdb5cb3d0cbfcd739ebcc3c6fe0ac364db9490b4a208803101', '9f358dd0980f35ea86070d0fb12b2f5726857031ef56968005095cdb13e0a6f0', '05066ac05f174f1f98226c40889c566775592ec3807fbe080324447616773e18'], 7, ['cd6ee891c632e07ad468cd602c8d2d935356ca5901b21a75a2719d164a925382', '4cfc41b83cf64e0cf14a0ea8179aa67c6324699557c508dfc424604674805864', '4efb02f72dbc085ead53657647e893f3ceb29c9f81d411dd817f3be512cad632', '6cd4c16c3d5db473280b64f6b3fce54cb4b6810b46331899f4c07f884fd89aae']], ['580bd4db1071906bcd101600baf51d33b9930ba6e26853e85634bf38c0acef92', 6, 16, ['f8b28423de50f3b0cbcf88caacb6d4f6789ba3cecdc7791b38d5bbcd700ecbd2', '5c41ad0b9d813740b516cb61cf9ce06966efcf82e8ee5881ca86d5b18400d03d', 'af38f9a1873b70d113dab45d6312e6d2a7f4afa45a8c82ebe788abf63dd85650', 'a57a3ccb7cbffdf4d346f1ecf10ead43a4ce1e52b51170789698b7aece6c7687'], 4, ['b703a38bb22b758c5c23c08f096b6c3155c56885d57e1280ff521126282fa857', '4e602f00ef1e1de0b733f467de61805f09a1ebee8db72cc64c62dd8d55836de1', 'af38f9a1873b70d113dab45d6312e6d2a7f4afa45a8c82ebe788abf63dd85650', 'a57a3ccb7cbffdf4d346f1ecf10ead43a4ce1e52b51170789698b7aece6c7687']]]