I am writing a cable mapping script that needs to find the closest switch. So if a patch panel is in Rack 08AB, and there is a switch in Rack 08AC and 08AD, I need it to pick the closest(08AC). The problem is the rack numbering sequence. The first two digits will always be the same (08) and the letters increment. But they increment A-Z then AA-AZ. So if the panel is in Rack 08Z, 08AA is closer than 08X.

I have this working by converting the letters into numbers and seeing which is closest but it seems clunky and I'm wondering if there's a better way:

###CLOSEST SWITCH IS IN 08AA
full_panel_location = '08Z'
full_switches_location = ['08X', '08AA']
switches_checksum = []


###REMOVE DIGITS AND CONVERT LETTERS TO CHECKSUM
panel_letters = ''.join([i for i in full_panel_location if not i.isdigit()])
panel_checksum = int(reduce(lambda x,y:x+y, map(ord, panel_letters)))
if panel_checksum > 100:
    panel_checksum -= 39

for switch in full_switches_location:
    switch_letters = ''.join([i for i in switch if not i.isdigit()])
    switch_checksum = int(reduce(lambda x,y:x+y, map(ord, switch_letters)))
    if switch_checksum > 100:
        switch_checksum -= 39
    switches_checksum.append(switch_checksum)

###FIND CLOSEST CHECKSUM/INDEX/SWITCH
closest_switch_checksum = min(switches_checksum, key=lambda x: abs(x - panel_checksum))
closest_switch_index = switches_checksum.index(closest_switch_checksum)

closest_switch = full_switches_location[closest_switch_index]


This provides the closest switch being 08AA, which is what I want. My question is, is there a better way to be doing this?

1 Answers

1
blhsing On Best Solutions

This is basically a base 26 conversion problem. Iterate through each letter of a location in reversed order and add its ordinal number difference to letter A times 26 to the power of the letter offset to get the checksum, with which you can calculate the distance to the reference location as a key for the min function:

def checksum(x):
    s = 0
    for i, c in enumerate(reversed(x)):
        s += (ord(c) - ord('A') + 1) * 26 ** i
    return s

full_panel_location = '08Z'
full_switches_location = ['08X', '08AA']
panel_checksum = checksum(full_panel_location[2:])
print(min(full_switches_location, key=lambda i: abs(checksum(i[2:]) - panel_checksum)))

This outputs:

08AA