Войти Регистрация
Код-ревью

11. Назначение заказов ближайшим курьерам

Сложная

Go · 59 строк

Каждые 2 секунды Assign получает пачку новых заказов и назначает каждому ближайшего свободного курьера. Координаты курьеров приходят из приложений раз в 5 секунд через UpdatePosition, параллельно с Assign.

В Москве в час пик — 30 000 курьеров онлайн и до 2 000 заказов в пачке. Отметьте строки с ошибками.

В работе: Ядро диспетчеризации доставки: от него зависит, через сколько минут приедет еда.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Ответ один на подход: после него показываем разбор.
геометриягонкисложность алгоритмаграничные случаи

Источник: на задачах Яндекса: диспетчеризация курьеров Доставки. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package dispatch
  2. import (
  3. "math"
  4. "sort"
  5. "sync"
  6. "time"
  7. )
  8. type Courier struct {
  9. ID string
  10. Lat float64
  11. Lon float64
  12. Busy bool
  13. Updated time.Time
  14. }
  15. type Order struct {
  16. ID string
  17. Lat float64
  18. Lon float64
  19. }
  20. type Dispatcher struct {
  21. mu sync.Mutex
  22. couriers map[string]*Courier
  23. }
  24. func (d *Dispatcher) UpdatePosition(id string, lat, lon float64) {
  25. c := d.couriers[id]
  26. c.Lat, c.Lon, c.Updated = lat, lon, time.Now()
  27. }
  28. func dist(lat1, lon1, lat2, lon2 float64) float64 {
  29. dx := lat1 - lat2
  30. dy := lon1 - lon2
  31. return math.Sqrt(dx*dx + dy*dy)
  32. }
  33. // Assign подбирает каждому заказу ближайшего свободного курьера.
  34. func (d *Dispatcher) Assign(orders []Order) map[string]string {
  35. d.mu.Lock()
  36. defer d.mu.Unlock()
  37. result := map[string]string{}
  38. for _, o := range orders {
  39. var free []*Courier
  40. for _, c := range d.couriers {
  41. if !c.Busy {
  42. free = append(free, c)
  43. }
  44. }
  45. sort.Slice(free, func(i, j int) bool {
  46. return dist(o.Lat, o.Lon, free[i].Lat, free[i].Lon) < dist(o.Lat, o.Lon, free[j].Lat, free[j].Lon)
  47. })
  48. best := free[0]
  49. result[o.ID] = best.ID
  50. }
  51. return result
  52. }