[identity profile] vdas.livejournal.com posting in [community profile] useful_faq
Мля... Совсем поломал голову. Тупая, простейшая задача, но я уже вообще ничего не соображаю. Есть список <50, <100, >=100, >200 итд итп - надо преобразовать его в пары (с-до): 1-49, 50-99, 100-200, 201-MAX

Тетки дают такие списки.
А нужны пары "С-До" .Сегодня (больше некому было) пришлось ручками это все раскладывать. [...] Тарифы, мля...[...]

Я - тупой :( Мне не приходит в голову простой и эффективный алгоритм. Все время монстры какие-то рисуютсо... Некрасивые... Хелп.

Date: 2008-02-15 01:44 am (UTC)
From: [identity profile] meanab.livejournal.com
Что-то в таком духе: два прохода. Каждый интервал представлен парой (from, to), где from и to — либо число, либо NIL. При первом проходе заполняем указанные в явном виде части интервала. При втором проходе заменяем NIL в поле from на to предыдущего интервала, а NIL в поле to — на from следующего. В реальности алгоритм будет чуть сложнее, так как нужно учитывать граничные условия и, возможно, открытость/закрытость интервала (если речь идет о целых числах, то можно просто заменять '<100' на '<=99').

Date: 2008-02-15 01:55 am (UTC)
From: [identity profile] meanab.livejournal.com
Ну, разумеется, добавить всякие проверки, на то, что при замене NIL мы не наткнемся на другой NIL, на то, что в интервале поле to должно быть больше, чем from и т.д. В этих случаях сразу signal a condition (raise an exception или как это называется в вашем языке). Можно, конечно, сделать и в один проход, но, насколько я понимаю, вопроса эффективности здесь возникать не должно, только чистоты и простоты кода.

Date: 2008-02-15 03:56 am (UTC)
From: [identity profile] urvin.livejournal.com
SELECT id,tname,tcost
FROM tariffs
WHERE tcost<100
AND tcost>50

Date: 2008-02-15 08:24 am (UTC)
From: [identity profile] a-bronx.livejournal.com
Всё в целых числах?

Сортируем список и начинаем создавать интервалы. Все интервалы - полуоткрытые. Первый интервал - [1, null). Бежим по списку. Каждый шаг закрывает один интервал и создаёт новый.
- Если встречаем "<N" - текущий интервал закрывается числом N-1, и открываем новый интервал [N, null).
- Если "<=N" - число N закрывает текущий интервал, создаём новый интервал [N+1, null).
- Если ">=N" - число N-1 закрывает текущий интервал, создаём [N, null).
- Если ">N" - число N закрывает текущий интервал, создаём [N+1, null).
По окончании закрываем последний интервал числом MAX.

Date: 2008-02-15 08:44 am (UTC)
From: [identity profile] a-bronx.livejournal.com
Да, сортировать список нужно по-хитрому:

"<=N" == ">N" == "<N+1" == ">=N+1" < "<=N+1" == ">N+1" == ...

Вообще говоря, эквивалентных элементов в списке быть не должно, т.к. они сгенерят одинаковые интервалы, а это исключительная ситуация.

Date: 2008-02-15 09:34 am (UTC)
From: [identity profile] a-bronx.livejournal.com
А, если допускаются разрывы, то их можно поймать во время генерации интервалов по типичным паттернам в последовательности, например, отлавливать смежные пары ("<", ">") и т.п. Простой автомат с запоминанием предыдущего шага.

Неоднозначности отловятся при сортировке, т.к. возникнут эквивалентные элементы, что должно породить исключение.

Date: 2008-02-15 06:41 pm (UTC)
From: [identity profile] a-bronx.livejournal.com
Тьфу, на свежую голову вижу косяк: я сначала написал, что все интервалы полуоткрытые, а на деле генерирую закрытые. Ну да фигня, в общем-то, чуть упростятся выражения при генерации (и чуть усложнятся при выводе):

"<N", ">=N" ==> [_, N), [N, null)
"<=N", ">N" ==> [_, N+1), [N+1, null)

Date: 2008-02-15 07:44 am (UTC)
From: [identity profile] sam-buddy.livejournal.com
select * from table sort by id :)