Task
Solve Dinesman's multiple dwelling problem but in a way that most naturally follows the problem statement given below.

Solutions are allowed (but not required) to parse and interpret the problem text, but should remain flexible and should state what changes to the problem text are allowed. Flexibility and ease of expression are valued.

Examples may be be split into "setup", "problem statement", and "output" sections where the ease and naturalness of stating the problem and getting an answer, as well as the ease and flexibility of modifying the problem are the primary concerns.

Example output should be shown here, as well as any comments on the examples flexibility.



The problem
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors.


   Baker does not live on the top floor.
   Cooper does not live on the bottom floor. 
   Fletcher does not live on either the top or the bottom floor.
   Miller lives on a higher floor than does Cooper.
   Smith does not live on a floor adjacent to Fletcher's. 
   Fletcher does not live on a floor adjacent to Cooper's.

Where does everyone live?

# attempt to solve the dinesman Multiple Dwelling problem #
 
# SETUP #
 
# special floor values #
INT    top floor    = 4;
INT    bottom floor = 0;
 
# mode to specify the persons floor constraint #
MODE PERSON = STRUCT( STRING name, REF INT floor, PROC( INT )BOOL ok );
 
# yields TRUE if the floor of the specified person is OK, FALSE otherwise #
OP OK = ( PERSON p )BOOL: ( ok OF p )( floor OF p );
 
# yields TRUE if floor is adjacent to other persons floor, FALSE otherwise #
PROC adjacent = ( INT floor, other persons floor )BOOL: floor >= ( other persons floor - 1 ) AND floor <= ( other persons floor + 1 );
 
# displays the floor of an occupant #
PROC print floor = ( PERSON occupant )VOID: print( ( whole( floor OF occupant, -1 ), " ", name OF occupant, newline ) );
 
# PROBLEM STATEMENT #
 
# the inhabitants with their floor and constraints #
PERSON baker    = ( "Baker",    LOC INT := 0, ( INT floor )BOOL: floor /= top floor );
PERSON cooper   = ( "Cooper",   LOC INT := 0, ( INT floor )BOOL: floor /= bottom floor );
PERSON fletcher = ( "Fletcher", LOC INT := 0, ( INT floor )BOOL: floor /= top floor AND floor /= bottom floor
                                                                                    AND NOT adjacent( floor, floor OF cooper ) );
PERSON miller   = ( "Miller",   LOC INT := 0, ( INT floor )BOOL: floor > floor OF cooper );
PERSON smith    = ( "Smith",    LOC INT := 0, ( INT floor )BOOL: NOT adjacent( floor, floor OF fletcher ) );
 
# SOLUTION #
 
# "brute force" solution - we run through the possible 5^5 configurations          #
# we cold optimise this by e.g. restricting f to bottom floor + 1 TO top floor - 1 #
# at the cost of reducing the flexibility of the constraints                       #
# alternatively, we could add minimum and maximum allowed floors to the PERSON     #
# STRUCT and loop through these instead of bottom floor TO top floor               #
 
FOR b FROM bottom floor TO top floor DO
    floor OF baker := b;
    FOR c FROM bottom floor TO top floor DO
        IF b /= c THEN
            floor OF cooper := c;
            FOR f FROM bottom floor TO top floor DO
                IF b /= f AND c /= f THEN
                    floor OF fletcher := f;
                    FOR m FROM bottom floor TO top floor DO
                        IF b /= m AND c /= m AND f /= m THEN
                            floor OF miller   := m;
                            FOR s FROM bottom floor TO top floor DO
                                IF b /= s AND c /= s AND f /= s AND m /= s THEN
                                    floor OF smith    := s;
                                    IF OK baker AND OK cooper AND OK fletcher AND OK miller AND OK smith
                                    THEN
                                        # found a solution #
                                        print floor( baker    );
                                        print floor( cooper   );
                                        print floor( fletcher );
                                        print floor( miller   );
                                        print floor( smith    )
                                    FI
                                FI
                            OD
                        FI
                    OD
                FI
            OD
        FI
    OD
OD