fork(2) download
  1. from math import sqrt, ceil, log2
  2. from sys import exit
  3. data = []
  4. ddata = dict()
  5. def fill(r1, r2, r3, rest):
  6. if len(r1) > 3:
  7. return
  8. if not rest:
  9. k = (list(sorted(r1)),list(sorted(r2)),list(sorted(r3)))
  10. ddata[str(k)] = k
  11. return
  12. t = [rest[0]]
  13. fill(t+r1, r2, r3, rest[1:])
  14. fill(r1, t+r2, r3, rest[1:])
  15. fill(r1, r2, t+r3, rest[1:])
  16.  
  17. fill([],[],[],[0,1,2,3,4])
  18.  
  19. def to_bin(r):
  20. c = 0
  21. for i in r:
  22. c |= 1<<i
  23. return c
  24.  
  25. for _, v in ddata.items():
  26. r1, r2, r3 = v
  27. data.append((to_bin(r1)<<10) | (to_bin(r2)<<5) | to_bin(r3))
  28.  
  29.  
  30. def hash_func(data, pow2=True):
  31. class DoesNotFit(Exception):
  32. pass
  33.  
  34. #controlla che elementi nella stessa posizione non siano settati
  35. def check(l, r):
  36. for a, b in zip(l, r):
  37. if (a&b)==1:
  38. return False
  39. return True
  40.  
  41. #calcolo dimensione minima
  42. size = max(ceil(sqrt(max(data))), len(data))
  43. if pow2:
  44. size = 1<<ceil(log2(size))
  45.  
  46. #procedo per tentativi
  47. while True:
  48. try:
  49.  
  50. square = [[0]*size for i in range(size)]
  51. rowcounts = [0] * size
  52.  
  53. #tabella da comprimere
  54. for c in data:
  55. square[c//size][c%size] = 1
  56. rowcounts[c//size]+=1
  57.  
  58. most_frequent_row_order = reversed(sorted(zip(rowcounts, range(size))))
  59.  
  60. #shift relativo ad ogni riga
  61. shifts = [0]*size
  62.  
  63. #tabella compressa in una riga
  64. C = [0]*size
  65.  
  66. #cerco di ruotare ogni riga in modo che non ci siano duplicati sulle colonne
  67. for _, r in most_frequent_row_order:
  68. tmp = square[r]
  69. #ruoto finché non trovo una rotazione che vada bene o abbia fatto un giro completo
  70. while not check(C, tmp) and shifts[r] < size:
  71. shifts[r] += 1
  72. tmp = tmp[-1:]+tmp[:-1]
  73. #Se ho compiuto un giro completo non posso sistemare le righe
  74. if shifts[r] == size:
  75. raise DoesNotFit
  76. #marko le posizioni occupate dalla riga corrente ruotata
  77. C = list(map(sum, zip(C, tmp)))
  78. return size, shifts
  79. except DoesNotFit:
  80. pass
  81.  
  82. #ritento con una dimensione più grande
  83. if pow2:
  84. size = size << 1
  85. else:
  86. size += 1
  87.  
  88. def output_c_hash_func(data, prefix="", pow2=True):
  89. size, shifts = hash_func(data, pow2)
  90. tsize = prefix+"SIZE"
  91. def tshifts(n):
  92. return prefix+"SHIFTS["+str(n)+"]"
  93. def ttable(n):
  94. return prefix+"TABLE["+str(n)+"]"
  95. print("#define", tsize, size)
  96. print("int", tshifts(size), "= {", end="")
  97. it = iter(shifts)
  98. print(next(it), end="")
  99. for c in it:
  100. print(",", c, end="")
  101. print("};")
  102. print("int", ttable(size), ";")
  103. print("#define", prefix+"lookup(i)", ttable("((i)+"+tshifts("(i)/"+tsize)+")%"+tsize))
  104.  
  105. output_c_hash_func(data, "HT_", True)
Success #stdin #stdout 0.09s 30408KB
stdin
Standard input is empty
stdout
#define HT_SIZE 512
int HT_SHIFTS[512] = {0, 1, 0, 4, 0, 4, 13, 25, 0, 1, 7, 22, 3, 17, 37, 48, 0, 1, 3, 18, 1, 16, 35, 45, 1, 1, 27, 0, 50, 49, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int HT_TABLE[512] ;
#define HT_lookup(i) HT_TABLE[((i)+HT_SHIFTS[(i)/HT_SIZE])%HT_SIZE]