This commit is contained in:
Ingy döt Net 2013-04-10 16:57:12 -07:00
parent 518da4a923
commit 764da6cbbb
6144 changed files with 83610 additions and 11 deletions

View file

@ -0,0 +1,8 @@
The task is to '''solve Dinesman's multiple dwelling [http://www-mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 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?''

View file

@ -0,0 +1,46 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure Dinesman is
subtype Floor is Positive range 1 .. 5;
type People is (Baker, Cooper, Fletcher, Miller, Smith);
type Floors is array (People'Range) of Floor;
type PtFloors is access all Floors;
function Constrained (f : PtFloors) return Boolean is begin
if f (Baker) /= Floor'Last and
f (Cooper) /= Floor'First and
Floor'First < f (Fletcher) and f (Fletcher) < Floor'Last and
f (Miller) > f (Cooper) and
abs (f (Smith) - f (Fletcher)) /= 1 and
abs (f (Fletcher) - f (Cooper)) /= 1
then return True; end if;
return False;
end Constrained;
procedure Solve (list : PtFloors; n : Natural) is
procedure Swap (I : People; J : Natural) is
temp : constant Floor := list (People'Val (J));
begin list (People'Val (J)) := list (I); list (I) := temp;
end Swap;
begin
if n = 1 then
if Constrained (list) then
for p in People'Range loop
Put_Line (p'Img & " on floor " & list (p)'Img);
end loop;
end if;
return;
end if;
for i in People'First .. People'Val (n - 1) loop
Solve (list, n - 1);
if n mod 2 = 1 then Swap (People'First, n - 1);
else Swap (i, n - 1); end if;
end loop;
end Solve;
thefloors : aliased Floors;
begin
for person in People'Range loop
thefloors (person) := People'Pos (person) + Floor'First;
end loop;
Solve (thefloors'Access, Floors'Length);
end Dinesman;

View file

@ -0,0 +1,48 @@
REM Floors are numbered 0 (ground) to 4 (top)
REM "Baker, Cooper, Fletcher, Miller, and Smith live on different floors":
stmt1$ = "Baker<>Cooper AND Baker<>Fletcher AND Baker<>Miller AND " + \
\ "Baker<>Smith AND Cooper<>Fletcher AND Cooper<>Miller AND " + \
\ "Cooper<>Smith AND Fletcher<>Miller AND Fletcher<>Smith AND " + \
\ "Miller<>Smith"
REM "Baker does not live on the top floor":
stmt2$ = "Baker<>4"
REM "Cooper does not live on the bottom floor":
stmt3$ = "Cooper<>0"
REM "Fletcher does not live on either the top or the bottom floor":
stmt4$ = "Fletcher<>0 AND Fletcher<>4"
REM "Miller lives on a higher floor than does Cooper":
stmt5$ = "Miller>Cooper"
REM "Smith does not live on a floor adjacent to Fletcher's":
stmt6$ = "ABS(Smith-Fletcher)<>1"
REM "Fletcher does not live on a floor adjacent to Cooper's":
stmt7$ = "ABS(Fletcher-Cooper)<>1"
FOR Baker = 0 TO 4
FOR Cooper = 0 TO 4
FOR Fletcher = 0 TO 4
FOR Miller = 0 TO 4
FOR Smith = 0 TO 4
IF EVAL(stmt2$) IF EVAL(stmt3$) IF EVAL(stmt5$) THEN
IF EVAL(stmt4$) IF EVAL(stmt6$) IF EVAL(stmt7$) THEN
IF EVAL(stmt1$) THEN
PRINT "Baker lives on floor " ; Baker
PRINT "Cooper lives on floor " ; Cooper
PRINT "Fletcher lives on floor " ; Fletcher
PRINT "Miller lives on floor " ; Miller
PRINT "Smith lives on floor " ; Smith
ENDIF
ENDIF
ENDIF
NEXT Smith
NEXT Miller
NEXT Fletcher
NEXT Cooper
NEXT Baker
END

View file

@ -0,0 +1,26 @@
( Baker Cooper Fletcher Miller Smith:?people
& ( constraints
=
. !arg
: ~(? Baker)
: ~(Cooper ?)
: ~(Fletcher ?|? Fletcher)
: ? Cooper ? Miller ?
: ~(? Smith Fletcher ?|? Fletcher Smith ?)
: ~(? Cooper Fletcher ?|? Fletcher Cooper ?)
)
& ( solution
= floors persons A Z person
. !arg:(?floors.?persons)
& ( !persons:
& constraints$!floors
& out$("Inhabitants, from bottom to top:" !floors)
| !persons
: ?A
%?`person
(?Z&solution$(!floors !person.!A !Z))
)
)
& solution$(.!people)
&
);

View file

@ -0,0 +1,81 @@
#include <stdio.h>
#include <stdlib.h>
int verbose = 0;
#define COND(a, b) int a(int *s) { return (b); }
typedef int(*condition)(int *);
/* BEGIN problem specific setup */
#define N_FLOORS 5
#define TOP (N_FLOORS - 1)
int solution[N_FLOORS] = { 0 };
int occupied[N_FLOORS] = { 0 };
enum tenants {
baker = 0,
cooper,
fletcher,
miller,
smith,
phantom_of_the_opera,
};
const char *names[] = {
"baker",
"cooper",
"fletcher",
"miller",
"smith",
};
COND(c0, s[baker] != TOP);
COND(c1, s[cooper] != 0);
COND(c2, s[fletcher] != 0 && s[fletcher] != TOP);
COND(c3, s[miller] > s[cooper]);
COND(c4, abs(s[smith] - s[fletcher]) != 1);
COND(c5, abs(s[cooper] - s[fletcher]) != 1);
#define N_CONDITIONS 6
condition cond[] = { c0, c1, c2, c3, c4, c5 };
/* END of problem specific setup */
int solve(int person)
{
int i, j;
if (person == phantom_of_the_opera) {
/* check condition */
for (i = 0; i < N_CONDITIONS; i++) {
if (cond[i](solution)) continue;
if (verbose) {
for (j = 0; j < N_FLOORS; j++)
printf("%d %s\n", solution[j], names[j]);
printf("cond %d bad\n\n", i);
}
return 0;
}
printf("Found arrangement:\n");
for (i = 0; i < N_FLOORS; i++)
printf("%d %s\n", solution[i], names[i]);
return 1;
}
for (i = 0; i < N_FLOORS; i++) {
if (occupied[i]) continue;
solution[person] = i;
occupied[i] = 1;
if (solve(person + 1)) return 1;
occupied[i] = 0;
}
return 0;
}
int main()
{
verbose = 0;
if (!solve(0)) printf("Nobody lives anywhere\n");
return 0;
}

View file

@ -0,0 +1,6 @@
Found arrangement:
2 baker
1 cooper
3 fletcher
4 miller
0 smith

View file

@ -0,0 +1,17 @@
import std.stdio, std.math, std.algorithm, std.traits, permutations2;
void main() {
enum Names { Baker, Cooper, Fletcher, Miller, Smith }
immutable(bool function(in Names[]) pure nothrow)[] predicates = [
s => s[Names.Baker] != s.length - 1,
s => s[Names.Cooper] != 0,
s => s[Names.Fletcher] != 0 && s[Names.Fletcher] != s.length-1,
s => s[Names.Miller] > s[Names.Cooper],
s => abs(s[Names.Smith] - s[Names.Fletcher]) != 1,
s => abs(s[Names.Cooper] - s[Names.Fletcher]) != 1];
permutations([EnumMembers!Names])
.filter!(solution => predicates.all!(pred => pred(solution)))
.writeln;
}

View file

@ -0,0 +1,13 @@
import std.stdio, std.math, std.algorithm, permutations2;
void main() {
["Baker", "Cooper", "Fletcher", "Miller", "Smith"]
.permutations
.filter!(s =>
s.countUntil("Baker") != 4 && s.countUntil("Cooper") &&
s.countUntil("Fletcher") && s.countUntil("Fletcher") != 4 &&
s.countUntil("Miller") > s.countUntil("Cooper") &&
abs(s.countUntil("Smith") - s.countUntil("Fletcher")) != 1 &&
abs(s.countUntil("Cooper") - s.countUntil("Fletcher")) != 1)
.writeln;
}

View file

@ -0,0 +1,51 @@
0 enum baker \ enumeration of all tenants
enum cooper
enum fletcher
enum miller
constant smith
create names \ names of all the tenants
," Baker"
," Cooper"
," Fletcher"
," Miller"
," Smith" \ get name, type it
does> swap cells + @c count type ." lives in " ;
5 constant #floor \ number of floors
#floor 1- constant top \ top floor
0 constant bottom \ we're counting the floors from 0
: num@ c@ [char] 0 - ; ( a -- n)
: floor chars over + num@ ; ( a n1 -- a n2)
\ is it a valid permutation?
: perm? ( n -- a f)
#floor base ! 0 swap s>d <# #floor 0 ?do # loop #>
over >r bounds do 1 i num@ lshift + loop
31 = r> swap decimal \ create binary mask and check
;
\ test a solution
: solution? ( a -- a f)
baker floor top <> \ baker on top floor?
if cooper floor bottom <> \ cooper on the bottom floor?
if fletcher floor dup bottom <> swap top <> and
if cooper floor swap miller floor rot >
if smith floor swap fletcher floor rot - abs 1 <>
if cooper floor swap fletcher floor rot - abs 1 <>
if true exit then \ we found a solution!
then
then
then
then
then false \ nice try, no cigar..
;
( a --)
: .solution #floor 0 do i names i chars over + c@ 1+ emit cr loop drop ;
\ main routine
: dinesman ( --)
2932 194 do
i perm? if solution? if .solution leave else drop then else drop then
loop
; \ show the solution
dinesman

View file

@ -0,0 +1,37 @@
import Data.List (permutations)
import Control.Monad (guard)
dinesman :: [(Int,Int,Int,Int,Int)]
dinesman = do
-- baker, cooper, fletcher, miller, smith are integers representing
-- the floor that each person lives on, from 1 to 5
-- Baker, Cooper, Fletcher, Miller, and Smith live on different floors
-- of an apartment house that contains only five floors.
[baker, cooper, fletcher, miller, smith] <- permutations [1..5]
-- Baker does not live on the top floor.
guard $ baker /= 5
-- Cooper does not live on the bottom floor.
guard $ cooper /= 1
-- Fletcher does not live on either the top or the bottom floor.
guard $ fletcher /= 5 && fletcher /= 1
-- Miller lives on a higher floor than does Cooper.
guard $ miller > cooper
-- Smith does not live on a floor adjacent to Fletcher's.
guard $ abs (smith - fletcher) /= 1
-- Fletcher does not live on a floor adjacent to Cooper's.
guard $ abs (fletcher - cooper) /= 1
-- Where does everyone live?
return (baker, cooper, fletcher, miller, smith)
main :: IO ()
main = do
print $ head dinesman -- print first solution: (3,2,4,5,1)
print dinesman -- print all solutions (only one): [(3,2,4,5,1)]

View file

@ -0,0 +1,2 @@
import Data.List (permutations)
main = print [ (b,c,f,m,s) | [b,c,f,m,s] <- permutations [1..5], b/=5,c/=1,f/=1,f/=5,m>c,abs(s-f)>1,abs(c-f)>1]

View file

@ -0,0 +1,64 @@
import java.util.*;
class DinesmanMultipleDwelling
{
private static void generatePermutations(String[] apartmentDwellers, Set<String> set, String curPermutation)
{
for (String s : apartmentDwellers)
{
if (!curPermutation.contains(s))
{
String nextPermutation = curPermutation + s;
if (nextPermutation.length() == apartmentDwellers.length)
set.add(nextPermutation);
else
generatePermutations(apartmentDwellers, set, nextPermutation);
}
}
return;
}
private static boolean topFloor(String permutation, String person)
{ return permutation.endsWith(person); }
private static boolean bottomFloor(String permutation, String person)
{ return permutation.startsWith(person); }
public static boolean livesAbove(String permutation, String upperPerson, String lowerPerson)
{ return permutation.indexOf(upperPerson) > permutation.indexOf(lowerPerson); }
public static boolean adjacent(String permutation, String person1, String person2)
{ return (Math.abs(permutation.indexOf(person1) - permutation.indexOf(person2)) == 1); }
private static boolean isPossible(String s)
{
// Conditions here
if (topFloor(s, "B"))
return false;
if (bottomFloor(s, "C"))
return false;
if (topFloor(s, "F") || bottomFloor(s, "F"))
return false;
if (!livesAbove(s, "M", "C"))
return false;
if (adjacent(s, "S", "F"))
return false;
if (adjacent(s, "F", "C"))
return false;
return true;
}
public static void main(String[] args)
{
Set<String> set = new HashSet<String>();
generatePermutations(new String[] { "B", "C", "F", "M", "S" }, set, "");
for (Iterator<String> iterator = set.iterator(); iterator.hasNext(); )
{
String permutation = iterator.next();
if (!isPossible(permutation))
iterator.remove();
}
for (String s : set)
System.out.println("Possible arrangement: " + s);
}
}

View file

@ -0,0 +1,27 @@
# Problem statement
(be dwelling (@Tenants)
(permute (Baker Cooper Fletcher Miller Smith) @Tenants)
(not (topFloor Baker @Tenants))
(not (bottomFloor Cooper @Tenants))
(not (or ((topFloor Fletcher @Tenants)) ((bottomFloor Fletcher @Tenants))))
(higherFloor Miller Cooper @Tenants)
(not (adjacentFloor Smith Fletcher @Tenants))
(not (adjacentFloor Fletcher Cooper @Tenants)) )
# Utility rules
(be topFloor (@Tenant @Lst)
(equal (@ @ @ @ @Tenant) @Lst) )
(be bottomFloor (@Tenant @Lst)
(equal (@Tenant @ @ @ @) @Lst) )
(be higherFloor (@Tenant1 @Tenant2 @Lst)
(append @ @Rest @Lst)
(equal (@Tenant2 . @Higher) @Rest)
(member @Tenant1 @Higher) )
(be adjacentFloor (@Tenant1 @Tenant2 @Lst)
(append @ @Rest @Lst)
(or
((equal (@Tenant1 @Tenant2 . @) @Rest))
((equal (@Tenant2 @Tenant1 . @) @Rest)) ) )

View file

@ -0,0 +1,82 @@
:- use_module(library(clpfd)).
:- dynamic top/1, bottom/1.
% Baker does not live on the top floor
rule1(L) :-
member((baker, F), L),
top(Top),
F #\= Top.
% Cooper does not live on the bottom floor.
rule2(L) :-
member((cooper, F), L),
bottom(Bottom),
F #\= Bottom.
% Fletcher does not live on either the top or the bottom floor.
rule3(L) :-
member((fletcher, F), L),
top(Top),
bottom(Bottom),
F #\= Top,
F #\= Bottom.
% Miller lives on a higher floor than does Cooper.
rule4(L) :-
member((miller, Fm), L),
member((cooper, Fc), L),
Fm #> Fc.
% Smith does not live on a floor adjacent to Fletcher's.
rule5(L) :-
member((smith, Fs), L),
member((fletcher, Ff), L),
abs(Fs-Ff) #> 1.
% Fletcher does not live on a floor adjacent to Cooper's.
rule6(L) :-
member((cooper, Fc), L),
member((fletcher, Ff), L),
abs(Fc-Ff) #> 1.
init(L) :-
% we need to define top and bottom
assert(bottom(1)),
length(L, Top),
assert(top(Top)),
% we say that they are all in differents floors
bagof(F, X^member((X, F), L), LF),
LF ins 1..Top,
all_different(LF),
% Baker does not live on the top floor
rule1(L),
% Cooper does not live on the bottom floor.
rule2(L),
% Fletcher does not live on either the top or the bottom floor.
rule3(L),
% Miller lives on a higher floor than does Cooper.
rule4(L),
% Smith does not live on a floor adjacent to Fletcher's.
rule5(L),
% Fletcher does not live on a floor adjacent to Cooper's.
rule6(L).
solve(L) :-
bagof(F, X^member((X, F), L), LF),
label(LF).
dinners :-
retractall(top(_)), retractall(bottom(_)),
L = [(baker, _Fb), (cooper, _Fc), (fletcher, _Ff), (miller, _Fm), (smith, _Fs)],
init(L),
solve(L),
maplist(writeln, L).

View file

@ -0,0 +1,33 @@
select([A|As],S):- select(A,S,S1),select(As,S1).
select([],_).
dinesmans(X) :-
%% Baker, Cooper, Fletcher, Miller, and Smith live on different floors
%% of an apartment house that contains only five floors.
select([Baker,Cooper,Fletcher,Miller,Smith],[1,2,3,4,5]),
%% Baker does not live on the top floor.
Baker =\= 5,
%% Cooper does not live on the bottom floor.
Cooper =\= 1,
%% Fletcher does not live on either the top or the bottom floor.
Fletcher =\= 1, Fletcher =\= 5,
%% Miller lives on a higher floor than does Cooper.
Miller > Cooper,
%% Smith does not live on a floor adjacent to Fletcher's.
1 =\= abs(Smith - Fletcher),
%% Fletcher does not live on a floor adjacent to Cooper's.
1 =\= abs(Fletcher - Cooper),
%% Where does everyone live?
X = ['Baker'(Baker), 'Cooper'(Cooper), 'Fletcher'(Fletcher),
'Miller'(Miller), 'Smith'(Smith)].
main :- bagof( X, dinesmans(X), L )
-> maplist( writeln, L), nl, write('No more solutions.')
; write('No solutions.').

View file

@ -0,0 +1,26 @@
dinesmans(X) :-
%% 1. Baker, Cooper, Fletcher, Miller, and Smith live on different floors
%% of an apartment house that contains only five floors.
Domain = [1,2,3,4,5],
%% 2. Baker does not live on the top floor.
select(Baker,Domain,D1), Baker =\= 5,
%% 3. Cooper does not live on the bottom floor.
select(Cooper,D1,D2), Cooper =\= 1,
%% 4. Fletcher does not live on either the top or the bottom floor.
select(Fletcher,D2,D3), Fletcher =\= 1, Fletcher =\= 5,
%% 5. Miller lives on a higher floor than does Cooper.
select(Miller,D3,D4), Miller > Cooper,
%% 6. Smith does not live on a floor adjacent to Fletcher's.
select(Smith,D4,_), 1 =\= abs(Smith - Fletcher),
%% 7. Fletcher does not live on a floor adjacent to Cooper's.
1 =\= abs(Fletcher - Cooper),
%% Where does everyone live?
X = ['Baker'(Baker), 'Cooper'(Cooper), 'Fletcher'(Fletcher),
'Miller'(Miller), 'Smith'(Smith)].

View file

@ -0,0 +1,132 @@
import re
from itertools import product
problem_re = re.compile(r"""(?msx)(?:
# Multiple names of form n1, n2, n3, ... , and nK
(?P<namelist> [a-zA-Z]+ (?: , \s+ [a-zA-Z]+)* (?: ,? \s+ and) \s+ [a-zA-Z]+ )
# Flexible floor count (2 to 10 floors)
| (?: .* house \s+ that \s+ contains \s+ only \s+
(?P<floorcount> two|three|four|five|six|seven|eight|nine|ten ) \s+ floors \s* \.)
# Constraint: "does not live on the n'th floor"
|(?: (?P<not_live> \b [a-zA-Z]+ \s+ does \s+ not \s+ live \s+ on \s+ the \s+
(?: top|bottom|first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth) \s+ floor \s* \. ))
# Constraint: "does not live on either the I'th or the J'th [ or the K'th ...] floor
|(?P<not_either> \b [a-zA-Z]+ \s+ does \s+ not \s+ live \s+ on \s+ either
(?: \s+ (?: or \s+)? the \s+
(?: top|bottom|first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth))+ \s+ floor \s* \. )
# Constraint: "P1 lives on a higher/lower floor than P2 does"
|(?P<hi_lower> \b [a-zA-Z]+ \s+ lives \s+ on \s+ a \s (?: higher|lower)
\s+ floor \s+ than (?: \s+ does) \s+ [a-zA-Z]+ \s* \. )
# Constraint: "P1 does/does not live on a floor adjacent to P2's"
|(?P<adjacency> \b [a-zA-Z]+ \s+ does (?:\s+ not)? \s+ live \s+ on \s+ a \s+
floor \s+ adjacent \s+ to \s+ [a-zA-Z]+ (?: 's )? \s* \. )
# Ask for the solution
|(?P<question> Where \s+ does \s+ everyone \s+ live \s* \?)
)
""")
names, lennames = None, None
floors = None
constraint_expr = 'len(set(alloc)) == lennames' # Start with all people on different floors
def do_namelist(txt):
" E.g. 'Baker, Cooper, Fletcher, Miller, and Smith'"
global names, lennames
names = txt.replace(' and ', ' ').split(', ')
lennames = len(names)
def do_floorcount(txt):
" E.g. 'five'"
global floors
floors = '||two|three|four|five|six|seven|eight|nine|ten'.split('|').index(txt)
def do_not_live(txt):
" E.g. 'Baker does not live on the top floor.'"
global constraint_expr
t = txt.strip().split()
who, floor = t[0], t[-2]
w, f = (names.index(who),
('|first|second|third|fourth|fifth|sixth|' +
'seventh|eighth|ninth|tenth|top|bottom|').split('|').index(floor)
)
if f == 11: f = floors
if f == 12: f = 1
constraint_expr += ' and alloc[%i] != %i' % (w, f)
def do_not_either(txt):
" E.g. 'Fletcher does not live on either the top or the bottom floor.'"
global constraint_expr
t = txt.replace(' or ', ' ').replace(' the ', ' ').strip().split()
who, floor = t[0], t[6:-1]
w, fl = (names.index(who),
[('|first|second|third|fourth|fifth|sixth|' +
'seventh|eighth|ninth|tenth|top|bottom|').split('|').index(f)
for f in floor]
)
for f in fl:
if f == 11: f = floors
if f == 12: f = 1
constraint_expr += ' and alloc[%i] != %i' % (w, f)
def do_hi_lower(txt):
" E.g. 'Miller lives on a higher floor than does Cooper.'"
global constraint_expr
t = txt.replace('.', '').strip().split()
name_indices = [names.index(who) for who in (t[0], t[-1])]
if 'lower' in t:
name_indices = name_indices[::-1]
constraint_expr += ' and alloc[%i] > alloc[%i]' % tuple(name_indices)
def do_adjacency(txt):
''' E.g. "Smith does not live on a floor adjacent to Fletcher's."'''
global constraint_expr
t = txt.replace('.', '').replace("'s", '').strip().split()
name_indices = [names.index(who) for who in (t[0], t[-1])]
constraint_expr += ' and abs(alloc[%i] - alloc[%i]) > 1' % tuple(name_indices)
def do_question(txt):
global constraint_expr, names, lennames
exec_txt = '''
for alloc in product(range(1,floors+1), repeat=len(names)):
if %s:
break
else:
alloc = None
''' % constraint_expr
exec(exec_txt, globals(), locals())
a = locals()['alloc']
if a:
output= ['Floors are numbered from 1 to %i inclusive.' % floors]
for a2n in zip(a, names):
output += [' Floor %i is occupied by %s' % a2n]
output.sort(reverse=True)
print('\n'.join(output))
else:
print('No solution found.')
print()
handler = {
'namelist': do_namelist,
'floorcount': do_floorcount,
'not_live': do_not_live,
'not_either': do_not_either,
'hi_lower': do_hi_lower,
'adjacency': do_adjacency,
'question': do_question,
}
def parse_and_solve(problem):
p = re.sub(r'\s+', ' ', problem).strip()
for x in problem_re.finditer(p):
groupname, txt = [(k,v) for k,v in x.groupdict().items() if v][0]
#print ("%r, %r" % (groupname, txt))
handler[groupname](txt)

View file

@ -0,0 +1,22 @@
if __name__ == '__main__':
parse_and_solve("""
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?""")
print('# Add another person with more constraints and more floors:')
parse_and_solve("""
Baker, Cooper, Fletcher, Miller, Guinan, and Smith
live on different floors of an apartment house that contains
only seven floors. Guinan does not live on either the top or the third or the fourth floor.
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?""")

View file

@ -0,0 +1,57 @@
from amb import Amb
if __name__ == '__main__':
amb = Amb()
maxfloors = 5
floors = range(1, maxfloors+1)
# Possible floors for each person
Baker, Cooper, Fletcher, Miller, Smith = (amb(floors) for i in range(5))
for _dummy in amb( lambda Baker, Cooper, Fletcher, Miller, Smith: (
len(set([Baker, Cooper, Fletcher, Miller, Smith])) == 5 # each to a separate floor
and Baker != maxfloors
and Cooper != 1
and Fletcher not in (maxfloors, 1)
and Miller > Cooper
and (Smith - Fletcher) not in (1, -1) # Not adjacent
and (Fletcher - Cooper) not in (1, -1) # Not adjacent
) ):
print 'Floors are numbered from 1 to %i inclusive.' % maxfloors
print '\n'.join(sorted(' Floor %i is occupied by %s'
% (globals()[name], name)
for name in 'Baker, Cooper, Fletcher, Miller, Smith'.split(', ')))
break
else:
print 'No solution found.'
print
print '# Add another person with more constraints and more floors:'
# The order that Guinan is added to any list of people must stay consistant
amb = Amb()
maxfloors = 7
floors = range(1, maxfloors+1)
# Possible floors for each person
Baker, Cooper, Fletcher, Miller, Guinan, Smith = (amb(floors) for i in range(6))
for _dummy in amb( lambda Baker, Cooper, Fletcher, Miller, Guinan, Smith: (
len(set([Baker, Cooper, Fletcher, Miller, Guinan, Smith])) == 6 # each to a separate floor
and Guinan not in (maxfloors, 3, 4)
and Baker != maxfloors
and Cooper != 1
and Fletcher not in (maxfloors, 1)
and Miller > Cooper
and (Smith - Fletcher) not in (1, -1) # Not adjacent
and (Fletcher - Cooper) not in (1, -1) # Not adjacent
) ):
print 'Floors are numbered from 1 to %i inclusive.' % maxfloors
print '\n'.join(sorted(' Floor %i is occupied by %s'
% (globals()[name], name)
for name in 'Baker, Cooper, Fletcher, Miller, Guinan, Smith'.split(', ')))
break
else:
print 'No solution found.'
print

View file

@ -0,0 +1,18 @@
from itertools import permutations
class Names:
Baker, Cooper, Fletcher, Miller, Smith = range(5)
seq = [Baker, Cooper, Fletcher, Miller, Smith]
strings = "Baker Cooper Fletcher Miller Smith".split()
predicates = [
lambda s: s[Names.Baker] != len(s)-1,
lambda s: s[Names.Cooper] != 0,
lambda s: s[Names.Fletcher] != 0 and s[Names.Fletcher] != len(s)-1,
lambda s: s[Names.Miller] > s[Names.Cooper],
lambda s: abs(s[Names.Smith] - s[Names.Fletcher]) != 1,
lambda s: abs(s[Names.Cooper] - s[Names.Fletcher]) != 1];
for sol in permutations(Names.seq):
if all(p(sol) for p in predicates):
print " ".join(Names.strings[s] for s in sol)

View file

@ -0,0 +1,32 @@
/*REXX pgm: Dinesman's multiple-dwelling problem with "natural" wording.*/
names= 'Baker Cooper Fletcher Miller Smith' /*names of the tenants.*/
floors=5; top=floors; bottom=1; #=floors; sols=0
/*floor 1 is the ground floor. */
do !.1=1 for #;do !.2=1 for #;do !.3=1 for #;do !.4=1 for #;do !.5=1 for #
do p=1 for words(names); _=word(names,p); upper _; call value _,!.p
end /*p*/
/* [↓] don't live on same floor.*/
do j=1 for #-1; do k=j+1 to #; if !.j==!.k then iterate !.5; end;end
call Waldo /* ◄───────────────────where the rubber meets the road.*/
end /*!.5*/; end /*!.4*/; end /*!.3*/; end /*!.2*/; end /*!.1*/
say; say 'found' sols "solution"s(sols)'.'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────Waldo subroutine────────────────────*/
Waldo:
if Baker == top then return
if Cooper == bottom then return
if Fletcher == bottom | Fletcher == top then return
if Miller <= Cooper then return
if Smith == Fletcher-1 | Smith == Fletcher+1 then return
if Fletcher == Cooper-1 | Fletcher == Cooper+1 then return
say; sols=sols+1 /*list tenants in order in list. */
do p=1 for words(names); _=word(names,p)
say right(_,20) 'lives on the' !.p||th(!.p) "floor."
end /*p*/
return
/*──────────────────────────────────one-liner subroutines───────────────*/
s: if arg(1)=1 then return ''; return 's' /*a simple pluralizer funct.*/
th:procedure;parse arg x;x=abs(x);return word('th st nd rd',1+x//10*(x//100%10\==1)*(x//10<4))

View file

@ -0,0 +1,38 @@
def dinesman(floors, names, criteria)
# the "bindVars" method returns a context where the "name" variables are bound to values
eval "
def bindVars(#{names.map {|n| n.downcase}.join ','})
return binding
end
"
expression = criteria.map {|c| "(#{c.downcase})"}.join " and "
floors.permutation.each do |perm|
b = bindVars *perm
return b if b.eval(expression)
end
nil
end
floors = (1..5).to_a
names = %w(Baker Cooper Fletcher Miller Smith)
criteria = [
"Baker != 5",
"Cooper != 1",
"Fletcher != 1",
"Fletcher != 5",
"Miller > Cooper",
"(Smith - Fletcher).abs != 1",
"(Fletcher - Cooper).abs != 1",
]
b = dinesman(floors, names, criteria)
if b.nil?
puts "no solution"
else
puts "Found a solution:"
len = names.map {|n| n.length}.max
residents = names.inject({}) {|r, n| r[b.eval(n.downcase)] = n; r}
floors.each {|f| puts " Floor #{f}: #{residents[f]}"}
end

View file

@ -0,0 +1,31 @@
object Dinesman extends App {
val tenants = List("Baker", "Cooper", "Fletcher", "Miller", "Smith")
val floors = (1 to tenants.size).toList
// define the predicates
import scala.math.abs
val predicates =
List((perm: Map[String, Int]) => !(perm("Baker")==floors.size)
,(perm: Map[String, Int]) => !(perm("Cooper")==1)
,(perm: Map[String, Int]) => !(perm("Fletcher")==1 || perm("Fletcher")==floors.size)
,(perm: Map[String, Int]) => !(perm("Miller")<=perm("Cooper"))
,(perm: Map[String, Int]) => !(abs(perm("Smith")-perm("Fletcher"))==1)
,(perm: Map[String, Int]) => !(abs(perm("Fletcher")-perm("Cooper"))==1)
)
val p: Seq[(String, Int)] => Boolean = perm => !predicates.map(_(perm.toMap)).contains(false)
tenants.permutations.map(_ zip floors).toList
.map(perm=>Pair(perm,p(perm))).filter(_._2==true).map(p=>p._1.toList)
match {
case Nil => println("no solution")
case xss => { println("solutions: "+xss.size)
xss.foreach{l=>
println("possible solution:")
l.foreach(p=>println(" "+p._1+ " lives on floor number "+p._2))
}
}
}
}

View file

@ -0,0 +1,11 @@
...
val tenants = List("Baker", "Cooper", "Fletcher", "Miller", "Smith", "Rollo")
...
val predicates =
List((perm: Map[String, Int]) => !(perm("Baker")==floors.size)
...
,(perm: Map[String, Int]) => !(perm("Rollo")==floors.size || perm("Rollo")==3 || perm("Rollo")==4)
,(perm: Map[String, Int]) => !(perm("Rollo")>perm("Smith"))
,(perm: Map[String, Int]) => !(perm("Rollo")<perm("Fletcher"))
)
...

View file

@ -0,0 +1,31 @@
package require Tcl 8.5
package require struct::list
proc dinesmanSolve {floors people constraints} {
# Search for a possible assignment that satisfies the constraints
struct::list foreachperm p $floors {
lassign $p {*}$people
set found 1
foreach c $constraints {
if {![expr $c]} {
set found 0
break
}
}
if {$found} break
}
# Found something, or exhausted possibilities
if {!$found} {
error "no solution possible"
}
# Generate in "nice" order
foreach f $floors {
foreach person $people {
if {[set $person] == $f} {
lappend result $f $person
break
}
}
}
return $result
}

View file

@ -0,0 +1,10 @@
set soln [dinesmanSolve {1 2 3 4 5} {Baker Cooper Fletcher Miller Smith} {
{$Baker != 5}
{$Cooper != 1}
{$Fletcher != 1 && $Fletcher != 5}
{$Miller > $Cooper}
{abs($Smith-$Fletcher) != 1}
{abs($Fletcher-$Cooper) != 1}
}]
puts "Solution found:"
foreach {where who} $soln {puts " Floor ${where}: $who"}