Step Number from 10 to N using python

后端 未结 4 1654
春和景丽
春和景丽 2021-01-21 18:04

The Program must accept an integer N. The program must print all the stepping number from 10 to N, if there is no such number present the program should print -1 as

相关标签:
4条回答
  • 2021-01-21 18:19

    Maybe the main trick here is that the max range is 10^7. If we consider each digit as a node of the graph, we can traverse it with bfs/dfs and at each point, we can only move to the adjacent node (digit + 1, digit -1). Because the maximum depth is only 7, the solution should be pretty fast.

    Here's a rough DFS implementation, you can improve the details.

    sol_list = []
    def dfs(i, num, N):
      # print(i, num)
      if num > N: # too much, need to break
        return
      if num <= N and num >= 10: # perfect range, add to solution, I can add some repeated solution as I called dfs(i+1,0,N) multiple times
        global sol_list
        # print(num)
        sol_list.append(num) # add to solution
    
      if i > 7:
        return
      if num == 0: # I can call another 0
        dfs(i+1, 0, N) # this is not needed if the numbers are added in the previous list without checking
      last_dig = num % 10
      if last_dig == 0:
          dfs(i+1, num*10 + 1, N) # if last digit is 0, we can only choose 1 as next digit not -1
      elif last_dig == 9:
        dfs(i+1, num*10 + 8, N)
      else:
        dfs(i+1, num*10 + (last_dig-1), N)
        dfs(i+1, num*10 + (last_dig+1), N)
    
    import time
    t1 = time.time()
    [dfs(0, i, 10000000) for i in range(10)] # staring with every digit possible 0-9
    t2 = time.time()
    print(t2-t1)
    sol = sorted(set(sol_list))
    print(sol) # added some repeated solutions, it's easier to set them
    
    0 讨论(0)
  • 2021-01-21 18:29
    from itertools import product
    from itertools import accumulate
    import time
    
    def main(n):
        result=set()
        for length in range(2,7):
            dxss=list(product([-1,1],repeat=length-1))
            for initial in range(1,10):
                for dxs in dxss:
                    ans=list(accumulate(dxs,initial=initial))
                    if all([(y in range(0,10)) for y in ans]):
                         result.add(int("".join(map(str,ans))))
        sorted_lst=sorted(result)
        return [x for x in sorted_lst if x<n]
    
    n=10000000
    start=time.time()
    lst=main(n)
    stop=time.time()
    print("time={0}[s]".format(stop-start))
    print(lst)
    

    time=0.0020003318786621094[s]

    [10,12,21,...989898]

    Step number definition is "(nth digit - n-1th digit)= 1 or -1".

    N is 10 < N < 10**7.Therefore, I must decide 1st number(1or2or..9) and 6 dx constructed by 1 or -1.

    0 讨论(0)
  • 2021-01-21 18:33

    Since I can't comment yet. I will explain the idea of Nick's algorithm here.

    1. Create 1-digit number list [1,2,3,4,5,6,7,8,9]

    2. Create 2-digit number list by combining number k in 1-digit number list with k*10 + (k-1) or k*10 + (k+1), for example 3 will generate 32 or 34

    3. Repeat the step 2 until reaches m-digit number. m is calculated before.
    0 讨论(0)
  • 2021-01-21 18:43

    You can simplify the generation of numbers by noting that each time a digit is added to an existing stepping number it must be either 1 more or 1 less than the existing last digit. So we can generate all the stepping numbers with a given number of digits by starting with single digit numbers (1-9) and then repeatedly adding digits to them until we have reached the number of digits we want. So for example, starting with the digit 1, and needing to go to 4 digits, we would produce

    1 => 10, 12
    10, 12 => 101, 121, 123
    101, 121, 123 => 1010, 1012, 1210, 1212, 1232, 1234
    

    The number of digits we need is computed by using math.ceil(math.log10(N)).

    import math
    
    def stepNums(N):
        if N < 10:
            return -1
        digits = math.ceil(math.log10(N))
        sn = [[]] * digits
        # 1 digit stepping numbers
        sn[0] = list(range(1, 10))
        # m digit stepping numbers
        for m in range(1, digits):
            sn[m] = []
            for s in sn[m-1]:
                if s % 10 != 0:
                    sn[m].append(s * 10 + s % 10 - 1)
                if s % 10 != 9:
                    sn[m].append(s * 10 + s % 10 + 1)
        return [s for l in sn for s in l if 10 <= s <= N]
    

    e.g.

    print(stepNums(3454))
    

    Output:

    [10, 12, 21, 23, 32, 34, 43, 45, 54, 56, 65, 67, 76, 78, 87, 89, 98, 101, 121, 123, 210, 212, 232, 234, 321, 323, 343, 345, 432, 434, 454, 456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 987, 989, 1010, 1012, 1210, 1212, 1232, 1234, 2101, 2121, 2123, 2321, 2323, 2343, 2345, 3210, 3212, 3232, 3234, 3432, 3434, 3454]
    

    Note that the code could potentially be sped up by comparing the generated numbers to N so that when calling stepNums(10001) we don't generate all the numbers up to 98989.

    0 讨论(0)
提交回复
热议问题