{
  "id": "P170",
  "slug": "eligibility-rules",
  "key": "P170-eligibility-rules",
  "title": "Eligibility rules",
  "summary": "300 made-up applicants and three rules written two ways: a negation distributed by hand keeps 56 it should skip, one clause of member-or-referred never decides, and a guard moved behind its test divides by zero.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P170 - Eligibility rules\n\n300 made-up applicants for a benefit and three rules, each written two\nways: who the difference reaches.\n\n- `main.eml` - the menu, the applicants, the skip rule, which clause\n  decides an approval, the means test, and an applicant of your own\n- `rules.eml` - the applicants, drawn from a fixed seed, and each rule in\n  its two forms\n\nHow each part works:\n\n- An applicant is skipped unless a resident adult, approved as a member\n  or a referred applicant, and paid only if the average income on record\n  is under 2,000.00 a month.\n- As in the corpus case `the-negation-was-distributed-by-hand`,\n  not (resident and adult) rewritten as (not resident) and (not adult)\n  agrees where both clauses hold or both fail, and keeps the applicants\n  who fail exactly one: 56 of the 300, 11 residents under 18 and 45 adults\n  from elsewhere.\n- As in `which-clause-actually-decided`, \"member or referred\" is right for\n  every applicant, and of the 101 approvals 76 are carried by membership\n  alone, 25 by both and none by the referral alone: every referred\n  applicant here is a member. That is a fact about who applies.\n- As in `the-guard-was-moved-for-readability`, the means test with the\n  months checked first answers for all 101; with the average first it\n  gives the same answer on the 94 with months on record and divides by\n  zero on the 7 without.\n\nWhat is checked: menu choices 1 to 6; y or n (or yes or no) for resident,\nmember and referred; an age from 0 to 120; 0 to 24 months on record; a\nwhole income from 0 to 999999. An empty answer cancels.\n\nSessions: `sessions/basic.in` gives:\n- the applicants, the skip rule, the clauses and the means test;\n- your own: a 17-year-old resident member (the hand-written rule keeps\n  them), a referred adult from elsewhere with no months on record, and a\n  resident member referred as well, over the income limit.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- a cancel and \"maybe\" for resident; ages: a cancel, 121 and x; member: a\n  cancel and k; referred: a cancel and q; months: a cancel, 25 and x;\n  income: a cancel, 1000000 and 1.5;\n- a 16-year-old from elsewhere, neither member nor referred, with 12 months\n  and no income.\n\nBuilt on the verified corpus cases `the-negation-was-distributed-by-hand`\n(a skip condition inverted with the negation distributed as an and),\n`which-clause-actually-decided` (administrator or owner, scored by which\nclause carried each request) and `the-guard-was-moved-for-readability` (two\nclauses swapped so the meaningful one reads first).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P170 eligibility rules: 300 applicants and three rules written two ways -\n# the applicants, the skip rule, which clause decides an approval, the\n# means test with its guard moved, and an applicant of your own.\nimport rules\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 lpad(s, n):\n    s => out\n    while len(out) < n:\n        \" \" + out => out\n    return out\n\ndef digits(t):\n    for c in t:\n        if c < \"0\" or c > \"9\":\n            return False\n    return len(t) > 0\n\ndef commas(n):\n    str(n) => s\n    \"\" => out\n    0 => k\n    len(s) => i\n    while i > 0:\n        if k == 3:\n            \",\" + out => out\n            0 => k\n        s[i - 1] + out => out\n        k + 1 => k\n        i - 1 => i\n    return out\n\ndef money(c):\n    c % 100 => r\n    if r < 10:\n        return commas(int((c - r) / 100)) + \".0\" + str(r)\n    return commas(int((c - r) / 100)) + \".\" + str(r)\n\ndef yn(b):\n    if b:\n        return \"yes\"\n    return \"no\"\n\ndef show_applicants():\n    rules.applicants() => aps\n    (\"300 applicants for a benefit; the first eight:\") ^0\n    (\"  \" + pad(\"\", 4) + pad(\"resident\", 10) + lpad(\"age\", 4) + \"  \" + pad(\"member\", 8) + pad(\"referred\", 10) + lpad(\"months\", 7) + lpad(\"income on record\", 18)) ^0\n    0 => i\n    while i < 8:\n        aps[i] => a\n        (\"  \" + pad(str(i + 1), 4) + pad(yn(a[0]), 10) + lpad(str(a[1]), 4) + \"  \" + pad(yn(a[2]), 8) + pad(yn(a[3]), 10) + lpad(str(a[4]), 7) + lpad(money(a[5]), 18)) ^0\n        i + 1 => i\n    \"The rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month.\" ^0\n\ndef show_skip():\n    rules.applicants() => aps\n    \"Skip unless resident and adult, written two ways:\" ^0\n    (\"  \" + pad(\"resident\", 10) + pad(\"adult\", 7) + pad(\"not (r and a)\", 15) + pad(\"not r and not a\", 17) + \"applicants\") ^0\n    [[True, True], [True, False], [False, True], [False, False]] => combos\n    0 => differ\n    for c in combos:\n        0 => n\n        for a in aps:\n            if a[0] == c[0] and rules.adult(a) == c[1]:\n                n + 1 => n\n        [c[0], 18] => probe\n        if not c[1]:\n            [c[0], 17] => probe\n        rules.skip_meant(probe) => s1\n        rules.skip_by_hand(probe) => s2\n        if s1 != s2:\n            differ + n => differ\n        (\"  \" + pad(yn(c[0]), 10) + pad(yn(c[1]), 7) + pad(yn(s1), 15) + pad(yn(s2), 17) + lpad(str(n), 10)) ^0\n    (\"The two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: \" + str(differ) + \" of 300 here, the residents under 18 and the adults from elsewhere.\") ^0\n\ndef show_clause():\n    rules.applicants() => aps\n    0 => kept\n    0 => yes\n    0 => m\n    0 => r\n    0 => b\n    for a in aps:\n        if not rules.skip_meant(a):\n            kept + 1 => kept\n            if rules.approved(a):\n                yes + 1 => yes\n                rules.decided(a) => d\n                if d == \"member\":\n                    m + 1 => m\n                if d == \"referral\":\n                    r + 1 => r\n                if d == \"both\":\n                    b + 1 => b\n    (\"Of the \" + str(kept) + \" resident adults, \" + str(yes) + \" are approved, as member or referred. Which clause carried each:\") ^0\n    (\"  membership alone   \" + lpad(str(m), 4)) ^0\n    (\"  referral alone     \" + lpad(str(r), 4)) ^0\n    (\"  both               \" + lpad(str(b), 4)) ^0\n    (\"The referral clause decided \" + str(r) + \" approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.\") ^0\n\ndef show_income():\n    rules.applicants() => aps\n    0 => zero\n    0 => agree\n    0 => n\n    for a in aps:\n        if not rules.skip_meant(a) and rules.approved(a):\n            n + 1 => n\n            rules.income_guard_first(a) => g\n            rules.income_meaning_first(a) => f\n            if f == \"divides by zero\":\n                zero + 1 => zero\n            elif f == g:\n                agree + 1 => agree\n    (\"The means test on the \" + str(n) + \" approved applicants: income on record / months under 2,000.00, and months on record above 0.\") ^0\n    (\"Guard first, months checked before the division: an answer for all \" + str(n) + \".\") ^0\n    (\"Meaning first, the average before the months: the same answer on \" + str(agree) + \", and a division by zero on the \" + str(zero) + \" with no months on record.\") ^0\n    \"Moving the guard behind the test it protects reads better and is no longer a guard.\" ^0\n\ndef ask_yes(prompt):\n    # True, False, or \"\" when cancelled, \"bad\" when neither\n    plain(input(prompt + \" (y/n)> \")) => t\n    if t == \"\":\n        return \"\"\n    if t == \"y\" or t == \"yes\":\n        return True\n    if t == \"n\" or t == \"no\":\n        return False\n    return \"bad\"\n\ndef own():\n    ask_yes(\"resident\") => res\n    if res == \"\":\n        \"Cancelled.\" ^0\n        return\n    if res == \"bad\":\n        \"Type y or n.\" ^0\n        return\n    plain(input(\"age (0 to 120)> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return\n    if len(t) > 3 or not digits(t) or int(t) > 120:\n        \"Type a whole number from 0 to 120.\" ^0\n        return\n    int(t) => age\n    ask_yes(\"member\") => mem\n    if mem == \"\":\n        \"Cancelled.\" ^0\n        return\n    if mem == \"bad\":\n        \"Type y or n.\" ^0\n        return\n    ask_yes(\"referred\") => ref\n    if ref == \"\":\n        \"Cancelled.\" ^0\n        return\n    if ref == \"bad\":\n        \"Type y or n.\" ^0\n        return\n    plain(input(\"months of income on record (0 to 24)> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return\n    if len(t) > 2 or not digits(t) or int(t) > 24:\n        \"Type a whole number from 0 to 24.\" ^0\n        return\n    int(t) => months\n    0 => total\n    if months > 0:\n        plain(input(\"income over those months, whole units (0 to 999999)> \")) => t\n        if t == \"\":\n            \"Cancelled.\" ^0\n            return\n        if len(t) > 6 or not digits(t):\n            \"Type a whole number from 0 to 999999.\" ^0\n            return\n        int(t) * 100 => total\n    [res, age, mem, ref, months, total] => a\n    (\"The skip rule: as meant it \" + skipped(rules.skip_meant(a)) + \" them; written by hand it \" + skipped(rules.skip_by_hand(a)) + \" them.\") ^0\n    if rules.approved(a):\n        (\"Member or referred: approved, by \" + [\"membership alone\", \"referral alone\", \"both\"][index(rules.decided(a))] + \".\") ^0\n    else:\n        \"Member or referred: not approved.\" ^0\n    rules.income_guard_first(a) => g\n    rules.income_meaning_first(a) => f\n    if months == 0:\n        \"The means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read.\" ^0\n    else:\n        (\"The means test: \" + money(int(total / months)) + \" a month on average, \" + verdict(g) + \" either way.\") ^0\n\ndef skipped(b):\n    if b:\n        return \"skips\"\n    return \"keeps\"\n\ndef index(d):\n    if d == \"member\":\n        return 0\n    if d == \"referral\":\n        return 1\n    return 2\n\ndef verdict(g):\n    if g:\n        return \"under 2,000.00, so it passes\"\n    return \"not under 2,000.00, so it fails\"\n\n\"== Eligibility rules ==\" ^0\n\"Three rules for a benefit, each written two ways, and who the difference reaches.\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        show_applicants()\n    elif choice == \"2\":\n        show_skip()\n    elif choice == \"3\":\n        show_clause()\n    elif choice == \"4\":\n        show_income()\n    elif choice == \"5\":\n        own()\n    elif choice == \"6\":\n        False => running\n    else:\n        \"Pick a number from 1 to 6.\" ^0\n\"Bye.\" ^0\n",
      "python": "import rules\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 lpad(s, n):\n    out = s\n    while len(out) < n:\n        out = \" \" + out\n    return out\n\ndef digits(t):\n    for c in t:\n        if c < \"0\" or c > \"9\":\n            return False\n    return len(t) > 0\n\ndef commas(n):\n    s = str(n)\n    out = \"\"\n    k = 0\n    i = len(s)\n    while i > 0:\n        if k == 3:\n            out = \",\" + out\n            k = 0\n        out = s[i - 1] + out\n        k = k + 1\n        i = i - 1\n    return out\n\ndef money(c):\n    r = c % 100\n    if r < 10:\n        return commas(int((c - r) / 100)) + \".0\" + str(r)\n    return commas(int((c - r) / 100)) + \".\" + str(r)\n\ndef yn(b):\n    if b:\n        return \"yes\"\n    return \"no\"\n\ndef show_applicants():\n    aps = rules.applicants()\n    print(\"300 applicants for a benefit; the first eight:\")\n    print(\"  \" + pad(\"\", 4) + pad(\"resident\", 10) + lpad(\"age\", 4) + \"  \" + pad(\"member\", 8) + pad(\"referred\", 10) + lpad(\"months\", 7) + lpad(\"income on record\", 18))\n    i = 0\n    while i < 8:\n        a = aps[i]\n        print(\"  \" + pad(str(i + 1), 4) + pad(yn(a[0]), 10) + lpad(str(a[1]), 4) + \"  \" + pad(yn(a[2]), 8) + pad(yn(a[3]), 10) + lpad(str(a[4]), 7) + lpad(money(a[5]), 18))\n        i = i + 1\n    print(\"The rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month.\")\n\ndef show_skip():\n    aps = rules.applicants()\n    print(\"Skip unless resident and adult, written two ways:\")\n    print(\"  \" + pad(\"resident\", 10) + pad(\"adult\", 7) + pad(\"not (r and a)\", 15) + pad(\"not r and not a\", 17) + \"applicants\")\n    combos = [[True, True], [True, False], [False, True], [False, False]]\n    differ = 0\n    for c in combos:\n        n = 0\n        for a in aps:\n            if a[0] == c[0] and rules.adult(a) == c[1]:\n                n = n + 1\n        probe = [c[0], 18]\n        if not c[1]:\n            probe = [c[0], 17]\n        s1 = rules.skip_meant(probe)\n        s2 = rules.skip_by_hand(probe)\n        if s1 != s2:\n            differ = differ + n\n        print(\"  \" + pad(yn(c[0]), 10) + pad(yn(c[1]), 7) + pad(yn(s1), 15) + pad(yn(s2), 17) + lpad(str(n), 10))\n    print(\"The two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: \" + str(differ) + \" of 300 here, the residents under 18 and the adults from elsewhere.\")\n\ndef show_clause():\n    aps = rules.applicants()\n    kept = 0\n    yes = 0\n    m = 0\n    r = 0\n    b = 0\n    for a in aps:\n        if not rules.skip_meant(a):\n            kept = kept + 1\n            if rules.approved(a):\n                yes = yes + 1\n                d = rules.decided(a)\n                if d == \"member\":\n                    m = m + 1\n                if d == \"referral\":\n                    r = r + 1\n                if d == \"both\":\n                    b = b + 1\n    print(\"Of the \" + str(kept) + \" resident adults, \" + str(yes) + \" are approved, as member or referred. Which clause carried each:\")\n    print(\"  membership alone   \" + lpad(str(m), 4))\n    print(\"  referral alone     \" + lpad(str(r), 4))\n    print(\"  both               \" + lpad(str(b), 4))\n    print(\"The referral clause decided \" + str(r) + \" approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.\")\n\ndef show_income():\n    aps = rules.applicants()\n    zero = 0\n    agree = 0\n    n = 0\n    for a in aps:\n        if not rules.skip_meant(a) and rules.approved(a):\n            n = n + 1\n            g = rules.income_guard_first(a)\n            f = rules.income_meaning_first(a)\n            if f == \"divides by zero\":\n                zero = zero + 1\n            elif f == g:\n                agree = agree + 1\n    print(\"The means test on the \" + str(n) + \" approved applicants: income on record / months under 2,000.00, and months on record above 0.\")\n    print(\"Guard first, months checked before the division: an answer for all \" + str(n) + \".\")\n    print(\"Meaning first, the average before the months: the same answer on \" + str(agree) + \", and a division by zero on the \" + str(zero) + \" with no months on record.\")\n    print(\"Moving the guard behind the test it protects reads better and is no longer a guard.\")\n\ndef ask_yes(prompt):\n    t = plain(input(prompt + \" (y/n)> \"))\n    if t == \"\":\n        return \"\"\n    if t == \"y\" or t == \"yes\":\n        return True\n    if t == \"n\" or t == \"no\":\n        return False\n    return \"bad\"\n\ndef own():\n    res = ask_yes(\"resident\")\n    if res == \"\":\n        print(\"Cancelled.\")\n        return\n    if res == \"bad\":\n        print(\"Type y or n.\")\n        return\n    t = plain(input(\"age (0 to 120)> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return\n    if len(t) > 3 or not digits(t) or int(t) > 120:\n        print(\"Type a whole number from 0 to 120.\")\n        return\n    age = int(t)\n    mem = ask_yes(\"member\")\n    if mem == \"\":\n        print(\"Cancelled.\")\n        return\n    if mem == \"bad\":\n        print(\"Type y or n.\")\n        return\n    ref = ask_yes(\"referred\")\n    if ref == \"\":\n        print(\"Cancelled.\")\n        return\n    if ref == \"bad\":\n        print(\"Type y or n.\")\n        return\n    t = plain(input(\"months of income on record (0 to 24)> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return\n    if len(t) > 2 or not digits(t) or int(t) > 24:\n        print(\"Type a whole number from 0 to 24.\")\n        return\n    months = int(t)\n    total = 0\n    if months > 0:\n        t = plain(input(\"income over those months, whole units (0 to 999999)> \"))\n        if t == \"\":\n            print(\"Cancelled.\")\n            return\n        if len(t) > 6 or not digits(t):\n            print(\"Type a whole number from 0 to 999999.\")\n            return\n        total = int(t) * 100\n    a = [res, age, mem, ref, months, total]\n    print(\"The skip rule: as meant it \" + skipped(rules.skip_meant(a)) + \" them; written by hand it \" + skipped(rules.skip_by_hand(a)) + \" them.\")\n    if rules.approved(a):\n        print(\"Member or referred: approved, by \" + [\"membership alone\", \"referral alone\", \"both\"][index(rules.decided(a))] + \".\")\n    else:\n        print(\"Member or referred: not approved.\")\n    g = rules.income_guard_first(a)\n    f = rules.income_meaning_first(a)\n    if months == 0:\n        print(\"The means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read.\")\n    else:\n        print(\"The means test: \" + money(int(total / months)) + \" a month on average, \" + verdict(g) + \" either way.\")\n\ndef skipped(b):\n    if b:\n        return \"skips\"\n    return \"keeps\"\n\ndef index(d):\n    if d == \"member\":\n        return 0\n    if d == \"referral\":\n        return 1\n    return 2\n\ndef verdict(g):\n    if g:\n        return \"under 2,000.00, so it passes\"\n    return \"not under 2,000.00, so it fails\"\n\nprint(\"== Eligibility rules ==\")\nprint(\"Three rules for a benefit, each written two ways, and who the difference reaches.\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        show_applicants()\n    elif choice == \"2\":\n        show_skip()\n    elif choice == \"3\":\n        show_clause()\n    elif choice == \"4\":\n        show_income()\n    elif choice == \"5\":\n        own()\n    elif choice == \"6\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 6.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "rules.eml",
      "eml": "# P170 eligibility rules - 300 made-up applicants for a benefit, and three\n# rules each written two ways. As in the corpus case\n# the-negation-was-distributed-by-hand, \"skip unless resident and adult\"\n# rewritten as \"skip if not resident and not adult\" skips only those who\n# fail both. As in which-clause-actually-decided, \"member or referred\" is\n# right every time, and in this population the referral clause never\n# decides. And as in the-guard-was-moved-for-readability, an average\n# income test reads better with the average first, and then divides by\n# zero for anyone with no months on record.\n\ndef limit():\n    # average monthly income below which the benefit is paid, in cents\n    return 200000\n\ndef step(x):\n    return (x * 48271) % 2147483647\n\ndef applicants():\n    # [resident, age, member, referred, months on record, total income in cents]\n    [0] * 300 => out\n    424242 => x\n    0 => k\n    while k < 300:\n        step(x) => x\n        x % 100 < 85 => resident\n        step(x) => x\n        14 + x % 67 => age\n        step(x) => x\n        x % 100 < 40 => member\n        step(x) => x\n        member and x % 100 < 30 => referred\n        step(x) => x\n        x % 13 => months\n        step(x) => x\n        months * (50000 + 5000 * (x % 71)) => total\n        [resident, age, member, referred, months, total] => out[k]\n        k + 1 => k\n    return out\n\ndef adult(a):\n    return a[1] >= 18\n\ndef skip_meant(a):\n    # skip unless a resident adult\n    return not (a[0] and adult(a))\n\ndef skip_by_hand(a):\n    # the negation distributed by hand\n    return not a[0] and not adult(a)\n\ndef approved(a):\n    return a[2] or a[3]\n\ndef decided(a):\n    # which clause carried an approval: \"member\", \"referral\" or \"both\"\n    if a[2] and a[3]:\n        return \"both\"\n    if a[2]:\n        return \"member\"\n    if a[3]:\n        return \"referral\"\n    return \"neither\"\n\ndef income_guard_first(a):\n    # True, False: the applicant passes the means test, guard read first\n    if a[4] > 0:\n        if a[5] < limit() * a[4]:\n            return True\n    return False\n\ndef income_meaning_first(a):\n    # the average first: \"divides by zero\" when there are no months\n    if a[4] == 0:\n        return \"divides by zero\"\n    if a[5] / a[4] < limit():\n        if a[4] > 0:\n            return True\n    return False\n",
      "python": "def limit():\n    return 200000\n\ndef step(x):\n    return x * 48271 % 2147483647\n\ndef applicants():\n    out = [0] * 300\n    x = 424242\n    k = 0\n    while k < 300:\n        x = step(x)\n        resident = x % 100 < 85\n        x = step(x)\n        age = 14 + x % 67\n        x = step(x)\n        member = x % 100 < 40\n        x = step(x)\n        referred = member and x % 100 < 30\n        x = step(x)\n        months = x % 13\n        x = step(x)\n        total = months * (50000 + 5000 * (x % 71))\n        out[k] = [resident, age, member, referred, months, total]\n        k = k + 1\n    return out\n\ndef adult(a):\n    return a[1] >= 18\n\ndef skip_meant(a):\n    return not (a[0] and adult(a))\n\ndef skip_by_hand(a):\n    return not a[0] and not adult(a)\n\ndef approved(a):\n    return a[2] or a[3]\n\ndef decided(a):\n    if a[2] and a[3]:\n        return \"both\"\n    if a[2]:\n        return \"member\"\n    if a[3]:\n        return \"referral\"\n    return \"neither\"\n\ndef income_guard_first(a):\n    if a[4] > 0:\n        if a[5] < limit() * a[4]:\n            return True\n    return False\n\ndef income_meaning_first(a):\n    if a[4] == 0:\n        return \"divides by zero\"\n    if a[5] / a[4] < limit():\n        if a[4] > 0:\n            return True\n    return False\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n5\n\n5\nmaybe\n5\ny\n\n5\ny\n121\n5\ny\nx\n5\ny\n30\n\n5\ny\n30\nk\n5\ny\n30\ny\n\n5\ny\n30\ny\nq\n5\ny\n30\ny\nn\n\n5\ny\n30\ny\nn\n25\n5\ny\n30\ny\nn\nx\n5\ny\n30\ny\nn\n4\n\n5\ny\n30\ny\nn\n4\n1000000\n5\ny\n30\ny\nn\n4\n1.5\n5\nno\n16\nno\nno\n12\n0\n6\n",
      "screen": "== Eligibility rules ==\nThree rules for a benefit, each written two ways, and who the difference reaches.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 0\nPick a number from 1 to 6.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> x\nPick a number from 1 to 6.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> maybe\nType y or n.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 121\nType a whole number from 0 to 120.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> x\nType a whole number from 0 to 120.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> k\nType y or n.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> q\nType y or n.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> 25\nType a whole number from 0 to 24.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> x\nType a whole number from 0 to 24.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> 4\nincome over those months, whole units (0 to 999999)> \nCancelled.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> 4\nincome over those months, whole units (0 to 999999)> 1000000\nType a whole number from 0 to 999999.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 30\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> 4\nincome over those months, whole units (0 to 999999)> 1.5\nType a whole number from 0 to 999999.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> no\nage (0 to 120)> 16\nmember (y/n)> no\nreferred (y/n)> no\nmonths of income on record (0 to 24)> 12\nincome over those months, whole units (0 to 999999)> 0\nThe skip rule: as meant it skips them; written by hand it skips them.\nMember or referred: not approved.\nThe means test: 0.00 a month on average, under 2,000.00, so it passes either way.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\n3\n4\n5\ny\n17\ny\nn\n3\n4500\n5\nn\n30\nn\ny\n0\n5\ny\n40\ny\ny\n6\n15000\n6\n",
      "screen": "== Eligibility rules ==\nThree rules for a benefit, each written two ways, and who the difference reaches.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 1\n300 applicants for a benefit; the first eight:\n      resident   age  member  referred   months  income on record\n  1   yes         34  yes     yes             9         27,900.00\n  2   yes         43  no      no              9         16,650.00\n  3   no          46  no      no              0              0.00\n  4   yes         35  yes     yes             6         14,700.00\n  5   yes         60  no      no             10         30,000.00\n  6   yes         43  yes     yes             2          6,800.00\n  7   yes         61  yes     yes             7         22,400.00\n  8   yes         27  yes     no              8         15,200.00\nThe rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 2\nSkip unless resident and adult, written two ways:\n  resident  adult  not (r and a)  not r and not a  applicants\n  yes       yes    no             no                      242\n  yes       no     yes            no                       11\n  no        yes    yes            no                       45\n  no        no     yes            yes                       2\nThe two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: 56 of 300 here, the residents under 18 and the adults from elsewhere.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 3\nOf the 242 resident adults, 101 are approved, as member or referred. Which clause carried each:\n  membership alone     76\n  referral alone        0\n  both                 25\nThe referral clause decided 0 approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 4\nThe means test on the 101 approved applicants: income on record / months under 2,000.00, and months on record above 0.\nGuard first, months checked before the division: an answer for all 101.\nMeaning first, the average before the months: the same answer on 94, and a division by zero on the 7 with no months on record.\nMoving the guard behind the test it protects reads better and is no longer a guard.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 17\nmember (y/n)> y\nreferred (y/n)> n\nmonths of income on record (0 to 24)> 3\nincome over those months, whole units (0 to 999999)> 4500\nThe skip rule: as meant it skips them; written by hand it keeps them.\nMember or referred: approved, by membership alone.\nThe means test: 1,500.00 a month on average, under 2,000.00, so it passes either way.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> n\nage (0 to 120)> 30\nmember (y/n)> n\nreferred (y/n)> y\nmonths of income on record (0 to 24)> 0\nThe skip rule: as meant it skips them; written by hand it keeps them.\nMember or referred: approved, by referral alone.\nThe means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 5\nresident (y/n)> y\nage (0 to 120)> 40\nmember (y/n)> y\nreferred (y/n)> y\nmonths of income on record (0 to 24)> 6\nincome over those months, whole units (0 to 999999)> 15000\nThe skip rule: as meant it keeps them; written by hand it keeps them.\nMember or referred: approved, by both.\nThe means test: 2,500.00 a month on average, not under 2,000.00, so it fails either way.\n\n1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "the-negation-was-distributed-by-hand",
      "caseId": "468-the-negation-was-distributed-by-hand",
      "title": "The negation was distributed by hand"
    },
    {
      "slug": "which-clause-actually-decided",
      "caseId": "476-which-clause-actually-decided",
      "title": "Which clause actually decided"
    },
    {
      "slug": "the-guard-was-moved-for-readability",
      "caseId": "465-the-guard-was-moved-for-readability",
      "title": "The guard was moved for readability"
    }
  ],
  "updated": "2026-10-19"
}
