krzysztof-w
4/9/2015 - 4:38 PM

einstein.scala

val time = System.currentTimeMillis();
  val colors = List('red, 'yellow, 'green, 'blue, 'white)
  val nations = List('brit, 'swede, 'dane, 'german, 'norwegian)
  val beverages = List('tea, 'coffee, 'milk, 'water, 'beer)
  val cigars = List('pallmall, 'dunhill, 'blend, 'bluemaster, 'prince)
  val pets = List('fish, 'dog, 'bird, 'cat, 'horse)

  def thingToPerson(ordering: Seq[Symbol]): Map[Symbol, Int] =
    ordering.zip(0 until 5).toMap
  def ownagePerms(stuff: List[Symbol]) =
    stuff.permutations.map(thingToPerson).toStream
  def einsteinPuzzleSolutions: Stream[Array[Map[Symbol, Int]]] =
    for (color <- ownagePerms(colors)
         if color('green) == color('white) - 1;
         nation <- ownagePerms(nations)
         if nation('brit) == color('red) &&
           nation('norwegian) == 0 &&
           math.abs(nation('norwegian) - color('blue)) == 1;
         beverage <- ownagePerms(beverages)
         if nation('dane) == beverage('tea) &&
           color('green) == beverage('coffee) &&
           beverage('milk) == 2;
         cigar <- ownagePerms(cigars)
         if color('yellow) == cigar('dunhill) &&
           cigar('bluemaster) == beverage('beer) &&
           nation('german) == cigar('prince);
         pet <- ownagePerms(pets)
         if nation('swede) == pet('dog) &&
           cigar('pallmall) == pet('bird) &&
           math.abs(cigar('blend) - pet('cat)) == 1 &&
           math.abs(cigar('dunhill) - pet('horse)) == 1)
    yield Array(color, nation, beverage, cigar, pet)

  def prettyPrintResult() {
    val firstSolution = einsteinPuzzleSolutions.head
    val reversedMaps = for (map <- firstSolution)
    yield for ((a, b) <- map)
      yield (b, a)
    for (person <- 0 until 5) {
      print("Person #" + person + ": ")
      print(reversedMaps.map(_(person)).mkString("\n"))
    }
  }

val e = einsteinPuzzleSolutions.head.map({_.map{a => (a._2, List(a._1))}});
e.reduce { (l, r) =>
  l.map { k =>
    (k._1, l.get(k._1).get ++ r.getOrElse(k._1, Nil))
  }
}.toList.map{_._2}

time - System.currentTimeMillis();