|
| 1 | +type Pos = {x: Int with x >= 0} |
| 2 | + |
| 3 | +def safeDiv(x: Pos, y: Pos with y > 1): {res: Pos with res < x} = |
| 4 | + (x / y).asInstanceOf[{res: Pos with res < x}] |
| 5 | + |
| 6 | +object SafeSeqs: |
| 7 | + opaque type SafeSeq[T] = Seq[T] |
| 8 | + object SafeSeq: |
| 9 | + def fromSeq[T](seq: Seq[T]): SafeSeq[T] = seq |
| 10 | + def apply[T](elems: T*): SafeSeq[T] = fromSeq(elems) |
| 11 | + extension [T](a: SafeSeq[T]) |
| 12 | + def len: Pos = a.length.runtimeChecked |
| 13 | + def apply(i: Pos with i < a.len): T = a(i) |
| 14 | + def splitAt(i: Pos with i < a.len): (SafeSeq[T], SafeSeq[T]) = a.splitAt(i) |
| 15 | + def head: T = a(0) |
| 16 | + def tail: SafeSeq[T] = a.tail |
| 17 | + def ++(that: SafeSeq[T]): SafeSeq[T] = a ++ that |
| 18 | + |
| 19 | +import SafeSeqs.* |
| 20 | + |
| 21 | +def merge[T: Ordering as ord](left: SafeSeq[T], right: SafeSeq[T]): SafeSeq[T] = |
| 22 | + if left.len == 0 then right |
| 23 | + else if right.len == 0 then left |
| 24 | + else |
| 25 | + if ord.lt(left.head, right.head) then SafeSeq(left.head) ++ merge(left.tail, right) |
| 26 | + else SafeSeq(right.head) ++ merge(left, right.tail) |
| 27 | + |
| 28 | +def mergeSort[T: Ordering](list: SafeSeq[T]): SafeSeq[T] = |
| 29 | + val len = list.len |
| 30 | + val middle = safeDiv(len, 2) |
| 31 | + if middle == 0 then list |
| 32 | + else |
| 33 | + val (left, right) = list.splitAt(middle) |
| 34 | + merge(mergeSort(left), mergeSort(right)) |
| 35 | + |
| 36 | +@main def Test = |
| 37 | + val nums = SafeSeq(5, 3, 8, 1, 2, 7, 4, 6) |
| 38 | + val sortedNums = mergeSort(nums) |
| 39 | + println(s"Unsorted: $nums") |
| 40 | + println(s"Sorted: $sortedNums") |
| 41 | + |
| 42 | + val nums2 = SafeSeq(7, 4, 5, 3, 2, 6, 1) |
| 43 | + val sortedNums2 = mergeSort(nums2) |
| 44 | + println(s"Unsorted: $nums2") |
| 45 | + println(s"Sorted: $sortedNums2") |
0 commit comments