def check_attendance(registrants, attendees, config):
    """Iterates through the list of registrants and checks each registrant
    against the collection of emails of the actual attendees.  If the
    registrant's email address is present in the collection of attendees,
    the ATTENDED_FIELD field is set to true for the registrant.
    
    This function maintains a set of registered attendee email addresses.
    The difference between the original attendee set and the set of registered
    attendees is treated as the collection of attendees that did not register.
    
    This collection of individuals that attended, but did not register is
    iterated over and corresponding registration records are created for each
    unregistered attendee.  Note that these new records will not contain most
    of the registration information.
    Args:
        registrants - list of all registration records
        attendees - dictionary containing the actual attendee records, with
                    email addresses forced to lowercase as the keys
        config - ConfigParser object containing the configuration data

    Returns:
        Dictionary containing the attendance counts.
    """
    # Field name mappings, note that the "_att" suffixes apply to the
    # attendee file, while "_reg" applies to the registration file
    email_field_reg = config['REGISTRANTS']['EMAIL_FIELD']
    email_field_att = config['ATTENDEES']['EMAIL_FIELD']
    attended_field = config['REGISTRANTS']['ATTENDED_FIELD']
    first_nm_field_reg = config['REGISTRANTS']['FIRST_NM_FIELD']
    first_nm_field_att = config['ATTENDEES']['FIRST_NM_FIELD']
    last_nm_field_reg = config['REGISTRANTS']['LAST_NM_FIELD']
    last_nm_field_att = config['ATTENDEES']['LAST_NM_FIELD']
    attend_dur_reg = config['REGISTRANTS']['ATTEND_DUR_FIELD']
    attend_dur_att = config['ATTENDEES']['ATTEND_DUR_FIELD']
    na_val = config['REGISTRANTS']['NOT_AVAIL']

    def proc_unreg(unregistered, reg_fields):
        """Factory method to create a new registration record for the given
        email address.  NOTE:  the default value for all fields is specified
        in this method

        Args:
            unregistered - dictionary containing the information of an
                                individual that attended the event.  Will be
                                used for the new registration record
            reg_fields - list of strings identifying the field names (used
                                as keys in this implementation) for the
                                registration record.
        Returns:
            counts - dictionary containing attendance statistics
        """
        # Initialize the dictionary representing the new record with the
        # default field value, then set the ATTENDED_FIELD field to True,
        # finally add the new row to the collection of registrants.
        new_reg = {fld:na_val for fld in reg_fields}
        new_reg[email_field_reg] = unregistered[email_field_att]
        new_reg[last_nm_field_reg] = unregistered[last_nm_field_att]
        new_reg[first_nm_field_reg] = unregistered[first_nm_field_att]
        new_reg[attend_dur_reg] = unregistered[attend_dur_att]
        new_reg[attended_field] = True        
        registrants.append(new_reg)
        print("Unregistered attendee: " + repr(unregistered[email_field_att]))

    # Keeps the counts of registrants, attendees, etc.
    counts = {'registrants':len(registrants)
             ,'attendees':len(attendees)
             ,'reg_no_attend':0
             ,'attend_no_reg':0
             }
    # We'll keep a list of the attendees that were also registered.  This list
    # will be used to deduce the list of attendees that weren't registered.
    registered = []
    reg_fields = list(registrants[0].keys())
    # We'll need a set identify the group of attended, but unregistered
    # individuals, so we might as well use it for checking attendance, as
    # well
    attendee_set = frozenset(attendees.keys())
    
    for reg in registrants:
        reg_email = reg[email_field_reg].lower()
        if reg_email in attendee_set:
            reg[attended_field] = True
            reg[attend_dur_reg] = attendees[reg_email][attend_dur_att]
            registered.append(reg_email)
    # We should have all of the registered attendees marked. The registrants
    # that did not attend are marked when the registration list was processed.
    # Now we have to deal with the attendees that weren't registered
    unregistered = attendee_set - set(registered)
    for unreg in unregistered:
        proc_unreg(attendees[unreg], reg_fields)
    
    # Complete the counts
    counts['attend_no_reg'] = len(unregistered)
    counts['reg_no_attend'] = counts['registrants'] - (counts['attendees'] -
                                                       counts['attend_no_reg'])
    return counts