Python provides binary operators for working with integers.

One can get the binary representation of an integer using an f-string.

print(f"{1:b}")
print(f"{4:b}")
print(f"{10:b}")
1
100
1010

5. Binary operators#

  • & bitwise and: 2 & 3 = 0

a, b = 2, 3
print(f"a : {a} : {a:b}")
print(f"b : {b} : {b:b}")
print(f"and : a & b : {a & b} : {a & b:b}")
print(f"or  : a | b : {a | b} : {a | b:b}")
print(f"xor : a ^ b : {a ^ b} : {a ^ b:b}")
print(f"a ^ b : {a ^ b} : {a ^ b:b}")
a : 2 : 10
b : 3 : 11
and : a & b : 2 : 10
or  : a | b : 3 : 11
xor : a ^ b : 1 : 1
a ^ b : 1 : 1

6. Queen#

    class Queens:
    def __init__(self, n):
        self.n = n
        rangen = range(n)

        # Assign a unique int to each column and diagonal.
        # columns:  n of those, range(n).
        # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
        # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
        # based.
        # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
        # each, smallest i+j is 0, largest is 2n-2.

        # For each square, compute a bit vector of the columns and
        # diagonals it covers, and for each row compute a function that
        # generates the possibilities for the columns in that row.
        self.rowgenerators = []
        for i in rangen:
            rowuses = [(1 << j) |                  # column ordinal
                       (1 << (n + i-j + n-1)) |    # NW-SE ordinal
                       (1 << (n + 2*n-1 + i+j))    # NE-SW ordinal
                            for j in rangen]

            def rowgen(rowuses=rowuses):
                for j in rangen:
                    uses = rowuses[j]
                    if uses & self.used == 0:
                        self.used |= uses
                        yield j
                        self.used &= ~uses

            self.rowgenerators.append(rowgen)

    # Generate solutions.
    def solve(self):
        self.used = 0
        for row2col in conjoin(self.rowgenerators):
            yield row2col

    def printsolution(self, row2col):
        n = self.n
        assert n == len(row2col)
        sep = "+" + "-+" * n
        print(sep)
        for i in range(n):
            squares = [" " for j in range(n)]
            squares[row2col[i]] = "Q"
            print("|" + "|".join(squares) + "|")
            print(sep)
  Cell In[3], line 2
    def __init__(self, n):
    ^
IndentationError: expected an indented block after class definition on line 1