แบ่งและอยู่อย่างมีความสุข ใครสนใจเกี่ยวกับส่วนของ Conquer


12

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

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

อินพุต

1 อาร์เรย์ขององค์ประกอบ (N * 2) ที่ระบุ N * 2 ไว้ในบรรทัดที่ 1
องค์ประกอบของอาร์เรย์ในบรรทัดต่อไปนี้

เอาท์พุต

2 อาร์เรย์ขององค์ประกอบ N แต่ละอย่างเช่น:
ความแตกต่างของ (ผลรวมขององค์ประกอบของอาร์เรย์ 1) และ (ผลรวมขององค์ประกอบของอาร์เรย์ 2) ใกล้เคียงที่สุดเท่าที่เป็นไปได้ถึง 0

ตัวอย่าง

อินพุต

4
1 2 3 4 

เอาท์พุต

1 4
2 3
diff=0

ข้อจำกัดความรับผิดชอบ : ฉันไม่มีภรรยาสองคน แต่เมื่อฉันรู้สึกไม่ดีฉันจินตนาการว่ามีภรรยาสองคน และทันใดนั้นฉันรู้สึกขอบคุณและมีความสุขที่ฉันมีเพียงคนเดียว : D


3
ตามที่มันยืน "2 องค์ประกอบขององค์ประกอบ N แต่ละ" บังคับให้กลุ่มมีขนาดเท่ากัน สิ่งนี้ตั้งใจหรือไม่ ตัวอย่างเช่นในขณะนี้สำหรับกลุ่มอินพุต1 1 1 1 1 5คำตอบที่ถูกต้องน่าจะเป็น1 1 1| 1 1 5ในขณะที่1 1 1 1 1| 5จะทำให้รู้สึกมากขึ้น
shiona

คิดว่าปัญหานี้ยังนำไปใช้กับฝาแฝดและอาจเป็นกับกลุ่มดาวเด็กอื่น ๆ ด้วย คริสต์มาสวันนี้ส่วนใหญ่เป็น 'เขาได้มากกว่าเหตุการณ์' ...
TheConstructor

1
@ shiona ใช่ขนาดเท่ากันมีจุดประสงค์ @ TheConstructor การแบ่งระหว่างเด็กนั้นไม่ตลกเท่าการแบ่งระหว่างภรรยาสองคน : D
rahulroy9202

แท็กโค้ด - ท้าทายต้องมีเกณฑ์การชนะอย่างมีวัตถุประสงค์ นอกจากนี้ยังมีความเกี่ยวข้องอย่างใกล้ชิดกับปัญหาผลรวมย่อยซึ่งถูกถามที่นี่ก่อน
Howard

@Howard มีความแตกต่างที่สำคัญกับผลรวมย่อย: คุณต้องสร้างรายการขนาดสองเท่า ๆ กัน (ไม่เพียงมูลค่าเท่ากัน) คุณต้องใช้องค์ประกอบทั้งหมด ...
TheConstructor

คำตอบ:


4

ชวา

พยายามที่จะแก้ปัญหานี้ในสองขั้นตอน:

  1. สร้างรายการที่มีขนาดเท่ากันสองรายการโดยการเพิ่มรายการที่ใหญ่ที่สุดที่เหลือไปยังรายการที่เล็กกว่าในปัจจุบันและรายการถัดไป ทำซ้ำ
  2. ระบุรายการจากรายการทั้งสองที่สามารถสลับเพื่อลดความแตกต่างของมูลค่า

ใส่เหมือน

8
1 2 3 4 5 6 7 8

ได้รับการแก้ไขแล้วหลังจากขั้นตอนที่ 1 เช่น

2 3 5 8
1 4 6 7
diff=0

และการป้อนข้อมูลเช่น

6
1 4 5 6 7 8

จะต้องใช้ทั้งสองขั้นตอน

1 5 8
4 6 7
diff=3

(หลังจากเฟสหนึ่ง) กลายเป็นผลลัพธ์ของ

1 6 8
4 5 7
diff=1

แม้ว่าฉันจะสามารถรับประกันได้ว่าความพยายามนี้จะให้ทางออกเสมอ แต่ฉันไม่สามารถพิสูจน์ได้ว่าพบวิธีแก้ปัญหาที่ดีที่สุดในทุกกรณี ด้วยข้อ จำกัด ของรายการที่มีขนาดเท่ากัน แต่ก็ให้ความรู้สึกเหมือนจริงมากว่าไม่มีมุมกล่องเล็ก ๆ พิสูจน์ว่าฉันผิด ;-)

โปรแกรมบนideone.com

import java.util.*;

/**
 * Created to solve http://codegolf.stackexchange.com/q/23461/16293 .
 */
public class EqualSums {

    public static void main(String[] args) {
        final Scanner s = new Scanner(System.in);
        // Read number of elements to divide
        final int count = s.nextInt();
        if (count % 2 == 1) {
            throw new IllegalStateException(count + " can not be divided by 2. Consider adding a 0 value.");
        }
        // Read the elements to divide
        final SortedList valueStack = new SortedList(count);
        for (int i = 0; i < count; i++) {
            valueStack.add(s.nextLong());
        }

        final SortedList targetOne = new SortedList(count / 2);
        final SortedList targetTwo = new SortedList(count / 2);
        // Divide elements into two groups
        addInPairs(targetOne, targetTwo, valueStack);
        // Try to ensure groups have equal value
        retaliate(targetOne, targetTwo);

        // Output result
        System.out.println(targetOne);
        System.out.println(targetTwo);
        System.out.println("diff=" + Math.abs(targetOne.getSum() - targetTwo.getSum()));
    }

    private static void addInPairs(SortedList targetOne, SortedList targetTwo, SortedList valueStack) {
        SortedList smallerTarget = targetOne;
        SortedList biggerTarget = targetTwo;
        while (!valueStack.isEmpty()) {
            // Add biggest remaining value to small target
            smallerTarget.add(valueStack.removeLast());

            // Add second biggest remaining value to big target
            biggerTarget.add(valueStack.removeLast());

            // Flip targets if roles have changed
            if (smallerTarget.getSum() > biggerTarget.getSum()) {
                final SortedList temp = smallerTarget;
                smallerTarget = biggerTarget;
                biggerTarget = temp;
            }
        }

    }

    private static void retaliate(SortedList targetOne, SortedList targetTwo) {
        long difference;
        boolean changed;
        outer:
        do {
            difference = Math.abs(targetOne.getSum() - targetTwo.getSum());
            if (difference == 0) {
                return;
            }
            changed = false;
            // Try to find two values, that reduce the difference by changing them between targets
            for (Long valueOne : targetOne) {
                for (Long valueTwo : targetTwo) {
                    final Long tempOne = targetOne.getSum() + valueTwo - valueOne;
                    final Long tempTwo = targetTwo.getSum() - valueTwo + valueOne;
                    if (Math.abs(tempOne - tempTwo) < difference) {
                        targetOne.remove(valueOne);
                        targetTwo.add(valueOne);
                        targetTwo.remove(valueTwo);
                        targetOne.add(valueTwo);
                        changed = true;
                        continue outer;
                    }
                }
            }
        } while (changed);
    }

    public static class SortedList extends AbstractList<Long> {

        private final ArrayList<Long> list;
        private long sum = 0;

        public SortedList(int count) {
            list = new ArrayList<>(count);
        }

        // the next functions access list-field directly
        @Override
        public Long get(int index) {
            return list.get(index);
        }

        @Override
        public boolean add(final Long t) {
            final int i = Collections.binarySearch(list, t);
            if (i < 0) {
                // No equal element present
                list.add(-i - 1, t);
            } else {
                list.add(afterLastEqual(i, t), t);
            }
            sum += t;
            return true;
        }

        @Override
        public Long remove(int index) {
            final Long old = list.remove(index);
            sum -= old;
            return old;
        }

        @Override
        public int size() {
            return list.size();
        }

        // the next functions access list-field only through the functions above this point
        // to ensure the sum is well kept

        public long getSum() {
            return sum;
        }

        private int afterLastEqual(final int start, Object o) {
            int found = start;
            while (found < size() && o.equals(get(found))) {
                found++;
            }
            return found;
        }

        private int beforeFirstEqual(final int start, final Object o) {
            int found = start;
            while (found >= 0 && o.equals(get(found))) {
                found--;
            }
            return found;
        }

        @Override
        public int indexOf(Object o) {
            try {
                final int i = Collections.binarySearch(this, (Long) o);
                if (i >= 0) {
                    return beforeFirstEqual(i, o) + 1;
                }
            } catch (ClassCastException e) {
                // Object was not instance of Long
            }
            return -1;
        }

        @Override
        public int lastIndexOf(Object o) {
            try {
                final int i = Collections.binarySearch(this, (Long) o);
                if (i >= 0) {
                    return afterLastEqual(i, o) - 1;
                }
            } catch (ClassCastException e) {
                // Object was not instance of Long
            }
            return -1;
        }

        @Override
        public boolean remove(Object o) {
            if (o == null) {
                return false;
            }
            final int i = indexOf(o);
            if (i >= 0) {
                remove(i);
                return true;
            }
            return false;
        }

        public Long removeLast() {
            return remove(size() - 1);
        }

        public Long removeFirst() {
            return remove(0);
        }

        @Override
        public String toString() {
            Iterator<Long> it = iterator();
            if (!it.hasNext()) {
                return "";
            }

            StringBuilder sb = new StringBuilder();
            for (; ; ) {
                Long e = it.next();
                sb.append(e);
                if (!it.hasNext()) {
                    return sb.toString();
                }
                sb.append(' ');
            }
        }
    }
}

3

Brachylog 2

pᶠḍᵐ{+ᵐo-}ᵒh

ลองออนไลน์!

นี่คือการประกวดความนิยม แต่นั่นไม่ได้หมายความว่าภาษากอล์ฟจะไม่เหมาะสม (จริง ๆ แล้วฉันควรจะตอบด้วย Jelly เพราะคำตอบของ Jelly มีแนวโน้มที่จะได้รับจำนวน upvote ที่ไม่สมส่วนด้วยเหตุผลบางประการไม่ว่าใครจะเป็นผู้ส่งพวกเขาหรือว่าพวกเขาเป็นนักกอล์ฟ แต่ Brachylog อ่านได้ง่ายขึ้น)

เราเริ่มต้นด้วยการจดรายการการเรียงสับเปลี่ยนทั้งหมดของอินพุท ( pᶠ) และแยกแต่ละอัน ( ) ออกเป็นสองส่วนเท่า ๆ กัน ( ; เราสามารถให้ห้อยได้ถ้าคุณมีภรรยามากกว่าสองคนด้วยเหตุผลบางอย่าง) จากนั้นเราสั่งการเรียงสับเปลี่ยน ( {…}ᵒ) โดยการหาผลรวม ( +) ของแต่ละครึ่ง( ) ครึ่งใช้ความแตกต่างแบบสัมบูรณ์ (เช่นo-"สั่งผลต่าง") และใช้ความแตกต่างเหล่านั้นเพื่อกำหนดลำดับการจัดเรียง ผลลัพธ์ที่ดีที่สุดคือผลลัพธ์แรกดังนั้นเราจะนำส่วนหัวของรายการด้วยhเพื่อให้ได้ผลลัพธ์


2

มาติกา

แบบฟอร์มการป้อนข้อมูล

สายป้อนจะต้องดำเนินการผ่าน STDIN assetsอ้างถึงจำนวนเงินที่จะแจกจ่ายให้กับภรรยา (หรือฝาแฝด) lengthคือจำนวนของสินทรัพย์

assets=ToExpression[Rest[s=StringSplit[input]]]
length=ToExpression[First[s]]

สำหรับวัตถุประสงค์ปัจจุบันเราจะสมมติว่าสินทรัพย์ประกอบด้วยจำนวนเต็มตั้งแต่ 1 ถึง 20

assets=Range[20];
length=Length[Range[20]]

การประมวลผล

(* find all possible distributions to one wife; the other presumably gets the remaining assets *)
r=Subsets[assets,{length/2}];

(*order them according to the difference with respect to the total of half of the assets. 
Remove the first set of assets.  One wife will get these.*)
s=SortBy[r/.{{a__Integer}:> {{a},Abs[Tr[Range[20]/2]-Tr[{a}]]}},Last][[1]];

(*The other wife's assets will be the complement.  The difference is carried over from the sorting routine. *)
Grid[{{Grid[{s[[1]],Complement[assets,s[[1]]]}]},{"difference = "<>ToString[s[[2]]]}}]

r20


การกระจายนั้นไม่ยุติธรรมหรือไม่? ดังนั้นเลือกอันอื่น

@ ผู้สร้างบันทึกว่าภรรยา 2 อาจโต้แย้งความจริงที่ว่าภรรยา 1 มีทรัพย์สินที่ดีที่สุดทั้งหมด ดังนั้นต่อไปนี้จะสร้างหุ้น "ยุติธรรม" ทั้งหมด (ผลต่าง = ผลต่างต่ำสุด) สำหรับภรรยา 1; ภรรยา 2 ได้ทรัพย์สินที่เหลือ ศูนย์หมายถึงความแตกต่างในสินทรัพย์สำหรับภรรยา มี 5448 วิธีในการกระจายเนื้อหาที่มีน้ำหนักตั้งแต่ 1 ถึง 20 มีการแสดงเพียงไม่กี่บรรทัด

รูปแบบคือ

s=SortBy[r/.{{a__Integer}:> {{a},Abs[Tr[Range[20]/2]-Tr[{a}]]}},Last];
z=Cases[s,{_List,x_}/;x==s[[1,2]]];
Short[z,10]
Length[z]

{{{1,2,3,4,5,16,17,18,19,20} 0}, {{1,2,3,4,6,15,17,18,19,20} 0}, {{1,2,3,4,7,14,17,18,19,20} 0}, {{1,2,3,4,7,15,16,18,19,20 } 0}, {{1,2,3,4,8,13,17,18,19,20} 0}, {{1,2,3,4,8,14,16,18,19 20} 0}, {{1,2,3,4,8,15,16,17,19,20} 0}, {{1,2,3,4,9,12,17,18 19,20} 0}, {{1,2,3,4,9,13,16,18,19,20} 0}, {{1,2,3,4,9,14,15 , 18,19,20} 0}, {{1,2,3,4,9,14,16,17,19,20} 0}, {{1,2,3,4,9,15 , 16,17,18,20} 0}, {{1,2,3,4,10,11,17,18,19,20} 0}, {{1,2,3,4,10 , 12,16,18,19,20}, 0}, <<5420>>, {{5,6,7,8,9,11,13,14,14,15,17}, 0}, {{5 , 6,7,8,9,12,13,14,15,16} 0}, {{5,6,7,8,10,11,12,13,14,19} 0}, { {5,6,7,8,10,11,12,13,15,18} 0}, {{5,6,7,8,10,11,12,13,16,17} 0} {{5,6,7,8,10,11,12,14,15,17} 0}, {{5,6,7,8,10,11,13,14,15,16} 0}, {{5,6,7,9,10,11,12,13,14,18} 0}, {{5,6,7,9,10,11,12,13,15,17 } 0}, {{5,6,7,9,10,11,12,14,15,16} 0}, {{5,6,8,9,10,11,12,13,14 17} 0}, {{5,6,8,9,10,11,12,13,15,16} 0}, {{5,7,8,9,10,11,12,13,14,16} 0}, {{6,7,8,9,10,11,12,13,14,15}}} 0

5448


การส่งก่อนสามารถพบได้ในการแก้ไข Permutationsมันอยู่ไกลไม่มีประสิทธิภาพมากขึ้นอาศัยมันไม่เกี่ยวกับ


Mathematica ดูสวยงามสำหรับงานดังกล่าว สิ่งหนึ่งที่สุดท้ายคือภรรยาที่แท้จริงอาจแย้งว่า 5 รายการที่มีค่าที่สุดทั้งหมดอยู่ในกองเดียว (ใช่ได้รับกับ 1 ถึง 20 ไม่มีวิธีแก้ปัญหาโดยไม่มีข้อโต้แย้ง)
TheConstructor

@ โดยปกติแล้วมีวิธีการกระจายทรัพย์สินค่อนข้างน้อย ฉันแสดงวิธีการบางอย่างในภาคผนวก หมายเหตุ: มีสินทรัพย์ของภรรยาเพียงคนเดียวที่ระบุไว้ อื่น ๆ ที่ได้รับการเติมเต็ม
DavidC

นั่นเป็นหนึ่งในเหตุผลที่ฉันเลือกที่จะสร้างสแต็ก inital ของฉันตามปกติ: ดังนั้นโดยปกติสิ่งที่มีค่าที่สุดสองอย่างนั้นไม่ได้อยู่ในสแต็กเดียวกัน ทางออกแรกของคุณพิสูจน์ว่ามีตัวเลข 10 คู่โดยรวมเป็น 21 คุณเลือกคู่ที่อยู่ติดกันโดยปริยาย
TheConstructor

ใช่ฉันขอขอบคุณตรรกะของวิธีการของคุณ
DavidC

2

J

มีสูตรโกงของ primitives J ทั้งหมดที่ลิงค์นี้ในกรณีที่คุณต้องการติดตามที่บ้าน โปรดจำไว้ว่า: J มักอ่านจากขวาไปซ้ายนั่น3*2+1คือ 7 ไม่ใช่ 9 ทุกกริยา (J สำหรับการทำงาน) เป็นแบบ monadic ดังนั้นด้านหน้าf yหรือแบบ dyadic ดังนั้นในระหว่างx f yนั้น

N =: (". 1!:1 ] 1) % 2          NB. number of items per wife
S =: ". 1!:1 ] 1                NB. list of items to distribute

bins =: #: i. 2 ^ 2*N           NB. all binary strings of length 2n
even =: bins #~ N = +/"1 bins   NB. select those with row-sum 1

NB. all distributions of equal numbers of items to each wife
NB. resultant shape: a list of 2xN matrices
NB. this /. adverb is where all the magic happens, see below
dist =: even ]/."1 S

diff =: | -/"1 +/"1 dist        NB. difference in wives' values
idx  =: (i. <./) diff           NB. index of the lowest difference

1!:2&2 idx { dist               NB. print the winning distribution of items
1!:2&2 'diff=', idx { diff      NB. and the difference of that distribution

หมายเหตุและคำอธิบาย:

  • u/หมายถึง "การพับu" เพื่อดำเนินการไบนารีกับแต่ละองค์ประกอบในรายการ ตัวอย่างเช่น: +/หมายถึงโฟลด์พลัสหรือผลรวม ; <.เป็นเลสเบี้ยนของดังนั้น<./วิธีการพับน้อยกว่าหรือขั้นต่ำ

  • u"1หมายถึง "ดำเนินการuกับเซลล์ 1 มิติ" เช่นเหนือทุกแถว โดยปกติคำกริยาใน J เป็นแบบอะตอมมิกหรือนำไปใช้กับการโต้แย้งทั้งหมด สิ่งนี้ใช้กับทั้งสองข้อโต้แย้งถ้าคำกริยาใช้ dyadically (มีสองข้อโต้แย้ง) พิจารณาสิ่งต่อไปนี้:

       i. 2 3        NB. just a 2x3 matrix of numbers
    0 1 2
    3 4 5
       +/   i. 2 3   NB. Sum the items
    3 5 7
       +/"1 i. 2 3   NB. Sum the items of each row
    3 12
    
  • #:เป็นคำกริยาที่ขยายจำนวนไปสู่การเป็นตัวแทนไบนารี เมื่อคุณใช้มันในรายการที่มีองค์ประกอบมากกว่าหนึ่งรายการมันจะจัดเรียงตัวเลขทั้งหมดอย่างถูกต้องเพื่อที่#:i.2^nจะให้คุณได้รับความยาวไบนารีสตริงทุกnรายการ

  • /.เมื่อใช้ dyadically จะเรียกว่าสำคัญ มันใช้องค์ประกอบของรายการทางด้านซ้ายเป็นปุ่มและองค์ประกอบทางด้านขวาเป็นค่า มันจัดกลุ่มค่าแต่ละชุดที่ใช้คีย์ร่วมกันจากนั้นทำการดำเนินการบางอย่างกับพวกเขา

    ในกรณีของ]/.การดำเนินการเป็นเพียงคำกริยาเอกลักษณ์ดังนั้นไม่มีอะไรพิเศษเกิดขึ้นที่นั่น แต่ความจริงที่ว่า/.จะแบ่งรายการสำหรับเราเป็นบิตที่สำคัญ นี่คือเหตุผลที่เราสร้างรายการไบนารี: เพื่อให้แต่ละรายการ ( "1) เราสามารถแบ่งของขวัญสำหรับภรรยาในรูปแบบที่เป็นไปได้ทั้งหมด

  • 1!:1]1และ1!:2&2เป็นการดำเนินการ read-in และ write-out ตามลำดับ 1!:nส่วนหนึ่งเป็นคำกริยาและหมายเลขอื่น ๆ คือการจัดการไฟล์ 1is console in, 2เป็น console out และ3 4 5คือ stdin, stdout และ stderr นอกจากนี้เรายังใช้".เมื่ออ่านเพื่อให้เราแปลงสตริงอินพุตเป็นตัวเลข


1
+1 สำหรับการส่งคำตอบใน J และอย่างน้อยพยายามเพื่อให้เข้าใจได้
เลเวลริเวอร์เซนต์

1

Clojure

(defn divide [n]
 (loop [lv [] rv [] d (reverse (sort n))]
  (if (empty? d)
   [lv rv]
   (if (> (reduce + lv) (reduce + rv))
     (if (>= (count lv ) (count rv))
       (recur lv (conj rv (first d)) (into [] (rest d)))
       (recur (conj lv (last d)) rv (pop d))) 
     (if (<= (count lv ) (count rv))
       (recur (conj lv (first d)) rv (into [] (rest d)) )
       (recur lv (conj rv (last d)) (pop d)))))))


 (defn display [[f s]]
   (println f)
   (println s)
   (println (str "Diff " (- (reduce + f) (reduce + s)))))

ทดสอบ

 (->> 
 [5 1 89 36 2 -4 20 7]
 divide 
 display)


 =: [89 -4 1 2]
    [36 20 7 5]
    Diff 20

ชุดผลลัพธ์ควรมีขนาดเท่ากันและความแตกต่างระหว่างค่าในแต่ละชุดควรพิมพ์ ตัดสินจากผลการทดสอบอย่างรวดเร็วเกี่ยวกับ ideoneคุณอาจพลาดทั้งสองจุด
TheConstructor

เพิ่มวิธีการแสดงผลเพื่อพิมพ์ผล
Mamun

ชุดผลลัพธ์ตอนนี้มีขนาดเท่ากัน
Mamun

สำหรับ[1 4 5 6 7 8]โปรแกรมของคุณคำนวณ[8 5 4] [7 6 1] Diff 3ว่าการแก้ปัญหาที่ชัดเจนมีความแตกต่าง 1 อยู่
TheConstructor

1

MATLAB

นี่คือทางออกของฉัน:

%input array
presents=zeros(2,8);
presents(1,1)=8; %number of presents
presents(2,:)=[1 2 7 4 5 3 2 8]; %list of presents

%calculate the cumulative sum of all permutations
%its all about the gift values
how_many=presents(1,1);
options=perms(presents(2,:);
subtotals=cumsum(options,2);

%find the first index where the difference between the two parts is minimal
%makes both wives happy!!
[~, double_happiness] = min(abs(sum(presents(2,:))/2-subtotals(:,how_many/2)));

%create the present lists for Jennifer and Kate :)
for_jennifer=options(double_happiness,1:how_many/2)
for_kate=options(double_happiness,how_many/2+1:end)

ตัวอย่างเช่นรายการปัจจุบันในซอร์สโค้ดของฉันส่งผลให้:

for_jennifer =

     8     2     5     1


for_kate =

     4     7     2     3

ซึ่งเป็นทั้ง 16

ถ้าฉันตีกอล์ฟรหัสของฉันซึ่งสนุกน้อยกว่าฉันจะได้รับ 132 ตัวอักษรที่ไม่มีการจับเวลา เอาชนะที่;)

function f(p);o=perms(p(:,2));s=cumsum(o,2);[~,d]=min(abs(sum(p(:,2))/2-s(:,p(1,1)/2)));a={o(d,1:p(1,1)/2);o(d,p(1,1)/2+1:end)};a{:}

อาร์เรย์อินพุตจะต้องเป็นสี่เหลี่ยมจัตุรัส
DavidC

ไม่ไม่เป็นรูปสี่เหลี่ยม? แต่ตอนนี้ฉันเห็นจำนวนรายการควรอยู่ในแถวแรก ฉันจะเปลี่ยนมัน
mmumboss

0

PHP

คำเตือน:รหัสสกปรกมาก
มันพยายามเปลี่ยนรูปแบบอาร์เรย์ที่เป็นไปได้ทุกครั้ง

ตัวอย่าง Ideone สำหรับ4/1 2 3 4: http://ideone.com/gIi174

<?php
// Discard the first input line! It's useless :)
fgets(STDIN);
$numbers = explode(' ', rtrim(fgets(STDIN)));
$valuePerWife = array_sum($numbers) / 2;

// Taken from here: http://stackoverflow.com/a/13194803/603003
// Credits to dAngelov: http://stackoverflow.com/users/955185/dangelov
function pc_permute($items, $perms = array( )) {
    if (empty($items)) {
        $return = array($perms);
    }  else {
        $return = array();
        for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
         list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             $return = array_merge($return, pc_permute($newitems, $newperms));
         }
    }
    return $return;
}


foreach (pc_permute($numbers) as $permutation) {
    $sum = 0;
    $rest = [];

    for ($i=0; $i<count($permutation); $i++) {
        $sum += $permutation[$i];
        if ($sum == $valuePerWife) {
            $rest = array_slice($permutation, $i + 1);
            break;
        }
    }

    if (array_sum($rest) == $valuePerWife) {
        echo implode(' ', array_slice($permutation, 0, $i + 1)), "\n";
        echo implode(' ', array_slice($permutation, $i + 1)), "\n";
        echo 'diff=0';
        exit;
    }
}
exit('DIDNT FOUND ANY COMBINATION!');

0

งูหลาม:

import itertools as t
raw_input()
a=[int(i) for i in raw_input().split()]
a=list(t.permutations(a))
b=len(a[0])/2
c=[(d[b:],d[:b]) for d in a]
d=[abs(sum(d[b:])-sum(d[:b])) for d in a]
e=zip(d,c)
e.sort()
print " ".join([str(i) for i in e[0][1][0]])
print " ".join([str(i) for i in e[0][1][1]])
print "diff",e[0][0]

หรือตีกอล์ฟเล็กน้อย:

import itertools as t
b=int(raw_input())/2
e=[(abs(sum(d[b:])-sum(d[:b])),(d[b:],d[:b])) for d in t.permutations([int(i) for i in raw_input().split()])]
e.sort()
f=e[0]
g=f[1]
print " ".join([str(i) for i in g[0]]),"\n"," ".join([str(i) for i in g[1]]),"\n","diff=",f[0]

หรือแม้กระทั่งตีกอล์ฟมากขึ้นเนื่องจากครึ่งไลน์เป็นเพียงการแต่งหน้า (สมมติว่าฉันสามารถดัมพ์อาเรย์ภายในแบบดิบได้เนื่องจากไม่ได้ระบุไว้ใน op) คุณสามารถละทิ้งprintอินเทอร์แอคทีฟ (ตัวอย่าง) เชลล์เชิงโต้ตอบและเพิ่ม a [::-1](ท้ายสุดหลังจาก[0]) หากคุณต้องการจริงๆ ความต่างสุดท้าย

import itertools as t
b=int(raw_input())/2
print sorted([(abs(sum(d[b:])-sum(d[:b])),(d[b:],d[:b])) for d in t.permutations([int(i) for i in raw_input().split()])])[0]

(ผลลัพธ์เป็น(0, ((1, 2, 7, 8), (3, 4, 5, 6))))

อย่างไรก็ตามนี่เป็นเพียงการทำลายชุดค่าผสมที่เป็นไปได้ทั้งหมดและไม่ควรพิจารณาว่ามีประสิทธิภาพในระยะไกล อย่างไรก็ตามหากรายการที่มีความยาวเท่ากันไม่สำคัญก็จะทำงานได้เช่นกัน (ในอาร์เรย์ขนาดใหญ่):

raw_input()
a,b=[],[]
for i in sorted([int(i) for i in raw_input().split()])[::-1]:
    b.append(i)
    if sum(b)>sum(a): b,a=a,b
print a,b,abs(sum(b)-sum(a))

ด้วยรหัสภายใต้สิ่งนี้มันทำงานด้วยความแตกต่างแทบทั้งหมด: 500k ในค่าสูงสุด 10 ^ 10 ไม่มากนักดังนั้นจะบอกว่า นี่เป็นสิ่งที่เร็วกว่ามากเช่นกันซึ่งรหัสอื่นอาจจะไม่เสร็จสิ้นภายในหนึ่งปี (และมันก็เป็นแง่ดีมาก) ซึ่งจะทำงานในเวลาประมาณครึ่งวินาทีถึงแม้ว่าระยะทางของคุณอาจแตกต่างกันไป

def raw_input():
    import random
    return " ".join([str(random.randint(1,10**10)) for _ in range(10000)])

raw_input()
a,b=[],[]
for i in sorted([int(i) for i in raw_input().split()])[::-1]:
    b.append(i)
    if sum(b)>sum(a): b,a=a,b
print a,b,abs(sum(b)-sum(a))

คำถาม: ทำไมโพสต์ CW ถึงเป็นเช่นนี้?
HyperNeutrino

0

Haskell

> import Data.List
> import Data.Function

ฉันใช้รายการ monad เพื่อแยกมันออก

> divide []=return ([], [])
> divide (x:xs)=do
>   (w1, w2) <- divide xs
>   [(x:w1, w2), (w1, x:w2)]

จากนั้นเราก็เป็นผู้ประเมิน

> rating (w1, w2)=abs $ (sum w1) - (sum w2)

แล้วฟังก์ชั่นที่จะลดความแตกต่าง

> best = minimumBy (compare `on` rating) . filter (\(x,y)->length x == length y)

และสิ่งที่รวมพวกเขาทั้งหมด

> bestDivison=best . divide

ถัดไปเป็นโปรแกรมแยกวิเคราะห์

> parse::String->[Int]
> parse=fmap read . words

และฟอร์แมตเอาท์พุท

> output (w1,w2)=unlines [unwords (map show w1)
>                        , unwords ( map show w2)
>                        , "diff="++(show $ abs $ (sum w1) - (sum w2))]

และตอนนี้โปรแกรม

> main = do
>   getLine --Ignored, I don't need the arrays length
>   input <- fmap parse getLine
>   putStrLn "" --For readability
>   putStrLn $ output $ bestDivison input

ตัวอย่าง:

λ <*Main>: main
8
5 1 89 36 2 -4 20 7

5 36 20 7
1 89 2 -4
diff=20

ชุดผลลัพธ์ควรมีขนาดเท่ากัน
TheConstructor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.