Skip to main content Skip to navigation

Elizabeth Hudnott's answer to Exercise 4

The following annotated JS-EDEN script is a solution to Exercise 4 constructed by Elizabeth Hudnott. It contains comments that explain the train of thought that accompanied the construction. To check out the solution, you should first load the Light-in-the-Room and Electrical Circuit Diagram construals, then copy-and-paste the script below into the JS-EDEN Input Window and press Submit. To appreciate the construction fully, it may be most appropriate to do this in an incremental fashion.

initializing = true;

masterSwitchClosed = true;

##The bathroom light doesn't come on when the bulb is broken regardless of whether the cord has been
##pulled or not.
lightison = false;

##Remodel the original light switch as a pull cord that sometimes gets stuck.
switchlabel is "Pull Cord";

##Whether or not Anna left light on before she left home or not. Assumes each possibily is equally likely. Anna cannot see this observable.
lightLeftOn = randomInteger(1, 2) == 1;
##Number of times that the cord switch has transitioned ON->OFF or OFF->ON (possibly via the intermediate stuck state).
timesCordPulled = 0;
##Assume that only OFF->ON transitions get stuck, with a 1 in 3 probability.
stuckProbability = 1/3;
##Whether or not the cord switch is currently in the stuck state.
cordStuck = !lightLeftOn && random() <= stuckProbability;
##The minimum and maxiumum possible number of switch transitions, according to Anna's observations about the stuck state.
minTimesCordPulled = 0;
maxTimesCordPulled = 0;
definitelyOn = false;
definitelyOff = false;
definitelyNotLive is !masterSwitchClosed || definitelyOff;
myanswercorrect is ((myanswer == "Y") and (definitelyNotLive)) or ((myanswer == "N") and (!definitelyNotLive));
resulttext is myanswer == @? "" : myanswercorrect? "Correct answer!" : "Oops.. are you sure?";

##Assumptions about the stuck state (based on my own experiences of a failing pull cord):
##Only OFF->ON transitions have a chance of getting stuck. ON->OFF transitions always succeed without getting stuck.
##Anna can detect when the switch becomes unstuck (e.g. it makes it an unusual kind of click sound (different to normal) or a has a different tactile feel).
##Anna cannot detect when the switch becomes stuck while the bulb is broken (i.e. OFF->STUCK and OFF->ON seem the same).
##1 in 3 chance of getting stuck.
##Anna cannot differentiate STUCK->STUCK transitions from STUCK->ON transitions while the bulb is broken.
##Exercise: Try changing the last condition. My experience suggests that it is sometimes possible to differentiate these two things, if one pays careful attention to their senses.

cordDescription is "Cord pulled " // (
(minTimesCordPulled == maxTimesCordPulled)?
str(minTimesCordPulled) :
"between " // str(minTimesCordPulled) // " and " // str(maxTimesCordPulled)
) // " times. " // cordNotice;
cordNotice = "";
cordText is Text(cordDescription, 200, 80);

proc press_switch: lightswitch_clicked {
auto previouslyStuck;
##The random part models the fact that the switch sometimes gets stuck and doesn't change state.
if (!lightswitch_clicked && !initializing) {
previouslyStuck = cordStuck;
cordStuck = !switch1Closed && random() <= stuckProbability;

if (previouslyStuck && !cordStuck) {
cordNotice = "UNSTUCK!";
definitelyOn = true;
definitelyOff = false;
} else {
if (definitelyOn) {
definitelyOn = false;
definitelyOff = true;
} else {
definitelyOff = false;
cordNotice = "";

if (!cordStuck) {

##Link the state of the pull cord to the circuit diagram.
switch1Closed is ((lightLeftOn? 1 : 0) + timesCordPulled) % 2 == 0;

##Remove ability to throw the switch using the circuit diagram.

##Add the master switch to the things that Anna can observe.
masterlightswitch is Button("masterlightswitch", "Flick master switch", 200, 123);

proc press_master_switch: masterlightswitch_clicked {
if (masterlightswitch_clicked) {
masterSwitchClosed = not masterSwitchClosed;

##Model the unknown switch position and the broken bulb in the circuit diagram.
lightLeftOnColour = "#FFBB11";
lightNotLeftOnColour = "#BBBBBB";

func unknownSwitch {
para position, length, radius, inPosition1;
auto x, y, items;
x = position.x;
y = position.y;
length = length - radius;
items = [];
if (!inPosition1) {
append items, Line(x, y + radius, x + length / sqrt(2), y + length / sqrt(2), lightLeftOnColour);
append items, Line(x, y + radius, x, y + length, lightNotLeftOnColour);
} else {
append items, Line(x, y + radius, x + length / sqrt(2), y + length / sqrt(2), lightNotLeftOnColour);
append items, Line(x, y + radius, x, y + length, lightLeftOnColour);
append items, Circle(x + length / sqrt(2), y + length / sqrt(2), radius, "white", "black");
append items, Circle(x, y + radius, radius, "white", "black");
append items, Circle(x, y + length, radius, "white", "black");
append items, Text("?", x + 3, y + (length + radius) / 2, "18pt", "#666666", {italic: true, valign: "middle"});
return items;
switch1 is unknownSwitch(switch1Position, switchLength, junctionRadius, switch1Closed);

func brokenBulb {
para position, r, masterSwitchCondition, switchedOn;
auto x, y, ratio, items, colour;
x = position.x;
y = position.y;
ratio = 0.55;
items = [];
if (!masterSwitchCondition) {
colour = @;
} else if (switchedOn) {
colour = lightLeftOnColour;
} else {
colour = lightNotLeftOnColour;
append items, Circle(x, y, r, colour, "black");
append items, Line(x, y - r, x, y - ( 1 - ratio) * r);
append items, Line(x, y + (1 - ratio) * r, x, y + r);
return items;
bulb1 is brokenBulb(bulb1Position, bulbRadius, masterSwitchClosed, switch1Closed);

keyText is
"<p style='color: " // lightLeftOnColour // "'>
If the light was left on when Anna left home then the connections are live when the bulb is shaded in this colour (even number of cord pulls).
<p style='color: " // lightNotLeftOnColour // "'>
If the light was switched off when Anna left home then the connections are live when the bulb is shaded in this colour (odd number of cord pulls).
<p style='color: " // _view_circuit_background_colour // "'>
The connections are definitely not live when the bulb is shaded in this colour.
keyTop is bottom + 35;
key is Div(keyText, left, keyTop, width, "key", "background-color: #FF3333; padding: 0pt 4pt");

##Change the puzzle question.
question is Text("Is is safe to change the bulb?", 50, 200, "10pt","blue" );

withAppendedItem(&picture, "cordText, masterlightswitch, masterswitchlabel");
withAppendedItem(&circuit, "key");
_view_circuit_height is keyTop + key_height;
initializing = false;