简体   繁体   中英

How to get all values possible from a list of number without itertools

I want to create an algorithm that find all values that can be created with the 4 basic operations + - * / from a list of number n , where 2 <= len(l) <= 6 and n >= 1 All numbers must be integers. I have seen a lot of similar topics but I don't want to use the itertool method, I want to understand why my recursive program doesn't work

I tried to make a costly recursive program that makes an exhaustive search of all the possible combinations, like a tree with n=len(l) start and each tree depth is n .

  • L list of the starting number
  • C the current value
  • M the list of all possible values

My code:

def result(L,C,M):
    if len(L)>0:
            for i in range(len(L)) :
                a=L[i]
                if C>=a:
                    l=deepcopy(L)  
                    l.remove(a)
                    m=[]  # new current values 
                    #+
                    m.append(C+a)
                    # * 1 is useless
                    if C !=1 or a !=1:
                            m.append(C*a)
                    # must be integer    
                    if C%a==0 and a<=C: # a can't be ==0
                            m.append(C//a)
                    #0 is useless
                    if C!=a:
                            m.append(C-a)
                    for r in m: #update all values possible
                            if r not in M:
                                    M.append(r)
                    for r in m: # call the fucntion again with new current values,and updated list of remaining number     
                            result(l,r,M)

def values_possible(L) :
    m=[]
    for i in  L:
        l=deepcopy(L) 
        l.remove(i)
        result(l,i,m)
    m.sort()
    return m

For small lists without duplicate numbers, my algorithm seems to work but with lists like [1,1,2,2,4,5] it misses some values.

It returns:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 94, 95, 96, 97, 98, 99, 100, 101, 
102, 104, 105, 110, 112, 115, 116, 118, 119, 120, 121, 122, 124, 125, 128, 130, 
140, 160]

but it misses 93,108,114,117,123,126,132,135,150,180 .

Let's take an even simpler example: [1, 1, 2, 2] .

One of the numbers your algorithm can't find is 9 = (1 + 2) * (1 + 2) .

Your algorithm simply cannot come up with this computation because it always deals with a "current" value C . You can start with C = 1 + 2 , but you cannot find the next 1 + 2 because it has to be constructed separately.

So your recursion will have to do at least some kind of partitioning into two groups, finding all the answers for those and then doing combining them.

Something like this could work:

def partitions(L):
    if not L:
        yield ([], [])
    else:
        for l, r in partitions(L[1:]):
            yield [L[0]] + l, r
            yield l, [L[0]] + r

def values_possible(L):
    if len(L) == 1:
        return L
    results = set()
    for a, b in partitions(L):
        if not a or not b:
            continue
        for va in values_possible(a):
            for vb in values_possible(b):
                results.add(va + vb)
                results.add(va * vb)
                if va > vb:
                    results.add(va - vb)
                if va % vb == 0:
                    results.add(va // vb)
    return results

Not too efficient though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM