(****************************************************************************** * SNU 4190.310 Programming Languages (Fall 2006) * * HW 5: readings, treasure island ******************************************************************************) (****************************************************************************** * Exercise 2. * treasure island ******************************************************************************) type treasurebox = Star | Name of string type key = Bar | Node of key * key type map = End of treasurebox | Branch of map * map | Guide of string * map /// ÀÚÁÖ ¾µ °Íµé // ÇÕ¼º ÇÔ¼ö fun (@@) g f = (fn x => g (f x)) // ¸®½ºÆ®ÀÇ À¯ÀÏÇÑ ¿ø¼Òµé fun unique l = List.fold_left (fn (x::l) y => if x = y then x::l else y::x::l | [] y => [y]) [] (List.sort compare l) /// º¸¹°»óÀÚµé°ú À̵éÀ» ¿­±â À§ÇÑ Á¦¾àµéÀ» ´©ÀûÇÑ ¿­¼è¸ð¾çÇ¥¸¦ ±¸ÇÏ´Â ºÎºÐ. // ¿­¼è¸ð¾çÀº ¿­¼è(key) ŸÀÔ¿¡ º¸¹°»óÀÚ¸¦ ¿­±â À§ÇÑ ¿­¼è Á¤º¸(KEY)¿Í // ¾ÆÁ÷ ¸ð¸£´Â ¿­¼è¸¦ ¹ÌÁö¼ö·Î ³õ°í Ç®±â À§ÇÑ Á¤º¸(UNKNOWN)¸¦ Ãß°¡ÇÑ °Í. type keyshape = BAR | KEY of string | UNKNOWN of int | NODE of keyshape * keyshape (* ¿­¼è¸ð¾çÇ¥´Â ¾î¶² ¿­¼è¸ð¾çÀ» ´Ù¸¥ ¿­¼è¸ð¾çÀ¸·Î ¹Ù²ãÄ¡±âÇÒ ¼ö ÀÖ´Ù´Â Á¦¾àÀ» ±â¾ïÇÏ¿© ¿­¼è¸ð¾çÀ» ¹Þ¾Æ¼­ ¸ðµÎ ¹Ù²ãÄ¡±âÇÑ ¿­¼è¸ð¾çÀ» µ¹·ÁÁÖ´Â ÇÔ¼öÀÌ´Ù. *) type subst = keyshape -> keyshape // »õ ¿­¼è¸ð¾çÇ¥ ¸¸µé±â fun subst x key = let fun s k = ( case k of BAR => BAR | KEY _ | UNKNOWN _ => if x = k then key else k | NODE (k1, k2) => NODE (s k1, s k2) ) in s end fun id key = key // ¿­¼è¸ð¾ç x°¡ ¿­¼è¸ð¾ç key¼Ó¿¡ ³ªÅ¸³ª´ÂÁö °Ë»ç fun occurs x key = (case key of BAR => false | KEY _ | UNKNOWN _ => x = key | NODE (k1, k2) => occurs x k1 orelse occurs x k2 ) (* mustbe: keyshape -> keyshape -> subst µÎ ¿­¼è¸ð¾çÀÌ °°´Ù°í ÇÒ ¶§ÀÇ Á¦¾àÀ» °¡ÇÏ´Â ¿­¼è¸ð¾çÇ¥. µÎ ¿­¼è¸ð¾çÀÌ °°À» ¼ö ¾øÀ¸¸é Not_found ¿¹¿Ü ¹ß»ý. *) fun mustbe BAR BAR = id | mustbe NODE (k1, k2) NODE (k1', k2') = let val s1 = mustbe k1 k1' val s2 = mustbe (s1 k2) (s1 k2') in s2 @@ s1 end | mustbe (x as (KEY _ | UNKNOWN _)) key = if x = key then id else if occurs x key then raise Not_found else subst x key | mustbe key (x as (KEY _ | UNKNOWN _)) = mustbe x key | mustbe _ _ = raise Not_found // ¸ð¸£´Â ¿­¼è¸ð¾ç val keyshapeid = ref 0 fun some_keyshape () = keyshapeid++; UNKNOWN !keyshapeid // ¾È³»Ã¥ type guide = string -> keyshape val emptyGuide = fn _ => some_keyshape () // ¾È³»ÆÇÀÌ ¾ø¾ú´ø º¸¹°Àº Ç×»ó // »õ·Î¿î ¿­¼è·Î ¿­ ¼ö ÀÖ´Ù°í °¡Á¤. fun put guide x keyshape = (fn y => if y = x then keyshape else guide y) fun wrap subst guide = (fn x => subst (guide x)) (* see: guide -> map -> keyshape -> (treasurebox list * subst) ¾È³»Ã¥ guide°¡ ÀÖ°í, Áöµµ mapÀÇ ÇöÀç À§Ä¡°¡ ¾Ï½ÃÇÏ´Â ¿­¼è¸ð¾çÀÌ myselfÀ̸é, ¿­¾î¾ß ÇÒ º¸¹°»óÀÚµé°ú ¿­¼è¸ð¾çÇ¥´Â see guide map myself. *) fun see guide map myself = (case map of End box => ([box], case box of Star => mustbe BAR myself | Name x => (mustbe (guide x) myself) @@ (mustbe KEY x myself) ) | Guide (x, e1) => let val a = some_keyshape () val b = some_keyshape () val s = mustbe myself NODE (a, b) val (bxs, s1) = see (put (wrap s guide) x a) e1 (s b) in (bxs, s1 @@ s) end | Branch (e1, e2) => let val a = some_keyshape () val b = myself val (bx1, s1) = see guide e1 NODE (a, b) val (bx2, s2) = see (wrap s1 guide) e2 (s1 a) in (bx1 @ bx2, s2 @@ s1) end ) // ÀÚÀ¯º¸¹° ã±â fun freetreasure guide map = (case map of End (Name x) => if List.mem x guide then [] else [x] | Guide (x, e1) => freetreasure (x::guide) e1 | Branch (e1, e2) => freetreasure guide e1 @ freetreasure guide e2 | _ => [] ) // ÀÚÀ¯º¸¹° ¾ø¾Ö±â fun closed map = List.fold_left (fn map x => Guide (x, map)) map (unique (freetreasure [] map)) /// ¿­¼è¸ð¾çµé·ÎºÎÅÍ °¡Àå ÀÛÀº Å©±âÀÇ ¿­¼è²Ù·¯¹Ì¸¦ ã´Â ºÎºÐ. (* match: subst -> keyshape list -> subst list ÁÖ¾îÁø ¿­¼è¸ð¾çÇ¥ subst°¡ ÀÖ°í ¿­¼è¸ð¾çµé keyshapes°¡ ÀÖÀ» ¶§, ¿­¼è¸ð¾çµéÀ» ¼­·Î ¹Ù²ãÄ¡±âÇÒ ¼ö ÀÖ´Â ¸ðµç °æ¿ì¿¡ ´ëÇؼ­ °¢°¢ ½á¾ßÇÏ´Â ¿­¼è¸ð¾çÇ¥¸¦ ¸ðÀº °ÍÀÌ match subst keyshapes. keyshapes = [k1, k2, k3, ..., kn]À̶ó¸é, k1 = kiÀ¸·Î ¹Ù²ãÄ¡±âÇϱâ À§ÇÑ ¿­¼è¸ð¾çÇ¥¸¦ ³ª¸ÓÁö [k1, ..., ki-1, ki+1, ..., kn]¿¡¼­ ³ª¿Ã ¼ö ÀÖ´Â ¿­¼è¸ð¾çÇ¥µé¿¡ µ¡ºÙ¿©ÁÖ¾î ¸ðÀº °ÍÀÌ ³ª¿Ã ¼ö ÀÖ´Â ¸ðµç ¿­¼è¸ð¾çÇ¥ÀÌ´Ù. ¸¸¾à k1ÀÌ ´Ù¸¥ ¸ðµç ¿­¼è¸ð¾çµé°ú ¹Ù²ãÄ¡±âÇÒ ¼ö ¾ø´Â µ¶Æ¯ÇÑ °ÍÀ̶ó¸é k1À» »©°í ³ª¸ÓÁö ¿­¼è¸ð¾çµé¿¡¼­ ³ª¿Ã ¼ö ÀÖ´Â ¿­¼è¸ð¾çÇ¥µéÀÌ ÀüºÎÀÌ´Ù. *) fun match subst [] = [subst] | match subst (h::t) = let val l = List.flatten (List.map (fn k => let val subst' = (mustbe (subst k) (subst h)) @@ subst in List.map (fn s => s @@ subst') (match subst' (h :: List.filter (fn k' => k' <> k) t)) end handle Not_found => [] ) t) in if l = [] then match subst t else l end // realkey: subst -> keyshape -> key fun realkey s BAR = Bar | realkey s NODE (k1, k2) = Node (realkey s k1, realkey s k2) | realkey s k = let val k' = s k in if k' = k then Bar else realkey s k' end fun realkeys s = List.map (realkey s) // sizeofkey: key -> int, sizeofkeys: key list -> int // ¿­¼è/¿­¼è²Ù·¯¹ÌÀÇ Å©±â fun sizeofkey Bar = 1 | sizeofkey Node (k1, k2) = sizeofkey k1 + sizeofkey k2 + 1 fun sum f = (fn s x => s + f x) val sizeofkeys = List.fold_left (sum sizeofkey) 0 (* minkeys: keyshape list -> subst list -> key list ¿­¼è¸ð¾çµé(keyshapes)°ú ÀÌµé »çÀÌ¿¡ ¹Ù²ãÄ¡±â °¡´ÉÇÑ ¿­¼è¸ð¾çÇ¥µé(substs) Áß¿¡¼­ ³ª¿Ã ¼ö ÀÖ´Â °¡Àå ÀÛÀº Å©±âÀÇ ¿­¼è²Ù·¯¹Ì°¡ minkeys keyshapes substs. *) fun minkeys keyshapes substs = let fun min [] = unique (realkeys id keyshapes) | min [k] = k | min (k::t) = let val k' = min t in if sizeofkeys k < sizeofkeys k' then k else k' end in min (List.map (fn s => unique (realkeys s keyshapes)) substs) end (* getReady: map -> key list ¿­¾î¾ß ÇÒ º¸¹°»óÀÚµé°ú ¿­¼è¸ð¾çÇ¥¸¦ ±¸ÇÏ°í ÇÊ¿äÇÒ ¿­¼è¸ð¾çµéÀ» °¡Áö°í °¡Àå ÀÛÀº Å©±âÀÇ ¿­¼è²Ù·¯¹Ì¸¦ ã´Â´Ù. *) fun getReady map = let val me = some_keyshape () val (boxes, table) = see emptyGuide (closed map) me fun keyshapefor Star = BAR | keyshapefor Name x = (table KEY x) val keyshapes = unique (List.map keyshapefor boxes) in minkeys keyshapes (match id keyshapes) end handle Not_found => []