7.7 Помогите рассчитать уровень ветки(вложенности?, ...) 1С7.7 бух dbf

Тема в разделе "Общие вопросы "1С:Предприятие 7.7"", создана пользователем Lsr, 12 дек 2012.

  1. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Помогите рассчитать уровень ветки(вложенности?, ...) 1с7.7 бух dbf
    В математическом виде проблема выглядит она так:
    Есть таблица значений, в которой хранятся некие пары чисел. Строки пронумерованы(это не важно)
    Указываем любую строку в ТЗ и программа должна найти в этой таблице все строки, числа в которых
    не выходят за диапазон чисел в указанной паре (это легко) и надо пронумеровать полученные строки
    начиная с1 так, что бы в числах отражался уровень (вложенности, ветки ...).
    Когда всё вложено как в матрешке реализовал. А когда в одной матрешке может быть несколько самостоятельных матрешек, что-то не соображу. Тут надо как-то через рекурсию, но в ней я слаб.
    Например, программа выбрала строку 13. Просмотр начинаем сверху.
    1) 1,5 2
    2) 1,3 3
    4) 6,9 2
    7) 6,8 3
    3) 7,8 4
    6) 3,5 3
    5) 4,5 4
    8) 1,40
    9) 8,35
    10) 9,15
    11) 9,18
    12) 1,14
    13) 1,9 1
    14) 18,18
    15) 2,14

    Графически это выглядит приблизительно так:
    4 |-----| |-----|
    3 |-----------|----------| |-----------|
    2 |----------------------| |----------------|
    1 |-----|-----|-----|-----|-----|-----|-----|-----|-----
    1 2 3 4 5 6 7 8 9
    обратите внимание, что 1)нельзя сортировать данную таблицу, что бы разместить как можно больше
    строк из неё. 2) результат зависит от напрвления обхода таблицы, т.е. от того, что ляжет на второй уровень. Если второй уровень умостить значениями 1-2,2-3,3-4...8-9, то на такие основания можно положить только такие же (если все числа натуральные). Из "графика" видно, что проекции любых
    пар чисел на ось 1-9 не должны накладываться друг на друга. Если втречается более "широкая" пара, должно сформироваться сообщение о номере строке и паре, но обход должен быть продолжен до конца таблицы значений. (По размеру она не более 50 строк) На Инфостарт была информация, близкая
    к моей проблеме( http://infostart.ru/public/78285/ , Как не «попасть на миллион», решая задачу разузлования, http://infostart.ru/public/78032/ ), но я уже несколько раз "вскипятил" мозг, но не могу применить полученную информацию
    к решению моей задачи. Так же есть что-то общее с "ханойской" башней, только количество башен заранее не известно. В общем, помоги кодом, если можете.
  2. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Графически решение выглядит как в прикрепленном файле

    Вложения:

  3. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Ваш преподаватель информатики - садист и извращенец.
  4. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Согласен! Тем более, что преподаватель - реальная жизнь.
  5. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    читал минут пять - не понял суть задачи..
    ТЗ с одной колонкой или список?
  6. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Там две колонки... Третья цифра определяет группу к которой принадлежит строка. На скрине лучше видно
  7. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    Ну я скрин всосал. .а вот что подразумевалось под многомерными матрешками..
    Такая таблица на входе может быть?


    Код:
    Функция ИнициализироватьТЗ()
    
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("ДиапазонС");
    ТЗ.НоваяКолонка("ДиапазонПо");
    
    Возврат ТЗ;
    
    КонецФункции;	 
    Процедура ДобавитьСтрокуТЗ(ТЗ,ДиапазонС,ДиапазонПо)
    
    ТЗ.НоваяСтрока();
    ТЗ.ДиапазонС = ДиапазонС;
    ТЗ.ДиапазонПо = ДиапазонПо;
    
    КонецПроцедуры
    
    Процедура ПриОткрытии()
    
    ТЗ = ИнициализироватьТЗ();
    ДобавитьСтрокуТЗ(ТЗ,1,5);
    ДобавитьСтрокуТЗ(ТЗ,1,3);
    ДобавитьСтрокуТЗ(ТЗ,6,9);
    
    ТЗ2 = ИнициализироватьТЗ();
    ДобавитьСтрокуТЗ(ТЗ2,5,7);
    ДобавитьСтрокуТЗ(ТЗ2,1,4);
    
    ДобавитьСтрокуТЗ(ТЗ,ТЗ2,9);
    
    
    КонецПроцедуры
  8. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    думаю речь идет о сортировке вложенного диапазона....
    Ух... Самому бы понять что сказал
  9. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    //*******************************************
    Функция ИнициализироватьТЗ()

    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("ДиапазонС");
    ТЗ.НоваяКолонка("ДиапазонПо");

    Возврат ТЗ;
    КонецФункции


    Процедура ДобавитьСтрокуТЗ(ТЗ, ДиапазонС, ДиапазонПо)

    ТЗ.НоваяСтрока();
    ТЗ.ДиапазонС = ДиапазонС;
    ТЗ.ДиапазонПо = ДиапазонПо;
    КонецПроцедуры

    Процедура ПриОткрытии()

    ТЗ = ИнициализироватьТЗ();
    ДобавитьСтрокуТЗ(ТЗ,1,5);
    ДобавитьСтрокуТЗ(ТЗ,1,3);
    ДобавитьСтрокуТЗ(ТЗ,6,9);

    ТЗ2 = ИнициализироватьТЗ();
    ДобавитьСтрокуТЗ(ТЗ2,5,7);
    ДобавитьСтрокуТЗ(ТЗ2,1,4);

    ДобавитьСтрокуТЗ(ТЗ,ТЗ2,9);

    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    Сообщить("ТЗ.ДиапазонС="+ТЗ.ДиапазонС+", ДиапазонПо="+ТЗ.ДиапазонПо);
    КонецЦикла;

    ТЗ2.ВыбратьСтроки();
    Пока ТЗ2.ПолучитьСтроку()=1 Цикл
    Сообщить("ТЗ2.ДиапазонС="+ТЗ2.ДиапазонС+", ТЗ2.ДиапазонПо="+ТЗ2.ДиапазонПо);
    КонецЦикла;

    КонецПроцедуры

    Получили:
    ТЗ.ДиапазонС=1, ДиапазонПо=5
    ТЗ.ДиапазонС=1, ДиапазонПо=3
    ТЗ.ДиапазонС=6, ДиапазонПо=9
    ТЗ.ДиапазонС=ТаблицаЗначений, ДиапазонПо=9
    ТЗ2.ДиапазонС=5, ТЗ2.ДиапазонПо=7
    ТЗ2.ДиапазонС=1, ТЗ2.ДиапазонПо=4

    Очевидно, что про две таблицы речь не шла. Что бы стало понятней, забудем о матрешках. Возьмем в руки лист бумаги и карандаш.
    Изначально есть ТЗ с двумя столбиками. Пусть 1-й столбец "ДиапазонС", а второй "ДиапазонПо" , но я назвал бы Х1 и Х2, так как числа будут проецироваться на ось Х .Третий должна заполнить программа, но для наглядности я уже заполнил. Для первой строки имеем: ДиапазонС=1, ДиапазонПо=5. Пусть "базовой" строкой будет №13. Поход ведем сверху вниз.

    1) 1,5 2
    2) 1,3 3
    4) 6,9 2
    7) 6,8 3
    3) 7,8 4
    6) 3,5 3
    5) 4,5 4
    8) 1,40
    9) 8,35
    10) 9,15
    11) 9,18
    12) 1,14
    13) 1,9 1
    14) 18,18
    15) 2,14

    Начертите посреди листа линию длиной 9 см (1-9 см стр№13). Потом на втором уровне(на 1см выше) начертите первую пару (1-5) из строки №1, потом из строки №2 (1-3). Но это (1-5см)место уже занято. Поскольку (1-3) меньше (1-9) и меньше (1-5). поэтому рисуем в третьем уровне. Берем следующую пару из ТЗ. (6-9)-она вписывается на втором уровне над (1-9). Далее (6-8). На втором уровне место занято, но вписывается на третьем. Далее(7-8) на третьем уровне место занято, но вписывается на четвертом. Для пары(3-5)есть местечко над площадкой (1-5) рядом с (1-3). Ну и (4-5) может разместиться только над (3-5). При этом номер уровня для выбранной строки заносим в эту же строку строку ТЗ в столбец №3.
    Если втречается более "широкая" пара, которая пересекается с соседом больше чем точкой или шире предыдущего уровня - пропустить. В 3-м столбце ничего не будет. И так до конца ТЗ. Саму себя (строка №13) пропустить. Хотя я думаю, что можно остановиться на "базовой" строке.
    Во сколько написал, а код получится в 10 строчек.
  10. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Алгоритм без привязки к языку.
    Есть 2 столбца А,Б. В базовой строке находятся два значения А и Б
    В "Базовой" строке пишем в третий столбец 1
    Выбрали следующую строку ТЗ
    Если Аn<А или Бn>Б тогда пропустить//сравнили с 1-м уровнем
    Если Аn>А и Бn<Б тогда//такую пару имеет смысл анализировать дальше
    Если есть уровни, тогда определим какие.
    начиная с максимального уровня надо определить есть ли свободный промежуток для искомой пары (Б-А)-(Бn-Аn)-...
    Если итог больше чем "ширина" искомой пары, значит,возможно, есть свободное место и цифры из искомой пары надо сравнивать с цифрами каждой пары данного уровня. Если есть пересечение Аn<А(n1) или Бn>Б(n1) или......Аn<А(nn) или Бn>Б(nn), то в текущем уровне места для данной пары нет. Но может и найтись.
    Но! если под текущим уровнем уже есть уровень (кроме 1), надо сравнить текущую пару цифр с каждой парой цифр предыдущего уровня.
    Если (Аn<А(n-1) или Бn>Б(n-1)) для каждой пары тогда //не помещаемся.
    Если есть место в текущем уровне и не вылезли за нижний уровень, в третьем столбце пишем номер текущего уровня.
    Если не проканало, пытаемя разместить пару на новом уровне и для этого сравниваемся с предыдущим
    Если Аn>А(n-1) и Бn<Б(n-1) тогда присваиваем уровню следующий номер и записываем его в 3-м столбце текущей строки.
    Вот что-то такое я организовал, но очень много Если и циклов. Где-то сделал ошибку, но обнаружить пока не могу. Предполагаю, что используя рекурсию, код можно значительно облагородить и сделать понятней. Поэтому и обратился за помощью, а то у меня как-то очень сумбурно получается. До третьего уровня мой код работает, а потом как бог на душу положит.
  11. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    на самом деле, на работе уже набросал в каком то виде алгоритм.. немного не завершенный и смешноватый на парсинге текстовой переменной.. по хорошему надо осмыслить это все в массивах, правда (у меня там ошибка была, я заполнял по свободному диапазону а не с позиции указанной в ячейке - типа если в ячейке есть промежуток между 3 и 9 тогда туда можно вписать к примеру 1-4).. когда завтра появится немного свободного времени порешаю задачку. Хорошо что какие-то разъяснения появились, а то больше абстрактно писал..
  12. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    в общем, на бумажке нацарапал кое-что - завтра к обеду, после деклараций отпишусь :)
  13. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    спасибо.
  14. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    не так все радужно оказалось, как казалось вчера)
    но тут мое решение без рекурсии выглядит примерно так
    Код:
    Перем УровеньВложенности;
    Перем НоваяТЗ;
    
    Функция ИнициализироватьТЗ()
    
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("X1");
    ТЗ.НоваяКолонка("X2");
    ТЗ.НоваяКолонка("Уровень");
    
    Возврат ТЗ;
    
    КонецФункции	 
    Процедура ДобавитьСтрокуТаб(ТЗ,ДиапазонС,ДиапазонПо)
    
    ТЗ.НоваяСтрока();
    ТЗ.X1 = ДиапазонС;
    ТЗ.X2 = ДиапазонПо;
    
    КонецПроцедуры
    
    Функция ВернутьОдноСтроч(ТекстОбъект)
    Одностроч = "";
    Для i = 1 по ТекстОбъект.КоличествоСтрок() Цикл
    Одностроч = Одностроч+ТекстОбъект.ПолучитьСтроку(i);
    КонецЦикла;
    
    Возврат Одностроч;
    
    КонецФункции
    
    
    Функция Прописать(ДиапазонС,ДиапазонПо)
    НоваяТЗ.ВыбратьСтроки();
    
    Пока НоваяТЗ.ПолучитьСтроку() = 1 Цикл
    ТребуемыйРазмер = ДиапазонПо-ДиапазонС;
    
    ЗначениеЯчейки = НоваяТЗ.Диапазон;
    Следующая = 0;
    
    Для i = ДиапазонС По ДиапазонПо Цикл
    
    Если Найти(ЗначениеЯчейки,""+i+".") >0 Тогда
    Следующая = 1;	 
    Прервать;
    ИначеЕсли  Сред(ЗначениеЯчейки,i,1) = " " Тогда //кстати, проверим можно ли вообще использовать эту позицию
    //Сообщить();
    Следующая = 1;	 
    Прервать;
    КонецЕсли;	
    
    КонецЦикла;
    
    Если Следующая = 1 Тогда
    
    Продолжить;
    
    КонецЕсли; 
    
    МногоСтроч = СтрЗаменить(ЗначениеЯчейки," "," "+РазделительСтрок);
    МногоСтроч = СтрЗаменить(МногоСтроч,"_","_"+РазделительСтрок);
    МногоСтроч = СтрЗаменить(МногоСтроч,".","."+РазделительСтрок);
    
    
    ОбъектТекст = СоздатьОбъект("Текст");
    ОбъектТекст.ДобавитьСтроку(МногоСтроч);
    ОбъектТекст.УдалитьСтроку(ОбъектТекст.КоличествоСтрок()); //однастрока лишняя
    
    Для i = ДиапазонС По ДиапазонПо Цикл
    
    ОбъектТекст.ЗаменитьСтроку(i,""+i+".");
    
    КонецЦикла;
    
    НоваяТЗ.Диапазон = ВернутьОдноСтроч(ОбъектТекст);
    
    УровеньВложенности = НоваяТЗ.НомерСтроки;
    
    Возврат 1;
    
    КонецЦикла;
    
    Возврат 0; 
    
    КонецФункции
    Процедура Посчитать(ТЗ)
    
    ДиапазонС = 1; ДиапазонПо = 9;
    
    ШаблонСтроки = "";
    
    Для i = 1 По ДиапазонПо Цикл
    
    Если i < ДиапазонС Тогда
    ШаблонСтроки = ШаблонСтроки + " ";
    Иначе
    ШаблонСтроки = ШаблонСтроки + "_";
    КонецЕсли;
    
    КонецЦикла;
    ДобавитьСтрокуТаб(ТЗ,18,18);
    
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    
    Если (ТЗ.X1 > ДиапазонПо) Или (ТЗ.X2 > ДиапазонПо) Тогда
    
    Сообщить("Выход за пределы диапазона "+ТЗ.НомерСтроки+"стр.   ТЗ.X1 = "+ТЗ.X1+"   ТЗ.X2 = "+ТЗ.X2);
    Сообщить();
    Продолжить;
    
    КонецЕсли;
    
    
    Пока Прописать(ТЗ.X1,ТЗ.X2) = 0 Цикл
    
    НоваяТЗ.НоваяСтрока();
    НоваяТЗ.Диапазон = ШаблонСтроки;
    //НоваяТЗ.НаправлениеСортировки = НоваяТЗ.НомерСтроки;
    
    КонецЦикла;
    
    ТЗ.Уровень = УровеньВложенности;
    
    КонецЦикла;
    
    Сообщить("Результат:");
    НоваяТЗ.ВыбратьСтроки();
    Пока НоваяТЗ.ПолучитьСтроку() = 1 Цикл
    Сообщить("НоваяТЗ.Диапазон = "+НоваяТЗ.Диапазон);
    КонецЦикла;
    
    Сообщить("Уровни ТЗ:");
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    Сообщить(""+ТЗ.НомерСтроки+") "+ТЗ.X1+","+ТЗ.X2+ "   "+ТЗ.Уровень);
    КонецЦикла;
    
    КонецПроцедуры
    
    Процедура Main()
    
    ClearMessageWindow();
    
    ТЗ = ИнициализироватьТЗ();
    ДобавитьСтрокуТаб(ТЗ,1,5);
    ДобавитьСтрокуТаб(ТЗ,1,3);
    ДобавитьСтрокуТаб(ТЗ,6,9);
    ДобавитьСтрокуТаб(ТЗ,6,8);
    ДобавитьСтрокуТаб(ТЗ,7,8);
    ДобавитьСтрокуТаб(ТЗ,3,5);
    ДобавитьСтрокуТаб(ТЗ,4,5);
    ДобавитьСтрокуТаб(ТЗ,1,40);
    ДобавитьСтрокуТаб(ТЗ,8,35);
    ДобавитьСтрокуТаб(ТЗ,9,15);
    ДобавитьСтрокуТаб(ТЗ,9,18);
    ДобавитьСтрокуТаб(ТЗ,1,14);
    ДобавитьСтрокуТаб(ТЗ,1,9);
    ДобавитьСтрокуТаб(ТЗ,18,18);
    ДобавитьСтрокуТаб(ТЗ,2,14);
    
    Посчитать(ТЗ);
    
    КонецПроцедуры
    
    УровеньВложенности = 1;
    НоваяТЗ = СоздатьОбъект("ТаблицаЗначений");
    НоваяТЗ.НоваяКолонка("Диапазон");//СвободныйДиапазонС
    //НоваяТЗ.НоваяКолонка("НаправлениеСортировки");
    
    только результат немного отличается от вашего (даже без учета того что вы заюзали первую строку в самом начале))

    у меня по уровням так

    Уровни ТЗ:
    1) 1,5 1
    2) 1,3 2
    3) 6,9 1
    4) 6,8 2
    5) 7,8 3
    6) 3,5 3
    7) 4,5 2
    8) 1,40
    9) 8,35
    10) 9,15
    11) 9,18
    12) 1,14
    13) 1,9 4
    14) 18,18
    15) 2,14
    16) 18,18

    еще забыл обнулить НоваяТЗ в стартующей процедуре
  15. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Странно. Писал в 18.05 в электричке "спасибо. вечером дома посмотрю", но поста нет. Всёравно спасибо. Вот добрался посмотреть. О результатах скорей всего отпишусь завтра. А задачка мне тоже на первый взгляд показалась не очень сложной. Кстати, я её сильно упростил для форумов. И таблицу дал с цифрами, что бы показать смысл. А в реале всё сложней: строки могут дублироваться и надо решить составлять из них "башню" или нет. "Широких" пар по идее быть не должно, но они есть и надо выяснить и указать причину их появления. Поскольку многие факты не предполагались и оказались "сюрпризом", то код получился "с костылями" или "индусский". Хотелось красивого кода, а то через 20 строчек сплошного "Если" и циклов я не мог понять какой функционал реализует следующий оператор. Ваш код явно покрасивше моего. Проверю как с функционалом.
  16. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    Уважаемый Фобец.
    Проверил Вашу программу. За попытку спасибо, но работает ошибочно.
    Таблицу я давал упрощенную для пояснения "графической" части. Но она может быть совсем другой.
    Примените в своей программе вот такую таблицу

    ДобавитьСтрокуТаб(ТЗ,1,5);
    ДобавитьСтрокуТаб(ТЗ,6,8);
    ДобавитьСтрокуТаб(ТЗ,1,2);
    ДобавитьСтрокуТаб(ТЗ,6,9);

    ДобавитьСтрокуТаб(ТЗ,7,8);
    ДобавитьСтрокуТаб(ТЗ,3,5);
    ДобавитьСтрокуТаб(ТЗ,4,5);
    ДобавитьСтрокуТаб(ТЗ,1,40);
    ДобавитьСтрокуТаб(ТЗ,8,35);
    ДобавитьСтрокуТаб(ТЗ,9,15);
    ДобавитьСтрокуТаб(ТЗ,9,18);
    ДобавитьСтрокуТаб(ТЗ,1,14);
    ДобавитьСтрокуТаб(ТЗ,1,9);
    ДобавитьСтрокуТаб(ТЗ,18,18);
    ДобавитьСтрокуТаб(ТЗ,2,14);

    И Вы увидите, как (6-9) будет помещена над (6-8), а должна быть исключена.
    Ваша реализация не соответствует алгоритму, потому, что Вы проводите сравнение
    с "базовым" диапазоном и в текущем диапазоне, а надо еще и с предыдущим.
  17. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    да, ошибку я увидел вчера вечером.. надо подумать
  18. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    к сожалению нет платформы под рукой, поэтому писал без отладки в блокноте

    Код:
    Перем УровеньВложенности;
    Перем НоваяТЗ;
    Функция ИнициализироватьТЗ()
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("X1");
    ТЗ.НоваяКолонка("X2");
    ТЗ.НоваяКолонка("Уровень");
    ТЗ.НоваяКолонка("СчетчикСтрок"); //на всякий случай
    ТЗ.НоваяКолонка("ПризнакВыбора");
    Возврат ТЗ;
    КонецФункции
    
    Процедура НекаяПроцедураВыбора(ТЗ)
    
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    ТЗ.СчетчикСтрок = ТЗ.НомерСтроки;
    Если ТЗ.НомерСтроки = 13 Тогда
    ТЗ.ПризнакВыбора = 1;
    КонецЕсли;
    КонецЦикла;
    ТЗ.Sort("ПризнакВыбора,НомерСтроки") // не помню русское написание, пишу анг
    //В реальности так и есть, вы используете сначала выбранную строку, хотя в таблице это не отображено
    КонецПроцедуры
    
    
    Процедура ДобавитьСтрокуТаб(ТЗ,ДиапазонС,ДиапазонПо)
    ТЗ.НоваяСтрока();
    ТЗ.X1 = ДиапазонС;
    ТЗ.X2 = ДиапазонПо;
    КонецПроцедуры
    
    Функция ВернутьОдноСтроч(ТекстОбъект)
    Одностроч = "";
    
    Для i = 1 по ТекстОбъект.КоличествоСтрок() Цикл
    Одностроч = Одностроч+ТекстОбъект.ПолучитьСтроку(i);
    КонецЦикла;
    Возврат Одностроч;
    КонецФункции
    
    Функция ВернутьНовоеЗначениеЯчейки(ЗначениеЯчейки,ДиапазонС,ДиапазонПо)
    
    МногоСтроч = СтрЗаменить(ЗначениеЯчейки," "," "+РазделительСтрок);
    МногоСтроч = СтрЗаменить(МногоСтроч,"_","_"+РазделительСтрок);
    МногоСтроч = СтрЗаменить(МногоСтроч,".","."+РазделительСтрок);
    
    
    ОбъектТекст = СоздатьОбъект("Текст");
    ОбъектТекст.ДобавитьСтроку(МногоСтроч);
    ОбъектТекст.УдалитьСтроку(ОбъектТекст.КоличествоСтрок()); //одна строка почему-то лишняя
    
    Для i = ДиапазонС По ДиапазонПо Цикл
    
    ОбъектТекст.ЗаменитьСтроку(i,""+i+".");
    
    КонецЦикла;
    Возврат ВернутьОдноСтроч(ОбъектТекст);
    КонецФункции
    Функция ЗаполнитьРезультирующуюТаблицу(ДиапазонС,ДиапазонПо)
    НовоеЗначениеЯчейки = "";
    НоваяТЗ.ВыбратьСтроки();
    
    Пока НоваяТЗ.ПолучитьСтроку() = 1 Цикл
    
    ЗначениеЯчейки = НоваяТЗ.Диапазон;
    Следующая = 0;
    
    Для i = ДиапазонС По ДиапазонПо Цикл
    
    Если Найти(ЗначениеЯчейки,""+i+".") >0 Тогда
    Следующая = 1; 
    Прервать;
    ИначеЕсли  Сред(ЗначениеЯчейки,i,1) = " " Тогда //кстати, проверим можно ли вообще использовать эту позицию
    Следующая = 1; 
    Прервать;
    КонецЕсли;
    //здесь проверка ляжет или не ляжет)
    Если НовоеЗначениеЯчейки<>"" Тогда
    Если Найти(НовоеЗначениеЯчейки,""+i+".") = 0 Тогда
    Следующий = 1;
    Сообщить("Исключение для параметров "+ДиапазонС+"   "+ДиапазонПо); //под нами пустота
    Прервать;
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    
    Если Следующая = 1 Тогда
    
    Продолжить;
    
    КонецЕсли;
    
    
    НовоеЗначениеЯчейки = ВернутьНовоеЗначениеЯчейки(ЗначениеЯчейки,ДиапазонС,ДиапазонПо);
    НоваяТЗ.Диапазон = НовоеЗначениеЯчейки;
    
    УровеньВложенности = НоваяТЗ.НомерСтроки;
    
    Возврат 1;
    
    КонецЦикла;
    
    Возврат 0;
    
    КонецФункции
    Процедура Посчитать(ТЗ)
    ДиапазонС = 1; ДиапазонПо = 9;
    ШаблонСтроки = "";
    Для i = 1 По ДиапазонПо Цикл
    
    Если i < ДиапазонС Тогда
    ШаблонСтроки = ШаблонСтроки + " ";
    Иначе
    ШаблонСтроки = ШаблонСтроки + "_";
    КонецЕсли;
    
    КонецЦикла;
    
    
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    
    Если (ТЗ.X1 > ДиапазонПо) Или (ТЗ.X2 > ДиапазонПо) Тогда
    
    Сообщить("Выход за пределы диапазона "+ТЗ.НомерСтроки+"стр.   ТЗ.X1 = "+ТЗ.X1+"   ТЗ.X2 = "+ТЗ.X2);
    Сообщить();
    Продолжить;
    
    КонецЕсли;
    
    Пока ЗаполнитьРезультирующуюТаблицу(ТЗ.X1,ТЗ.X2) = 0 Цикл
    
    НоваяТЗ.НоваяСтрока();
    НоваяТЗ.Диапазон = ШаблонСтроки;
    //НоваяТЗ.НаправлениеСортировки = НоваяТЗ.НомерСтроки;
    
    КонецЦикла;
    
    ТЗ.Уровень = УровеньВложенности;
    
    КонецЦикла;
    Сообщить("Результат:");
    НоваяТЗ.ВыбратьСтроки();
    Пока НоваяТЗ.ПолучитьСтроку() = 1 Цикл
    Сообщить("НоваяТЗ.Диапазон = "+НоваяТЗ.Диапазон);
    КонецЦикла;
    Сообщить("Уровни ТЗ:");
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    Сообщить(""+ТЗ.НомерСтроки+") "+ТЗ.X1+","+ТЗ.X2+ "   "+ТЗ.Уровень);
    КонецЦикла;
    КонецПроцедуры
    Процедура Main()
    ClearMessageWindow();
    ТЗ = ИнициализироватьТЗ();
    ДобавитьСтрокуТаб(ТЗ,1,5);
    ДобавитьСтрокуТаб(ТЗ,1,3);
    ДобавитьСтрокуТаб(ТЗ,6,9);
    ДобавитьСтрокуТаб(ТЗ,6,8);
    ДобавитьСтрокуТаб(ТЗ,7,8);
    ДобавитьСтрокуТаб(ТЗ,3,5);
    ДобавитьСтрокуТаб(ТЗ,4,5);
    ДобавитьСтрокуТаб(ТЗ,1,40);
    ДобавитьСтрокуТаб(ТЗ,8,35);
    ДобавитьСтрокуТаб(ТЗ,9,15);
    ДобавитьСтрокуТаб(ТЗ,9,18);
    ДобавитьСтрокуТаб(ТЗ,1,14);
    ДобавитьСтрокуТаб(ТЗ,1,9);
    ДобавитьСтрокуТаб(ТЗ,18,18);
    ДобавитьСтрокуТаб(ТЗ,2,14);
    НекаяПроцедураВыбора(ТЗ);
    Посчитать(ТЗ);
    ТЗ.Sort("НомерСтроки");
    ТЗ.ChooseLine();
    
    КонецПроцедуры
    УровеньВложенности = 1;
    НоваяТЗ = СоздатьОбъект("ТаблицаЗначений");
    НоваяТЗ.НоваяКолонка("Диапазон");//СвободныйДиапазонС
    //НоваяТЗ.НоваяКолонка("НаправлениеСортировки");
    
  19. shurikvz
    Offline

    shurikvz Модераторы Команда форума Модератор

    Регистрация:
    1 окт 2009
    Сообщения:
    8.409
    Симпатии:
    316
    Баллы:
    104
    О, алгоритмы. Алгоритмы это хорошо, это клево. :) Жаль только что на семерке, я уже забыл как на ней писать. Если бы на 8-ке даже наверно попробовал бы рабочий код состряпать.

    Мой вариант условно рисую:
    Код:
    
    Процедура Главная()
    
    МассивРезультат = Новый Массив;
    
    
    Добавить(МассивРезультат, ВыбранныйОтрезок);
    
    Для каждого Отрезок из Отрезки Цикл
    
    Если Отрезок = ВыбранныйОтрезок Тогда //Здесь все понятно, можно по индексу сравнить: если это выбранный отрезок (13 в примере), то повторно его смотреть естественно не надо
    
    Продолжить;
    
    КонецЕсли;
    
    
    Если ОтрезокПринадлежитьОдномуИзОтрезковПоследнегоУровня(МассивРезультат, Отрезок) Тогда
    
    Добавить(МассивРезультат, Отрезок);
    
    Продолжить;
    
    КонецЕсли;
    
    
    Если ОтрезокПринадлежитПустомуИнтервалу(МассивРезультат, Отрезок, Уровень) Тогда //Уровень - возвращаемое значение
    
    Вставить(МассивРезультат, Отрезок, Уровень);
    
    Продолжить;
    
    КонецЕсли;
    
    
    
    //Здесь выводим сообщение или как-то помечаем, что отрезок добавить не можем, поскольку некуда
    
    
    
    
    
    КонецЦикла;
    
    
    КонецПроцедуры
    
    
    //И для простоты сделать служебные функции
    
    Функция ОтрезокВходитВИнтервал(Отрезок, Интервал) //Результат - булево. Здесь несложно, просто сравнить координаты
    
    КонецФункции
    
    Функция ОтрезокПринадлежитьОдномуИзОтрезковУровня(МассивРезультат, Отрезок, Уровень) //Результат - булево. Описание ниже
    
    КонецФункции
    

    Пояснения по структуре:

    Отрезки - исходный массив отрезков.

    МассивРезультат - результирующий массив - количество элементов будет равно количеству получившихся уровней. Каждый элемент этого массива - это в свою очередь массив (т.е. список) отрезков, принадлежащих этому уровню.


    По функциям:

    Добавить() - добавляет Отрезок в массив результат (т.е. по сути создает новый уровень)

    Вставить() - вставляет отрезок в указанный уровень

    У функций тип возвращаемого значения - булево. По названию функций вроде понятно что они должны делать:

    ОтрезокПринадлежитьОдномуИзОтрезковПоследнегоУровня(МассивРезультат) - т.е. берем последний элемент массива МассивРезультат (это тоже массив), и проверяем входит ли отрезок в один из интервалов в этом массиве.
    Код:
    Функция ОтрезокПринадлежитьОдномуИзОтрезковПоследнегоУровня(МассивРезультат, Отрезок)
    
    ПоследнийУровень = МассивРезультат.Количество() - 1;
    
    Принадлежит = ОтрезокПринадлежитьОдномуИзОтрезковУровня(МассивРезультат, Отрезок, ПоследнийУровень)
    
    Возврат Принадлежит;
    
    КонецФункции
    
    Код:
    
    Функция ОтрезокПринадлежитьОдномуИзОтрезковУровня(МассивРезультат, Отрезок, Уровень)
    
    МассивОтрезковУровня = МассивРезультат[Уровень];
    
    Принадлежит = Ложь;
    
    Для каждого ОтрезокУровня из МассивОтрезковУровня Цикл
    
    Если ОтрезокВходитВИнтервал(Отрезок, ОтрезокУровня) Тогда
    
    Принадлежит = Истина;
    
    Прервать;
    
    КонецЕсли;
    
    КонецЦикла;
    
    Возврат Принадлежит;
    
    КонецФункции
    
    



    ОтрезокПринадлежитПустомуИнтервалу(МассивРезультат, Отрезок, Уровень). Уровень - возвращаемое значение (в 77 же переменные тоже по ссылке передаются, правильно?). Просматриваем все уровни в поисках не занятого интервала.
    Код:
    
    Функция ОтрезокПринадлежитПустомуИнтервалу(МассивРезультат, Отрезок, Уровень)
    
    //Отрезок должен входить в занятый интервал ПРЕДЫДУЩЕГО уровня, ну и соответственно надо найти на каком уровне есть свободный интервал (еще раз: с учетом того что отрезок будет входить в занятый интервал ПРЕДЫДУЩЕГО уровня).
    
    Пренадлежит = Ложь;
    
    Для Уровень = 1 по МассивРезультат.Количество() - 1 Цикл //Начинаем не с 0, а с первого уровня. На нулевой ничего добавить не можем
    ПринадлежитПредыдущемуУровню = ОтрезокПринадлежитьОдномуИзОтрезковУровня(МассивРезультат, Отрезок, Уровень - 1);
    Если НЕ ПринадлежитПредыдущемуУровню Тогда // не принадлежит предыдущему уровню, дальше искать нельзя, возврат ложь
    Прервать;
    КонецЕсли;
    
    СписокСвободныхОтрезков = ПолучитьСписокСвободныхОтрезков(МассивРезультат, Уровень);
    
    Для каждого СвободныйОтрезок из СписокСвободныхОтрезков Цикл
    
    Если ОтрезокВходитВИнтервал(Отрезок, СвободныйОтрезок) Тогда
    
    Принадлежит = Истина;
    
    Прервать;
    
    КонецЕсли;
    
    КонецЦикла;
    
    
    Если Принадлежит Тогда //Нашли, дальше обходить уровни не надо
    Прервать;
    КонецЕсли;
    
    КонецЦикла;
    
    Возврат Принадлежит;
    
    КонецФункции
    
    




    По типу данных:
    Отрезок - здесь в алгоритме рассматривал как самостоятельный тип данных (т.е. аналог допустим struct {x, y} на других языках). Поскольку насколько помню в 77 подобного типа данных нет, то придется делать как-то через таблицу значений.


    Не описал процедуру ПолучитьСписокСвободныхОтрезков(МассивРезультат, Уровень), там вроде не особо сложно должно быть: берем нулевой уровень - это база будет, от базы вычитаем интервалы всех отрезков, имеющихся на уровне Уровень. И возвращаем в виде набора отрезков.
  20. TopicStarter Overlay
    Lsr
    Offline

    Lsr

    Регистрация:
    12 дек 2012
    Сообщения:
    11
    Симпатии:
    0
    Баллы:
    1
    shurikvz, спасибо, конечно, но Ваш код смотреть не буду. И 8 у меня нет. Кто-нибудь сейчас скажет, пардон, 7.7 не знаю, поэтому напишу на Oracle и в десятке строк решит проблему. Думаете мне полегчает?
Похожие темы
  1. Pasha
    Ответов:
    9
    Просмотров:
    2.014
  2. oleg4mok
    Ответов:
    1
    Просмотров:
    306
  3. Tiger86
    Ответов:
    8
    Просмотров:
    429
Загрузка...

Поделиться этой страницей