diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 72d87cec11eade2afab25312c5438725a461073c..b76d05c6064b7c5f33760e6e7cc58429403ad38e 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -68,6 +68,16 @@ object PrettyPrinter {
   private def pp(tree: Expr, sb: StringBuffer, lvl: Int): StringBuffer = tree match {
     case Variable(id) => sb.append(id)
     case DeBruijnIndex(idx) => sb.append("_" + idx)
+    case LetTuple(bs,d,e) => {
+        //pp(e, pp(d, sb.append("(let (" + b + " := "), lvl).append(") in "), lvl).append(")")
+      sb.append("(let (" + bs.mkString(",") + " := ");
+      pp(d, sb, lvl)
+      sb.append(") in\n")
+      ind(sb, lvl+1)
+      pp(e, sb, lvl+1)
+      sb.append(")")
+      sb
+    }
     case Let(b,d,e) => {
         //pp(e, pp(d, sb.append("(let (" + b + " := "), lvl).append(") in "), lvl).append(")")
       sb.append("(let (" + b + " := ");
diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala
index e32b3dd7a888b3cc04dbb9ab43e3ff7823d74777..259ce7911c506e0b9f9f801c0d8d09f2542f4cfe 100644
--- a/src/main/scala/leon/purescala/Trees.scala
+++ b/src/main/scala/leon/purescala/Trees.scala
@@ -59,12 +59,12 @@ object Trees {
       setType(et)
   }
 
-  //case class LetTuple(binders: Seq[Identifier], value: Expr, body: Expr) extends Expr {
-  //  binders.foreach(_.markAsLetBinder)
-  //  val et = body.getType
-  //  if(et != Untyped)
-  //    setType(et)
-  //}
+  case class LetTuple(binders: Seq[Identifier], value: Expr, body: Expr) extends Expr {
+    binders.foreach(_.markAsLetBinder)
+    val et = body.getType
+    if(et != Untyped)
+      setType(et)
+  }
 
   case class LetDef(value: FunDef, body: Expr) extends Expr {
     val et = body.getType
diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala
index b9dc74af176689e0a534bb6c753051781ac06a87..83ed51723781298115c03088ac2370a0ce938c37 100644
--- a/src/main/scala/leon/synthesis/Rules.scala
+++ b/src/main/scala/leon/synthesis/Rules.scala
@@ -1,11 +1,57 @@
 package leon
 package synthesis
 
+import purescala.Trees._
+
 object Rules {
-  def all = List()
+  def all = List(
+    OnePoint
+  )
 }
 
 
 abstract class Rule(val name: String) {
   def isApplicable(p: Problem, parent: Task): List[Task]
 }
+
+object OnePoint extends Rule("One-point") {
+  def isApplicable(p: Problem, parent: Task): List[Task] = {
+
+    p.phi match {
+      case And(exprs) =>
+        val candidates = exprs.collect {
+          case eq @ Equals(Variable(x), e) if (p.xs contains x) && !(variablesOf(e) contains x) =>
+            (x, e, eq)
+          case eq @ Equals(e, Variable(x)) if (p.xs contains x) && !(variablesOf(e) contains x) =>
+            (x, e, eq)
+        }
+
+        if (!candidates.isEmpty) {
+          val (x, e, eq) = candidates.head
+
+          val others = exprs.filter(_ != eq)
+          val oxs    = p.xs.filter(_ != x)
+
+          val newProblem = Problem(p.as, replace(Map(Variable(x) -> e), And(others)), oxs)
+
+          val onSuccess: List[Solution] => Solution = { 
+            case List(Solution(pre, term)) =>
+              if (oxs.isEmpty) {
+                Solution(pre, e) 
+              } else {
+                Solution(pre, LetTuple(oxs, term, replace(Map(Variable(x) -> e), Tuple(p.xs.map(Variable(_))))) ) 
+              }
+            case _ => Solution.none
+          }
+
+          List(new Task(parent, p, List(newProblem), onSuccess, 100))
+        } else {
+          Nil
+        }
+
+
+      case _ =>
+        Nil
+    }
+  }
+}
diff --git a/src/main/scala/leon/synthesis/Solution.scala b/src/main/scala/leon/synthesis/Solution.scala
index f59c8b693e0b1fd17f482d551e3eb3c9f15dedda..8346a9a60f95474f0e4a325687aec390cbc5ed6a 100644
--- a/src/main/scala/leon/synthesis/Solution.scala
+++ b/src/main/scala/leon/synthesis/Solution.scala
@@ -11,4 +11,6 @@ case class Solution(pre: Expr, term: Expr) {
 
 object Solution {
   def choose(p: Problem): Solution = Solution(BooleanLiteral(true), Choose(p.xs, p.phi))
+
+  def none: Solution = throw new Exception("Unexpected failure to construct solution")
 }
diff --git a/src/main/scala/leon/synthesis/Synthesizer.scala b/src/main/scala/leon/synthesis/Synthesizer.scala
index ab5f75432c13de551f0eb0ba525a8f10516314c1..94fa516d58868b2fcf050fe2c08c63e130711691 100644
--- a/src/main/scala/leon/synthesis/Synthesizer.scala
+++ b/src/main/scala/leon/synthesis/Synthesizer.scala
@@ -38,7 +38,7 @@ class Synthesizer(rules: List[Rule]) {
 
             alternatives.find(_.isSuccess) match {
               case Some(ss) =>
-                ss.onSuccess()
+                ss.succeeded()
               case None =>
                 workList ++= alternatives
             }
@@ -46,7 +46,7 @@ class Synthesizer(rules: List[Rule]) {
             // We are stuck
             if (alternatives.isEmpty) {
               // I give up
-              task.onSuccess(sp, Solution.choose(sp))
+              task.subSucceeded(sp, Solution.choose(sp))
             }
           }
       }
@@ -65,9 +65,9 @@ class Synthesizer(rules: List[Rule]) {
     import purescala.Trees._
     import purescala.TypeTrees._
 
-    val aID = FreshIdentifier("a").setType(Int32Type)
-    val a = Variable(aID)
-    val p = Problem(Nil, And(GreaterThan(a, IntLiteral(2)), Equals(a, IntLiteral(3))), List(aID))
+    val x = Variable(FreshIdentifier("x").setType(Int32Type))
+    val y = Variable(FreshIdentifier("y").setType(Int32Type))
+    val p = Problem(Nil, And(GreaterThan(x, y), Equals(x, IntLiteral(3))), List(x.id, y.id))
 
     synthesize(p)
   }
diff --git a/src/main/scala/leon/synthesis/Task.scala b/src/main/scala/leon/synthesis/Task.scala
index 69a3232808e305ca445aebee1fb220fa3a6c53c2..2b8d6ad8862a03e688157f27759aae17ca976631 100644
--- a/src/main/scala/leon/synthesis/Task.scala
+++ b/src/main/scala/leon/synthesis/Task.scala
@@ -5,7 +5,7 @@ class Task(
         val parent: Task,
         val problem: Problem,
         val subProblems: List[Problem],
-        val construct: List[Solution] => Solution,
+        val onSuccess: List[Solution] => Solution,
         val score: Score
   ) extends Ordered[Task] {
 
@@ -15,12 +15,12 @@ class Task(
 
   def isSuccess = subProblems.isEmpty
 
-  def onSuccess() {
+  def succeeded() {
     assert(isSuccess)
-    notifyParent(construct(Nil))
+    notifyParent(onSuccess(Nil))
   }
 
-  def onSuccess(p: Problem, s: Solution) {
+  def subSucceeded(p: Problem, s: Solution) {
     assert(subProblems contains p)
     assert(!(subSolutions contains p))
 
@@ -28,16 +28,16 @@ class Task(
 
     if (subSolutions.size == subProblems.size) {
 
-      val solution = construct(subProblems map subSolutions) 
+      val solution = onSuccess(subProblems map subSolutions) 
 
-      println(": "+problem+" ⊢  "+solution)
+      println("Found solution to: "+problem+" ⊢  "+solution)
 
       notifyParent(solution)
     }
   }
 
   def notifyParent(solution: Solution) {
-    parent.onSuccess(problem, solution)
+    parent.subSucceeded(problem, solution)
   }
 }