Задача по программированию (длина цепочки нулей)

1. scientes 289 03.11.22 14:08 Сейчас в теме
Среди публикаций на Infostart обнаружил следующую (https://infostart.ru/public/612325/). Среди приведенного автором списка задач есть такая:
Требуется найти самую длинную непрерывную цепочку нулей в последовательности нулей и единиц. Входные данные: последовательности нулей и единиц. Выходные данные: число (длина цепочки)
Автор предлагает вариант перебора входной строки. Как мне кажется, эта задача может быть решена значительно проще с помощью встроенных функций платформы.
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. DanDy 52 03.11.22 14:22 Сейчас в теме
(1)Ну как вариант искать в строке вхождения "1", соответственно длина строки нулей это разница позиций предыдущей "1" и текущей.
СтрНайти() в помощь)
3. user1831019 03.11.22 14:40 Сейчас в теме
(1)
Как мне кажется, эта задача может быть решена значительно проще с помощью встроенных функций платформы.
Продолжайте наблюдать.
4. Zevzm 03.11.22 14:42 Сейчас в теме
(1)
МассивСтрок = СтрРазделить(Строка, "1"); 
	ТЗ = Новый ТаблицаЗначений;
	ТЗ.Колонки.Добавить("Строки");
	Для каждого ЭлементМассива из МассивСтрок Цикл
		НоваяСтрока = ТЗ.Добавить();
		НоваяСтрока.Строки = ЭлементМассива;
	КонецЦикла;
	//ТЗ.ЗагрузитьКолонку(МассивСтрок, "Строки");
	Тз.Сортировать("Строки УБЫВ");  
	Сообщить("Максимальная длина непрерывной цепочки нулей - " + СтрДлина(ТЗ[0].Строки));
Показать

Как вариант так.
6. user1831019 03.11.22 14:47 Сейчас в теме
(4) Зачем тебе сортировать делать таблицу, если сразу в массиве можно проверять длину элемента? Опять же, твое решение выполнимо только на сервере.

UPD. В (5) уже опередили.
8. Zevzm 03.11.22 14:49 Сейчас в теме
(6) Надежда была изначально на этот метод "//ТЗ.ЗагрузитьКолонку(МассивСтрок, "Строки");", но он не работает пока не создашь пустые строки в ТЗ, поэтому и получилось как получилось. Клиент или сервер условий не было.
9. Zevzm 03.11.22 14:51 Сейчас в теме
(6) Вопрос, как к опытному, есть способ загрузить массив в ТЗ не добавляя пустые строки по количеству элементов массива как при использовании ЗагрузитьКолонку?
10. nomad_irk 72 03.11.22 14:51 Сейчас в теме
12. Zevzm 03.11.22 14:54 Сейчас в теме
(10) Какой-то странный метод от 1С... Если ТЗ наполнена данными метод ЗагрузитьКолонку() подойдет в особых случаях, если ТЗ пустая почему строки не добавить автоматически по количеству элементов массива?
17. nomad_irk 72 03.11.22 15:02 Сейчас в теме
(12)Все вопросы к программистам платформы.
11. user1831019 03.11.22 14:53 Сейчас в теме
(9) Нет.
А сортировать можно и список значений. В который можно загрузить массив без предварительного добавления элементов списка. И список значений доступен на клиенте.
13. Zevzm 03.11.22 14:55 Сейчас в теме
(11) Про загрузку в список без предварительного добавления не знал. Спасибо.
14. user1831019 03.11.22 14:57 Сейчас в теме
(13)
Синтаксис:
ЗагрузитьЗначения(<МассивЗначений>)
Параметры:
<МассивЗначений> (обязательный)
Тип: Массив.
Массив, содержащий значения для заполнения списка значений.
Описание:
Загружает список значений значениями из переданного массива. При этом все прежние элементы списка удаляются.
16. Zevzm 03.11.22 15:00 Сейчас в теме
(14)
МассивСтрок = СтрРазделить(Строка, "1", Ложь); 
	СЗ = Новый СписокЗначений;
	СЗ.ЗагрузитьЗначения(МассивСтрок);
	СЗ.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
	Сообщить("Максимальная длина непрерывной цепочки нулей - " + СтрДлина(СЗ[0].Значение));
succub1_5; +1 Ответить
18. user1831019 03.11.22 15:05 Сейчас в теме
(16) Это частный случай. А если задача будет найти не цепочку нулей, а самую длинную цепочку "без единиц"? Тогда будет работать и решение в (5). Оно всегда будет работать (особенно если вынести его в отдельную функцию, и передавать в параметр разделитель).
А твоё - не будет )))
22. Zevzm 03.11.22 15:09 Сейчас в теме
(18) Частный случай к конкретным условиям задачи? Одна и та же функция используется СтрРазделить(), что мешает вынести разделитель из моей? Можно подробнее...
23. user1831019 03.11.22 15:11 Сейчас в теме
(22) Хороший программист всегда программирует "с запасом", а не костылит по каждому частному случаю и конкретной задаче...
что мешает вынести разделитель из моей?
Вынести - можно. А вот Сортировать() уже не сработает.
28. Zevzm 03.11.22 15:17 Сейчас в теме
51. SlavaKron 04.11.22 07:44 Сейчас в теме
Результат = Вычислить("Макс(" + СтрЗаменить(СокрЛП(СтрЗаменить(СтрЗаменить(Текст, "1", " "), "0", "1+")), "1+ ", "1, ") + "0)");
Сообщить(Результат);
Vitaly1C8; spacecraft; +2 Ответить
53. user856012 13 04.11.22 11:24 Сейчас в теме
(51) Красиво, но не вызовет ли ошибку случай, когда последним символом в Текст будет "0"?
55. SlavaKron 04.11.22 11:47 Сейчас в теме
(53) Все "0" будут заменены на "1+", в конце добавляю "0", чтобы исключить ошибку.
Прикрепленные файлы:
60. user856012 13 04.11.22 12:34 Сейчас в теме
(55)
Все "0" будут заменены на "1+"
Это изначально было понятно.
в конце добавляю "0", чтобы исключить ошибку.
Другое дело, теперь вопросов нет.
5. Ivan_Sol 19 03.11.22 14:45 Сейчас в теме
МаксимальнаяДлина = 0;
СтрокаНолейИЕдениц = "0100011100000011001";

МассивСтрок = СтрРазделить(СтрокаНолейИЕдениц, "1");
Для каждого ЗаписьСтрока Из МассивСтрок Цикл
	Если МаксимальнаяДлина < СтрДлина(ЗаписьСтрока) Тогда
		МаксимальнаяДлина = СтрДлина(ЗаписьСтрока)
	КонецЕсли;
КонецЦикла;
Показать
Zevzm; succub1_5; papami; +3 Ответить
7. user1831019 03.11.22 14:48 Сейчас в теме
(5) Проще:
МаксимальнаяДлина = Макс(МаксимальнаяДлина, СтрДлина(ЗаписьСтрока));
Ivan_Sol; +1 Ответить
15. spacecraft 03.11.22 14:59 Сейчас в теме
ВхСтрока = "10010001010000101";
ВхМассив = СтрРазделить(ВхСтрока,"1");
СЗ = Новый СписокЗначений;
СЗ.ЗагрузитьЗначения(ВхМассив);
СЗ.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
Сообщить(СтрДлина(СЗ.Получить(0)));
Ivan_Sol; +1 Ответить
19. user1831019 03.11.22 15:06 Сейчас в теме
20. spacecraft 03.11.22 15:07 Сейчас в теме
(19) прикольно. Отвечаешь на 15 сообщение, что в 16 уже научили :)
21. user1831019 03.11.22 15:09 Сейчас в теме
(20) Ну, секунды решают всё! )) Я то сообщение увидел раньше (потому что я там отмечен).
24. scientes 289 03.11.22 15:12 Сейчас в теме
Добавлю свой код.
Функция ЗадачаДлинаЦепочки(вхСтрока)
	счетчик=0;
	дСтроки=СтрДлина(вхСтрока);
	маска="0";
	пока истина цикл
		приемник=СтрЗаменить(вхСтрока,маска,"");
		если СтрДлина(приемник)=дСтроки тогда
			 прервать
		 конецесли;
		 счетчик=счетчик+1;
		 маска=маска+"0";
	конеццикла;	
	
	возврат счетчик;
КонецФункции		

Показать
25. user1831019 03.11.22 15:13 Сейчас в теме
(24) Ровно такой же перебор, против которого ты возмущался. В чем суть-то?
26. spacecraft 03.11.22 15:16 Сейчас в теме
(25) там не полный перебор получается. Итераций цикла будет равно максимальной цепочке нулей.
32. user1831019 03.11.22 15:33 Сейчас в теме
(26) Мммм... Тогда мне интересно - в каком случае значение "дСтроки" станет равной значению СтрДлина(Приемник)?
Ведь "дСтроки" у нас - максимальная длина первоначальной вхСтрока, и нигде далее по циклу не изменяется.
А вот длина "приемника" - всегда уменьшается в цикле за счет увеличения "маски".

Таким образом я хочу понять - в каком случае сработает "Прервать"???
39. spacecraft 03.11.22 16:23 Сейчас в теме
(32)
Таким образом я хочу понять - в каком случае сработает "Прервать"???

когда после СтрЗаменить ничего не изменится в первоначальной строке.
А в цикле в СтрЗаменить передается нарастающая строка из нулей.
маска=маска+"0";
Как только цепочка нулей превысит существующую цепочку в первоисточнике, то и замены не произойдет. Вот и получится Макс длина такой цепочки (вычисленная на предыдущей итерации).
41. user1831019 03.11.22 16:29 Сейчас в теме
(39) Долго думал. Логику понял. Попытка работать от обратного. Но это не кошерно.
Сразу вспомнил свою работу в санатории. Там был хороший кореш, который работал одновременно и гастроэнтерологом и проктологом.
Главная его фраза - "не забывать руки мыть".
27. scientes 289 03.11.22 15:16 Сейчас в теме
(25) Весь перебор спрятан в СтрЗаменить.
29. spacecraft 03.11.22 15:21 Сейчас в теме
(27) только метод СтрЗаменить довольно ресурсоемкий. И если цепочка будет достаточно большая, то не факт, что будет выгода.

101000000000000000000000000000000000000000000000000000000000­00000000000000001
:)
30. scientes 289 03.11.22 15:25 Сейчас в теме
(29) Возможно, есть варианты использования результатов предыдущих замен. Это должно ускорить поиск.
31. scientes 289 03.11.22 15:28 Сейчас в теме
Например, после первой замены мы уже знаем сколько единиц в записи, отсюда получаем максимально возможную длину строки с нулями.
33. spacecraft 03.11.22 15:40 Сейчас в теме
(31)
111111111111111111111111111111111110000000000000000000000000­000000000000000001
101010101010101010101010101010101010101010101010101010101010­1010101010101

и как это поможет?
37. scientes 289 03.11.22 15:59 Сейчас в теме
(33)Как то так. (В первоначальном варианте была ошибка, исправил.)
Функция ЗадачаДлинаЦепочки(вхСтрока)
	дСтроки=СтрДлина(вхСтрока);
	маска="0";
	приемник=СтрЗаменить(вхСтрока,маска,"");
	счетчик=дСтроки-СтрДлина(приемник);
	если счетчик <2 тогда
		возврат счетчик;
	конецесли;	
	для н=1 по счетчик цикл 
	 маска=маска+"0";
	конеццикла;
        счетчик=счетчик+1;
	пока истина цикл
		приемник=СтрЗаменить(вхСтрока,маска,"");
		если СтрДлина(приемник)<>дСтроки тогда
			 прервать
		 конецесли;
		 счетчик=счетчик-1;
                 
		 маска=Лев(маска,счетчик);
	конеццикла;	
	
	возврат счетчик;
КонецФункции

Показать
40. user1831019 03.11.22 16:25 Сейчас в теме
(37) По мне так еще хуже стало... Ты точно программист?
ВхСтрока = "000001111000101010101111110000";
дСтроки=СтрДлина(вхСтрока); // Получаем 30
Приемник=СтрЗаменить(вхСтрока,"0",""); // Получаем "11111111111111"
Счетчик=дСтроки-СтрДлина(приемник); // 30 - 14 = 16
// 
для н=1 по счетчик цикл 
     маска=маска+"0";
конеццикла; // Добавляем к маске 16 нулей, и получаем маску(!!!) в семндацать(!) нулей.
// 
    пока истина цикл
        приемник=СтрЗаменить(вхСтрока,маска,""); // То есть пытаемся найти в строке 17(!!!) нулей. Но их там нет.
        если СтрДлина(приемник)<>дСтроки тогда // Никогда не равна. Длина входной строки 30, а приемника 16
             прервать
         конецесли;
         счетчик=счетчик-1; // Счетчик стал 16
                 
         маска=Лев(маска,счетчик);
         // А приёмник не изменился!!! 
    конеццикла;
Показать

Пойду лучше коньяка выпью.
49. Zevzm 03.11.22 22:58 Сейчас в теме
(37) Еще один способ, на случай если отберут СтрРазделить() или СтрЗаменить(). Для любителей пузырьков.
&НаКлиенте
Функция ЗадачаДлинаЦепочкиПоловинноеДеление(ВхСтрока)
	ДлинаСтроки     = СтрДлина(вхСтрока);
	СтрокаИзНулей   = СтрЗаменить(ВхСтрока, "1", "");
	КоличествоНулей = СтрДлина(СтрокаИзНулей);
	Маска           = СтрокаИзНулей; 
	ИсходнаяСтрока = ВхСтрока;  
	Возврат ПроверитьВхождениеСтроки(Маска, КоличествоНулей)
КонецФункции 
&НаКлиенте 
Функция ПроверитьВхождениеСтроки(Маска, КоличествоНулей)
	КоличествоИтераций = 1 + КоличествоИтераций;
	ПозицияНуля = СтрНайти(ИсходнаяСтрока, Маска);	
	Если ПозицияНуля = 0 Тогда   //не нашли, идем влево
		КоличествоНулей = Окр(КоличествоНулей / 2);
		Маска           = Лев(СтрокаИзНулей, КоличествоНулей);  
		Возврат ПроверитьВхождениеСтроки(Маска, КоличествоНулей);
	Иначе //нашли
		Если СтрНайти(ИсходнаяСтрока, Маска + "0") = 0 Тогда //проверим что по маске в которой на один "0" больше нет
			Возврат КоличествоНулей; 
		Иначе //нашли по маске в которой на один "0" больше
			КоличествоНулей = КоличествоНулей + Окр(КоличествоНулей / 2); //идем вправо
			Маска           = Лев(СтрокаИзНулей, КоличествоНулей);
			Возврат ПроверитьВхождениеСтроки(Маска, КоличествоНулей);
		КонецЕсли;
	КонецЕсли;	
КонецФункции
Показать
50. user1831019 04.11.22 00:15 Сейчас в теме
(49) Усложнять - просто.
Упрощать - намного сложнее.

Не надо заниматься первым без надобности.
34. user1831019 03.11.22 15:40 Сейчас в теме
Ну и напоследок: "задача по программированию" <> "задача по программированию на платформе 1С".
35. spacecraft 03.11.22 15:45 Сейчас в теме
(34) лошадью ходи сортировка пузырем пузырьком :)
36. user1831019 03.11.22 15:51 Сейчас в теме
(35) Ну так-то да ))) Всегда интересны умения программиста обращаться с базовыми конструктами программирования. Потому что сегодня СтрРазделить() или СтрЗаменить() есть в платформе, а завтра его уже нет.
И это даже не про умения. Это про понимание принципов.
38. spacecraft 03.11.22 16:20 Сейчас в теме
(36)
Потому что сегодня СтрРазделить() или СтрЗаменить() есть в платформе, а завтра его уже нет.

Ок. Можно поговорить, когда же уберут из других ЯП метод split.
42. user1831019 03.11.22 16:31 Сейчас в теме
(38) Можно поговорить и о том, что в старых платформах нет сплита.
43. spacecraft 03.11.22 16:32 Сейчас в теме
(42) а в первых релизах С++ вообще мало что было. Это же не повод?
44. user1831019 03.11.22 16:34 Сейчас в теме
(43) Как раз таки повод. Я ж говорю "задача на программирование" <> "задача на программирование на последней платформе 1С" (добавил слово "последней).
52. starik-2005 3037 04.11.22 10:33 Сейчас в теме
(43) В первых релизах С++ был С и пара "++" )))
Но там все это можно было писать, и работало это быстро. Вот пример кода со "стрзаменить" - это постоянный обход массива, т.е. цикл в цикле. Кажется, что платформа делает это быстро, но если сравнить с простым проходом по двоичным данным, то последнее будет делать это за одну итерацию цикла, т.к. никто не знает, будет ли строка заканчиваться единицей. С друго стороны, если у нас длина максимальной последовательности нулей больше, чем остаток строки и мы встретили единицу, то цикл можно заканчивать.
45. user1831019 03.11.22 16:41 Сейчас в теме
Фреккен Бок напекла на кухне плюшки.
И разложила их в 15 тарелок: в первую тарелку 1 плюшку, в вторую - 2 плюшки,... в 15-ю -15 плюшек.
Карлсон собрался их пи... воровать и таскать из кухни в спальню.
Условие: За один прилет в кухню Карслсон может взять плюшки "с любого количества тарелок", но с каждой выбранной тарелки можно взять только "одинаковое количество за один прилет". (нельзя с одной тарелки взять 2, а с другой -три).

Какие минимальное количество "прилетов" понадобиться Карлсону, чтобы стащить все плюшки?

Объяснить логику, привести конечную формулу.

Задача на программирование. 1С тут ни при чем. Но этот алгоритм вполне себе используется в прикладных задачах бизнеса.

(Если что - то конечную формулу можно выразить встроенными средствами 1С, но это не главное)
46. Sashares 34 03.11.22 16:56 Сейчас в теме
(45) За 4 раза
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -8
1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 -4
1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 -2
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 -1

Берем по (N+1)/2 плюшек, где N - максимальное количество плюшек на тарелке.
Прикрепленные файлы:
47. user1831019 03.11.22 17:04 Сейчас в теме
(46) ТЫ ЗНАЛ! Но, ты обратным методом (от максимума к минимуму). Я решал наоборот (у нас разный циклы в решении получатся просто). Что не отменяет правильности обоих решений ))
Но вопрос про финальную формулу расчета количества ходов остается открытым.
48. Sashares 34 03.11.22 17:06 Сейчас в теме
(47)Я подобрал, прикольная задачка =)
54. scientes 289 04.11.22 11:25 Сейчас в теме
Сделал сравнение двух алгоритмов. На тестовых данных ДлинаЦепочкиСтрЗаменить работает быстрее чем ДлинаЦепочкиСтрРазделить.

Функция ДлинаЦепочкиСтрРазделить(вхСтрока) экспорт
	список=новый СписокЗначений;
	список.ЗагрузитьЗначения(СтрРазделить(вхСтрока,"1"));
	список.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
	
	счетчик=СтрДлина(список.Получить(0));
	
	возврат (счетчик);
КонецФункции	


Функция ДлинаЦепочкиСтрЗаменить(вхСтрока)

	дСтроки=СтрДлина(вхСтрока);
	маска="0";
	приемник=СтрЗаменить(вхСтрока,маска,"");
	ЧислоЕдиниц=СтрДлина(приемник)        ;    
	ЧислоНулей =дСтроки-СтрДлина(приемник);
	если ЧислоНулей <2 тогда
		возврат ЧислоНулей;
	конецесли;	

	//минимальная длина цепочки
	счетчик=(ЧислоНулей-ЧислоНулей%(ЧислоЕдиниц+1))/(ЧислоЕдиниц+1);
	для н=1 по счетчик-1 цикл 
	 маска=маска+"0";
        конеццикла;
	если счетчик=0 тогда
		счетчик=1;
	конецесли;	
	пока истина цикл
		приемник=СтрЗаменить(вхСтрока,маска,"");
		если СтрДлина(приемник)=дСтроки тогда
			 прервать
		 конецесли;
		 счетчик=счетчик+1;
		 маска=маска+"0";
	конеццикла;	
	
	возврат счетчик-1;
КонецФункции	




Функция ТестоваяСтрока(вхДлина)
	
	ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяУниверсальнаяДатаВМиллисекундах());
	т="";
	для н=1 по вхДлина цикл
		т=т+ГСЧ.СлучайноеЧисло(0,1);
	конеццикла;	
	возврат т;
КонецФункции	 


Функция ТестированиеАлгоритмов(вхДлина) экспорт
	перем счетчик;
	
	т=ТестоваяСтрока(вхДлина);   
	
	для каждого имя из СтрРазделить("ДлинаЦепочкиСтрЗаменить(т),ДлинаЦепочкиСтрРазделить(т)",",") цикл	
		старт=ТекущаяУниверсальнаяДатаВМиллисекундах();
		Выполнить("счетчик="+имя);
		сообщить("Результат "+счетчик+" "+имя+ " "+(ТекущаяУниверсальнаяДатаВМиллисекундах()-старт));
	конеццикла;
КонецФункции

Показать
56. spacecraft 04.11.22 11:55 Сейчас в теме
(54)
На тестовых данных ДлинаЦепочкиСтрЗаменить работает быстрее чем ДлинаЦепочкиСтрРазделить.

Что я делаю не так?
Прикрепленные файлы:
58. scientes 289 04.11.22 12:04 Сейчас в теме
(56) Ничего не могу сказать. У меня вот такие результаты.
Прикрепленные файлы:
59. spacecraft 04.11.22 12:18 Сейчас в теме
(58) потому что ГСЧ более менее равномерно получается распределить 0 и 1. Больших цепочек не получится.
Ну и СтрРазделить(вхСтрока,"1"). Тут более уместно не выбирать пустые значения.

Попробуйте такую строку:
ТестСтрока = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
	|10000000000001
	|10000000001
	|111111111111111111111111111111111111111111111111111111111111­1111111111111111111111111111111111111111111111
	|100000000000000000000000000000000000000000000000000000000000­00000000000000000000000000000000000000000000001
	|111111111111111111111111111111111111111111111111111111111111­11111111111111111
	|1000000000000000001
	|101
	|111111111111111111111111111111111111111111111111111111111111­1111111111111111111111111111111111111111111111
	|10000000001
	|111111111111111111111111111111111111111111111111111111111111­1111111111111111111111111111111111111111111111
	|1000000000000000000000000000000000000000001
	|10000000000001
	|10000000001
	|111111111111111111111111111111111111111111111111111111111111­1111111111111111111111111111111111111111111111
	|100000000000000000000000000000000000000000000000000000000000­00000000000000000000000000000000000000000000001
|";
Возврат СтрЗаменить(ТестСтрока, Символы.ПС, "");
Показать

Ее можно многократно размножить, для больших значений вычислений.
62. scientes 289 04.11.22 12:44 Сейчас в теме
(59)
Длина строки 934 000 Результат 105 ДлинаЦепочкиСтрЗаменить(т) 517
Длина строки 934 000 Результат 105 ДлинаЦепочкиСтрРазделить(т) 686

Длина строки 1 868 000 Результат 105 ДлинаЦепочкиСтрЗаменить(т) 1 096
Длина строки 1 868 000 Результат 105 ДлинаЦепочкиСтрРазделить(т) 1 366

Длина строки 3 736 000 Результат 105 ДлинаЦепочкиСтрЗаменить(т) 2 282
Длина строки 3 736 000 Результат 105 ДлинаЦепочкиСтрРазделить(т) 2 716
63. spacecraft 04.11.22 12:56 Сейчас в теме
(62) еще раз.
СтрРазделить(вхСтрока,"1", Ложь)

И основное, ДлинаЦепочкиСтрЗаменить(т) будет не всегда выигрывать. Я привел пример.
Просто слабое место в ДлинаЦепочкиСтрРазделить(т) это использование списка значений и его сортировка. Когда цепочка будет большой, а количество таких цепочек будет немного, то ДлинаЦепочкиСтрЗаменить(т) существенно проигрывает.
65. scientes 289 04.11.22 13:11 Сейчас в теме
(59)
СтрРазделить(вхСтрока,"1", Ложь)

Исправил. Для предложенной тестовой строки картина поменялась. Для строки через генератор случайных чисел нет, как правильно замечено, из-за равномерности нулей и единиц.
64. spacecraft 04.11.22 13:04 Сейчас в теме
(62) да и какой смысл сравнивать эти два алгоритма, когда в (51) был дан более простой и производительный алгоритм...
66. scientes 289 04.11.22 13:31 Сейчас в теме
(64)
Все верно, через Вычислить получается быстрее.

Длина строки 500 000 Результат 20 ДлинаЦепочкиСтрЗаменить(т) 192
Длина строки 500 000 Результат 20 ДлинаЦепочкиСтрРазделить(т) 352
Длина строки 500 000 Результат 20 ДлинаЦепочкиВычислить(т) 158

Цель обсуждения была найти новые алгоритмы, что и было достигнуто.
67. spacecraft 04.11.22 13:42 Сейчас в теме
(66) но от так же будет проигрывать СтрРазделить при тех же примерах, когда цепочка нулей большая, а количество таких цепочек немного.

Тут нет "серебряной пули".
68. spacecraft 04.11.22 14:06 Сейчас в теме
(66) и вишенка на тортик... перебор в цикле быстрее всего :)

Результат для тех же 500 000 :
Функция ДлинаЦепочкиСтрРазделитьПеребор(вхСтрока)

	Длина = 0;
	ВхМассив = СтрРазделить(вхСтрока,"1", Ложь);
	
	Для Каждого СтрМассива Из ВхМассив Цикл
		Длина = Макс(Длина, СтрДлина(СтрМассива));
	КонецЦикла;
	Возврат Длина;
	
КонецФункции
Показать
Прикрепленные файлы:
69. user856012 13 04.11.22 14:34 Сейчас в теме
(68)
перебор в цикле быстрее всего :)
Интересно, а что будет с быстродействием при тупой проверке каждого символа в строке, вообще без ее преобразования? То есть:
Функция ДлинаЦепочкиСтр(вхСтрока)

    Длина = 0;
    МаксДлина = 0;

    Сч = СтрДлина(вхСтрока);
    
    Пока Сч > 0 Цикл
        Если Сред(вхСтрока,Сч,1) = "0" Тогда
            Длина = Длина + 1;
        Иначе
            МаксДлина = Макс(МаксДлина, Длина);
            Длина = 0;
        КонецЕсли;
        Сч = Сч - 1;
    КонецЦикла;

    Возврат МаксДлина;
    
КонецФункции
Показать
Проверьте, если не трудно?

P.S. Маленький плюс данного алгоритма - "ненужный" символ необязательно должен быть "1", он может быть любым, даже набором самых разных символов - будет найдена длина последовательности именно нулей.
70. spacecraft 04.11.22 14:56 Сейчас в теме
(69)
Проверьте, если не трудно?

весь код тестов тут приведен. можете сами проверить.

Результат 19 ДлинаЦепочкиСтрЗаменить(т) 237
Результат 19 ДлинаЦепочкиСтрРазделить(т) 308
Результат 19 ДлинаЦепочкиВычислить(т) 177
Результат 19 ДлинаЦепочкиСтрРазделитьПеребор(т) 140
Результат 19 ДлинаЦепочкиСтр(т) 794
57. scientes 289 04.11.22 11:57 Сейчас в теме
Задача с плюшками.
1. Шаг
Берем по одной плюшке - общее количество 1*15,
берем по 2 плюшке - общее количество 2*14
по 3 - 3*13 и т.д.

Общая формула x*(16-x). Максимум при x=8. Уносим 8^2 = 2^6 плюшки

2. Шаг
Остается следующий набор
0
1,2,3,4,5.6,7
1,2,3,4,5.6,7

Для последовательности 1,2,3,4,5,6,7 формула будет x*(8-x). Максимум при x=4. Уносим 2*4^2 =2^5 плюшек.

3. Шаг
Остается следующий набор
0,0
1,2,3,
1,2,3,
1,2,3,
1,2,3,

Теперь берем по 2 плюшке. Уносим 4 *2^2=2^4 плюшки

4. Шаг Остается 8 тарелок по одной плюшке . Забираем оставшееся 8*1=2^3

Проверяем.
Всего было 8*15=120
Забрали 2^6+2^5+2^4+2^3=8*(8+4+2+1)=8*15=120
61. user856012 13 04.11.22 12:37 Сейчас в теме
(50)
Усложнять - просто.
Упрощать - намного сложнее.
В данном случае усложнение кода дает дихотомия, но она же дает и эффективность (скорость выполнения).

Для сравнения можно упростить алгоритм: создать строку из одних нулей, по длине равную обрабатываемой, и в цикле "откусывать" от нее по одному нолику до тех пор, пока СтрокаИзНулей не будет найдена в вхСтрока - элементарно, одна строка кода внутри цикла.

Вот только выполняться такой код может гораздо дольше предложенного в (49) - так, при длине исходной строки в 1024 символа сложный цикл с половинным делением выполнится максимум 10 раз, а "простой" - до 1023.
71. user654641_yaga_m 12 04.11.22 16:15 Сейчас в теме
ДД, а я бы использовал шаблон в VBScript.RegExp в цикле - начал бы 20 нулей и пошел бы в большую или меньшую сторону.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот