|
| 1 | +import os |
| 2 | + |
| 3 | +class KnotHash: |
| 4 | + |
| 5 | + def __init__(self, nums, input): |
| 6 | + self.nums = nums |
| 7 | + self.input = input |
| 8 | + self.pos = 0 |
| 9 | + self.skip_size = 0 |
| 10 | + |
| 11 | + def dense_hash(self): |
| 12 | + sh = self.sparse_hash() |
| 13 | + dh = [None] * 16 |
| 14 | + for i in list(range(16)): |
| 15 | + section = [sh[j] for j in list(range(i*16, (i+1)*16))] |
| 16 | + result = section[0] |
| 17 | + for j in list(range(1, 16)): |
| 18 | + result = result ^ section[j] |
| 19 | + dh[i] = str(format(result, '02x')) |
| 20 | + return ''.join(dh) |
| 21 | + |
| 22 | + def sparse_hash(self): |
| 23 | + for i in list(range(64)): |
| 24 | + ascii_ints = self.string_ascii_converter(list(self.input)) + [17, 31, 73, 47, 23] |
| 25 | + self.nums = self.knot_hash_round(self.nums, ascii_ints, self.pos, self.skip_size) |
| 26 | + return self.nums |
| 27 | + |
| 28 | + def knot_hash_simple(self): |
| 29 | + rev_len_list = [int(d) for d in self.input.split(',')] |
| 30 | + return self.knot_hash_round(self.nums, rev_len_list) |
| 31 | + |
| 32 | + def knot_hash_round(self, nums, rev_len_list, pos=0, skip_size=0): |
| 33 | + if len(rev_len_list) == 0: |
| 34 | + return nums |
| 35 | + rev_len = rev_len_list.pop(0) |
| 36 | + hashed_nums = self.knot_hash_step(nums, rev_len, pos) |
| 37 | + pos = (pos + rev_len + skip_size) % len(nums) |
| 38 | + skip_size += 1 |
| 39 | + self.pos = pos |
| 40 | + self.skip_size = skip_size |
| 41 | + return self.knot_hash_round(hashed_nums, rev_len_list, pos, skip_size) |
| 42 | + |
| 43 | + def knot_hash_step(self, nums, rev_len, pos): |
| 44 | + i_in_rev = [i % len(nums) for i in list(range(pos, pos + rev_len))] |
| 45 | + rev_lst = self.rev([nums[i] for i in i_in_rev]) |
| 46 | + i_not_in_rev = list(set(list(range(len(nums)))) - set(i_in_rev)) |
| 47 | + lst = [None] * (len(nums)) |
| 48 | + for i in list(range(len(i_in_rev))): |
| 49 | + rev_i = i_in_rev[i] |
| 50 | + lst[rev_i] = rev_lst[i] |
| 51 | + for i in i_not_in_rev: |
| 52 | + lst[i] = nums[i] |
| 53 | + return lst |
| 54 | + |
| 55 | + def rev(self, l): |
| 56 | + return list(reversed(l)) |
| 57 | + |
| 58 | + def string_ascii_converter(self, string): |
| 59 | + return [ord(c) for c in list(string)] |
| 60 | + |
| 61 | +if __name__ == '__main__': |
| 62 | + test_data = '3,4,1,5' |
| 63 | + test_nums = [0, 1, 2, 3, 4] |
| 64 | + print(KnotHash(test_nums, test_data).knot_hash_simple()) |
| 65 | + |
| 66 | + input = '189,1,111,246,254,2,0,120,215,93,255,50,84,15,94,62' |
| 67 | + hashed = KnotHash(list(range(256)), input).knot_hash_simple() |
| 68 | + print(hashed[0] * hashed[1]) |
| 69 | + |
| 70 | + kh = KnotHash(list(range(256)), input) |
| 71 | + print(kh.dense_hash()) |
| 72 | + |
0 commit comments