Перебор не занятых шаров

jenya7
Дата: 09.09.2018 12:20:13
Возникла такая вот алгоритмическая проблема.

Есть 19 коробок. В каждой коробке 19 пронумерованных шаров от 1 до 19.
Скажем начинаем с первой коробки - выбираем там шар номер 2. Во второй коробке я могу выбрать любой шар кроме номер 2.
Скажем выбрал шар номер 3. В третьей коробке я могу выбрать шар только из оставшихся 1,4,5,6,7,8,9,10...и так далее
Проблема как отображать оставшиеся шары на дисплее циклически?

Есть три кнопки ENTER,UP,DOWN.
ENTER выбирает следующую коробку - движение только вверх, вернуться к предыдущей коробке я не могу.
UP, DOWN выбирают следующий доступный шар.
И текущая коробка и выбранный шар отображаются на дисплее.

Я сделал симуляцию на Сшарп

byte g_counter;

int box_number;
byte ball_number;

byte[] mslseq = new byte[20];
byte[] selected = new byte[20];

private void Form1_Load(object sender, EventArgs e)
{
           
  ball_number = 1;
  box_number = 0;
  g_counter = 1;

  DisplayText();
}

private void buttonEnter_Click(object sender, EventArgs e)
{  
   if (ball_number < 20)
   {
       mslseq[box_number] = ball_number;
       selected[ball_number] = 1;
   }

   //select next box
   box_number++;

   //find first available ball
    ball_number = GetNextBallNumber(UP_KEY, 1);
    g_counter = ball_number;

    if (box_number > 18)
    {
        box_number = 0;
        textBoxDisplay.Text = "Finished!!!";
    }

    DisplayText();
}


private void buttonUp_Click(object sender, EventArgs e)
{
    g_counter++;
    if (g_counter > 19)
       g_counter = 1;

    ball_number = GetNextBallNumber(UP_KEY, g_counter);
        g_counter = ball_number;

    DisplayText();

}

private void buttonDown_Click(object sender, EventArgs e)
{
    g_counter--;
    if (g_counter > 19)
        g_counter = 19;

    ball_number = GetNextBallNumber(DOWN_KEY, g_counter);
        g_counter = ball_number;

    DisplayText();
}

void DisplayText()
{
   textBoxBox.Text = (box_number + 1).ToString();
   textBoxBall.Text = ball_number.ToString();
}

byte GetNextMissleNumber(int key, byte b_num)
{
   int done = 0;
            
   while (done == 0)
   {
      if (selected[b_num] == 0)
      {
          done = 1;
          return b_num;
      }
      else
      {
          if (key == UP_KEY)
          {
               b_num++;
               if (b_num > 19)
               {
                  done = 1;
                  return 1;  //????
               }
          }
          else if (key == DOWN_KEY)
          {
              b_num--;
              if (b_num > 19) //overflow
              {
                 done = 1;
                 return 19; //????
              }
          }
       }
   }
   return 0;
}


Проблема в переходах 1-19, 19-1.Не получается разрулить логику.
MBo
Дата: 09.09.2018 17:37:14
Задача не сформулирована.
Покажи, как должно работать, на примере с 4 коробками и шарами.
Aleksandr Sharahov
Дата: 09.09.2018 18:13:50
jenya7,

фактически у тебя человек вручную генерирует перестановку,
из этого и исходи при проектировании структуры данных.

После того как человек выбирает i-тый шар,
номер выбранного шара помещаешь на i-тое место, а остальные номера сдвигаешь.
Т.о. у тебя всегда в начале массива будут выбранные номера, в конце - не выбранные.
Ну и останется только закольцевать в UI невыбранные, ты должен справиться.
mayton
Дата: 09.09.2018 21:29:41
Тут что-то не то. После декремента не принято сравнивать переменную на "больше".
    g_counter--;
    if (g_counter > 19)
           g_counter = 19;
Aleksandr Sharahov
Дата: 09.09.2018 22:42:45
Aleksandr Sharahov, на паскале примерно так (не отлаживал)

//массив шаров
var
  box: array of integer;

//начальное заполнение массива шаров
procedure InitBox(count: integer);
begin;
  SetLength(box, count);
  for i:=0 to count-1 do box[i]:=i;
  end;

//передвинуть положение текущего шара на value=-1..1
function RotateOffset(boxNo, offset, value): integer;
var
  m: integer;
begin;
  m:=Length(box)-boxNo; //количество оставшихся шаров
  Result:=(offset+value+m) mod m;
  end;

//получить номер текущего шара
function GetBall(boxNo, offset): integer;
begin;
  Result:=box[boxNo+offset];
  end;

//выбрать шар (не забыть потом увеличить boxNo)
procedure SwapBalls(boxNo, offset);
var
  b, i: integer;
begin;
  b:=box[boxNo+offset];
  for i:=boxNo+offset-1 downto boxNo do box[i+1]:=box[i];
  box[boxNo]:=b;
  end;
Gennadiy Usov
Дата: 10.09.2018 05:17:31
А если взглянуть на эту задачу с точки зрения задачи расстановки ферзей.

Коробка - это номер ферзя.
Номер шара - значение ферзя.

А далее, выбирая номер коробки и номер шара, определяем расклад (выборку).

Тут и модулярные выборки, и прочие выборки. Всего: 4968057848 выборок.

Кто-то захочет исследовать торовые выборки, а кого-то заинтересует выборка из 50000 коробок, а кто-то обозначит множество алгоритмов по выборкам.

Так что, jenya7, становитесь участником топика "Расстановка ферзей".
Gennadiy Usov
Дата: 10.09.2018 05:31:01
Предыдущее сообщение - первое что пришло на ум.

На самом деле имеем выборку не ферзей, а ладей. И количество выборок будет значительно больше.
mayton
Дата: 10.09.2018 09:01:02
Gennadiy Usov
exp98
Дата: 10.09.2018 09:51:36
jenya7, 2 момента непонятны

1) я могу выбрать шар только из оставшихся
Как понимать? обязательно надо переходить к другой коробке и в ней искать, пока не наткнёшься на новый шар? или достаточно обойтись одной коробкой, тогда и искать не надо.
В последнем случае типичная схема выбора без возврата.

2) разрулить логику перехода
уточнить проблему, остаток от деления на 19 разве не есть логика перехода?
что такое отображать циклически?
Aleksandr Sharahov
Дата: 10.09.2018 10:17:06
exp98
jenya7, 2 момента непонятны

1) я могу выбрать шар только из оставшихся
Как понимать? обязательно надо переходить к другой коробке и в ней искать, пока не наткнёшься на новый шар? или достаточно обойтись одной коробкой, тогда и искать не надо.
В последнем случае типичная схема выбора без возврата.

2) разрулить логику перехода
уточнить проблему, остаток от деления на 19 разве не есть логика перехода?
что такое отображать циклически?


Автор затаился)

В меру моего понимания:

1. У него выбор без возврата (причем описание UI мешает описанию алгоритма)

2. Проблема в UI - автор не может изобразить модную нынче "карусель",
когда у пользователя есть возможность выбрать текущий элемент
или сделать текущим его соседа слева/справа (сверху/снизу).