Разделить на 3, функция в C # - PullRequest
0 голосов
/ 09 марта 2012

У меня есть функция, которая возвращает мне список значений int, зависит от части значений:

private List<int> GetColumn(int total, int column)
{
    List<int> retList = new List<int>();

    if (total <= 0)
    {
        return retList;
    }

    if (column < 0 || column > 2)
    {
        column = 0;
    }

    int pageSize = total / 3;

    int startIndex = column * pageSize;
    int endIndex = column * pageSize + pageSize;

    if (endIndex > total)
    {
        endIndex = total;
    }

    for (int i = startIndex; i < endIndex; i++)
    {
        retList.Add(i);
    }

    return retList;

}

, но работает неправильно, потому что для: GetColumn (17, 0)

возвращает [0,1,2,3,4], но должен возвращать [0,1,2,3,4,5]
для GetColumn (17, 1) - [6,7,8,9,10, 11]
для GetColumn (17, 2) - [12,13,14,15,16]

для 16 должно возвращаться: для GetColumn (16, 0) - [0,1,2,3,4,5]
для GetColumn (16, 1) - [6,7,8,9,10]
для GetColumn (16, 2) - [11,12,13,14,15]

Что я должен изменить в своей функции?Спасибо!

Ответы [ 3 ]

3 голосов
/ 09 марта 2012

Если это то, что вам нужно (числа увеличиваются по столбцам, но сначала нужно заполнить строки):

for 16:
0  6  11
1  7  12
2  8  13
3  9  14
4  10 15
5

for 17:
0  6  12
1  7  13
2  8  14
3  9  15
4  10 16
5  11

Вам необходимо определить, какой столбец получает остатки:

int remainder = total % 3;

если остаток равен 1, только первый столбец состоит из 6 элементов. если остаток равен 2, первый и второй столбцы состоят из 6 элементов. Вы должны рассчитать startIndex и endIndex в соответствии с этим.

Итак,

int pageSize = total / 3;
int remainder = total % 3;

int startIndex = column * pageSize + min(column, remainder);
int endIndex = startIndex + pageSize + (remainder > column ? 1 : 0);

должно работать. Я только что проверил, он работает для разных размеров строк, чем 3.

Вот как я получил формулы: составление таблиц - хорошая практика для сортировки таких алгоритмов:

r: остаток, c: столбец, ps: размер страницы (как рассчитано выше)

StartingIndex:
.  |r:0 |r:1   |r:2
----------------------
c:0|0   |0     |0
----------------------
c:1|ps  |ps+1  |ps+1
----------------------
c:2|ps*2|ps*2+1|ps*2+2

Вы можете увидеть шаблон, если вы расширите таблицу для размера строки 4:

StartingIndex:
.  |r:0 |r:1   |r:2   |r:3
------------------------------
c:0|0   |0     |0     |0
------------------------------
c:1|ps  |ps+1  |ps+1  |ps+1
------------------------------
c:2|ps*2|ps*2+1|ps*2+2|ps*2+2
------------------------------
c:3|ps*3|ps*3+1|ps*3+2|ps*3+3

добавляемое вами значение является минимумом соответствующего столбца и остатка

Аналогично для endIndex, желаемая длина столбцов может быть видна при построении таблицы для данного остатка по сравнению со столбцом. Я не буду сейчас это писать, потому что на составление таблиц уходит слишком много времени, и я думаю, что у вас уже есть идея.

0 голосов
/ 09 марта 2012

Если я правильно понимаю, требование:

If the number is 3n,   divide it in 3 groups of n,   n   and n   elements.
If the number is 3n+1, divide it in 3 groups of n+1, n   and n   elements.
If the number is 3n+2, divide it in 3 groups of n+1, n+1 and n   elements.

Лучше всего сделать это явным образом в своем коде и избегать любой «умной» логики. Прямое разделение сводится к:

If the number is 3n, the divisions are:
     0 ..  n-1
     n .. 2n-1
    2n .. 3n-1
If the number is 3n+1, the divisions are:
     0 .. n
   n+1 .. 2n
  2n+1 .. 3n
If the number is 3n+2, the divisions are:
     0 .. n
   n+1 .. 2n+1
  2n+2 .. 3n+1

В c # это было бы что-то вроде:

public static List<int> Divide3Columns(int total, int column)
{
  int startIndex = 0;
  int endIndex = 0;
  int pageSize = total / 3;

  if (total % 3 == 0)
  {
    startIndex = column * pageSize;
    endIndex = (column + 1) * pageSize - 1;
  }

  if (total % 3 == 1)
  {
    if (column == 0)
    {
      startIndex = 0;
      endIndex = pageSize; //pageSize + 1 elements;
    }
    else
    {
      startIndex = column * pageSize + 1;
      endIndex = (column + 1) * pageSize;
    }
  }

  if (total % 3 == 2)
  {
    if (column == 2)
    {
      startIndex = 2 * pageSize + 2;
      endIndex = 3 * pageSize + 1; //same as total - 1;
    }
    else
    {
      startIndex = column * (pageSize + 1);
      endIndex = (column + 1) * pageSize + column;
    }
  }

  List<int> result = new List<int>();
  for (int i = startIndex; i <= endIndex; i++)
  {
    result.Add(i);
  }
  return result;
}

Ответ предполагает, что мы всегда будем делить на 3 и только 3 столбца . Если число является переменным, логика для определения столбцов может быть обобщена.

0 голосов
/ 09 марта 2012

Целочисленное деление округляет до нуля.Итак, 17/3 = 5 и -17/3 = -5Я думаю, что вы хотите округлить до следующего целого числа, как это

int pageSize = (int)Math.Ceiling(total / 3d);
...