{
  "id": "P098",
  "slug": "washing-machine",
  "key": "P098-washing-machine",
  "title": "Washing machine",
  "summary": "Washing programs of timed stages run minute by minute, with pause and resume, a door that stays locked while there is water or the drum is turning, and power cuts that make the stage under way start again - the finish accounted for minute by minute.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P098 - Washing machine\n\nWashing programs of timed stages, run minute by minute, and what can\nhappen to a real machine along the way:\n- pause and resume;\n- a door that stays locked while it is unsafe;\n- power cuts, after which the stage under way starts again.\n\nThe finish is accounted for minute by minute.\n\n- `main.eml` - the menu, the programs, events and the run table\n- `washer.eml` - the programs and their stages, reading events, and the\n  minute-by-minute run\n\nHow each part works:\n\n- A program is a list of stages, each with a fixed number of minutes, as\n  in the corpus case `washing-machine-cycle-simulator`. Cotton is fill 4,\n  wash 40 and drain 2, then 3 rinses (fill 3, rinse 6, drain 2), then\n  spin 10, for 89 minutes. Quick takes 31 minutes, delicate 50, and spin\n  only 10.\n- Events happen at the start of their minute, in the order typed: pause,\n  resume, open, close, cut (the power) or on.\n- The door stays locked while the program runs and while there is water\n  in the drum (from the first fill to the last drain). It also stays\n  locked for a minute after the drum stops. The program cannot resume\n  with the door open.\n- A power cut keeps the stage but loses the minutes done in it. When the\n  power comes back, that stage starts again, or waits paused if the\n  machine was paused or the door is open.\n- The finish is accounted for: the program's minutes, plus minutes\n  paused, plus minutes without power, plus minutes done again after a\n  power cut.\n\nWhat is checked: menu choices 1 to 4; a program name; 1 to 16 events,\neach a minute from 0 to 299 and an action, in order of minutes, or none.\nAn empty answer cancels. Events that make no sense at the time are\nrefused with the reason, such as resume when not paused or a second cut.\nThe run stops at minute 300.\n\nSessions: `sessions/basic.in` gives:\n- the four programs;\n- quick, straight through in 31 minutes;\n- quick with two pauses, the door refused and then opened, a resume\n  refused with the door open, and a power cut in a drain, finishing at\n  42 = 31 + 7 + 3 + 1;\n- cotton with a 30-minute power cut 26 minutes into the wash: 145 = 89 +\n  30 + 26;\n- spin only.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x; the program lizard; a cancel;\n- events abc, an unknown action, minutes out of order, an odd count,\n  minute 300, and 17 events; a cancel;\n- events at the wrong time, each refused with its reason, around a pause\n  and a power cut in the fill;\n- a pause never resumed: not finished by minute 300.\n\nBuilt on the verified corpus case `washing-machine-cycle-simulator`\n(stages with fixed times, run in order with a running total).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P098 washing machine: programs of timed stages, run minute by minute,\n# with pause and resume, a door that stays locked while it is unsafe, and\n# power cuts.\nimport washer\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    while len(s) < n:\n        s + \" \" => s\n    return s\n\ndef lpad(s, n):\n    while len(s) < n:\n        \" \" + s => s\n    return s\n\ndef describe(name):\n    washer.program(name) => p\n    washer.stages(p) => st\n    \"\" => line\n    if p[0] > 0:\n        \"fill \" + str(p[0]) + \", wash \" + str(p[1]) + \", drain \" + str(p[2]) + \", \" => line\n    if p[3] == 1:\n        line + \"1 rinse (fill \" + str(p[4]) + \", rinse \" + str(p[5]) + \", drain \" + str(p[6]) + \"), \" => line\n    elif p[3] > 1:\n        line + str(p[3]) + \" rinses (fill \" + str(p[4]) + \", rinse \" + str(p[5]) + \", drain \" + str(p[6]) + \" each), \" => line\n    line + \"spin \" + str(p[7]) => line\n    (\"  \" + pad(name, 10) + lpad(str(washer.total(st)), 3) + \" minutes: \" + line) ^0\n\ndef show_programs():\n    \"Programs, in minutes:\" ^0\n    for name in [\"cotton\", \"quick\", \"delicate\", \"spin\"]:\n        describe(name)\n    \"The door stays locked while the program runs, while there is water in the drum, and for a minute after the drum stops.\" ^0\n\ndef show_events(events):\n    if len(events) == 0:\n        \"No events: the program runs straight through.\" ^0\n        return\n    \"\" => line\n    for ev in events:\n        if line != \"\":\n            line + \", \" => line\n        line + str(ev[0]) + \" \" + ev[1] => line\n    (\"Events (minute and action): \" + line + \".\") ^0\n\ndef run(events):\n    plain(input(\"program (cotton, quick, delicate or spin)> \")) => name\n    if name == \"\":\n        \"Cancelled.\" ^0\n        return\n    washer.program(name) => p\n    if len(p) == 0:\n        \"Type cotton, quick, delicate or spin.\" ^0\n        return\n    washer.stages(p) => st\n    washer.total(st) => need\n    washer.simulate(st, events, 300) => r\n    (\"The \" + name + \" program, \" + washer.minutes(need) + \".\") ^0\n    show_events(events)\n    (\"  \" + pad(\"minutes\", 10) + pad(\"stage\", 28) + pad(\"water\", 7) + \"door\") ^0\n    0 => first\n    r[0] => tl\n    for t in [1:len(tl)]:\n        if t == len(tl) or tl[t][0] != tl[first][0] or tl[t][1] != tl[first][1] or tl[t][2] != tl[first][2]:\n            \"     \" => span\n            if t - 1 > first:\n                \"-\" + pad(str(t - 1), 4) => span\n            \"no\" => water\n            if tl[first][1]:\n                \"yes\" => water\n            (\"  \" + lpad(str(first), 3) + span + \"  \" + pad(tl[first][0], 28) + pad(water, 7) + tl[first][2]) ^0\n            t => first\n    for n in r[1]:\n        (\"Minute \" + str(n[0]) + \", \" + n[1] + \": \" + n[2] + \".\") ^0\n    if r[2] == -1:\n        (\"Not finished by minute 300.\") ^0\n        return\n    \"\" => extra\n    if r[3] > 0:\n        extra + \" + \" + str(r[3]) + \" paused\" => extra\n    if r[4] > 0:\n        extra + \" + \" + str(r[4]) + \" without power\" => extra\n    if r[5] > 0:\n        extra + \" + \" + str(r[5]) + \" done again after a power cut\" => extra\n    if extra == \"\":\n        (\"Finished at minute \" + str(r[2]) + \", the program's \" + str(need) + \".\") ^0\n    else:\n        (\"Finished at minute \" + str(r[2]) + \" = the program's \" + str(need) + extra + \".\") ^0\n\ndef set_events(events):\n    \"Events as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\" ^0\n    plain(input(\"events> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return events\n    if t == \"none\":\n        \"No events.\" ^0\n        return []\n    washer.parse_events(t) => out\n    if len(out) == 0:\n        \"Type up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\" ^0\n        return events\n    show_events(out)\n    return out\n\n[] => events\n\n\"== Washing machine ==\" ^0\n\"Programs of timed stages, minute by minute - with pause, a door that stays locked while it is unsafe, and power cuts.\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) programs  2) run  3) events  4) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        show_programs()\n    elif choice == \"2\":\n        run(events)\n    elif choice == \"3\":\n        set_events(events) => events\n    elif choice == \"4\":\n        False => running\n    else:\n        \"Pick a number from 1 to 4.\" ^0\n\"Bye.\" ^0\n",
      "python": "import washer\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    while len(s) < n:\n        s = s + \" \"\n    return s\n\ndef lpad(s, n):\n    while len(s) < n:\n        s = \" \" + s\n    return s\n\ndef describe(name):\n    p = washer.program(name)\n    st = washer.stages(p)\n    line = \"\"\n    if p[0] > 0:\n        line = \"fill \" + str(p[0]) + \", wash \" + str(p[1]) + \", drain \" + str(p[2]) + \", \"\n    if p[3] == 1:\n        line = line + \"1 rinse (fill \" + str(p[4]) + \", rinse \" + str(p[5]) + \", drain \" + str(p[6]) + \"), \"\n    elif p[3] > 1:\n        line = line + str(p[3]) + \" rinses (fill \" + str(p[4]) + \", rinse \" + str(p[5]) + \", drain \" + str(p[6]) + \" each), \"\n    line = line + \"spin \" + str(p[7])\n    print(\"  \" + pad(name, 10) + lpad(str(washer.total(st)), 3) + \" minutes: \" + line)\n\ndef show_programs():\n    print(\"Programs, in minutes:\")\n    for name in [\"cotton\", \"quick\", \"delicate\", \"spin\"]:\n        describe(name)\n    print(\"The door stays locked while the program runs, while there is water in the drum, and for a minute after the drum stops.\")\n\ndef show_events(events):\n    if len(events) == 0:\n        print(\"No events: the program runs straight through.\")\n        return\n    line = \"\"\n    for ev in events:\n        if line != \"\":\n            line = line + \", \"\n        line = line + str(ev[0]) + \" \" + ev[1]\n    print(\"Events (minute and action): \" + line + \".\")\n\ndef run(events):\n    name = plain(input(\"program (cotton, quick, delicate or spin)> \"))\n    if name == \"\":\n        print(\"Cancelled.\")\n        return\n    p = washer.program(name)\n    if len(p) == 0:\n        print(\"Type cotton, quick, delicate or spin.\")\n        return\n    st = washer.stages(p)\n    need = washer.total(st)\n    r = washer.simulate(st, events, 300)\n    print(\"The \" + name + \" program, \" + washer.minutes(need) + \".\")\n    show_events(events)\n    print(\"  \" + pad(\"minutes\", 10) + pad(\"stage\", 28) + pad(\"water\", 7) + \"door\")\n    first = 0\n    tl = r[0]\n    for t in range(1, len(tl)+1):\n        if t == len(tl) or tl[t][0] != tl[first][0] or tl[t][1] != tl[first][1] or tl[t][2] != tl[first][2]:\n            span = \"     \"\n            if t - 1 > first:\n                span = \"-\" + pad(str(t - 1), 4)\n            water = \"no\"\n            if tl[first][1]:\n                water = \"yes\"\n            print(\"  \" + lpad(str(first), 3) + span + \"  \" + pad(tl[first][0], 28) + pad(water, 7) + tl[first][2])\n            first = t\n    for n in r[1]:\n        print(\"Minute \" + str(n[0]) + \", \" + n[1] + \": \" + n[2] + \".\")\n    if r[2] == -1:\n        print(\"Not finished by minute 300.\")\n        return\n    extra = \"\"\n    if r[3] > 0:\n        extra = extra + \" + \" + str(r[3]) + \" paused\"\n    if r[4] > 0:\n        extra = extra + \" + \" + str(r[4]) + \" without power\"\n    if r[5] > 0:\n        extra = extra + \" + \" + str(r[5]) + \" done again after a power cut\"\n    if extra == \"\":\n        print(\"Finished at minute \" + str(r[2]) + \", the program's \" + str(need) + \".\")\n    else:\n        print(\"Finished at minute \" + str(r[2]) + \" = the program's \" + str(need) + extra + \".\")\n\ndef set_events(events):\n    print(\"Events as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\")\n    t = plain(input(\"events> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return events\n    if t == \"none\":\n        print(\"No events.\")\n        return []\n    out = washer.parse_events(t)\n    if len(out) == 0:\n        print(\"Type up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\")\n        return events\n    show_events(out)\n    return out\n\nevents = []\nprint(\"== Washing machine ==\")\nprint(\"Programs of timed stages, minute by minute - with pause, a door that stays locked while it is unsafe, and power cuts.\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) programs  2) run  3) events  4) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        show_programs()\n    elif choice == \"2\":\n        run(events)\n    elif choice == \"3\":\n        events = set_events(events)\n    elif choice == \"4\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 4.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "washer.eml",
      "eml": "# P098 washing machine - a program as stages with fixed times, run minute\n# by minute with a running total, as in the corpus case\n# washing-machine-cycle-simulator; and the things that happen to a real\n# machine: pause and resume, a door that stays locked while it is unsafe,\n# and a power cut, after which the stage under way starts again.\n\ndef program(name):\n    # [fill, wash, drain, rinses, rinse fill, rinse, rinse drain, spin]\n    {\"cotton\": [4, 40, 2, 3, 3, 6, 2, 10], \"quick\": [3, 12, 2, 1, 3, 4, 2, 5], \"delicate\": [4, 20, 2, 2, 3, 5, 2, 4], \"spin\": [0, 0, 0, 0, 0, 0, 0, 10]} => programs\n    if name in programs:\n        return programs[name]\n    return []\n\ndef stages(p):\n    # [label, minutes, water in the drum]\n    [] => out\n    if p[0] > 0:\n        out + [[\"fill\", p[0], True], [\"wash\", p[1], True], [\"drain\", p[2], True]] => out\n    if p[3] > 0:\n        for r in [1:p[3]]:\n            \"rinse \" + str(r) => n\n            out + [[n + \": fill\", p[4], True], [n, p[5], True], [n + \": drain\", p[6], True]] => out\n    out + [[\"spin\", p[7], False]] => out\n    return out\n\ndef total(st):\n    0 => n\n    for s in st:\n        n + s[1] => n\n    return n\n\ndef minutes(n):\n    if n == 1:\n        return \"1 minute\"\n    return str(n) + \" minutes\"\n\ndef parse_events(text):\n    # \"12 pause 15 resume\": minute then action, minutes 0 to 299 in order,\n    # 1 to 16 events; [] if anything is wrong.\n    {\"pause\": 1, \"resume\": 1, \"open\": 1, \"close\": 1, \"cut\": 1, \"on\": 1} => actions\n    [] => words\n    \"\" => w\n    for c in text + \" \":\n        if c == \" \":\n            if w != \"\":\n                words + [w] => words\n            \"\" => w\n        else:\n            w + c => w\n    if len(words) == 0 or len(words) % 2 == 1 or len(words) > 32:\n        return []\n    [] => out\n    0 => i\n    while i < len(words):\n        -1 => m\n        if len(words[i]) <= 3:\n            0 => m\n            for c in words[i]:\n                if m >= 0 and c >= \"0\" and c <= \"9\":\n                    m * 10 + int(c) => m\n                else:\n                    -1 => m\n        if m < 0 or m > 299 or not (words[i + 1] in actions):\n            return []\n        if len(out) > 0 and m < out[len(out) - 1][0]:\n            return []\n        out + [[m, words[i + 1]]] => out\n        i + 2 => i\n    return out\n\ndef simulate(st, events, cap):\n    # Minute by minute. Events at a minute happen before it is counted.\n    # Returns [timeline, notes, finish, paused, off, lost]: timeline holds\n    # [label, water, door] for each minute; finish is the minute the last\n    # stage is done (-1 if not by `cap`); lost is the minutes done in\n    # stages that a power cut made start again.\n    0 => s\n    0 => done_in\n    \"running\" => status\n    \"\" => before\n    False => door_open\n    0 => stopped\n    -1 => finish\n    0 => paused\n    0 => off\n    0 => lost\n    [] => timeline\n    [] => notes\n    0 => e\n    -1 => last\n    if len(events) > 0:\n        events[len(events) - 1][0] => last\n    0 => m\n    while m < cap and (finish == -1 or m <= finish + 1 or m <= last):\n        while e < len(events) and events[e][0] == m:\n            events[e][1] => a\n            \"\" => label\n            if status != \"done\":\n                st[s][0] => label\n            \"\" => text\n            if a == \"pause\":\n                if status == \"running\":\n                    \"paused\" => status\n                    m => stopped\n                    \"paused in \" + label => text\n                elif status == \"paused\":\n                    \"already paused\" => text\n                elif status == \"off\":\n                    \"the power is off\" => text\n                else:\n                    \"already finished\" => text\n            elif a == \"resume\":\n                if status == \"paused\":\n                    if door_open:\n                        \"close the door first\" => text\n                    else:\n                        \"running\" => status\n                        if done_in == 0:\n                            label + \" starts, \" + minutes(st[s][1]) => text\n                        else:\n                            label + \" goes on, \" + minutes(st[s][1] - done_in) + \" left in it\" => text\n                elif status == \"running\":\n                    \"not paused\" => text\n                elif status == \"off\":\n                    \"the power is off\" => text\n                else:\n                    \"already finished\" => text\n            elif a == \"open\":\n                if door_open:\n                    \"already open\" => text\n                elif status == \"running\":\n                    \"stays locked - the program is running\" => text\n                elif status != \"done\" and st[s][2]:\n                    \"stays locked - water in the drum\" => text\n                elif m - stopped < 1:\n                    \"stays locked - the drum is still turning\" => text\n                else:\n                    True => door_open\n                    \"the door opens\" => text\n            elif a == \"close\":\n                if door_open:\n                    False => door_open\n                    \"the door closes\" => text\n                else:\n                    \"already closed\" => text\n            elif a == \"cut\":\n                if status == \"off\":\n                    \"already off\" => text\n                elif status == \"done\":\n                    \"done\" => before\n                    \"off\" => status\n                    \"power off; the program had finished\" => text\n                else:\n                    status => before\n                    if status == \"running\":\n                        m => stopped\n                    \"off\" => status\n                    if done_in == 0:\n                        \"power off in \" + label + \", none of it done yet\" => text\n                    elif done_in == 1:\n                        \"power off in \" + label + \": the 1 minute done in it is lost\" => text\n                    else:\n                        \"power off in \" + label + \": the \" + minutes(done_in) + \" done in it are lost\" => text\n                    lost + done_in => lost\n                    0 => done_in\n            else:\n                if status != \"off\":\n                    \"the power is on\" => text\n                elif before == \"done\":\n                    \"done\" => status\n                    \"power back\" => text\n                elif before == \"running\" and not door_open:\n                    \"running\" => status\n                    \"power back: \" + label + \" starts again\" => text\n                else:\n                    \"paused\" => status\n                    if before == \"running\":\n                        \"power back; the door is open, so it waits, paused: \" + label + \" will start again\" => text\n                    else:\n                        \"power back, still paused: \" + label + \" will start again\" => text\n            notes + [[m, a, text]] => notes\n            e + 1 => e\n        \"finished\" => label\n        False => water\n        if status != \"done\" and not (status == \"off\" and before == \"done\"):\n            st[s][0] => label\n            st[s][2] => water\n            if status == \"paused\":\n                \"paused in \" + label => label\n            elif status == \"off\":\n                \"no power in \" + label => label\n        elif status == \"off\":\n            \"no power, finished\" => label\n        \"closed\" => door\n        if door_open:\n            \"open\" => door\n        elif status == \"running\" or water or m - stopped < 1:\n            \"locked\" => door\n        timeline + [[label, water, door]] => timeline\n        if status == \"running\":\n            done_in + 1 => done_in\n            if done_in == st[s][1]:\n                s + 1 => s\n                0 => done_in\n                if s == len(st):\n                    \"done\" => status\n                    m + 1 => finish\n                    m + 1 => stopped\n                    len(st) - 1 => s\n        elif finish == -1:\n            if status == \"paused\":\n                paused + 1 => paused\n            else:\n                off + 1 => off\n        m + 1 => m\n    return [timeline, notes, finish, paused, off, lost]\n",
      "python": "def program(name):\n    programs = {\"cotton\": [4, 40, 2, 3, 3, 6, 2, 10], \"quick\": [3, 12, 2, 1, 3, 4, 2, 5], \"delicate\": [4, 20, 2, 2, 3, 5, 2, 4], \"spin\": [0, 0, 0, 0, 0, 0, 0, 10]}\n    if name in programs:\n        return programs[name]\n    return []\n\ndef stages(p):\n    out = []\n    if p[0] > 0:\n        out = out + [[\"fill\", p[0], True], [\"wash\", p[1], True], [\"drain\", p[2], True]]\n    if p[3] > 0:\n        for r in range(1, p[3]+1):\n            n = \"rinse \" + str(r)\n            out = out + [[n + \": fill\", p[4], True], [n, p[5], True], [n + \": drain\", p[6], True]]\n    out = out + [[\"spin\", p[7], False]]\n    return out\n\ndef total(st):\n    n = 0\n    for s in st:\n        n = n + s[1]\n    return n\n\ndef minutes(n):\n    if n == 1:\n        return \"1 minute\"\n    return str(n) + \" minutes\"\n\ndef parse_events(text):\n    actions = {\"pause\": 1, \"resume\": 1, \"open\": 1, \"close\": 1, \"cut\": 1, \"on\": 1}\n    words = []\n    w = \"\"\n    for c in text + \" \":\n        if c == \" \":\n            if w != \"\":\n                words = words + [w]\n            w = \"\"\n        else:\n            w = w + c\n    if len(words) == 0 or len(words) % 2 == 1 or len(words) > 32:\n        return []\n    out = []\n    i = 0\n    while i < len(words):\n        m = -1\n        if len(words[i]) <= 3:\n            m = 0\n            for c in words[i]:\n                if m >= 0 and c >= \"0\" and c <= \"9\":\n                    m = m * 10 + int(c)\n                else:\n                    m = -1\n        if m < 0 or m > 299 or not words[i + 1] in actions:\n            return []\n        if len(out) > 0 and m < out[len(out) - 1][0]:\n            return []\n        out = out + [[m, words[i + 1]]]\n        i = i + 2\n    return out\n\ndef simulate(st, events, cap):\n    s = 0\n    done_in = 0\n    status = \"running\"\n    before = \"\"\n    door_open = False\n    stopped = 0\n    finish = -1\n    paused = 0\n    off = 0\n    lost = 0\n    timeline = []\n    notes = []\n    e = 0\n    last = -1\n    if len(events) > 0:\n        last = events[len(events) - 1][0]\n    m = 0\n    while m < cap and (finish == -1 or m <= finish + 1 or m <= last):\n        while e < len(events) and events[e][0] == m:\n            a = events[e][1]\n            label = \"\"\n            if status != \"done\":\n                label = st[s][0]\n            text = \"\"\n            if a == \"pause\":\n                if status == \"running\":\n                    status = \"paused\"\n                    stopped = m\n                    text = \"paused in \" + label\n                elif status == \"paused\":\n                    text = \"already paused\"\n                elif status == \"off\":\n                    text = \"the power is off\"\n                else:\n                    text = \"already finished\"\n            elif a == \"resume\":\n                if status == \"paused\":\n                    if door_open:\n                        text = \"close the door first\"\n                    else:\n                        status = \"running\"\n                        if done_in == 0:\n                            text = label + \" starts, \" + minutes(st[s][1])\n                        else:\n                            text = label + \" goes on, \" + minutes(st[s][1] - done_in) + \" left in it\"\n                elif status == \"running\":\n                    text = \"not paused\"\n                elif status == \"off\":\n                    text = \"the power is off\"\n                else:\n                    text = \"already finished\"\n            elif a == \"open\":\n                if door_open:\n                    text = \"already open\"\n                elif status == \"running\":\n                    text = \"stays locked - the program is running\"\n                elif status != \"done\" and st[s][2]:\n                    text = \"stays locked - water in the drum\"\n                elif m - stopped < 1:\n                    text = \"stays locked - the drum is still turning\"\n                else:\n                    door_open = True\n                    text = \"the door opens\"\n            elif a == \"close\":\n                if door_open:\n                    door_open = False\n                    text = \"the door closes\"\n                else:\n                    text = \"already closed\"\n            elif a == \"cut\":\n                if status == \"off\":\n                    text = \"already off\"\n                elif status == \"done\":\n                    before = \"done\"\n                    status = \"off\"\n                    text = \"power off; the program had finished\"\n                else:\n                    before = status\n                    if status == \"running\":\n                        stopped = m\n                    status = \"off\"\n                    if done_in == 0:\n                        text = \"power off in \" + label + \", none of it done yet\"\n                    elif done_in == 1:\n                        text = \"power off in \" + label + \": the 1 minute done in it is lost\"\n                    else:\n                        text = \"power off in \" + label + \": the \" + minutes(done_in) + \" done in it are lost\"\n                    lost = lost + done_in\n                    done_in = 0\n            elif status != \"off\":\n                text = \"the power is on\"\n            elif before == \"done\":\n                status = \"done\"\n                text = \"power back\"\n            elif before == \"running\" and not door_open:\n                status = \"running\"\n                text = \"power back: \" + label + \" starts again\"\n            else:\n                status = \"paused\"\n                if before == \"running\":\n                    text = \"power back; the door is open, so it waits, paused: \" + label + \" will start again\"\n                else:\n                    text = \"power back, still paused: \" + label + \" will start again\"\n            notes = notes + [[m, a, text]]\n            e = e + 1\n        label = \"finished\"\n        water = False\n        if status != \"done\" and not (status == \"off\" and before == \"done\"):\n            label = st[s][0]\n            water = st[s][2]\n            if status == \"paused\":\n                label = \"paused in \" + label\n            elif status == \"off\":\n                label = \"no power in \" + label\n        elif status == \"off\":\n            label = \"no power, finished\"\n        door = \"closed\"\n        if door_open:\n            door = \"open\"\n        elif status == \"running\" or water or m - stopped < 1:\n            door = \"locked\"\n        timeline = timeline + [[label, water, door]]\n        if status == \"running\":\n            done_in = done_in + 1\n            if done_in == st[s][1]:\n                s = s + 1\n                done_in = 0\n                if s == len(st):\n                    status = \"done\"\n                    finish = m + 1\n                    stopped = m + 1\n                    s = len(st) - 1\n        elif finish == -1:\n            if status == \"paused\":\n                paused = paused + 1\n            else:\n                off = off + 1\n        m = m + 1\n    return [timeline, notes, finish, paused, off, lost]\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n2\nlizard\n2\n\n3\nabc\n3\n5 dance\n3\n10 pause 5 resume\n3\n12\n3\n300 pause\n3\n0 open 1 open 2 open 3 open 4 open 5 open 6 open 7 open 8 open 9 open 10 open 11 open 12 open 13 open 14 open 15 open 16 open\n3\n\n3\n0 resume 0 close 0 on 2 pause 3 pause 4 cut 5 cut 6 pause 7 resume 8 on 9 resume 10 resume\n2\nquick\n3\n5 pause\n2\ndelicate\n4\n",
      "screen": "== Washing machine ==\nPrograms of timed stages, minute by minute - with pause, a door that stays locked while it is unsafe, and power cuts.\n\n1) programs  2) run  3) events  4) quit\nchoice> 0\nPick a number from 1 to 4.\n\n1) programs  2) run  3) events  4) quit\nchoice> x\nPick a number from 1 to 4.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> lizard\nType cotton, quick, delicate or spin.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> \nCancelled.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> abc\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 5 dance\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 10 pause 5 resume\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 12\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 300 pause\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 0 open 1 open 2 open 3 open 4 open 5 open 6 open 7 open 8 open 9 open 10 open 11 open 12 open 13 open 14 open 15 open 16 open\nType up to 16 pairs: a minute from 0 to 299, then pause, resume, open, close, cut or on; minutes in order.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> \nCancelled.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 0 resume 0 close 0 on 2 pause 3 pause 4 cut 5 cut 6 pause 7 resume 8 on 9 resume 10 resume\nEvents (minute and action): 0 resume, 0 close, 0 on, 2 pause, 3 pause, 4 cut, 5 cut, 6 pause, 7 resume, 8 on, 9 resume, 10 resume.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> quick\nThe quick program, 31 minutes.\nEvents (minute and action): 0 resume, 0 close, 0 on, 2 pause, 3 pause, 4 cut, 5 cut, 6 pause, 7 resume, 8 on, 9 resume, 10 resume.\n  minutes   stage                       water  door\n    0-1     fill                        yes    locked\n    2-3     paused in fill              yes    locked\n    4-7     no power in fill            yes    locked\n    8       paused in fill              yes    locked\n    9-11    fill                        yes    locked\n   12-23    wash                        yes    locked\n   24-25    drain                       yes    locked\n   26-28    rinse 1: fill               yes    locked\n   29-32    rinse 1                     yes    locked\n   33-34    rinse 1: drain              yes    locked\n   35-39    spin                        no     locked\n   40       finished                    no     locked\n   41       finished                    no     closed\nMinute 0, resume: not paused.\nMinute 0, close: already closed.\nMinute 0, on: the power is on.\nMinute 2, pause: paused in fill.\nMinute 3, pause: already paused.\nMinute 4, cut: power off in fill: the 2 minutes done in it are lost.\nMinute 5, cut: already off.\nMinute 6, pause: the power is off.\nMinute 7, resume: the power is off.\nMinute 8, on: power back, still paused: fill will start again.\nMinute 9, resume: fill starts, 3 minutes.\nMinute 10, resume: not paused.\nFinished at minute 40 = the program's 31 + 3 paused + 4 without power + 2 done again after a power cut.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 5 pause\nEvents (minute and action): 5 pause.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> delicate\nThe delicate program, 50 minutes.\nEvents (minute and action): 5 pause.\n  minutes   stage                       water  door\n    0-3     fill                        yes    locked\n    4       wash                        yes    locked\n    5-299   paused in wash              yes    locked\nMinute 5, pause: paused in wash.\nNot finished by minute 300.\n\n1) programs  2) run  3) events  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\nquick\n3\n10 pause 11 open 14 resume 20 cut 23 on 36 pause 36 open 37 open 38 resume 38 close 39 resume 42 open 43 open\n2\nquick\n3\n30 cut 60 on\n2\ncotton\n3\nnone\n2\nspin\n4\n",
      "screen": "== Washing machine ==\nPrograms of timed stages, minute by minute - with pause, a door that stays locked while it is unsafe, and power cuts.\n\n1) programs  2) run  3) events  4) quit\nchoice> 1\nPrograms, in minutes:\n  cotton     89 minutes: fill 4, wash 40, drain 2, 3 rinses (fill 3, rinse 6, drain 2 each), spin 10\n  quick      31 minutes: fill 3, wash 12, drain 2, 1 rinse (fill 3, rinse 4, drain 2), spin 5\n  delicate   50 minutes: fill 4, wash 20, drain 2, 2 rinses (fill 3, rinse 5, drain 2 each), spin 4\n  spin       10 minutes: spin 10\nThe door stays locked while the program runs, while there is water in the drum, and for a minute after the drum stops.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> quick\nThe quick program, 31 minutes.\nNo events: the program runs straight through.\n  minutes   stage                       water  door\n    0-2     fill                        yes    locked\n    3-14    wash                        yes    locked\n   15-16    drain                       yes    locked\n   17-19    rinse 1: fill               yes    locked\n   20-23    rinse 1                     yes    locked\n   24-25    rinse 1: drain              yes    locked\n   26-30    spin                        no     locked\n   31       finished                    no     locked\n   32       finished                    no     closed\nFinished at minute 31, the program's 31.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 10 pause 11 open 14 resume 20 cut 23 on 36 pause 36 open 37 open 38 resume 38 close 39 resume 42 open 43 open\nEvents (minute and action): 10 pause, 11 open, 14 resume, 20 cut, 23 on, 36 pause, 36 open, 37 open, 38 resume, 38 close, 39 resume, 42 open, 43 open.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> quick\nThe quick program, 31 minutes.\nEvents (minute and action): 10 pause, 11 open, 14 resume, 20 cut, 23 on, 36 pause, 36 open, 37 open, 38 resume, 38 close, 39 resume, 42 open, 43 open.\n  minutes   stage                       water  door\n    0-2     fill                        yes    locked\n    3-9     wash                        yes    locked\n   10-13    paused in wash              yes    locked\n   14-18    wash                        yes    locked\n   19       drain                       yes    locked\n   20-22    no power in drain           yes    locked\n   23-24    drain                       yes    locked\n   25-27    rinse 1: fill               yes    locked\n   28-31    rinse 1                     yes    locked\n   32-33    rinse 1: drain              yes    locked\n   34-35    spin                        no     locked\n   36       paused in spin              no     locked\n   37       paused in spin              no     open\n   38       paused in spin              no     closed\n   39-41    spin                        no     locked\n   42       finished                    no     locked\n   43       finished                    no     open\nMinute 10, pause: paused in wash.\nMinute 11, open: stays locked - water in the drum.\nMinute 14, resume: wash goes on, 5 minutes left in it.\nMinute 20, cut: power off in drain: the 1 minute done in it is lost.\nMinute 23, on: power back: drain starts again.\nMinute 36, pause: paused in spin.\nMinute 36, open: stays locked - the drum is still turning.\nMinute 37, open: the door opens.\nMinute 38, resume: close the door first.\nMinute 38, close: the door closes.\nMinute 39, resume: spin goes on, 3 minutes left in it.\nMinute 42, open: stays locked - the drum is still turning.\nMinute 43, open: the door opens.\nFinished at minute 42 = the program's 31 + 7 paused + 3 without power + 1 done again after a power cut.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> 30 cut 60 on\nEvents (minute and action): 30 cut, 60 on.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> cotton\nThe cotton program, 89 minutes.\nEvents (minute and action): 30 cut, 60 on.\n  minutes   stage                       water  door\n    0-3     fill                        yes    locked\n    4-29    wash                        yes    locked\n   30-59    no power in wash            yes    locked\n   60-99    wash                        yes    locked\n  100-101   drain                       yes    locked\n  102-104   rinse 1: fill               yes    locked\n  105-110   rinse 1                     yes    locked\n  111-112   rinse 1: drain              yes    locked\n  113-115   rinse 2: fill               yes    locked\n  116-121   rinse 2                     yes    locked\n  122-123   rinse 2: drain              yes    locked\n  124-126   rinse 3: fill               yes    locked\n  127-132   rinse 3                     yes    locked\n  133-134   rinse 3: drain              yes    locked\n  135-144   spin                        no     locked\n  145       finished                    no     locked\n  146       finished                    no     closed\nMinute 30, cut: power off in wash: the 26 minutes done in it are lost.\nMinute 60, on: power back: wash starts again.\nFinished at minute 145 = the program's 89 + 30 without power + 26 done again after a power cut.\n\n1) programs  2) run  3) events  4) quit\nchoice> 3\nEvents as minute and action, in order: pause, resume, open, close, cut (the power) or on. For example: 10 pause 12 open 14 resume. Or none.\nevents> none\nNo events.\n\n1) programs  2) run  3) events  4) quit\nchoice> 2\nprogram (cotton, quick, delicate or spin)> spin\nThe spin program, 10 minutes.\nNo events: the program runs straight through.\n  minutes   stage                       water  door\n    0-9     spin                        no     locked\n   10       finished                    no     locked\n   11       finished                    no     closed\nFinished at minute 10, the program's 10.\n\n1) programs  2) run  3) events  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "washing-machine-cycle-simulator",
      "caseId": "079-washing-machine-cycle-simulator",
      "title": "Washing machine cycle simulator"
    }
  ],
  "updated": "2026-10-15"
}
