Codewars--Phone Directory

Phone Directory

Finally, I got it!


Problem Description:

John keeps a backup of his old personal phone book as a text file. On each line of the file he can find the phone number (formated as +X-abc-def-ghij where X stands for one or two digits), the corresponding name between < and > and the address.

Unfortunately everything is mixed, things are not always in the same order, lines are cluttered with non-alpha-numeric characters.

Examples of John’s phone book lines:

“/+1-541-754-3010 156 Alphand_St. \n”

" 133, Green, Rd. NY-56423 ;+1-541-914-3010!\n"

" +48-421-674-8974 Via Quirinal Roma\n"

Could you help John with a program that, given the lines of his phone book and a phone number returns a string for this number : “Phone => num, Name => name, Address => adress”

Examples:

s = “/+1-541-754-3010 156 Alphand_St. \n 133, Green, Rd. NY-56423 ;+1-541-914-3010!\n”

phone(s, “1-541-754-3010”) should return “Phone => 1-541-754-3010, Name => J Steeve, Address => 156 Alphand St.”

It can happen that, for a few phone numbers, there are many people for a phone number -say nb- , then

return : “Error => Too many people: nb”

or it can happen that the number nb is not in the phone book, in that case

return: “Error => Not found: nb”

You can see other examples in the test cases.

JavaScript random tests completed by @matt c
Note

Codewars stdout doesn’t print part of a string when between < and >

在這裏插入圖片描述

Click to get the problem description.


Version of Python:

在這裏插入圖片描述

Solution:

Method1:

# http://funhacks.net/2016/12/27/regular_expression/
import re
def phone(strng,num):
    lines = []
    lines = strng.split('\n')
    #print(lines)
    lists = []
    count = 0
    
    
    for i in range(len(lines)-1):
        pattern1=re.compile('.\d\-\d\d\d\-\d\d\d\-\d\d\d\d')
        Phone1=pattern1.findall(lines[i])
        Phone2=re.sub('[\+]','',Phone1[0])
        #print(Phone2)
        

        pattern2=re.compile('\<.*\>')
        Name1=pattern2.findall(lines[i])
        #print(Name1[0])
        

        Address1=re.sub('[\/\,\+\;\*]','',lines[i])
        Address2=Address1.replace(Phone2,'')
        Address3=Address2.replace(Name1[0],'').strip()
        Address4=re.sub('[\_\$\!\?\:]',' ',Address3)
        #print(Address4)
        Address4=Address4.split()
        #print(Address4)
        Address5=" ".join(Address4)
        #print(Address5)
        
        str1 = Phone2+'/'+Name1[0]+'/'+Address5
        #print(str1)
        
        lists.append(str1.split("/"))
        #print(lists)
        
    for i in range(len(lists)):
        if num == lists[i][0]:
            count += 1
    if count == 0:
        str2 = "Error => Not found: "+num
        return str2
    elif count == 1:
        for i in range(len(lists)):
            if num == lists[i][0]:
                Name2 = re.sub('[\<\>]','',lists[i][1])
                str3 = "Phone => "+lists[i][0]+", Name => "+Name2+", Address => "+lists[i][2]
        return str3
    else:
        str4 = "Error => Too many people: "+num
        return str4

Running:

在這裏插入圖片描述

在這裏插入圖片描述

Method2:

from re import sub

def phone(dir, num):
    if dir.count("+" + num) == 0:
        return "Error => Not found: " + num
    
    if dir.count("+" + num) > 1:
        return "Error => Too many people: " + num
    
    for line in dir.splitlines():
        if "+" + num in line:
            name = sub(".*<(.*)>.*", "\g<1>", line)
            line = sub("<" + name + ">|\+" + num, "", line)
            address = " ".join(sub("[^a-zA-Z0-9\.-]", " ", line).split())
            return "Phone => %s, Name => %s, Address => %s" % (num, name, address)

Method3:

import re

# Create the directory Phonebook
class Phonebook(object):
    def __init__(self):
        self.people = []


    def add_person(self, person):
        self.people.append(person)

    def __iter__(self):
        for elem in self.people:
            yield elem

    def find_phone(self, phone ):
        found = []
        for person in self.people:
            if str(person.phone) == str(phone):
                found.append(person)
        return found


# This is what will be stored in the phonebook:
class Person(object):
    def __init__(self, name, phone=None, address=None):
        self.name = name
        self.phone = phone
        self.address = address

    def add_phone(self, number):
        self.phone = number

    def add_address(self, address):
        self.address = address

    def show(self):
        print("Data:")
        s = 'name: %s \n' % self.name
        if self.phone is not None:
            s += 'general phone:   %s\n' % self.phone
        if self.address is not None:
            s += 'address address:  %s\n' % self.address
        print (s)




def phone(strng, num):
    phonebook = Phonebook()
# Working with the given data:
    datas = strng.split("\n")
    datas = [data for data in datas if data]
# Clean each line:
    for data in datas: # Not as clean as I would like:
        tel = re.findall("([1-9]*[1-9]-[0-9]\d{2}-[0-9]\d{2}-[0-9]\d{3})", data)[0]
        name = re.findall("(?<=\<)(.*?)(?=\>)", data)[0]
        address = data.replace(tel,"") # I bet there are better ways!!
        address = address.replace("<" + name + ">", "")
        address = re.sub('[^A-Za-z0-9-" ."]+', ' ', address)
        address = " ".join(address.split())
    # Now with the data clean, add it to a person:
        person = Person(name=name, phone=tel, address=address)
    # And add the person to phonebook
        phonebook.add_person(person)
    # Find the person by the Phone:
    results = phonebook.find_phone(num)
    if len(results) == 1:
        return ("Phone => {}, Name => {}, Address => {}".format(results[0].phone, results[0].name, results[0].address))
    if len(results) > 1:
        return "Error => Too many people: {}".format(num)
    if len(results) == 0:
        return "Error => Not found: {}".format(num)

Grammar Explanation(Method1):

  • pattern1=re.compile('.\d\-\d\d\d\-\d\d\d\-\d\d\d\d')
    Regular expression, in the page, the usage of regular expressions is described in detail. I am very grateful to the author for his help.
  1. In regular expression, it uses ".* " to represent a string of arbitrary length.
  2. The output of findall() function is a list. Both outputs of sub() and replace() are string.
  3. The append() function is based on list, in another way, it must to be used to handle list.3. The append() function is based on list, in another way, it must to be used to handle list.
  • lines = strng.split('\n')
    Click here to learn split() fuction.In conclusion, the output of this function is a list.
  • Address5=" ".join(Address4)
    Give some codes to show the usage of join() function.
## str >>>list 

str1 = "12345"
list1 = list(str1)
print list1
['1', '2', '3', '4', '5']
 
str2 = "123 sjhid dhi"
list2 = str2.split() #or list2 = str2.split(" ")
print list2
['123', 'sjhid', 'dhi']
 
str3 = "www.google.com"
list3 = str3.split(".")
print list3
['www', 'google', 'com']


##  list>>>str

str4 = "".join(list3)
print str4
wwwgooglecom

str5 = ".".join(list3)
print str5
www.google.com

str6 = " ".join(list3)
print str6
www google com

Also, you can refer to this page list>>>str and list—str .

It’s not easy for me to finish this problem. Write a blog to record it.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章