Welcome to the site of Mike Moran. You may find something useful or interesting here. If you're lucky.
Welcome to the site of Mike Moran. You may find something useful or interesting here. If you're lucky.
It's LSystem Sunday! I was curious about investigating an assertion that I'd made the other day: that the dragon curve loops back and traces over itself. Turns out, I was talking nonsense:
|
|
The above shows the dragon curve at it's 7th expansion, with an animation of how this is drawn on the right. As you can see, it has overlapping points, but not overlapping line segments. I was wrong.
Btw, yes, I know, but today is still logical Sunday for me.
Note: animated gif rendering supported by http://elliot.kroo.net/software/java/GifSequenceWriter/
Btw, doing conditional GET in Jersey using ETags is piss-easy. Combine this with apache server-side caching and you have a very nice persistent caching solution. I can now do some pretty inefficient LSystem drawing without worrying about my server melting ;-) For example:

LSystems have once-again distracted me, this time from German homework:



You're in a museum. You're looking at these, a foot off the ground, below a display case. Which are you expected to play with?
Now imagine you're a three-old child. Hint: if you start playing with the flap on the right a moany-faced man will start up his moaning machinery until your father directs your hand to the button. Why didn't they use covers which aren't openable by kids?
The National Museum of Scotland has many 'play pods' interspersed throughout the museum, between the more adult-friendly displays. This leads to a less-subtle form of dissonance. In one example on the bottom floor, there are some blocks which you can assemble to illustrate the strength of a Keystone Bridge. My first inclination was to demonstrate this literally to Nils by getting him to sit on the keystone. However, this involved getting some shoe marks on base of the display. I was soon told to get him down and "please wipe off the shoe marks". Perhaps I went a little too far here, but nevertheless the point is that you are always questioning exactly what you're expected to do: encourage interaction or enforce a barrier? This adds stress to your visit and makes you less likely to come back again. This is surely not the intent.
Snow, snow, lots of snow!
More arsing around with Scala. This time, trying to reimplement lesscss. This is about two hours worth of hacking:
object LessParser extends RegexParsers {
def parse(spec: String) : Sequence = {
parseAll(sequence, spec) match {
case Success(l, _) => l
case Failure(m, _) => throw new IllegalArgumentException(m)
case Error(m, _) => throw new IllegalArgumentException(m)
}
}
def sequence = rep(namedNested | atom) ^^ {
Sequence(_)
}
def namedNested = nestedName~"{"~rep(atom)~"}" ^^ {
case name~"{"~contents~"}" => NamedNested(name, contents)
}
def nestedName = """[\.\#][a-zA-Z]+""".r
def atom = variableDef | variableUse | text
def text = "[^@{}]+".r ^^ { Text(_) }
def variableDef = "@"~variableName~":"~variableValue~";" ^^ {
case "@"~name~":"~value~";" => VariableDef(name, value)
}
def variableUse = "@"~variableName ^^ {
case "@"~name => VariableUse(name)
}
def variableName = "[a-z-]+".r
def variableValue = "[^;]+".r
}
abstract class Tree {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String]
}
case class Sequence(parts: List[Tree]) extends Tree {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = {
parts.foldLeft (defs) { (accumDefs : Map[String, String], part : Tree) =>
part.eval(accumDefs, out)
}
}
}
case class NamedNested(name: String, contents: List[Atom]) extends Tree {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = {
out.append(name)
out.append(" {")
contents.foldLeft (defs) { (accumDefs : Map[String, String], part : Tree) =>
part.eval(accumDefs, out)
}
out.append("}")
defs
}
}
abstract case class Atom() extends Tree
case class VariableDef(name: String, value: String) extends Atom {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = {
defs + (name -> value)
}
}
case class VariableUse(name: String) extends Atom {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = {
out.append(defs(name))
defs
}
}
case class Text(value: String) extends Atom {
def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = {
out.append(value)
defs
}
}
object Less {
def main(args : Array[String]) : Unit = {
println(LessParser.parse("@nice-blue: #5B83AD;"))
println(LessParser.parse("@nice-blue"))
println(LessParser.parse("@nice-blue: #5B83AD; @nice-blue"))
println(LessParser.parse("@nice-blue: #5B83AD; #header { background-color: @nice-blue; }"))
var fullExample = """
@nice-blue: #5B83AD;
#header { background-color: @nice-blue; }
"""
var buf = new StringBuffer
LessParser.parse(fullExample).eval(Map(), buf)
println(buf)
}
}
Output:
Sequence(List(VariableDef(nice-blue,#5B83AD)))
Sequence(List(VariableUse(nice-blue)))
Sequence(List(VariableDef(nice-blue,#5B83AD), VariableUse(nice-blue)))
Sequence(List(VariableDef(nice-blue,#5B83AD), NamedNested(#header,List(Text(background-color: ),
VariableUse(nice-blue), Text(; )))))
#header {background-color: #5B83AD; }
It does variables and the beginnings of mixins. It's actually quite lame e.g. it throws away whitespace. Hohum, time to learn more about parsers in Scala...