burik писал(а):А что касается самого алгоритма, так вы тут так спорили по поводу оптимизации перемешивания, что я хотел обойтись без него (в любом виде), а suffle - тоже мешает
Если смущает название - можно назвать GenerateNew.
Shuffle в данном случае мешает только один раз - т.е. заполняет массив случайными неповторяющимися числами от 1 до 16. Согласись, это проще и быстрее, чем Do...Loop внутри цикла, как у тебя, причем именно случайными (насколько Rnd может быть случаен), а не j+1 в случае повторения. Далее функция Solveable проверяет массив на "решаемость". На всякий случай алгоритм (может, я чего недопонял):
Согласно ссылки на теорию, задача решаема, если количество "инверсных" фишек и номер ряда пустой ячейки - парные (т.е. обе чёт или нечёт). Инверсными фишками считаются с номерами меньше заданной. Пример из ссылки: первая фишка - 13, т.е. далее идут 12 "инверсных" фишек (1-12). Следующая - 10, за ней 9 инверсных (1-9). Далее - 11 - опять 9 инверсных (десятка стоит раньше) и т.д. Всё делается в двойном цикле (заодно запоминаем номер пустой ячейки):
- Код: Выделить всё
emptyID = 16
For i = 1 To 15
For j = i + 1 To 16
If cells(j) < cells(i) Then Solveable = Not Solveable
Next
If cells(i) = 16 Then emptyID = i
Next
Сумма нам, в принципе, ни к чему, выжно лишь чёт/нечёт - потому прибавление единички заменил на логику - все быстрее, в итоге получаем нечёт == True, чёт == False. Если пустой ряд чётный (
If (emptyID \ 4 Mod 2) = 0) - меняем True/False. Далее, если получаем False - достаточно переставить 2 любых непустых ячейки, чтобы изменить чётность. Усё. Итого - 16 операций на инициализацию + 16 перемешивание + 121 на Solveable + 1 если False. Остальное - антураж. Не знаю, может Swap через 3 XOR'а быстрее будет, чем присваивание, по размеру кода - одинаково