Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
3
Task/Dinesmans-multiple-dwelling-problem/00-META.yaml
Normal file
3
Task/Dinesmans-multiple-dwelling-problem/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Dinesman's_multiple-dwelling_problem
|
||||
note: Dinesman's multiple-dwelling problem
|
||||
23
Task/Dinesmans-multiple-dwelling-problem/00-TASK.txt
Normal file
23
Task/Dinesmans-multiple-dwelling-problem/00-TASK.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
;Task
|
||||
Solve [https://web.archive.org/web/20170325033240/http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 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.<br>
|
||||
::* 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?''<br>
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
-V
|
||||
BAKER = 0
|
||||
COOPER = 1
|
||||
FLETCHER = 2
|
||||
MILLER = 3
|
||||
SMITH = 4
|
||||
names = [‘Baker’, ‘Cooper’, ‘Fletcher’, ‘Miller’, ‘Smith’]
|
||||
|
||||
V floors = Array(1..5)
|
||||
|
||||
L
|
||||
I floors[BAKER] != 5 &
|
||||
floors[COOPER] != 1 &
|
||||
floors[FLETCHER] !C (1, 5) &
|
||||
floors[MILLER] > floors[COOPER] &
|
||||
abs(floors[SMITH] - floors[FLETCHER]) != 1 &
|
||||
abs(floors[FLETCHER] - floors[COOPER]) != 1
|
||||
L(floor) floors
|
||||
print(names[L.index]‘ lives on floor ’floor)
|
||||
L.break
|
||||
|
||||
I !floors.next_permutation()
|
||||
print(‘No solution found.’)
|
||||
L.break
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# syntax: GAWK -f DINESMANS_MULTIPLE-DWELLING_PROBLEM.AWK
|
||||
BEGIN {
|
||||
for (Baker=1; Baker<=5; Baker++) {
|
||||
for (Cooper=1; Cooper<=5; Cooper++) {
|
||||
for (Fletcher=1; Fletcher<=5; Fletcher++) {
|
||||
for (Miller=1; Miller<=5; Miller++) {
|
||||
for (Smith=1; Smith<=5; Smith++) {
|
||||
if (rules() ~ /^1+$/) {
|
||||
printf("%d Baker\n",Baker)
|
||||
printf("%d Cooper\n",Cooper)
|
||||
printf("%d Fletcher\n",Fletcher)
|
||||
printf("%d Miller\n",Miller)
|
||||
printf("%d Smith\n",Smith)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
function rules( stmt1,stmt2,stmt3,stmt4,stmt5,stmt6,stmt7) {
|
||||
# The following problem statements may be changed:
|
||||
#
|
||||
# Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house
|
||||
# that contains only five floors numbered 1 (ground) to 5 (top)
|
||||
stmt1 = Baker!=Cooper && Baker!=Fletcher && Baker!=Miller && Baker!=Smith &&
|
||||
Cooper!=Fletcher && Cooper!=Miller && Cooper!=Smith &&
|
||||
Fletcher!=Miller && Fletcher!=Smith &&
|
||||
Miller!=Smith
|
||||
stmt2 = Baker != 5 # Baker does not live on the top floor
|
||||
stmt3 = Cooper != 1 # Cooper does not live on the bottom floor
|
||||
stmt4 = Fletcher != 5 && Fletcher != 1 # Fletcher does not live on either the top or the bottom floor
|
||||
stmt5 = Miller > Cooper # Miller lives on a higher floor than does Cooper
|
||||
stmt6 = abs(Smith-Fletcher) != 1 # Smith does not live on a floor adjacent to Fletcher's
|
||||
stmt7 = abs(Fletcher-Cooper) != 1 # Fletcher does not live on a floor adjacent to Cooper's
|
||||
return(stmt1 stmt2 stmt3 stmt4 stmt5 stmt6 stmt7)
|
||||
}
|
||||
function abs(x) { if (x >= 0) { return x } else { return -x } }
|
||||
|
|
@ -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,33 @@
|
|||
on Dinesman()
|
||||
set output to {}
|
||||
(* American floor numbering used in these comments to match AppleScript's 1-based indices. *)
|
||||
-- Baker's not on the fifth floor.
|
||||
repeat with Baker from 1 to 4
|
||||
-- Cooper's not on the first floor. Nor on the fifth as Miller's somewhere above him.
|
||||
-- Fletcher's also not on these floors, so both are in the middle three. They're also
|
||||
-- at least two floors apart, so one must be on the second and the other on the fourth.
|
||||
repeat with Cooper from 2 to 4 by 2
|
||||
if (Cooper ≠ Baker) then
|
||||
set Fletcher to 6 - Cooper
|
||||
-- Miller's somewhere above Cooper.
|
||||
if (Fletcher ≠ Baker) then repeat with Miller from (Cooper + 1) to 5
|
||||
-- Try to fit Smith in somewhere not adjacent to Fletcher.
|
||||
if ((Miller ≠ Fletcher) and (Miller ≠ Baker)) then repeat with Smith from 1 to 5
|
||||
if ((Smith is not in {Baker, Cooper, Fletcher, Miller}) and ¬
|
||||
((Fletcher - Smith > 1) or (Smith - Fletcher > 1))) then
|
||||
tell {missing value, missing value, missing value, missing value, missing value}
|
||||
set {item Baker, item Cooper, item Fletcher, item Miller, item Smith} to ¬
|
||||
{"Baker", "Cooper", "Fletcher", "Miller", "Smith"}
|
||||
set end of output to {bottomToTop:it}
|
||||
end tell
|
||||
end if
|
||||
end repeat
|
||||
end repeat
|
||||
end if
|
||||
end repeat
|
||||
end repeat
|
||||
|
||||
return {numberOfSolutions:(count output), solutions:output}
|
||||
end Dinesman
|
||||
|
||||
return Dinesman()
|
||||
|
|
@ -0,0 +1 @@
|
|||
{numberOfSolutions:1, solutions:{{bottomToTop:{"Smith", "Cooper", "Baker", "Fletcher", "Miller"}}}}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
print "Los apartamentos están numerados del 0 (bajo) al 4 (ático)."
|
||||
print "Baker, Cooper, Fletcher, Miller y Smith viven en apartamentos diferentes."
|
||||
print "- Baker no vive en el último apartamento (ático)."
|
||||
print "- Cooper no vive en el piso inferior (bajo)."
|
||||
print "- Fletcher no vive ni en el ático ni en el bajo."
|
||||
print "- Miller vive en un apartamento más alto que Cooper."
|
||||
print "- Smith no vive en un apartamento adyacente al de Fletcher."
|
||||
print "- Fletcher no vive en un apartamento adyacente al de Cooper." & chr(10)
|
||||
|
||||
for Baker = 0 to 3
|
||||
for Cooper = 1 to 4
|
||||
for Fletcher = 1 to 3
|
||||
for Miller = 0 to 4
|
||||
for Smith = 0 to 4
|
||||
if 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 and Miller>Cooper and abs(Smith-Fletcher)<>1 and abs(Fletcher-Cooper)<>1 then
|
||||
print "Baker vive en el piso "; Baker
|
||||
print "Cooper vive en el piso "; Cooper
|
||||
print "Fletcher vive en el piso "; Fletcher
|
||||
print "Miller vive en el piso "; Miller
|
||||
print "Smith vive en el piso "; Smith
|
||||
end if
|
||||
next Smith
|
||||
next Miller
|
||||
next Fletcher
|
||||
next Cooper
|
||||
next Baker
|
||||
end
|
||||
|
|
@ -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,27 @@
|
|||
( 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)
|
||||
& ~ { The ~ always fails on evaluation. Here, failure forces Bracmat to backtrack and find all solutions, not just the first one. }
|
||||
| !persons
|
||||
: ?A
|
||||
%?`person
|
||||
(?Z&solution$(!floors !person.!A !Z))
|
||||
)
|
||||
)
|
||||
& solution$(.!people)
|
||||
| { After outputting all solutions, the lhs of the | operator fails. The rhs of the | operator, here an empty string, is the final result. }
|
||||
);
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
int main() {
|
||||
constexpr auto floors = 5u;
|
||||
constexpr auto top = floors - 1u, bottom = 0u;
|
||||
|
||||
using namespace std;
|
||||
array<string, floors> tenants = { "Baker", "Cooper", "Fletcher", "Miller", "Smith" };
|
||||
const auto floor_of = [&tenants](string t) {
|
||||
for (int i = bottom; i <= top; i++)
|
||||
if (tenants[i] == t) return i;
|
||||
throw "invalid tenant";
|
||||
};
|
||||
|
||||
const list<function<bool()>> constraints = {
|
||||
[&tenants]() { return tenants[top] != "Baker"; },
|
||||
[&tenants]() { return tenants[bottom] != "Cooper"; },
|
||||
[&tenants]() { return tenants[top] != "Fletcher"; },
|
||||
[&tenants]() { return tenants[bottom] != "Fletcher"; },
|
||||
[&floor_of]() { return floor_of("Miller") > floor_of("Cooper"); },
|
||||
[&floor_of]() { return abs(floor_of("Fletcher") - floor_of("Smith")) != 1; },
|
||||
[&floor_of]() { return abs(floor_of("Fletcher") - floor_of("Cooper")) != 1; }
|
||||
};
|
||||
|
||||
sort(tenants.begin(), tenants.end());
|
||||
do {
|
||||
if (all_of(constraints.begin(), constraints.end(), [](auto f) { return f(); } )) {
|
||||
for (const auto &t : tenants) cout << t << ' ';
|
||||
cout << endl;
|
||||
}
|
||||
} while (next_permutation(tenants.begin(), tenants.end()));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
const int count = 5;
|
||||
const int Baker = 0, Cooper = 1, Fletcher = 2, Miller = 3, Smith = 4;
|
||||
string[] names = { nameof(Baker), nameof(Cooper), nameof(Fletcher), nameof(Miller), nameof(Smith) };
|
||||
|
||||
Func<int[], bool>[] constraints = {
|
||||
floorOf => floorOf[Baker] != count-1,
|
||||
floorOf => floorOf[Cooper] != 0,
|
||||
floorOf => floorOf[Fletcher] != count-1 && floorOf[Fletcher] != 0,
|
||||
floorOf => floorOf[Miller] > floorOf[Cooper],
|
||||
floorOf => Math.Abs(floorOf[Smith] - floorOf[Fletcher]) > 1,
|
||||
floorOf => Math.Abs(floorOf[Fletcher] - floorOf[Cooper]) > 1,
|
||||
};
|
||||
|
||||
var solver = new DinesmanSolver();
|
||||
foreach (var tenants in solver.Solve(count, constraints)) {
|
||||
Console.WriteLine(string.Join(" ", tenants.Select(t => names[t])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DinesmanSolver
|
||||
{
|
||||
public IEnumerable<int[]> Solve(int count, params Func<int[], bool>[] constraints) {
|
||||
foreach (int[] floorOf in Permutations(count)) {
|
||||
if (constraints.All(c => c(floorOf))) {
|
||||
yield return Enumerable.Range(0, count).OrderBy(i => floorOf[i]).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<int[]> Permutations(int length) {
|
||||
if (length == 0) {
|
||||
yield return new int[0];
|
||||
yield break;
|
||||
}
|
||||
bool forwards = false;
|
||||
foreach (var permutation in Permutations(length - 1)) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
yield return permutation.InsertAt(forwards ? i : length - i - 1, length - 1).ToArray();
|
||||
}
|
||||
forwards = !forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Extensions
|
||||
{
|
||||
public static IEnumerable<T> InsertAt<T>(this IEnumerable<T> source, int position, T newElement) {
|
||||
if (source == null) throw new ArgumentNullException(nameof(source));
|
||||
if (position < 0) throw new ArgumentOutOfRangeException(nameof(position));
|
||||
return InsertAtIterator(source, position, newElement);
|
||||
}
|
||||
|
||||
private static IEnumerable<T> InsertAtIterator<T>(IEnumerable<T> source, int position, T newElement) {
|
||||
int index = 0;
|
||||
foreach (T element in source) {
|
||||
if (index == position) yield return newElement;
|
||||
yield return element;
|
||||
index++;
|
||||
}
|
||||
if (index < position) throw new ArgumentOutOfRangeException(nameof(position));
|
||||
if (index == position) yield return newElement;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static System.Linq.Enumerable;
|
||||
|
||||
static class Program
|
||||
{
|
||||
enum Tenants { Baker = 0, Cooper = 1, Fletcher = 2, Miller = 3, Smith = 4 };
|
||||
|
||||
static void Main()
|
||||
{
|
||||
var count = Enum.GetNames(typeof(Tenants)).Length;
|
||||
var top = count - 1;
|
||||
|
||||
var solve =
|
||||
from f in Range(0, count).Permutations()
|
||||
let floors = f.ToArray()
|
||||
where floors[(int)Tenants.Baker] != top //r1
|
||||
where floors[(int)Tenants.Cooper] != 0 //r2
|
||||
where floors[(int)Tenants.Fletcher] != top && floors[(int)Tenants.Fletcher] != 0 //r3
|
||||
where floors[(int)Tenants.Miller] > floors[(int)Tenants.Cooper] //r4
|
||||
where Math.Abs(floors[(int)Tenants.Smith] - floors[(int)Tenants.Fletcher]) !=1 //r5
|
||||
where Math.Abs(floors[(int)Tenants.Fletcher] - floors[(int)Tenants.Cooper]) !=1 //r6
|
||||
select floors;
|
||||
var solved = solve.First();
|
||||
var output = Range(0,count).OrderBy(i=>solved[i]).Select(f => ((Tenants)f).ToString());
|
||||
Console.WriteLine(String.Join(" ", output));
|
||||
Console.Read();
|
||||
}
|
||||
|
||||
public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> values)
|
||||
{
|
||||
if (values.Count() == 1)
|
||||
return values.ToSingleton();
|
||||
|
||||
return values.SelectMany(v => Permutations(values.Except(v.ToSingleton())), (v, p) => p.Prepend(v));
|
||||
}
|
||||
|
||||
public static IEnumerable<T> ToSingleton<T>(this T item) { yield return item; }
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
#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,24 @@
|
|||
shared void run() {
|
||||
|
||||
function notAdjacent(Integer a, Integer b) => (a - b).magnitude >= 2;
|
||||
function allDifferent(Integer* ints) => ints.distinct.size == ints.size;
|
||||
|
||||
value solutions = [
|
||||
for (baker in 1..4)
|
||||
for (cooper in 2..5)
|
||||
for (fletcher in 2..4)
|
||||
for (miller in 2..5)
|
||||
for (smith in 1..5)
|
||||
if (miller > cooper &&
|
||||
notAdjacent(smith, fletcher) &&
|
||||
notAdjacent(fletcher, cooper) &&
|
||||
allDifferent(baker, cooper, fletcher, miller, smith))
|
||||
"baker lives on ``baker``
|
||||
cooper lives on ``cooper``
|
||||
fletcher lives on ``fletcher``
|
||||
miller lives on ``miller``
|
||||
smith lives on ``smith``"
|
||||
];
|
||||
|
||||
print(solutions.first else "No solution!");
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
(ns rosettacode.dinesman
|
||||
(:use [clojure.core.logic]
|
||||
[clojure.tools.macro :as macro]))
|
||||
|
||||
; whether x is immediately above (left of) y in list s; uses pattern matching on s
|
||||
(defne aboveo [x y s]
|
||||
([_ _ (x y . ?rest)])
|
||||
([_ _ [_ . ?rest]] (aboveo x y ?rest)))
|
||||
|
||||
; whether x is on a higher floor than y
|
||||
(defne highero [x y s]
|
||||
([_ _ (x . ?rest)] (membero y ?rest))
|
||||
([_ _ (_ . ?rest)] (highero x y ?rest)))
|
||||
|
||||
; whether x and y are on nonadjacent floors
|
||||
(defn nonadjacento [x y s]
|
||||
(conda
|
||||
((aboveo x y s) fail)
|
||||
((aboveo y x s) fail)
|
||||
(succeed)))
|
||||
|
||||
(defn dinesmano [rs]
|
||||
(macro/symbol-macrolet [_ (lvar)]
|
||||
(all
|
||||
(permuteo ['Baker 'Cooper 'Fletcher 'Miller 'Smith] rs)
|
||||
(aboveo _ 'Baker rs) ;someone lives above Baker
|
||||
(aboveo 'Cooper _ rs) ;Cooper lives above someone
|
||||
(aboveo 'Fletcher _ rs)
|
||||
(aboveo _ 'Fletcher rs)
|
||||
(highero 'Miller 'Cooper rs)
|
||||
(nonadjacento 'Smith 'Fletcher rs)
|
||||
(nonadjacento 'Fletcher 'Cooper rs))))
|
||||
|
||||
(let [solns (run* [q] (dinesmano q))]
|
||||
(println "solution count:" (count solns))
|
||||
(println "solution(s) highest to lowest floor:")
|
||||
(doseq [soln solns] (println " " soln)))
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
100 T=5:REM TOP FLOOR
|
||||
110 FOR B=1 TO T
|
||||
120 : REM BAKER DOES NOT LIVE ON THE TOP FLOOR
|
||||
130 : IF B=T THEN 420
|
||||
140 : FOR C=1 TO T
|
||||
150 : IF C=B THEN 410: REM ONE PERSON PER FLOOR
|
||||
160 : REM COOPER DOES NOT LIVE ON THE BOTTOM FLOOR
|
||||
170 : IF C=1 THEN 410
|
||||
180 : FOR F=1 TO T
|
||||
190 : IF F=B OR F=C THEN 400: REM ONE PERSON PER FLOOR
|
||||
200 : REM FLETCHER DOES NOT LIVE ON TOP OR BOTTOM
|
||||
210 : IF F=1 OR F=T THEN 400
|
||||
220 : REM FLETCHER DOES NOT LIVE ADJACENT TO COOPER
|
||||
230 : IF ABS(F-C)=1 THEN 400
|
||||
240 : FOR M=1 TO T
|
||||
250 : IF M=B OR M=C OR M=F THEN 390: REM ONE PERSON PER FLOOR
|
||||
260 : REM MILLER LIVES ABOVE COOPER
|
||||
270 : IF M < C THEN 390
|
||||
280 : FOR S=1 TO T
|
||||
290 : IF S=B OR S=C OR S=F OR S=M THEN 380: REM ONE PERSON PER FLOOR
|
||||
300 : REM SMITH DOES NOT LIVE ADJACENT TO FLETCHER
|
||||
310 : IF ABS(F-S)=1 THEN 380
|
||||
320 : PRINT "BAKER IS ON"B
|
||||
330 : PRINT "COOPER IS ON"C
|
||||
340 : PRINT "FLETCHER IS ON"F
|
||||
350 : PRINT "MILLER IS ON"M
|
||||
360 : PRINT "SMITH IS ON"S
|
||||
370 : END
|
||||
380 : NEXT S
|
||||
390 : NEXT M
|
||||
400 : NEXT F
|
||||
410 : NEXT C
|
||||
420 NEXT B
|
||||
430 PRINT "NO SOLUTION"
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
(defpackage :dinesman
|
||||
(:use :cl
|
||||
:screamer)
|
||||
(:export :dinesman :dinesman-list))
|
||||
(in-package :dinesman)
|
||||
|
||||
(defun distinctp (list)
|
||||
(equal list (remove-duplicates list)))
|
||||
|
||||
(defun dinesman ()
|
||||
(all-values
|
||||
(let ((baker (an-integer-between 1 5))
|
||||
(cooper (an-integer-between 1 5))
|
||||
(fletcher (an-integer-between 1 5))
|
||||
(miller (an-integer-between 1 5))
|
||||
(smith (an-integer-between 1 5)))
|
||||
(unless (distinctp (list baker cooper fletcher miller smith)) (fail))
|
||||
(when (= 5 baker) (fail))
|
||||
(when (= 1 cooper) (fail))
|
||||
(when (or (= 1 fletcher) (= 5 fletcher)) (fail))
|
||||
(unless (> miller cooper) (fail))
|
||||
(when (= 1 (abs (- fletcher smith))) (fail))
|
||||
(when (= 1 (abs (- fletcher cooper))) (fail))
|
||||
(format t "~{~A: ~A~%~}" (list 'baker baker 'cooper cooper 'fletcher fletcher 'miller miller 'smith smith)))))
|
||||
|
||||
(defun dinesman-list ()
|
||||
(all-values
|
||||
(let* ((men '(baker cooper fletcher miller smith))
|
||||
(building (list (a-member-of men) (a-member-of men) (a-member-of men) (a-member-of men) (a-member-of men))))
|
||||
(unless (distinctp building) (fail))
|
||||
(when (eql (car (last building)) 'baker) (fail))
|
||||
(when (eql (first building) 'cooper) (fail))
|
||||
(when (or (eql (car (last building)) 'fletcher)
|
||||
(eql (first building) 'fletcher))
|
||||
(fail))
|
||||
(unless (> (position 'miller building)
|
||||
(position 'cooper building))
|
||||
(fail))
|
||||
(when (= 1 (abs (- (position 'fletcher building) (position 'smith building))))
|
||||
(fail))
|
||||
(when (= 1 (abs (- (position 'fletcher building) (position 'cooper building))))
|
||||
(fail))
|
||||
(format t "(~{~A~^ ~})~%" building))))
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
module Enumerable(T)
|
||||
def index!(element)
|
||||
index(element).not_nil!
|
||||
end
|
||||
end
|
||||
|
||||
residents = [:Baker, :Cooper, :Fletcher, :Miller, :Smith]
|
||||
|
||||
predicates = [
|
||||
->(p : Array(Symbol)){ :Baker != p.last },
|
||||
->(p : Array(Symbol)){ :Cooper != p.first },
|
||||
->(p : Array(Symbol)){ :Fletcher != p.first && :Fletcher != p.last },
|
||||
->(p : Array(Symbol)){ p.index!(:Miller) > p.index!(:Cooper) },
|
||||
->(p : Array(Symbol)){ (p.index!(:Smith) - p.index!(:Fletcher)).abs != 1 },
|
||||
->(p : Array(Symbol)){ (p.index!(:Cooper) - p.index!(:Fletcher)).abs != 1}
|
||||
]
|
||||
|
||||
puts residents.permutations.find { |p| predicates.all? &.call p }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import std.stdio, std.math, std.algorithm, std.traits, std.array, permutations2:permutations;
|
||||
|
||||
void main() {
|
||||
|
||||
enum Names { Baker, Cooper, Fletcher, Miller, Smith }
|
||||
|
||||
immutable(bool function(in Names[]) pure nothrow)[] predicates = [
|
||||
s => s.countUntil(Names.Baker) != 4 && s.countUntil(Names.Cooper) != 0,
|
||||
s => s.countUntil(Names.Fletcher) != 4 && s.countUntil(Names.Fletcher) != 0,
|
||||
s => s.countUntil(Names.Miller) > s.countUntil(Names.Cooper),
|
||||
s => abs(s.countUntil(Names.Smith) - s.countUntil(Names.Fletcher)) != 1,
|
||||
s => abs(s.countUntil(Names.Cooper) - s.countUntil(Names.Fletcher)) != 1
|
||||
];
|
||||
|
||||
permutations([EnumMembers!Names]).filter!(solution => predicates.all!(pred => pred(solution)))
|
||||
.writeln;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
void main() {
|
||||
import std.stdio, std.math, std.algorithm, permutations2:permutations;
|
||||
|
||||
["Baker", "Cooper", "Fletcher", "Miller", "Smith"]
|
||||
.permutations
|
||||
.filter!(s =>
|
||||
s.countUntil("Baker") != 4 && s.countUntil("Cooper") != 0 &&
|
||||
s.countUntil("Fletcher") != 0 && 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,48 @@
|
|||
PROGRAM DINESMAN
|
||||
|
||||
BEGIN
|
||||
! Floors are numbered 0 (ground) to 4 (top)
|
||||
|
||||
! "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"
|
||||
|
||||
! "Baker does not live on the top floor":
|
||||
stmt2$="Baker<>4"
|
||||
|
||||
! "Cooper does not live on the bottom floor":
|
||||
stmt3$="Cooper<>0"
|
||||
|
||||
! "Fletcher does not live on either the top or the bottom floor":
|
||||
stmt4$="Fletcher<>0 AND Fletcher<>4"
|
||||
|
||||
! "Miller lives on a higher floor than does Cooper":
|
||||
stmt5$="Miller>Cooper"
|
||||
|
||||
! "Smith does not live on a floor adjacent to Fletcher's":
|
||||
stmt6$="ABS(Smith-Fletcher)<>1"
|
||||
|
||||
! "Fletcher does not live on a floor adjacent to Cooper's":
|
||||
stmt7$="ABS(Fletcher-Cooper)<>1"
|
||||
|
||||
FOR Baker=0 TO 4 DO
|
||||
FOR Cooper=0 TO 4 DO
|
||||
FOR Fletcher=0 TO 4 DO
|
||||
FOR Miller=0 TO 4 DO
|
||||
FOR Smith=0 TO 4 DO
|
||||
IF Baker<>4 AND Cooper<>0 AND Miller>Cooper THEN
|
||||
IF Fletcher<>0 AND Fletcher<>4 AND ABS(Smith-Fletcher)<>1 AND ABS(Fletcher-Cooper)<>1 THEN
|
||||
IF 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 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)
|
||||
END IF
|
||||
END IF
|
||||
END IF
|
||||
END FOR ! Smith
|
||||
END FOR ! Miller
|
||||
END FOR ! Fletcher
|
||||
END FOR ! Cooper
|
||||
END FOR ! Baker
|
||||
END PROGRAM
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
(require 'hash)
|
||||
(require' amb)
|
||||
|
||||
;;
|
||||
;; Solver
|
||||
;;
|
||||
|
||||
(define (dwelling-puzzle context names floors H)
|
||||
;; each amb calls gives a floor to a name
|
||||
(for ((name names))
|
||||
(hash-set H name (amb context floors)))
|
||||
;; They live on different floors.
|
||||
(amb-require (distinct? (amb-choices context)))
|
||||
(constraints floors H) ;; may fail and backtrack
|
||||
;; result returned to amb-run
|
||||
(for/list ((name names))
|
||||
(cons name (hash-ref H name)))
|
||||
;; (amb-fail) is possible here to see all solutions
|
||||
)
|
||||
|
||||
(define (task names)
|
||||
(amb-run dwelling-puzzle
|
||||
(amb-make-context)
|
||||
names
|
||||
(iota (length names)) ;; list of floors : 0,1, ....
|
||||
(make-hash)) ;; hash table : "name" -> floor
|
||||
)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
(define names '("baker" "cooper" "fletcher" "miller" "smith" ))
|
||||
|
||||
(define-syntax-rule (floor name) (hash-ref H name))
|
||||
(define-syntax-rule (touch a b) (= (abs (- (hash-ref H a) (hash-ref H b))) 1))
|
||||
|
||||
(define (constraints floors H)
|
||||
(define top (1- (length floors)))
|
||||
;; Baker does not live on the top floor.
|
||||
(amb-require (!= (floor "baker") top))
|
||||
;; Cooper does not live on the bottom floor.
|
||||
(amb-require (!= (floor "cooper") 0))
|
||||
;; Fletcher does not live on either the top or the bottom floor.
|
||||
(amb-require (!= (floor "fletcher") top))
|
||||
(amb-require (!= (floor "fletcher") 0))
|
||||
;; Miller lives on a higher floor than does Cooper.
|
||||
(amb-require (> (floor "miller") (floor "cooper")))
|
||||
;; Smith does not live on a floor adjacent to Fletcher's.
|
||||
(amb-require (not (touch "smith" "fletcher")))
|
||||
;; Fletcher does not live on a floor adjacent to Cooper's.
|
||||
(amb-require (not (touch "fletcher" "cooper")))
|
||||
)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
(task names)
|
||||
→ ((baker . 2) (cooper . 1) (fletcher . 3) (miller . 4) (smith . 0))
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
;; add a name/floor
|
||||
(define names '("baker" "cooper" "fletcher" "miller" "smith" "antoinette"))
|
||||
|
||||
(define (constraints floors H)
|
||||
;; ... same as above, add the following
|
||||
|
||||
;; Antoinette does not like 💔 Smith
|
||||
(amb-require (not (touch "smith" "antoinette")))
|
||||
;; Antoinette is very close ❤️ to Cooper
|
||||
(amb-require (touch "cooper" "antoinette"))
|
||||
;; Antoinette wants a prime numbered floor
|
||||
(amb-require (prime? (floor "antoinette")))
|
||||
)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
(task names)
|
||||
→ ((baker . 0) (cooper . 1) (fletcher . 3) (miller . 4) (smith . 5) (antoinette . 2))
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
defmodule Dinesman do
|
||||
def problem do
|
||||
names = ~w( Baker Cooper Fletcher Miller Smith )a
|
||||
predicates = [fn(c)-> :Baker != List.last(c) end,
|
||||
fn(c)-> :Cooper != List.first(c) end,
|
||||
fn(c)-> :Fletcher != List.first(c) && :Fletcher != List.last(c) end,
|
||||
fn(c)-> floor(c, :Miller) > floor(c, :Cooper) end,
|
||||
fn(c)-> abs(floor(c, :Smith) - floor(c, :Fletcher)) != 1 end,
|
||||
fn(c)-> abs(floor(c, :Cooper) - floor(c, :Fletcher)) != 1 end]
|
||||
|
||||
permutation(names)
|
||||
|> Enum.filter(fn candidate ->
|
||||
Enum.all?(predicates, fn predicate -> predicate.(candidate) end)
|
||||
end)
|
||||
|> Enum.each(fn name_list ->
|
||||
Enum.with_index(name_list)
|
||||
|> Enum.each(fn {name,i} -> IO.puts "#{name} lives on #{i+1}" end)
|
||||
end)
|
||||
end
|
||||
|
||||
defp floor(c, name), do: Enum.find_index(c, fn x -> x == name end)
|
||||
|
||||
defp permutation([]), do: [[]]
|
||||
defp permutation(list), do: (for x <- list, y <- permutation(list -- [x]), do: [x|y])
|
||||
end
|
||||
|
||||
Dinesman.problem
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
-module( dinesman_multiple_dwelling ).
|
||||
|
||||
-export( [solve/2, task/0] ).
|
||||
|
||||
solve( All_persons, Rules ) ->
|
||||
[house(Bottom_floor, B, C, D, Top_floor) || Bottom_floor <- All_persons, B <- All_persons, C <- All_persons, D <- All_persons, Top_floor <- All_persons,
|
||||
lists:all( fun (Fun) -> Fun( house(Bottom_floor, B, C, D, Top_floor) ) end, rules( Rules ))].
|
||||
|
||||
task() ->
|
||||
All_persons = [baker, cooper, fletcher, miller, smith],
|
||||
Rules = [all_on_different_floors, {not_lives_on_floor, 4, baker}, {not_lives_on_floor, 0, cooper}, {not_lives_on_floor, 4, fletcher}, {not_lives_on_floor, 0, fletcher},
|
||||
{on_higher_floor, miller, cooper}, {not_adjacent, smith, fletcher}, {not_adjacent, fletcher, cooper}],
|
||||
[House] = solve( All_persons, Rules ),
|
||||
[io:fwrite("~p lives on floor ~p~n", [lists:nth(X, House), X - 1]) || X <- lists:seq(1,5)].
|
||||
|
||||
|
||||
|
||||
house( A, B, C, D, E ) -> [A, B, C, D, E].
|
||||
|
||||
is_all_on_different_floors( [A, B, C, D, E] ) ->
|
||||
A =/= B andalso A =/= C andalso A =/= D andalso A =/= E
|
||||
andalso B =/= C andalso B =/= D andalso B =/= E
|
||||
andalso C =/= D andalso C =/= E
|
||||
andalso D =/= E.
|
||||
|
||||
is_not_adjacent( Person1, Person2, House ) ->
|
||||
is_not_below( Person1, Person2, House ) andalso is_not_below( Person2, Person1, House ).
|
||||
|
||||
is_not_below( _Person1, _Person2, [_Person] ) -> true;
|
||||
is_not_below( Person1, Person2, [Person1, Person2 | _T] ) -> false;
|
||||
is_not_below( Person1, Person2, [_Person | T] ) -> is_not_below( Person1, Person2, T ).
|
||||
|
||||
is_on_higher_floor( Person1, _Person2, [Person1 | _T] ) -> false;
|
||||
is_on_higher_floor( _Person1, Person2, [Person2 | _T] ) -> true;
|
||||
is_on_higher_floor( Person1, Person2, [_Person | T] ) -> is_on_higher_floor( Person1, Person2, T ).
|
||||
|
||||
rules( Rules ) -> lists:map( fun rules_fun/1, Rules ).
|
||||
|
||||
rules_fun( all_on_different_floors ) -> fun is_all_on_different_floors/1;
|
||||
rules_fun( {not_lives_on_floor, N, Person} ) -> fun (House) -> Person =/= lists:nth(N + 1, House) end;
|
||||
rules_fun( {on_higher_floor, Person1, Person2} ) -> fun (House) -> is_on_higher_floor( Person1, Person2, House ) end;
|
||||
rules_fun( {not_below, Person1, Person2} ) -> fun (House) -> is_not_below( Person1, Person2, House ) end;
|
||||
rules_fun( {not_adjacent, Person1, Person2} ) -> fun (House) -> is_not_adjacent( Person1, Person2, House ) end.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// Dinesman's multiple-dwelling. Nigel Galloway: September 23rd., 2020
|
||||
type names = |Baker=0 |Cooper=1 |Miller=2 |Smith=3 |Fletcher=4
|
||||
let fN=Ring.PlainChanges [|for n in System.Enum.GetValues(typeof<names>)->n:?>names|]
|
||||
let fG n g l=n|>Array.pairwise|>Array.forall(fun n->match n with (n,i) when (n=g && i=l)->false |(i,n) when (n=g && i=l)->false |_->true)
|
||||
fN|>Seq.filter(fun n->n.[4]<>names.Baker && n.[0]<>names.Cooper && n.[0]<>names.Fletcher && n.[4]<>names.Fletcher && fG n names.Smith names.Fletcher
|
||||
&& fG n names.Cooper names.Fletcher && (Array.findIndex((=)names.Cooper) n) < (Array.findIndex((=)names.Miller) n))
|
||||
|>Seq.iter(Array.iteri(fun n g->printfn "%A lives on floor %d" g n))
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
USING: kernel
|
||||
combinators.short-circuit
|
||||
math math.combinatorics math.ranges
|
||||
sequences
|
||||
qw prettyprint ;
|
||||
IN: rosetta.dinesman
|
||||
|
||||
: /= ( x y -- ? ) = not ;
|
||||
: fifth ( seq -- elt ) 4 swap nth ;
|
||||
|
||||
: meets-constraints? ( seq -- ? )
|
||||
{
|
||||
[ first 5 /= ] ! Baker does not live on the top floor.
|
||||
[ second 1 /= ] ! Cooper does not live on the bottom floor.
|
||||
[ third { 1 5 } member? not ] ! Fletcher does not live on either the top or bottom floor.
|
||||
[ [ fourth ] [ second ] bi > ] ! Miller lives on a higher floor than does Cooper.
|
||||
[ [ fifth ] [ third ] bi - abs 1 /= ] ! Smith does not live on a floor adjacent to Fletcher's.
|
||||
[ [ third ] [ second ] bi - abs 1 /= ] ! Fletcher does not live on a floor adjacent to Cooper's.
|
||||
} 1&& ;
|
||||
|
||||
: solutions ( -- seq )
|
||||
5 [1,b] all-permutations [ meets-constraints? ] filter ;
|
||||
|
||||
: >names ( seq -- seq )
|
||||
[ qw{ baker cooper fletcher miller smith } nth swap 2array ] map-index ;
|
||||
|
||||
: dinesman ( -- )
|
||||
solutions [ >names . ] each ;
|
||||
|
|
@ -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,33 @@
|
|||
Print "Los apartamentos estan numerados del 0 (bajo) al 4 (atico)."
|
||||
Print "Baker, Cooper, Fletcher, Miller y Smith viven en apartamentos diferentes."
|
||||
Print "- Baker no vive en el ultimo apartamento (atico)."
|
||||
Print "- Cooper no vive en el piso inferior (bajo)."
|
||||
Print "- Fletcher no vive ni en el atico ni en el bajo."
|
||||
Print "- Miller vive en un apartamento más alto que Cooper."
|
||||
Print "- Smith no vive en un apartamento adyacente al de Fletcher."
|
||||
Print "- Fletcher no vive en un apartamento adyacente al de Cooper." & Chr(10)
|
||||
|
||||
Dim As Ubyte Baker, Cooper, Fletcher, Miller, Smith
|
||||
|
||||
For Baker = 0 To 3
|
||||
For Cooper = 1 To 4
|
||||
For Fletcher = 1 To 3
|
||||
For Miller = 0 To 4
|
||||
For Smith = 0 To 4
|
||||
If 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 And Miller>Cooper And Abs(Smith-Fletcher)<>1 _
|
||||
And Abs(Fletcher-Cooper)<>1 Then
|
||||
Print "Baker vive en el piso "; Baker
|
||||
Print "Cooper vive en el piso "; Cooper
|
||||
Print "Fletcher vive en el piso "; Fletcher
|
||||
Print "Miller vive en el piso "; Miller
|
||||
Print "Smith vive en el piso "; Smith
|
||||
End If
|
||||
Next Smith
|
||||
Next Miller
|
||||
Next Fletcher
|
||||
Next Cooper
|
||||
Next Baker
|
||||
Sleep
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// The program here is restricted to finding assignments of tenants (or more
|
||||
// generally variables with distinct names) to floors (or more generally
|
||||
// integer values.) It finds a solution assigning all tenants and assigning
|
||||
// them to different floors.
|
||||
|
||||
// Change number and names of tenants here. Adding or removing names is
|
||||
// allowed but the names should be distinct; the code is not written to handle
|
||||
// duplicate names.
|
||||
var tenants = []string{"Baker", "Cooper", "Fletcher", "Miller", "Smith"}
|
||||
|
||||
// Change the range of floors here. The bottom floor does not have to be 1.
|
||||
// These should remain non-negative integers though.
|
||||
const bottom = 1
|
||||
const top = 5
|
||||
|
||||
// A type definition for readability. Do not change.
|
||||
type assignments map[string]int
|
||||
|
||||
// Change rules defining the problem here. Change, add, or remove rules as
|
||||
// desired. Each rule should first be commented as human readable text, then
|
||||
// coded as a function. The function takes a tentative partial list of
|
||||
// assignments of tenants to floors and is free to compute anything it wants
|
||||
// with this information. Other information available to the function are
|
||||
// package level defintions, such as top and bottom. A function returns false
|
||||
// to say the assignments are invalid.
|
||||
var rules = []func(assignments) bool{
|
||||
// Baker does not live on the top floor
|
||||
func(a assignments) bool {
|
||||
floor, assigned := a["Baker"]
|
||||
return !assigned || floor != top
|
||||
},
|
||||
// Cooper does not live on the bottom floor
|
||||
func(a assignments) bool {
|
||||
floor, assigned := a["Cooper"]
|
||||
return !assigned || floor != bottom
|
||||
},
|
||||
// Fletcher does not live on either the top or the bottom floor
|
||||
func(a assignments) bool {
|
||||
floor, assigned := a["Fletcher"]
|
||||
return !assigned || (floor != top && floor != bottom)
|
||||
},
|
||||
// Miller lives on a higher floor than does Cooper
|
||||
func(a assignments) bool {
|
||||
if m, assigned := a["Miller"]; assigned {
|
||||
c, assigned := a["Cooper"]
|
||||
return !assigned || m > c
|
||||
}
|
||||
return true
|
||||
},
|
||||
// Smith does not live on a floor adjacent to Fletcher's
|
||||
func(a assignments) bool {
|
||||
if s, assigned := a["Smith"]; assigned {
|
||||
if f, assigned := a["Fletcher"]; assigned {
|
||||
d := s - f
|
||||
return d*d > 1
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
// Fletcher does not live on a floor adjacent to Cooper's
|
||||
func(a assignments) bool {
|
||||
if f, assigned := a["Fletcher"]; assigned {
|
||||
if c, assigned := a["Cooper"]; assigned {
|
||||
d := f - c
|
||||
return d*d > 1
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// Assignment program, do not change. The algorithm is a depth first search,
|
||||
// tentatively assigning each tenant in order, and for each tenant trying each
|
||||
// unassigned floor in order. For each tentative assignment, it evaluates all
|
||||
// rules in the rules list and backtracks as soon as any one of them fails.
|
||||
//
|
||||
// This algorithm ensures that the tenative assignments have only names in the
|
||||
// tenants list, only floor numbers from bottom to top, and that tentants are
|
||||
// assigned to different floors. These rules are hard coded here and do not
|
||||
// need to be coded in the the rules list above.
|
||||
func main() {
|
||||
a := assignments{}
|
||||
var occ [top + 1]bool
|
||||
var df func([]string) bool
|
||||
df = func(u []string) bool {
|
||||
if len(u) == 0 {
|
||||
return true
|
||||
}
|
||||
tn := u[0]
|
||||
u = u[1:]
|
||||
f:
|
||||
for f := bottom; f <= top; f++ {
|
||||
if !occ[f] {
|
||||
a[tn] = f
|
||||
for _, r := range rules {
|
||||
if !r(a) {
|
||||
delete(a, tn)
|
||||
continue f
|
||||
}
|
||||
}
|
||||
occ[f] = true
|
||||
if df(u) {
|
||||
return true
|
||||
}
|
||||
occ[f] = false
|
||||
delete(a, tn)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if !df(tenants) {
|
||||
fmt.Println("no solution")
|
||||
return
|
||||
}
|
||||
for t, f := range a {
|
||||
fmt.Println(t, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,20 @@
|
|||
import Data.List (permutations)
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
print
|
||||
[ ( "Baker lives on " <> show b,
|
||||
"Cooper lives on " <> show c,
|
||||
"Fletcher lives on " <> show f,
|
||||
"Miller lives on " <> show m,
|
||||
"Smith lives on " <> show 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,19 @@
|
|||
100 PROGRAM "Dinesman.bas"
|
||||
110 PRINT "Floors are numbered 0 (ground) to 4 (top).":PRINT "Baker, Cooper, Fletcher, Miller, and Smith live on different floors."
|
||||
120 PRINT "- Baker does not live on the top floor.":PRINT "- Cooper does not live on the bottom floor."
|
||||
130 PRINT "- Fletcher does not live on either the top or the bottom floor.":PRINT "- Miller lives on a higher floor than does Cooper."
|
||||
140 PRINT "- Smith does not live on a floor adjacent to Fletcher's.":PRINT "- Fletcher does not live on a floor adjacent to Cooper's.":PRINT :LET S$=" lives on floor"
|
||||
150 FOR B=0 TO 3
|
||||
150 FOR C=1 TO 4
|
||||
170 FOR F=1 TO 3
|
||||
180 FOR M=0 TO 4
|
||||
190 FOR S=0 TO 4
|
||||
200 IF B<>C AND B<>F AND B<>M AND B<>S AND C<>F AND C<>M AND C<>S AND F<>M AND F<>S AND M<>S AND M>C AND ABS(S-F)<>1 AND ABS(F-C)<>1 THEN
|
||||
210 PRINT "Baker",S$;B:PRINT "Cooper",S$;C:PRINT "Fletcher";S$;F:PRINT "Miller",S$;M:PRINT "Smith",S$;S
|
||||
220 END
|
||||
230 END IF
|
||||
240 NEXT
|
||||
250 NEXT
|
||||
260 NEXT
|
||||
270 NEXT
|
||||
280 NEXT
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
invocable all
|
||||
global nameL, nameT, rules
|
||||
|
||||
procedure main() # Dinesman
|
||||
|
||||
nameT := table()
|
||||
nameL := ["Baker", "Cooper", "Fletcher", "Miller", "Smith"]
|
||||
rules := [ [ distinct ],
|
||||
[ "~=", "Baker", top() ],
|
||||
[ "~=", "Cooper", bottom() ],
|
||||
[ "~=", "Fletcher", top() ],
|
||||
[ "~=", "Fletcher", bottom() ],
|
||||
[ ">", "Miller", "Cooper" ],
|
||||
[ notadjacent, "Smith", "Fletcher" ],
|
||||
[ notadjacent, "Fletcher", "Cooper" ],
|
||||
[ showsolution ],
|
||||
[ stop ] ]
|
||||
|
||||
if not solve(1) then
|
||||
write("No solution found.")
|
||||
end
|
||||
|
||||
procedure dontstop() # use if you want to search for all solutions
|
||||
end
|
||||
|
||||
procedure showsolution() # show the soluton
|
||||
write("The solution is:")
|
||||
every write(" ",n := !nameL, " lives in ", nameT[n])
|
||||
return
|
||||
end
|
||||
|
||||
procedure eval(n) # evaluate a rule
|
||||
r := copy(rules[n-top()])
|
||||
every r[i := 2 to *r] := rv(r[i])
|
||||
if get(r)!r then suspend
|
||||
end
|
||||
|
||||
procedure rv(x) # return referenced value if it exists
|
||||
return \nameT[x] | x
|
||||
end
|
||||
|
||||
procedure solve(n) # recursive solver
|
||||
if n > top() then { # apply rules
|
||||
if n <= top() + *rules then
|
||||
( eval(n) & solve(n+1) ) | fail
|
||||
}
|
||||
else # setup locations
|
||||
(( nameT[nameL[n]] := bottom() to top() ) & solve(n + 1)) | fail
|
||||
return
|
||||
end
|
||||
|
||||
procedure distinct(a,b) # ensure each name is distinct
|
||||
if nameT[n := !nameL] = nameT[n ~== key(nameT)] then fail
|
||||
suspend
|
||||
end
|
||||
|
||||
procedure notadjacent(n1,n2) # ensure n1,2 are not adjacent
|
||||
if not adjacent(n1,n2) then suspend
|
||||
end
|
||||
|
||||
procedure adjacent(n1,n2) # ensure n1,2 are adjacent
|
||||
if abs(n1 - n2) = 1 then suspend
|
||||
end
|
||||
|
||||
procedure bottom() # return bottom
|
||||
return if *nameL > 0 then 1 else 0
|
||||
end
|
||||
|
||||
procedure top() # return top
|
||||
return *nameL
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
possible=: ((i.!5) A. i.5) { 'BCFMS'
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
possible=: (#~ 'B' ~: {:"1) possible NB. Baker not on top floor
|
||||
possible=: (#~ 'C' ~: {."1) possible NB. Cooper not on bottom floor
|
||||
possible=: (#~ 'F' ~: {:"1) possible NB. Fletcher not on top floor
|
||||
possible=: (#~ 'F' ~: {."1) possible NB. Fletcher not on bottom floor
|
||||
possible=: (#~ </@i."1&'CM') possible NB. Miller on higher floor than Cooper
|
||||
possible=: (#~ 0 = +/@E."1~&'SF') possible NB. Smith not immediately below Fletcher
|
||||
possible=: (#~ 0 = +/@E."1~&'FS') possible NB. Fletcher not immediately below Smith
|
||||
possible=: (#~ 0 = +/@E."1~&'CF') possible NB. Cooper not immediately below Fletcher
|
||||
possible=: (#~ 0 = +/@E."1~&'FC') possible NB. Fletcher not immediately below Cooper
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
possible
|
||||
SCBFM
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean topFloor(String permutation, String person) { //Checks to see if the person is on the top floor
|
||||
return permutation.endsWith(person);
|
||||
}
|
||||
|
||||
private static boolean bottomFloor(String permutation, String person) {//Checks to see if the person is on the bottom floor
|
||||
return permutation.startsWith(person);
|
||||
}
|
||||
|
||||
public static boolean livesAbove(String permutation, String upperPerson, String lowerPerson) {//Checks to see if the person lives above the other person
|
||||
return permutation.indexOf(upperPerson) > permutation.indexOf(lowerPerson);
|
||||
}
|
||||
|
||||
public static boolean adjacent(String permutation, String person1, String person2) { //checks to see if person1 is adjacent to person2
|
||||
return (Math.abs(permutation.indexOf(person1) - permutation.indexOf(person2)) == 1);
|
||||
}
|
||||
|
||||
private static boolean isPossible(String s) {
|
||||
/*
|
||||
What this does should be obvious...proper explaination can be given if needed
|
||||
Conditions here Switching any of these to ! or reverse will change what is given as a result
|
||||
|
||||
example
|
||||
if(topFloor(s, "B"){
|
||||
}
|
||||
to
|
||||
if(!topFloor(s, "B"){
|
||||
}
|
||||
or the opposite
|
||||
if(!topFloor(s, "B"){
|
||||
}
|
||||
to
|
||||
if(topFloor(s, "B"){
|
||||
}
|
||||
*/
|
||||
if (topFloor(s, "B")) {//B is on Top Floor
|
||||
return false;
|
||||
}
|
||||
if (bottomFloor(s, "C")) {//C is on Bottom Floor
|
||||
return false;
|
||||
}
|
||||
if (topFloor(s, "F") || bottomFloor(s, "F")) {// F is on top or bottom floor
|
||||
return false;
|
||||
}
|
||||
if (!livesAbove(s, "M", "C")) {// M does not live above C
|
||||
return false;
|
||||
}
|
||||
if (adjacent(s, "S", "F")) { //S lives adjacent to F
|
||||
return false;
|
||||
}
|
||||
return !adjacent(s, "F", "C"); //F does not live adjacent to C
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Set<String> set = new HashSet<String>();
|
||||
generatePermutations(new String[]{"B", "C", "F", "M", "S"}, set, ""); //Generates Permutations
|
||||
for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {//Loops through iterator
|
||||
String permutation = iterator.next();
|
||||
if (!isPossible(permutation)) {//checks to see if permutation is false if so it removes it
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
for (String s : set) {
|
||||
System.out.println("Possible arrangement: " + s);
|
||||
/*
|
||||
Prints out possible arranagement...changes depending on what you change in the "isPossible method"
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
const concatMap = (f, xs) => [].concat.apply([], xs.map(f));
|
||||
|
||||
// range :: Int -> Int -> [Int]
|
||||
const range = (m, n) =>
|
||||
Array.from({
|
||||
length: Math.floor(n - m) + 1
|
||||
}, (_, i) => m + i);
|
||||
|
||||
// and :: [Bool] -> Bool
|
||||
const and = xs => {
|
||||
let i = xs.length;
|
||||
while (i--)
|
||||
if (!xs[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// nubBy :: (a -> a -> Bool) -> [a] -> [a]
|
||||
const nubBy = (p, xs) => {
|
||||
const x = xs.length ? xs[0] : undefined;
|
||||
return x !== undefined ? [x].concat(
|
||||
nubBy(p, xs.slice(1)
|
||||
.filter(y => !p(x, y)))
|
||||
) : [];
|
||||
}
|
||||
|
||||
// PROBLEM DECLARATION
|
||||
|
||||
const floors = range(1, 5);
|
||||
|
||||
return concatMap(b =>
|
||||
concatMap(c =>
|
||||
concatMap(f =>
|
||||
concatMap(m =>
|
||||
concatMap(s =>
|
||||
and([ // CONDITIONS
|
||||
nubBy((a, b) => a === b, [b, c, f, m, s]) // all floors singly occupied
|
||||
.length === 5,
|
||||
b !== 5, c !== 1, f !== 1, f !== 5,
|
||||
m > c, Math.abs(s - f) > 1, Math.abs(c - f) > 1
|
||||
]) ? [{
|
||||
Baker: b,
|
||||
Cooper: c,
|
||||
Fletcher: f,
|
||||
Miller: m,
|
||||
Smith: s
|
||||
}] : [],
|
||||
floors), floors), floors), floors), floors);
|
||||
|
||||
// --> [{"Baker":3, "Cooper":2, "Fletcher":4, "Miller":5, "Smith":1}]
|
||||
})();
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"Baker":3, "Cooper":2, "Fletcher":4, "Miller":5, "Smith":1}]
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
const concatMap = (f, xs) => [].concat.apply([], xs.map(f));
|
||||
|
||||
// range :: Int -> Int -> [Int]
|
||||
const range = (m, n) =>
|
||||
Array.from({
|
||||
length: Math.floor(n - m) + 1
|
||||
}, (_, i) => m + i);
|
||||
|
||||
// and :: [Bool] -> Bool
|
||||
const and = xs => {
|
||||
let i = xs.length;
|
||||
while (i--)
|
||||
if (!xs[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// permutations :: [a] -> [[a]]
|
||||
const permutations = xs =>
|
||||
xs.length ? concatMap(x => concatMap(ys => [
|
||||
[x].concat(ys)
|
||||
],
|
||||
permutations(delete_(x, xs))), xs) : [
|
||||
[]
|
||||
];
|
||||
|
||||
// delete :: a -> [a] -> [a]
|
||||
const delete_ = (x, xs) =>
|
||||
deleteBy((a, b) => a === b, x, xs);
|
||||
|
||||
// deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
|
||||
const deleteBy = (f, x, xs) =>
|
||||
xs.reduce((a, y) => f(x, y) ? a : a.concat(y), []);
|
||||
|
||||
// PROBLEM DECLARATION
|
||||
|
||||
const floors = range(1, 5);
|
||||
|
||||
return concatMap(([c, b, f, m, s]) =>
|
||||
and([ // CONDITIONS (assuming full occupancy, no cohabitation)
|
||||
b !== 5, c !== 1, f !== 1, f !== 5,
|
||||
m > c, Math.abs(s - f) > 1, Math.abs(c - f) > 1
|
||||
]) ? [{
|
||||
Baker: b,
|
||||
Cooper: c,
|
||||
Fletcher: f,
|
||||
Miller: m,
|
||||
Smith: s
|
||||
}] : [], permutations(floors));
|
||||
|
||||
// --> [{"Baker":3, "Cooper":2, "Fletcher":4, "Miller":5, "Smith":1}]
|
||||
})();
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"Baker":3, "Cooper":2, "Fletcher":4, "Miller":5, "Smith":1}]
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# Input: an array representing the apartment house, with null at a
|
||||
# particular position signifying that the identity of the occupant
|
||||
# there has not yet been determined.
|
||||
# Output: an elaboration of the input array but including person, and
|
||||
# satisfying cond, where . in cond refers to the placement of person
|
||||
def resides(person; cond):
|
||||
range(0;5) as $n
|
||||
| if (.[$n] == null or .[$n] == person) and ($n|cond) then .[$n] = person
|
||||
else empty # no elaboration is possible
|
||||
end ;
|
||||
|
||||
# English:
|
||||
def top: 4;
|
||||
def bottom: 0;
|
||||
def higher(j): . > j;
|
||||
def adjacent(j): (. - j) | (. == 1 or . == -1);
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[]
|
||||
| resides("Baker"; . != top) # Baker does not live on the top floor
|
||||
| resides("Cooper"; . != bottom) # Cooper does not live on the bottom floor
|
||||
| resides("Fletcher"; . != top and . != bottom) # Fletcher does not live on either the top or the bottom floor.
|
||||
| index("Cooper") as $Cooper
|
||||
| resides("Miller"; higher( $Cooper) ) # Miller lives on a higher floor than does Cooper
|
||||
| index("Fletcher") as $Fletcher
|
||||
| resides("Smith"; adjacent($Fletcher) | not) # Smith does not live on a floor adjacent to Fletcher's.
|
||||
| select( $Fletcher | adjacent( $Cooper ) | not ) # Fletcher does not live on a floor adjacent to Cooper's.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
$ jq -n -f Dinesman.jq
|
||||
[
|
||||
"Smith",
|
||||
"Cooper",
|
||||
"Baker",
|
||||
"Fletcher",
|
||||
"Miller"
|
||||
]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Combinatorics
|
||||
|
||||
function solve(n::Vector{<:AbstractString}, pred::Vector{<:Function})
|
||||
rst = Vector{typeof(n)}(0)
|
||||
for candidate in permutations(n)
|
||||
if all(p(candidate) for p in predicates)
|
||||
push!(rst, candidate)
|
||||
end
|
||||
end
|
||||
return rst
|
||||
end
|
||||
|
||||
Names = ["Baker", "Cooper", "Fletcher", "Miller", "Smith"]
|
||||
predicates = [
|
||||
(s) -> last(s) != "Baker",
|
||||
(s) -> first(s) != "Cooper",
|
||||
(s) -> first(s) != "Fletcher" && last(s) != "Fletcher",
|
||||
(s) -> findfirst(s, "Miller") > findfirst(s, "Cooper"),
|
||||
(s) -> abs(findfirst(s, "Smith") - findfirst(s, "Fletcher")) != 1,
|
||||
(s) -> abs(findfirst(s, "Cooper") - findfirst(s, "Fletcher")) != 1]
|
||||
|
||||
solutions = solve(Names, predicates)
|
||||
foreach(x -> println(join(x, ", ")), solutions)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
perm: {x@m@&n=(#?:)'m:!n#n:#x}
|
||||
filter: {y[& x'y]}
|
||||
reject: {y[& ~x'y]}
|
||||
adjacent: {1 = _abs (z?x) - (z?y)}
|
||||
|
||||
p: perm[`Baker `Cooper `Fletcher `Miller `Smith]
|
||||
p: reject[{`Cooper=x[0]}; p]
|
||||
p: reject[{`Baker=x[4]}; p]
|
||||
p: filter[{(x ? `Miller) > (x ? `Cooper)}; p]
|
||||
p: reject[{adjacent[`Smith; `Fletcher; x]}; p]
|
||||
p: reject[{adjacent[`Cooper; `Fletcher; x]}; p]
|
||||
p: reject[{(x ? `Fletcher)_in (0 4)}; p]
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// version 1.1.3
|
||||
|
||||
typealias Predicate = (List<String>) -> Boolean
|
||||
|
||||
fun <T> permute(input: List<T>): List<List<T>> {
|
||||
if (input.size == 1) return listOf(input)
|
||||
val perms = mutableListOf<List<T>>()
|
||||
val toInsert = input[0]
|
||||
for (perm in permute(input.drop(1))) {
|
||||
for (i in 0..perm.size) {
|
||||
val newPerm = perm.toMutableList()
|
||||
newPerm.add(i, toInsert)
|
||||
perms.add(newPerm)
|
||||
}
|
||||
}
|
||||
return perms
|
||||
}
|
||||
|
||||
/* looks for for all possible solutions, not just the first */
|
||||
fun dinesman(occupants: List<String>, predicates: List<Predicate>) =
|
||||
permute(occupants).filter { perm -> predicates.all { pred -> pred(perm) } }
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val occupants = listOf("Baker", "Cooper", "Fletcher", "Miller", "Smith")
|
||||
|
||||
val predicates = listOf<Predicate>(
|
||||
{ it.last() != "Baker" },
|
||||
{ it.first() != "Cooper" },
|
||||
{ it.last() != "Fletcher" && it.first() != "Fletcher" },
|
||||
{ it.indexOf("Miller") > it.indexOf("Cooper") },
|
||||
{ Math.abs(it.indexOf("Smith") - it.indexOf("Fletcher")) > 1 },
|
||||
{ Math.abs(it.indexOf("Fletcher") - it.indexOf("Cooper")) > 1 }
|
||||
)
|
||||
|
||||
val solutions = dinesman(occupants, predicates)
|
||||
val size = solutions.size
|
||||
if (size == 0) {
|
||||
println("No solutions found")
|
||||
}
|
||||
else {
|
||||
val plural = if (size == 1) "" else "s"
|
||||
println("$size solution$plural found, namely:\n")
|
||||
for (solution in solutions) {
|
||||
for ((i, name) in solution.withIndex()) {
|
||||
println("Floor ${i + 1} -> $name")
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
local wrap, yield = coroutine.wrap, coroutine.yield
|
||||
local function perm(n)
|
||||
local r = {}
|
||||
for i=1,n do r[i]=i end
|
||||
return wrap(function()
|
||||
local function swap(m)
|
||||
if m==0 then
|
||||
yield(r)
|
||||
else
|
||||
for i=m,1,-1 do
|
||||
r[i],r[m]=r[m],r[i]
|
||||
swap(m-1)
|
||||
r[i],r[m]=r[m],r[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
swap(n)
|
||||
end)
|
||||
end
|
||||
|
||||
local function iden(...)return ... end
|
||||
local function imap(t,f)
|
||||
local r,fn = {m=imap, c=table.concat, u=table.unpack}, f or iden
|
||||
for i=1,#t do r[i]=fn(t[i])end
|
||||
return r
|
||||
end
|
||||
|
||||
local tenants = {'Baker', 'Cooper', 'Fletcher', 'Miller', 'Smith'}
|
||||
|
||||
local conds = {
|
||||
'Baker ~= TOP',
|
||||
'Cooper ~= BOTTOM',
|
||||
'Fletcher ~= TOP and Fletcher~= BOTTOM',
|
||||
'Miller > Cooper',
|
||||
'Smith + 1 ~= Fletcher and Smith - 1 ~= Fletcher',
|
||||
'Cooper + 1 ~= Fletcher and Cooper - 1 ~= Fletcher',
|
||||
}
|
||||
|
||||
local function makePredicate(conds, tenants)
|
||||
return load('return function('..imap(tenants):c','..
|
||||
') return ' ..
|
||||
imap(conds,function(c)
|
||||
return string.format("(%s)",c)
|
||||
end):c"and "..
|
||||
" end ",'-',nil,{TOP=5, BOTTOM=1})()
|
||||
end
|
||||
|
||||
local function solve (conds, tenants)
|
||||
local try, pred, upk = perm(#tenants), makePredicate(conds, tenants), table.unpack
|
||||
local answer = try()
|
||||
while answer and not pred(upk(answer)) do answer = try()end
|
||||
if answer then
|
||||
local floor = 0
|
||||
return imap(answer, function(person)
|
||||
floor=floor+1;
|
||||
return string.format(" %s lives on floor %d",tenants[floor],person)
|
||||
end):c"\n"
|
||||
else
|
||||
return nil, 'no solution'
|
||||
end
|
||||
end
|
||||
|
||||
print(solve (conds, tenants))
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
Module Dinesman_s_multiple_dwelling_problem {
|
||||
// this is the standard perimutation function
|
||||
// which create a lambda function:
|
||||
// pointer_to_array=Func(&BooleanVariable)
|
||||
// when BooleanVariable = true we get the last permutation
|
||||
Function PermutationStep (a as array) {
|
||||
c1=lambda (&f, a) ->{
|
||||
=a : f=true
|
||||
}
|
||||
integer m=len(a)
|
||||
if m=0 then Error "No items to make permutations"
|
||||
c=c1
|
||||
While m>1
|
||||
c1=lambda c2=c,p=0%, m=(,) (&f, a, clear as boolean=false) ->{
|
||||
if clear then m=(,)
|
||||
if len(m)=0 then m=a
|
||||
=cons(car(m),c2(&f, cdr(m)))
|
||||
if f then f=false:p++: m=cons(cdr(m), car(m)) : if p=len(m) then p=0 : m=(,):: f=true
|
||||
}
|
||||
c=c1
|
||||
m--
|
||||
End While
|
||||
=lambda c, a (&f, clear as boolean=false) -> {
|
||||
=c(&f, a, clear)
|
||||
}
|
||||
}
|
||||
boolean k
|
||||
object s=("Baker", "Cooper", "Fletcher", "Miller", "Smith")
|
||||
StepA=PermutationStep(s)
|
||||
while not k
|
||||
s=StepA(&k)
|
||||
if s#val$(4)= "Baker" then continue
|
||||
if s#val$(0)="Cooper" then continue
|
||||
if s#val$(0)="Fletcher" then continue
|
||||
if s#val$(4)="Fletcher" then continue
|
||||
if s#pos("Cooper")> s#pos("Miller") then continue
|
||||
if abs(s#pos("Smith")-s#pos("Fletcher"))=1 then continue
|
||||
if abs(s#pos("Cooper")-s#pos("Fletcher"))=1 then continue
|
||||
exit // for one solution
|
||||
end while
|
||||
object c=each(s)
|
||||
while c
|
||||
Print array$(c)+" lives on floor "+(c^+1)
|
||||
end while
|
||||
}
|
||||
Dinesman_s_multiple_dwelling_problem
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
Module Using_AmbFunction {
|
||||
Enum Solution {First, Any=-1}
|
||||
Function Amb(way as Solution, failure) {
|
||||
read a
|
||||
c1=lambda i=0, a, (&any, &ret) ->{
|
||||
any=(array(a,i),)
|
||||
ret=any
|
||||
i++
|
||||
ok=i=len(a)
|
||||
if ok then i=0
|
||||
=ok
|
||||
}
|
||||
m=stack.size
|
||||
if m=0 then Error "At least two arrays needed"
|
||||
c=c1
|
||||
while m>0 {
|
||||
read a
|
||||
c1=lambda c2=c, i=0, a, (&any, &ret) ->{
|
||||
any=(array(a,i),)
|
||||
ret=(,) : ok=false : anyother=(,)
|
||||
ok=c2(&anyother, &ret)
|
||||
ret=cons(ret, any)
|
||||
if ok then i++
|
||||
ok=i=len(a)
|
||||
if ok then i=0
|
||||
=ok
|
||||
}
|
||||
c=c1 : m--
|
||||
}
|
||||
ok=false
|
||||
any=(,)
|
||||
flush
|
||||
while not ok
|
||||
ret=(,)
|
||||
ok=c(&any, &ret)
|
||||
s=stack(ret)
|
||||
if not failure(! s) then data ret : if way>0 then ok=true
|
||||
End While
|
||||
if empty then
|
||||
ret=(("",),)
|
||||
else
|
||||
ret=array([])
|
||||
end if
|
||||
=ret
|
||||
}
|
||||
Range=lambda (a, f) ->{
|
||||
for i=a to f-1: data i: next
|
||||
=array([])
|
||||
}
|
||||
|
||||
Baker=range(1, 5)
|
||||
Cooper=range(2, 6)
|
||||
Fletcher=range(2, 5)
|
||||
Miller=range(1,6)
|
||||
Smith=range(1,6)
|
||||
|
||||
failure=lambda (Baker, Cooper, Fletcher, Miller, Smith)->{
|
||||
if Baker=Cooper or Baker=Fletcher or Baker=Miller or Baker=Smith then =true:exit
|
||||
if Cooper=Fletcher or Cooper =Miller or Cooper=Smith then =true:exit
|
||||
if Fletcher=Miller or Fletcher=Smith or Miller=Smith then =true:exit
|
||||
if Miller<Cooper or abs(Cooper-Fletcher)=1 or abs(Smith-Fletcher)=1 then =true:exit
|
||||
}
|
||||
all=amb(Any, failure, Baker, Cooper, Fletcher, Miller, Smith)
|
||||
k=each(all)
|
||||
s=("Baker", "Cooper", "Fletcher", "Miller", "Smith")
|
||||
while k
|
||||
z=array(k)
|
||||
zz=each(z, , -2)
|
||||
while zz
|
||||
? s#val$(zz^)+" ("+array(zz)+"), ";
|
||||
end while
|
||||
zz=each(z, -1)
|
||||
while zz
|
||||
? s#val$(zz^)+" ("+array(zz)+") "
|
||||
end while
|
||||
end while
|
||||
}
|
||||
Using_AmbFunction
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{Baker, Cooper, Fletcher, Miller, Smith};
|
||||
(Unequal @@ %) && (And @@ (0 < # < 6 & /@ %)) &&
|
||||
Baker < 5 &&
|
||||
Cooper > 1 &&
|
||||
1 < Fletcher < 5 &&
|
||||
Miller > Cooper &&
|
||||
Abs[Smith - Fletcher] > 1 &&
|
||||
Abs[Cooper - Fletcher] > 1 //
|
||||
Reduce[#, %, Integers] &
|
||||
|
|
@ -0,0 +1 @@
|
|||
Baker == 3 && Cooper == 2 && Fletcher == 4 && Miller == 5 && Smith == 1
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
p = Position[#1, #2][[1, 1]] &;
|
||||
Permutations[{"Baker", "Cooper", "Fletcher", "Miller", "Smith"}, {5}];
|
||||
Select[%, #[[5]] != "Baker" &];
|
||||
Select[%, #[[1]] != "Cooper" &];
|
||||
Select[%, #[[1]] != "Fletcher" && #[[5]] != "Fletcher" &];
|
||||
Select[%, #~p~"Miller" > #~p~"Cooper" &];
|
||||
Select[%, Abs[#~p~"Smith" - #~p~"Fletcher"] > 1 &];
|
||||
Select[%, Abs[#~p~"Cooper" - #~p~"Fletcher"] > 1 &]
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{"Smith", "Cooper", "Baker", "Fletcher", "Miller"}}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
%Dinesman's multiple-dwelling problem. Nigel Galloway, September 25th., 2020
|
||||
include "alldifferent.mzn";
|
||||
enum names={Baker,Cooper,Miller,Smith,Fletcher};
|
||||
array[names] of var 1..5: res; constraint alldifferent([res[n] | n in names]);
|
||||
constraint res[Baker] !=5;
|
||||
constraint res[Cooper] !=1;
|
||||
constraint res[Fletcher] !=1;
|
||||
constraint res[Fletcher] !=5;
|
||||
constraint abs(res[Smith] -res[Fletcher]) > 1;
|
||||
constraint abs(res[Cooper]-res[Fletcher]) > 1;
|
||||
constraint res[Cooper] < res[Miller];
|
||||
output["\(n) resides on floor \(res[n])\n" | n in names]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import algorithm
|
||||
|
||||
type
|
||||
|
||||
Person {.pure.} = enum Baker, Cooper, Fletcher, Miller, Smith
|
||||
Floor = range[1..5]
|
||||
|
||||
var floors: array[Person, Floor] = [Floor 1, 2, 3, 4, 5]
|
||||
|
||||
while true:
|
||||
if floors[Baker] != 5 and
|
||||
floors[Cooper] != 1 and
|
||||
floors[Fletcher] notin [1, 5] and
|
||||
floors[Miller] > floors[Cooper] and
|
||||
abs(floors[Smith] - floors[Fletcher]) != 1 and
|
||||
abs(floors[Fletcher] - floors[Cooper]) != 1:
|
||||
for person, floor in floors:
|
||||
echo person, " lives on floor ", floor
|
||||
break
|
||||
if not floors.nextPermutation():
|
||||
echo "No solution found."
|
||||
break
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature <state say>;
|
||||
use List::Util 1.33 qw(pairmap);
|
||||
use Algorithm::Permute qw(permute);
|
||||
|
||||
our %predicates = (
|
||||
# | object | sprintf format for Perl expression |
|
||||
# --------------------+-----------+------------------------------------+
|
||||
'on bottom' => [ '' , '$f[%s] == 1' ],
|
||||
'on top' => [ '' , '$f[%s] == @f' ],
|
||||
'lower than' => [ 'person' , '$f[%s] < $f[%s]' ],
|
||||
'higher than' => [ 'person' , '$f[%s] > $f[%s]' ],
|
||||
'directly below' => [ 'person' , '$f[%s] == $f[%s] - 1' ],
|
||||
'directly above' => [ 'person' , '$f[%s] == $f[%s] + 1' ],
|
||||
'adjacent to' => [ 'person' , 'abs($f[%s] - $f[%s]) == 1' ],
|
||||
'on' => [ 'ordinal' , '$f[%s] == \'%s\'' ],
|
||||
);
|
||||
|
||||
our %nouns = (
|
||||
'person' => qr/[a-z]+/i,
|
||||
'ordinal' => qr/1st | 2nd | 3rd | \d+th/x,
|
||||
);
|
||||
|
||||
sub parse_and_solve {
|
||||
my @facts = @_;
|
||||
|
||||
state $parser = qr/^(?<subj>$nouns{person}) (?<not>not )?(?|@{[
|
||||
join '|', pairmap {
|
||||
"(?<pred>$a)" .
|
||||
($b->[0] ? " (?<obj>$nouns{$b->[0]})" : '')
|
||||
} %predicates
|
||||
]})$/;
|
||||
|
||||
my (@expressions, %ids, $i);
|
||||
my $id = sub { defined $_[0] ? $ids{$_[0]} //= $i++ : () };
|
||||
|
||||
foreach (@facts) {
|
||||
/$parser/ or die "Cannot parse '$_'\n";
|
||||
|
||||
my $pred = $predicates{$+{pred}};
|
||||
{ no warnings;
|
||||
my $expr = '(' . sprintf($pred->[1], $id->($+{subj}),
|
||||
$pred->[0] eq 'person' ? $id->($+{obj}) : $+{obj}). ')';
|
||||
$expr = '!' . $expr if $+{not};
|
||||
push @expressions, $expr;
|
||||
}
|
||||
}
|
||||
|
||||
my @f = 1..$i;
|
||||
eval '
|
||||
permute {
|
||||
say join(", ", pairmap { "$f[$b] $a" } %ids)
|
||||
if ('.join(' && ', @expressions).');
|
||||
} @f;';
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
parse_and_solve(<DATA>);
|
||||
|
||||
__DATA__
|
||||
Baker not on top
|
||||
Cooper not on bottom
|
||||
Fletcher not on top
|
||||
Fletcher not on bottom
|
||||
Miller higher than Cooper
|
||||
Smith not adjacent to Fletcher
|
||||
Fletcher not adjacent to Cooper
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">enum</span> <span style="color: #000000;">Baker</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Cooper</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Fletcher</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Miller</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Smith</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">names</span><span style="color: #0000FF;">={</span><span style="color: #008000;">"Baker"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Cooper"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Miller"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Smith"</span><span style="color: #0000FF;">}</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Baker</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">5</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Cooper</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Fletcher</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Miller</span><span style="color: #0000FF;">]></span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Cooper</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Smith</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Fletcher</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Fletcher</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Cooper</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">?{</span><span style="color: #000000;">names</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">names</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Baker"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Cooper"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Miller"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Smith"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #000000;">rules</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Baker"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">names</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Cooper"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">names</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">">"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Miller"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Cooper"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #000080;font-style:italic;">-- {"!=",{"abs","Smith","Fletcher"},1},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"nadj"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Smith"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #000080;font-style:italic;">-- {"!=",{"abs","Fletcher","Cooper"},1},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"nadj"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Fletcher"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Cooper"</span><span style="color: #0000FF;">}}</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">rule</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #004080;">string</span> <span style="color: #000000;">operand</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">op1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">op2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rule</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">op1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">names</span><span style="color: #0000FF;">)]</span>
|
||||
<span style="color: #000080;font-style:italic;">-- elsif sequence(op1) then
|
||||
-- op1 = eval(op1,flats)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">op2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">names</span><span style="color: #0000FF;">)]</span>
|
||||
<span style="color: #000080;font-style:italic;">-- elsif sequence(op2) then
|
||||
-- op2 = eval(op2,flats)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">switch</span> <span style="color: #000000;">operand</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #008000;">"!="</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">op1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">op2</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #008000;">">"</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">op1</span><span style="color: #0000FF;">></span><span style="color: #000000;">op2</span>
|
||||
<span style="color: #000080;font-style:italic;">-- case "abs": return abs(op1-op2)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #008000;">"nadj"</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">op2</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">flats</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rules</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rules</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">names</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">?{</span><span style="color: #000000;">names</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">names</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">names</span><span style="color: #0000FF;">))))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import util.
|
||||
import cp.
|
||||
|
||||
dinesman_cp =>
|
||||
println(dinesman_cp),
|
||||
N = 5,
|
||||
X = [Baker, Cooper, Fletcher, Miller, Smith],
|
||||
X :: 1..N,
|
||||
|
||||
all_different(X),
|
||||
|
||||
% Baker does not live on the fifth floor.
|
||||
Baker #!= 5,
|
||||
|
||||
% Cooper does not live on the first floor.
|
||||
Cooper #!= 1,
|
||||
|
||||
% Fletcher does not live on either the fifth or the first floor.
|
||||
Fletcher #!= 5,
|
||||
Fletcher #!= 1,
|
||||
|
||||
% Miller lives on a higher floor than does Cooper.
|
||||
Miller #> Cooper,
|
||||
|
||||
% Smith does not live on a floor adjacent to Fletcher'.
|
||||
abs(Smith-Fletcher) #> 1,
|
||||
|
||||
% Fletcher does not live on a floor adjacent to Cooper's.
|
||||
abs(Fletcher-Cooper) #> 1,
|
||||
|
||||
solve(X),
|
||||
|
||||
println([baker=Baker, cooper=Cooper, fletcher=Fletcher, miller=Miller, smith=Smith]).
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
%
|
||||
% floors: 1: bottom .. 5: top floor
|
||||
%
|
||||
constraints([B,C,F,M,S]) =>
|
||||
B != 5, % Baker not top floor
|
||||
C != 1, % Cooper not bottom floor
|
||||
F != 1, F != 5, % Fletcher not botton nor top floor
|
||||
M > C, % Miller higher floor than Cooper
|
||||
not adjacent(S, F), % Smith and Fletcher not adjacent
|
||||
not adjacent(F, C). % Fletcher and Cooper not adjacent
|
||||
|
||||
adjacent(A,B) => abs(A-B) == 1.
|
||||
|
||||
dinesman2 =>
|
||||
println(dinesman2),
|
||||
foreach([B,C,F,M,S] in permutations(1..5), constraints([B,C,F,M,S]))
|
||||
println([baker=B, cooper=C, fletcher=F, miller=M, smith=S])
|
||||
end.
|
||||
|
|
@ -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,68 @@
|
|||
# Floors are numbered 1 (ground) to 5 (top)
|
||||
|
||||
# Baker, Cooper, Fletcher, Miller, and Smith live on different floors:
|
||||
$statement1 = '$baker -ne $cooper -and $baker -ne $fletcher -and $baker -ne $miller -and
|
||||
$baker -ne $smith -and $cooper -ne $fletcher -and $cooper -ne $miller -and
|
||||
$cooper -ne $smith -and $fletcher -ne $miller -and $fletcher -ne $smith -and
|
||||
$miller -ne $smith'
|
||||
|
||||
# Baker does not live on the top floor:
|
||||
$statement2 = '$baker -ne 5'
|
||||
|
||||
# Cooper does not live on the bottom floor:
|
||||
$statement3 = '$cooper -ne 1'
|
||||
|
||||
# Fletcher does not live on either the top or the bottom floor:
|
||||
$statement4 = '$fletcher -ne 1 -and $fletcher -ne 5'
|
||||
|
||||
# Miller lives on a higher floor than does Cooper:
|
||||
$statement5 = '$miller -gt $cooper'
|
||||
|
||||
# Smith does not live on a floor adjacent to Fletcher's:
|
||||
$statement6 = '[Math]::Abs($smith - $fletcher) -ne 1'
|
||||
|
||||
# Fletcher does not live on a floor adjacent to Cooper's:
|
||||
$statement7 = '[Math]::Abs($fletcher - $cooper) -ne 1'
|
||||
|
||||
for ($baker = 1; $baker -lt 6; $baker++)
|
||||
{
|
||||
for ($cooper = 1; $cooper -lt 6; $cooper++)
|
||||
{
|
||||
for ($fletcher = 1; $fletcher -lt 6; $fletcher++)
|
||||
{
|
||||
for ($miller = 1; $miller -lt 6; $miller++)
|
||||
{
|
||||
for ($smith = 1; $smith -lt 6; $smith++)
|
||||
{
|
||||
if (Invoke-Expression $statement2)
|
||||
{
|
||||
if (Invoke-Expression $statement3)
|
||||
{
|
||||
if (Invoke-Expression $statement5)
|
||||
{
|
||||
if (Invoke-Expression $statement4)
|
||||
{
|
||||
if (Invoke-Expression $statement6)
|
||||
{
|
||||
if (Invoke-Expression $statement7)
|
||||
{
|
||||
if (Invoke-Expression $statement1)
|
||||
{
|
||||
$multipleDwellings = @()
|
||||
$multipleDwellings+= [PSCustomObject]@{Name = "Baker" ; Floor = $baker}
|
||||
$multipleDwellings+= [PSCustomObject]@{Name = "Cooper" ; Floor = $cooper}
|
||||
$multipleDwellings+= [PSCustomObject]@{Name = "Fletcher"; Floor = $fletcher}
|
||||
$multipleDwellings+= [PSCustomObject]@{Name = "Miller" ; Floor = $miller}
|
||||
$multipleDwellings+= [PSCustomObject]@{Name = "Smith" ; Floor = $smith}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
$multipleDwellings
|
||||
|
|
@ -0,0 +1 @@
|
|||
$multipleDwellings | Sort-Object -Property Floor -Descending
|
||||
|
|
@ -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,100 @@
|
|||
Prototype cond(Array t(1))
|
||||
|
||||
Enumeration #Null
|
||||
#Baker
|
||||
#Cooper
|
||||
#Fletcher
|
||||
#Miller
|
||||
#Smith
|
||||
EndEnumeration
|
||||
|
||||
Procedure checkTenands(Array tenants(1), Array Condions.cond(1))
|
||||
Protected i, j
|
||||
Protected.cond *f
|
||||
j=ArraySize(Condions())
|
||||
For i=0 To j
|
||||
*f=Condions(i) ; load the function pointer to the current condition
|
||||
If *f(tenants()) = #False
|
||||
ProcedureReturn #False
|
||||
EndIf
|
||||
Next
|
||||
ProcedureReturn #True
|
||||
EndProcedure
|
||||
|
||||
Procedure C1(Array t(1))
|
||||
If Int(Abs(t(#Fletcher)-t(#Cooper)))<>1
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
Procedure C2(Array t(1))
|
||||
If t(#Baker)<>5
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
Procedure C3(Array t(1))
|
||||
If t(#Cooper)<>1
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
Procedure C4(Array t(1))
|
||||
If t(#Miller) >= t(#Cooper)
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
Procedure C5(Array t(1))
|
||||
If t(#Fletcher)<>1 And t(#Fletcher)<>5
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
Procedure C6(Array t(1))
|
||||
If Int(Abs(t(#Smith)-t(#Fletcher)))<>1
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
|
||||
If OpenConsole()
|
||||
Dim People(4)
|
||||
Dim Conditions(5)
|
||||
Define a, b, c, d, e, i
|
||||
;
|
||||
;- Load all conditions
|
||||
Conditions(i)=@C1(): i+1
|
||||
Conditions(i)=@C2(): i+1
|
||||
Conditions(i)=@C3(): i+1
|
||||
Conditions(i)=@C4(): i+1
|
||||
Conditions(i)=@C5(): i+1
|
||||
Conditions(i)=@C6()
|
||||
;
|
||||
; generate and the all legal combinations
|
||||
For a=1 To 5
|
||||
For b=1 To 5
|
||||
If a=b: Continue: EndIf
|
||||
For c=1 To 5
|
||||
If a=c Or b=c: Continue: EndIf
|
||||
For d=1 To 5
|
||||
If d=a Or d=b Or d=c : Continue: EndIf
|
||||
For e=1 To 5
|
||||
If e=a Or e=b Or e=c Or e=d: Continue: EndIf
|
||||
People(#Baker)=a
|
||||
People(#Cooper)=b
|
||||
People(#Fletcher)=c
|
||||
People(#Miller)=d
|
||||
People(#Smith)=e
|
||||
If checkTenands(People(), Conditions())
|
||||
PrintN("Solution found;")
|
||||
PrintN("Baker="+Str(a)+#CRLF$+"Cooper="+Str(b)+#CRLF$+"Fletcher="+Str(c))
|
||||
PrintN("Miller="+Str(d)+#CRLF$+"Smith="+Str(e)+#CRLF$)
|
||||
EndIf
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
Print("Press ENTER to exit"): Input()
|
||||
EndIf
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
EnableExplicit
|
||||
|
||||
Global verbose = #False
|
||||
|
||||
Macro COND ( a, b )
|
||||
Procedure a ( Array s ( 1 ) )
|
||||
ProcedureReturn Bool( b )
|
||||
EndProcedure
|
||||
EndMacro
|
||||
|
||||
Prototype condition ( Array s ( 1 ) )
|
||||
|
||||
#N_FLOORS = 5
|
||||
#TOP = #N_FLOORS - 1
|
||||
|
||||
Global Dim solutions ( #N_FLOORS - 1 )
|
||||
Global Dim occupied ( #N_FLOORS - 1 )
|
||||
|
||||
Enumeration tenants
|
||||
#baker
|
||||
#cooper
|
||||
#fletcher
|
||||
#miller
|
||||
#smith
|
||||
#phantom_of_the_opera
|
||||
EndEnumeration
|
||||
|
||||
Global Dim names.s ( 4 )
|
||||
names( 0 ) = "baker"
|
||||
names( 1 ) = "cooper"
|
||||
names( 2 ) = "fletcher"
|
||||
names( 3 ) = "miller"
|
||||
names( 4 ) = "smith"
|
||||
|
||||
COND( c0, s( #baker ) <> #TOP )
|
||||
COND( c1, s( #cooper ) <> 0 )
|
||||
COND( c2, s( #fletcher ) <> 0 And 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 )
|
||||
|
||||
#N_CONDITIONS = 6
|
||||
|
||||
Global Dim conds ( #N_CONDITIONS - 1 )
|
||||
conds( 0 ) = @c0()
|
||||
conds( 1 ) = @c1()
|
||||
conds( 2 ) = @c2()
|
||||
conds( 3 ) = @c3()
|
||||
conds( 4 ) = @c4()
|
||||
conds( 5 ) = @c5()
|
||||
|
||||
Procedure solve ( person.i )
|
||||
Protected i.i, j.i
|
||||
If person = #phantom_of_the_opera
|
||||
For i = 0 To #N_CONDITIONS - 1
|
||||
Protected proc.condition = conds( i )
|
||||
If proc( solutions( ) )
|
||||
Continue
|
||||
EndIf
|
||||
If verbose
|
||||
For j = 0 To #N_FLOORS - 1
|
||||
PrintN( Str( solutions( j ) ) + " " + names( j ) )
|
||||
Next
|
||||
PrintN( "cond" + Str( i ) + " bad\n" )
|
||||
EndIf
|
||||
ProcedureReturn 0
|
||||
Next
|
||||
PrintN( "Found arrangement:" )
|
||||
For i = 0 To #N_FLOORS - 1
|
||||
PrintN( Str( solutions( i ) ) + " " + names( i ) )
|
||||
Next
|
||||
ProcedureReturn 1
|
||||
EndIf
|
||||
For i = 0 To #N_FLOORS - 1
|
||||
If occupied( i )
|
||||
Continue
|
||||
EndIf
|
||||
solutions( person ) = i
|
||||
occupied( i ) = #True
|
||||
If solve( person + 1 )
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
occupied( i ) = #False
|
||||
Next
|
||||
ProcedureReturn #False
|
||||
EndProcedure
|
||||
|
||||
|
||||
|
||||
OpenConsole( )
|
||||
|
||||
verbose = #False
|
||||
|
||||
If Not solve( 0 )
|
||||
PrintN( "Nobody lives anywhere" )
|
||||
EndIf
|
||||
|
||||
Input( )
|
||||
CloseConsole( )
|
||||
|
||||
End
|
||||
|
|
@ -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(x for x, y in sorted(zip(Names.strings, sol), key=lambda x: x[1])))
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
'''Dinesman's multiple-dwelling problem'''
|
||||
|
||||
from itertools import permutations
|
||||
|
||||
print([
|
||||
(
|
||||
'Baker on ' + str(b),
|
||||
'Cooper on ' + str(c),
|
||||
'Fletcher on ' + str(f),
|
||||
'Miller on ' + str(m),
|
||||
'Smith on ' + str(s)
|
||||
) for [b, c, f, m, s] in permutations(range(1, 6))
|
||||
if all([
|
||||
5 != b,
|
||||
1 != c,
|
||||
1 != f,
|
||||
5 != f,
|
||||
c < m,
|
||||
1 < abs(s - f),
|
||||
1 < abs(c - f)
|
||||
])
|
||||
])
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
'''Dinesman's multiple-dwelling problem'''
|
||||
|
||||
from itertools import chain, permutations
|
||||
|
||||
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Solution or null result.'''
|
||||
print(report(
|
||||
concatMap(dinesman)(
|
||||
permutations(range(1, 6))
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
# dinesman :: (Int, Int, Int, Int, Int) -> [(Int, Int, Int, Int, Int)]
|
||||
def dinesman(bcfms):
|
||||
'''A list containing the given permutation of five
|
||||
integers if it matches all the dinesman conditions,
|
||||
or an empty list if it does not.
|
||||
'''
|
||||
[b, c, f, m, s] = bcfms
|
||||
return [bcfms] if all([
|
||||
5 != b,
|
||||
1 != c,
|
||||
1 != f,
|
||||
5 != f,
|
||||
c < m,
|
||||
1 < abs(s - f),
|
||||
1 < abs(c - f)
|
||||
]) else []
|
||||
|
||||
|
||||
# report :: [(Int, Int, Int, Int, Int)] -> String
|
||||
def report(xs):
|
||||
'''A message summarizing the first (if any) solution found.
|
||||
'''
|
||||
return ', '.join(list(map(
|
||||
lambda k, n: k + ' in ' + str(n),
|
||||
['Baker', 'Cooper', 'Fletcher', 'Miller', 'Smith'],
|
||||
xs[0]
|
||||
))) + '.' if xs else 'No solution found.'
|
||||
|
||||
|
||||
# GENERAL -------------------------------------------------
|
||||
|
||||
# concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
def concatMap(f):
|
||||
'''A concatenated list over which a function has been mapped.
|
||||
The list monad can be derived by using a function f which
|
||||
wraps its output in a list,
|
||||
(using an empty list to represent computational failure).
|
||||
'''
|
||||
return lambda xs: list(
|
||||
chain.from_iterable(map(f, xs))
|
||||
)
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
names = unlist(strsplit("baker cooper fletcher miller smith", " "))
|
||||
|
||||
test <- function(floors) {
|
||||
f <- function(name) which(name == floors)
|
||||
if ((f('baker') != 5) &&
|
||||
(f('cooper') != 1) &&
|
||||
(any(f('fletcher') == 2:4)) &&
|
||||
(f('miller') > f('cooper')) &&
|
||||
(abs(f('fletcher') - f('cooper')) > 1) &&
|
||||
(abs(f('smith') - f('fletcher')) > 1))
|
||||
cat("\nFrom bottom to top: --> ", floors, "\n")
|
||||
}
|
||||
|
||||
do.perms <- function(seq, func, built = c()){
|
||||
if (0 == length(seq)) func(built)
|
||||
else for (x in seq) do.perms( seq[!seq==x], func, c(x, built)) }
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
> do.perms(names, test)
|
||||
From bottom to top: --> smith cooper baker fletcher miller
|
||||
|
||||
> system.time(do.perms(names, test))
|
||||
From bottom to top: --> smith cooper baker fletcher miller
|
||||
user system elapsed
|
||||
0 0 0
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*REXX program solves the Dinesman's multiple─dwelling problem with "natural" wording.*/
|
||||
names= 'Baker Cooper Fletcher Miller Smith' /*names of multiple─dwelling tenants. */
|
||||
#tenants= words(names) /*the number of tenants in the building*/
|
||||
floors= 5; top= floors; bottom= 1 /*floor 1 is the ground (bottom) floor.*/
|
||||
#= 0 /*the number of solutions found so far.*/
|
||||
do @.1=1 for floors /*iterate through all floors for rules.*/
|
||||
do @.2=1 for floors /* " " " " " " */
|
||||
do @.3=1 for floors /* " " " " " " */
|
||||
do @.4=1 for floors /* " " " " " " */
|
||||
do @.5=1 for floors /* " " " " " " */
|
||||
call set
|
||||
do j=1 for floors-1; a= @.j /* [↓] people don't live on same floor*/
|
||||
do k=j+1 to floors /*see if any people live on same floor.*/
|
||||
if a==@.k then iterate @.5 /*Is anyone cohabiting? Then not valid*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
call Waldo /* ◄══ where the rubber meets the road.*/
|
||||
end /*@.5*/
|
||||
end /*@.4*/
|
||||
end /*@.3*/
|
||||
end /*@.2*/
|
||||
end /*@.1*/
|
||||
|
||||
say 'found ' # " solution"s(#). /*display the number of solutions found*/
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
set: do p=1 for #tenants; call value word(names, p), @.p; end; return
|
||||
s: if arg(1)=1 then return ''; return "s" /*a simple pluralizer function.*/
|
||||
th: arg x; x=abs(x); return word('th st nd rd', 1 +x// 10* (x//100%10\==1)*(x//10<4))
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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
|
||||
#= # + 1 /* [↑] "|" is REXX's "or" comparator.*/
|
||||
say; do p=1 for #tenants; tenant= word(names, p)
|
||||
say right(tenant, 35) 'lives on the' @.p || th(@.p) "floor."
|
||||
end /*p*/ /* [↑] "||" is REXX's concatenation. */
|
||||
return /* [↑] show tenants in order in NAMES.*/
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#lang racket
|
||||
|
||||
;; A quick `amb' implementation
|
||||
(define fails '())
|
||||
(define (fail) (if (pair? fails) ((car fails)) (error "no more choices!")))
|
||||
(define (amb xs)
|
||||
(let/cc k (set! fails (cons k fails)))
|
||||
(if (pair? xs) (begin0 (car xs) (set! xs (cdr xs)))
|
||||
(begin (set! fails (cdr fails)) (fail))))
|
||||
(define (assert . conditions) (when (memq #f conditions) (fail)))
|
||||
|
||||
;; Convenient macro for definining problem items
|
||||
(define-syntax-rule (with: all (name ...) #:in choices body ...)
|
||||
(let* ([cs choices] [name (amb cs)] ... [all `([,name name] ...)]) body ...))
|
||||
|
||||
;; ===== problem translation starts here =====
|
||||
|
||||
;; Baker, Cooper, Fletcher, Miller, and Smith live on different floors
|
||||
;; of an apartment house that contains only five floors.
|
||||
(with: residents [Baker Cooper Fletcher Miller Smith] #:in (range 1 6)
|
||||
;; Some helpers
|
||||
(define (on-top x) (for/and ([y residents]) (x . >= . (car y))))
|
||||
(define (on-bottom x) (for/and ([y residents]) (x . <= . (car y))))
|
||||
(define (adjacent x y) (= 1 (abs (- x y))))
|
||||
(assert
|
||||
;; ... live on different floors ...
|
||||
(assert (= 5 (length (remove-duplicates (map car residents)))))
|
||||
;; Baker does not live on the top floor.
|
||||
(not (on-top Baker))
|
||||
;; Cooper does not live on the bottom floor.
|
||||
(not (on-bottom Cooper))
|
||||
;; Fletcher does not live on either the top or the bottom floor.
|
||||
(not (on-top Fletcher))
|
||||
(not (on-bottom Fletcher))
|
||||
;; Miller lives on a higher floor than does Cooper.
|
||||
(> Miller Cooper)
|
||||
;; Smith does not live on a floor adjacent to Fletcher's.
|
||||
(not (adjacent Smith Fletcher))
|
||||
;; Fletcher does not live on a floor adjacent to Cooper's.
|
||||
(assert (not (adjacent Fletcher Cooper))))
|
||||
;; Where does everyone live?
|
||||
(printf "Solution:\n")
|
||||
(for ([x (sort residents > #:key car)]) (apply printf " ~a. ~a\n" x)))
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
use MONKEY-SEE-NO-EVAL;
|
||||
|
||||
sub parse_and_solve ($text) {
|
||||
my %ids;
|
||||
my $expr = (grammar {
|
||||
state $c = 0;
|
||||
rule TOP { <fact>+ { make join ' && ', $<fact>>>.made } }
|
||||
|
||||
rule fact { <name> (not)? <position>
|
||||
{ make sprintf $<position>.made.fmt($0 ?? "!(%s)" !! "%s"),
|
||||
$<name>.made }
|
||||
}
|
||||
rule position {
|
||||
|| on bottom { make "\@f[%s] == 1" }
|
||||
|| on top { make "\@f[%s] == +\@f" }
|
||||
|| lower than <name> { make "\@f[%s] < \@f[{$<name>.made}]" }
|
||||
|| higher than <name> { make "\@f[%s] > \@f[{$<name>.made}]" }
|
||||
|| directly below <name> { make "\@f[%s] == \@f[{$<name>.made}] - 1" }
|
||||
|| directly above <name> { make "\@f[%s] == \@f[{$<name>.made}] + 1" }
|
||||
|| adjacent to <name> { make "\@f[%s] == \@f[{$<name>.made}] + (-1|1)" }
|
||||
|| on <ordinal> { make "\@f[%s] == {$<ordinal>.made}" }
|
||||
|| { note "Failed to parse line " ~ +$/.prematch.comb(/^^/); exit 1; }
|
||||
}
|
||||
|
||||
token name { :i <[a..z]>+ { make %ids{~$/} //= $c++ } }
|
||||
token ordinal { [1st | 2nd | 3rd | \d+th] { make +$/.match(/(\d+)/)[0] } }
|
||||
}).parse($text).made;
|
||||
|
||||
EVAL 'for [1..%ids.elems].permutations -> @f {
|
||||
say %ids.kv.map({ "$^a=@f[$^b]" }) if (' ~ $expr ~ ');
|
||||
}'
|
||||
}
|
||||
|
||||
parse_and_solve Q:to/END/;
|
||||
Baker not on top
|
||||
Cooper not on bottom
|
||||
Fletcher not on top
|
||||
Fletcher not on bottom
|
||||
Miller higher than Cooper
|
||||
Smith not adjacent to Fletcher
|
||||
Fletcher not adjacent to Cooper
|
||||
END
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Contains only five floors. 5! = 120 permutations.
|
||||
for (flat (1..5).permutations) -> $b, $c, $f, $m, $s {
|
||||
say "Baker=$b Cooper=$c Fletcher=$f Miller=$m Smith=$s"
|
||||
if $b != 5 # Baker !live on top floor.
|
||||
and $c != 1 # Cooper !live on bottom floor.
|
||||
and $f != 1|5 # Fletcher !live on top or the bottom floor.
|
||||
and $m > $c # Miller lives on a higher floor than Cooper.
|
||||
and $s != $f-1|$f+1 # Smith !live adjacent to Fletcher
|
||||
and $f != $c-1|$c+1 # Fletcher !live adjacent to Cooper
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
floor1 = "return 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"
|
||||
floor2 = "return baker!=4"
|
||||
floor3 = "return cooper!=0"
|
||||
floor4 = "return fletcher!=0 and fletcher!=4"
|
||||
floor5 = "return miller>cooper"
|
||||
floor6 = "return fabs(smith-fletcher)!=1"
|
||||
floor7 = "return fabs(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(floor2) if eval(floor3) if eval(floor5)
|
||||
if eval(floor4) if eval(floor6) if eval(floor7)
|
||||
if eval(floor1)
|
||||
see "baker lives on floor " + baker + nl
|
||||
see "cooper lives on floor " + cooper + nl
|
||||
see "fletcher lives on floor " + fletcher + nl
|
||||
see "miller lives on floor " + miller + nl
|
||||
see "smith lives on floor " + smith + nl ok ok ok ok ok ok ok
|
||||
next
|
||||
next
|
||||
next
|
||||
next
|
||||
next
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
def solve( problem )
|
||||
lines = problem.split(".")
|
||||
names = lines.first.scan( /[A-Z]\w*/ )
|
||||
re_names = Regexp.union( names )
|
||||
# Later on, search for these keywords (the word "not" is handled separately).
|
||||
words = %w(first second third fourth fifth sixth seventh eighth ninth tenth
|
||||
bottom top higher lower adjacent)
|
||||
re_keywords = Regexp.union( words )
|
||||
|
||||
predicates = lines[1..-2].flat_map do |line| #build an array of lambda's
|
||||
keywords = line.scan( re_keywords )
|
||||
name1, name2 = line.scan( re_names )
|
||||
keywords.map do |keyword|
|
||||
l = case keyword
|
||||
when "bottom" then ->(c){ c.first == name1 }
|
||||
when "top" then ->(c){ c.last == name1 }
|
||||
when "higher" then ->(c){ c.index( name1 ) > c.index( name2 ) }
|
||||
when "lower" then ->(c){ c.index( name1 ) < c.index( name2 ) }
|
||||
when "adjacent" then ->(c){ (c.index( name1 ) - c.index( name2 )).abs == 1 }
|
||||
else ->(c){ c[words.index(keyword)] == name1 }
|
||||
end
|
||||
line =~ /\bnot\b/ ? ->(c){not l.call(c) } : l # handle "not"
|
||||
end
|
||||
end
|
||||
|
||||
names.permutation.detect{|candidate| predicates.all?{|predicate| predicate.(candidate)}}
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#Direct positional words like top, bottom, first, second etc. can be combined; they refer to one name.
|
||||
#The relative positional words higher, lower and adjacent can be combined; they need two names, not positions.
|
||||
|
||||
demo1 = "Abe Ben Charlie David. Abe not second top. not adjacent Ben Charlie.
|
||||
David Abe adjacent. David adjacent Ben. Last line."
|
||||
|
||||
demo2 = "A B C D. A not adjacent D. not B adjacent higher C. C lower D. Last line"
|
||||
|
||||
problem1 = "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?"
|
||||
|
||||
# from the Python version:
|
||||
problem2 = "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?"
|
||||
|
||||
[demo1, demo2, problem1, problem2].each{|problem| puts solve( problem ) ;puts }
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
names = %i( Baker Cooper Fletcher Miller Smith )
|
||||
|
||||
predicates = [->(c){ :Baker != c.last },
|
||||
->(c){ :Cooper != c.first },
|
||||
->(c){ :Fletcher != c.first && :Fletcher != c.last },
|
||||
->(c){ c.index(:Miller) > c.index(:Cooper) },
|
||||
->(c){ (c.index(:Smith) - c.index(:Fletcher)).abs != 1 },
|
||||
->(c){ (c.index(:Cooper) - c.index(:Fletcher)).abs != 1 }]
|
||||
|
||||
puts names.permutation.detect{|candidate| predicates.all?{|predicate| predicate.call(candidate)}}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
N = %w(Baker Cooper Fletcher Miller Smith)
|
||||
b,c,f,m,s = N
|
||||
|
||||
N.permutation.map{|a| a.join " "}.
|
||||
grep(/(?=.*#{b}.)
|
||||
(?=.+#{c})
|
||||
(?=.+#{f}.)
|
||||
(?=.*#{c}.*#{m})
|
||||
(?=.*(#{f}..+#{s}|#{s}..+#{f}))
|
||||
(?=.*(#{f}..+#{c}|#{c}..+#{f}))/x).
|
||||
first
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
for baler = 1 to 4 ' can not be in room 5
|
||||
for cooper = 2 to 5 ' can not be in room 1
|
||||
for fletcher = 2 to 4 ' can not be in room 1 or 5
|
||||
for miller = 1 to 5 ' can be in any room
|
||||
for smith = 1 to 5 ' can be in any room
|
||||
if baler <> cooper and fletcher <> miller and miller > cooper and abs(smith - fletcher) > 1 and abs(fletcher - cooper) > 1 then
|
||||
if baler + cooper + fletcher + miller + smith = 15 then ' that is 1 + 2 + 3 + 4 + 5
|
||||
rooms$ = baler;cooper;fletcher;miller;smith
|
||||
print "baler: ";baler;" copper: ";cooper;" fletcher: ";fletcher;" miller: ";miller;" smith: ";smith
|
||||
end
|
||||
end if
|
||||
end if
|
||||
next smith
|
||||
next miller
|
||||
next fletcher
|
||||
next cooper
|
||||
next baler
|
||||
print "Can't assign rooms" ' print this if it can not find a solution
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import scala.math.abs
|
||||
|
||||
object Dinesman3 extends App {
|
||||
val tenants = List("Baker", "Cooper2", "Fletcher4", "Miller", "Smith")
|
||||
val (groundFloor, topFloor) = (1, tenants.size)
|
||||
|
||||
/** Rules with related tenants and restrictions*/
|
||||
val exclusions =
|
||||
List((suggestedFloor0: Map[String, Int]) => suggestedFloor0("Baker") != topFloor,
|
||||
(suggestedFloor1: Map[String, Int]) => suggestedFloor1("Cooper2") != groundFloor,
|
||||
(suggestedFloor2: Map[String, Int]) => !List(groundFloor, topFloor).contains(suggestedFloor2("Fletcher4")),
|
||||
(suggestedFloor3: Map[String, Int]) => suggestedFloor3("Miller") > suggestedFloor3("Cooper2"),
|
||||
(suggestedFloor4: Map[String, Int]) => abs(suggestedFloor4("Smith") - suggestedFloor4("Fletcher4")) != 1,
|
||||
(suggestedFloor5: Map[String, Int]) => abs(suggestedFloor5("Fletcher4") - suggestedFloor5("Cooper2")) != 1)
|
||||
|
||||
tenants.permutations.map(_ zip (groundFloor to topFloor)).
|
||||
filter(p => exclusions.forall(_(p.toMap))).toList match {
|
||||
case Nil => println("No solution")
|
||||
case xss => {
|
||||
println(s"Solutions: ${xss.size}")
|
||||
xss.foreach { l =>
|
||||
println("possible solution:")
|
||||
l.foreach(p => println(f"${p._1}%11s lives on floor number ${p._2}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import scala.math.abs
|
||||
|
||||
object Dinesman3 extends App {
|
||||
val tenants = List("Baker", "Cooper2", "Fletcher4", "Miller", "Rollo5", "Smith")
|
||||
val (groundFloor, topFloor) = (1, tenants.size)
|
||||
|
||||
/** Rules with related tenants and restrictions*/
|
||||
val exclusions =
|
||||
List((suggestedFloor0: Map[String, Int]) => suggestedFloor0("Baker") != topFloor,
|
||||
(suggestedFloor1: Map[String, Int]) => suggestedFloor1("Cooper2") != groundFloor,
|
||||
(suggestedFloor2: Map[String, Int]) => !List(groundFloor, topFloor).contains(suggestedFloor2("Fletcher4")),
|
||||
(suggestedFloor3: Map[String, Int]) => suggestedFloor3("Miller") > suggestedFloor3("Cooper2"),
|
||||
(suggestedFloor4: Map[String, Int]) => abs(suggestedFloor4("Smith") - suggestedFloor4("Fletcher4")) != 1,
|
||||
(suggestedFloor5: Map[String, Int]) => abs(suggestedFloor5("Fletcher4") - suggestedFloor5("Cooper2")) != 1,
|
||||
|
||||
(suggestedFloor6: Map[String, Int]) => !List(3, 4, topFloor).contains(suggestedFloor6("Rollo5")),
|
||||
(suggestedFloor7: Map[String, Int]) => suggestedFloor7("Rollo5") < suggestedFloor7("Smith"),
|
||||
(suggestedFloor8: Map[String, Int]) => suggestedFloor8("Rollo5") > suggestedFloor8("Fletcher4"))
|
||||
|
||||
tenants.permutations.map(_ zip (groundFloor to topFloor)).
|
||||
filter(p => exclusions.forall(_(p.toMap))).toList match {
|
||||
case Nil => println("No solution")
|
||||
case xss => {
|
||||
println(s"Solutions: ${xss.size}")
|
||||
xss.foreach { l =>
|
||||
println("possible solution:")
|
||||
l.foreach(p => println(f"${p._1}%11s lives on floor number ${p._2}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import scala.math.abs
|
||||
|
||||
object Dinesman2 extends App {
|
||||
val groundFloor = 1
|
||||
|
||||
abstract class Rule(val person: String) { val exclusion: Map[String, Int] => Boolean }
|
||||
|
||||
/** Rules with related tenants and restrictions*/
|
||||
def rulesDef(topFloor: Int) = List(
|
||||
new Rule("Baker") { val exclusion = (_: Map[String, Int])(person) != topFloor },
|
||||
new Rule("Cooper2") { val exclusion = (_: Map[String, Int])(person) != groundFloor },
|
||||
new Rule("Fletcher4") {
|
||||
val exclusion = (suggestedFloor2: Map[String, Int]) => !List(groundFloor, topFloor).contains(suggestedFloor2(person))
|
||||
}, new Rule("Miller") {
|
||||
val exclusion = (suggestedFloor3: Map[String, Int]) => suggestedFloor3(person) > suggestedFloor3("Cooper2")
|
||||
}, new Rule("Smith") {
|
||||
val exclusion = (suggestedFloor4: Map[String, Int]) => abs(suggestedFloor4(person) - suggestedFloor4("Fletcher4")) != 1
|
||||
}, new Rule("Fletcher4") {
|
||||
val exclusion = (suggestedFloor5: Map[String, Int]) => abs(suggestedFloor5(person) - suggestedFloor5("Cooper2")) != 1
|
||||
})
|
||||
|
||||
def extensionDef(topFloor: Int) = List(new Rule("Rollo5") {
|
||||
val exclusion = (suggestedFloor6: Map[String, Int]) => !List(3, 4, topFloor).contains((suggestedFloor6: Map[String, Int])(person))
|
||||
}, new Rule("Rollo5") {
|
||||
val exclusion = (suggestedFloor7: Map[String, Int]) => suggestedFloor7(person) < suggestedFloor7("Smith")
|
||||
}, new Rule("Rollo5") {
|
||||
val exclusion = (suggestedFloor8: Map[String, Int]) => suggestedFloor8(person) > suggestedFloor8("Fletcher4")
|
||||
})
|
||||
|
||||
def allRulesDef(topFloor: Int) = rulesDef(topFloor) ++ extensionDef(topFloor)
|
||||
|
||||
val tenants = allRulesDef(0).map(_.person).distinct // Pilot balloon to get # of tenants
|
||||
val topFloor = tenants.size
|
||||
val exclusions = allRulesDef(topFloor).map(_.exclusion)
|
||||
|
||||
tenants.permutations.map(_ zip (groundFloor to topFloor)).
|
||||
filter(p => exclusions.forall(_(p.toMap))).toList match {
|
||||
case Nil => println("No solution")
|
||||
case xss => {
|
||||
println(s"Solutions: ${xss.size}")
|
||||
xss.foreach { l =>
|
||||
println("possible solution:")
|
||||
l.foreach(p => println(f"${p._1}%11s lives on floor number ${p._2}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
func dinesman(problem) {
|
||||
var lines = problem.split('.')
|
||||
var names = lines.first.scan(/\b[A-Z]\w*/)
|
||||
var re_names = Regex(names.join('|'))
|
||||
|
||||
# Later on, search for these keywords (the word "not" is handled separately).
|
||||
var words = %w(first second third fourth fifth sixth seventh eighth ninth tenth
|
||||
bottom top higher lower adjacent)
|
||||
var re_keywords = Regex(words.join('|'))
|
||||
|
||||
# Build an array of lambda's
|
||||
var predicates = lines.ft(1, lines.end-1).map{ |line|
|
||||
var keywords = line.scan(re_keywords)
|
||||
var (name1, name2) = line.scan(re_names)...
|
||||
|
||||
keywords.map{ |keyword|
|
||||
var l = do {
|
||||
given(keyword) {
|
||||
when ("bottom") { ->(c) { c.first == name1 } }
|
||||
when ("top") { ->(c) { c.last == name1 } }
|
||||
when ("higher") { ->(c) { c.index(name1) > c.index(name2) } }
|
||||
when ("lower") { ->(c) { c.index(name1) < c.index(name2) } }
|
||||
when ("adjacent") { ->(c) { c.index(name1) - c.index(name2) -> abs == 1 } }
|
||||
default { ->(c) { c[words.index(keyword)] == name1 } }
|
||||
}
|
||||
}
|
||||
line ~~ /\bnot\b/ ? func(c) { l(c) -> not } : l; # handle "not"
|
||||
}
|
||||
}.flat
|
||||
|
||||
names.permutations { |*candidate|
|
||||
predicates.all { |predicate| predicate(candidate) } && return candidate
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
var demo1 = "Abe Ben Charlie David. Abe not second top. not adjacent Ben Charlie.
|
||||
David Abe adjacent. David adjacent Ben. Last line."
|
||||
|
||||
var demo2 = "A B C D. A not adjacent D. not B adjacent higher C. C lower D. Last line"
|
||||
|
||||
var problem1 = "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?"
|
||||
|
||||
var problem2 = "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?"
|
||||
|
||||
[demo1, demo2, problem1, problem2].each{|problem| say dinesman(problem).join("\n"); say '' }
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue