OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Суббота, 18 Ноябрь, 2017 07:19

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 75 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Пятница, 23 Апрель, 2010 10:54 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Опять непонятно, зачем LOOP:
Код:
found := FALSE;
LOOP
   IF A THEN
      EXIT
   ELSIF B THEN
      found := TRUE;
      EXIT
   END;
   Step;
END; (* loop *)
IF ~found THEN
   SomeCode;
END;
Нетрудно увидеть, что при выходе found = ~A. Это же просто линейный поиск:
Код:
WHILE ~A & ~B DO
   Step;
END;
IF A THEN
   SomeCode;
END;
Переменная found не понадобилась.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Пятница, 23 Апрель, 2010 12:01 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Александр Ильин писал(а):
Опять непонятно, зачем LOOP:
Просто могучий, но девственный интеллект наладился орудовать узловатой дубиной. Откуда знать партизану про боевые искусства.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Пятница, 23 Апрель, 2010 12:25 

Зарегистрирован: Четверг, 12 Июль, 2007 23:18
Сообщения: 1982
Откуда: Узбекистан, Чирчик
Так все эти LOOP'ы написаны Стефаном Мейтцлером, которого тут приводили как пример профессионала, заработавшего миллионы программированием на Обероне?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Пятница, 23 Апрель, 2010 16:48 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Поиск элемента последовательность с номером index (index >= 0).
Код:
PROCEDURE DoSomething (index: INTEGER);
VAR
   n: INTEGER;
BEGIN
   n := 0;
   LOOP
      IF A THEN
         EXIT
      ELSIF n = index THEN
         OneShotCode;
         EXIT
      END;
      INC (n);
      Step;
   END;
END DoSomething;
Преобразуем в WHILE по привычной схеме:
Код:
PROCEDURE DoSomething (index: INTEGER);
VAR
   n: INTEGER;
BEGIN
   n := 0;
   WHILE ~A & ~(n = index) DO
      INC (n);
      Step;
   END;
   IF ~A THEN
      OneShotCode;
   END;
END DoSomething;
Убираем лишнюю локальную переменную:
Код:
PROCEDURE DoSomething (index: INTEGER);
BEGIN
   WHILE ~A & ~(index = 0) DO
      DEC (index);
      Step;
   END;
   IF ~A THEN
      OneShotCode;
   END;
END DoSomething;
Насколько я знаю, проверка на равенство нулю выполняется быстрее, чем сравнение двух произвольных чисел.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Пятница, 23 Апрель, 2010 18:42 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Александр Ильин писал(а):
Насколько я знаю, проверка на равенство нулю выполняется быстрее, чем сравнение двух произвольных чисел.
В реале этого не измерить, но без лишней переменной код проще.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Понедельник, 31 Май, 2010 18:59 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Код:
WHILE ~A DO
   IF Found() THEN
      RETURN TRUE
   END;
   Step();
END;
RETURN FALSE
Эквивалентно следующему коду:
Код:
WHILE ~A & ~Found() DO
   Step();
END;
RETURN ~A


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Понедельник, 12 Июль, 2010 18:27 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Исходный LOOP с тремя EXIT'ами. Задача - организовать цикл обработки сообщений для модального окна с некоторыми дополнительными проверками при нажатии кнопки "OK" (SomeCheckIfOk). "ptr" - некая переменная, заданная до цикла:
Код:
LOOP
   cmd := GetCmd ();
   IF cmd = Commands.Ok THEN
      IF SomeCheckIfOk () THEN
         SomeCode1 ();
         IF ptr = NIL THEN
            EXIT
         END;
         SomeCode2 (ptr);
         EXIT
      END;
      DoOnOk ();
   ELSIF cmd = Commands.Cancel THEN
      DoOnCancel ();
      EXIT
   END; (* if cmd *)
END;
Для начала удалим самый внутренний EXIT:
Код:
LOOP
   cmd := GetCmd ();
   IF cmd = Commands.Ok THEN
      IF SomeCheckIfOk () THEN
         SomeCode1 ();
         IF ptr # NIL THEN
            SomeCode2 (ptr);
         END;
         EXIT
      END;
      DoOnOk ();
   ELSIF cmd = Commands.Cancel THEN
      DoOnCancel ();
      EXIT
   END; (* if cmd *)
END;
Выносим из цикла всё, что будет выполняться лишь один раз:
Код:
cmd := GetCmd ();
WHILE (cmd # Commands.Cancel) & ~((cmd = Commands.Ok) & SomeCheckIfOk ()) DO
   IF cmd = Commands.Ok THEN (* ~SomeCheckIfOk () *)
      DoOnOk ();
   END; (* if cmd *)
   cmd := GetCmd ();
END;
IF cmd = Commands.Cancel THEN
   DoOnCancel ();
ELSE (* (cmd = Commands.Ok) & SomeCheckIfOk () *)
   SomeCode1 ();
   IF ptr # NIL THEN
      SomeCode2 (ptr);
   END;
END; (* if cmd *)
UPD: Забыл 'DO' после 'WHILE'.


Последний раз редактировалось Александр Ильин Понедельник, 12 Июль, 2010 19:50, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 14:54 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Задача: найти последний элемент цепочки объектов. Если последний элемент - составной (тип Values.Struct), то углубиться в него и найти последний там. Если там в конце тоже составной элемент, ещё раз углубиться, и так далее, пока не будет найден самый последний в самой глубине.

Код с LOOP/EXIT:
Код:
LOOP
   IF v.next = NIL THEN
      IF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) THEN
         v := v (Values.Struct).parts; (* recurse into substructure *)
      ELSE
         EXIT
      END
   END;
   v := v.next;
END;


После преобразования текст сократился на 2 строки:
Код:
REPEAT
   WHILE v.next # NIL DO
      v := v.next;
   END; (* find last *)
   IF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) THEN
      v := v (Values.Struct).parts; (* recurse into substructure *)
   END;
UNTIL v.next = NIL;
Попутно устранена ошибка лишнего "v := v.next" после захода в подструктуру в первом варианте кода. Если эту же ошибку устранить в первом варианте, добавив ELSE ко внешнему IF, то получим выигрыш уже в 3 строки.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 15:02 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Как насчет цикла Дейкстры:
Код:
   WHILE v.next # NIL DO
      v := v.next;
   ELSIF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) DO
      v := v (Values.Struct).parts; (* recurse into substructure *)
   END;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 15:54 

Зарегистрирован: Пятница, 24 Апрель, 2009 16:28
Сообщения: 524
Откуда: Москва
Александр Ильин писал(а):
После преобразования текст сократился на 2 строки:
Код:
REPEAT
   WHILE v.next # NIL DO
      v := v.next;
   END; (* find last *)
   IF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) THEN
      v := v (Values.Struct).parts; (* recurse into substructure *)
   END;
UNTIL v.next = NIL;
Попутно устранена ошибка лишнего "v := v.next" после захода в подструктуру в первом варианте кода. Если эту же ошибку устранить в первом варианте, добавив ELSE ко внешнему IF, то получим выигрыш уже в 3 строки.
Насколько я понял, этот код вообще неправильный. Пусть после v := v (Values.Struct).parts оказывается, что v.next = NIL. В этом случае нужно опять смотреть на parts, а не отваливать в строке UNTIL v.next = NIL.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 16:18 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Info21 писал(а):
Как насчет цикла Дейкстры
Действительно, исходный код после исправления можно представить в виде
Код:
LOOP
   IF v.next = NIL THEN
      IF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) THEN
         v := v (Values.Struct).parts; (* recurse into substructure *)
      ELSE
         EXIT
      END
   ELSE
      v := v.next;
   END;
END;
Это равнозначно коду
Код:
LOOP
   IF v.next # NIL THEN
      v := v.next;
   ELSIF (v IS Values.Struct) & (v (Values.Struct).parts # NIL) THEN
      v := v (Values.Struct).parts; (* recurse into substructure *)
   ELSE
      EXIT
   END;
END;
А это уже с очевидностью цикл Дейкстры. Спасибо за подсказку. : )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 16:29 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2284
Откуда: Россия, Санкт-Петербург
Peter Almazov писал(а):
Насколько я понял, этот код вообще неправильный.
Вы правы, спасибо. Преобразование я сделал правильно, но в исходном коде ошибка, это да. Просто, видимо, в реальном применении не сталкивались. (Специфика данных. По той же причине и лишний переход на v.next не мешал.)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 20:53 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Александр Ильин писал(а):
А это уже с очевидностью цикл Дейкстры.
Либо полный проход, либо линейный поиск, либо аккуратненький Дейкстра. Исключений пока не встречал.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 21:04 

Зарегистрирован: Пятница, 24 Апрель, 2009 16:28
Сообщения: 524
Откуда: Москва
Info21 писал(а):
Либо полный проход, либо линейный поиск, либо аккуратненький Дейкстра. Исключений пока не встречал.
Тяжелый случай.
Ну вот здесь "распознайте" viewtopic.php?f=27&t=2981


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 22:07 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Peter Almazov писал(а):
Тяжелый случай.
Это типа "Дурак."?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 22:28 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
В тему к циклам.
Попал на днях в руки свежий белорусский учебник по информатике за 9-й класс. Ориентация - Pascal.ABC. Первая конструкция - FOR. Далее тема линейного поиска. Если хотите найти определённый элемент, то выходите из цикла по условию:
Код:
FOR i:=0 TO ... DO
  IF A[i] = искомое THEN BREAK;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Вторник, 08 Февраль, 2011 22:50 

Зарегистрирован: Пятница, 24 Апрель, 2009 16:28
Сообщения: 524
Откуда: Москва
Info21 писал(а):
Либо полный проход, либо линейный поиск, либо аккуратненький Дейкстра. Исключений пока не встречал.
Info21 писал(а):
Это типа "Дурак."?
Типа, встретьте исключений.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Среда, 09 Февраль, 2011 06:15 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Peter Almazov писал(а):
Info21 писал(а):
Это типа "Дурак."?
Типа, встретьте исключений.
Это ведь повелительное наклонение? Тогда, i!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Среда, 09 Февраль, 2011 14:32 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Info21 писал(а):
Александр Ильин писал(а):
А это уже с очевидностью цикл Дейкстры.
Либо полный проход, либо линейный поиск, либо аккуратненький Дейкстра. Исключений пока не встречал.
Мне кажется в данном случае применение цикла Дейкстры неоправдано. По назначению было бы его применение для спутанного поиска (чередование ветвей цикла на каждом шаге). А тут же факторизация налицо - сначала полностью выполняется простой линейный поиск, затем делается проверка и всё повторяется.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Убираю LOOP'ы
СообщениеДобавлено: Среда, 09 Февраль, 2011 15:11 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7712
Откуда: Троицк, Москва
Сергей Губанов писал(а):
Info21 писал(а):
Александр Ильин писал(а):
А это уже с очевидностью цикл Дейкстры.
Либо полный проход, либо линейный поиск, либо аккуратненький Дейкстра. Исключений пока не встречал.
Мне кажется в данном случае применение цикла Дейкстры неоправдано.
Можно подумать, что цикл Дейкстры это МБР с ядерным зарядом.

Код-то самый короткий и ясный :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 75 ]  На страницу Пред.  1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2017, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB