Skip to content

Commit

Permalink
Merge 9974475 into f95416e
Browse files Browse the repository at this point in the history
  • Loading branch information
vaskoz committed Aug 5, 2019
2 parents f95416e + 9974475 commit 5868cc1
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,4 +333,5 @@ problems from
* [Day 339](https://github.com/vaskoz/dailycodingproblem-go/issues/676)
* [Day 340](https://github.com/vaskoz/dailycodingproblem-go/issues/679)
* [Day 342](https://github.com/vaskoz/dailycodingproblem-go/issues/682)
* [Day 346](https://github.com/vaskoz/dailycodingproblem-go/issues/688)
* [Day 347](https://github.com/vaskoz/dailycodingproblem-go/issues/689)
41 changes: 41 additions & 0 deletions day346/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package day346

// Flights represents all the flights and their prices.
type Flights map[string]map[string]int

// CheapestItinerary returns the cheapest itinerary that respects the
// maxConnections limit.
// Effectively, DFS for all possible answers that don't exceed the maximum
// number of connections.
// Runs in DFS performance. O(N+M)
func CheapestItinerary(flights Flights, origin, destination string, maxConnections int) ([]string, int) {
visited := make(map[string]struct{})
return cheapestItinerary(flights, origin, destination, maxConnections, visited)
}

func cheapestItinerary(flights Flights, origin, destination string, connections int,
visited map[string]struct{}) ([]string, int) {
if connections < 0 {
return nil, 0
}
if origin == destination {
return []string{destination}, 0
}
cheapest := int(^uint(0) >> 1)
var itinerary []string
for next := range flights[origin] {
if _, seen := visited[next]; seen {
continue
}
visited[next] = struct{}{}
segments, price := cheapestItinerary(flights, next, destination, connections-1, visited)
if len(segments) != 0 {
if total := flights[origin][next] + price; total < cheapest {
cheapest = total
itinerary = append([]string{origin}, segments...)
}
}
delete(visited, next)
}
return itinerary, cheapest
}
84 changes: 84 additions & 0 deletions day346/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package day346

import (
"reflect"
"testing"
)

// nolint
var testcases = []struct {
flights Flights
origin, destination string
connections int
itinerary []string
cost int
}{
{
Flights{
"JFK": {
"ATL": 150,
"HKG": 800,
"LAX": 500,
},
"ATL": {
"SFO": 400,
"JFK": 1,
"ORD": 90,
},
"ORD": {
"LAX": 200,
},
"LAX": {
"DFW": 80,
},
},
"JFK",
"LAX",
3,
[]string{"JFK", "ATL", "ORD", "LAX"},
440,
},
{
Flights{
"JFK": {
"ATL": 150,
"HKG": 800,
"LAX": 500,
},
"ATL": {
"SFO": 400,
"ORD": 90,
},
"ORD": {
"LAX": 200,
},
"LAX": {
"DFW": 80,
},
},
"JFK",
"LAX",
1,
[]string{"JFK", "LAX"},
500,
},
}

func TestCheapestItinerary(t *testing.T) {
t.Parallel()
for _, tc := range testcases {
if itinerary, price := CheapestItinerary(tc.flights, tc.origin,
tc.destination, tc.connections); !reflect.DeepEqual(tc.itinerary, itinerary) ||
tc.cost != price {
t.Errorf("Expected (%v,%v), got (%v,%v)", tc.itinerary, tc.cost, itinerary, price)
}
}
}

func BenchmarkCheapestItinerary(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
CheapestItinerary(tc.flights, tc.origin, tc.destination, tc.connections)
}
}
}

0 comments on commit 5868cc1

Please sign in to comment.