Tạo số bằng cách sử dụng danh sách các số và toán tử số học đã cho


11

Bạn được cung cấp một danh sách các số L = [17, 5, 9, 17, 59, 14], một túi của các nhà khai thác O = {+:7, -:3, *:5, /:1}và một số N = 569.

Bài tập

Xuất ra một phương trình sử dụng tất cả các số ở Lphía bên trái và chỉ số Nở phía bên phải. Nếu điều này là không thể, đầu ra Sai. Giải pháp ví dụ:

59*(17-5)-9*17+14 = 569

Hạn chế và làm rõ

  • Bạn không được nối các số ( [13,37]có thể không được sử dụng như 1337)
  • Chỉ có số tự nhiên và số không sẽ xuất hiện trong L.
  • Thứ tự Lkhông quan trọng.
  • Bạn phải sử dụng tất cả các số trong L.
  • Chỉ các nhà khai thác +, -, *, /sẽ xuất hiện trong O.
  • Ocó thể có nhiều toán tử hơn bạn cần, nhưng ít nhất là các |L|-1toán tử
  • Bạn có thể sử dụng mỗi toán tử bất kỳ số lần lên đến giá trị trong O.
  • Tất cả bốn hoạt động trong Olà các hoạt động toán học tiêu chuẩn; đặc biệt, /là phân chia bình thường với các phân số chính xác.

Điểm

  • Càng ít điểm, càng tốt
  • Mỗi ký tự mã của bạn cung cấp cho bạn một điểm

Bạn phải cung cấp một phiên bản không chơi gôn dễ đọc.

Lý lịch

Một câu hỏi tương tự đã được hỏi về Stack Overflow. Tôi nghĩ rằng nó có thể là một thử thách golf-code thú vị.

Độ phức tạp tính toán

Như Peter Taylor đã nói trong các bình luận, bạn có thể giải tổng số tập hợp con bằng cách này:

  1. Bạn có một thể hiện của tổng tập hợp con (do đó một tập hợp S số nguyên và một số x)
  2. L: = S + [0, ..., 0] (| S | lần một số không), N: = x, O: = {+: | S | -1, *: | S | - 1, /: 0, -: 0}
  3. Bây giờ giải quyết trường hợp này của vấn đề của tôi
  4. Giải pháp cho tổng tập hợp con là số S không được nhân với số không.

Nếu bạn tìm thấy Thuật toán tốt hơn O (2 ^ n), bạn chứng minh rằng P = NP. Vì P vs NP là một vấn đề giải thưởng thiên niên kỷ và do đó trị giá 1.000.000 đô la Mỹ, rất khó có khả năng ai đó tìm ra giải pháp cho vấn đề này. Vì vậy, tôi loại bỏ phần này của bảng xếp hạng.

Các trường hợp thử nghiệm

Sau đây không phải là câu trả lời hợp lệ duy nhất, các giải pháp khác tồn tại và được cho phép:

  • ( [17,5,9,17,59,14], {+:7, -:3, *:5, /:1}, 569)
    => 59 * (17-5)- 9 * 17 + 14 = 569
  • ( [2,2], {'+':3, '-':3, '*':3, '/':3}, 1)
    => 2/2 = 1
  • ( [2,3,5,7,10,0,0,0,0,0,0,0], {'+':20, '-':20, '*':20, '/':20}, 16)
    => 5+10-2*3+7+0+0+0+0+0+0+0 = 16
  • ( [2,3,5,7,10,0,0,0,0,0,0,0], {'+':20, '-':20, '*':20, '/':20}, 15)
    => 5+10+0*(2+3+7)+0+0+0+0+0+0 = 15

m = |L|? Nếu có, làm thế nào bạn có thể mong đợi thời gian chạy không phụ thuộc vào kích thước của danh sách đó? Ví dụ , [2,2],[+,+,...,+,/],1. Trong thực tế, vì n là O (m), bạn có thể viết tất cả theo m.
gian hàng

3
Loại số học này sẽ được sử dụng - phân số chính xác, số nguyên ( /div), chỉ là dấu phẩy động và hy vọng không làm tròn-lỗi, ...?
đã ngừng quay ngược chiều

4
Tại sao các quy tắc tính điểm phức tạp cho độ phức tạp tính toán? Có một mức giảm dễ dàng từ tổng tập hợp con, do đó, bất cứ điều gì tốt hơn O (2 ^ n) đều đáng giá một triệu USD.
Peter Taylor


1
Trường hợp thử nghiệm thứ 3 không sai ...5+10+2*3+7*0+0...
Shmiddty

Câu trả lời:


3

Python 2.7 / 478 ký tự

L=[17,5,9,17,59,14]
O={'+':7,'-':3,'*':5,'/':1}
N=569
P=eval("{'+l+y,'-l-y,'*l*y,'/l/y}".replace('l',"':lambda x,y:x"))
def S(R,T):
 if len(T)>1:
  c,d=y=T.pop();a,b=x=T.pop()
  for o in O:
   if O[o]>0 and(o!='/'or y[0]):
    T+=[(P[o](a, c),'('+b+o+d+')')];O[o]-=1
    if S(R,T):return 1
    O[o]+=1;T.pop()
  T+=[x,y]
 elif not R:
  v,r=T[0]
  if v==N:print r
  return v==N
 for x in R[:]:
  R.remove(x);T+=[x]
  if S(R,T):return 1
  T.pop();R+=[x]
S([(x,`x`)for x in L],[])

Ý tưởng chính là sử dụng dạng postfix của một biểu thức để tìm kiếm. Ví dụ, 2*(3+4)ở dạng postfix sẽ là 234+*. Vì vậy, vấn đề trở thành một hoán vị một phần của L+ Omà bỏ qua N.

Phiên bản sau đây là phiên bản chưa được chỉnh sửa. Các ngăn xếp stktrông như thế nào [(5, '5'), (2, '5-3', (10, ((4+2)+(2*(4/2))))].

L = [17, 5, 9, 17, 59, 14]
O = {'+':7, '-':3, '*':5, '/':1} 
N = 569

P = {'+':lambda x,y:x+y,
     '-':lambda x,y:x-y,
     '*':lambda x,y:x*y,
     '/':lambda x,y:x/y}

def postfix_search(rest, stk):
    if len(stk) >= 2:
        y = (v2, r2) = stk.pop()
        x = (v1, r1) = stk.pop()
        for opr in O:
            if O[opr] > 0 and not (opr == '/' and v2 == 0):
                stk += [(P[opr](v1, v2), '('+r1+opr+r2+')')]
                O[opr] -= 1
                if postfix_search(rest, stk): return 1
                O[opr] += 1
                stk.pop()
        stk += [x, y]
    elif not rest:
        v, r = stk[0]
        if v == N: print(r)
        return v == N
    for x in list(rest):
        rest.remove(x)
        stk += [x]
        if postfix_search(rest, stk):
            return True
        stk.pop()
        rest += [x]
postfix_search(list(zip(L, map(str, L))), [])

1
Wow, nó ngắn hơn tôi mong đợi. Tôi đã viết nguệch ngoạc một thuật toán bao gồm một hậu tố chuyển đổi <=> infix, nhưng chữ viết nguệch ngoạc của tôi không ngắn hơn nhiều so với triển khai của bạn. Ấn tượng. Và cảm ơn cho việc xây dựng P[opr](v1, v2). Tôi chưa bao giờ nghĩ đến việc kết hợp lambdas và từ điển như thế này, mặc dù bây giờ nó có vẻ rõ ràng.
Martin Thoma

Tôi đã thử kiểm tra giải pháp của bạn với testcase thứ 4 của tôi. Sau 2h, tôi dừng hành quyết.
Martin Thoma

@moose Tôi sẽ cố gắng thêm một số heuristic để làm cho nó nhanh hơn. Nhưng sau đó, chiều dài mã có thể tăng gấp đôi.
Ray

Sử dụng Phân số như tôi đã làm ở đây khắc phục một vấn đề trong câu trả lời của bạn. Chỉ cần thử nó cho ví dụ đã cho trên liên kết tôi đã cung cấp. Mã hiện tại của bạn không tìm thấy câu trả lời, nhưng khi bạn sử dụng phân số thì không.
Martin Thoma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.