Advertisement
nigredo

Untitled

Jun 7th, 2014
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.49 KB | None | 0 0
  1. import java.io.FileOutputStream
  2. import scalax.io.{Resource, Output}
  3. import java.time.format.DateTimeFormatter
  4. import java.time.LocalDate
  5. import java.time.temporal.ChronoUnit
  6.  
  7. /**
  8.  * Created by nigredo on 07.06.2014.
  9.  */
  10. object Fp06 extends App {
  11.  
  12.   val zero = LocalDate.of(2013, 9, 27) // Начинаем отсчет с первого зафиксированного события
  13.   val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
  14.  
  15.   def string2Date(s: String): LocalDate =
  16.     LocalDate.parse(s, formatter)
  17.  
  18.   def date2Int(date: LocalDate): Int =
  19.     zero.until(date, ChronoUnit.DAYS).toInt
  20.  
  21.   def string2Int = string2Date _ andThen date2Int
  22.   val events =
  23.     Array(
  24.       "27.09.2013", "06.10.2013", "23.10.2013", "06.11.2013", "26.11.2013", "27.11.2013", "21.12.2013", "30.12.2013",
  25.       "06.01.2014", "16.01.2014", "17.01.2014", "21.01.2014", "25.01.2014", "26.01.2014", "05.02.2014", "11.02.2014",
  26.       "21.02.2014", "02.03.2014", "07.03.2014", "30.03.2014", "08.04.2014", "18.04.2014", "23.04.2014", "27.04.2014",
  27.       "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.       "28.05.2014") map string2Int
  29.  
  30.   val start = events.head // 0 из-за выбора точки отсчета
  31.   val finish = events.last
  32.  
  33.   val eventsSet = Set(events: _*)
  34.  
  35.   /**
  36.    * Последовательность: для каждого дня в рассматриваемом промежутке - true если событие случилось в этот день
  37.    */
  38.   val timeline: Seq[Boolean] = start to finish map eventsSet
  39.  
  40.   val defaultProbability = (timeline count identity).toDouble / timeline.length
  41.  
  42.   def transposeUneven[A](xss: Seq[Seq[A]]): Stream[Seq[A]] = xss.filter(_.nonEmpty) match {
  43.     case Seq() => Stream()
  44.     case xss => (xss map (_.head)) #:: transposeUneven(xss map (_.tail))
  45.   }
  46.  
  47.   def byRemainder(period: Int): Seq[Seq[Boolean]] = transposeUneven(timeline.grouped(period).toSeq)
  48.  
  49.   case class Pattern(period: Int, offset: Int, probability: Double, datasetSize: Int)
  50.  
  51.   def patterns(period: Int): Seq[Pattern] = for {
  52.     (data, remainder) <- byRemainder(period).zipWithIndex
  53.     positives = data count identity
  54.     all = data.length
  55.   } yield Pattern(period, remainder, positives.toDouble / all, all)
  56.  
  57.   // Пропускаем наблюдения для слишком длинных периодов
  58.   val allPatterns: Seq[Pattern] = 2 to ((finish - start) / 4) flatMap patterns
  59.  
  60.   def isRelevant(p: Pattern): Boolean =
  61.     p.probability - defaultProbability > defaultProbability.max(1 / math.sqrt(p.datasetSize))
  62.  
  63.   val relevantPatterns = allPatterns filter (isRelevant)
  64.  
  65.   def getProbability(day: Int): Double =
  66.     relevantPatterns
  67.       .filter(p => day % p.period == p.offset)
  68.       .sortBy(p => -p.probability * p.datasetSize)
  69.       .map(_.probability)
  70.       .headOption.getOrElse(0.0)
  71.  
  72.   def getProbability: LocalDate => Double = date2Int _ andThen getProbability
  73.  
  74.   val forecastStart = LocalDate.of(2014, 06, 06)
  75.   val forecastEnd = LocalDate.of(2015, 01, 01)
  76.  
  77.   def getResultLine(date: LocalDate): String =
  78.     f"${date.format(formatter)}%s: ${100 * getProbability(date)}%2.4f"
  79.  
  80.   val resultLines: String =
  81.     Stream.iterate(forecastStart)(_.plusDays(1))
  82.       .takeWhile(_.isBefore(forecastEnd))
  83.       .map(getResultLine)
  84.       .mkString("\n")
  85.  
  86.   val output: Output = Resource.fromOutputStream(new FileOutputStream("d:/downloads/out.txt"))
  87.  
  88.   output.write(resultLines)
  89. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement