Speed up search for the smallest x such that f(x) = target

风格不统一 提交于 2021-01-07 02:43:43

问题


Problem

Given n, find the smallest positive x such that f(x) = n.

f(x) is the sum of the digit sum of the factorials of the digits of x.

For example,

    f(15) 
    = digit_sum(1!) + digit_sum(5!)
    = digit_sum(1) + digit_sum(120)
    = (1) + (1 + 2 + 0)
    = 4

Breath first search can find the answer. Are there faster ways?

Breath First Search

def bfs(target, d_map):
    # Track which values of f(x) have we visited
    visited = set([0])
    # f(x) of the current level of the search tree
    todo = [0]
    # Digits of x for the current level of the search tree
    paths = [[0] * 10]
    while True:
        new_visited = set()
        # Discard old visited every 9 level.
        # This is because the worst case for pruning is
        # nine steps of 8! finally is equivalent to 1
        # step of 9!
        for i in range(9):
            # For holding new nodes of the next level:
            new_todo = []
            new_paths = []
            # Visit the next level
            for old_fx, old_digits in zip(todo, paths):
                # Visit the 9 new digits in the order of
                # large to small. This is because reaching
                # the target with just one big digit is
                # better than reaching the target with
                # several small digits. For example,
                # f(9) is same as f(888888888) but
                # x = 9 is definite smaller than
                # x = 888888888. Therefore, we visit
                # the big digits first.
                for d in [9, 6, 5, 3, 2, 1]:
                    new_fx = old_fx + d_map[d]
                    if new_fx not in visited:
                        # Update the set of visited values of f(x)
                        new_visited.add(new_fx)  # for pruning visited
                        visited.add(new_fx)
                        # Make digits for the new x
                        new_p = old_digits.copy()
                        new_p[d] += 1
                        # Record the digits of the new x
                        new_todo.append(new_fx)
                        new_paths.append(new_p)
                    # Stop if we reach our target
                    if new_fx == target:
                        return new_p
                # Discard record of the nodes of the previous level.
                todo = new_todo
                paths = new_paths
        visited = new_visited  # prune visited every 11 levels


def main():
    # map a digit to f(digit)
    d_map = {0: 1, 1: 1, 2: 2, 3: 6, 4: 6, 5: 3, 6: 9, 7: 9, 8: 9, 9: 27}
    d_map = {1: 1, 2: 2, 3: 6, 5: 3, 6: 9, 9: 27}
    print(bfs(1000000, d_map))
    # [0, 1, 0, 0, 0, 0, 0, 0, 0, 37037]
    # That means 1 one followed by 37037 nines


main()


回答1:


def find_x(target):
    t = [0, 1, 2, 5, 15, 25, 3, 13, 23, 6, 16, 
         26, 56, 156, 256, 36, 136, 236, 66, 166, 
         266, 566, 1566, 2566, 366, 1366, 2366]
    r = target % 27
    n_nine = (target // 27) * 3
    if r != 0:
        return str(t[r]) + str(9) * n_nine
    else:
        return str(9) * n_nine



回答2:


Here is my solution.

def digit_sum (n):
    return sum([int(i) for i in str(n)])

def search (target):
    factorials = [1]
    digit_sums = [0]
    for i in range(1, 10):
        factorials.append(i * factorials[i-1])
        digit_sums.append(digit_sum(factorials[i]))

    last_digit = {0: None}
    todo = [0]
    pos = 0
    while target not in last_digit:
        for i in range(1, 10):
            ds = digit_sums[i]
            x = todo[pos] + ds
            if x not in last_digit:
                last_digit[x] = i
                todo.append(x)
        pos += 1
    answer = []
    x = target
    while 0 < x:
        answer.append(last_digit[x])
        x -= digit_sums[last_digit[x]]
    return int("".join([str(d) for d in reversed(answer)]))

answer = search(1000000)
print((answer[0:10], len(answer))


来源:https://stackoverflow.com/questions/64826841/speed-up-search-for-the-smallest-x-such-that-fx-target

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!