Hello

Forth

"Einstein's Riddle"

\ er.f  "Einstein's Riddle" - Leo Wong  12-23 March 2001 +
\ Solves who owns the fish

\ macro by Neil Bawd
: macro  ( "name <char> ccc<char>" -- )
   : char parse  postpone sliteral  postpone evaluate  postpone ;
   immediate ;

: n!  ( n -- n! )  dup 2 < if drop 1 exit then  dup 1- recurse * ;
\ Permutations after Er Hersom, Forthwrite, Issue 109, November 2000
0 value #items
: ,perm   ( -- )  #items 0 ?do i pick c, loop ;
: perm  ( <items> #items -- <items> #items )
   dup 1 = if  >r ,perm r>
   else dup 0 do >r  r@ 1- recurse  roll r> loop then ;
: drops  ( n -- )  0 ?do drop loop ;
: permutations
   create  ( <items> #items -- )
    dup n! ,  dup c,  dup to #items  perm  #items 1+ drops
   does>  ( n -- n a #perms )  dup @ >r cell+ count chars swap r> ;

0 1 2 3 4  5 permutations perms 

: string,  ( a u -- )  dup c, 0 do count c, loop drop ;
: spells  ( a u -- a' )  create here >r  0 c,  string,  r> ;
: ,s  ( x1 ... xn n -- )  begin ?dup while dup roll , 1- repeat ;
: category  ( x1 x2 x3 x4 x5 -- )  create  5 ,s ;

\ colors
s" yellow" spells yellow
s" blue" spells blue
s" red" spells red
s" green" spells green
s" white" spells white  category colors

\ nationalities
s" Brit" spells brit
s" Dane" spells dane
s" Norwegian" spells norwegian
s" German" spells german
s" Swede" spells swede  category nationalities

\ drinks
s" beer" spells beer
s" milk" spells milk
s" tea" spells tea
s" coffee" spells coffee
s" water" spells water  category drinks

\ smokes
s" Blaumeister" spells blaumeister
s" blends" spells blends
s" Dunhill" spells dunhill
s" Prince" spells prince 
s" Pall Mall" spells pallmall  category smokes

\ pets
s" birds" spells birds
s" cats" spells cats
s" dogs" spells dogs
s" fish" spells fish
s" horse" spells horse  category pets

2 milk c!                \ hint 8
0 norwegian c!           \ hint 9
norwegian c@ 1+ blue c!  \ hint 14

: colors!  ( permutation -- colors ) 
   count red c!  count yellow c!  c@ dup green c!
   1+ white c!  \ hint 4
   colors ;

: nationalities!  ( permutation -- nationalities )
   count dane c!  count german c!  c@ swede c!
   red c@ brit c!  \ hint 1
   nationalities ;

: drinks!  ( permutation -- drinks )
   count beer c!  c@ water c! 
   dane c@ tea c!      \ hint 3
   green c@ coffee c!  \ hint 5
   drinks ;

: smokes!  ( permutation -- smokes )
   count blends c!  c@ pallmall c!
   yellow c@ dunhill c!    \ hint 7
   beer c@ blaumeister c!  \ hint 12
   german c@ prince c!     \ hint 13
   smokes ;

: pets!  ( permutation -- pets )
   count cats c!  count fish c!  c@ horse c!
   swede c@ dogs c!      \ hint 2
   pallmall c@ birds c!  \ hint 6
   pets ;

create board 6 chars allot
: c++  ( a -- )  dup c@ 1+ swap c! ;
: scan  ( ca1 u1 c -- ca2 u2 )
   >r
   begin dup while over c@ r@ <> while 1 /string repeat then
   r> drop ;
: placed  ( category -- ? )
   board 5 0 fill
   5 0 do dup @ c@ chars board + c++ cell+ loop drop
   board 5 0 scan nip 0= ;

macro ?no " ( a1 a2 -- )  - if false exit then"
: constraints  ( -- ? )
\  (  1 ) brit c@ red c@ ?no
\  (  2 ) swede c@ dogs c@ ?no
\  (  3 ) dane c@ tea c@ ?no
\  (  4 ) green c@ white c@ 1- ?no
\  (  5 ) green c@ coffee c@ ?no
\  (  6 ) pallmall c@ birds c@ ?no
\  (  7 ) yellow c@ dunhill c@ ?no
\  (  8 ) milk c@ 2 ?no
\  (  9 ) norwegian c@ 0 ?no
   ( 10 ) blends c@ cats c@ - abs 1 ?no
   ( 11 ) horse c@ dunhill c@ - abs 1 ?no
\  ( 12 ) blaumeister c@ beer c@ ?no
\  ( 13 ) german c@ prince c@ ?no
\  ( 14 ) norwegian c@ blue c@ - abs 1 ?no
   ( 15 ) blends c@ water c@ - abs 1 ?no
   true ;

: .spell  ( a -- )  count type space ;
: .nth  ( n category -- )
   5 0 do
     2dup @ count rot = if .spell leave else drop then cell+
   loop 2drop ;
: .solution  ( -- )
   CR ." The " fish c@ nationalities .nth ." owns the fish." 

macro perms{ " ( -- n a a )  perms 0 do dup"
macro }perms " ( n a -- )  over + loop 2drop"
macro unloops " ( n -- )  begin ?dup while unloop 1- repeat"

: er  ( -- )  \ Einstein's riddle
   perms{ colors!  placed if
      perms{ nationalities!  placed if
         perms{ drinks!  placed if
            perms{ smokes!  placed if
               perms{ pets!  placed if 
                  constraints if 
                        .solution  10 drops  5 unloops  exit
                     then
                  then    
               }perms then 
            }perms then
         }perms then
      }perms then
   }perms ;

er

Leo Wong hello@albany.net

Forth

Hello