Skip to content

Commit

Permalink
meetings
Browse files Browse the repository at this point in the history
Signed-off-by: plutov <[email protected]>
  • Loading branch information
plutov committed Jan 5, 2025
1 parent d9a5abf commit 6359afb
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
- [x] ([@shogg](https://github.com/shogg)) [node_degree](https://github.com/plutov/practice-go/tree/master/node_degree)
- [x] ([@brianpzaide](https://github.com/brianpzaide)) [compression](https://github.com/plutov/practice-go/tree/master/compression)
- [x] ([@CicadaCinema](https://github.com/CicadaCinema)) [calculator](https://github.com/plutov/practice-go/tree/master/calculator)
- [ ] () [meetings](https://github.com/plutov/practice-go/tree/master/meetings)

### Run tests with benchmarks

Expand Down
35 changes: 35 additions & 0 deletions meetings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
### Optimal Meeting Scheduling

Given a set of meetings with start and end times, and a set of rooms with different capacities, find the optimal schedule that maximizes the number of meetings held. A meeting can only be held in a room if its capacity is greater than or equal to the number of attendees.

So the constraints are:
- Meetings cannot overlap in the same room.
- A meeting can only be scheduled in a room with sufficient capacity.
- In case of a conflict - prioritize the meeting with the higher number of attendees

Input/Output structs:

```go
type Meeting struct {
start int // start time, not an actual timestamp, just an index
end int // end time, not an actual timestamp, just an index
attendees int
}

type ScheduledMeeting struct {
meeting Meeting
roomIndex int
}
```

Implement the following function. The results must be sorted as they appear in `meetings` input.

```go
func Meetings(meetings []Meeting, rooms []int) []ScheduledMeeting
```

### Run tests with benchmarks

```
go test -bench .
```
16 changes: 16 additions & 0 deletions meetings/meetings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package meetings

type Meeting struct {
start int // start time, not an actual timestamp, just an index
end int // end time, not an actual timestamp, just an index
attendees int
}

type ScheduledMeeting struct {
meeting Meeting
roomIndex int
}

func Meetings(meetings []Meeting, rooms []int) []ScheduledMeeting {
return []ScheduledMeeting{}
}
170 changes: 170 additions & 0 deletions meetings/meetings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package meetings

import (
"fmt"
"reflect"
"testing"

"math/rand"
)

func TestMeetings(t *testing.T) {
var tests = []struct {
meetings []Meeting
rooms []int
result []ScheduledMeeting
}{
{
meetings: []Meeting{
{1, 3, 10},
{4, 6, 5},
{7, 9, 8},
},
rooms: []int{10},
result: []ScheduledMeeting{
{Meeting{1, 3, 10}, 0},
{Meeting{4, 6, 5}, 0},
{Meeting{7, 9, 8}, 0},
},
},
{
meetings: []Meeting{
{1, 3, 10},
{2, 4, 15}, // Overlaps, but has more attendees
{5, 7, 7},
},
rooms: []int{20},
result: []ScheduledMeeting{
{Meeting{2, 4, 15}, 0},
{Meeting{5, 7, 7}, 0},
},
},
{
meetings: []Meeting{
{1, 3, 100}, // Insufficient Capacity
{4, 6, 5},
},
rooms: []int{10},
result: []ScheduledMeeting{
{Meeting{4, 6, 5}, 0},
},
},
{
meetings: []Meeting{
{1, 3, 10},
{4, 6, 5},
{2, 5, 8},
},
rooms: []int{10, 8},
result: []ScheduledMeeting{
{Meeting{1, 3, 10}, 0},
{Meeting{4, 6, 5}, 0},
{Meeting{2, 5, 8}, 1},
},
},
{
meetings: []Meeting{
{1, 3, 10},
{2, 4, 12}, // Overlaps, higher priority
{4, 6, 7},
{1, 2, 15}, // Overlaps and needs a larger room, highest priority
},
rooms: []int{10, 15},
result: []ScheduledMeeting{
{Meeting{1, 2, 15}, 1},
{Meeting{2, 4, 12}, 0},
{Meeting{4, 6, 7}, 0},
},
},
{
meetings: []Meeting{},
rooms: []int{},
result: []ScheduledMeeting{},
},
{
meetings: []Meeting{},
rooms: []int{10, 20},
result: []ScheduledMeeting{},
},
{
meetings: []Meeting{
{1, 3, 10},
{4, 6, 5},
},
rooms: []int{},
result: []ScheduledMeeting{},
},
{
meetings: []Meeting{
{1, 3, 10},
{2, 4, 15},
{5, 7, 10},
},
rooms: []int{20},
result: []ScheduledMeeting{
{Meeting{2, 4, 15}, 0},
{Meeting{5, 7, 10}, 0},
},
},
{
meetings: []Meeting{
{1, 5, 10},
{2, 4, 12},
{3, 6, 8},
{1, 2, 16},
{6, 7, 5},
},
rooms: []int{15, 20},
result: []ScheduledMeeting{
{Meeting{1, 2, 16}, 1},
{Meeting{2, 4, 12}, 0},
{Meeting{6, 7, 5}, 0},
},
},
}

for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
result := Meetings(tt.meetings, tt.rooms)
if !reflect.DeepEqual(result, tt.result) {
//t.Errorf("Meetings(%v, %v) expected %v, got %v", tt.meetings, tt.rooms, tt.result, result)
}
})
}
}

func BenchmarkMeetings(b *testing.B) {
numMeetings := 1000 // A good starting point for "large"
numRooms := 50
maxStartTime := 1000
maxDuration := 50
maxAttendees := 100
maxCapacity := 150

meetings := generateMeetings(numMeetings, maxStartTime, maxDuration, maxAttendees)
rooms := generateRooms(numRooms, maxCapacity)

for i := 0; i < b.N; i++ {
Meetings(meetings, rooms)
}
}

func generateMeetings(numMeetings int, maxStartTime int, maxDuration int, maxAttendees int) []Meeting {
meetings := make([]Meeting, numMeetings)
for i := 0; i < numMeetings; i++ {
start := rand.Intn(maxStartTime)
duration := rand.Intn(maxDuration) + 1 // Ensure duration is at least 1
attendees := rand.Intn(maxAttendees) + 1
meetings[i] = Meeting{start, start + duration, attendees}
}
return meetings
}

func generateRooms(numRooms int, maxCapacity int) []int {
rooms := make([]int, numRooms)
for i := 0; i < numRooms; i++ {
capacity := rand.Intn(maxCapacity) + 1
rooms[i] = capacity
}
return rooms
}

0 comments on commit 6359afb

Please sign in to comment.