Last active
July 11, 2017 14:55
-
-
Save carlosmcevilly/a5f8dd5880404509af31 to your computer and use it in GitHub Desktop.
Playing with the idea of a Hamming ball. This calculates the Hamming ball starting at a given number, with given number of bits and given radius.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# What is a hamming ball? | |
# | |
# I couldn't find any definition for it on the Internets. But reading between the lines | |
# of what people in the know say, I'll take a stab at a preliminary definition. Don't | |
# trust this... I haven't studied it and am not a mathematician. Having said that, | |
# It seems to be the set of all numbers having the same number of bits as a starting | |
# number (the center) and differing from that number by at most (radius) bits. The | |
# code below assumes the starting number is also included, but I haven't confirmed | |
# that this should be the case. This is just me playing around with a quick hack. | |
# | |
# Another word used is "Hamming sphere" but I think this might be something different, | |
# namely: The set of all numbers having the same number of bits as a starting number | |
# (the center) and differing from that number by exactly (radius) bits. | |
# | |
# This script calculates the Hamming ball according to the first definition above. | |
# | |
import os | |
import sys | |
def ball_for_number_with_bits_with_radius(number, numBits, radius): | |
ball = ball_for_number(number, numBits) | |
if radius == 1: | |
return ball | |
else: | |
result = ball.copy() | |
for neighbor in ball: | |
items = ball_for_number_with_bits_with_radius(neighbor, numBits, radius-1) | |
result = result.union(items) | |
return result | |
def ball_for_number(number, numBits): | |
ball = set() | |
start = number & 0xFFFFFFFF # limit to 64-or-smaller-bit numbers | |
ball.add(number) | |
for n in range(0,numBits): | |
mutated = number ^ 1<<n; | |
ball.add(mutated) | |
return ball | |
def legal_argument(arg): | |
legal_args = 'nbr' | |
if arg in legal_args: | |
return True | |
return False | |
def usage_exit(): | |
print("\nUsage: " + sys.argv[0] + " -n number -b bits -r radius") | |
print( | |
""" | |
Options: | |
-n the starting number | |
-b how many bits to treat the number as (including left padding) | |
-r how many bit differences from the starting number to include | |
""") | |
exit(-1) | |
def main(): | |
if len(sys.argv) < 7: | |
usage_exit() | |
try: | |
if len(sys.argv) < 4 or not legal_argument(sys.argv[1][1]) or not legal_argument(sys.argv[3][1]) or not legal_argument(sys.argv[5][1]): | |
usage_exit() | |
if sys.argv[1].startswith('-') and sys.argv[1][1] == 'n': | |
number = int(sys.argv[2]) | |
if sys.argv[1].startswith('-') and sys.argv[3][1] == 'b': | |
numBits = int(sys.argv[4]) | |
if sys.argv[1].startswith('-') and sys.argv[5][1] == 'r': | |
radius = int(sys.argv[6]) | |
except IndexError: | |
usage_exit() | |
if numBits > 64: | |
numBits = 64 | |
print("warning: limited to 64 bits") | |
limit = (2**(numBits+1))-1 | |
if number > limit: | |
print("error: number " + str(number) | |
+ " is larger than " + str(limit) | |
+ ", the max value for " + str(numBits) | |
+ " bits.") | |
sys.exit() | |
ball = ball_for_number_with_bits_with_radius(number, numBits, radius) | |
for item in ball: | |
result = bin(item)[2:].zfill(numBits) | |
print(str(item).zfill(8) + ": " + result) | |
if __name__ == '__main__': | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment