确定给定数字所需的行/列

时间:2010-11-05 14:43:05

标签: c# algorithm silverlight math

我有许多控件(在这种情况下为图表),这些控件是在运行时确定的。我想将它们放在具有适当行数和列数的网格中。例如,

  • 4项= 2 x 2
  • 8项= 4 x 2
  • 9项= 3 x 3
  • 20项= 5 x 4
  • 11项= 4 x 3(我不关心空单元格)

抱歉,我没有任何代码可以显示我的尝试。我开始玩,确定平方根是否是一个整数,如果数字可以被2整除,并意识到我不知道如何解决这个问题。但这就是我的想法:

  • 如果平方根是一个整数,则使用平方根表示行数和列数(没有问题)
  • 如果没有,请确保该数字是偶数(如果必须,请添加一个 - 没有问题)
  • 找出产生该数字的最高两个整数。例如如果我有20个控件,则网格应为5 x 4而不是10 x 2(不确定最佳方式)

如果有人能指出我正确的方向,我会很感激 - 如果我离开基地的话,我会建议不同的算法。

6 个答案:

答案 0 :(得分:24)

想法:如果平方根不是整数,那么将它放在一边,然后将整数除以此值,然后将其放置。

int columns = (int)sqrt(number);
int lines = (int)ceil(number / (float)columns);

示例:21 => columns = 4,lines = 6。

更新:奖金,当sqrt(数字)为整数时也有效。任何地方都不会发生舍入,值也是正确的。

答案 1 :(得分:3)

处理这个问题的“通常”方法是说总会有N列(不常见,总是N行)。然后问题就是采用项目数除以N,这就是你拥有的行数(如果有余数则加一个)。

更改网格的大小会导致令人困惑的用户界面。用户不会理解为什么网格的大小会不断变化。他们不会对此感到好奇,但他们会被看似随意的变化所迷惑。

如果你仍想做你所说的话,我认为你需要更好地定义你的问题。网格上是否有最大数量的项目?您允许的最大列数是多少?例如,如果您允许50个项目,它们应该是25行2个项目吗? 5行10项? 10行5项?

在某些时候,您必须水平滚动或说“最大列数为X”。如果你要强加最大数量的列,那么你最好只说“总会有X列。”

除非有令人信服的理由去做你要求的可变维度网格,否则你最好只修复列数。它简单易用,而不是一些复杂的黑客攻击,它为用户提供了更加一致的界面。

答案 2 :(得分:3)

快速检查@ jv42的解决方案很有效:

public struct Grid
{
    public int x;
    public int y;

    public Grid(int xx, int yy)
    {
        x = xx;
        y = yy;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Grid g0 = GetGrid(1); Debug.Assert(g0.x == 1 && g0.y == 1);
        Grid g1 = GetGrid(4); Debug.Assert(g1.x == 2 && g1.y == 2);
        Grid g2 = GetGrid(8); Debug.Assert(g2.x == 2 && g2.y == 4);
        Grid g3 = GetGrid(9); Debug.Assert(g3.x == 3 && g3.y == 3);
        Grid g4 = GetGrid(20); Debug.Assert(g4.x == 4 && g4.y == 5);
        Grid g5 = GetGrid(30); Debug.Assert(g5.x == 5 && g5.y == 6);
        Grid g6 = GetGrid(99); Debug.Assert(g6.x == 9 && g6.y == 11);
    }

    public static Grid GetGrid(int n)
    {
        int columns = (int)Math.Sqrt(n);
        int lines   = (int)Math.Ceiling(n / (double)columns);

        return new Grid(columns, lines);
    }

答案 3 :(得分:1)

感谢您提出这个问题和答案!

以下代码已翻译成Javascript:

cols = Math.floor( Math.sqrt(totalTiles) );
rows = Math.floor(  Math.ceil( totalTiles / cols ) );

答案 4 :(得分:0)

在WPF中,控件UniformGrid自动计算网格的行和列,而不确定行和列。 例如:

   <UniformGrid >
        <Image Source="Images\Aquarium.jpg"  Margin="5"/>
        <Image Source="Images\Ascent.jpg"   Margin="5" />
        <Image Source="Images\Autumn.jpg"  Margin="5"/>
        <Image Source="Images\Crystal.jpg" Margin="5"/>
        <Image Source="Images\DaVinci.jpg"  Margin="5"/>
        <Image Source="Images\Follow.jpg"  Margin="5"/>
        <Image Source="Images\Friend.jpg" Margin="5"/>
        <Image Source="Images\Aquarium.jpg"  Margin="5"/>
    </UniformGrid>

结果=&GT;以3列3行显示图像

答案 5 :(得分:0)

我遇到了这个问题,但是有一些特定要求;

  • 列数不能超过一定数量
  • 如果项目的数量不能完全符合特定的列数,我希望有尽可能多的寡妇。

例如:

1 2 3
4 5 6

1 2 3
4 5

1 2 3 4
5 6 7

我想出了这个(PHP)函数,但是我敢肯定它可以得到改进:

<?php
function optimalColCount ($numItems, $maxCols = 4) {
    $numCols = $numItems;

    if ($numCols > $maxCols and $maxCols === 2) {
        $numCols = 2;
    }
    else if ($numCols > $maxCols) {
        $numCols = sqrt($numItems);

        if (!is_int($numCols) or $numCols > $maxCols) {
            $numCols = -1;

            for ($i = $maxCols; $i > 2; $i--) {
                if ($numItems % $i === 0) {
                    $numCols = $i;

                    break;
                }
            }

            if ($numCols === -1) {
                $rests = [];

                for ($i = $maxCols; $i > 2; $i--) {
                    $rests[$i] = $numItems % $i;
                }

                $numCols = array_search(max($rests), $rests);
            }
        }
    }

    return $numCols;
}