Вычислить максимальное население предоставлен список людей, рождение и смерть год


Я недавно наткнулась на краткое программирования головоломка подсказка (говорят, что в три раза быстро), в котором просил вернуть года, что население достигло максимума.

Фактический алгоритм, чтобы вычислить это можно сделать несколькими способами, и не особо сложно, но у меня недавно было сложно себе написать .. кхм .. "более функциональный" код.

Существует несколько принципов ФП, но Главного никто не производит то, что разработчики называют "побочными эффектами". Я надеюсь, чтобы добраться до точки, где я не столько опираюсь на классический объектно-ориентированной модели и чувствовать себя более уверенно, ныряя в функциональном стиле. Конечно, это требует практики, поэтому я решил потратить немного времени полировать мой код, чтобы удовлетворить мои внутренние потребности:

val persons = Seq(
  Person(2000, 2010),
  Person(2000, 2005),
  Person(1990, 2005)
)

// Create an array of population change.
val births = persons.groupBy(_.birthYear).mapValues(_.length)
val deaths = persons.groupBy(_.deathYear).mapValues(_.length)
val populationChanges = (births.keySet ++ deaths.keySet).map { year =>
  (year, births.getOrElse(year, 0) - deaths.getOrElse(year, 0))
}.toMap

println("populationChanges", populationChanges)

val sortedYears = populationChanges.keys.toSeq.sorted
println(sortedYears)

// construct an array of total populations
val populations = populationChanges.toSeq
  .sortBy(_._1)
  .scanLeft(0) { (a, b) => a + b._2 }
  .tail
  .zip(sortedYears) // this is a bit hacky
  .map{ case(count, year) => (year, count) }

println("pop", populations)
println("max pop", populations.maxBy(_._2)) // (2000, 3)

Это демонстрация того, что я создал после нескольких минут итерации.

Я был вполне способен подготовить список изменений населения и оттуда, выполняются дальнейшие преобразования, чтобы прибыть в список общей численности населения за каждый год. Оттуда, определяющих год, что население островерхие был тривиальным.

Однако, я не полностью доволен этим решением. Я мог бы быть слишком категоричным, но на мой взгляд, я бы не нарушая функции карту для ссылки на внешние ценности, и хотя оказалось целесообразным в данном случае.



107
0
задан 25 января 2018 в 08:01 Источник Поделиться
Комментарии
1 ответ

Ваш подход-это не плохо, если вы хотите сделать несколько анализов населения с течением времени. Для программирования головоломки это часто полезно, чтобы сосредоточиться на то, что запрашивается и оставить другие интересные вещи еще на один день.

persons.flatMap(p => Seq((p.birthYear, 1), (p.deathYear, -1)))
.sorted
.foldLeft((0,0,0)){case ((mxYear,mxPop,curPop), (thisYear,dif)) =>
if (curPop+dif > mxPop) (thisYear, curPop+dif, curPop+dif)
else (mxYear, mxPop, curPop+dif)
}._1 //res0: Int = 2000

В этом случае данные


  • проходится один раз - чтобы вложить 1 или -1

  • отсортированный - к вам все годы в порядке

  • прошла 2-й и последний раз - для подсчета изменения населения и сохранить Максов

1
ответ дан 26 января 2018 в 09:01 Источник Поделиться