Bạn nên sắp xếp ghế như thế nào?


20

Bạn dạy một lớp học sinh với những sở thích thú vị về cách sắp xếp ghế của họ. Có 3 yêu cầu rất cụ thể mà họ có về cách sắp xếp ghế:

  1. Hầu hết chúng được sắp xếp trong một hình chữ nhật, ngay cả khi điều đó có nghĩa là một số ghế trống.

  2. Phải có càng ít ghế trống càng tốt.

  3. Chúng phải càng "vuông" càng tốt. Squarey-ness được xác định bởi khoảng cách giữa chiều rộng và chiều cao của hình chữ nhật, thấp hơn là tốt hơn. Ví dụ, một hình chữ nhật 4x7có số vuông là 3.

Cụ thể hơn, "điểm số" của sự sắp xếp là khoảng cách giữa chiều rộng và chiều cao cộng với số ghế sẽ trống.

Hãy lấy một ví dụ. Giả sử bạn có 13 sinh viên. Bạn có thể sắp xếp những chiếc ghế theo bất kỳ cách nào sau đây:

1x13
2x7
3x5
4x4

1x13không phải là rất vuông. Trong thực tế, 1 và 13 cách nhau 12, vì vậy chúng tôi cho cách sắp xếp này 12 điểm. Nó cũng có 0 ghế trống, vì vậy chúng tôi thêm 0 điểm, cho sự sắp xếp này điểm 12. Không phải là tuyệt vời.

2x7chắc chắn là tốt hơn 2 và 7 chỉ cách nhau 5 điểm, vì vậy chúng tôi cho sự sắp xếp này 5 điểm. Tuy nhiên, nếu bạn thực sự sắp xếp 2 hàng bảy ghế, thì sẽ mất 14 ghế, nghĩa là một ghế sẽ trống. Vì vậy, chúng tôi thêm một điểm, cho điểm sắp xếp này là 6 điểm.

Chúng tôi cũng có thể làm 3x5. 3 và 5 cách nhau 2 điểm, vì vậy +2 điểm. Phải mất 15 ghế, có nghĩa là chúng tôi sẽ có thêm hai ghế, vì vậy thêm 2 điểm nữa, cho số điểm là 4.

Tùy chọn cuối cùng , 4x4. 4 và 4 cách nhau 0, vì vậy chúng tôi cho điểm +0 này. 4x4 mất 16 ghế, vì vậy 3 ghế trống, với tổng số điểm là 3. Đây là giải pháp tối ưu.

Trong trường hợp cà vạt, giải pháp tối ưu là cái có ít ghế trống.

Các thách thức

Bạn phải viết một chương trình hoặc hàm lấy số nguyên và đưa ra cách sắp xếp ghế tối ưu cho số học sinh đó. IO có thể ở bất kỳ định dạng hợp lý. Đây là đầu ra mẫu cho bất kỳ số lượng sinh viên từ 1 đến 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)

Như thường lệ, đây là môn đánh gôn, do đó, sơ hở tiêu chuẩn được áp dụng và người chiến thắng là câu trả lời ngắn nhất tính bằng byte.


Câu trả lời:


8

Thạch , 16 15 14 byte

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

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Làm thế nào nó hoạt động

÷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 byte

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

Tương đương với nhiều hơn nữa

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

Bạn có thể lưu ba byte bằng cách lặp lại range(-n,0), giống như tôi làm trong câu trả lời của mình . Bộ thử nghiệm.
Dennis

3

Haskell, 65 byte

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

Ví dụ sử dụng: map f [1..5]-> [(1,1),(1,2),(2,2),(2,2),(2,3)].

Đi qua một vòng lặp bên ngoài a từ 1đến x(x -> số lượng sinh viên) và một vòng lặp bên trong btừ 1đến a. Giữ tất cả các (b,a)vị trí a*b>=xvà xây dựng các cặp ((arrangement points,seats left), (b,a))theo thứ tự từ điển chúng ta cần tìm tối thiểu. Lưu ý: aluôn luôn lớn hơn b, vì vậy chúng ta không cần phải absvuông. Không cần phải trừ xđiểm "chỗ còn lại", bởi vì chỉ có thứ tự tương đối mới quan trọng. Cuối cùng, chúng tôi loại bỏ cặp điểm với snd.


Tại sao không chỉ (a b + ab, (b, a))? Nếu bạn giảm thiểu điểm số, chắc chắn bạn sẽ giảm thiểu b, hoặc tôi đang thiếu thứ gì đó?
justinpc

@jpcooper: a*b(số ghế miễn phí) là bộ ngắt kết nối nếu số điểm chính bằng nhau. Ví dụ n=43: a) a=7, b=7, điểm: (49,49)b) a=9, b=5, điểm : (49,45). Điểm chính là bằng nhau, tie breaker quyết định, b) thắng.
nimi

Bạn đúng. Tôi nên đọc mô tả tốt hơn.
justinpc

@jpcooper: đợi một chút ... nếu tôi gỡ bỏ bộ ngắt kết nối a*b, các số (b,a)mà tôi phải mang theo dù sao cũng đóng vai trò là bộ ngắt kết nối và cho kết quả tương tự (ít nhất) n=1..300. Một sản phẩm nhỏ nếu một trong các yếu tố (ở đây b) nhỏ. Nhưng miễn là tôi không có bằng chứng chính thức, tôi không muốn sử dụng thực tế này. Hãy xem nếu tôi tìm thấy một.
nimi

Điểm tốt. Có vẻ đúng, và không quá khó để đưa ra một bằng chứng. Tôi bắt đầu tự hỏi mặc dù có thể có một giải pháp tuyến tính cho vấn đề này.
justinpc

2

Ruby, 64 byte

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

Một lambada lấy số lượng người làm đối số và trả về một mảng có chiều rộng và chiều cao của giải pháp tối ưu.


Tại sao bạn cần w*hlà yếu tố thứ hai trong mảng của bạn? Tôi không nghĩ nó đặc biệt thay đổi bất cứ điều gì khi bạn gọi minvì bạn giảm thiểu điểm số hay còn gọi là yếu tố đầu tiên.
Mực giá trị

@ KevinLau-notKenny từ câu hỏi:In case of a tie, the optimal solution is the one with less empty chairs
MegaTom

2

MATL , 18 byte

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

Hãy thử trực tuyến!

Giải trình

:      % 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 byte

Golf mã đầu tiên của tôi, vì vậy tôi gửi bài nào!

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}

Ban đầu của tôi olà một đối tượng trống rỗng và tôi đã kiểm tra xem o.acó trống không, vì vậy đó là trường hợp đặc biệt ở vòng đầu tiên. Nhưng tôi đã tìm thấy mẹo 1/0 trong câu trả lời của edc65 để khởi tạo biến thành Infinity.


Và tôi sẽ thử mẹo sử dụng một đối tượng để lưu trữ kết quả tạm thời
edc65

1

Pyth, 24 22 21 byte

Chỉnh sửa : trong khóa sắp xếp, tôi nhận ra rằng không cần phải tìm số lượng ghế trống. Nó tương đương với số điểm tổng số ghế. Điều này tiết kiệm cho tôi 2 byte.

h.m_+B*FbaFbm,d.EcQdS

Hãy thử trực tuyến!


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)
  • mẹo 1: tôi đã thêm số tiền 1-1/length*widthdưới dạng tie-points

  • mẹo 2: tôi tính number_students/lengthtrần cho chiều rộng của hình chữ nhật, giới hạn trên là hình vuông nhưng trần cũng vậy

  • Tôi chắc chắn rằng nó có thể được chơi gôn hơn nữa ...

thử nó


Chỉnh sửa: được tham chiếu đến nhận xét của @StewieGriffin.

Chỉnh sửa 2:

  • 1nlà hằng số không cần thêm chúng vào tổng điểm.
  • Một hàm ít hơn vài byte so với chương trình độc lập stdin.
  • Tôi đã sử dụng kỹ thuật sắp xếp tăng dần, nó tiết kiệm quá nhiều byte.

Chỉnh sửa 3: kiểm tra peformance.


@StewieGriffin không phải là vấn đề lớn, nó có thể được giải quyết bằng cách sử dụngunique
Abr001am

1
Tôi nghĩ rằng tôi đang ở giữa một số bản dịch toán học hay cho vấn đề này, nhưng nó vẫn còn là phỏng đoán
Abr001am

Cũng nghĩ về điều này. Xem ví dụ julia.
mschauer


1

Julia, 61 59 55 53 52 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Mã tương đương với phiên bản sau đây, không cldphân chia , trong đó phân chia trần.

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

Để tìm ra sự sắp xếp tối ưu, rõ ràng là đủ để kiểm tra các cặp [i, j] , trong đó 1 ≤ i ≤ nj = n / i⌉ .

Điểm cho sự sắp xếp như vậy là | j - i | + (ij - n) , trong đó triệu hồi thứ hai là số ghế trống. Thay vì điểm thực tế, chúng ta có thể so sánh điểm số được tăng thêm bởi một hằng số, chẳng hạn như ij + | j - i | + 1 .

Việc xem xét các cặp [i, j] trong đó i ≤ j là đủ vì các sắp xếp [i, j][j, i] có giá trị như nhau. Thay vào đó, chúng tôi xử lý các cặp giảm dần nghiêm ngặt bằng cách đặt j = max (⌈n / i⌉, i) , điều này đảm bảo rằng j ≥ i và sẽ mang lại điểm tối ưu nếu n / i⌉ <i .

j - i ≥ 0 , nên ta có ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1) , có thể được tính bằng ít byte mã hơn.

Cuối cùng indmin/ indmaxđưa ra chỉ số m (và do đó là giá trị của i ) của sự sắp xếp tối ưu, là m by ⌈n / m⌉ . Các mối quan hệ bị phá vỡ bởi lần xuất hiện đầu tiên, tương ứng với giá trị thấp nhất của i , do đó giá trị cao nhất của j - i và do đó giá trị thấp nhất của ij - n (ghế trống).


1

JavaScript (ES6) 74 78

Chỉnh sửa giữ kết quả tạm thời dưới dạng một mảng thay vì 2 vars, mượn từ câu trả lời của Thiht

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

Ít chơi gôn

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
}

Kiểm tra

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 byte

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);}

Ung dung:

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 byte

Thuật toán giải quyết vấn đề này rất đơn giản và có lẽ nó được sử dụng bởi các câu trả lời khác trong các ngôn ngữ tương tự như PHP (JavaScript, fe):

  • bắt đầu với một giá trị lớn cho điểm ban đầu; nlà đủ lớn (nơi nlà giá trị đầu vào); điểm của sự sắp xếp được tính trên lần lặp đầu tiên ( 1, n) là (n-1)+0;
  • Lặp lại cho tất cả các giá trị của chiều rộng giữa 1n ; tính chiều cao tối thiểu như ceil(n/width), tính điểm sắp xếp bằng công thức được cung cấp trong câu hỏi (nghĩa là abs(width - height) + (width * height - n)); nếu điểm tốt hơn điểm tốt nhất trước đó thì hãy nhớ chiều rộng, chiều cao và điểm mới tốt nhất; trên các mối quan hệ sử dụng giá trị của width * height - nsắp xếp hiện tại và sắp xếp tốt nhất trước đó để phát hiện sự sắp xếp tốt nhất mới;
  • đó là tất cả.

Sau khi chơi gôn, thuật toán này tạo ra một cái gì đó như thế này (được gói ở đây để dễ đọc):

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";

Nó sử dụng 137 byte (khi đặt trên một dòng) và nó khác xa so với 104 byte được quảng cáo trong tiêu đề. Mã có thể được rút ngắn thêm 2-3 byte nhưng nguồn cải tiến lớn là ở một nơi khác: trong các chi tiết của thuật toán.

Thuật toán sửa đổi:

Có một số nơi mà thuật toán có thể được cải thiện bằng cách loại bỏ mã vô dụng.

  • không cần phải lặp lại chiều rộng từ 1đến $n; đối với tốc độ, chiều rộng ( $i) phải lặp lại giữa 1floor(sqrt($n))nhưng điều này làm cho mã dài hơn thay vì rút ngắn nó; nhưng nếu chiều rộng không vượt quá sqrt($n), chiều cao tối thiểu ( $j) sẽ luôn lớn hơn sqrt($n)(sản phẩm của họ phải ít nhất $n);
  • câu lệnh trước cho phép sử dụng $i <= $j(width <= height) làm điều kiện kết thúc cho vòng lặp; bằng cách này, chiều rộng sẽ lặp lại từ 1đến floor(sqrt($n))và chiều cao sẽ nhận được các giá trị bắt đầu bằng $nvà đi xuốngceil(sqrt($n)) (không nhất thiết là tất cả chúng);
  • biết rằng chiều rộng luôn nhỏ hơn hoặc bằng chiều cao cho phép chúng ta biết abs(width - height)luôn luôn là height - width($j-$i ); 5 byte được lưu theo cách này;
  • giá trị đầu vào $nđược sử dụng trong tính toán điểm số (số lượng ghế không có người ở width * height - n) nhưng không cần thiết; điểm số không cần phải được hiển thị, nó chỉ được tính để so sánh các sắp xếp; bằng cách xóa - nkhỏi công thức tính điểm, chúng tôi tiết kiệm thêm 3 byte (mã PHP -$n) mà không mất bất cứ thứ gì;
  • đưa ra hai câu lệnh cuối cùng, công thức tính điểm trở thành height - width + width * height( $j-$i+$i*$j);
  • về các mối quan hệ (điểm số của sự sắp xếp hiện tại giống như điểm số tốt nhất trước đó), các quy tắc nói rằng sử dụng sự sắp xếp với ít chỗ ngồi miễn phí hơn; bởi vì chiều rộng luôn tăng và chiều cao luôn giảm,height - width phần của điểm giảm dần trên mỗi bước;
  • nếu điểm số hiện tại bằng với điểm số tốt nhất trước đó, thì các tuyên bố trước cho chúng ta biết rằng số lượng ghế miễn phí của sự sắp xếp hiện tại lớn hơn so với điểm số tốt nhất trước đó; điều này có nghĩa là sự sắp xếp tốt nhất trước đó giành chiến thắng;
  • bởi vì các mối quan hệ luôn giành được bởi sự sắp xếp tốt nhất trước đó, một sự sắp xếp mới trở thành sự sắp xếp tốt nhất mới chỉ khi điểm của nó nhỏ hơn điểm tốt nhất trước đó; mã kiểm tra các mối quan hệ là vô ích và có thể được gỡ bỏ (||$c==$s&&$i*$j<$w*$h - rất nhiều byte);
  • do loại bỏ -$nkhỏi công thức của điểm số, điểm cho cách sắp xếp đầu tiên ( 1x$n) là $n-1+1*$n(nghĩa là 2*$n-1); giá trị ban đầu của điểm tốt nhất ( $s) có thể là bất kỳ giá trị nào lớn hơn hoặc bằng 2*$n; lần lặp đầu tiên có điểm số tốt hơn và nó trở thành sự sắp xếp tốt nhất để thuật toán chạy mà không gặp vấn đề khởi tạo.

Mã mới ( 104 byte ), sau khi áp dụng các cải tiến được mô tả ở trên là:

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";

Nó được bọc ở đây để dễ đọc. Chuẩn bị mã ở trên với điểm đánh dấu PHP <?php(về mặt kỹ thuật, nó không phải là một phần của mã), đặt nó vào một tệp (giả sử arrange-your-chairs.php) và chạy nó với số nguyên lớn hơn 0 làm đối số. Nó sẽ hiển thị chiều rộng và chiều cao của sự sắp xếp được tính toán, được phân tách bằng dấu phẩy:

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

Một giải pháp khác (116 byte)

Một giải pháp khác sử dụng thuật toán khác:

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ó đặt tất cả các kết hợp của ít nhất $nchỗ ngồi vào một danh sách liên kết; chìa khóa là biểu diễn văn bản của sự sắp xếp, giá trị là điểm số của sự sắp xếp. Sau đó, nó sắp xếp danh sách (tăng dần theo giá trị) và lấy khóa của mục nhập đầu tiên.

Thêm một (115 byte)

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";

Đây là phiên bản PHP của câu trả lời của @ Neil (JavaScript / ES6, 85 byte).

Có một số khác biệt đáng chú ý do các tính năng của từng ngôn ngữ:

  • câu trả lời JS tạo ra một mảng các ngiá trị (không xác định) sau đó sử dụng các khóa của nó để lặp từ 0đến n-1; nó tăng i( d=(n+i++)/i|0) để làm cho nó lặp từ 1đến n; giải pháp PHP không cần tăng; nó sử dụng range()để tạo một mảng sau đó nó sử dụng các giá trị được tạo ra ( 1đển ) để lặp lại;
  • câu trả lời JS sử dụng (n+i)/isau đó chuyển đổi giá trị thành số nguyên bằng cách sử dụng |0số nguyên nhỏ nhất lớn hơn n/i; câu trả lời PHP giải quyết vấn đề này một cách dễ dàng với hàm PHP ceil(); JavaScript cũng cung cấp Math.ceil()nhưng nó sử dụng nhiều hơn 5 byte so với giải pháp mà Neil tìm thấy;
  • PHP cung cấp hàm array_map()tương tự với JS Array.map()nhưng không giúp được gì ở đây; cú pháp của nó là dài dòng, một foreachmã tạo ra ngắn hơn; mặc dù nó lớn hơn mã JS;
  • Không thể hợp nhất các bài tập vào các điều kiện sử dụng ||trong PHP vì nó thiếu toán tử dấu phẩy; Tôi đã dịch a||b||csang if(!a&&!b)cđó, bởi vì ablà so sánh, tôi đã phủ nhận các toán tử của họ (thay thế <bằng >=); điều này cũng tạo ra mã lớn hơn phiên bản JS;
  • 23 byte khác phải được thêm vào chỉ vì tên của các biến trong PHP phải được thêm tiền tố bởi $.

Các phiên bản chưa được chỉnh sửa của tất cả các giải pháp và bộ thử nghiệm có thể được tìm thấy trên Github .


1
Đây là câu trả lời mã golf kỹ lưỡng nhất mà tôi từng thấy.
DJMcMayhem

0

JavaSCript (ES6), 83 byte

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

Có lẽ bạn có thể áp dụng mẹo của tôi (để tiết kiệm 2 byte)
Leaky Nun

@KennyLau Tôi không nghĩ nó giúp được; Tôi sẽ phải tăng mđể bù đắp.
Neil

0

Julia, 87

Tôi nghĩ rằng đây là một bước trong việc tìm kiếm một chức năng ma thuật cho vấn đề:

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(_)

Nó chỉ nhìn vào cặp (i, j=(i+n)/(i+1))hoặc(i, j+1)


vui lòng giải thích thêm về cách thức hoạt động của nó, bạn v khiến tôi tò mò về chức năng của bạn
Abr001am

2
Tôi không chắc làm thế nào để nó hoạt động. Bạn không xác định nbất cứ nơi nào và dường như bạn không nhận đầu vào.
Dennis

Ah, xin lỗi, tôi chỉ lấy nlàm đầu vào. Người ta sẽ cần phải bọc nó vào n->.... Rất vui vì bạn có thể làm cho nó hoạt động.
mschauer

0

Oracle SQL 11.2, 173 byte

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;

Không chơi gôn

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 byte

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

Lamba tính chi phí tối thiểu cho một giá trị nhất định (x) và trả về một chuỗi gồm hai giá trị (chiều rộng, chiều cao)

Thêm tên vào lambda đó yêu cầu hai char khác (ví dụ f: {..} thay vì {..})

Kiểm tra

{..}'1+!100

trong đó {..} là lambda. Đọc là "áp dụng lambda cho mỗi giá trị của 1 + 100 ints đầu tiên" (nói cách khác cho mỗi giá trị 1..100)

Tạo

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
..

Giải trình

Lamdba lồng {((b<a)?1b)#+(b:-_-x%a;a:1+!x)} tạo ra tất cả các cặp ứng cử viên (widht, height) cho x ghế là hai chuỗi (w1 w2 w3 ..; h1 h2 h3 ..) (chiều rộng và chiều cao). Đọc từ trái sang phải, nhưng đánh giá từ phải sang trái

a:1+!x tạo các giá trị 1..x và gán chuỗi đó cho

-_- là phủ định phủ định sàn, và thực hiện trần (trần không phải là nguyên thủy của ngôn ngữ)

b:-_-x%aáp dụng trần cho mỗi giá trị của x chia cho bất kỳ mục nào im a và gán chuỗi kết quả cho b. Nói cách khác, b là trần mỗi x chiaBy mỗi 1..x

+(b;a) trả về một khoảng bao gồm seq a và seq b, sau đó lật nó (kết quả là một chuỗi các cặp trong đó cặp i chứa phần tử i của a và phần tử i của b)

b<a so sánh từng mục theo mục của b và a và tạo ra một giá trị logic (true = 1b cho mỗi chỉ mục trong đó b [i]

s?xtrả về vị trí đầu tiên của mục x trong chuỗi s. Với (b<a)?1bChúng tôi tìm kiếm 1b (giá trị thực) theo thứ tự kết quả so sánh b và a, và có được vị trí đầu tiên trong đó b

n#smất n mục đầu tiên từ seq s. Chúng tôi muốn loại bỏ các cặp trùng lặp, vì vậy chúng tôi dừng lại khi mục đầu tiên của một cặp <mục thứ hai (ví dụ: xem xét 13,1 chứ không phải 1,13).

Là một tác dụng phụ, mỗi cặp của chuỗi kết quả là khoảng cách giảm dần giữa a và b (ví dụ (13 1; 7 2; 5 3; 4 4)

Cặp ứng cử viên được tạo bởi lambda lồng nhau được gán cho c. Sau đó chúng ta lật c (lấy b, một lần nữa) và áp dụng hai hàm cho đối số đó: */nhân lên và -/trừ đi. Kết quả (-/;*/)@\:+clà sự khác biệt và sản phẩm của mỗi cặp.+/là tổng số, và chi phí cuối cùng calculares. Chi phí của mỗi patir được gán cho d

& / là tối thiểu hơn, vì vậy &/d là chi phí tối thiểu. Với việc d?&/dchúng tôi tìm thấy sự xuất hiện đầu tiên của chi phí tối thiểu trong d và với c @ .. chúng tôi lấy cặp ở vị trí đó. Vì mỗi cặp giảm dần khoảng cách giữa a và n, nên mức tối thiểu đầu tiên được tìm thấy có các cặp tối thiểu khác nhau, do đó chúng tôi áp dụng quy tắc ràng buộc chính xác

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.