Belirli bir sayı listesi ve aritmetik işleçleri kullanarak sayı oluşturma


11

Size bir numara listesi L = [17, 5, 9, 17, 59, 14], bir çanta operatörü O = {+:7, -:3, *:5, /:1}ve bir numara verilir N = 569.

Görev

LSol taraftaki tüm sayıları ve yalnızca Nsağ taraftaki sayıyı kullanan bir denklem çıkar . Bu mümkün değilse False çıktısını alın. Örnek çözüm:

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

Sınırlamalar ve Açıklama

  • Sayıları birleştiremezsiniz ( [13,37]olarak kullanılamaz 1337)
  • Yalnızca doğal sayılar ve sıfır görünür L.
  • Sıralama Lönemli değil.
  • İçindeki tüm sayıları kullanmalısınız L.
  • Sadece operatörler +, -, *, /görünür O.
  • Ogerekenden daha fazla operatöre sahip olabilir, ancak en azından |L|-1operatörler
  • Her bir operatörü, içindeki değere kadar istediğiniz sayıda kullanabilirsiniz O.
  • Dört işlemin Otümü standart matematiksel işlemlerdir; özellikle /kesin kesirlerle normal bölünmedir.

makas

  • Daha az puan, daha iyi
  • Kodunuzun her karakteri size bir puan verir

Okuması kolay golf olmayan bir versiyon sağlamanız gerekir.

Arka fon

Bir benzer soru Yığın taşması istendi. İlginç bir kod-golf meydan okuma olabileceğini düşündüm.

Hesaplama Karmaşıklığı

Peter Taylor'ın yorumlarda söylediği gibi, alt küme toplamını bununla çözebilirsiniz :

  1. Bir alt küme toplamı örneğiniz var (bu nedenle bir S tamsayı kümesi ve bir x sayısı)
  2. L: = S + [0, ..., 0] (| S | sıfır kez), N: = x, O: = {+: | S | -1, *: | S | - 100}
  3. Şimdi problemimin bu örneğini çöz
  4. Alt küme toplamı için çözüm, sıfır ile çarpılmayan S sayılarıdır.

O (2 ^ n) değerinden daha iyi bir Algoritma bulursanız, P = NP olduğunu kanıtlarsınız. As NP vs P bir olan Milenyum Ödülü Problemi ve dolayısıyla değer 1.000.000 ABD-Doları, Birileri bunun için bir çözüm bulur olasılığı son derece düşüktür. Bu yüzden sıralamanın bu kısmını kaldırdım.

Test senaryoları

Aşağıdakiler sadece geçerli cevaplar değildir, başka çözümler de vardır ve bunlara izin verilir:

  • ( [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

Öyle m = |L|mi? Evetse, çalışma zamanının bu listenin boyutuna bağlı olmamasını nasıl bekleyebilirsiniz? Örneğin [2,2],[+,+,...,+,/],1,. Aslında, n O (m) olduğu için, hepsini m cinsinden yazabilirsiniz.
boothby

3
Bu nasıl bir aritmetik - kesin kesirler, tamsayı ( /div), sadece kayan nokta ve yuvarlama hataları için umut, ...?
counterclockwis

4
Neden hesaplama karmaşıklığı için karmaşık puanlama kuralları? Alt küme toplamında kolay bir azalma var, bu yüzden O (2 ^ n) 'den daha iyi bir şey bir milyon USD değerinde.
Peter Taylor


1
3. test davası yanlış değil ...5+10+2*3+7*0+0...
Shmiddty

Yanıtlar:


3

Python 2.7 / 478 karakter

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],[])

Ana fikir, aramak için bir ifadenin postfix formunu kullanmaktır. Örneğin, 2*(3+4)postfix formunda olacak 234+*. Böylece sorun, kısmen L+ ' Oya dönüşen permütasyon bulmaya başlar N.

Aşağıdaki sürüm desteksiz sürümdür. Yığın stkbenziyor [(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
Vay canına, bu beklediğimden daha kısa. Bir dönüşüm postfix <=> infix içeren bir algoritma karaladım, ancak karalamam uygulamanızdan çok daha kısa değildi. Etkileyici. Ve inşaat için teşekkürler P[opr](v1, v2). Lambdaları ve sözlükleri bir araya getirmeyi hiç düşünmemiştim, ancak şimdi açık görünüyor.
Martin Thoma

Çözümünüzü 4. test çantayla test etmeye çalıştım. 2 saat sonra, yürütmeyi durdurdum.
Martin Thoma

@moose Daha hızlı hale getirmek için biraz sezgisel eklemeye çalışacağım. Ancak bundan sonra kod uzunluğu iki katına çıkabilir.
Ray

Kesir'i burada yaptığım gibi kullanmak cevabınızdaki bir sorunu çözer. Sağladığım bağlantıda verilen örnek için deneyin. Geçerli kodunuz bir cevap bulamıyor, ancak kesir kullandığınızda yanıt veriyor.
Martin Thoma
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.