datatype TreeNode = Nil | Cons(val: nat, left: TreeNode, right: TreeNode)\r
function TreeSeq(root: TreeNode): seq<TreeNode> {\r
case Cons(val, left, right) => [root]+TreeSeq(left)+TreeSeq(right)\r
function TreeSet(root: TreeNode): set<TreeNode> {\r
case Cons(val, left, right) => TreeSet(left)+{root}+TreeSet(right)\r
predicate isPath(paths: seq<TreeNode>, root: TreeNode) {\r
if |paths| == 0 then false else match paths[0] {\r
case Cons(val, left, right) => if |paths| == 1 then root == paths[0] else root == paths[0] && (isPath(paths[1..], left) || isPath(paths[1..], right))\r
function pathSum(paths: seq<TreeNode>): nat {\r
if |paths| == 0 then 0 else match paths[0] {\r
case Cons(val, left, right) => val + pathSum(paths[1..])\r
method hasPathSum(root: TreeNode, targetSum: int) returns (b: bool) \r
ensures b ==> exists p: seq<TreeNode> :: isPath(p, root) && pathSum(p) == targetSum\r
if(root.val - targetSum == 0 && root.left == Nil && root.right == Nil) {\r
assert isPath([root], root) && pathSum([root]) == targetSum;\r
var leftPath := hasPathSum(root.left, targetSum-root.val);\r
var rightPath := hasPathSum(root.right, targetSum-root.val);\r
ghost var p: seq<TreeNode> :| isPath(p, root.left) && pathSum(p) == targetSum-root.val;\r
assert isPath([root]+p, root) && pathSum([root]+p) == targetSum;\r
ghost var p: seq<TreeNode> :| isPath(p, root.right) && pathSum(p) == targetSum-root.val;\r
assert isPath([root]+p, root) && pathSum([root]+p) == targetSum;\r
return leftPath || rightPath;\r
var c := Cons(3, Nil, Nil);\r
var b := Cons(2, c, Nil);\r
var a := Cons(1, b, Nil);\r
assert isPath([a,b], a);\r
assert isPath([a,b,c], a);\r