คุณควรจัดเก้าอี้อย่างไร?


20

คุณสอนชั้นเรียนของนักเรียนที่มีความชอบที่น่าสนใจสำหรับวิธีการจัดเก้าอี้ของพวกเขา มีข้อกำหนดเฉพาะ 3 ข้อที่พวกเขามีสำหรับวิธีการจัดเก้าอี้:

  1. พวกเขาส่วนใหญ่จะถูกจัดเรียงในรูปสี่เหลี่ยมผืนผ้าแม้ว่ามันจะหมายความว่าเก้าอี้บางตัวว่างเปล่า

  2. จะต้องมีเก้าอี้ว่างน้อยที่สุดเท่าที่จะทำได้

  3. พวกเขาจะต้องเป็น "squarey" ที่สุด Squarey-ness พิจารณาจากระยะห่างระหว่างความกว้างและความสูงของสี่เหลี่ยมผืนผ้าต่ำกว่าดีกว่า ตัวอย่างเช่นสี่เหลี่ยมผืนผ้าที่มีสี่เหลี่ยมจัตุรัสเป็น4x73

จะมีความเฉพาะเจาะจงมากขึ้น "คะแนน" ของข้อตกลงคือระยะห่างระหว่างความกว้างและความสูงบวกกับจำนวนเก้าอี้ที่ว่างเปล่า

ลองยกตัวอย่าง สมมติว่าคุณมีนักเรียน 13 คน คุณสามารถจัดเก้าอี้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้:

1x13
2x7
3x5
4x4

1x13ไม่กว้างมาก อันที่จริง 1 และ 13 อยู่ห่างกัน 12 เราจึงให้ข้อตกลงนี้ 12 คะแนน นอกจากนี้ยังมีเก้าอี้ว่าง 0 ตัวดังนั้นเราจึงเพิ่ม 0 คะแนนทำให้ข้อตกลงนี้มีคะแนน 12 ไม่ดีเท่าไหร่

2x7ดีกว่าอย่างแน่นอน 2 และ 7 อยู่ห่างกันเพียง 5 เราจึงให้ข้อตกลงนี้ 5 คะแนน อย่างไรก็ตามถ้าคุณจัดเก้าอี้สองแถวเจ็ดแถวจริง ๆ จะใช้เก้าอี้ 14 อันหมายความว่าเก้าอี้หนึ่งอันจะว่างเปล่า ดังนั้นเราจึงเพิ่มหนึ่งจุดโดยให้ข้อตกลงนี้มีคะแนน 6

เราทำได้เช่น3x5กัน 3 และ 5 อยู่ห่างกัน 2 จุดดังนั้นจึงมีคะแนน 2 ใช้เวลา 15 เก้าอี้หมายความว่าเรามีเก้าอี้สองตัวเพิ่มอีก +2 คะแนนสำหรับคะแนน 4

ตัวเลือกสุดท้าย, 4x4. 4 และ 4 อยู่ห่างกัน 0 เราจึงให้ +0 คะแนนนี้ 4x4 ใช้เก้าอี้ 16 ตัวดังนั้นเก้าอี้ 3 ตัวจึงว่างเปล่ารวมเป็น 3 คะแนนนี่เป็นทางออกที่ดีที่สุด

ในกรณีที่เน็คไททางออกที่ดีที่สุดคือตัวที่มีเก้าอี้ว่างน้อย

ความท้าทาย

คุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่ใช้จำนวนเต็มและจัดเรียงเก้าอี้ที่เหมาะสมสำหรับนักเรียนจำนวนนั้น IO สามารถอยู่ในรูปแบบที่สมเหตุสมผล นี่คือตัวอย่างผลลัพธ์สำหรับนักเรียนจำนวนใดก็ได้ตั้งแต่ 1 ถึง 100:

1:  (1, 1)
2:  (1, 2)
3:  (2, 2)
4:  (2, 2)
5:  (2, 3)
6:  (2, 3)
7:  (3, 3)
8:  (3, 3)
9:  (3, 3)
10: (2, 5)
11: (3, 4)
12: (3, 4)
13: (4, 4)
14: (4, 4)
15: (4, 4)
16: (4, 4)
17: (3, 6)
18: (3, 6)
19: (4, 5)
20: (4, 5)
21: (3, 7)
22: (5, 5)
23: (5, 5)
24: (5, 5)
25: (5, 5)
26: (4, 7)
27: (4, 7)
28: (4, 7)
29: (5, 6)
30: (5, 6)
31: (4, 8)
32: (4, 8)
33: (6, 6)
34: (6, 6)
35: (6, 6)
36: (6, 6)
37: (5, 8)
38: (5, 8)
39: (5, 8)
40: (5, 8)
41: (6, 7)
42: (6, 7)
43: (5, 9)
44: (5, 9)
45: (5, 9)
46: (7, 7)
47: (7, 7)
48: (7, 7)
49: (7, 7)
50: (5, 10)
51: (6, 9)
52: (6, 9)
53: (6, 9)
54: (6, 9)
55: (7, 8)
56: (7, 8)
57: (6, 10)
58: (6, 10)
59: (6, 10)
60: (6, 10)
61: (8, 8)
62: (8, 8)
63: (8, 8)
64: (8, 8)
65: (6, 11)
66: (6, 11)
67: (7, 10)
68: (7, 10)
69: (7, 10)
70: (7, 10)
71: (8, 9)
72: (8, 9)
73: (7, 11)
74: (7, 11)
75: (7, 11)
76: (7, 11)
77: (7, 11)
78: (9, 9)
79: (9, 9)
80: (9, 9)
81: (9, 9)
82: (7, 12)
83: (7, 12)
84: (7, 12)
85: (8, 11)
86: (8, 11)
87: (8, 11)
88: (8, 11)
89: (9, 10)
90: (9, 10)
91: (7, 13)
92: (8, 12)
93: (8, 12)
94: (8, 12)
95: (8, 12)
96: (8, 12)
97: (10, 10)
98: (10, 10)
99: (10, 10)
100: (10, 10)

ตามปกตินี่คือ code-golf ดังนั้นจึงใช้ช่องโหว่มาตรฐานและผู้ชนะคือคำตอบที่สั้นที่สุดในหน่วยไบต์


คำตอบ:


8

เยลลี่ , 16 15 14 ไบต์

÷RĊ,Rµạ/+PỤḢịZ

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

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

÷RĊ,Rµạ/+PỤḢịZ  Main link. Argument: n

 R              Range; yield [1, ..., n].
÷               Divide n by each k in [1, ..., n].
  Ċ             Ceil; round the quotients up to the nearest integer.
    R           Range; yield [1, ..., n].
   ,            Pair; yield A := [[ ⌈n ÷ 1⌉, ..., ⌈n ÷ n⌉ ], [ 1, ..., n ]].
     µ          Begin a new, monadic chain. Argument: A
      ạ/        Reduce A by absolute difference.
                This yields [ |⌈n ÷ 1⌉ - 1|, ..., |⌈n ÷ n⌉ - n| ].
         P      Product; reduce A by multiplication.
                This yields [ ⌈n ÷ 1⌉ × 1, ..., ⌈n ÷ n⌉ × n].
       +        Add the results to left and right, element by element. This yields
                [ |⌈n ÷ 1⌉ - 1| + ⌈n ÷ 1⌉ × 1, ..., |⌈n ÷ n⌉ - n| + ⌈n ÷ n⌉ × n ].
          Ụ     Grade up; sort the indices of the list of sums by their values.
           Ḣ    Head; extract the first value, which corresponds to the smallest
                sum. Grading up is stable, so this selects the first index of all
                with the smallest sum in case of a tie. In this event, the first
                index will have the highest absolute difference of all indices
                with the smallest sum, meaning that it has the lowest product and,
                therefore, the lowest number of empty chairs.
             Z  Zip; transpose A's rows and columns.
                This yields [[ ⌈n ÷ 1⌉, 1 ], ..., [ ⌈n ÷ n⌉, n ]].
            ị   Retrieve the pair at that index.

4

Python 2, 68 ไบต์

lambda n:min((abs(~i-n/~i)+n/~i*~i,i+1,0-n/~i)for i in range(n))[1:]

เทียบเท่ากับ "ชัดเจน" มากขึ้น:

lambda n:min([(i+1,0-n/~i)for i in range(n)],key=lambda(p,q):abs(p-q)+p*q)

คุณสามารถบันทึกสามไบต์โดยวนซ้ำ range(-n,0)เหมือนที่ฉันทำในคำตอบของฉัน ชุดทดสอบ
Dennis

3

Haskell, 65 ไบต์

f x=snd$minimum[((a*b+a-b,a*b),(b,a))|a<-[1..x],b<-[1..a],a*b>=x]

ตัวอย่างการใช้งาน: ->map f [1..5][(1,1),(1,2),(2,2),(2,2),(2,3)]

ไปถึงลูปภายนอกaจาก1ถึงx(x -> จำนวนนักเรียน) และลูปภายในbจาก1aไป เก็บ(b,a)ตำแหน่งทั้งหมดa*b>=xและสร้างคู่((arrangement points,seats left), (b,a))ซึ่งปฏิบัติตามคำสั่งทางพจนานุกรมที่เราต้องค้นหาขั้นต่ำ หมายเหตุ: aยิ่งใหญ่กว่าเสมอbดังนั้นเราไม่จำเป็นต้องabsใช้ความสแควร์เนส ไม่จำเป็นต้องลบออกxจากคะแนน "ที่นั่งด้านซ้าย" เพราะมีเพียงคำสั่งที่เกี่ยวข้องเท่านั้น sndในที่สุดเราเอาคู่คะแนนด้วย


ทำไมไม่ใช่แค่ ( a + b, a (b, a))? หากคุณลดคะแนนให้แน่นอนคุณต้องลด b ต่อไปหรือฉันขาดอะไรไป?
justinpc

@jpcooper: a*b(จำนวนที่นั่งฟรี) เป็นตัวแบ่งไทเกอร์หากคะแนนหลักเท่ากัน เช่นn=43: ก) a=7, b=7คะแนน: (49,49)ข) a=9, b=5คะแนน: (49,45). คะแนนหลักมีค่าเท่ากันไทเบรกเกอร์ตัดสินใจ b) ชนะ
nimi

คุณถูก. ฉันควรอ่านคำอธิบายให้ดีขึ้น
justinpc

@jpcooper: รอสักครู่ ... ถ้าฉันจะลบเบรกผูกa*bหมายเลขของตัวเอง(b,a)ซึ่งผมต้องดำเนินการรอบอยู่แล้วทำหน้าที่เป็นเบรกเกอร์ผูกและให้ผลลัพธ์ที่เหมือนกันสำหรับ n=1..300(อย่างน้อย) ผลิตภัณฑ์มีขนาดเล็กหากปัจจัยหนึ่ง (ที่นี่b) มีขนาดเล็ก แต่ตราบใดที่ฉันไม่มีหลักฐานทางการฉันไม่ต้องการใช้ความจริงข้อนี้ ลองดูว่าฉันเจอแล้วหรือยัง
nimi

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

2

Ruby, 64 ไบต์

->n{(1..n).map{|w|h=(n+w-1)/w;[(h-w).abs+h*w,w*h,w,h]}.min[2,3]}

แลมบ์ดาที่รับจำนวนคนเป็นอาร์กิวเมนต์และส่งกลับอาร์เรย์ที่มีความกว้างและความสูงของโซลูชันที่เหมาะสม


ทำไมคุณต้องw*hเป็นองค์ประกอบที่สองในอาร์เรย์ของคุณ? ฉันไม่คิดว่ามันจะเปลี่ยนแปลงสิ่งใดเป็นพิเศษเมื่อคุณโทรหาminเพราะคุณย่อหย่อนคะแนนหรือองค์ประกอบแรก
มูลค่าหมึก

@ KevinLau-notKenny จากคำถาม:In case of a tie, the optimal solution is the one with less empty chairs
MegaTom

2

MATL , 18 ไบต์

:Gy/Xkvtd|yp+&X<Z)

ลองออนไลน์!

คำอธิบาย

:      % Implicit input number N. Range [1 2 ... N]
G      % Push N again
y      % Duplicate second-from-top: push [1 2 ... N] again
/Xk    % Divide and round up
v      % Vertically concatenate. Gives 2×N array of rectangle sizes
td|    % Duplicate. Absolute difference of each column
y      % Duplicate second-from-top: push 2×N array again
p      % Product of each column
+      % Sum absolute differences and products
&X<    % Arg min
Z)     % Use as column index into the 2×N array. Implicitly display

2

Javascript, 98 ไบต์

รหัสกอล์ฟครั้งแรกของฉันดังนั้นฉันโพสต์ต่อไป!

f=n=>{for(o=1/0,i=1;i<=n;i++)for(j=n;i*j>=n;j--)t=i*j-n+Math.abs(i-j),o>t&&(o=t,a=[i,j]);return a}

ตอนแรกฉันoเป็นวัตถุที่ว่างเปล่าและฉันตรวจสอบว่าo.aว่างเปล่าดังนั้นมันจึงเป็นกรณีพิเศษในรอบแรก แต่ฉันพบเคล็ดลับ 1/0 ในคำตอบของ edc65 เพื่อเริ่มต้นตัวแปรให้ Infinity


และฉันจะลองใช้เคล็ดลับในการใช้วัตถุเพื่อเก็บผลชั่วคราว
edc65

1

Pyth, 24 22 21 ไบต์

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

h.m_+B*FbaFbm,d.EcQdS

ลองออนไลน์!


1

Matlab(174) (146)121

  function g(n),f=@(n,i)ceil(n/i);x=[];for i=1:n,x=[sortrows(x); f(n,i)*i-1/(f(n,i)*i)+abs(f(n,i)-i) i f(n,i)];end,x(1,2:3)
  • เคล็ดลับที่ 1:ฉันเพิ่มจำนวน1-1/length*widthเป็นคะแนนเท่ากัน

  • เคล็ดลับที่ 2:ฉันคำนวณnumber_students/lengthความกว้างของสี่เหลี่ยมจัตุรัสคำนวณขอบเขตบนเป็นสี่เหลี่ยมจัตุรัส

  • ฉันแน่ใจว่ามันสามารถตีกอล์ฟต่อไป ...

ลองมัน


แก้ไข:อ้างอิงถึงคำพูดของ @StewieGriffin

แก้ไข 2:

  • 1และnค่าคงที่ไม่จำเป็นต้องเพิ่ม 'em ลงในคะแนนโดยรวม
  • ฟังก์ชั่นนั้นมีขนาดเล็กกว่าโปรแกรม stdin เพียงไม่กี่ไบต์
  • ฉันใช้เทคนิคการเรียงลำดับ ascendent ซึ่งจะช่วยประหยัดจำนวนไบต์ที่มากเกินไป

แก้ไข 3:การทดสอบรอบการแสดง


@StewieGriffin ที่ไม่ได้เป็นปัญหาใหญ่ก็สามารถแก้ไขได้โดยใช้unique
Abr001am

1
ฉันคิดว่าฉันอยู่ระหว่างการแปลทางคณิตศาสตร์ที่ดีสำหรับปัญหานี้ แต่ก็ยังถือว่าเป็นการคาดเดา
Abr001am

คิดยังเกี่ยวกับเรื่องนี้ ดูตัวอย่างจูเลีย
mschauer

1

Python 2, 64 ไบต์

lambda n:max((~-i*~min(i,n/i),0-n/i,-i)for i in range(-n,0))[1:]

นี่เป็นการรวมกันของคำตอบ Pythonของ@ Lynn (จากที่ฉันใช้max(...)[1:]เคล็ดลับ) และอัลกอริทึมจากคำตอบ Julia ของฉัน (ซึ่งช่วยให้การใช้งานสั้นลงเล็กน้อย)

ทดสอบบนIdeone


1

Julia, 61 59 55 53 52 ไบต์

/ =cld
n->[m=indmax([~i*~-max(i,n/i)for i=1:n]),n/m]

ลองออนไลน์!

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

รหัสนี้เทียบเท่ากับรุ่นที่ไม่ได้รับเกียรติดังต่อไปนี้ซึ่งcldเป็นส่วนที่อยู่บนเพดาน

function chairs(n)
    m = indmin([(i + 1) * (max(i, cld(n, i)) - 1) for i in 1:n])
    return [m, cld(n, m)]
end

เพื่อหาการจัดเรียงที่ดีที่สุดมันก็เพียงพอแล้วที่จะตรวจสอบคู่[i, j]โดยที่1 ≤ i ≤ nและ J = ⌈n / i⌉

คะแนนสำหรับการจัดการดังกล่าวคือ| j - i | + (ij - n)โดยที่ summand ที่สองคือจำนวนเก้าอี้ว่าง แทนที่จะเป็นคะแนนจริงเราสามารถเปรียบเทียบคะแนนที่เพิ่มขึ้นด้วยค่าคงที่เช่น ij + | j - i | + 1

มันเพียงพอที่จะพิจารณาคู่[i, j]โดยที่i ≤ jเนื่องจากข้อตกลง[i, j]และ[j, i]นั้นใช้ได้อย่างเท่าเทียมกัน เราจัดการกับคู่จากมากไปน้อยโดยการตั้งค่าj = สูงสุด (⌈n / i⌉, i)แทนซึ่งทำให้แน่ใจว่าj ≥ iและจะให้คะแนนที่ไม่ดีหาก ⌈n / i⌉ <i

ตั้งแต่j - i ≥ 0เรามี ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1)ซึ่งสามารถคำนวณได้ในรหัสไบต์ที่น้อยลง

ในที่สุดindmin/ indmaxให้ดัชนีเมตร (และค่าของฉัน ) ของการจัดที่ดีที่สุดซึ่งเป็นเมตรโดย⌈n / m⌉ ความสัมพันธ์จะถูกทำลายโดยการเกิดขึ้นครั้งแรกซึ่งสอดคล้องกับค่าต่ำสุดของฉันดังนั้นค่าสูงสุดของj - iและทำให้ค่าต่ำสุดของij - n (เก้าอี้ว่างเปล่า)


1

JavaScript (ES6) 74 78

แก้ไขการเก็บผลอุณหภูมิไว้เป็นอาร์เรย์แทนที่จะเป็น 2 vars ซึ่งยืมมาจากคำตอบของ Thiht

n=>(z=>{for(x=0;y=-~(~-n/++x),x<=y;)(s=y-x+x*y-n)>=z||(z=s,r=[x,y])})()||r

น้อย golfed

n=>{
  z = 1/0
  for (x=0; y=(n-1)/++x+1|0, x <= y; )
  {
    s = y-x+x*y-n;
    if (s<z)
      z=s, r=[x,y]
  }
  return r
}

ทดสอบ

f=n=>(z=>{for(x=0;y=-~(~-n/++x),x<=y;)(s=y-x+x*y-n)>=z||(z=s,r=[x,y])})()||r

out=x=>O.textContent+=x+'\n'

for(i=1;i<=100;i++)out(i+' :( '+f(i)+' )')
<pre id=O></pre>


1

PHP, 129 ไบต์

function f($i){$s=INF;for($x=1;$x<$i;$x++){if($s>$t=(abs($x-$e=ceil($i/$x))-$i+($e*$x))){$s=$t;$d[0]=$x;$d[1]=$e;}}var_dump($d);}

Ungolfed:

function f ($i){
    $s=INF;
    for($x=1; $x<$i; $x++){ // for every number less than the input
        if( $s > $t=( abs($x-$e=ceil($i/$x))-$i+($e*$x) ) ){ 
            // determine the other dimension, the score, and compare to the minimum score
            $s=$t;
            $d[0]=$x;
            $d[1]=$e;
        }
    }
    var_dump($d);
}

1

PHP, 104 ไบต์

อัลกอริทึมที่แก้ปัญหานี้นั้นง่ายและอาจถูกใช้โดยคำตอบอื่น ๆ ในภาษาที่คล้ายกับ PHP (JavaScript, fe):

  • เริ่มต้นด้วยค่ามากสำหรับคะแนนเริ่มต้น; nมีขนาดใหญ่พอ (โดยที่nค่าอินพุต); คะแนนของข้อตกลงที่คำนวณในการคำนวณซ้ำครั้งแรก ( 1, n) คือ(n-1)+0 ;
  • วนซ้ำสำหรับค่าความกว้างทั้งหมดระหว่าง1และn; คำนวณความสูงขั้นต่ำเช่นceil(n/width)คำนวณคะแนนการจัดเรียงโดยใช้สูตรที่ให้ไว้ในคำถาม (เช่นabs(width - height) + (width * height - n) ) หากคะแนนดีกว่าคะแนนที่ดีที่สุดก่อนหน้าให้จำความกว้างความสูงและคะแนนที่ดีที่สุดใหม่ ในความสัมพันธ์ใช้ค่าของwidth * height - nการจัดการในปัจจุบันและการจัดเรียงที่ดีที่สุดก่อนหน้านี้ในการตรวจสอบการจัดเรียงใหม่ที่ดีที่สุด;
  • นั่นคือทั้งหมดที่

หลังจากเล่นกอล์ฟอัลกอริทึมนี้จะสร้างบางสิ่งเช่นนี้ (ห่อไว้เพื่อความสะดวกในการอ่าน):

for($s=$h=$j=$n=$argv[$w=$i=1];$i<=$j;$j=ceil($n/++$i)
{$c=$j-$i+$i*$j-$n;if($c<$s||$c==$s&&$i*$j<$w*$h){$w=$i;$h=$j;$s=$c;}}
echo"$w,$h";

มันใช้137 ไบต์ (เมื่อวางบนบรรทัดเดียว) และอยู่ไกลจาก 104 ไบต์โฆษณาในชื่อ รหัสอาจสั้นลงอีก 2-3 ไบต์ แต่แหล่งใหญ่ของการปรับปรุงอยู่ที่อื่น: ในรายละเอียดของอัลกอริทึม

อัลกอริทึมที่แก้ไข:

มีหลายที่ที่อัลกอริทึมสามารถปรับปรุงได้โดยการลบรหัสที่ไร้ประโยชน์

  • ไม่จำเป็นต้องวนซ้ำความกว้างจาก1เป็น$n; สำหรับความเร็วความกว้าง ( $i) จะต้องวนซ้ำระหว่าง1และfloor(sqrt($n))สิ่งนี้ทำให้รหัสยาวขึ้นแทนที่จะย่อให้สั้นลง แต่หากความกว้างไม่เกินsqrt($n)ความสูงขั้นต่ำ ( $j) จะสูงกว่าเสมอsqrt($n)(ผลิตภัณฑ์ต้องมีอย่างน้อย$n);
  • ข้อความก่อนหน้านี้อนุญาตให้ใช้$i <= $j(width <= height) เป็นเงื่อนไขการเลิกจ้างสำหรับลูป ด้วยวิธีนี้ความกว้างจะวนจาก1ไปถึงfloor(sqrt($n))และความสูงจะได้รับค่าเริ่มต้น$nและลงไปที่ceil(sqrt($n))(ไม่จำเป็นต้องทั้งหมด)
  • การรู้ว่าความกว้างนั้นเล็กกว่าหรือเท่ากับความสูงเสมอทำให้เรารู้ว่าabs(width - height)เป็นเสมอheight - width( $j-$i); 5 ไบต์บันทึกด้วยวิธีนี้
  • ค่าอินพุต$nถูกใช้ในการคำนวณคะแนน (จำนวนที่นั่งว่างคือwidth * height - n) แต่ไม่จำเป็นต้องใช้ คะแนนไม่จำเป็นต้องมีการแสดงมันจะคำนวณเฉพาะสำหรับการเปรียบเทียบของการเตรียมการ; โดยลบออก- nจากสูตรการให้คะแนนเราบันทึกอีก 3 ไบต์ (รหัส PHP -$n) โดยไม่เสียอะไรเลย
  • รับสองงบสุดท้ายสูตรคะแนนกลายเป็นheight - width + width * height( $j-$i+$i*$j);
  • ในความสัมพันธ์ (คะแนนของข้อตกลงในปัจจุบันเป็นเช่นเดียวกับคะแนนที่ดีที่สุดก่อนหน้านี้) กฎบอกว่าจะใช้การจัดเรียงที่มีที่นั่งว่างน้อยกว่า; เนื่องจากความกว้างเพิ่มขึ้นเสมอและความสูงจะลดลงเสมอheight - widthส่วนของคะแนนจะลดลงในแต่ละขั้นตอน
  • หากคะแนนปัจจุบันเท่ากับคะแนนที่ดีที่สุดก่อนหน้านี้ข้อความก่อนหน้านี้บอกเราว่าจำนวนที่นั่งว่างของข้อตกลงในปัจจุบันมีขนาดใหญ่กว่าหนึ่งในข้อตกลงที่ดีที่สุดก่อนหน้านี้; นี่หมายถึงการจัดการที่ดีที่สุดก่อนหน้านี้ชนะการเสมอกัน
  • เพราะความสัมพันธ์จะชนะเสมอโดยการจัดการที่ดีที่สุดก่อนหน้านี้การจัดใหม่กลายเป็นการจัดการที่ดีที่สุดใหม่เฉพาะเมื่อคะแนนของมันมีขนาดเล็กกว่าที่ดีที่สุดก่อนหน้า; รหัสที่ตรวจสอบความสัมพันธ์นั้นไร้ประโยชน์และสามารถลบออกได้ ( ||$c==$s&&$i*$j<$w*$h- จำนวนมากไบต์);
  • เนื่องจากการลบออก-$nจากสูตรของคะแนนคะแนนสำหรับการจัดเรียงครั้งแรก ( 1x$n) คือ$n-1+1*$n(เช่น2*$n-1); ค่าเริ่มต้นของคะแนนที่ดีที่สุด ( $s) สามารถเป็นค่าใด ๆ ที่มากกว่าหรือเท่ากับ2*$n; การวนซ้ำครั้งแรกมีคะแนนที่ดีกว่าและจะกลายเป็นการจัดเรียงที่ดีที่สุดเพื่อให้อัลกอริทึมทำงานโดยไม่มีปัญหาการเริ่มต้น

รหัสใหม่ ( 104 ไบต์ ) หลังจากใช้การปรับปรุงที่อธิบายไว้ข้างต้นคือ:

for($s=2*$j=$n=$argv[$i=1];$i<=$j;$j=ceil($n/++$i))
if($s>$c=$j-$i+$i*$j){$w=$i;$h=$j;$s=$c;}echo"$w,$h";

มันถูกห่อไว้ที่นี่เพื่อให้สามารถอ่านได้ ใส่รหัสข้างต้นด้วยเครื่องหมาย PHP <?php(โดยทางเทคนิคแล้วไม่ใช่ส่วนหนึ่งของรหัส) ใส่ลงในไฟล์ (สมมติว่าarrange-your-chairs.php) แล้วเรียกใช้ด้วยจำนวนเต็มมากกว่าศูนย์เป็นอาร์กิวเมนต์ มันจะแสดงความกว้างและความสูงของการจัดเรียงที่คำนวณโดยคั่นด้วยเครื่องหมายจุลภาค:

$ php arrange-your-chairs.php 1001
28,36

วิธีแก้ปัญหาอื่น (116 ไบต์)

โซลูชันอื่นที่ใช้อัลกอริทึมที่แตกต่างกัน:

for($n=$argv[1];++$j<=$n;)for($i=0;++$i<=$j;)
if($n<=$k=$i*$j)$a["$i,$j"]=($j-$i+$k-$n)*$n+$k;asort($a);echo key($a);

มันทำให้การรวมกันทั้งหมดอย่างน้อย $nที่นั่งลงในรายการเชื่อมโยง; กุญแจสำคัญคือการแสดงข้อความของข้อตกลงค่าเป็นคะแนนของการจัด จากนั้นเรียงลำดับรายการ (น้อยไปหามากตามมูลค่า) และรับคีย์ของรายการแรก

อีกหนึ่ง (115 ไบต์)

foreach(range(1,$m=$n=$argv[1])as$i)
if(($d=ceil($n/$i))<=$i&&$m>=$s=$i*$d-$n+$i-$d){$m=$s;$w=$d;$h=$i;}echo"$w,$h";

นี่เป็นคำตอบของ @ Neil เวอร์ชัน PHP (JavaScript / ES6, 85 ไบต์)

มีความแตกต่างที่เห็นได้ชัดเจนเนื่องจากคุณสมบัติของแต่ละภาษา:

  • คำตอบ JS สร้างอาร์เรย์ของค่าn(ไม่ได้กำหนด) จากนั้นใช้คีย์เพื่อวนซ้ำจาก0ถึงn-1; มันเพิ่มขึ้นi( d=(n+i++)/i|0) เพื่อให้ซ้ำจาก1ถึงn; โซลูชัน PHP ไม่จำเป็นต้องเพิ่มขึ้น มันใช้range()ในการสร้างอาร์เรย์จากนั้นจะใช้ค่าที่สร้างขึ้น ( 1เพื่อn) เพื่อย้ำ;
  • คำตอบ JS ใช้(n+i)/iแล้วแปลงค่าเป็นจำนวนเต็มโดยใช้|0เพื่อรับจำนวนเต็มที่น้อยที่สุดที่ใหญ่กว่าn/i; คำตอบ PHP แก้ปัญหานี้ได้อย่างง่ายดายด้วยฟังก์ชั่น PHP ceil(); JavaScript ยังมีMath.ceil()แต่จะใช้ 5 ไบต์มากกว่าโซลูชันที่พบโดย Neil;
  • PHP มีฟังก์ชั่นarray_map()ที่คล้ายกับ JS Array.map()แต่มันไม่ช่วยอะไร ไวยากรณ์ของมันคือ verbose, aforeachสร้างรหัสที่สั้นกว่า; มันมีขนาดใหญ่กว่ารหัส JS แต่;
  • การรวมการมอบหมายเข้ากับเงื่อนไขที่ใช้||เป็นไปไม่ได้ใน PHP เพราะมันขาดเครื่องหมายจุลภาค; ฉันแปลa||b||cเป็นif(!a&&!b)cแล้วเพราะaและbมีการเปรียบเทียบฉันเมื่อตะกี้ผู้ประกอบการของพวกเขา (แทนที่<ด้วย>=); สิ่งนี้ยังสร้างโค้ดที่ใหญ่กว่าเวอร์ชัน JS
  • อีก 23 ไบต์จะต้องมีการเพิ่มเพียงเพราะชื่อของตัวแปรใน PHP $จะต้องนำหน้าด้วย

รุ่น ungolfed ของการแก้ปัญหาทั้งหมดและชุดทดสอบที่สามารถพบได้บน Github


1
นี่คือคำตอบที่ละเอียดที่สุดของกอล์ฟที่ฉันเคยเห็นมา
DJMcMayhem

0

JavaSCript (ES6), 83 ไบต์

n=>[...Array(m=n)].map((_,i)=>(d=(n+i++)/i|0)>i||(s=i*d-n+i-d)>m||(m=s,r=[d,i]))&&r

บางทีคุณอาจจะใช้เคล็ดลับของฉัน (เพื่อประหยัด 2 bytes)
รั่วนูน

@ KennyLau ฉันไม่คิดว่าจะช่วยได้ ฉันต้องเพิ่มขึ้นmเพื่อชดเชย
Neil

0

จูเลียอายุ 87 ปี

ฉันคิดว่านี่เป็นขั้นตอนเดียวในการหาฟังก์ชั่นเวทย์มนตร์สำหรับปัญหา:

f(i)=(i+n)÷(i+1)|>j->(j*i<n)+j
_=indmin([sqrt(n)<=i?i-f(i)*(1-i):2n for i=1:n])
_,f(_)

มันดูที่คู่(i, j=(i+n)/(i+1))หรือเท่านั้น(i, j+1)


โปรดอธิบายเพิ่มเติมว่ามันทำงานอย่างไรคุณ v ทำให้ฉันอยากรู้อยากเห็นเกี่ยวกับการทำงานของคุณ
Abr001am

2
ฉันไม่แน่ใจว่ามันควรจะทำงานอย่างไร คุณไม่ได้กำหนดnที่ใดก็ได้และดูเหมือนว่าคุณจะไม่ป้อนข้อมูล
เดนนิส

อ่าขอโทษด้วยฉันแค่รับnข้อมูลเข้ามา n->...หนึ่งจะต้องตัดมันลงไป ยินดีที่คุณทำงานได้
mschauer

0

Oracle SQL 11.2, 173 ไบต์

SELECT MIN(x||','||y)KEEP(DENSE_RANK FIRST ORDER BY y-x+(y*x-:1))FROM(SELECT CEIL(LEVEL/:1)x,CEIL(MOD(LEVEL+.1,:1))y FROM DUAL CONNECT BY LEVEL<=:1*:1)WHERE x<=y AND:1<=x*y;

ยกเลิกแข็งแรงเล่นกอล์ฟ

SELECT MIN(x||','||y)KEEP(DENSE_RANK FIRST ORDER BY y-x+(y*x-:1))  -- Keeps the minimal score
FROM   (SELECT CEIL(LEVEL/:1)x,CEIL(MOD(LEVEL+.1,:1))y FROM DUAL CONNECT BY LEVEL<=:1*:1) -- Generate x,y combinations 
WHERE  x<=y AND :1<=x*y  -- Filters out wrong combinations

0

Q 58 ไบต์

{c@d?&/d:+/(-/;*/)@\:+c:{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}x}

Lamba ที่คำนวณต้นทุนขั้นต่ำสำหรับค่าที่กำหนด (x) และส่งคืนลำดับของสองค่า (ความกว้างความสูง)

การเพิ่มชื่อให้กับแลมบ์ดานั้นต้องการถ่านอีกสองตัว (เช่น f: {.. } แทนที่จะเป็น {.. })

ทดสอบ

{..}'1+!100

โดยที่ {.. } เป็นแลมบ์ดา อ่านเป็น "ใช้แลมบ์ดากับแต่ละค่า 1 + 100 int แรก" (กล่าวอีกนัยหนึ่งกับแต่ละค่า 1..100)

สร้าง

1 1
2 1
2 2
2 2
3 2
3 2
3 3
3 3
3 3
5 2
4 3
4 3
4 4
4 4
4 4
4 4
6 3
6 3
5 4
5 4
7 3
5 5
..

คำอธิบาย

lamdba ที่ซ้อนกัน{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}สร้างคู่ผู้สมัครทั้งหมด (widht, height) สำหรับเก้าอี้ x เป็นสองลำดับ (w1 w2 w3 .. ; h1 h2 h3 .. ) (ความกว้างและความสูง) อ่านจากซ้ายไปขวา แต่ประเมินจากขวาไปซ้าย

a:1+!x สร้างค่า 1..x และกำหนดลำดับนั้นให้กับ

-_- เป็นลบล้างพื้นลบล้างและใช้ ceil (ceil ไม่ใช่ภาษาดั้งเดิม)

b:-_-x%aใช้ ceil กับแต่ละค่าของ x หารด้วยรายการใด ๆ a และกำหนดลำดับผลลัพธ์ให้กับ b กล่าวอีกนัยหนึ่ง b คือ ceil แต่ละ x หารด้วยแต่ละ 1..x

+(b;a) ส่งคืน secuence ที่ประกอบด้วย seq a และ seq b แล้วจึงพลิกมัน (ผลลัพธ์คือลำดับของคู่ที่ i-pair มีองค์ประกอบ i ของ a และองค์ประกอบ i ของ b)

b<a เปรียบเทียบรายการตามรายการของ b และ a และสร้าง secuence ของค่าตรรกะ (จริง = 1b สำหรับแต่ละดัชนีที่ b [i]

s?xส่งคืนตำแหน่งแรกของรายการ x ในลำดับ s ด้วย(b<a)?1bเราค้นหา 1b (ค่าจริง) ตามลำดับผลลัพธ์ของการเปรียบเทียบ b และ a และรับตำแหน่งแรกโดยที่ b

n#sใช้ n รายการแรกจาก seq s เราต้องการยกเลิกคู่ที่ซ้ำกันดังนั้นเราจึงหยุดเมื่อรายการแรกของคู่ <รายการที่สอง (เช่นพิจารณา 13,1 แต่ไม่ใช่ 1,13)

ผลข้างเคียงแต่ละคู่ของลำดับผลลัพธ์จะลดระยะห่างระหว่าง a และ b (เช่น (13 1; 7 2; 5 3; 4 4)

คู่ผู้สมัครที่สร้างโดยแลมบ์ดาที่ซ้อนกันถูกกำหนดให้กับค จากนั้นเราจะพลิก c (หา b อีกครั้ง) และใช้สองฟังก์ชันกับอาร์กิวเมนต์นั้น: */คูณและ-/ลบ ผลที่ได้(-/;*/)@\:+cคือความแตกต่างและผลิตภัณฑ์ของแต่ละคู่ +/คือผลรวมมากกว่าและคำนวณต้นทุนขั้นสุดท้าย ค่าใช้จ่ายของแต่ละ patir ถูกกำหนดให้ d

& / ต่ำกว่าขั้นต่ำดังนั้น&/d คือค่าใช้จ่ายขั้นต่ำ เมื่อd?&/dเราพบการเกิดขึ้นครั้งแรกของค่าใช้จ่ายขั้นต่ำใน d และด้วย c @ .. เราดึงคู่ที่ตำแหน่งนั้น เนื่องจากแต่ละคู่มีการลดระยะห่างระหว่าง a และ n ต่ำสุดที่พบครั้งแรกมีระยะห่างสูงสุดระหว่างคู่ขั้นต่ำอื่น ๆ ดังนั้นเราจึงใช้กฎการผูกอย่างถูกต้อง

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