![]() |
|
Оптимальный алгоритм хитрого перебора | ☑ | ||
---|---|---|---|---|
0
conscious
04.10.22
✎
20:36
|
Есть массив из 6 символов: ABCDEF
1. Нужно получить все возможные массивы (порядок элементов не учитывать), длинной по 5 символов, удаляя из исходного массива по одному разному символу (т.е., должно получиться: ABCDE, ABCDF, ABCEF, ABDEF, ACDEF, BCDEF) 2. То же самое, что в п. 1, но нужно получать массивы по 4 символа, удаляя по два (ABCD, ABEF, ABCF, ABCE, ...) 3. Как итог выполнения п. 1 и п. 2 должна получиться функция, в которую передается массив элементов (ABCDEF) и количество элементов, которое должно быть в массивах на выходе. Возвращаемое значение - массив массивов (ну, для наглядности, можно выводить результат с помощью Сообщить()). Такая вот головоломка. Кому не лень, поделитесь идеями реализации. |
|||
1
H A D G E H O G s
04.10.22
✎
20:42
|
Даже не знаю, что тут может быть трудного
|
|||
2
PR
04.10.22
✎
20:58
|
(0) У меня хрень похожей сложности была при приеме на первую работу
Без трех лет стажа на Мисте, замечу Позор в общем |
|||
3
conscious
04.10.22
✎
21:03
|
(2) Я сделал по-своему. Но оно медленное. Может, кто-то более быстрый алгоритм предложит...
|
|||
4
Злопчинский
04.10.22
✎
21:04
|
(3) ну так в (0) не стоит критерий "чтобы быстро"
|
|||
5
Злопчинский
04.10.22
✎
21:06
|
(0) можно например не удалять из исходного массива. а складывать из элементов исходного массива, пропуская ненужное
|
|||
6
conscious
04.10.22
✎
21:06
|
(4) В заголовке "Оптимальный"...
|
|||
7
Злопчинский
04.10.22
✎
21:07
|
(6) критерий оптимальносьти может быть разный. Пусть тогда будет оптимальный по скорости, раз уж так
|
|||
8
Garykom
гуру
04.10.22
✎
21:10
|
(1) Сделай запросами?
|
|||
9
RomanYS
04.10.22
✎
21:21
|
(3) без указания границ условий говорить о быстроте и оптимальности смысла нет. Для 6 элементов всё будет быстро
|
|||
10
NorthWind
04.10.22
✎
21:27
|
ну, кстати заметить, придется вспомнить институтскую комбинаторику, в частности, генерацию сочетаний. Я бы без обращения к инету не накалякал бы ну или потратил достаточно много времени.
|
|||
11
NorthWind
04.10.22
✎
21:28
|
когда-то оно писалось курсачами чуть не в каждом семестре, но с тех пор 20 лет прошло
|
|||
12
Asmody
04.10.22
✎
21:31
|
(2) Я прошёл собес? |
|||
13
mistеr
04.10.22
✎
21:31
|
(11) Когда-то оно давалось даже на школьных олимпиадах
|
|||
14
mistеr
04.10.22
✎
21:32
|
(0) Погугли "перебор с возвратом"
|
|||
15
RomanYS
04.10.22
✎
21:32
|
(12) Где задать количество требуемых элементов))))?
|
|||
16
Asmody
04.10.22
✎
21:33
|
(15) В тексте запроса. Ну или написать функцию, которая будет генерить текст запроса. Это элементарно
|
|||
17
Krendel
04.10.22
✎
21:33
|
(13) Вряд ли, я это проходил в 9 классе на бейсике
|
|||
18
Asmody
04.10.22
✎
21:35
|
(17) это банальный цикл в цикле с динамической границей и .. да и всё!
|
|||
19
RomanYS
04.10.22
✎
21:35
|
(16) так и банальный перебор "это элементарно" :). Ну и вопрос оптимальности остается открытым
|
|||
20
Asmody
04.10.22
✎
21:37
|
(19) какая, нафиг "оптимальность"?
|
|||
21
RomanYS
04.10.22
✎
21:39
|
(20) это к (3). Мой вопрос по этому поводу в (9)
|
|||
22
mistеr
04.10.22
✎
21:42
|
(21) Оптимальность можно задать по количеству операций. Отношение общего количества итераций к количеству элементов на выходе.
|
|||
23
Garykom
гуру
04.10.22
✎
22:12
|
что можно придумать лучше и проще двух вложенных циклов?
http://www.gilev.ru/алгоритм-перебора-всех-возможных-соч/ |
|||
24
conscious
04.10.22
✎
23:08
|
(12) А где функция, в которую передаётся массив и количество элементов в массивах на выходе?
|
|||
25
conscious
04.10.22
✎
23:13
|
Я такое вот написал:
&НаСервереБезКонтекста
Может, кто-то предложит более "правильный", красивый вариант?.. |
|||
26
conscious
04.10.22
✎
23:16
|
(25) Парсер кода "съел" закрывающую скобку в строке "Процедура Выполнить_(Команда//кнопка на форме".
|
|||
27
RomanYS
05.10.22
✎
00:03
|
(23) офигенно круто, только задачу (0) не решает. Попробуй на 100 элементах запустить... а сама по себе задача вполне решаема для 99, 98 и даже 97 из 100, но не этим алгоритмом.
|
|||
28
Конструктор1С
05.10.22
✎
03:04
|
(8) нафига запросами???
|
|||
29
Михаил Козлов
05.10.22
✎
07:41
|
Число элементов в массиве C(n,k) - число сочетаний (= n!/(k!*(n-k)!) может быть большим (при заданном n максимально для k = n/2 и растет как n^2/SQRT(n)).
Трудоемкость меньше этого не получишь. |
|||
30
SweetaAngel
05.10.22
✎
08:12
|
(23) Это не про это. Я еще тупил стараясь понять код, пока описание не прочитал.
Функция ВсеПодмножества(Множество) Ответ = Новый Массив; Ответ.Добавить(Новый СписокЗначений); Для ИндексЭлемента = 0 По Множество.Количество() - 1 Цикл Для ИндексВарианта = 0 По Ответ.Количество() - 1 Цикл Ответ.Добавить(Ответ[ИндексВарианта].Скопировать()); Ответ[ИндексВарианта].Добавить(Множество[ИндексЭлемента]) КонецЦикла КонецЦикла; Возврат Ответ КонецФункции &НаКлиенте Процедура Команда1(Команда) мсМножество = Новый Массив(); мсМножество.Добавить("А"); мсМножество.Добавить("Б"); мсМножество.Добавить("В"); мсМножество.Добавить("Г"); мсМножество.Добавить("Д"); мсМножество.Добавить("Е"); мсРеузльт = ВсеПодмножества(мсМножество); чНПП = 0; Для каждого элмРез из мсРеузльт Цикл сВариант = ""; Для Каждого элмВар из элмРез Цикл сВариант = сВариант + " " + элмВар.Значение; КонецЦикла; Сообщить("" + чНПП + " = " + элмРез); чНПП = чНПП + 1; КонецЦикла; КонецПроцедуры |
|||
31
НафНаф
05.10.22
✎
08:18
|
(0) если нужно именно количество элементов только (просто число) то это N!/(N-K)!, где надо вычеркнуть K-элементов из последовательности N. Правда, без учета того, что в последовательности элементы могут повторяться
|
|||
32
Bigbro
05.10.22
✎
08:24
|
в том то и дело что не нужно количество почему-то.
у нужны сами значения но при этом не все, а только то количество которое мы запрашиваем. причем пофиг какие именно будут возвращаться видимо, что странно. потому что алгоритм можно сделать таким что для близких чисел будут возвращаться совершенно разные массивы результатов. например Ф(АБСДЕФ,1) = [АБСДЕ] Ф(АБСДЕФ,2) = [БСДЕ][СДЕФ] выглядит странно. |
|||
33
Михаил Козлов
05.10.22
✎
08:31
|
В связи с этой задачей был забавный случай.
В бытность мою в ВЦ АН приходит как-то мужчина (пенсионер, работяга), которого направили к нашему нач. отдела из президиума АН и рассказывает. Я на пенсии. Иногда хожу к палатке пивка выпить. И там мужики говорят, что если купить 625 билетов Спортлото (кажется 7 из 49), то можно заполнить все возможные комбинации. Я пришел домой и попробовал на бумажке заполнять. И скоро понял, что новой комбинации не могу придумать и задумался, как же регулярно их получать. Короче, он принес пачки заполненных комбинаций для небольших значений (2 и 3, кажется). Ну и, вроде, для себя выработал "алгоритм". Послал письмо в АН: может это нужно для науки. Его к нам и направили. Вот такие работяги были в СССР. |
|||
34
NorthWind
05.10.22
✎
09:01
|
вообще странно что тут столько срача на эту тему. В яндексе все ищется за несколько секунд и даже образцы алгоритма на главной есть. Число сочетаний из N по К с перестановками и без перестановок. Для любителей теплого и лампового есть книжки, например Витольд Липский Комбинаторика для программиста.
|
|||
35
NorthWind
05.10.22
✎
09:01
|
все было придумано еще лет 50 назад, если не раньше
|
|||
36
Мимохожий Однако
05.10.22
✎
09:20
|
(34) Сюда не только по работе, но и поболтать приходят. Кто-то о бабах, а кто-то о комбинаторике )
|
|||
37
mistеr
05.10.22
✎
11:23
|
(34) Эх, как я ей дорожил в детстве, и все-таки пролюбил!..
|
|||
38
Garykom
гуру
05.10.22
✎
14:24
|
(34) Есть тонкости реализации на разных системах программирования.
И скорости работы, зависящие от какие структуры использовать и т.д. На больших количествах N и K, выгодней конечно же не запросами а передать это в ПолеHTML и там на JS вычислить Причем не простым алгоритмом а https://ru.stackoverflow.com/questions/1205413/Как-реализовать-генерацию-сочетаний-без-повторений |
|||
39
asady
05.10.22
✎
14:34
|
(0) по сути твоя задача описывает пространство чисел порядка N в разрядности M
где M - количество символов всего ABCDEF = 6 N = 5 - если исключаем 1 цифру, 4 - если исключаем 2 цифры с дополнительным фильтром на повторяющиеся цифры в числе. |
|||
40
Garykom
гуру
05.10.22
✎
14:37
|
(39) еще упомяни абелева группа и кольцо ))
|
|||
41
asady
05.10.22
✎
14:39
|
(39)+ если принять M =10 АБВГДЕЖЗИК
И N =3 То просто все числа от 012 до 987 исключая числа с повторяющимися цифрами например 012, 13, 014, 015,016, 017, 018, 019, 021, 023, 024 и т.д. |
|||
42
SweetaAngel
06.10.22
✎
07:51
|
Вспомнил молодость набросал как сумел. Насколько оптимально — не знаю
Функция Факториал(чЗначение) чРезульт = 1; Для чНом = 1 по чЗначение Цикл чРезульт = чРезульт * чНом; КонецЦикла; Возврат чРезульт; КонецФункции &НаКлиенте Процедура Команда1(Команда) чКолво = 6; чМаксимальнаяГлубина = 4; Сообщить("Планове количество результатов = " + Факториал(чКолво) / ( Факториал(чКолво - чМаксимальнаяГлубина)) ); // (= n!/((n-k)!) мсМножество = Новый Массив(чКолво + 1); Для чНПП = 0 по чКолво Цикл мсМножество[чНПП] = Символ(64 + чНПП); КонецЦикла; мсТекРезульт = Новый Массив(чМаксимальнаяГлубина + 1); мсИспользовано = Новый Массив(чКолво + 1); чНомерТекЭлемента = 0; чУровень = 1; чНППРезультат = 1; чНПП = 0; Пока чУровень > 0 Цикл //На первом уровне перебрали все варианты расчет окончен. чНомерТекЭлемента = чНомерТекЭлемента + 1; Если чНомерТекЭлемента > чКолво Тогда // На этой глубине перебрали все элементы. Очищаем использованный элемент и возвращаемся на предыдущий уровень. мсИспользовано[мсТекРезульт[чУровень]] = 0; мсТекРезульт[чУровень] = 0; чУровень = чУровень - 1; чНомерТекЭлемента = мсТекРезульт[чУровень]; Продолжить; Иначе Если мсИспользовано[чНомерТекЭлемента] <> 0 и мсИспользовано[чНомерТекЭлемента] <> Неопределено Тогда //Текущий элементы уже был использован на предыдущем уровне. Продолжить; //Этот элемент уже использован продолжаем Иначе //Найден новый элемент для этого уровня мсИспользовано[?(мсТекРезульт[чУровень]=неопределено, 0, мсТекРезульт[чУровень])] = 0; мсИспользовано[чНомерТекЭлемента] = чУровень; мсТекРезульт[чУровень] = чНомерТекЭлемента; КонецЕСли; КонецЕсли; Если чУровень < чМаксимальнаяГлубина Тогда // Если нужный уровень не достигнут идем на следющий чНомерТекЭлемента = 0; чУровень = чУровень + 1; Иначе ///////////////////// Вывод результата //////////////////////////////// сРезульт = ""; Для чНомРез = 1 по чУровень Цикл сРезульт = сРезульт + мсМножество[мсТекРезульт[чНомРез]]; КонецЦикла; Сообщить("№" + чНППРезультат +" " + сРезульт); чНППРезультат = чНППРезультат + 1; КонецЕсли; КонецЦикла; КонецПроцедуры |
|||
43
kostyan29
06.10.22
✎
10:10
|
Вот этот код в точности выполняет то, что просил и объяснял ТС.
По умолчанию он не делает все возможные перестановки в получившихся массивах, т.к. из условий задачи как-то непонятно, нужно их в итоге делать или нет. Но если нужно, то добавляет и перестановки. Функцию Перестановки не привожу, т.к. я ее просто взял с инфостарта, первая же ссылка в гугле. &НаКлиенте Функция Комбинации(масИсходный,СколькоОставить,НужныПерестановки=Ложь) массивМассивов = Новый Массив; Если СколькоОставить>=масИсходный.Количество() ИЛИ СколькоОставить<=0 Тогда //нечего тут хулиганить Возврат массивМассивов; КонецЕсли; ДопСмещение = масИсходный.Количество() - СколькоОставить - 1; индВнеш = масИсходный.Количество()-1; Пока индВнеш>=ДопСмещение Цикл времМассив = Новый Массив; Для индВнутр=0 По масИсходный.Количество() - 1 Цикл Если индВнутр<индВнеш-ДопСмещение ИЛИ индВнутр>индВнеш Тогда времМассив.Добавить(масИсходный[индВнутр]); КонецЕсли; КонецЦикла; индВнеш = индВнеш - 1; Если НужныПерестановки Тогда массивПерестановок = Перестановки(времМассив,времМассив.Количество(),Истина); Для каждого массив Из массивПерестановок Цикл массивМассивов.Добавить(массив); КонецЦикла; Иначе массивМассивов.Добавить(времМассив); КонецЕсли; КонецЦикла; Возврат массивМассивов; КонецФункции &НаКлиенте Процедура ABCDEF(Команда) Массив = Новый Массив; массив.Добавить("A"); массив.Добавить("B"); массив.Добавить("C"); массив.Добавить("D"); массив.Добавить("E"); массив.Добавить("F"); массивМассивов = Комбинации(массив,2); //просто вывод результатов Сообщение = Новый СообщениеПользователю; Для каждого массив Из массивМассивов Цикл Сообщение.Текст = ""; Для каждого символ Из массив Цикл Сообщение.Текст = Сообщение.Текст + символ; КонецЦикла; Сообщение.Сообщить(); КонецЦикла; Сообщение.Текст = "Всего результатов найдено и выведено: "+ Строка(массивМассивов.Количество()); Сообщение.Сообщить(); КонецПроцедуры |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |