New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
This is not going to be merged #1
Open
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
67f4812
Add reference implementation in python
maheshm f34c64e
Implement the structure of the code
maheshm 17cb5b7
Update dir structure and implement lca
maheshm 5dd9d74
Add some test cases for lca
maheshm 4f9de11
Implement memory store, and model functions
maheshm be1cd54
Complete the create and search flow
maheshm 1e2a1aa
Add comment to these files
maheshm 477d621
Stich everything together
maheshm 8b0399d
Restructure directories
maheshm c14a223
Update Readme
maheshm 3c5a22d
Mask
maheshm
Jump to file or symbol
Failed to load files and symbols.
Diff settings
12
.gitignore
| @@ -0,0 +1,12 @@ | ||
| # Binaries for programs and plugins | ||
| *.exe | ||
| *.exe~ | ||
| *.dll | ||
| *.so | ||
| *.dylib | ||
| # Test binary, build with `go test -c` | ||
| *.test | ||
| # Output of the go coverage tool, specifically when used with LiteIDE | ||
| *.out |
| @@ -0,0 +1,26 @@ | ||
| # Find closest common Manager | ||
| To build run the following from the parent most directory of the project | ||
| go get github.com/manifoldco/promptui | ||
| go build ccm | ||
| To run use the following command: | ||
| ./ccm -cmd | ||
| ## Assumptions and limitations | ||
| * All the employee names are unique | ||
| * I am writing Go code for the first time! | ||
| * A manager can have n number of subordinates | ||
| * All the negative cases have been omitted - like during search it is assumed that you enter a name that you have already fed as an employee | ||
| * Test cases are there, but limitted | ||
| ## Note | ||
| * Design has been given more importance | ||
| * It has been coded to make it adaptable - you can have different storage types later, different APIs later, that the employee model could have more functionalities etc | ||
| * There are files lying around without any code. They are for future implementation/improvement | ||
| * I have added comments in few places where I felt I could improve or implement in different way | ||
| * I started off coding in Python to get a feel of the problem statement and it has been put in `reference` directory. It is not part of solution. | ||
| * LCA has been implemented in the easiest possible way. It may not be the perfect one. |
File renamed without changes.
| @@ -0,0 +1,91 @@ | ||
| from pprint import pprint | ||
| class Node: | ||
| def __init__(self, key): | ||
| self.key = key | ||
| self.children = [] | ||
| self.ancestor = None | ||
| self.rank = 0 | ||
| self.color = 0 | ||
| self.parent = None | ||
| def printnodes(): | ||
| pprint(vars(p_u)) | ||
| pprint(vars(p_v)) | ||
| #pprint(vars(three)) | ||
| #pprint(vars(four)) | ||
| #pprint(vars(five)) | ||
| def makeset(node): | ||
| node.parent = node | ||
| node.rank = 1 | ||
| def union(nodex, nodey): | ||
| xroot = find(nodex) | ||
| yroot = find(nodey) | ||
| if xroot.rank > yroot.rank: | ||
| yroot.parent = xroot | ||
| elif xroot.rank < yroot.rank: | ||
| xroot.parent = yroot | ||
| elif xroot.rank == yroot.rank: | ||
| yroot.parent = xroot | ||
| xroot.rank += 1 | ||
| def find(node): | ||
| if node.parent != node: | ||
| node.parent = find(node.parent) | ||
| return node.parent | ||
| def lca(u, found = False): | ||
| #print "lca with %d" %(u.key) | ||
| #printnodes() | ||
| makeset(u) | ||
| u.ancestor = u | ||
| for w in u.children: | ||
| res = lca(w, False) | ||
| if res["found"]: | ||
| return res | ||
| #print "union u: %d, w: %d" %(u.key, w.key) | ||
| union(u,w) | ||
| #print "u.parent: %d, w.parent: %d, u.rank: %d, w.rank: %d" %(u.parent.key, w.parent.key, u.rank, w.rank) | ||
| find(u).ancestor = u | ||
| #print "find(u): %d, u_a: %d, w_a: %d, find(w).a: %d" %(find(u).key, u.ancestor.key, w.ancestor.key, find(w).ancestor.key) | ||
| u.color = 1 | ||
| #print "p_u: %d, p_v: %d, u: %d, p_v.color: %d, p_u.color: %d, p_v_a: %d" %(p_u.key, p_v.key, u.key, p_v.color, p_u.color, (p_v.ancestor and p_v.ancestor.key) or 0) | ||
| if (p_v.key == u.key) and (p_v.color == 1 and p_u.color == 1): | ||
| #printnodes() | ||
| #print find(p_u).key | ||
| #print find(p_u).ancestor.key | ||
| #print "\n" | ||
| return {"a": find(p_u).ancestor, "found": True} | ||
| elif (p_u.key == u.key) and (p_v.color == 1 and p_u.color == 1): | ||
| #printnodes() | ||
| #print find(p_v).key | ||
| #print find(p_v).ancestor.key | ||
| #print "hgf \n" | ||
| return { "a": find(p_v).ancestor, "found": True} | ||
| else: | ||
| return {"found": False} | ||
| root = Node(1) | ||
| two = Node(2) | ||
| three = Node(3) | ||
| four = Node(4) | ||
| five = Node(5) | ||
| six = Node(6) | ||
| seven = Node(7) | ||
| eight = Node(8) | ||
| root.children.append(two) | ||
| root.children.append(three) | ||
| two.children.append(four) | ||
| two.children.append(five) | ||
| three.children.append(six) | ||
| three.children.append(seven) | ||
| three.children.append(eight) | ||
| p_u = two | ||
| p_v = eight | ||
| a = lca(root) | ||
| print a["a"].key |
| @@ -0,0 +1,63 @@ | ||
| package cmd | ||
| import ( | ||
| "fmt" | ||
| "ccm/employee/create" | ||
| "ccm/model/employee_model" | ||
| "ccm/employee/search_manager" | ||
| "github.com/manifoldco/promptui" | ||
| ) | ||
| func ask(question string) string { | ||
| prompt := promptui.Prompt{ Label: question, Validate: nil } | ||
| result, err := prompt.Run() | ||
| if err != nil { | ||
| fmt.Printf("Prompt failed %v\n", err) | ||
| return "" | ||
| } | ||
| return result | ||
| } | ||
| func get_employees_of_manager(manager *employee_model.Employee) { | ||
| question := "Enter names of people who directly report to "+ manager.Name + " " | ||
| for ans := ask(question); ans != "q"; ans = ask(question) { | ||
| emp := employee.Create(ans) | ||
| employee.Link(manager, emp) | ||
| } | ||
| for _, emp := range manager.Manages { | ||
| get_employees_of_manager(emp) | ||
| } | ||
| } | ||
| func search(ceo *employee_model.Employee) { | ||
| cont := true | ||
| for ; cont ; { | ||
| emp1 := ask("Enter the name of first employee ") | ||
| emp2 := ask("Enter the name of second employee ") | ||
| search_manager.Setceo(ceo) | ||
| emp1_obj := employee_model.Find_by_name(emp1) | ||
| emp2_obj := employee_model.Find_by_name(emp2) | ||
| manager := search_manager.Search_common_manager(emp1_obj, emp2_obj) | ||
| fmt.Printf("The closest common Manager of %v and %v is %v\n\n", emp1, emp2, manager.Name) | ||
| wish_to_continue := ask("Do you wish to continue? (y/n) ") | ||
| if wish_to_continue == "n" { | ||
| cont = false | ||
| } | ||
| } | ||
| } | ||
| func Init() { | ||
| ceo := employee.Create(ask("Enter the name of CEO ")) | ||
| fmt.Println("Enter `q` to skip adding more") | ||
| get_employees_of_manager(ceo) | ||
| search(ceo) | ||
| } |
| @@ -0,0 +1 @@ | ||
| // Yet to be implemented |
| @@ -0,0 +1 @@ | ||
| //Yet to be implemented |
| @@ -0,0 +1,21 @@ | ||
| package main | ||
| import ( | ||
| "fmt" | ||
| "flag" | ||
| "ccm/api/cmd" | ||
| ) | ||
| func main() { | ||
| cmd_flag := flag.Bool("cmd", false, "Interactive commandline prompt") | ||
| api_flag := flag.Bool("api", false, "Web API - not implemented") | ||
| file_flag := flag.Bool("file", false, "File input - not implemented") | ||
| flag.Parse() | ||
| if *api_flag == true || *file_flag == true || *cmd_flag == false { | ||
| fmt.Println("Only interactive commandline promt is implemented. Please use -cmd flag") | ||
| } else { | ||
| cmd.Init() | ||
| } | ||
| } |
| @@ -0,0 +1,55 @@ | ||
| package memory | ||
| import "strconv" | ||
| type Entry struct { | ||
| Id int | ||
| Data map[string]interface{} | ||
| } | ||
| var current_id = 1 | ||
| var memory_store map[int]*Entry | ||
| func store_data(data map[string]interface{}) map[string]interface{} { | ||
| var data_to_be_stored map[string]interface{} | ||
| data_to_be_stored = make(map[string]interface{}) | ||
| for k,v := range data { | ||
| data_to_be_stored[k] = v | ||
| } | ||
| return data_to_be_stored | ||
| } | ||
| func Get(key, value string) *Entry { | ||
| if key == "Id" { | ||
| val, _ := strconv.Atoi(value) | ||
| return memory_store[val] | ||
| } | ||
| for _, entry := range memory_store { | ||
| if entry.Data[key] == value { | ||
| return entry | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
| func Set(data map[string]interface{}) *Entry { | ||
| entry_data := store_data(data) | ||
| // get lock here | ||
| new_entry := &Entry{Id: current_id, Data: entry_data} | ||
| if memory_store == nil { | ||
| memory_store = make(map[int]*Entry) | ||
| } | ||
| memory_store[current_id] = new_entry | ||
| current_id += 1 | ||
| //release lock | ||
| return new_entry | ||
| } | ||
| func Update(id int, data map[string]interface{}) *Entry { | ||
| entry_data := store_data(data) | ||
| memory_store[id].Data = entry_data | ||
| return memory_store[id] | ||
| } | ||
| func Delete () {} |
| @@ -0,0 +1,12 @@ | ||
| package employee | ||
| import "ccm/model/employee_model" | ||
| func Create(name string) *employee_model.Employee { | ||
| employee := employee_model.Create(name) | ||
| return employee.Save() | ||
| } | ||
| func Link(manager, employee *employee_model.Employee) { | ||
| manager.Link_employee(employee) | ||
| } |
| @@ -0,0 +1,3 @@ | ||
| package employee | ||
| //yet to be implemented |
| @@ -0,0 +1,3 @@ | ||
| package employee | ||
| //yet to be implemented |
| @@ -0,0 +1,3 @@ | ||
| package employee | ||
| //yet to be implemented |
| @@ -0,0 +1,16 @@ | ||
| package search_manager | ||
| import ( | ||
| "ccm/model/employee_model" | ||
| ) | ||
| var ceo_of_company *employee_model.Employee | ||
| func Setceo(ceo *employee_model.Employee) { | ||
| ceo_of_company = ceo | ||
| } | ||
| func Search_common_manager (employee1, employee2 *employee_model.Employee) *employee_model.Employee { | ||
| manager := employee_model.Search_common_manager(ceo_of_company, employee1, employee2) | ||
| return manager | ||
| } |
Oops, something went wrong.
ProTip!
Use n and p to navigate between commits in a pull request.