Преобразовать диапазоны РосСвязи в заданный вид

Androgen1985
Дата: 06.05.2015 17:33:28
Есть задача преобразовать диапазоны номеров взятых с сайта РосСвязи. Ранее решал похожую, но условия были проще, нужно было определить лучшую цену предлагаемую провайдерами по разным направлениям и вывести диапазоны. Для примера имеем тарифные сетки операторов в таком виде:

Префикс номера
30000
30001
30002
30003
30004
30005
30006
30007
30008
30009
...
99999


и преобразуем вот в такой
Начало диапазона Окончание диапазона Провайдер Диапазоны
30000 30119 1 300[0123456789]xxxxxx; 301[01]xxxxxx
30120 30129 2 3012[0123456789]xxxxx
30130 30219 1 301[3456789]xxxxxx; 302[01]xxxxxx
30220 30229 3 3022[0123456789]xxxxx
30230 34099 2 3[123]xxxxxxxx; 30[3456789]xxxxxxx; 302[3456789]xxxxxx; 340[0123456789]xxxxxx
99995 99999 3 9999[56789]xxxxx


+
Тут все просто за счет того, что операторы изначально предоставляют тарифы с префиксами номеров, т.е. указывается только первые несколько цифр, как правило не больше 5. Далее создаем табличку, в которой перебираются все возможные комбинации префиксов номеров. После чего определяем диапазоны (начало и окончание диапазона) с лучшим тарифом. Далее нам нужно преобразовать этот диапазон в требуемый вид (столбец диапазон), для чего выполняем группировку с различной градацией - по первой цифре префикса, по первым двум цифрам, первым трем и т.д. Далее для каждой группы находим случаи когда кол-во сгруппированных строк равно соответственно 10000, 1000, 100 и т.д. Сам скрипт могу приложить чуть позже. В результате получаем то, что надо, и отрабатывает быстро.


Но как теперь сделать тоже самое по таблице РосСвязи?! Выглядит она вот так:
code from_num to_num capacity operator region
301 2100000 2109999 10000 АСВТ(Москва) Улан - Удэ |Республика Бурятия
301 2110000 2129999 20000 Ростелеком Улан - Удэ |Республика Бурятия
301 2150000 2169999 20000 Ростелеком Улан - Удэ |Республика Бурятия
301 2180000 2189999 10000 Ростелеком Улан - Удэ |Республика Бурятия
301 2191000 2199999 9000 Ростелеком Улан - Удэ |Республика Бурятия
301 2200000 2201999 2000 Компания ТрансТелеКом Улан - Удэ |Республика Бурятия
495 9419497 9419497 1 Альтернативная связь Москва
495 9419498 9419539 42 Вымпел-Коммуникации Москва


В выше описанном примере у меня есть все возможные переборы префиксов, если и здесь использовать всевозможные переборы, то понадобится 4 млрд. строк. Попробовал реализовать на мобильных кодах, это около 1 млрд. строк, но все жутко медленно работает, и место жрет по страшному.

Есть варианты как реализовать то что требуется? Может кто уже делал подобное?
Владислав Колосов
Дата: 06.05.2015 18:01:46
Androgen1985,

а что не так? Росссвязь предоставляет нормализованные диапазоны в готовом виде.
alexeyvg
Дата: 06.05.2015 21:15:35
Androgen1985
Есть варианты как реализовать то что требуется?
Так что требуется-то? Что нужно получить из показанной таблицы РосСвязи?
Androgen1985
Дата: 07.05.2015 08:15:49
Нужно получить диапазоны вида - 300[0123456789]xxxxxx; 301[01]xxxxxx (ну не знаю как их еще назвать). Например для указанной выше таблицы РосСвязи, в случае если делаем группировку по оператору и региону, это должно выглядеть так:

code from_num to_num operator region Диапазоны
301 2100000 2109999 АСВТ(Москва) Улан - Удэ |Республика Бурятия 301210[0123456789]xxx
301 2110000 2129999 Ростелеком Улан - Удэ |Республика Бурятия 30121[12]xxxx
301 2150000 2169999 Ростелеком Улан - Удэ |Республика Бурятия 30121[56]xxxx
301 2180000 2189999 Ростелеком Улан - Удэ |Республика Бурятия 30121[8]xxxx
301 2191000 2199999 Ростелеком Улан - Удэ |Республика Бурятия 301219[123456789]xxx
301 2200000 2201999 Компания ТрансТелеКом Улан - Удэ |Республика Бурятия 301220[01]xxx
495 9419497 9419497 Альтернативная связь Москва 4959419497
495 9419498 9419539 Вымпел-Коммуникации Москва 495941949[89]; 49594195[0123]x


В последней строке у РосСвязи указан один диапазон, а в моем случае его требуется разбить на 2 диапазона, где в первая разбивка - префикс 495941949 далее одна из цифр 8 или 9, вторая - 49594195 далее одна из цифр 1, 2, 3, далее любая одна цифра. Такая запись диапазонов нужна для системы обзвона, и таблицу из РосСвязи нужно превратить в понятный для нее вид.
Glory
Дата: 07.05.2015 08:18:17
Androgen1985
Например для указанной выше таблицы РосСвязи, в случае если делаем группировку по оператору и региону, это должно выглядеть так:

И с какой трудностью вы столкнулись ? В чем проблема то ?
Вы написали какой-то код и он не работает ?
Androgen1985
Дата: 07.05.2015 08:30:01
Я реализовывал похожую задачу (описано выше), но там условия были проще. Реализовывал путем перебора всевозможных вариантов номеров. Если в этом случае делать так же, то потребуется 4 млрд.строк. Попробовал реализовать на мобильных кодах, это около 1 млрд. строк, но все жутко медленно работает, и место жрет по страшному.
Glory
Дата: 07.05.2015 08:31:14
Androgen1985
Если в этом случае делать так же, то потребуется 4 млрд.строк.

4 млрд. строк кода ?
Androgen1985
Дата: 07.05.2015 08:35:09
Glory,

нет). 4 млрд.строк номеров телефонов (все возможные комбинации).
Glory
Дата: 07.05.2015 08:36:32
Androgen1985
4 млрд.строк номеров телефонов (все возможные комбинации).

Т.е. ваш код генерирует больше запсией, чем вам нужно ?
Androgen1985
Дата: 07.05.2015 09:02:15
Нет. Моя реализация строится на том, что я делаю сначала всевозможные варианты номеров. А потом выполняю группировку сначала по первой цифре номеров, потом по первым двум цифрам номера, потом по первым трем и т.д. В каждой группе определяю строки где сгруппированны данные по Х строк. Для примера:
Диапазон из РосСвязи
3012100000 3012109999 АСВТ(Москва) Улан - Удэ |Республика Бурятия


попал бы в группу, которая группировалась по первым 6 цифрам номера, по региону и оператору. По данной группировке смотрим, есть ли строки в которых кол-во сгруппированных записей равно 10000 (в нашем случае с префиксом 301210 это все номера от 3012100000 и до 3012109999). По префикс 301210 как раз кол-во сгруппированных данных 10000, следовательно все номера начинающиеся на 301210 находятся у одного оператора и в одном регионе. Диапазон формируется как - 301210[0123456789]xxx.