// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t" // RUN: %diff "%s.expect" "%t" function Count(s: set): int { if s == {} then 0 else var x :| x in s; // let x be such that "x in s" 1 + Count(s - {x}) } method Copy(s: set) returns (t: set) ensures s == t; { t := {}; var r := s; while (r != {}) invariant s == r + t; decreases r; { var x :| x in r; r, t := r - {x}, t + {x}; } } method CopyFaster(s: set) returns (t: set) ensures s == t; { t := {}; var r := s; while (r != {}) invariant s == r + t; decreases r; { var p :| p != {} && p <= r; // pick a nonempty subset of r r, t := r - p, t + p; } } method CopyFastest(s: set) returns (t: set) ensures s == t; { t := s; // :) } iterator Iter(s: set) yields (x: T) yield ensures x in s && x !in xs[..|xs|-1]; ensures s == set z | z in xs; { var r := s; while (r != {}) invariant forall z :: z in xs ==> x !in r; // r and xs are disjoint invariant s == r + set z | z in xs; { var y :| y in r; r, x := r - {y}, y; yield; assert y == xs[|xs|-1]; // needed as a lemma to prove loop invariant } } method UseIterToCopy(s: set) returns (t: set) ensures s == t; { t := {}; var m := new Iter(s); while (true) invariant m.Valid() && fresh(m._new); invariant t == set z | z in m.xs; decreases s - t; { var more := m.MoveNext(); if (!more) { break; } t := t + {m.x}; } }