Example #1
0
 private void button4_Click(object sender, EventArgs e)
 {
     set_blocked_state(false);
     richTextBox1.Text = DateTime.Now.ToString() + "\n";
     CallBackMy.callbackEventHandler("Начало выполнения методов\n");
     for (int i = 0; i < meth.checkedListBox1.Items.Count; i++)
     {
         if (count == 2 && i >= 3)
         {
             CallBackMy.callbackEventHandler("Разблокируем метод №" + i + "\n");
             meth.checkedListBox1.SetItemChecked(i, true);
         }
         if (meth.checkedListBox1.GetItemChecked(i))
         {
             CallBackMy.callbackEventHandler("Выполняем метод №" + i + "\n");
             update();
             main.do_method(i);
         }
         if (count == 0 && (i == 0 || i == 2))
         {
             CallBackMy.callbackEventHandler("Блокируем для выполнения метод №" + i + "\n");
             meth.checkedListBox1.SetItemChecked(i, false);
         }
     }
     CallBackMy.callbackEventHandler("Конец выполнения методов\n");
     update();
     print_debug();
     count++;
     ((Button)sender).Text = "Го " + count;
     set_blocked_state(true);
 }
Example #2
0
 void print()
 {
     //шапка
     CallBackMy.callbackEventHandler("    ");
     for (int i = 0; i < n; i++)
     {
         CallBackMy.callbackEventHandler(sum[0, i] + " ");
     }
     CallBackMy.callbackEventHandler("\n");
     //середина
     for (int i = 0; i < n; i++)
     {
         for (int j = 0; j < n; j++)
         {
             if (j == 0)
             {
                 CallBackMy.callbackEventHandler(sum[2, i] + "  ");
             }
             CallBackMy.callbackEventHandler(matrix[i, j] + " ");
             if (j == n - 1)
             {
                 CallBackMy.callbackEventHandler(" " + sum[3, i] + "\n");
             }
         }
     }
     //хвост
     CallBackMy.callbackEventHandler("    ");
     for (int i = 0; i < n; i++)
     {
         CallBackMy.callbackEventHandler(sum[1, i] + " ");
     }
     CallBackMy.callbackEventHandler("\n");
 }
Example #3
0
        void free_stairs()
        {
            //реализация clear_cand_hard для блоков
            bool l_d = true;

            for (int i = 0; i < blocks_table.Count; i++)
            {
                if (((block)blocks_table[i]).sum > 2 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[0])).value == 0 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[1])).value == 0 &&
                    ((block)blocks_table[i]).is_all_empty(((block)blocks_table[i]).cells_mas.Count - 1) &&
                    ((block)blocks_table[i]).fully_isolated
                    )
                {
                    int max = ((block)blocks_table[i]).max_cand();

                    if (((block)blocks_table[i]).sum > 2)
                    {
                        for (int n = 0; n < ((block)blocks_table[i]).sum - 2; n++)
                        {
                            //проверка на удаление чего-либо
                            bool flag = false;
                            for (int m = 0; m < ((block)blocks_table[i]).sum - n - 2; m++)
                            {
                                if (is_cell_in_block_have_a_candidate(i, n, max - m))
                                {
                                    flag = true;
                                    break;
                                }
                            }

                            if (flag)
                            {
                                if (g_d && l_d)
                                {
                                    CallBackMy.callbackEventHandler("free_stairs >: удаляем у ячейки (" + i + ", " + n + ") кандидаты ");
                                }
                                for (int m = 0; m < ((block)blocks_table[i]).sum - n - 2; m++)
                                {
                                    if (g_d && l_d)
                                    {
                                        CallBackMy.callbackEventHandler(max - m + " ");
                                    }
                                    erase_cell_s_cand_for_block(i, n, max - m);
                                }
                                if (g_d && l_d)
                                {
                                    CallBackMy.callbackEventHandler("\n");
                                }
                            }
                        }
                    }
                }
            }
        }
Example #4
0
 //печать
 void print_blocks()
 {
     CallBackMy.callbackEventHandler2("Блоки (" + blocks_table.Count + ")\n", true);
     for (int i = 0; i < blocks_table.Count; i++)
     {
         CallBackMy.callbackEventHandler2("Блок " + i + "  ");
         ((block)blocks_table[i]).print();
         CallBackMy.callbackEventHandler2("\n");
     }
     CallBackMy.callbackEventHandler2("Конец распечатки блоков \n");
 }
Example #5
0
        //Ариадна-1
        void Ariadna_for_cells()
        {
            bool l_d = true;

            //для числа кандидатов в ячейках
            for (int k = 2; k < n - 2; k++)
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        int       cout_of_true_candidates = 0;
                        ArrayList pos_of_true_candidates  = new ArrayList();
                        for (int s = 0; s < n; s++)
                        {
                            if (candidates[i, j, s])
                            {
                                cout_of_true_candidates++;
                                pos_of_true_candidates.Add(s);
                            }
                        }
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("Сложность " + k + "; уровень " + entry_level + ": Рассматриваем ячейку (" + i + ", " + j + ")");
                        }
                        if (cout_of_true_candidates == k)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler(": углубляемся\n");
                            }
                            ArrayList mas = new ArrayList();
                            for (int r = 0; r < k; r++)
                            {
                                mas.Add(this);
                            }
                            for (int r = 0; r < mas.Count; r++)
                            {
                                ((table)mas[r]).entry_level++;
                                if (Ariadna((table)mas[r], new point(i, j, (int)pos_of_true_candidates[r] + 1)))
                                {
                                    return;
                                }
                            }
                        }
                        else if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler(": пропускаем\n");
                        }
                    }
                }
            }
        }
Example #6
0
        //методы - заполнение и исключение без блоков
        void begin()
        {
            bool l_d = false;

            //заполнение самых больших возле единичек
            if (g_d && l_d)
            {
                CallBackMy.callbackEventHandler("Метод №0: begin()\n");
            }
            for (int j = 0; j < 4; j++)
            {
                for (int iter = 0; iter < n; iter++)
                {
                    if (sum[j, iter] == 1)
                    {
                        int x = -1;
                        int y = -1;
                        switch (j)
                        {
                        case 0:
                            x = iter;
                            y = 0;
                            break;

                        case 1:
                            x = iter;
                            y = n - 1;
                            break;

                        case 2:
                            x = 0;
                            y = iter;
                            break;

                        case 3:
                            x = n - 1;
                            y = iter;
                            break;
                        }
                        if (matrix[x, y] == 0)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("Заполняем ячейку (" + x + ", " + y + ") единственным возможным значением " + n + "\n");
                            }
                            set_cell(x, y, n);
                        }
                        continue;
                    }
                }
            }
        }
Example #7
0
        bool Ariadna(table t, point p)
        {
            bool l_d = false;

            if (g_d && l_d)
            {
                CallBackMy.callbackEventHandler("Рассматриваем таблицку\n");
                t.print(); t.print_cand();
                CallBackMy.callbackEventHandler("\n");
            }
            t.set_cell(p);

            int k = 0;

            for (k = 0; (k < 5) && !t.is_full(); k++)
            {
                try {
                    t.Check();
                    //методы работы для Ариадны
                    t.creating_blocks(); t.optimization_blocks(); t.Check();
                    t.sum_two(); t.check_set_single(); t.Check();
                    t.max_stairs(); t.check_set_single(); t.Check();
                    t.min_stairs(); t.check_set_single(); t.Check();
                    t.free_stairs(); t.check_set_single(); t.Check();
                    //t->print_blocks();
                    //сама Ариадна
                    //if (t.entry_level < 2 && k >= 4)
                    //{
                    //	t.Ariadna_s_thread(); t.check_set_single();
                    //}
                }
                catch (Exception e)
                {
                    CallBackMy.callbackEventHandler("Уровень " + t.entry_level + ": Ариадна отсекла кандидат " + p.value + " у ячейки (" + p.x + ", " + p.y + ")\n");
                    this.candidates[p.x, p.y, p.value - 1] = false;
                    return(true);
                }
            }
            if (g_d && l_d)
            {
                CallBackMy.callbackEventHandler("После преобразований\n");
                t.print(); t.print_cand();
                CallBackMy.callbackEventHandler("\n");
            }
            return(false);
        }
Example #8
0
 void print_cand()
 {
     for (int i = 0; i < n; i++)
     {
         for (int j = 0; j < n; j++)
         {
             String str = "";
             for (int k = 0; k < n; k++)
             {
                 if (candidates[i, j, k])
                 {
                     str += Convert.ToString(k + 1);
                 }
             }
             CallBackMy.callbackEventHandler(str.PadRight(n, '_') + ' ');
         }
         CallBackMy.callbackEventHandler("\n");
     }
 }
Example #9
0
 public void print()
 {
     CallBackMy.callbackEventHandler2("| " + fully_isolated + " " + dir + " " + number + ", ячейки: ");
     foreach (block_cell i in cells_mas)
     {
         CallBackMy.callbackEventHandler2(Convert.ToString(i.cell_s_coord));
     }
     CallBackMy.callbackEventHandler2("\n" + sum + " | ");
     foreach (block_cell i in cells_mas)
     {
         CallBackMy.callbackEventHandler2(" " + i.value);
     }
     CallBackMy.callbackEventHandler2("\n");
     foreach (block_cell i in cells_mas)
     {
         for (int j = 0; j < i.candidates.Count; j++)
         {
             CallBackMy.callbackEventHandler2(Convert.ToString(i.candidates[j]));
         }
         CallBackMy.callbackEventHandler2(" ");
     }
     CallBackMy.callbackEventHandler2("\n");
 }
Example #10
0
        void clear_cand_hard()
        {
            bool l_d = false;

            //для пустых полей
            //удаление крайних максимальных кандидатов
            for (int j = 0; j < 4; j++)
            {
                for (int iter = 0; iter < n; iter++)
                {
                    if (sum[j, iter] >= 2)
                    {
                        for (int number = 0; number < sum[j, iter] - 1; number++)
                        {
                            System.Drawing.Point temp = convert_to_point_coord(j, number, iter);
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("clear_cand_hard (" + j + "): удаляем у ячейки (" + temp.X + ", " + temp.Y + ") кандидаты ");
                            }
                            for (int m = 0; m < sum[j, iter] - number - 1; m++)
                            {
                                if (g_d && l_d)
                                {
                                    CallBackMy.callbackEventHandler(n - m + " ");
                                }
                                candidates[temp.X, temp.Y, n - m - 1] = false;
                            }
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("\n");
                            }
                        }
                    }
                }
            }
        }
Example #11
0
        //методы - с блоками
        void sum_two()
        {
            bool l_d = true;

            //можно ли доразвить до большего хз, но довольно хорошо сформулироно
            //проверка суммы-2, наличие size, и m>=2 пустых клеток до него:
            // 1) исключение m-1, m-2, ... кандидатов в первой клетке
            // 2) верхний зубец стенки - убирание кандидатов максимума от n до края, исключая сам край
            // 3) нижний зубец стенки - убирание минимума у нулевого
            for (int i = 0; i < blocks_table.Count; i++)
            {
                if (((block)blocks_table[i]).sum == 2 &&
                    ((block)blocks_table[i]).is_all_empty(((block)blocks_table[i]).get_value_s_pos(n)) &&
                    ((block)blocks_table[i]).get_value_s_pos(n) > 1 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[0])).value == 0 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[1])).value == 0)
                {
                    //1
                    bool flag_1 = false;
                    for (int k = 1; ((block)blocks_table[i]).get_value_s_pos(n) - k > 0; k++)
                    {
                        int temp = ((block)blocks_table[i]).get_value_s_pos(n) - k;
                        if (is_cell_in_block_have_a_candidate(i, 0, temp))
                        {
                            flag_1 = true;
                            break;
                        }
                    }
                    if (flag_1)
                    {
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("sum_two_1 >: удаляем в блоке " + i + " у ячейки " + 0 + " при сумме-2 и наличии " + n + " лишние кандидаты: ");
                        }
                        for (int k = 1; ((block)blocks_table[i]).get_value_s_pos(n) - k > 0; k++)
                        {
                            int temp = ((block)blocks_table[i]).get_value_s_pos(n) - k;
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler(temp + " ");
                            }
                            erase_cell_s_cand_for_block(i, 0, temp);
                        }
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("\n");
                        }
                    }

                    //2
                    bool flag_2 = false;
                    for (int j = ((block)blocks_table[i]).get_value_s_pos(n) - 1; j > 0; j--)
                    {
                        int temp = ((block)blocks_table[i]).max_cand();
                        if (is_cell_in_block_have_a_candidate(i, j, temp))
                        {
                            flag_2 = true;
                            break;
                        }
                    }
                    if (flag_2)
                    {
                        for (int j = ((block)blocks_table[i]).get_value_s_pos(n) - 1; j > 0; j--)
                        {
                            int temp = ((block)blocks_table[i]).max_cand();
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("sum_two_2 >: удаляем в блоке " + i + " у ячейки " + j + " кандидат " + temp + " при сумме-2 и наличии " + n + " в блоке\n");
                            }
                            erase_cell_s_cand_for_block(i, j, temp);
                        }
                    }

                    //3
                    bool flag_3 = false;
                    if (((block)blocks_table[i]).is_cell_have_a_candidate(0, ((block)blocks_table[i]).min_cand()))
                    {
                        int temp = ((block)blocks_table[i]).min_cand();
                        if (is_cell_in_block_have_a_candidate(i, 0, temp))
                        {
                            flag_3 = true;
                            break;
                        }
                    }
                    if (flag_3)
                    {
                        if (((block)blocks_table[i]).is_cell_have_a_candidate(0, ((block)blocks_table[i]).min_cand()))
                        {
                            int temp = ((block)blocks_table[i]).min_cand();

                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("sum_two_3 >: удаляем в блоке " + i + " у ячейки " + 0 + " минимальный кандидат " + temp + " в начале блока\n");
                            }
                            erase_cell_s_cand_for_block(i, 0, temp);
                        }
                    }
                }
            }
        }
Example #12
0
        void check_set_single()
        {
            bool l_d = false;

            if (g_d && l_d)
            {
                CallBackMy.callbackEventHandler("Метод №1: check_set_single\n");
            }
            //кандидат - одиночка
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (matrix[i, j] == 0)
                    {
                        int count    = 0;
                        int last_pos = -1;
                        for (int k = 0; k < n; k++)
                        {
                            if (candidates[i, j, k])
                            {
                                count++;
                                if (count > 1)
                                {
                                    last_pos = -1;
                                    break;
                                }
                                last_pos = k;
                            }
                        }
                        if (count == 1)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("Заполняем ячейку-одиночку (" + i + ", " + j + ") значением " + candidates[i, j, last_pos] + "\n");
                            }
                            set_cell(i, j, last_pos + 1);
                        }
                    }
                }
            }

            //единственный кандидат в строке\столбце
            for (int k = 0; k < n; k++)
            {
                for (int iter = 0; iter < n; iter++)
                {
                    //для строк
                    int count    = 0;
                    int last_pos = -1;
                    for (int i = 0; i < n; i++)
                    {
                        if (candidates[i, iter, k])
                        {
                            count++;
                            if (count > 1)
                            {
                                last_pos = -1;
                                break;
                            }
                            last_pos = i;
                        }
                    }
                    if (count == 1 && matrix[last_pos, iter] == 0)
                    {
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("Заполняем ячейку (" + last_pos + ", " + iter + ") значением " + (k + 1) + ", т.к. это единственный кандидат в столбце" + "\n");
                        }
                        set_cell(last_pos, iter, k + 1);
                    }
                    //для столбцов
                    count    = 0;
                    last_pos = -1;
                    for (int j = 0; j < n; j++)
                    {
                        if (candidates[iter, j, k])
                        {
                            count++;
                            if (count > 1)
                            {
                                last_pos = -1;
                                break;
                            }
                            last_pos = j;
                        }
                    }
                    if (count == 1 && matrix[iter, last_pos] == 0)
                    {
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("Заполняем ячейку (" + iter + ", " + last_pos + ") значением " + (k + 1) + ", т.к. это единственный кандидат в строке" + "\n");
                        }
                        set_cell(iter, last_pos, k + 1);
                    }
                }
            }
        }
Example #13
0
        void optimization_blocks()
        {
            //нужно дописать внутри исключение полностью закрытых, бесполезных для анализа блоков
            bool l_d = false;

            //упрощение блоков
            for (int i = 0; i < blocks_table.Count; i++)
            {
                ArrayList pos_for_deleting = new ArrayList();
                //подсчет вектора переходов
                int       last             = 0;
                ArrayList change_positions = new ArrayList();
                for (int j = 0; j < ((block)blocks_table[i]).cells_mas.Count; j++)
                {
                    int temp = ((block_cell)(((block)blocks_table[i]).cells_mas)[j]).value;
                    if (temp > last)
                    {
                        last = temp;
                        change_positions.Add(j);
                    }
                }

                int count = 0;
                //перебираем содержимое вектора переходов
                for (int j = 0; j < change_positions.Count - 1; j++)
                {
                    bool flag_delete = false;
                    //перебираем ячейки от начала до очередного элемента вектора переходов
                    for (int k = 0; k < (int)change_positions[j + 1]; k++)
                    {
                        //перебираем кандидаты от последнего кандидата до size -- т.е. ищем ячейки, способные закрыть отрезок стенкой
                        for (int candd = ((block_cell)(((block)blocks_table[i]).cells_mas)[(int)change_positions[j]]).value; candd < n; candd++)
                        {
                            if (((block)blocks_table[i]).is_cell_have_a_candidate(k, candd))
                            {
                                flag_delete = true;
                            }
                        }
                    }
                    //метим ячейки, которые нужно удалить
                    if (!flag_delete)
                    {
                        count++;
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("Удаляем в блоке " + i + ": ");
                        }
                        for (int k = (int)change_positions[j]; k < (int)change_positions[j + 1]; k++)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler(" " + k);
                            }
                            pos_for_deleting.Add(k);
                        }
                        if (g_d && l_d)
                        {
                            CallBackMy.callbackEventHandler("\n");
                        }
                    }
                }

                //дописать что-то, что исключит 3 | 4 0 0 0 0 6

                //если мы вообще что-нибудь отметили для удаления
                if (pos_for_deleting.Count > 0)
                {
                    if (g_d && l_d)
                    {
                        CallBackMy.callbackEventHandler("\nДо удаления, блок " + i + ": ");
                    }
                    if (g_d && l_d)
                    {
                        ((block)blocks_table[i]).print();
                    }
                    //удаляем в обратном порядке отмеченное в pos_for_deleting и снижение суммы на count
                    for (int j = pos_for_deleting.Count - 1; j >= 0; j--)
                    {
                        ((block)blocks_table[i]).cells_mas.RemoveAt((int)pos_for_deleting[j]);
                    }
                    ((block)blocks_table[i]).sum -= count;
                    if (g_d && l_d)
                    {
                        CallBackMy.callbackEventHandler("После удаления, блок " + i + ": ");
                    }
                    if (g_d && l_d)
                    {
                        ((block)blocks_table[i]).print();
                    }
                    if (g_d && l_d)
                    {
                        CallBackMy.callbackEventHandler("________________________________\n");
                    }
                }
            }
            for (int i = blocks_table.Count - 1; i >= 0; i--)
            {
                //проверяем, может это блок вообще больше не нужен, если так - то удаляем нахер!
                if (((block)blocks_table[i]).cells_mas.Count <= 2)
                {
                    if (g_d && l_d)
                    {
                        CallBackMy.callbackEventHandler("Совсем удаляем блок " + i + " за бесполезностью\n");
                    }
                    blocks_table.RemoveAt(i);
                }
            }
        }
Example #14
0
        void min_stairs()
        {
            bool l_d = true;

            //проверка условия, два пустых места сначала, наличие в конце чего-нибудь - убирание кандидатов лесенкой, начиная со второго
            for (int i = 0; i < blocks_table.Count; i++)
            {
                if (((block)blocks_table[i]).sum == ((block)blocks_table[i]).calc_real_sum() + ((block)blocks_table[i]).calc_empty_places_until_noempty() &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[0])).value == 0 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[1])).value == 0 &&
                    ((block)blocks_table[i]).is_all_empty(((block)blocks_table[i]).cells_mas.Count - 1)
                    )
                {
                    int min_cand = 0;
                    for (int j = 0; j < ((block)blocks_table[i]).cells_mas.Count; j++)
                    {
                        //в каждой ячейке блока: сначала находим следующий первый за минимумом кандидат
                        for (int k = 0; k < ((block_cell)((block)blocks_table[i]).cells_mas[j]).candidates.Count; k++)
                        {
                            int temp = (int)((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates[k];
                            if (temp > min_cand)
                            {
                                min_cand = temp;
                                break;
                            }
                        }
                        //проверка на необходимость пробега
                        bool flag = false;
                        for (int k = ((block_cell)((block)blocks_table[i]).cells_mas[j]).candidates.Count - 1; k >= 0; k--)
                        {
                            int temp = (int)((block_cell)((block)blocks_table[i]).cells_mas[j]).candidates[k];
                            if (temp < min_cand)
                            {
                                if (is_cell_in_block_have_a_candidate(i, j, temp))
                                {
                                    flag = true;
                                    break;
                                }
                            }
                        }
                        //удаляем в строке все кандидаты, меньше минимума, проход обратный
                        if (flag)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("min_stairs >: исключаем кандидаты блока " + i + " лесенкой\n");
                            }
                            for (int k = ((block_cell)((block)blocks_table[i]).cells_mas[j]).candidates.Count - 1; k >= 0; k--)
                            {
                                int temp = (int)((block_cell)((block)blocks_table[i]).cells_mas[j]).candidates[k];
                                if (temp < min_cand)
                                {
                                    if (g_d && l_d)
                                    {
                                        CallBackMy.callbackEventHandler(" (" + i + ", " + j + "): " + temp + "\n");
                                    }
                                    if (i == 1 && j == 1 && temp == 1)
                                    {
                                        int a = 0;
                                    }
                                    erase_cell_s_cand_for_block(i, j, temp);
                                }
                            }
                        }
                    }
                }
            }
        }
Example #15
0
        void max_stairs()
        {
            bool l_d = true;

            //исключение кандидатов лесенкой, начиная с ближайшего к первому ненулевому
            for (int i = 0; i < blocks_table.Count; i++)
            {
                if (((block)blocks_table[i]).sum == ((block)blocks_table[i]).calc_real_sum() + ((block)blocks_table[i]).calc_empty_places_until_noempty() &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[0])).value == 0 &&
                    ((block_cell)(((block)blocks_table[i]).cells_mas[1])).value == 0 &&
                    ((block)blocks_table[i]).is_all_empty(((block)blocks_table[i]).cells_mas.Count - 1)
                    )
                {
                    int max_cand = n;
                    for (int j = ((block)blocks_table[i]).calc_empty_places_until_noempty() - 1; j >= 0; j--)
                    {
                        //в каждой ячейке блока: сначала находим следующий первый за максимумом кандидат
                        for (int k = ((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates.Count - 1; k >= 0; k--)
                        {
                            int temp = (int)((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates[k];
                            if (temp < max_cand)
                            {
                                max_cand = temp;
                                break;
                            }
                        }
                        //проверка на необходимость пробега
                        bool flag = false;
                        for (int k = 0; k < ((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates.Count; k++)
                        {
                            int temp = (int)((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates[k];
                            if (temp > max_cand)
                            {
                                if (is_cell_in_block_have_a_candidate(i, j, temp))
                                {
                                    flag = true;
                                    break;
                                }
                            }
                        }
                        //удаляем в строке все кандидаты, большие максимума, проход обратный обратному - т.е. нормальный
                        if (flag)
                        {
                            if (g_d && l_d)
                            {
                                CallBackMy.callbackEventHandler("max_stairs >: исключаем кандидаты блока " + i + " лесенкой\n");
                            }
                            for (int k = 0; k < ((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates.Count; k++)
                            {
                                int temp = (int)((block_cell)(((block)blocks_table[i]).cells_mas[j])).candidates[k];
                                if (temp > max_cand)
                                {
                                    if (g_d && l_d)
                                    {
                                        CallBackMy.callbackEventHandler(" (" + i + ", " + j + "): " + temp + "\n");
                                    }
                                    erase_cell_s_cand_for_block(i, j, temp);
                                }
                            }
                        }
                    }
                }
            }
        }