Turn a canary's hash range into router rules

Agent buildMedium25 min

Your task

A canary puts a new version of your agent on a small slice of traffic. Your router hashes each user to a number and sends the user to the canary when that number falls in the canary's range. The router cannot match a range directly. It only matches blocks, and its memory for them is short, so you want as few blocks as you can get.

Write canary_rules(bits, start, count) that returns the fewest rules that cover the canary's range exactly.

Input and output:

  • bits: how many bits the hash has, a whole number from 1 to 48. Hash values are the whole numbers from 0 to 2 ** bits - 1.
  • start: the first hash value in the range, a whole number in the hash space.
  • count: how many hash values the range holds, a whole number from 1 to 2 ** bits.
  • Return a list of rules, each [first, size], sorted by first.

Rules:

  • A rule [first, size] covers the hash values from first to first + size - 1. Its size must be a power of 2, and first must be a multiple of size. So [8, 4] is a rule, and [6, 4] is not.
  • The range is the count hash values in a row from start. Past the last hash value it carries on from 0.
  • The rules must cover every value in the range and no value outside it.
  • Only one set of rules is the smallest, so there is one right answer.

Examples

canary_rules(bits: int, start: int, count: int) -> list[list[int]]
Example 1
Inputcanary_rules(4, 5, 6)
Output[[5, 1], [6, 2], [8, 2], [10, 1]]
Example 2
Inputcanary_rules(3, 6, 4)
Output[[0, 2], [6, 2]]
Example 3
Inputcanary_rules(3, 0, 8)
Output[[0, 8]]