| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- #!/usr/bin/env python3
- from functools import reduce
- from operator import xor
- def knot_round(nums, lengths, pos=0, skip=0, n=256):
- for length in lengths:
- for i in range(length // 2):
- left = (pos + i) % n
- right = (pos + length - i - 1) % n
- nums[left], nums[right] = nums[right], nums[left]
- pos = (pos + length + skip) % n
- skip = (skip + 1) % n
- return pos, skip
- def knot_hash(inp, rounds=64):
- lengths = tuple(map(ord, inp)) + (17, 31, 73, 47, 23)
- pos = skip = 0
- sparse = list(range(256))
- for r in range(rounds):
- pos, skip = knot_round(sparse, lengths, pos, skip)
- dense = 0
- for i in range(0, 256, 16):
- group = reduce(xor, sparse[i:i + 16])
- dense = (dense << 8) | group
- return dense
- def hamming_weight(n):
- return sum((n >> i) & 1 for i in range(n.bit_length()))
- def used_squares(key):
- return sum(hamming_weight(knot_hash(f'{key}-{i}')) for i in range(128))
- def used_regions(key):
- grid = []
- for y in range(128):
- h = knot_hash(f'{key}-{y}')
- grid.extend(-((h >> i) & 1) for i in range(128))
- def spread(x, y, region):
- i = y * 128 + x
- if grid[i] == -1:
- grid[i] = region
- if x > 0:
- spread(x - 1, y, region)
- if x < 127:
- spread(x + 1, y, region)
- if y > 0:
- spread(x, y - 1, region)
- if y < 127:
- spread(x, y + 1, region)
- region = 1
- for i, cell in enumerate(grid):
- if cell == -1:
- y, x = divmod(i, 128)
- spread(x, y, region)
- region += 1
- return region - 1
- print(used_squares('ljoxqyyw'))
- print(used_regions('ljoxqyyw'))
|