LINUX.ORG.RU

Задачка по сортировке, а может быть и не по сортировке %)


0

0

Есть список телефонных кодов, типа 892120, 892121, 892122, 8877, 8878 и т.п. размером приблизительно 4000 строк. Есть список телефонных звонков размером приблизительно 65000 строк. Нужно написать программу, которая смотрит на телефонный номер и выдергивает из него телефонный код, т.е. делит номер типа 89212112345 на код 892121 и номер 12345. Загвоздка (для меня) состоит в том, что длина телефонного кода не определена и варьируется от 3 и до 7 символов + программа должна быть по-возможности быстрой. Ищется решение на Питоне, но, в принципе, подойдет любой язык программирования :)

★★

тел коды обладают тем свойством что ни один из них не является префиксом другого.

Тебе нужно просто по этим кодам построить trie -- дерево в каждом узле которого (кроме корня) лежит цифра.

Например если коды 810 8123 и 095, то строится дерево:
                   ХХХ
                  /   \
                 0     8
                /     /
               9     1
              /     / \
             5     0   2
                        \
                         3

и когда ты получаешь звонок, то ты просто спускаешься по дереву.



dilmah ★★★★★
()
Ответ на: комментарий от Cy6erBr4in

А можно создать побитовый массив, в котором еденицами заполнены те номера, которые представляют собой коды. (благо больше 10 метров памяти оно не сьест при макс. 7 знаках кода). После проверять каждый номер на наличие в себе одного из таких номеров (еще семь действий на каждй номер).

Плюсы - просто и быстро. Минусы - не понтонёшься бинарным деревом.

anonymous
()
Ответ на: комментарий от anonymous

> Минусы - не понтонёшься бинарным деревом.

а там не бинарное дерево -- до 10 детей может быть у узла:)

> А можно создать побитовый массив

а массив это просто один из способов хранить дерево у которого количество детей ограничено:)

dilmah ★★★★★
()

Наверное не самый оптимальный вариант, но думаю, по скорости должно быть нормально.
Тут есть несколько моментов - filter используется, чтоб убрать пустые строки, set - чтоб отсеять повторяющиеся номера и коды(если они есть)
И примечательно использование for - else - если не один из кодов не подошел(вдруг так получится) - то сработает ветвь else.
Надеюсь это поможет :)

# -------------------------------------------------------------------
# coding:cp1251
# считаем, что ни один код не является префиксом другого

codes = list(set(filter(None, open("codes.txt").read().split("\n"))))
phones = list(set(filter(None, open("phones.txt").read().split("\n"))))

for p in phones:
	for i in range(len(p)+1):
		if p[:i] in codes:
			print '('+p[:i]+')'+p[i:]
			break
	else:
		print '()'+p

# -------------------------------------------------------------------

Вывод:
>pythonw -u "doit.py"
(55)153131
(55)6551
(111)521315
(810)4645646
(55)11
(55)553
()77777
(8123)551
(87)4564
(111)
(223)3533
(55)55
(87)55521
(55)1225
(2244)11361

xonix
()
Ответ на: комментарий от xonix

import sys
import os

codes = {}

for code in list(set(filter(None, open("codes.txt").read().split("\n")))):
	obj = codes
	for key in code:
		if key not in obj.keys():
			obj[key]={}
		obj=obj[key]
		
for phone in list(set(filter(None, open("phones.txt").read().split("\n")))):
	obj = codes
	count = 0
	for i in phone:
		if i in obj.keys():
			count += 1
			obj = obj[i]
		else:
			print '(%s) %s' %(phone[:count],phone[count:])
			break 

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.