Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.FileOutputStream
- import scalax.io.{Resource, Output}
- import java.time.format.DateTimeFormatter
- import java.time.LocalDate
- import java.time.temporal.ChronoUnit
- /**
- * Created by nigredo on 07.06.2014.
- */
- object Fp06 extends App {
- val zero = LocalDate.of(2013, 9, 27) // Начинаем отсчет с первого зафиксированного события
- val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
- def string2Date(s: String): LocalDate =
- LocalDate.parse(s, formatter)
- def date2Int(date: LocalDate): Int =
- zero.until(date, ChronoUnit.DAYS).toInt
- def string2Int = string2Date _ andThen date2Int
- val events =
- Array(
- "27.09.2013", "06.10.2013", "23.10.2013", "06.11.2013", "26.11.2013", "27.11.2013", "21.12.2013", "30.12.2013",
- "06.01.2014", "16.01.2014", "17.01.2014", "21.01.2014", "25.01.2014", "26.01.2014", "05.02.2014", "11.02.2014",
- "21.02.2014", "02.03.2014", "07.03.2014", "30.03.2014", "08.04.2014", "18.04.2014", "23.04.2014", "27.04.2014",
- "02.05.2014", "15.05.2014", "17.05.2014", "18.05.2014", "19.05.2014", "20.05.2014", "25.05.2014", "26.05.2014",
- "28.05.2014") map string2Int
- val start = events.head // 0 из-за выбора точки отсчета
- val finish = events.last
- val eventsSet = Set(events: _*)
- /**
- * Последовательность: для каждого дня в рассматриваемом промежутке - true если событие случилось в этот день
- */
- val timeline: Seq[Boolean] = start to finish map eventsSet
- val defaultProbability = (timeline count identity).toDouble / timeline.length
- def transposeUneven[A](xss: Seq[Seq[A]]): Stream[Seq[A]] = xss.filter(_.nonEmpty) match {
- case Seq() => Stream()
- case xss => (xss map (_.head)) #:: transposeUneven(xss map (_.tail))
- }
- def byRemainder(period: Int): Seq[Seq[Boolean]] = transposeUneven(timeline.grouped(period).toSeq)
- case class Pattern(period: Int, offset: Int, probability: Double, datasetSize: Int)
- def patterns(period: Int): Seq[Pattern] = for {
- (data, remainder) <- byRemainder(period).zipWithIndex
- positives = data count identity
- all = data.length
- } yield Pattern(period, remainder, positives.toDouble / all, all)
- // Пропускаем наблюдения для слишком длинных периодов
- val allPatterns: Seq[Pattern] = 2 to ((finish - start) / 4) flatMap patterns
- def isRelevant(p: Pattern): Boolean =
- p.probability - defaultProbability > defaultProbability.max(1 / math.sqrt(p.datasetSize))
- val relevantPatterns = allPatterns filter (isRelevant)
- def getProbability(day: Int): Double =
- relevantPatterns
- .filter(p => day % p.period == p.offset)
- .sortBy(p => -p.probability * p.datasetSize)
- .map(_.probability)
- .headOption.getOrElse(0.0)
- def getProbability: LocalDate => Double = date2Int _ andThen getProbability
- val forecastStart = LocalDate.of(2014, 06, 06)
- val forecastEnd = LocalDate.of(2015, 01, 01)
- def getResultLine(date: LocalDate): String =
- f"${date.format(formatter)}%s: ${100 * getProbability(date)}%2.4f"
- val resultLines: String =
- Stream.iterate(forecastStart)(_.plusDays(1))
- .takeWhile(_.isBefore(forecastEnd))
- .map(getResultLine)
- .mkString("\n")
- val output: Output = Resource.fromOutputStream(new FileOutputStream("d:/downloads/out.txt"))
- output.write(resultLines)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement