Имя: Пароль:
IT
 
Алгоритм получения комбинации строк
0 Balabass
 
15.09.17
07:37
Коллеги, извините, но нид хелп. Не соображу как оптимально построить алгоритм сложения строк.

Исходные данные:
Массив[3]

1 = а
2 = б
3 = с

Надо перебрать все варианты возможных комбинаций длинною от 1 до 3х знаков и получить в результате таблицу

а
б
в
аа
аб
ав
ба
бб
бв
ва
вб
вв
ааа
ааб
и т.д.

Буду признателен за функцию комбинаторики.
Ключевая особенность - не получать на ВОЗВРАТ таблицу со всеми вариантами, а получать СТРОКУ, следующую по номеру комбинации.
1 1dvd
 
15.09.17
07:47
как-то так


ДлинаМассива = 3;

Мас = Новый Массив(ДлинаМассива);
Мас[0] = "а";
Мас[1] = "б";
Мас[2] = "с";

Номер = 20;

Н1 = Номер % ДлинаМассива;
Н2 = Цел(Номер / ДлинаМассива) % ДлинаМассива;
Н3 = Цел(Цел(Номер / ДлинаМассива) / ДлинаМассива);

Результат = Мас[Н1] + Мас[Н2] + Мас[Н3];
2 1dvd
 
15.09.17
07:50
хотя, если тебе нужны комбинации из 1 и 2 элементов, то надо доработать
3 Йохохо
 
15.09.17
07:59
(2) перевести в троичную систему счисления?)
4 Zmich
 
15.09.17
08:18
(0).
Функция ПолучитьСтрокуПоНомеру(Номер)
  Массив = Новый Массив(3);
  Массив[0] = "а";
  Массив[1] = "б";
  Массив[2] = "в";
  Если (Номер >= 1) И (Номер <=3) Тогда
    Стр = Массив[(Номер-1)%3];
  ИначеЕсли (Номер >=4) И (Номер <=12) Тогда
    Стр = Массив[Цел((Номер - 4)/3)] + Массив[(Номер-1)%3];
  ИначеЕсли (Номер >=13) И (Номер <= 39) Тогда
    Стр = Массив[Цел((Номер - 13)/9)] + Массив[(Цел((Номер - 1)/3) - 1)%3] + Массив[(Номер-1)%3];
  Иначе
    Стр = "Номер за пределами возможных значений!";
  КонецЕсли;
  Возврат Стр;
КонецФункции

Конечно, можно доработать для произвольного числа символов, но лень.
5 v77
 
15.09.17
08:30
6 Ненавижу 1С
 
гуру
15.09.17
09:03
может немного поможет, надо допиливать:

https://naf2000.blogspot.ru/2015/06/1-82.html
7 Ёпрст
 
15.09.17
09:12
(0)
пихай в запрос и кросс джоин
8 Широкий
 
15.09.17
09:13
Детский сад. В таблицу и полное соединение
9 Широкий
 
15.09.17
09:17
ВЫБРАТЬ
    "a" КАК Буква
ПОМЕСТИТЬ Алфавит

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "b"

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "c"

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ""
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Алфавит1.Буква + Алфавит2.Буква + Алфавит3.Буква КАК Слово
ИЗ
    Алфавит КАК Алфавит1,
    Алфавит КАК Алфавит2,
    Алфавит КАК Алфавит3

УПОРЯДОЧИТЬ ПО
    Алфавит1.Буква,
    Алфавит2.Буква,
    Алфавит3.Буква
10 Ненавижу 1С
 
гуру
15.09.17
09:20
(9)это не полное соединение, а внутреннее
11 Ненавижу 1С
 
гуру
15.09.17
09:23
+(9) немного улучшу:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Алфавит1.Буква + Алфавит2.Буква + Алфавит3.Буква КАК Слово
ИЗ
    Алфавит КАК Алфавит1,
    Алфавит КАК Алфавит2,
    Алфавит КАК Алфавит3
ГДЕ  Алфавит1.Буква + Алфавит2.Буква + Алфавит3.Буква<>""  

УПОРЯДОЧИТЬ ПО
    Алфавит1.Буква + Алфавит2.Буква + Алфавит3.Буква
12 Ёпрст
 
15.09.17
09:25
(10) это cross join
13 Йохохо
 
15.09.17
09:25
в (0) "Ключевая особенность - не получать на ВОЗВРАТ таблицу со всеми вариантами, а получать СТРОКУ, следующую по номеру комбинации."
14 Широкий
 
15.09.17
09:26
(10) Согласен, внутреннее.
(11) Доведу до идеала

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    Результат.Слово КАК Слово
ИЗ
    (ВЫБРАТЬ
        Алфавит1.Буква + Алфавит2.Буква + Алфавит3.Буква КАК Слово
    ИЗ
        Алфавит КАК Алфавит1,
        Алфавит КАК Алфавит2,
        Алфавит КАК Алфавит3) КАК Результат
ГДЕ
    Результат.Слово <> ""

УПОРЯДОЧИТЬ ПО
    Слово
15 Ёпрст
 
15.09.17
09:27
(14) да не иннер это, а кросс.
16 Ёпрст
 
15.09.17
09:27
иннер будет, если условие наложить
17 Вафель
 
15.09.17
09:31
+1 к последнему элементу массива, если = 3 то +1 ко второму,а последний  = 0.
Элементарный алгоритм
18 Широкий
 
15.09.17
09:32
(15) В скуле - да. По понятиям 1с - это внутреннее соединение.
19 Широкий
 
15.09.17
09:38
Не поленился в профайлер слазить:

SELECT DISTINCT
#V8TblAli1_Q_002_T_001._Q_001_F_000 AS _sf_1
FROM
(
SELECT
#T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_001._Q_000_F_000 + #T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_002._Q_000_F_000 + #T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_003._Q_000_F_000 AS _Q_001_F_000
FROM
#tt2 #T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_001 WITH(NOLOCK)
INNER JOIN #tt2 #T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_002 WITH(NOLOCK)
ON 0 = 0
INNER JOIN #tt2 #T55cd2562e102435c8a0e2eb85a5a3fbf_Q_001_T_003 WITH(NOLOCK)
ON 0 = 0
) #V8TblAli1_Q_002_T_001
WHERE
#V8TblAli1_Q_002_T_001._Q_001_F_000 <> CAST(@P1 AS NVARCHAR(1))
ORDER BY
_sf_1


1с его в inner транслирует
20 Ёпрст
 
15.09.17
09:42
(19) см. (16)
21 Широкий
 
15.09.17
09:45
(20) условия в 1с запросе нет, но в скуле все равно inner
22 Михаил Козлов
 
15.09.17
09:53
Почему не (3)?
Только нужно иметь в виду, что это будут 3-х символьные значения. Нужно к ним добавить 1 и 2-х символьные.
Всего: 3+9+27 = 39 значений.
23 Йохохо
 
15.09.17
09:56
(22) 2 это односимвольное значение, 4 двух, все хорошо
(20) в книжке селф джойн разворачивают как иннер
24 Zmich
 
15.09.17
10:19
(14). В таком варианте возможно слово "a b", т.е. с пробелом посередине. Плюс слова "ab " и " ab" (с пробелом в начале и в конце) будут выбраны, как различные.
25 Широкий
 
15.09.17
10:23
(24) Там пустая строка, не пробел. Посмотри сам
26 Zmich
 
15.09.17
10:26
(25). А, ок тогда, всё верно.
27 1dvd
 
15.09.17
10:26
(25) один хрен будут повторяться
28 Zmich
 
15.09.17
10:47
(27). Повторяться не будут (ВЫБРАТЬ РАЗЛИЧНЫЕ).
(14). Думаю, что сортировка правильно работать не будет. Порядок в выборке, по-видимому, будет такой: а, аа, ааа, ааб, аав, аб, аба, абб и т.д., а не такой, как нужно автору. Как по номеру предполагается слово получать?
29 RS2017
 
15.09.17
11:00
Запрос для данной задачи - бред. Он явно загнется при вводе например 99999999999. Правильная идея в (4), реализация правда слишком линейная)).
30 Ненавижу 1С
 
гуру
15.09.17
11:02
(15) йопта:

CROSS JOIN это INNER JOIN ON (1=1)
31 Ёпрст
 
15.09.17
11:12
(30) я в курсе. Но правильно, называть вещи своими именами
32 Филиал-msk
 
15.09.17
11:13
Какая пятничная ветка...

Думаете, 1С при присвоении следующего буквенного номера/кода тоже джоины и декартовы произведения прокручивает? (:
33 Широкий
 
15.09.17
11:36
(29) Молодой ты еще.
Я попробовал на 12 символах. Не загнулась. Отработала за 16 сек (с учетом вывода результата в табличную часть)
34 тарам пам пам
 
15.09.17
12:01
эхх, погромисты....
бОльшая часть даже условие не дочитала (про то, что не нужно при вызове функции формировать полную таблицу)
задача элементарная же. Цифры слева - индексы исходного массива, цифры справа - число, переданное в функцию:
0 = а = 0
1 = б = 1
2 = в = 2
00 = аа = 3
01 = аб = 4
02 = ав = 5
10 = ба = 6
11 = бб = 7
12 = бв = 8
20 = ва = 9
21 = вб = 10
22 = вв = 11
000 = ааа = 12
001 = ааб = 13
002 = аав = 14
010 = аба = 15
011 = абб = 16
012 = абв = 17
020 = ава = 18
021 = авб = 19
022 = авв = 20
100 = баа = 21
101 = баб = 22
102 = бав = 23
110 = бба = 24
111 = ббб = 25
112 = ббв = 26
120 = бва = 27
121 = бвб = 28
122 = бвв = 29
200 = ваа = 30
201 = ваб = 31
202 = вав = 32
210 = вба = 33
211 = вбб = 34
212 = вбв = 35
220 = вва = 36
221 = ввб = 37
222 = ввв = 38

если внимательно посмотреть, то индексы массива можно получить следующим образом - делим исходное число на 3, остаток записываем, вычитаем из результата 1, делим результат на 3, записываем остаток и т. д.

Примеры:
7
7 / 3 = 2, остаток 1
(2-1) / 3 = 0, остаток 1

20
20 / 3 = 6, остаток 2
(6-1) / 3 = 1, остаток 2
(1-1) / 3 = 0, остаток 0

34
34 / 3 = 11, остаток 1
(11-1) / 3 = 3, остаток 1
(3-1) / 3 = 0, остаток 2

15:
15 / 3 = 5, остаток 0
(5-1) / 3 = 1, остаток 1
(1-1) / 3 = 0, остаток 0,

30:
30 / 3 = 10, остаток 0
9 / 3 = 3, остаток 0
2 / 3 = 0, остаток 2
35 Zmich
 
15.09.17
12:13
(34). В (4) всё это и сделано, идея еще в (1) была.
36 RS2017
 
15.09.17
12:21
(33) 3^12 = 531441 как бы в на 6-7 порядков меньше чем 99999999999. Или ты считаешь, что 16*10^6 секунд (предполагаем, что время будет расти линейно) это приемлемое время? Особенно при наличии решения менее чем за 0.001 сек (это на 1С).
37 тарам пам пам
 
15.09.17
13:37
(35) в (4) жестко прописаны все границы. Для каждой новой длины массива писать новый алгоритм? В (1) нечто более близкое, но там не ясно, как алгоритм распространить для произвольной длины массива.
38 RS2017
 
15.09.17
13:49
(37) всё там ясно: сначала определяем число разрядов(последовательно вычитая 3^N), потом остаток выводим в троичной системе с лидирующими нулями до нужного числа разрядов.
Естественно будет несколько циклов, а не как в (4)
39 Йохохо
 
15.09.17
14:29
(38) Используй рекурсию Люк!
40 Вафель
 
15.09.17
14:31
вообще по идее нужна функция, которая на входе берез массив [1, 2, 3] на выходе получать массив [1, 3, 1]
41 RS2017
 
15.09.17
14:40
(39) можно и без рекурсии, можно и с рекурсией если очень хочется. Здесь она абсолютным злом не будет.
(40) ничего пе понятно. На входе число [4], на выходе строка "aa"
42 Вафель
 
15.09.17
14:42
(41) Зачем число? лишний раз только в другую систему переводить
43 Вафель
 
15.09.17
14:42
тут счетчик не число, а массив
44 RS2017
 
15.09.17
14:44
(42) "Зачем число?" это условие задачи, прочитай последнее предложение (0)
Я тебя не очень понимаю, расшифруй пример в (40)
45 Вафель
 
15.09.17
14:45
(44) Я смотрю на шаг дальше )))
46 Йохохо
 
15.09.17
14:53
(4) а красивая идея, тлько код будет коряво смотреться
47 Йохохо
 
15.09.17
14:58
вообще олскульно через код символа, инкремент и обработку переполнения разряда, лепота
48 RS2017
 
15.09.17
15:05
(45) Так поясни, я так далеко не вижу). Хотя я вижу решение от начала и до конца.

(46) там сейчас коряво. Что там будет коряво с двумя циклами, не представляю. На вкус и цвет...
49 RS2017
 
15.09.17
15:05
(47) Это как "инкремент", перебирать подряд?
50 Вафель
 
15.09.17
15:10
(48) Типо такого
Счетчик = [1, 1, 1];
Пока Счетчик <= [3, 3, 3] Цикл
    Сообщить(СобратьСтроку(Счетчик));
    Следующий(Счетчик);
КонецЦикла;
51 Balabass
 
15.09.17
15:18
Участникам беседы респект и уважение.
В (0) пример достаточно простой - для понимания задачи.
Я увидел варианты решения, пойду покапаю.
52 RS2017
 
15.09.17
15:19
(50) ты опять перебор всех значений для 3 разрядов? Для 3 разрядов можно ручками в массив записать. В (0) задача по произвольному индексу получить "типа троичное" представление.
53 Вафель
 
15.09.17
15:25
Нужно у ТС спросить.
Доступ по индексу нужен или построчное формирование значений.
54 Вафель
 
15.09.17
15:25
Я вангую, что, все-таки, построчное формирование
55 RS2017
 
15.09.17
15:35
(54) (53) прочитай последнее предложение (0)
56 Balabass
 
15.09.17
15:40
(53)  Построчное.
57 Вафель
 
15.09.17
15:44
(55) Какчай уровень телепатии, джуниор )))
58 RS2017
 
15.09.17
15:45
(56) т.е. тебе всё-таки надо "получать на ВОЗВРАТ таблицу"?
59 Вафель
 
15.09.17
15:46
(58) Всю заранее не нужно. А ля перебор паролей. где-то там посередине есть нужная комбинация
60 RS2017
 
15.09.17
15:50
(57) )))красавец, из серии "послушай женщину и сделай наоборот"
(59) т.е. никакого номера комбинации не существует? тогда действительно проще перебирать запросом.
61 Вафель
 
15.09.17
16:16
Накидал алгоритм перебора
https://gist.github.com/a-sitnikov/aed4a8360622e80890e6750756b785bf
62 Йохохо
 
15.09.17
22:18
непонятен такой уровень решения, Ненавижу 1с даже в сових темах предлагает не оптимальные решения
Семнадцать из трёх тысяч