Python演算法筆試題目,破解Hash值,N進製法
Find the string whichhas this hash: 25267566250558
The string has length8.
Characters can befrom: c,e,i,a,r,w,u,s,p
The hash functionworks like this:
hash(str):
1.LETTERS = c, e, i, a, r, w, u, s, p
2. h =7
3. forc in str:
1.i = index of c in LETTERS
2.h = 37 * h + i
4.return h
Please send us thestring you found, and the code you used to find it.
使用N進位制的解法的核心思想是:首先計算出解法的總數(possibilitites),然後從0到possibilitites遍歷,將每一個遍歷到的結果轉換為N進位制(這裡N是8)。
程式碼如下:
#coding=utf-8
# for every possiblity , hexadecimal convertion is involved, its complexity is O("pow()*len(需要的字串的長度)" *每次hash的計算量)
## correct: I found 'surprise' when the index of c in LETTERS begins from 0
# 'uwasaeuc' when 1
#====================
## result: the only string found is
# my result is based on the condition that the index of c in LETTERS begins
# from 1 rather 0, otherwise, no answer will be found.
## analysis:
# we don't konw the what specific characters their order are,
# there may also be duplicate chracters
# the goal is to find the string which has the specified key
## may be three solutions, I just implemented the first one
# 1. recursive
# 2. nonrecursive with stack
# 3. dynamic programming
# related project: combination(!permutation is more precise) of 8 chracters,eg 8-nary
#-- need it? 37 的二進位制, ans: no
## simulate the step 3 in hash(str):
# use h(x) to represent the value of the xth time h
# 3.1 h(1) = 37*7 + LETTERS.index('c')
# 3.2 h(2) = 37*h(1) + LETTERS.index('c')
# ..
# so the general formula is h(x) =
# idx = 0...len(str_hash)-1
# c = str_hash[idx]
# i = LETTERS.index(c)
# calculate the hash number of the str_hash
str_hash_length = 8
LETTERS = ['c', 'e', 'i', 'a', 'r', 'w', 'u', 's', 'p']
# str_hash_length = 2
# LETTERS = ['c', 'e', 'i']
hash_result = 25267566250558
def calculate_hash(str_hash):
h = 7
for c in str_hash:
# print c
i = LETTERS.index(c) # + 1 ###
# print i,
h = 37*h + i
return h
## for test of calculate_hash()
# str_hash = 'ec'
# print calculate_hash(str_hash)
## calculate the str_hash using n-nary and recursive
# instialize a list to store the characters
str_hash_list = ['' for i in xrange(str_hash_length)]
# print 'the type is ',type(str_hash_list)
from math import pow
def main():
LETTERS_len = len(LETTERS)
possibilitites = pow(LETTERS_len, str_hash_length)
#print possibilitites # result is 43046721.0
possibilitites = int(possibilitites)
# selection state, use [0...LETTERS_len-1], or['c','e'...]; choose the former one
selection_state = [7 for i in xrange(str_hash_length)]
#print selection_state
# for num in xrange(possibilitites):
##
# pos_range = [ elem for elem in xrange(possibilitites)]
# pos_range.reverse()
for num in xrange(possibilitites):
#for num in pos_range:
num_copy = num
# hexadecimal conversion , decimal --> N-nary, N is LETTERS_len( number of choices very time )
# after conversion, the N-nary number is a reverse of what it should be
for place in xrange(str_hash_length):
selection_state[place] = num_copy%LETTERS_len
num_copy /= LETTERS_len
# print selection_state
str_hash = [LETTERS[j] for j in selection_state ]
str_hash_value = calculate_hash(str_hash)
# print str_hash
# print str_hash_value
if str_hash_value == hash_result:
str_hash_string = ''.join(str_hash)
print "the string found is '%s' " % (str_hash_string)
if __name__ == '__main__':
main()