[contest] Is a Cow an animal ++

miasma _ at freenode.net.via_irc
Wed Sep 29 12:59:56 PDT 2010


29.9.2010 18:57, Danny Wilson wrote:
> Op Wed, 29 Sep 2010 15:33:29 +0200 schreef retard <re at tard.com.invalid>:
>
>> Wed, 29 Sep 2010 09:21:11 +0200, Norbert Nemec wrote:
>>
>> I experimented with this (a colleague of mine already solved all 11 cases
>> at compile time with Scala)
>
> Would your colleague share the Scala solution? :-)

Minor note about the implementation -- the state passing style isn't 
idiomatic Scala and the HumanFood tag might be implementable more 
modularly with implicits. This is just a really quick rewrite of the 
existing parametric C++ code.

---

abstract class EnergyEntity(var energy: Int)

abstract class Food(energy: Int) extends EnergyEntity(energy)

abstract class Meat(energy: Int) extends Food(energy) with HumanFood

abstract class Vegetable[+VegType <: Food](energy: Int) extends 
Food(energy) with Edible[VegType]

class EatenMeat(energy: Int) extends Meat(energy)

abstract class EdibleMeat(energy: Int) extends Meat(energy) with 
Edible[Meat] {
   def result = new EatenMeat(energy)
}

trait HumanFood

trait Edible[+Result <: Food] {
   protected def energy: Int
   protected def result: Result

   def eaten: (Int, Result) = (energy, result)
}

abstract class Animal(i_energy: Int) extends EnergyEntity(i_energy)

class DeadAnimal(i_energy: Int) extends Animal(i_energy)

abstract class AliveAnimal[When_slaughtered, Accepted_food <: Food](
   val when_slaughtered: Int => When_slaughtered,
   i_energy: Int) extends Animal(i_energy) {

   def eat[R <: Food](food: Edible[R] with Accepted_food) = {
     val (food_energy, food_result) = food.eaten
     energy += food_energy
     (this, food_result)
   }

   def slaughter =
     (new DeadAnimal(energy), when_slaughtered(energy))
}

class Carrot(energy: Int) extends Vegetable[Carrot](energy) with HumanFood {
   def result = this
}

class Grass(energy: Int) extends Vegetable[Grass](energy) {
   def result = this
}

class Beef(energy: Int) extends EdibleMeat(energy)
class Dead_rabbit(energy: Int) extends EdibleMeat(energy)
class Dead_human(energy: Int) extends EdibleMeat(energy)

class Cow(energy: Int) extends
   AliveAnimal[Beef, Grass](new Beef(_), energy)

class Rabbit(energy: Int) extends
   AliveAnimal[Dead_rabbit, Carrot](new Dead_rabbit(_), energy)

class Human(energy: Int) extends
   AliveAnimal[Dead_human, Food with HumanFood](new Dead_human(_), energy)

object test {

   def main(a: Array[String]) {
     val grass         = new Grass(5)
     val carrot        = new Carrot(10)

     val a_rabbit      = new Rabbit(100)
     val a_cow         = new Cow(1000)
     val a_human       = new Human(300)
     val another_human = new Human(350)

     val animals = List(a_rabbit, a_cow, a_human, another_human)

     for (a <- animals) println(a + " " + a.energy)

     val (a_rabbit2, carrot2) = a_rabbit eat carrot
     val (a_cow2, grass2) = a_cow eat grass

     val (a_rabbit3, a_dead_rabbit) = a_rabbit2.slaughter
     val (a_cow3, a_beef) = a_cow2.slaughter

     val (a_human2, carrot3) = a_human eat carrot2
     val (a_human3, carrot4) = a_human2 eat carrot3
     val (a_human4, a_beef2) = a_human3 eat a_beef
     val (a_human5, a_dead_rabbit2) = a_human4 eat a_dead_rabbit

     val (another_human2, human_slaughter) = another_human.slaughter
     val (a_human6, human_slaughter2) = a_human5 eat human_slaughter

     if (a_human6.energy != 1785) throw new Error("Failed")

     println("ok")

//    (new Cow(10)).slaughter.eat(grass)
//    (new Cow(10)).slaughter.slaughter
//    carrot4 eat grass
//    carrot4.slaughter
//    (new Cow(10)) eat carrot
//    (new Cow(10)).eat((new Cow(10)).slaughter)
//    a_human6 eat (new Cow(10))
//    a_human6 eat grass
//    a_human6 eat a_beef2
//    a_cow3 eat grass
//    a_cow3.slaughter

   }
}


More information about the Digitalmars-d mailing list