2010-03-17 62 views
1

如果有數倍的對象,如何安排它,這樣行X中列對象的每一個號碼形成近正方形?安排n個對象的

EXP:14組的對象安排是這樣的:

0 0 0 0 
0 0 0 0 
0 0 0 0 
0 0 
+0

除非我完全誤解了問題,這有沒有關係組合或置換... – Guffa 2010-03-17 14:26:34

回答

6

採取平方根的小區?

import math 
ceil(14**(.5)) 

它返回:

>>> from math import ceil 
>>> ceil(14**(.5)) 
4.0 
2

獲取項目數的平方根:

n = 14^0.5 ~ 3.7417 

四捨五入爲最接近的整數:

在Python

n = ceil(14^0.5) = 4 

,直到你用完現在只需安排的n個項目行的項目。

1

鑑於n對象,所得到的「廣場」的大小是ceil(sqrt(n)),有專門的快捷案件,其中n = 0(不畫任何東西)或n = 1(只是一個1x1平方)。

而且,問題的標題是有點誤導。你永遠不能在一個NxN方安排N個對象,除非N爲1

+0

'小區(開方(0))== 0'和'小區(開方(1))= = 1';應該不需要特殊情況。 – Thomas 2010-05-08 12:14:34

+0

@Thomas:在數學上,他們不是特例。以編程方式,他們是;當只需要處理零個或一個事物時,具有執行算法簡單版本的快捷條件是很常見的。 – 2010-05-08 14:15:14

+0

如果在一般情況下處理特殊情況,爲什麼要添加額外的代碼來編寫,讀取,調試和維護?除非這個代碼實際上是一個性能瓶頸,並且這個快捷方式確實可以加快速度;但添加它們應該是例外,而不是規則。 – Thomas 2010-05-08 15:29:24

2

那要看情況。假定列的數目應該大於行數等於或大於以下計算的列數(在僞代碼):

Ceiling(Sqrt(n)) 

其中n是項數。

1

如果您希望將網格居中,您需要知道您將提前多少行,該函數(它是javascript,但我認爲它應該可以輕鬆移植到另一種語言)將生成一個網格的位置和支持居中和間距。

在僞代碼

columns = Ceiling(Sqrt(n)) 
rows = (columns - 1) if (Round(Sqrt(n)) < columns) else columns 

如果centerfalse,該功能會產生這樣的事情(o爲原點):

+———————+ 
|oxx | 
|xxx | 
|xx  | 
|  | 
|  | 
+———————+ 

如果centertrue

+———————+ 
|  | 
| xxx | 
| xox | 
| x | 
|  | 
+———————+ 

代碼

/** 
* Creates a grid of positions for the given items count and size. 
* It assumes items anchor are centered. 
* 
* @param {number} x    - The grid x position 
* @param {number} y    - The grid y position 
* @param {number} count   - The number of positions you wish to create 
* @param {number} size   - The item size 
* @param {boolean} [center=true] - If true wil center the grid according to `x`, `y` 
* @param {number} [spacing=0] - Item spacing 
* @return {Array.<{x: number, y: number}>} The generated positions 
*/ 
export const makeGrid = (x, y, count, size, { center = true, spacing = 0 } = {}) => { 
    // avoid computing trivial cases 
    if (count === 0) return [] 
    if (count === 1) return [{ x, y }] 

    const sqrt   = Math.sqrt(count) 
    const columns  = Math.ceil(sqrt) 
    const rows   = Math.round(sqrt) < columns ? columns - 1 : columns 
    const sizeAndSpacing = size + spacing 

    let offsetX = x 
    let offsetY = y 

    // if grid is centered apply offset according to `columns` and `rows` 
    if (center === true) { 
     offsetX -= (columns - 1) * sizeAndSpacing * .5 
     offsetY -= (rows - 1) * sizeAndSpacing * .5 
    } 

    let column = 0 
    let row = 0 

    return _.range(count).map(() => { 
     // if we're on last row's first column and grid is centered 
     if (row === rows - 1 && column === 0 && center === true) { 
      // if last row's items doesn't completely fill the line 
      // we apply an extra offset to center them 
      const modulus = count % columns 
      if (modulus > 0) { 
       offsetX += (columns - modulus) * sizeAndSpacing * .5 
      } 

     } 
     const pos = { 
      x: offsetX + column * sizeAndSpacing, 
      y: offsetY + row * sizeAndSpacing, 
     } 

     column++ 
     if (column === columns) { 
      column = 0 
      row++ 
     } 

     return pos 
    }) 
}