Toplamı eşit veya tam tersi olan ürünler


22

Eğlenceli bir eşdeğer çift 1 + 5 = 2 · 3 ve 1 · 5 = 2 + 3'tür . Bunun gibi çok şey var, bir diğeri 1 + 1 + 8 = 1 · 2 · 5 ve 1 · 1 · 8 = 1 + 2 + 5 . Genel bir üründe , n pozitif tam bir toplamına eşittir , n tersi pozitif tamsayılar ve yardımcısı.

Bu mücadelede , permütasyonlar hariç n> 1 bir giriş için tüm pozitif tamsayı kombinasyonlarını oluşturmalısınız . Bunları makul herhangi bir biçimde çıkarabilirsiniz. Örneğin, n = 3 için tüm olası çözümler şunlardır:

(2, 2, 2) (1, 1, 6)
(1, 2, 3) (1, 2, 3)
(1, 3, 3) (1, 1, 7)
(1, 2, 5) (1, 1, 8)

2GB RAM'imde 64-bit Intel Ubuntu dizüstü bilgisayarımla bir dakika içinde en yüksek n için en fazla kombinasyonu üretebilen program kazandı. Cevabınız 2GB'tan fazla RAM kullanıyorsa veya özgürce kullanılabilir bir yazılımla test edemediğim bir dilde yazılmışsa, cevabınızı puanlandırmayacağım. Cevapları iki hafta sonra anlayacağım ve kazananı seçeceğim. Daha sonra yarışmacı olmayan cevaplar elbette yayınlanabilir.

Tüm çözümleri dolu setleri neyi bilinen değil beri n , sen eksik çözümler üretmek sonrası cevaplara izin verilir. Bununla birlikte, başka bir cevap (daha fazla) eksiksiz bir çözüm üreterse, maksimum n değeri daha küçük olsa bile , bu cevap kazanır.


Açıklığa kavuşturmak için işte kazanana karar vermek için puanlama süreci:

  1. Programınızı n = 2, n = 3 vb. İle test edeceğim ... Tüm çıktılarınızı saklarım ve programınız bir dakika veya 2GB RAM'den fazla sürdüğünde durur. Program belirli bir giriş n için çalıştırıldığında, 1 dakikadan uzun sürerse program sonlandırılır.

  2. Tüm programlar için n = 2 olan tüm sonuçlara bakarım. Bir program diğerinden daha az geçerli çözümler ürettiyse, bu program elimine edilir.

  3. N = 3, n = 4, vb. İçin 2. adımı tekrarlayın.


1
Öyleyse pencerelere özel dillerde cevap yok mu?
Conor O'Brien,

3
Şahsen, puanlama kriterlerini beğenmedim. Çözümlerimizin işe yarayıp yaramadığını ve bilgisayarınızda yapılan testlerden sonuç alıncaya kadar eşiklerin nerede belirleneceğini bilmek imkansızdır. Bence basit bir kod golf daha iyi bir soru olur.
musicman523

2
Kodlamanın izin verilmediğini farz ediyorum. Ama o zaman bu kısıtlama gözlemlenemez olmaya yakın
Luis Mendo

1
@ user202729 Bilmiyorum, hangi programın daha fazla çözüm ürettiğini görmek için her n için her programı denemek zorundayım .
orlp

2
"Bundan iki hafta sonra" 3 gün önce.
GB

Yanıtlar:


4

C (gcc) , n = 50000000, 6499 ile 59 saniyede sonuçlanır

Neredeyse tamamen 1 saniyeden oluşan bir terabayttan fazla üretim yapmaktan kaçınmak için, 49999995 1s dizisi olarak kısaltılır 1x49999995.

#include <stdio.h>
#include <stdlib.h>

static int n, *a1, k1 = 0, *a2, k2 = 0, s1, p1, *factor;

static void out() {
  if (s1 == p1) {
    for (int i = 0; i < k1 && i < k2; i++) {
      if (a1[i] < a2[i])
        return;
      else if (a1[i] > a2[i])
        break;
    }
  }

  for (int i = 0; i < k1; i++)
    printf("%d ", a1[i]);
  printf("1x%d | ", n - k1);
  for (int i = 0; i < k2; i++)
    printf("%d ", a2[i]);
  printf("1x%d\n", n - k2);
}

static void gen2(int p, int s, int m);

static void gen3(int p, int s, int m, int x, int q) {
  int r = s - n + k2 + 2;
  int d = factor[q];
  do {
    if (x * d <= m)
      x *= d;
    q /= d;
  } while (q % d == 0);
  do {
    if (q == 1) {
      a2[k2++] = x;
      gen2(p / x, s - x, x);
      k2--;
    } else {
      gen3(p, s, m, x, q);
    }
    if (x % d != 0)
      break;
    x /= d;
  } while (p / (x * q) >= r - x * q);
}

static void gen2(int p, int s, int m) {
  int n2 = n - k2;
  if (p == 1) {
    if (s == n2)
      out();
  } else if (n2 >= 1 && m > 1) {
    int r = s - n2 + 1;
    if (r < 2 || p < r)
      return;
    if (m > r)
      m = r;
    if (factor[p] <= m)
      gen3(p, s, m, 1, p);
  }
}

static void gen1(int p, int s, int m) {
  int n1 = n - k1;
  p1 = p;
  s1 = s + n1;
  gen2(s1, p1, s + n1 + 1 - n);
  if (n1 != 0) {
    int *p1 = &a1[k1++];
    for (int x = 2; x <= m && p * x <= s + x + n1 - 1; x++) {
      *p1 = x;
      gen1(p * x, s + x, x);
    }
    k1--;
  }
}

int main(int argc, char **argv) {
  if (argc < 2)
    return 1;
  n = atoi(argv[1]);
  if (n < 2)
    return 1;
  a1 = malloc(n * sizeof(int));
  a2 = malloc(n * sizeof(int));
  factor = calloc(4 * n - 1, sizeof(int));
  for (int p = 2; p < 4 * n - 1; p++)
    if (factor[p] == 0) {
      factor[p] = p;
      for (int i = p; i <= (4 * n - 2) / p; i++)
        factor[p * i] = p;
    } else if (factor[p] < factor[p / factor[p]]) {
      factor[p] = factor[p / factor[p]];
    }
  gen1(1, 0, 3 * n - 1);
  return 0;
}

Çevrimiçi deneyin!


3

Mathematica, n = 293, 12 çözümle

OP meydan okumayı değiştirdi ve girdi istedi
İşte herhangi bir n'i girdi olarak alan yeni kod
n = 293 için 12 çözümü alıyorsunuz

If[#<5,Union[Sort/@Select[Tuples[{1,2,3,4,5,6,7,8,9},{#}],Tr@#==Times@@#&]],For[a=1,a<3,a++,For[b=a,b<3,b++,For[c=b,c<5,c++,For[d=c,d<10,d++,For[e=d,e<300,e++,If[Tr[s=Join[Table[1,#-5],{a,b,c,d,e}]]==Times@@s,Print[s]]]]]]]]&


giriş

[N]

Bu algoritmayı çevrimiçi olarak özgürce erişilebilen bir yazılım olan Wolfram Sandbox'ta test edebilirsiniz. Sadece bağlantıyı takip edin, kodu yapıştırın (ctrl + v), kodun sonundaki girişi yapıştırın ve çalıştırmak için shift + enter tuşlarına basın. Tüm çözümlerimi saniyeler içinde alacaksın

İşte ayrıca çevrimiçi deneyin! in C ++ (gcc)
(Kodumu ücretsiz bir dile çevirip çevirdiği için @ ThePirateBay'e teşekkürler)

bu program yalnızca {a, b, c} {a, b, c} biçiminde çözümler üretir
; bu, a + b + c = a * b * c anlamına gelir.

Hesaplamak 1 saniye sürer

on iki çözüm:

{1,1 ..., 1,1,1,2,293} {1,1 ..., 1,1,1,2,293}
{1,1 ..., 1,1,1,3,147} {1 , 1 ..., 1,1,1,3,147)
{1,1 ..., 1,1,1,5,74) {1,1 ..., 1,1,1,5,74}
{1,1 ..., 1,1,2,2,98) {1,1 ..., 1,1,2,2,98)
{1,1 ..., 1,1,2, 3,59} {1,1 ...,
1,1,2,3,59} {1,1 ..., 1,1,2,5,33} {1,1 ..., 1, 1,2,5,33}
{1,1 ..., 1,1,2,7,23} {1,1 ..., 1,1,2,7,23}
{1,1 .. ., 1,1,2,8,20} {1,1 ..., 1,1,2,8,20}
{1,1 ..., 1,1,3,3,37} {1 , 1 ..., 1,1,3,3,37
} {1,1 ..., 1,1,3,4,27} {1,1 ..., 1,1,3,4, 27}
{1,1 ..., 1,1,3,7,15} {1,1 ..., 1,1,3,7,15}
{1,1 ..., 1,2, 2,6,13) {1,1 ..., 1,2,2,6,13}


1
"Cevabınız [...] bir dilde yazılmışsa, özgürce kullanılabilir bir yazılımla test edemiyorum, cevabınızı alamayacağım."
Leaky Nun

4
@GB "Tamamlanmamış çözümler üreten cevaplar yayınlamanıza izin verildi"
user202729

1
programım "bir dakika içinde en yüksek n için en kombinasyonları ..generates" It hardcoded.It sadece bir dakika altında ilk 12 'en kolay' çözümler bulur değildir
J42161217

1
N'nin bir girdi olması gerektiği daha açık olabilirdi . Bunu şimdi açıklığa kavuşturdum. Programınızın bir n girdi alır görünmüyor .
orlp

2
@orlp Sabit! Programım herhangi bir n'i girdi olarak alıyor. N = 293 için 12 çözümü alırsınız. un-down oy ver, eğer her şey işe yaradığından beri!
J42161217

2

Python 2 , n = 175, 28 sonuç 59s

Bir azaltma faktörü 2 kullanarak biraz yavaşladı, ancak n = 83 ile başlayan daha fazla çözüm alıyor

Tek bir çalışmada TIO'da 92'ye kadar n sonuçları alıyorum.

def submats(n, r):
    if n == r:
        return [[]]
    elif r > 6:
        base = 1
    else:
        base = 2
    mx = max(base, int(n*2**(1-r)))

    mats = []
    subs = submats(n, r+1)
    for m in subs:
        if m:
            mn = m[-1]
        else:
            mn = 1
        for i in range(mn, mx + 1):
            if i * mn < 3*n:
                mats += [m + [i]]
    return mats

def mats(n):
    subs = []
    for sub in submats(n, 0):
        sum = 0
        prod = 1
        for m in sub:
            sum += m
            prod *= m
        if prod > n and prod < n*3:
            subs += [[sub, sum, prod]]
    return subs

def sols(n):
    mat = mats(n)
    sol = [
        [[1]*(n-1)+[3*n-1],[1]*(n-2)+[2,2*n-1]],
    ]
    if n > 2:
        sol += [[[1]*(n-1)+[2*n+1],[1]*(n-2)+[3,n]]]
    for first in mat:
        for second in mat:
            if first[2] == second[1] and first[1] == second[2] and [second[0], first[0]] not in sol:
                sol += [[first[0], second[0]]];
    return sol

Çevrimiçi deneyin!


1
"5 elementi [1..2] tut ve 3n 'i sınırla ..." Algoritmamı beğendiğine sevindim ;-)
J42161217

Ruby sürümünde zaten benzer bir şey yaptım ve şimdi bu sınırlamayı kaldırmaya çalışıyorum.
GB

Belirli bir n için algoritmanızda kaç çözüm kodlanmış?
J42161217

Gerçekten kodlanmış değil: Kısayol kullanılarak 2 standart çözüm üretilebilir (aynı kombinasyonun olduğu n = 2 hariç) ve bunları atlayarak, aralığı 3n yerine 2n ile sınırlayabilirim. Bu kodlanmış olarak kabul edilirse değiştireceğim.
GB

1
61 için benim
sonucum

1

Ruby , n = 12 6 çözüm bulur

En azından TIO’da, 1’den 11’e kadar olan normal sonuçlar

->n{
  arr=[*1..n*3].product(*(0..n-2).map{|x|
    [*1..[n/3**x,2].max]|[1]
  }).select{|a|
    a.count(1) >= n-4
  }.map(&:sort).uniq
  arr.product(arr).map(&:sort).uniq.select{|r|
    r[0].reduce(&:+) == r[1].reduce(&:*) &&
    r[0].reduce(&:*) == r[1].reduce(&:+)
  }
}

Çevrimiçi deneyin!

Dizüstü bilgisayarımda n = 13 için bir dakikanın altında 10 sonuç alır.


1

Mathematica, n = 19, 11 çözüm

OP’nin yeni kriterlerine göre bu yeni cevabım

(SOL = {};
For[a = 1, a < 3, a++, 
For[b = a, b < 3, b++, 
For[c = b, c < 5, c++, 
 For[d = c, d < 6, d++, 
  For[e = d, e < 3#, e++, 
   For[k = 1, k < 3, k++, 
    For[l = k, l < 3, l++, 
     For[m = l, m < 5, m++, 
      For[n = m, n < 6, n++, For[o = n, o < 3#, o++,
        s = Join[Table[1, # - 5], {a, b, c, d, e}];
        t = Join[Table[1, # - 5], {k, l, m, n, o}];            
        If[Tr[s[[-# ;;]]] == Times @@ t[[-# ;;]] && 
          Tr[t[[-# ;;]]] == Times @@ s[[-# ;;]], 
         AppendTo[SOL,{s[[-#;;]],t[[-#;;]]}]]]]]]]]]]]];
Union[SortBy[#,Last]&/@SOL])&

sonunda bir giriş [n] yaparsanız, program çözümleri görüntüler.

İşte sonuçlarım (eski dizüstü bilgisayarım 64-bit 2.4GHz'de)

n-> çözümler
2 -> 2
3 -> 4
4 -> 3
5 -> 5
6 -> 4
7 -> 6
8 -> 5
9 -> 7
10 -> 7
11 -> 8
12 -> 6 (içinde 17 saniye)
13 -> 10 (20 saniyede)
14 -> 7 (25 saniyede)
15 -> 7 (29 saniyede)
16 -> 9 (34 saniyede)
17 -> 10 (39 saniyede)
18 - > 9 (45 saniyede)
19 -> 11 (51 saniyede)
20 -> 7 (58 saniyede)


1

Haskell, çok hızlı çözüm

import System.Environment

pr n v = prh n v v

prh 1 v l = [ [v] | v<=l ]
prh n 1 _ = [ take n $ repeat 1 ]
prh _ _ 1 = []
prh n v l = [ d:r | d <-[2..l], v `mod` d == 0, r <- prh (n-1) (v`div`d) d ]

wo n v = [ (c,k) | c <- pr n v, let s = sum c, s>=v,
                   k <- pr n s, sum k == v, s>v || c>=k ]

f n = concatMap (wo n) [n+1..3*n]

main = do [ inp ] <- getArgs
          let results = zip [1..] $ f (read inp)
          mapM_ (\(n,s) -> putStrLn $ (show n) ++ ": " ++ (show s)) results

fçözümleri hesaplar, mainfonksiyon girdiyi komut satırından almayı ve bazı biçimlendirme ve sayma işlemlerini ekler.


Bu şekilde derleyin: ghc -O3 -o prodsum prodsum.hsve komut satırı argümanı ile çalıştırın:./prodsum 6
Christian Sievers

0

Haskell , n = 10 2 çözümle


import           Data.List

removeDups = foldl' (\seen x -> if x `elem` seen then seen else x : seen) []
removeDups' = foldl' (\seen x -> if x `elem` seen then seen else x : seen) []

f n= removeDups $ map sort filterSums
  where maxNumber = 4
        func x y = if (((fst x) == (fst.snd$y)) && ((fst y) == (fst.snd$x)))
                     then [(snd.snd$x),(snd.snd$y)]
                     else [[],[]]
        pOf = removeDups' $ (map sort (mapM (const [1..maxNumber]) [1..n]))
        sumOf = map (\x->((sum x),((product x), x))) pOf
        filterSums = filter (\x-> not$(x == [[],[]])) (funcsumOfsumOf)

Bu saçmalık gibi davranıyor, ama en azından düzelttim, bu yüzden şu anda mücadeleyi ele alıyorum!

Çevrimiçi deneyin!


n = 2 için ["[3,3] [2,3]", "[2,2] [2,2]", "[1,3] [2,2]", "[1, 2] [1,3] "," [1,1] [1,2] "] yanlış olan
J42161217

Tüm çözümler aslında yanlış gibi görünüyor
GB

@ Jenny_mathy Nasıl yanlış? 3 + 3 6 ve 2 * 3 6'dır. Soruyu yanlış mı anlıyorum.
maple_shaft

"tam tersi" eksik
J42161217

@Jenny_mathy Benim açımdan aptalca hata! Düzelttim, şimdi çalışmalıyım.
maple_shaft

0

Aksiyom, n = 83, burada 59 saniye içinde

-- copy the below text in the file name "thisfile.input" 
-- and give something as the command below in the Axiom window:
-- )read C:\Users\thisuser\thisdirectory\thisfile

)cl all
)time on

-- controlla che l'array a e' formato da elementi  a.i<=a.(i+1)
tv(a:List PI):Boolean==(for i in 1..#a-1 repeat if a.i> a.(i+1) then return false;true)

-- funzione incremento: incrementa a, con #a=n=b/3,sotto la regola di "reduce(+,a)+#a-1>=reduce(*,a)"
-- e che n<reduce(*,a)<3*n ed reduce(+,a)<3*n 
inc3(a:List PI):INT==
   i:=1; n:=#a; b:=3*n
   repeat
      if i>n  then return 0
      x:=reduce(*,a)
      if x>=b then a.i:=1
      else
          y:=reduce(+,a)
          if y>b then a.i=1
          else if y+n-1>=x then
                      x:=x quo a.i
                      a.i:=a.i+1
                      x:=x*a.i
                      if tv(a) then break
                      else a.i:=1
          else a.i:=1
      i:=i+1
   if x<=n then return inc3(a) -- x<=n non va
   x

-- ritorna una lista di liste di 4 divisori di n
-- tali che il loro prodotto e' n
g4(n:PI):List List PI==
  a:=divisors(n)
  r:List List PI:=[]
  for i in 1..#a repeat
     for j in i..#a repeat
        x:=a.i*a.j
        if x*a.j>n then break
        for k in j..#a repeat
            y:=x*a.k
            if y*a.k>n then break
            for h in k..#a repeat
                z:=y*a.h
                if z=n  then r:=cons([a.h,a.k,a.j,a.i],r)
                if z>=n then break 
  r

-- ritorna una lista di liste di 3 divisori di n
-- tali che il loro prodotto e' n
g(n:PI):List List PI==
  a:=divisors(n)
  r:List List PI:=[]
  for i in 1..#a repeat
     for j in i..#a repeat
        x:=a.i*a.j
        if x*a.j>n then break
        for k in j..#a repeat
            y:=x*a.k
            if y=n  then r:=cons([a.k,a.j,a.i],r)
            if y>=n then break
  r

-- cerca che [a,b] nn si trovi gia' in r
searchr(r:List List List PI,a:List PI,b:List PI):Boolean==
  aa:=sort(a); bb:=sort(b)
  for i in 1..#r repeat
      x:=sort(r.i.1);y:=sort(r.i.2)
      if x=aa and y=bb then return false
      if x=bb and y=aa then return false
  true

-- input n:PI
-- ritorna r, tale che se [a,b] in r
-- allora #a=#b=n
--        ed reduce(+,a)=reduce(*,b) ed reduce(+,b)=reduce(*,a)
f(n:PI):List List List PI==
  n>100000 or n<=1 =>[]
  a:List PI:=[]; b:List PI:=[]; r:List List List PI:=[]
  for i in 1..n repeat(a:=cons(1,a);b:=cons(1,b))
  if n~=72 and n<86 then  m:=min(3,n)
  else                    m:=min(4,n) 
  q:=reduce(*,a) 
  repeat
    w:=reduce(+,a)
    if n~=72 and n<86 then x:= g(w)
    else                   x:=g4(w)
    if q=w then r:=cons([copy a, copy a],r)
    for i in 1..#x repeat
           for j in 1..m repeat
                  b.j:=(x.i).j
           -- per costruzione abbiamo che reduce(+,a)= prodotto dei b.i=reduce(*,b)
           -- manca solo di controllare che reduce(+,b)=reduce(*,a)=q
           if reduce(+,b)=q and searchr(r,a,b) then r:=cons([copy a, copy b],r)
    q:=inc3(a)
    if q=0 then break
  r

Sonuçlar:

 for i in 2..83 repeat output [i, # f(i)]
   [2,2][3,4][4,3][5,5][6,4][7,6][8,5][9,7][10,7][11,8][12,6][13,10][14,7][15,7]
   [16,10][17,10][18,9][19,12][20,7][21,13][22,9][23,14][24,7][25,13][26,11]
   [27,10][28,11][29,15][30,9][31,16][32,11][33,17][34,9][35,9][36,13][37,19]
   [38,11][39,14][40,12][41,17][42,11][43,20][44,12][45,16][46,14][47,14][48,13]
   [49,16][50,14][51,17][52,11][53,20][54,15][55,17]
   [56,14][57,20][58,17][59,16][60,15][61,28][62,15][63,16][64,17][65,18]
   [66,14][67,23][68,20][69,19][70,13][71,18][72,15][73,30][74,15][75,17][76,18]
   [77,25][78,16][79,27][80,9][81,23][82,17][83,26]


 f 3
    [[[1,2,5],[8,1,1]],[[1,3,3],[7,1,1]],[[1,2,3],[1,2,3]],[[2,2,2],[6,1,1]]]
                                     Type: List List List PositiveInteger
                                   Time: 0.07 (IN) + 0.05 (OT) = 0.12 sec

Axiom'daki metnin üzerinde çalıştırmanın yolu, tüm bu metni bir dosyaya kopyalayın, dosyayı şu adla kaydedin: Name.input, bir Axiom penceresinde ") absolutepath / Name" kullanın.
results: (# f (i), f (i) dizisinin uzunluğunu bulur, bu çözümlerin sayısıdır)

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.