пятница, 27 января 2012 г.

Алгоритм определения красивости номера

Компания, в которой я работаю получила телефонную номерную емкость и менеджер попросил меня, чтобы не просматривать весь список глазами и выбирать номера, отсортировать их по степени "красивости". У меня естественно сразу же возник вопрос: а как алгоритмически определить "красивость" номера? Стало самому интересно. Первое, что пришло в голову - присвоить каждой цифре номера начальный вес и увеличивать его в зависимости от удовлетворения каким-то условиям красоты. По быстрому наваял на коленке скрипт на любимом Python'е, и вот что получилось:

#-*- coding: utf-8 -*-
import operator

"""
   Author: Shiryaev Pavel
"""

def beauty_coef(num):
 """
    Возвращает "вес" номера. Чем выше вес, тем красивее номер.
 """
 charCount = {}
 last = ""
 lastcnt = 0
 i = 0
 bc = {}
 #У каждой цифры в номере базовый коэффициент(бк) = 1.
 for char in num:
  bc[i] = 1
  charCount[char] = charCount.get(char, 0) + 1
  i += 1
 #Если в номере цифра встречается дважды, то базовый коэф такой цифры увеличивается на 2, если 3 то на 3...
 for a in range(0,i):
  if charCount[num[a]]>1:
   bc[a] += charCount[num[a]]
 #Если в номере повторяющиеся цифры идут одна за другой, то базовый коэф подряд идущих цифр увеличивается на (кол-во повторений * 2).
 for a in range(0,i):
  if num[a] == last:
   lastcnt += 1
  if num[a] != last or a == i-1:
   if lastcnt>0:
    for b in range(0, lastcnt+1):
     bc[i-b-2] += (lastcnt+1) * 2
     #Если номер заканчивается на повторяющиеся цифры, то он считается более привлекательным и каждая повторяющаяся цифра получает к БК 0.4 балла
     if a == i-1 and num[a] == last:
      bc[i-b-2] += 0.4
   lastcnt = 0
  last = num[a]
 #Если в номере есть комбинации из 2 и более цифр, то все эти цифры получают (кол-во повторений + кол-во цифр в комбинации) к бк
 for j in range(0, i-2):
  for l in range(j+2, i):
   oc = num.count(num[j:l])
   if oc > 1:
    for p in range(j,l):
     bc[p] += (oc-1)+(l-j)
 #Затем все бк складываются и получается финальный вес номера.
 return sum(bc.values())

if __name__ == "__main__":
 r = range(2801000,2802000)
 array = {}
 for a in r:
  array[a] = beauty_coef(str(a))
 sora = sorted(array.iteritems(), key=operator.itemgetter(1))
 # num, coef
 for i in sora:
  print i[0],i[1]
Код конечно получился не очень читабельный, но выдает что-то похожее на ожидаемый результат ;) Не спрашивайте почему я увеличиваю вес на то или иное значение. Это просто импровизация, что в голову первое пришло, то и написал, а потом экспериментальным путем докрутил.