Last active
December 18, 2015 11:09
-
-
Save tyrcho/5773673 to your computer and use it in GitHub Desktop.
Exponentially decreasing blips
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.collection.immutable.SortedMap | |
import scala.collection.immutable.NumericRange | |
object Main extends App { | |
val halfLife: Double = 60 | |
val data = Seq( | |
Blip("a", strength = 1), | |
Blip("b", strength = 1), | |
Blip("c", strength = 1), | |
Blip("d", strength = 1), | |
Blip("a", timestamp = 10, strength = 10), | |
Blip("b", timestamp = 40, strength = 8), | |
Blip("c", timestamp = 70, strength = 10), | |
Blip("b", timestamp = 90, strength = 7), | |
Blip("d", timestamp = 105, strength = 3)) | |
val overTime = valuesOverTime(data, 0L to (120, 5)) | |
val keys = (for { | |
(_, blips) <- overTime | |
b <- blips | |
} yield b.id).toSet.toList sorted | |
println("time\t" + (keys mkString "\t")) | |
for ((t, blips) <- overTime) { | |
print(t + "\t") | |
def value(k: String) = blips find (_.id == k) map (_.strength) getOrElse 0 | |
println(((for (k <- keys) yield value(k)) mkString "\t").replaceAll("\\.", ",")) | |
} | |
case class Blip(id: String, strength: Double, timestamp: Long = 0) { | |
override def toString = f"$id : $strength%.2f" + (if (timestamp > 0) s"@$timestamp" else "") | |
} | |
def valuesOverTime(blips: Iterable[Blip], timeRange: NumericRange[Long]) = | |
for (t <- timeRange) | |
yield t -> average(blips filter (_.timestamp <= t), t) | |
def average(blips: Iterable[Blip], time: Long): List[Blip] = { | |
val ponderedBlips = for (b <- blips.toSeq) | |
yield Blip(b.id, weaken(b.strength, time - b.timestamp)) | |
val aggregated = for ((id, b) <- ponderedBlips groupBy (_.id)) | |
yield Blip(id, b.map(_.strength).sum) | |
// val total = aggregated map (_.strength) sum; | |
// def toPercent(b: Blip) = b.copy(strength = b.strength / total * 100) | |
aggregated.toList sortBy (-_.strength) //map toPercent | |
} | |
def weaken(strength: Double, duration: Long): Double = | |
strength / Math.pow(2, duration / halfLife) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment