def get_signal(wire):
    return wire("get_signal")

def set_signal(wire, new_value):
    return wire("set_signal")(new_value)

def add_action(wire, action_function):
    return wire("add_action")(action_function)
def make_time_segment(time, queue):
    return pair(time, queue)

def segment_time(s):
    return head(s)

def segment_queue(s):
    return tail(s)
def make_queue():
    return pair(None, None)
def front_ptr(queue):
    return head(queue)

def rear_ptr(queue):
    return tail(queue)

def set_front_ptr(queue, item):
    set_head(queue, item)

def set_rear_ptr(queue, item):
    set_tail(queue, item)
def is_empty_queue(queue):
    return is_none(front_ptr(queue))
def insert_queue(queue, item):
    new_pair = pair(item, None)
    if is_empty_queue(queue):
        set_front_ptr(queue, new_pair)
        set_rear_ptr(queue, new_pair)
    else:
        set_tail(rear_ptr(queue), new_pair)
        set_rear_ptr(queue, new_pair)
    return queue
def make_agenda():
    return llist(0)

def current_time(agenda):
    return head(agenda)

def set_current_time(agenda, time):
    set_head(agenda, time)

def segments(agenda):
    return tail(agenda)

def set_segments(agenda, segs):
    set_tail(agenda, segs)

def first_segment(agenda):
    return head(segments(agenda))

def rest_segments(agenda):
    return tail(segments(agenda))
def add_to_agenda(time, action, agenda):
    def belongs_before(segs):
        return is_none(segs) or time < segment_time(head(segs))
    def make_new_time_segment(time, action):
        q = make_queue()
        insert_queue(q, action)
        return make_time_segment(time, q)
    def add_to_segments(segs):
        if segment_time(head(segs)) == time:
            insert_queue(segment_queue(head(segs)), action)
        else:
            rest = tail(segs)
            if belongs_before(rest):
                set_tail(segs, pair(make_new_time_segment(time, action),
                                    tail(segs)))
            else:
                add_to_segments(rest)
    segs = segments(agenda)
    if belongs_before(segs):
        set_segments(agenda,
                     pair(make_new_time_segment(time, action), segs))
    else:
        add_to_segments(segs)
the_agenda = make_agenda()
inverter_delay = 2
and_gate_delay = 3
or_gate_delay = 5
def after_delay(delay, action):
    add_to_agenda(delay + current_time(the_agenda),
                  action,
                  the_agenda)
# contributed by GitHub user clean99

def logical_or(s1, s2):
    return (0
            if s1 == 0 and s2 == 0
            else (1
                  if s2 == 0 or s2 == 1
                  else error("invalid signal", s2))
            if s1 == 0 or s1 == 1
            else error("invalid signal", s1))
# contributed by GitHub user clean99

def or_gate(a1, a2, output):
    def or_action_function():
        new_value = logical_or(get_signal(a1),
                               get_signal(a2))
        after_delay(or_gate_delay,
                    lambda: set_signal(output, new_value))
    add_action(a1, or_action_function)
    add_action(a2, or_action_function)
    return "ok"
