2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,5 +1,7 @@
|
|||
{{omit from|GUISS}}
|
||||
The task is to '''solve Dinesman's multiple dwelling [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 problem] but in a way that most naturally follows the problem statement given below'''.
|
||||
|
||||
;Task
|
||||
Solve Dinesman's multiple dwelling [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 problem] but in a way that most naturally follows the problem statement given below.
|
||||
|
||||
Solutions are allowed (but not required) to parse and interpret the problem text, but should remain flexible and should state what changes to the problem text are allowed. Flexibility and ease of expression are valued.
|
||||
|
||||
|
|
@ -7,12 +9,14 @@ Examples may be be split into "setup", "problem statement", and "output" section
|
|||
|
||||
Example output should be shown here, as well as any comments on the examples flexibility.
|
||||
|
||||
;The problem:
|
||||
:Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors.
|
||||
:Baker does not live on the top floor.
|
||||
:Cooper does not live on the bottom floor.
|
||||
:Fletcher does not live on either the top or the bottom floor.
|
||||
:Miller lives on a higher floor than does Cooper.
|
||||
:Smith does not live on a floor adjacent to Fletcher's.
|
||||
:Fletcher does not live on a floor adjacent to Cooper's.
|
||||
:''Where does everyone live?''
|
||||
|
||||
;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.<br><br>
|
||||
''Where does everyone live?''<br>
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -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,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,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)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +1,6 @@
|
|||
import Data.List (permutations)
|
||||
main = print [ (b,c,f,m,s) | [b,c,f,m,s] <- permutations [1..5], b/=5,c/=1,f/=1,f/=5,m>c,abs(s-f)>1,abs(c-f)>1]
|
||||
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,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}]
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
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>
|
||||
|
|
@ -19,7 +22,7 @@ sub parse_and_solve ($text) {
|
|||
|| { note "Failed to parse line " ~ +$/.prematch.comb(/^^/); exit 1; }
|
||||
}
|
||||
|
||||
token name { :i <[a..z]>+ { make %ids{~$/} //= (state $)++ } }
|
||||
token name { :i <[a..z]>+ { make %ids{~$/} //= $c++ } }
|
||||
token ordinal { [1st | 2nd | 3rd | \d+th] { make +$/.match(/(\d+)/)[0] } }
|
||||
}).parse($text).made;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,32 +1,32 @@
|
|||
/*REXX pgm: Dinesman's multiple-dwelling problem with "natural" wording.*/
|
||||
names= 'Baker Cooper Fletcher Miller Smith' /*names of the tenants.*/
|
||||
floors=5; top=floors; bottom=1; #=floors; sols=0
|
||||
/*floor 1 is the ground floor. */
|
||||
do !.1=1 for #;do !.2=1 for #;do !.3=1 for #;do !.4=1 for #;do !.5=1 for #
|
||||
do p=1 for words(names); _=word(names,p); upper _; call value _,!.p
|
||||
end /*p*/
|
||||
/* [↓] don't live on same floor.*/
|
||||
do j=1 for #-1; do k=j+1 to #; if !.j==!.k then iterate !.5; end;end
|
||||
/*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; #=floors; /*floor 1 is the ground (bottom) floor.*/
|
||||
sols=0
|
||||
do !.1=1 for #; do !.2=1 for #; do !.3=1 for #; do !.4=1 for #; do !.5=1 for #
|
||||
do p=1 for tenants; _=word(names,p); upper _; call value _, !.p
|
||||
end /*p*/
|
||||
do j=1 for #-1 /* [↓] people don't live on same floor*/
|
||||
do k=j+1 to #; if !.j==!.k then iterate !.5 /*cohab?*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
call Waldo /* ◄══ where the rubber meets the road.*/
|
||||
end; end; end; end; end /*!.5 & !.4 & !.3 & !.2 & !.1*/
|
||||
|
||||
call Waldo /* ◄───────────────────where the rubber meets the road.*/
|
||||
end /*!.5*/; end /*!.4*/; end /*!.3*/; end /*!.2*/; end /*!.1*/
|
||||
|
||||
say; say 'found' sols "solution"s(sols)'.'
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────Waldo subroutine────────────────────*/
|
||||
Waldo:
|
||||
if Baker == top then return
|
||||
if Cooper == bottom then return
|
||||
if Fletcher == bottom | Fletcher == top then return
|
||||
if Miller \> Cooper then return
|
||||
if Smith == Fletcher-1 | Smith == Fletcher+1 then return
|
||||
if Fletcher == Cooper-1 | Fletcher == Cooper+1 then return
|
||||
|
||||
say; sols=sols+1 /*list tenants in order in list. */
|
||||
do p=1 for words(names); _=word(names,p)
|
||||
say right(_,20) 'lives on the' !.p||th(!.p) "floor."
|
||||
end /*p*/
|
||||
return
|
||||
/*──────────────────────────────────one-liner subroutines───────────────*/
|
||||
s: if arg(1)=1 then return ''; return 's' /*a simple pluralizer funct.*/
|
||||
th:procedure;parse arg x;x=abs(x);return word('th st nd rd',1+x//10*(x//100%10\==1)*(x//10<4))
|
||||
say 'found' sols "solution"s(sols). /*display the number of solutions found*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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
|
||||
sols=sols+1
|
||||
say; do p=1 for tenants; tenant=right( word(names, p), 30)
|
||||
say tenant 'lives on the' !.p || th(!.p) "floor."
|
||||
end /*p*/
|
||||
return /* [↑] show tenants in order in NAMES.*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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))
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
people$ = "Baler,Cooper,Fletcher,Miller,Smith"
|
||||
|
||||
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 miller > cooper and abs(smith - fletcher) > 1 and abs(fletcher - cooper) > 1 then
|
||||
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
|
||||
bad = 0
|
||||
for i = 1 to 5 ' make sure each room is unique
|
||||
rm$ = chr$(i + 48)
|
||||
r1 = instr(rooms$,rm$)
|
||||
r2 = instr(rooms$,rm$,r1+1)
|
||||
if r2 <> 0 then bad = 1
|
||||
next i
|
||||
if bad = 0 then goto [roomAssgn] ' if it is not bad it is a good assignment
|
||||
print "baler: ";baler;" copper: ";cooper;" fletcher: ";fletcher;" miller: ";miller;" smith: ";smith
|
||||
end
|
||||
end if
|
||||
end if
|
||||
next smith
|
||||
|
|
@ -23,11 +15,4 @@ for baler = 1 to 4 ' can not be in r
|
|||
next fletcher
|
||||
next cooper
|
||||
next baler
|
||||
print "Cam't assign rooms" ' print this if it can not find a solution
|
||||
wait
|
||||
|
||||
[roomAssgn]
|
||||
Print "Room Assignment"
|
||||
for i = 1 to 5
|
||||
print mid$(rooms$,i,1);" ";word$(people$,i,",");" "; ' print the room assignments
|
||||
next i
|
||||
print "Can't assign rooms" ' print this if it can not find a solution
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
10 REM Floors are numbered 0 (ground) to 4 (top)
|
||||
20 REM "Baker, Cooper, Fletcher, Miller, and Smith live on different floors":
|
||||
30 REM "Baker does not live on the top floor"
|
||||
40 REM "Cooper does not live on the bottom floor"
|
||||
50 REM "Fletcher does not live on either the top or the bottom floor"
|
||||
60 REM "Miller lives on a higher floor than does Cooper"
|
||||
70 REM "Smith does not live on a floor adjacent to Fletcher's"
|
||||
80 REM "Fletcher does not live on a floor adjacent to Cooper's"
|
||||
90 FOR b=0 TO 4: FOR c=0 TO 4: FOR f=0 TO 4: FOR m=0 TO 4: FOR s=0 TO 4
|
||||
100 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 B<>4 AND C<>0 AND F<>0 AND F<>4 AND M>C AND ABS (S-F)<>1 AND ABS (F-C)<>1 THEN PRINT "Baker lives on floor ";b: PRINT "Cooper lives on floor ";c: PRINT "Fletcher lives on floor ";f: PRINT "Miller lives on floor ";m: PRINT "Smith lives on floor ";s: STOP
|
||||
110 NEXT s: NEXT m: NEXT f: NEXT c: NEXT b
|
||||
Loading…
Add table
Add a link
Reference in a new issue