เรียงลำดับผลรวมย่อย


22

ชุดของnจำนวนบวกมี2^nชุดย่อย เราจะเรียกชุด "ดี" หากไม่มีชุดย่อยเหล่านั้นที่มีผลรวมเท่ากัน {2, 4, 5, 8}เป็นหนึ่งในชุดที่ดีเช่นนี้ เนื่องจากไม่มีชุดย่อยใดที่มีผลรวมเท่ากันเราจึงสามารถเรียงลำดับชุดย่อยตามผลรวม:

[{}, {2}, {4}, {5}, {2, 4}, {2, 5}, {8}, {4, 5}, {2, 8}, {2, 4, 5}, {4, 8}, {5, 8}, {2, 4, 8}, {2, 5, 8}, {4, 5, 8}, {2, 4, 5, 8}]

หากเราติดป้ายกำกับตัวเลข[2, 4, 5, 8]ด้วยสัญลักษณ์[a, b, c, d]เพื่อเพิ่มลำดับเราจะได้รับลำดับนามธรรมดังต่อไปนี้:

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}]

อีกชุดที่ดีของตัวเลขที่เป็นบวกสามารถมีลำดับที่เป็นนามธรรมหรือชุดอื่น ตัวอย่างเช่น[3, 4, 8, 10]เป็นชุดที่ดีที่มีลำดับนามธรรมที่แตกต่างกัน:

[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}]

ในการท้าทายนี้คุณต้องนับจำนวนลำดับนามธรรมที่แตกต่างของชุดnตัวเลขที่ดี ลำดับนี้คือOEIS A009997และค่าที่ทราบเริ่มต้นที่n=1:

1, 1, 2, 14, 516, 124187, 214580603

ตัวอย่างเช่นสำหรับn=3ต่อไปนี้เป็นลำดับนามธรรมที่เป็นไปได้ทั้งสอง:

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}]
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {a, b, c}]

สำหรับn=4ต่อไปนี้คือ 14 ลำดับนามธรรมที่เป็นไปได้รวมถึงตัวอย่างชุดที่ดีที่มีลำดับนั้น:

[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {a, b, c}, {d}, {a, d}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 4, 2, 1]                                       
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {d}, {a, b, c}, {a, d}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 6, 3, 2]                                      
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 7, 4, 2]                                      
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {d}, {a, d}, {b, c}, {a, b, c}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 4, 1]                                       
[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 8, 4, 3]                                      
[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {a, d}, {b, c}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 7, 4, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}, {d}, {a, d}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 4, 3, 2]                                      
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {d}, {a, b, c}, {a, d}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 4, 3, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 5, 4, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {a, d}, {b, c}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 7, 6, 2]                                      
[{}, {a}, {b}, {c}, {a, b}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 4, 3]                                       
[{}, {a}, {b}, {c}, {a, b}, {d}, {a, c}, {a, d}, {b, c}, {b, d}, {a, b, c}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 8, 6, 3]                                      
[{}, {a}, {b}, {c}, {d}, {a, b}, {a, c}, {b, c}, {a, d}, {b, d}, {c, d}, {a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 5, 4]                                       
[{}, {a}, {b}, {c}, {d}, {a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d}, {a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [7, 6, 5, 3]

ต่อไปนี้ไม่ใช่ลำดับนามธรรมที่ถูกต้อง:

{}, {a}, {b}, {c}, {d}, {a,b}, {e}, {a,c}, {b,c}, {a,d}, {a,e}, {b,d}, {b,e}, {c,d}, {a,b,c}, {a,b,d}, {c,e}, {d,e}, {a,b,e}, {a,c,d}, {a,c,e}, {b,c,d}, {b,c,e}, {a,d,e}, {b,d,e}, {a,b,c,d}, {c,d,e}, {a,b,c,e}, {a,b,d,e}, {a,c,d,e}, {b,c,d,e}, {a,b,c,d,e}

การสั่งซื้อนี้แสดงถึง:

d < a + b
b + c < a + d
a + e < b + d
a + b + d < c + e

การสรุปความไม่เท่าเทียมเหล่านี้ให้:

2a + 2b + c + 2d + e < 2a + 2b + c + 2d + e

ซึ่งเป็นความขัดแย้ง รหัสของคุณจะต้องไม่นับการสั่งซื้อนี้ n=5โต้แย้งดังกล่าวปรากฏตัวครั้งแรกที่ ตัวอย่างจากบทความนี้ตัวอย่าง 2.5 ในหน้า 3

การสั่งซื้อนี้ไม่ถูกต้องแม้จะมีความจริงที่ว่าA < Bหมายความว่าA U C < B U Cสำหรับการใด ๆCเคลื่อนจากและAB


รหัสหรือโปรแกรมของคุณจะต้องเร็วพอที่คุณจะสามารถรันให้เสร็จn=4ก่อนที่จะส่ง

การส่งอาจเป็นโปรแกรมฟังก์ชั่น ฯลฯ ตามปกติ

ช่องโหว่มาตรฐานเป็นสิ่งต้องห้ามเช่นเคย นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุดในจำนวนไบต์ชนะ อย่าลังเลที่จะถามคำถามชี้แจงในความคิดเห็น


ไม่เห็นเป็นเวลานาน isaac!
orlp

P,QPQPQpP,qQ(pq)abc

pP,qQ(pq){a,c},{b,c}

@ หรือดีที่จะกลับมา! ฉันคิดว่าฉันจะทำคำถามเป็นส่วนใหญ่สำหรับอนาคตอันใกล้
isaacg

คุณสามารถเพิ่มคำสั่งซื้อที่เป็นไปได้ 14 ข้อสำหรับ n = 4 หรือไม่
Peter Taylor

คำตอบ:


11

Python 3 + SciPy, 396 390 385 351 336 355 ไบต์

from scipy.optimize import*
n=int(input())
r=range(n)
def f(u):
 s=linprog(r,u,[-n]*len(u),options={'tol':.1});c=s.success;y=sorted(range(c<<n),key=lambda a:s.x.round()@[a>>i&1for i in r])
 for a,b in zip(y,y[1:]):
  v=[(a>>i&1)-(b>>i&1)for i in r]
  if~-(v in u):c+=f(u+[[-z for z in v]]);u+=v,
 return+c
print(f([[(i==j-1)-(i==j)for i in r]for j in r]))

ลองออนไลน์!

ตอนนี้ทำงานเป็นเวลาn = 5 ในเวลาประมาณ 5 วินาที if~-(v in u):สามารถถอดออกได้สำหรับ -18 ไบต์ แต่ลงโทษประสิทธิภาพมาก

หากคุณต้องการพิมพ์ลำดับนามธรรมทั้งหมดที่พบแทนที่จะเพียงแค่นับพวกเขาเพิ่มif c:print(s.x.round(),y)ก่อนforห่วง (เซตย่อยจะถูกแทนด้วยจำนวนเต็มไบนารีที่แต่ละบิตสอดคล้องกับการมีหรือไม่มีองค์ประกอบหนึ่ง: { a , c , d } ↔1101₂ = 13)

มันทำงานอย่างไร

fนับซ้ำลำดับนามธรรมที่เป็นไปตามรายการข้อ จำกัด ที่กำหนด เราเริ่มต้นด้วยข้อ จำกัดn ≤ , + n , B + nC , C + n ≤ d การใช้โปรแกรมเชิงเส้นเราหาวิธีการแก้ จำกัด (หรือกลับ 0 ถ้ามีไม่ได้เป็นหนึ่ง) -in กรณีนี้เราได้รับ= 4, B = 8, C = 12 D = 16 เรารอบวิธีการแก้จำนวนเต็ม จากนั้นคำนวณการเรียงลำดับการอ้างอิงโดยการเรียงลำดับชุดย่อยทั้งหมดตามผลรวม:

{ a }, { b }, { c }, { a , b }, { d }, { a , c }, { a , d }, { b , c }, { b , d }, { a , b , c }, { c , d }, { a , b , d }, { a , c , d }, { b , c , d }, {a , b , c , d }

ปัดเศษไม่สามารถทำให้เกิดข้อ จำกัด ใด ๆ ที่จะละเมิดโดยมากกว่าn / 2 ซึ่งเป็นเหตุผลที่เราได้เพิ่มอัตรากำไรขั้นต้นของn

เนื่องจาก Python sortedนั้นมีความเสถียรความสัมพันธ์ระหว่างชุดย่อยจะแตกในลำดับย้อนกลับ - พจนานุกรมเดียวกันที่เราสร้างมันขึ้นมา ดังนั้นเราสามารถจินตนาการได้ว่าจะแทนที่ { a , b , c , d } ด้วย { a · 2 ^ n + 2 ^ 0, b · 2 ^ n + 2 ^ 1, c · 2 ^ n + 2 ^ 2, d · 2 ^ n + 2 ^ 3} เพื่อรับการสั่งซื้อแบบเดียวกันโดยไม่มีความเกี่ยวข้องใด ๆ

แผนคือการจัดหมวดหมู่ทั้งหมด orderings นามธรรมอื่น ๆ โดยการวิเคราะห์กรณีขึ้นอยู่กับที่พวกเขาครั้งแรกที่ไม่เห็นด้วยกับการสั่งซื้ออ้างอิง:

อาจเป็น { a }> { b }
หรือ { a } <{ b }> { c }
หรือ { a } <{ b } <{ c }> { a , b }
หรือ { a } <{ b } < { c } <{ a , b }> { d },

ภายในแต่ละกรณีเราจะเพิ่มข้อ จำกัด ใหม่เหล่านี้ด้วยระยะขอบnและเรียกซ้ำfด้วยการเพิ่มข้อ จำกัด ใหม่

หมายเหตุ

ในขณะที่ฉันคาดเดา (แต่ไม่ได้คิด) ว่าโปรแกรมเชิงเส้นที่มีมาร์จิ้น 1 บนข้อ จำกัด นั้นจะเป็นจำนวนเต็มเสมอ สิ่งนี้กลายเป็นเท็จ: ตัวอย่างที่มีn = 7 คือ {2.5, 30, 62.5, 73.5, 82, 87.5, 99.5}

Python 606 ไบต์ (เร็วกว่าไม่มีไลบรารีภายนอก)

n=int(input())
r=range(n)
e=enumerate
def l(u,x):
 for i,v in e(u):
  for j,a in e(v):
   if a<0:break
  else:return[0]*len(x)
  if sum(b*x[k]for k,b in e(v))>0:
   x=l([[b*w[j]-a*w[k]for k,b in e(v)if k!=j]for w in u[:i]],x[:j]+x[j+1:]);x.insert(j,0)
   for k,b in e(v):
    if k!=j:x[j]+=b*x[k];x[k]*=-a
 return x
def f(u,x):
 x=l(u,x);c=any(x);y=sorted(range(c<<n),key=lambda a:sum(x[i]*(a>>i&1)for i in r))
 for a,b in zip(y,y[1:]):
  v=[(a>>i&1)-(b>>i&1)for i in r]+[1]
  if~-(v in u):c+=f(u+[[-z for z in v[:-1]]+[1]],x);u+=v,
 return+c
print(f([[(i==j-1)-(i==j)for i in r]+[1]for j in r],[1]*(n+1)))

ลองออนไลน์!

สิ่งนี้จะทำงานเป็นn = 5 ในหนึ่งในสี่ของวินาทีและn = 6 ใน 230 วินาที (75 วินาทีใน PyPy)

มันรวมถึงการแก้ปัญหาการเขียนโปรแกรมเชิงเส้นเขียนโปรแกรมด้วยมือโดยใช้คณิตศาสตร์จำนวนเต็มในพิกัดที่เป็นเนื้อเดียวกันเพื่อหลีกเลี่ยงปัญหาการปัดเศษจุดลอยตัว


390 ไบต์
Mr. Xcoder

@ Mr.Xcoder แน่นอนขอบคุณ!
Anders Kaseorg

@ ลินน์ขอบคุณ! ฉันประนีประนอมเล็กน้อยเพราะฉันไม่ต้องการลดความเร็วมากเกินไป - ใช้เวลาเกือบ 3 นาทีสำหรับ n = 5
Anders Kaseorg

1
@AlonAmit ดูเหมือนว่าจะใช้เวลาประมาณ 55 นาทีสำหรับ n = 6. SciPy ไม่ใช่ LP ที่ดีที่สุด ฉันมีรุ่นที่ใช้ GLPK แทน SciPy ที่ทำ n = 6 ใน 70 วินาที ยิ่งไปกว่านั้นเวอร์ชั่น SciPy ได้คำตอบที่ผิด (และ GLPK ถูกต้อง) …เอ่อนั่นคือ…น่าสนใจ…ฉันสงสัยว่านี่เป็นSciPy # 6690หรือไม่
Anders Kaseorg

1
@AlonAmit # 6690 ใช่ไหม แต่ฉันเพิ่มoptions={'tol':.1}ซึ่งดูเหมือนว่าจะดูแลปัญหา
Anders Kaseorg

0

Ruby ขนาด 308 ไบต์เร็วขึ้นมาก

รันเคส 4 ใน ~ 150ms ไม่มีการใช้ห้องสมุดเฉพาะทาง

->n{t=2**(n-1)
n==0 ?[[0]]:P[n-1].map{|a|b=a.map{|i|i+t}
[*0..t].repeated_combination(t).select{|m|m[0]>=a.index(n-1)}.map{|m|c,d=a.dup,b.dup;m.reverse.map{|i|c.insert(i,d.pop)};c}}.flatten(1).select{|p|p.combination(2).all?{|(x,y)|x&~y==0||y&~x!=0&&n.times.all?{|i|x!=y<<i+1}&&p.index(x&~y)<p.index(y&~x)}}}

มันกระจายผลซ้ำของกรณีเล็ก ๆ น้อย ๆ เช่น

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}]

ด้วยชุดย่อยที่สอดคล้องกันที่มีองค์ประกอบเพิ่มเติมที่เพิ่มเข้ามา - พวกเขาจะต้องรักษาลำดับญาติที่เหมือนกัน นอกจากนี้ยังช่วยให้มั่นใจว่ามีการเพิ่มซิงเกิลตันใหม่หลังจากซิงเกิลก่อนหน้าทั้งหมด

ส่วนที่ตรวจสอบความสอดคล้องนั้นเหมือนก่อน แต่ไม่มีชุดค่าผสมในการทดสอบน้อยกว่ามาก

รุ่นที่ขยายและแสดงความคิดเห็น:

->n{
    t=2**(n-1)
    if n==0
        [[0]]
    else
        # for each one of the previous nice orderings
        P[n-1].map { |a|
            # create the missing sets, keep order
            b = a.map{|i|i+t}
            # intersperse the two sets
            [*0..t].repeated_combination(t) # select t insertion points
                .select do |m|
                    # ensure the new singleton is after the old ones
                    m[0] >= a.index(n-1)
                end
                .map do |m|
                    # do the interspersion
                    c,d=a.dup,b.dup
                    m.reverse.map{|i|c.insert(i, d.pop)}
                    c
                end
        }.flatten(1).select{ |p|
            # check if the final ordering is still nice
            p.combination(2).all? { |(x,y)|
                (x&~y==0) || 
                (y&~x!=0) && 
                n.times.all?{|i|x!=y<<i+1} && 
                (p.index(x&~y)<p.index(y&~x))
            }
        }
    end
}

Ruby, 151 ไบต์ค่อนข้างช้า

(กรณีที่องค์ประกอบสามตัวใช้เวลา << 1 วินาทีกรณีที่สี่ยังคงทำงานอยู่)

->n{[*1...2**n-1].permutation.select{|p|p.combination(2).all?{|(x,y)|x&~y==0||y&~x!=0&&n.times.all?{|i|x!=y<<i+1}&&p.index(x&~y)<p.index(y&~x)}}.count}

มันทำงานกับการเป็นตัวแทนบิตฟิลด์ของชุดย่อยดังนั้นหนึ่งอาจต้องนวดผลลัพธ์ถ้าจำเป็นในการแสดงชุดย่อยตัวเอง

จัดรูปแบบ:

-> n {
  [*1...2**n-1]. # prepare permutations of non-empty and non-full sets
    permutation.
    select { |p|
      p.combination(2). # check all ordered pairs
        all? { |(x, y)|
          # first is subset of second 
          x &~ y == 0 ||
          # second is not subset of first
          y &~ x != 0 &&
          # first is not a right shift of second
          # (this normalizes the ordering on atoms)
          n.times.all? { |i| x != y << i+1 } &&
          # after taking out common elements, ordering agrees 
          p.index(x &~ y) < p.index(y &~ x)
        }
    }.
    count
}

ฉันไม่สามารถทดสอบมันเหนือ 3 บนเครื่องของฉัน แต่นี่ (139 ไบต์)ควรใช้งานได้เหมือนโซลูชันของคุณ การเปลี่ยนแปลง: ...x-1=> ..x-2, .select{...}.count=> .count{...}, |(x,y)|=> |x,y|, x&~y==0||y&~x!=0=> x&~y<1||y&~x>0เนื่องจากa&~bไม่สามารถลบได้หากฉันไม่ผิด
Asone Tuhid

1
ดูตัวอย่างที่n=5ฉันเพิ่งเพิ่ม หากฉันไม่ผิดรหัสของคุณจะยอมรับได้
isaacg

2
ลิงก์ TIO ที่แสดงว่าทำงานอย่างไม่ถูกต้องบนตัวอย่าง: ลองออนไลน์!
isaacg

1
รุ่นที่ใหม่กว่าของคุณดูเหมือนจะเป็นฟังก์ชันเรียกซ้ำPดังนั้นจึงไม่สามารถระบุตัวตนได้ นอกจากนี้ฉันคิดว่ามันยังคงล้มเหลวเนื่องจากตัวอย่างที่ฉันโพสต์ไว้
isaacg

1
สำหรับวิธีแก้ปัญหาที่เร็วกว่า: 280 ไบต์ลองออนไลน์! . โปรดทราบว่าคุณต้องรวมชื่อของฟังก์ชั่นวนซ้ำ ( P=) นอกจากนี้ฉันคิดว่าคุณต้องส่งคืนตัวเลขดังนั้นคุณอาจต้องรวมไว้ที่.sizeใดที่หนึ่ง
Asone Tuhid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.