Skip to content

Commit

Permalink
Merge pull request #2 from vaskoz/closestManager
Browse files Browse the repository at this point in the history
Closest manager
  • Loading branch information
vaskoz committed Sep 3, 2018
2 parents 39bb111 + bd6c338 commit 8b23d0f
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: go
go:
- master
before_install:
- go get github.com/mattn/goveralls
script:
- go test -bench=. -cover -v -race ./...
- $GOPATH/bin/goveralls -service=travis-ci
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[![Build Status](https://travis-ci.org/vaskoz/onsite-interviews-go.svg?branch=master)](https://travis-ci.org/vaskoz/onsite-interviews-go)
[![Coverage Status](https://coveralls.io/repos/github/vaskoz/onsite-interviews-go/badge.svg?branch=master)](https://coveralls.io/github/vaskoz/onsite-interviews-go?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/vaskoz/onsite-interviews-go)](https://goreportcard.com/report/github.com/vaskoz/onsite-interviews-go)
[![GoDoc](https://godoc.org/github.com/vaskoz/onsite-interviews-go?status.svg)](https://godoc.org/github.com/vaskoz/onsite-interviews-go)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.txt)

# onsite-interviews-go
The coding problems and solutions that I've encountered during onsite interviews.

Expand Down
49 changes: 49 additions & 0 deletions closestmanager/closestmanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package closestmanager

import "fmt"

// Employee represents an employee of a company.
type Employee struct {
id int
name string
title string
level int
manager *Employee
}

var errNoCommonManager = fmt.Errorf("No common manager found")

// NoCommonManagerError returns the errNoCommonManager error owned by the package.
func NoCommonManagerError() error {
return errNoCommonManager
}

// FindClosestManagerMap returns the manager of two given employees.
func FindClosestManagerMap(empMgrMap map[Employee]*Employee, e1, e2 Employee) (Employee, error) {
managers := make(map[Employee]struct{})
for mgr, found := empMgrMap[e1]; found && mgr != nil; mgr, found = empMgrMap[e1] {
managers[*mgr] = struct{}{}
e1 = *mgr
}
for mgr, found := empMgrMap[e2]; found && mgr != nil; mgr, found = empMgrMap[e2] {
if _, found := managers[*mgr]; found {
return *mgr, nil
}
e2 = *mgr
}
return Employee{}, NoCommonManagerError()
}

// FindClosestManagerGraph returns the manager of two given employees.
func FindClosestManagerGraph(e1, e2 *Employee) (*Employee, error) {
managers := make(map[*Employee]struct{})
for mgr := e1.manager; mgr != nil; mgr = mgr.manager {
managers[mgr] = struct{}{}
}
for mgr := e2.manager; mgr != nil; mgr = mgr.manager {
if _, found := managers[mgr]; found {
return mgr, nil
}
}
return nil, NoCommonManagerError()
}
120 changes: 120 additions & 0 deletions closestmanager/closestmanager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package closestmanager

import (
"testing"
)

var employeesForMap = map[string]*Employee{
"ceo": &Employee{100, "big", "boss", 11, nil},
"vpoe": &Employee{12, "big", "tech", 10, nil},
"opsDirector": &Employee{11, "ops", "dude", 9, nil},
"softDirector": &Employee{533, "sw", "peeps", 9, nil},
"swMgr": &Employee{80, "me", "you", 8, nil},
"otherMgr": &Employee{5, "other", "guy", 8, nil},
"vpop": &Employee{54, "prod", "uct guy", 10, nil},
}

func createTestCompanyMap() map[Employee]*Employee {
result := make(map[Employee]*Employee)
result[*employeesForMap["ceo"]] = nil
// engineering
result[*employeesForMap["vpoe"]] = employeesForMap["ceo"]
result[*employeesForMap["opsDirector"]] = employeesForMap["vpoe"]
result[*employeesForMap["softDirector"]] = employeesForMap["vpoe"]
result[*employeesForMap["swMgr"]] = employeesForMap["softDirector"]
result[*employeesForMap["otherMgr"]] = employeesForMap["softDirector"]
result[*employeesForMap["otherMgr"]] = employeesForMap["softDirector"]
// product
result[*employeesForMap["vpop"]] = employeesForMap["ceo"]
return result
}

var testcasesForMap = []struct {
e1, e2 *Employee
closestMgr *Employee
expectedErr error
}{
{employeesForMap["vpoe"], employeesForMap["vpop"], employeesForMap["ceo"], nil},
{employeesForMap["opsDirector"], employeesForMap["swMgr"], employeesForMap["vpoe"], nil},
{employeesForMap["otherMgr"], employeesForMap["swMgr"], employeesForMap["softDirector"], nil},
{employeesForMap["vpoe"], employeesForMap["ceo"], &Employee{}, NoCommonManagerError()},
}

func TestFindClosestManagerMap(t *testing.T) {
t.Parallel()
empMgrMap := createTestCompanyMap()
for _, tc := range testcasesForMap {
if mgr, err := FindClosestManagerMap(empMgrMap, *tc.e1, *tc.e2); err != tc.expectedErr {
t.Errorf("Expected error %v but got error %v", tc.expectedErr, err)
} else if mgr != *tc.closestMgr {
t.Errorf("Expected %v but got %v", tc.closestMgr, mgr)
}
}
}

func BenchmarkFindClosestManagerMap(b *testing.B) {
empMgrMap := createTestCompanyMap()
for i := 0; i < b.N; i++ {
for _, tc := range testcasesForMap {
FindClosestManagerMap(empMgrMap, *tc.e1, *tc.e2)
}
}
}

func createTestCompanyGraph() {
ceo := &Employee{100, "big", "boss", 11, nil}
employeesForGraph["ceo"] = ceo
vpoe := &Employee{12, "big", "tech", 10, ceo}
employeesForGraph["vpoe"] = vpoe
opsDirector := &Employee{11, "ops", "dude", 9, vpoe}
employeesForGraph["opsDirector"] = opsDirector
softDirector := &Employee{533, "sw", "peeps", 9, vpoe}
employeesForGraph["softDirector"] = softDirector
swMgr := &Employee{80, "me", "you", 8, softDirector}
employeesForGraph["swMgr"] = swMgr
otherMgr := &Employee{5, "other", "guy", 8, softDirector}
employeesForGraph["otherMgr"] = otherMgr
vpop := &Employee{54, "prod", "uct guy", 10, ceo}
employeesForGraph["vpop"] = vpop
}

var employeesForGraph = map[string]*Employee{}

type graphTestCase struct {
e1, e2 *Employee
closestMgr *Employee
expectedErr error
}

var testcasesForGraph []graphTestCase

func getTestCasesForGraph() {
testcasesForGraph = append(testcasesForGraph, graphTestCase{employeesForGraph["vpoe"], employeesForGraph["vpop"], employeesForGraph["ceo"], nil})
testcasesForGraph = append(testcasesForGraph, graphTestCase{employeesForGraph["opsDirector"], employeesForGraph["swMgr"], employeesForGraph["vpoe"], nil})
testcasesForGraph = append(testcasesForGraph, graphTestCase{employeesForGraph["otherMgr"], employeesForGraph["swMgr"], employeesForGraph["softDirector"], nil})
testcasesForGraph = append(testcasesForGraph, graphTestCase{employeesForGraph["vpoe"], employeesForGraph["ceo"], nil, NoCommonManagerError()})
}

func TestFindClosestManagerGraph(t *testing.T) {
t.Parallel()
createTestCompanyGraph()
getTestCasesForGraph()
for _, tc := range testcasesForGraph {
if mgr, err := FindClosestManagerGraph(tc.e1, tc.e2); err != tc.expectedErr {
t.Errorf("Expected error %v but got error %v", tc.expectedErr, err)
} else if mgr != tc.closestMgr {
t.Errorf("Expected %v but got %v", tc.closestMgr, mgr)
}
}
}

func BenchmarkFindClosestManagerGraph(b *testing.B) {
createTestCompanyGraph()
getTestCasesForGraph()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, tc := range testcasesForGraph {
FindClosestManagerGraph(tc.e1, tc.e2)
}
}
}

0 comments on commit 8b23d0f

Please sign in to comment.