1. 程式人生 > >Python演算法筆試題目,破解Hash值,N進製法

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()