Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,8 +1,18 @@
The task is to '''solve Dinesman's multiple dwelling [http://www-mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 problem] but in a way that most naturally follows the problem statement given below'''. Solutions are allowed (but not required) to parse and interpret the problem text, but should remain flexible and should state what changes to the problem text are allowed. Flexibility and ease of expression are valued.
{{omit from|GUISS}}
The task is to '''solve Dinesman's multiple dwelling [http://www-mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.2 problem] but in a way that most naturally follows the problem statement given below'''.
Solutions are allowed (but not required) to parse and interpret the problem text, but should remain flexible and should state what changes to the problem text are allowed. Flexibility and ease of expression are valued.
Examples may be be split into "setup", "problem statement", and "output" sections where the ease and naturalness of stating the problem and getting an answer, as well as the ease and flexibility of modifying the problem are the primary concerns.
Example output should be shown here, as well as any comments on the examples flexibility.
;The problem:
:''Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?''
:Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors.
:Baker does not live on the top floor.
:Cooper does not live on the bottom floor.
:Fletcher does not live on either the top or the bottom floor.
:Miller lives on a higher floor than does Cooper.
:Smith does not live on a floor adjacent to Fletcher's.
:Fletcher does not live on a floor adjacent to Cooper's.
:''Where does everyone live?''

View file

@ -0,0 +1,2 @@
---
note: Dinesman's multiple-dwelling problem

View file

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

View file

@ -1,6 +1,6 @@
import std.stdio, std.math, std.algorithm, permutations2;
void main() {
import std.stdio, std.math, std.algorithm, permutations2;
["Baker", "Cooper", "Fletcher", "Miller", "Smith"]
.permutations
.filter!(s =>

View file

@ -0,0 +1,39 @@
sub parse_and_solve ($text) {
my %ids;
my $expr = (grammar {
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{~$/} //= (state $)++ } }
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

View file

@ -1,20 +1,5 @@
sub next_perm ( @a is copy ) {
my $j = @a.end - 1;
return Nil if --$j < 0 while [>] @a[ $j, $j+1 ];
my $aj = @a[$j];
my $k = @a.end;
$k-- while [>] $aj, @a[$k];
@a[ $j, $k ] .= reverse;
my $r = @a.end;
my $s = $j + 1;
@a[ $r--, $s++ ] .= reverse while $r > $s;
return @a;
}
# Contains only five floors. 5! = 120 permutations.
for [1..5], &next_perm ...^ !* -> [ $b, $c, $f, $m, $s ] {
for [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.

View file

@ -0,0 +1,55 @@
use strict;
use warnings;
use feature qw(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}};
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 'no warnings "numeric";
permute {
say join(", ", pairmap { "$f[$b] $a" } %ids)
if ('.join(' && ', @expressions).');
} @f;';
}

View file

@ -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

View file

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

View file

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

View file

@ -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}"))
}
}
}
}