{
  "id": "P156",
  "slug": "comparator-lab",
  "key": "P156-comparator-lab",
  "title": "Comparator lab",
  "summary": "Insertion, selection and bubble sort run with a head-to-head record that has a cycle and with sets compared by subset: different results for every input order, and an adjacent-pairs check that passes on results that are not in order.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P156 - Comparator lab\n\nThree sorts - insertion, selection, bubble - run with comparisons that are\nnot a total order: a head-to-head record with a cycle, and sets compared\nby \"is a proper subset of\".\n\n- `main.eml` - the menu, the record and the subset relation, one sort of\n  the teams or the sets in a chosen order, and every order run through\n  every sort\n- `order.eml` - the teams and their record, the sets and the subset test,\n  the three sorts, the check of adjacent pairs and of every pair, and every\n  order of a list\n\nHow each part works:\n\n- As in the corpus case `non-transitive-comparator`, A beats B, B beats C\n  and C beats A, and D loses to every other team: every pair has a winner,\n  so every sort finishes. Over the 24 orders the teams can come in, each\n  sort returns 3 different results. The usual postcondition, adjacent pairs\n  in order, passes on all 72 runs; the check of every pair passes on none -\n  with a cycle no arrangement can.\n- As in the corpus case `partial-order-trap`, {a} comes before {a,b} and\n  {c} before {b,c}, and every other pair is incomparable. Insertion and\n  selection always return an order with every pair in order, but which one\n  is chosen by the input order: 6 different results each.\n- Bubble sort stops once every adjacent pair is in order. With a partial\n  order that is not enough: on 10 of the 24 orders it leaves a subset after\n  its superset - {a} {b,c} {a,b} {c} stays as it came - and the adjacent\n  check passes on every one of them.\n\nWhat is checked: menu choices 1 to 6; a sort of insertion, selection or\nbubble; the four teams A, B, C and D, or the four set numbers 1 to 4, each\nonce. An empty answer cancels.\n\nSessions: `sessions/basic.in` gives:\n- the comparisons; ABCD through insertion, selection and bubble; every\n  order of the teams;\n- the sets 1423 through bubble and insertion; every order of the sets.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- sorts: a cancel and quick; orders of teams: a cancel, ABC, ABCC and\n  abcd; orders of sets: 1235 and 1123; a cancel for the sort of the sets.\n\nBuilt on the verified corpus cases `non-transitive-comparator` (a\nthree-cycle through three sorts, and the adjacent check that cannot tell\nthem apart) and `partial-order-trap` (sorting sets by subset, the result an\narrangement of the incomparable ones).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P156 comparator lab: the head-to-head record and the subset relation,\n# one sort of the teams or the sets in a chosen order, and every order run\n# through every sort.\nimport order\n\ndef plain(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef pad(s, n):\n    s => out\n    while len(out) < n:\n        out + \" \" => out\n    return out\n\ndef shown(kind, x):\n    if kind == \"teams\":\n        return x\n    \"{\" => out\n    0 => i\n    for c in x:\n        if i > 0:\n            out + \",\" => out\n        out + c => out\n        i + 1 => i\n    return out + \"}\"\n\ndef line(kind, xs):\n    \"\" => out\n    for x in xs:\n        if out != \"\":\n            out + \" \" => out\n        out + shown(kind, x) => out\n    return out\n\ndef yes(b):\n    if b:\n        return \"yes\"\n    return \"no\"\n\ndef show_rules():\n    \"The head-to-head record (the row beats the column):\" ^0\n    (\"      \" + pad(\"A\", 4) + pad(\"B\", 4) + pad(\"C\", 4) + \"D\") ^0\n    for x in order.teams():\n        (\"  \" + pad(x, 4)) => row\n        for y in order.teams():\n            if x == y:\n                \"-\" => c\n            elif order.beats(x, y):\n                \"x\" => c\n            else:\n                \".\" => c\n            if y == \"D\":\n                row + c => row\n            else:\n                row + pad(c, 4) => row\n        row ^0\n    \"  A beats B, B beats C, C beats A: a cycle, and every pair still has a winner.\" ^0\n    \"The sets, one coming before another when it is a proper subset of it:\" ^0\n    for x in order.sets():\n        for y in order.sets():\n            if order.subset(x, y):\n                (\"  \" + shown(\"sets\", x) + \" comes before \" + shown(\"sets\", y)) ^0\n    \"  Every other pair is incomparable: neither comes first.\" ^0\n\ndef read_algo():\n    plain(input(\"sort (insertion, selection, bubble)> \")) => a\n    return a\n\ndef algo_ok(a):\n    return a == \"insertion\" or a == \"selection\" or a == \"bubble\"\n\ndef read_order(kind):\n    # the items in the order typed, or [] when not an order of them\n    if kind == \"teams\":\n        plain(input(\"teams in the order they come (e.g. ABCD)> \")) => t\n    else:\n        plain(input(\"sets in the order they come, by number 1 to 4 (e.g. 1234)> \")) => t\n    if t == \"\":\n        return [\"cancel\"]\n    if len(t) != 4:\n        return []\n    [] => out\n    for c in t:\n        if kind == \"teams\":\n            if c != \"A\" and c != \"B\" and c != \"C\" and c != \"D\":\n                return []\n            c => x\n        else:\n            if c < \"1\" or c > \"4\":\n                return []\n            order.sets()[int(c) - 1] => x\n        for y in out:\n            if y == x:\n                return []\n        out + [x] => out\n    return out\n\ndef one(kind):\n    read_algo() => a\n    if a == \"\":\n        \"Cancelled.\" ^0\n        return\n    if not algo_ok(a):\n        \"Type insertion, selection or bubble.\" ^0\n        return\n    read_order(kind) => xs\n    if len(xs) == 1:\n        \"Cancelled.\" ^0\n        return\n    if len(xs) == 0:\n        if kind == \"teams\":\n            \"Type the four teams A, B, C and D, each once.\" ^0\n        else:\n            \"Type the four set numbers 1 to 4, each once.\" ^0\n        return\n    order.sort(a, kind, xs) => out\n    (\"  in:     \" + line(kind, xs)) ^0\n    (\"  out:    \" + line(kind, out)) ^0\n    (\"  adjacent pairs in order: \" + yes(order.adjacent_ok(kind, out)) + \"; every pair in order: \" + yes(order.all_ok(kind, out))) ^0\n\ndef every(kind):\n    if kind == \"teams\":\n        order.teams() => base\n    else:\n        order.sets() => base\n    order.orders(base) => all\n    (\"Every one of the \" + str(len(all)) + \" orders the \" + kind + \" can come in, through each sort:\") ^0\n    (\"  \" + pad(\"sort\", 11) + \"different results   adjacent pairs in order   every pair in order\") ^0\n    [] => notes\n    for a in [\"insertion\", \"selection\", \"bubble\"]:\n        [] => outs\n        0 => adj\n        0 => full\n        for xs in all:\n            order.sort(a, kind, xs) => out\n            line(kind, out) => s\n            False => have\n            for o in outs:\n                if o == s:\n                    True => have\n            if not have:\n                outs + [s] => outs\n            if order.adjacent_ok(kind, out):\n                adj + 1 => adj\n            if order.all_ok(kind, out):\n                full + 1 => full\n        (\"  \" + pad(a, 11) + pad(str(len(outs)), 20) + pad(str(adj) + \" of \" + str(len(all)), 26) + str(full) + \" of \" + str(len(all))) ^0\n        if kind == \"teams\":\n            \"\" => all_outs\n            for o in outs:\n                if all_outs == \"\":\n                    o => all_outs\n                else:\n                    all_outs + \", \" + o => all_outs\n            notes + [\"  \" + a + \" returns \" + all_outs] => notes\n        elif full < adj:\n            notes + [\"  \" + a + \" stops once every adjacent pair is in order: on \" + str(adj - full) + \" of the \" + str(len(all)) + \" orders it leaves a subset after its superset, and the adjacent check passes\"] => notes\n    for n in notes:\n        n ^0\n    if kind == \"teams\":\n        \"No order of the teams has every pair in order: the cycle allows none, and every sort still finishes.\" ^0\n    else:\n        \"A sort by a partial order returns whichever arrangement the input order leads it to; nothing raises.\" ^0\n\n\"== Comparator lab ==\" ^0\n\"Three sorts with comparisons that are not a total order: a cycle, and a subset relation.\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        show_rules()\n    elif choice == \"2\":\n        one(\"teams\")\n    elif choice == \"3\":\n        every(\"teams\")\n    elif choice == \"4\":\n        one(\"sets\")\n    elif choice == \"5\":\n        every(\"sets\")\n    elif choice == \"6\":\n        False => running\n    else:\n        \"Pick a number from 1 to 6.\" ^0\n\"Bye.\" ^0\n",
      "python": "import order\n\ndef plain(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef pad(s, n):\n    out = s\n    while len(out) < n:\n        out = out + \" \"\n    return out\n\ndef shown(kind, x):\n    if kind == \"teams\":\n        return x\n    out = \"{\"\n    i = 0\n    for c in x:\n        if i > 0:\n            out = out + \",\"\n        out = out + c\n        i = i + 1\n    return out + \"}\"\n\ndef line(kind, xs):\n    out = \"\"\n    for x in xs:\n        if out != \"\":\n            out = out + \" \"\n        out = out + shown(kind, x)\n    return out\n\ndef yes(b):\n    if b:\n        return \"yes\"\n    return \"no\"\n\ndef show_rules():\n    print(\"The head-to-head record (the row beats the column):\")\n    print(\"      \" + pad(\"A\", 4) + pad(\"B\", 4) + pad(\"C\", 4) + \"D\")\n    for x in order.teams():\n        row = \"  \" + pad(x, 4)\n        for y in order.teams():\n            if x == y:\n                c = \"-\"\n            elif order.beats(x, y):\n                c = \"x\"\n            else:\n                c = \".\"\n            if y == \"D\":\n                row = row + c\n            else:\n                row = row + pad(c, 4)\n        print(row)\n    print(\"  A beats B, B beats C, C beats A: a cycle, and every pair still has a winner.\")\n    print(\"The sets, one coming before another when it is a proper subset of it:\")\n    for x in order.sets():\n        for y in order.sets():\n            if order.subset(x, y):\n                print(\"  \" + shown(\"sets\", x) + \" comes before \" + shown(\"sets\", y))\n    print(\"  Every other pair is incomparable: neither comes first.\")\n\ndef read_algo():\n    a = plain(input(\"sort (insertion, selection, bubble)> \"))\n    return a\n\ndef algo_ok(a):\n    return a == \"insertion\" or a == \"selection\" or a == \"bubble\"\n\ndef read_order(kind):\n    if kind == \"teams\":\n        t = plain(input(\"teams in the order they come (e.g. ABCD)> \"))\n    else:\n        t = plain(input(\"sets in the order they come, by number 1 to 4 (e.g. 1234)> \"))\n    if t == \"\":\n        return [\"cancel\"]\n    if len(t) != 4:\n        return []\n    out = []\n    for c in t:\n        if kind == \"teams\":\n            if c != \"A\" and c != \"B\" and c != \"C\" and c != \"D\":\n                return []\n            x = c\n        else:\n            if c < \"1\" or c > \"4\":\n                return []\n            x = order.sets()[int(c) - 1]\n        for y in out:\n            if y == x:\n                return []\n        out = out + [x]\n    return out\n\ndef one(kind):\n    a = read_algo()\n    if a == \"\":\n        print(\"Cancelled.\")\n        return\n    if not algo_ok(a):\n        print(\"Type insertion, selection or bubble.\")\n        return\n    xs = read_order(kind)\n    if len(xs) == 1:\n        print(\"Cancelled.\")\n        return\n    if len(xs) == 0:\n        if kind == \"teams\":\n            print(\"Type the four teams A, B, C and D, each once.\")\n        else:\n            print(\"Type the four set numbers 1 to 4, each once.\")\n        return\n    out = order.sort(a, kind, xs)\n    print(\"  in:     \" + line(kind, xs))\n    print(\"  out:    \" + line(kind, out))\n    print(\"  adjacent pairs in order: \" + yes(order.adjacent_ok(kind, out)) + \"; every pair in order: \" + yes(order.all_ok(kind, out)))\n\ndef every(kind):\n    if kind == \"teams\":\n        base = order.teams()\n    else:\n        base = order.sets()\n    all = order.orders(base)\n    print(\"Every one of the \" + str(len(all)) + \" orders the \" + kind + \" can come in, through each sort:\")\n    print(\"  \" + pad(\"sort\", 11) + \"different results   adjacent pairs in order   every pair in order\")\n    notes = []\n    for a in [\"insertion\", \"selection\", \"bubble\"]:\n        outs = []\n        adj = 0\n        full = 0\n        for xs in all:\n            out = order.sort(a, kind, xs)\n            s = line(kind, out)\n            have = False\n            for o in outs:\n                if o == s:\n                    have = True\n            if not have:\n                outs = outs + [s]\n            if order.adjacent_ok(kind, out):\n                adj = adj + 1\n            if order.all_ok(kind, out):\n                full = full + 1\n        print(\"  \" + pad(a, 11) + pad(str(len(outs)), 20) + pad(str(adj) + \" of \" + str(len(all)), 26) + str(full) + \" of \" + str(len(all)))\n        if kind == \"teams\":\n            all_outs = \"\"\n            for o in outs:\n                if all_outs == \"\":\n                    all_outs = o\n                else:\n                    all_outs = all_outs + \", \" + o\n            notes = notes + [\"  \" + a + \" returns \" + all_outs]\n        elif full < adj:\n            notes = notes + [\"  \" + a + \" stops once every adjacent pair is in order: on \" + str(adj - full) + \" of the \" + str(len(all)) + \" orders it leaves a subset after its superset, and the adjacent check passes\"]\n    for n in notes:\n        print(n)\n    if kind == \"teams\":\n        print(\"No order of the teams has every pair in order: the cycle allows none, and every sort still finishes.\")\n    else:\n        print(\"A sort by a partial order returns whichever arrangement the input order leads it to; nothing raises.\")\n\nprint(\"== Comparator lab ==\")\nprint(\"Three sorts with comparisons that are not a total order: a cycle, and a subset relation.\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        show_rules()\n    elif choice == \"2\":\n        one(\"teams\")\n    elif choice == \"3\":\n        every(\"teams\")\n    elif choice == \"4\":\n        one(\"sets\")\n    elif choice == \"5\":\n        every(\"sets\")\n    elif choice == \"6\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 6.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "order.eml",
      "eml": "# P156 comparator lab - three sorts run with comparisons that are not a\n# total order. As in the corpus case non-transitive-comparator, a\n# head-to-head record with a cycle (A beats B, B beats C, C beats A) gives\n# every pair a definite answer, so every sort finishes, and the order it\n# returns depends on the algorithm and the order the items came in; the\n# usual check, adjacent pairs in order, can pass on all of them. As in the\n# corpus case partial-order-trap, sets compared by \"is a proper subset of\"\n# leave most pairs incomparable, and the sorted list is an arrangement of\n# the incomparable ones chosen by the input order alone.\n\ndef teams():\n    return [\"A\", \"B\", \"C\", \"D\"]\n\ndef beats(x, y):\n    # the head-to-head record: A beats B, B beats C, C beats A; D loses to\n    # every other team\n    if x == y:\n        return False\n    if y == \"D\":\n        return True\n    if x == \"D\":\n        return False\n    return (x == \"A\" and y == \"B\") or (x == \"B\" and y == \"C\") or (x == \"C\" and y == \"A\")\n\ndef sets():\n    return [\"a\", \"ab\", \"c\", \"bc\"]\n\ndef subset(x, y):\n    # x is a proper subset of y; a set is a string of distinct letters\n    if len(x) >= len(y):\n        return False\n    for c in x:\n        False => found\n        for d in y:\n            if c == d:\n                True => found\n        if not found:\n            return False\n    return True\n\ndef before(kind, x, y):\n    # x must come before y\n    if kind == \"teams\":\n        return beats(x, y)\n    return subset(x, y)\n\ndef insertion(kind, xs):\n    [] => out\n    for x in xs:\n        [] => merged\n        False => placed\n        for y in out:\n            if not placed and before(kind, x, y):\n                merged + [x] => merged\n                True => placed\n            merged + [y] => merged\n        if not placed:\n            merged + [x] => merged\n        merged => out\n    return out\n\ndef selection(kind, xs):\n    xs => left\n    [] => out\n    while len(left) > 0:\n        0 => best\n        1 => i\n        while i < len(left):\n            if before(kind, left[i], left[best]):\n                i => best\n            i + 1 => i\n        out + [left[best]] => out\n        [] => rest\n        0 => j\n        for x in left:\n            if j != best:\n                rest + [x] => rest\n            j + 1 => j\n        rest => left\n    return out\n\ndef bubble(kind, xs):\n    xs => a\n    True => swapped\n    while swapped:\n        False => swapped\n        [] => b\n        0 => i\n        while i < len(a):\n            if i + 1 < len(a) and before(kind, a[i + 1], a[i]):\n                b + [a[i + 1], a[i]] => b\n                i + 2 => i\n                True => swapped\n            else:\n                b + [a[i]] => b\n                i + 1 => i\n        b => a\n    return a\n\ndef sort(algo, kind, xs):\n    if algo == \"insertion\":\n        return insertion(kind, xs)\n    if algo == \"selection\":\n        return selection(kind, xs)\n    return bubble(kind, xs)\n\ndef adjacent_ok(kind, xs):\n    # no item comes right after one it should come before\n    0 => i\n    while i + 1 < len(xs):\n        if before(kind, xs[i + 1], xs[i]):\n            return False\n        i + 1 => i\n    return True\n\ndef all_ok(kind, xs):\n    # no item comes anywhere after one it should come before\n    0 => i\n    while i < len(xs):\n        i + 1 => j\n        while j < len(xs):\n            if before(kind, xs[j], xs[i]):\n                return False\n            j + 1 => j\n        i + 1 => i\n    return True\n\ndef orders(xs):\n    # every order of the items\n    if len(xs) <= 1:\n        return [xs]\n    [] => out\n    0 => i\n    for x in xs:\n        [] => rest\n        0 => j\n        for y in xs:\n            if j != i:\n                rest + [y] => rest\n            j + 1 => j\n        for p in orders(rest):\n            out + [[x] + p] => out\n        i + 1 => i\n    return out\n",
      "python": "def teams():\n    return [\"A\", \"B\", \"C\", \"D\"]\n\ndef beats(x, y):\n    if x == y:\n        return False\n    if y == \"D\":\n        return True\n    if x == \"D\":\n        return False\n    return x == \"A\" and y == \"B\" or x == \"B\" and y == \"C\" or x == \"C\" and y == \"A\"\n\ndef sets():\n    return [\"a\", \"ab\", \"c\", \"bc\"]\n\ndef subset(x, y):\n    if len(x) >= len(y):\n        return False\n    for c in x:\n        found = False\n        for d in y:\n            if c == d:\n                found = True\n        if not found:\n            return False\n    return True\n\ndef before(kind, x, y):\n    if kind == \"teams\":\n        return beats(x, y)\n    return subset(x, y)\n\ndef insertion(kind, xs):\n    out = []\n    for x in xs:\n        merged = []\n        placed = False\n        for y in out:\n            if not placed and before(kind, x, y):\n                merged = merged + [x]\n                placed = True\n            merged = merged + [y]\n        if not placed:\n            merged = merged + [x]\n        out = merged\n    return out\n\ndef selection(kind, xs):\n    left = xs\n    out = []\n    while len(left) > 0:\n        best = 0\n        i = 1\n        while i < len(left):\n            if before(kind, left[i], left[best]):\n                best = i\n            i = i + 1\n        out = out + [left[best]]\n        rest = []\n        j = 0\n        for x in left:\n            if j != best:\n                rest = rest + [x]\n            j = j + 1\n        left = rest\n    return out\n\ndef bubble(kind, xs):\n    a = xs\n    swapped = True\n    while swapped:\n        swapped = False\n        b = []\n        i = 0\n        while i < len(a):\n            if i + 1 < len(a) and before(kind, a[i + 1], a[i]):\n                b = b + [a[i + 1], a[i]]\n                i = i + 2\n                swapped = True\n            else:\n                b = b + [a[i]]\n                i = i + 1\n        a = b\n    return a\n\ndef sort(algo, kind, xs):\n    if algo == \"insertion\":\n        return insertion(kind, xs)\n    if algo == \"selection\":\n        return selection(kind, xs)\n    return bubble(kind, xs)\n\ndef adjacent_ok(kind, xs):\n    i = 0\n    while i + 1 < len(xs):\n        if before(kind, xs[i + 1], xs[i]):\n            return False\n        i = i + 1\n    return True\n\ndef all_ok(kind, xs):\n    i = 0\n    while i < len(xs):\n        j = i + 1\n        while j < len(xs):\n            if before(kind, xs[j], xs[i]):\n                return False\n            j = j + 1\n        i = i + 1\n    return True\n\ndef orders(xs):\n    if len(xs) <= 1:\n        return [xs]\n    out = []\n    i = 0\n    for x in xs:\n        rest = []\n        j = 0\n        for y in xs:\n            if j != i:\n                rest = rest + [y]\n            j = j + 1\n        for p in orders(rest):\n            out = out + [[x] + p]\n        i = i + 1\n    return out\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n2\n\n2\nquick\n2\ninsertion\n\n2\ninsertion\nABC\n2\ninsertion\nABCC\n2\ninsertion\nabcd\n4\nbubble\n1235\n4\nbubble\n1123\n4\n\n6\n",
      "screen": "== Comparator lab ==\nThree sorts with comparisons that are not a total order: a cycle, and a subset relation.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 0\nPick a number from 1 to 6.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> x\nPick a number from 1 to 6.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> \nCancelled.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> quick\nType insertion, selection or bubble.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> insertion\nteams in the order they come (e.g. ABCD)> \nCancelled.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> insertion\nteams in the order they come (e.g. ABCD)> ABC\nType the four teams A, B, C and D, each once.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> insertion\nteams in the order they come (e.g. ABCD)> ABCC\nType the four teams A, B, C and D, each once.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> insertion\nteams in the order they come (e.g. ABCD)> abcd\nType the four teams A, B, C and D, each once.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 4\nsort (insertion, selection, bubble)> bubble\nsets in the order they come, by number 1 to 4 (e.g. 1234)> 1235\nType the four set numbers 1 to 4, each once.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 4\nsort (insertion, selection, bubble)> bubble\nsets in the order they come, by number 1 to 4 (e.g. 1234)> 1123\nType the four set numbers 1 to 4, each once.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 4\nsort (insertion, selection, bubble)> \nCancelled.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\ninsertion\nABCD\n2\nselection\nABCD\n2\nbubble\nABCD\n3\n4\nbubble\n1423\n4\ninsertion\n1423\n5\n6\n",
      "screen": "== Comparator lab ==\nThree sorts with comparisons that are not a total order: a cycle, and a subset relation.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 1\nThe head-to-head record (the row beats the column):\n      A   B   C   D\n  A   -   x   .   x\n  B   .   -   x   x\n  C   x   .   -   x\n  D   .   .   .   -\n  A beats B, B beats C, C beats A: a cycle, and every pair still has a winner.\nThe sets, one coming before another when it is a proper subset of it:\n  {a} comes before {a,b}\n  {c} comes before {b,c}\n  Every other pair is incomparable: neither comes first.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> insertion\nteams in the order they come (e.g. ABCD)> ABCD\n  in:     A B C D\n  out:    C A B D\n  adjacent pairs in order: yes; every pair in order: no\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> selection\nteams in the order they come (e.g. ABCD)> ABCD\n  in:     A B C D\n  out:    C A B D\n  adjacent pairs in order: yes; every pair in order: no\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 2\nsort (insertion, selection, bubble)> bubble\nteams in the order they come (e.g. ABCD)> ABCD\n  in:     A B C D\n  out:    A B C D\n  adjacent pairs in order: yes; every pair in order: no\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 3\nEvery one of the 24 orders the teams can come in, through each sort:\n  sort       different results   adjacent pairs in order   every pair in order\n  insertion  3                   24 of 24                  0 of 24\n  selection  3                   24 of 24                  0 of 24\n  bubble     3                   24 of 24                  0 of 24\n  insertion returns C A B D, B C A D, A B C D\n  selection returns C A B D, B C A D, A B C D\n  bubble returns A B C D, C A B D, B C A D\nNo order of the teams has every pair in order: the cycle allows none, and every sort still finishes.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 4\nsort (insertion, selection, bubble)> bubble\nsets in the order they come, by number 1 to 4 (e.g. 1234)> 1423\n  in:     {a} {b,c} {a,b} {c}\n  out:    {a} {b,c} {a,b} {c}\n  adjacent pairs in order: yes; every pair in order: no\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 4\nsort (insertion, selection, bubble)> insertion\nsets in the order they come, by number 1 to 4 (e.g. 1234)> 1423\n  in:     {a} {b,c} {a,b} {c}\n  out:    {a} {c} {b,c} {a,b}\n  adjacent pairs in order: yes; every pair in order: yes\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 5\nEvery one of the 24 orders the sets can come in, through each sort:\n  sort       different results   adjacent pairs in order   every pair in order\n  insertion  6                   24 of 24                  24 of 24\n  selection  6                   24 of 24                  24 of 24\n  bubble     14                  24 of 24                  14 of 24\n  bubble stops once every adjacent pair is in order: on 10 of the 24 orders it leaves a subset after its superset, and the adjacent check passes\nA sort by a partial order returns whichever arrangement the input order leads it to; nothing raises.\n\n1) the comparisons  2) sort the teams  3) every order of the teams  4) sort the sets  5) every order of the sets  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "non-transitive-comparator",
      "caseId": "265-non-transitive-comparator",
      "title": "Non-transitive comparator — three answers, and the postcondition likes all of them"
    },
    {
      "slug": "partial-order-trap",
      "caseId": "177-partial-order-trap",
      "title": "Sorting by a partial order"
    }
  ],
  "updated": "2026-10-18"
}
