CDE
This commit is contained in:
parent
518da4a923
commit
764da6cbbb
6144 changed files with 83610 additions and 11 deletions
8
Task/Dinesmans-multiple-dwelling-problem/0DESCRIPTION
Normal file
8
Task/Dinesmans-multiple-dwelling-problem/0DESCRIPTION
Normal 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?''
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
&
|
||||
);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Found arrangement:
|
||||
2 baker
|
||||
1 cooper
|
||||
3 fletcher
|
||||
4 miller
|
||||
0 smith
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)]
|
||||
|
|
@ -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]
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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)) ) )
|
||||
|
|
@ -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).
|
||||
|
|
@ -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.').
|
||||
|
|
@ -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)].
|
||||
|
|
@ -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)
|
||||
|
|
@ -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?""")
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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"))
|
||||
)
|
||||
...
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"}
|
||||
Loading…
Add table
Add a link
Reference in a new issue