Skip to content

Latest commit

 

History

History
179 lines (135 loc) · 3.43 KB

will_2022-10-03.md

File metadata and controls

179 lines (135 loc) · 3.43 KB

10/3 (will)

will finally showed up on time. sometimes its good to celebrate the small wins. this session was pretty light. we started by discussing binary data and bitwise XOR.

below we have some bytes objects:

>>> a = b'111000'
>>> b = b'000111'

and we can see that they're collections, so ^ doesn't work on them in aggregate:

>>> a ^ a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'bytes' and 'bytes'

we can define integers in bitstring literal form using the prefix 0b:

>>> a = 0b00001111
>>> a
15
>>> type(a)
<class 'int'>

but that's not the same thing as a bytes:

>>> 0b00001111 != b'00001111'
True
>>> type(b'00001111')
<class 'bytes'>

going back to XOR, we can do it on ints:

>>> a = 0b00001111
>>> b = 0b11110000
>>> a ^ a
0

the built-in function bin gives the bitstring representation of an int:

>>> bin(a ^ a)
'0b0'
>>> bin(8)
'0b1000'
>>> a ^ b
255
>>> bin(a ^ b)
'0b11111111'

quick review of the truth table for XOR:

>>> 0 ^ 0 == 1
False
>>> 0 ^ 1 == 1
True
>>> 1 ^ 0 == 1
True
>>> 1 ^ 1 == 1
False

setup:

>>> a = 0b00001111

>>> b = 0b11110000

>>> bin(a ^ b)

'0b11111111'
>>> a ^ b ^ a
240

and now we can see that XOR is commutative:

>>> bin(a ^ b ^ a)

'0b11110000'
>>> bin((a ^ b) ^ a)

'0b11110000'
>>> bin(a ^ (b ^ a))

'0b11110000'

and that XOR'ing something with itself "cancels" it out (note that both a and b are included in the below expression an even number of times):

>>> a ^ b ^ a ^ a ^ b ^ b ^ a ^ b
0

we can use the XOR operator to compose a function that works over bytes:

>>> x = bytes([0b00001111, 0b11110000])

>>> y = bytes([0b11110000, 0b00001111])

>>> bin(x[0]), bin(x[1])

('0b1111', '0b11110000'

>>> def xor_bytes(p: bytes, q: bytes) -> bytes:
...     return [s ^ t for s, t in zip(p, q)]
...
>>> xor_bytes(x, y)
[255, 255]
>>> [bin(p) for p in xor_bytes(x, y)]

['0b11111111', '0b11111111']

and then at this point i tried to free-hand a variadic version of above, and face-planted a little bit. "variadic" here means a function that takes an arbitrary number of arguments, as opposed to fixed positional parameters p and q in xor_mult above. check this out:

https://stackoverflow.com/questions/919680/can-a-variable-number-of-arguments-be-passed-to-a-function

here was my attempt:

>>> def xor_mult(*args):
...     return reduce(lambda acc, new: xor_bytes(acc, new), args, b'00000000')
...
>>> xor_mult(x, y)
[207, 207]
>>> xor_mult(x, y, x)
[192, 63]
>>> xor_mult(x, y, x, y)
[48, 48]

upone review today, looks like i was close -- i had 2 mistakes:

  1. used fixed-length bytes to seed the reduce accumulator
  2. forgot to call bytes on the return value, so returned a list of ints instead of a bytes!

oh, the joys of dynamically typed languages... anyway, here's the working impl

>>> def xor_mult(*args):
...     return bytes(reduce(lambda acc, new: xor_bytes(acc, new), args, bytes(len(args[0]))))
...
>>> xor_mult(b'0000', b'1111', b'0000', b'1010')
b'\x00\x01\x00\x01'
>>> xor_mult(b'0000', b'1111', b'0000', b'1111')
b'\x00\x00\x00\x00'
>>> xor_mult(b'0000', b'1111', b'0000', b'1111', b'1111')
b'1111'

also, somebody asked about TypedDict. check out our section in the resources doc for examples and doc pointers:

https://github.com/cs-gy6903/resources#typeddict