Ninety-Nine F# Problems - Problems 70 - 73 - Multiway Trees

These are F# solutions of Ninety-Nine Haskell Problems which are themselves translations of Ninety-Nine Lisp Problems and Ninety-Nine Prolog Problems. The solutions are hidden so you can try to solve them yourself.

Copy Source
Copy Link
Tools:

Ninety-Nine F# Problems - Problems 70 - 73 - Multiway Trees

 1: /// These are F# solutions of Ninety-Nine Haskell Problems 
 2: /// (http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_Problems), 
 3: /// which are themselves translations of Ninety-Nine Lisp Problems
 4: /// (http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html)
 5: /// and Ninety-Nine Prolog Problems
 6: /// (https://sites.google.com/site/prologsite/prolog-problems).
 7: ///
 8: /// If you would like to contribute a solution or fix any bugs, send 
 9: /// an email to paks at kitiara dot org with the subject "99 F# problems". 
10: /// I'll try to update the problem as soon as possible.
11: ///
12: /// The problems have different levels of difficulty. Those marked with a single asterisk (*) 
13: /// are easy. If you have successfully solved the preceeding problems you should be able to 
14: /// solve them within a few (say 15) minutes. Problems marked with two asterisks (**) are of 
15: /// intermediate difficulty. If you are a skilled F# programmer it shouldn't take you more than 
16: /// 30-90 minutes to solve them. Problems marked with three asterisks (***) are more difficult. 
17: /// You may need more time (i.e. a few hours or more) to find a good solution
18: ///
19: /// Though the problems number from 1 to 99, there are some gaps and some additions marked with 
20: /// letters. There are actually only 88 problems.
21: ///
22: /// 
23: /// A multiway tree is composed of a root element and a (possibly empty) set of successors which
24: /// are multiway trees themselves. A multiway tree is never empty. The set of successor trees is
25: /// sometimes called a forest.
26: ///  
27: ///                              (a)
28: ///                            /  |  \
29: ///                          (f) (c) (b)
30: ///                           |      /  \
31: ///                          (g)   (d)  (e)
32: /// 
33: /// Problem 70B 
34: /// 
35: /// (*) Check whether a given term represents a multiway tree. 
36: /// 
37: /// In Prolog or Lisp, one writes a predicate to check this. 
38: /// 
39: /// Example in Prolog: 
40: /// ?- istree(t(a,[t(f,[t(g,[])]),t(c,[]),t(b,[t(d,[]),t(e,[])])])).
41: /// Yes
42: ///  
43: /// In F#, we define multiway trees as a type.
44: /// 
45: type 'a Tree = Node of 'a  * 'a Tree list
46: ///         
47: /// Some example trees: 
48: /// 
49: let tree1 = Node ('a', [])
50: 
51: let tree2 = Node ('a', [Node ('b', [])])
52: 
53: let tree3 = Node ('a', [Node ('b', [Node ('c', [])])])
54: 
55: let tree4 = Node ('b', [Node ('d', []); Node ('e', [])])
56: 
57: let tree5 = Node ('a', [
58:                         Node ('f', [Node ('g', [])]);
59:                         Node ('c', []);
60:                         Node ('b', [Node ('d', []); Node ('e', [])])
61:                        ] )
62: 
63: /// The last is the tree illustrated above. 
64: /// 
65: /// 
66: /// (*) Problem 70B : Check whether a given term represents a multiway tree
67: /// As in problem 54A, all members of this type are multiway trees; there is no use for a 
68: /// predicate to test them.
69: /// 

(*) Problem 70C : Count the nodes of a multiway tree.

1: /// Example in F#: 
2: /// 
3: /// > nnodes tree2;;
4: /// val it : int = 2 
5: 
6: (Solution)

(**) Problem 70 : Tree construction from a node string.

 1: /// We suppose that the nodes of a multiway tree contain single characters. In the depth-first 
 2: /// order sequence of its nodes, a special character ^ has been inserted whenever, during the 
 3: /// tree traversal, the move is a backtrack to the previous level.
 4: ///  
 5: /// By this rule, the tree below (tree5) is represented as: afg^^c^bd^e^^^ 
 6: /// 
 7: /// 
 8: /// 
 9: /// Define the syntax of the string and write a predicate tree(String,Tree) to construct the 
10: /// Tree when the String is given. Make your predicate work in both directions.
11: ///
12: /// Example in F#: 
13: /// 
14: /// > string2Tree "afg^^c^bd^e^^^";;
15: /// val it : char Tree =
16: ///   Node
17: ///     ('a',
18: ///      [Node ('f',[Node ('g',[])]); Node ('c',[]);
19: ///       Node ('b',[Node ('d',[]); Node ('e',[])])])
20: /// > string2Tree "afg^^c^bd^e^^^" = tree5;;
21: /// val it : bool = true
22: 
23: (Solution)

(*) Problem 71 : Determine the internal path length of a tree.

 1: /// We define the internal path length of a multiway tree as the total sum of the path lengths
 2: /// from the root to all nodes of the tree. By this definition, tree5 has an internal path 
 3: /// length of 9.
 4: ///  
 5: /// Example in F#: 
 6: /// 
 7: /// > ipl tree5;;
 8: /// val it : int = 9
 9: /// > ipl tree4;;
10: /// val it : int = 2
11: 
12: (Solution)

(*) Problem 72 : Construct the bottom-up order sequence of the tree nodes.

 1: /// Write a predicate bottom_up(Tree,Seq) which constructs the bottom-up sequence of the nodes
 2: /// of the multiway tree Tree.
 3: ///  
 4: /// Example in F#: 
 5: /// 
 6: /// > bottom_up tree5;;
 7: /// val it : string = "gfcdeba"
 8: /// > bottom_up tree4;;
 9: /// val it : string = "deb"
10: 
11: (Solution)

(**) Problem 73 : Lisp-like tree representation.

 1: /// There is a particular notation for multiway trees in Lisp. Lisp is a prominent 
 2: /// functional programming language, which is used primarily for artificial intelligence 
 3: /// problems. As such it is one of the main competitors of Prolog. In Lisp almost everything
 4: /// is a list, just as in Prolog everything is a term.
 5: ///  
 6: /// The following pictures show how multiway tree structures are represented in Lisp.
 7: ///  
 8: ///    (a)        (a)        (a)        (b)            (a)
 9: ///                |          |        /   \         /  |  \
10: ///               (b)        (b)     (d)   (e)     (f)  (c)  (b)
11: ///                           |                     |       /   \
12: ///                          (c)                   (g)    (d)   (e)
13: ///
14: ///     a        (a b)    (a (b c))   (b d e)    (a (f g) c (b d e))
15: ///
16: /// Note that in the "lispy" notation a node with successors (children) in the tree is always
17: /// the first element in a list, followed by its children. The "lispy" representation of a 
18: /// multiway tree is a sequence of atoms and parentheses '(' and ')', which we shall 
19: /// collectively call "tokens". We can represent this sequence of tokens as a Prolog list; 
20: /// e.g. the lispy expression (a (b c)) could be represented as the Prolog list 
21: /// ['(', a, '(', b, c, ')', ')']. Write a predicate tree_ltl(T,LTL) which constructs the
22: /// "lispy token list" LTL if the tree is given as term T in the usual Prolog notation.
23: ///  
24: /// (The Prolog example given is incorrect.) 
25: /// 
26: /// Example in F#: 
27: /// 
28: /// > treeltl "(x (a (f g) c (b d e)))";;
29: /// val it : char list =
30: ///   ['('; 'x'; '('; 'a'; '('; 'f'; 'g'; ')'; 'c'; '('; 'b'; 'd'; 'e'; ')'; ')';
31: ///    ')']
32: ///
33: /// > displayList tree1;;
34: /// val it : string = "a"
35: /// > displayLisp tree2;;
36: /// val it : string = "(a b)"
37: /// > displayLisp tree3;;
38: /// val it : string = "(a (b c))"
39: /// > displayLisp tree4;;
40: /// val it : string = "(b d e)"
41: /// > displayLisp tree5;;
42: /// val it : string = "(a (f g) c (b d e))"
43: ///
44: /// > lisp2Tree "(a (f g) c (b d e))" = tree5;;
45: /// val it : bool = true
46: ///
47: /// As a second, even more interesting exercise try to rewrite tree_ltl/2 in a way that the
48: /// inverse conversion is also possible.
49: 
50: (Solution)
union case Tree.Node: 'a * 'a Tree list -> 'a Tree
type 'a Tree = | Node of 'a * 'a Tree list

Full name: Snippet.Tree<_>

  type: 'a Tree
  implements: System.IEquatable<'a Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<'a Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable


These are F# solutions of Ninety-Nine Haskell Problems
 (http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_Problems),
 which are themselves translations of Ninety-Nine Lisp Problems
 (http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html)
 and Ninety-Nine Prolog Problems
 (https://sites.google.com/site/prologsite/prolog-problems).

 If you would like to contribute a solution or fix any bugs, send
 an email to paks at kitiara dot org with the subject "99 F# problems".
 I'll try to update the problem as soon as possible.

 The problems have different levels of difficulty. Those marked with a single asterisk (*)
 are easy. If you have successfully solved the preceeding problems you should be able to
 solve them within a few (say 15) minutes. Problems marked with two asterisks (**) are of
 intermediate difficulty. If you are a skilled F# programmer it shouldn't take you more than
 30-90 minutes to solve them. Problems marked with three asterisks (***) are more difficult.
 You may need more time (i.e. a few hours or more) to find a good solution

 Though the problems number from 1 to 99, there are some gaps and some additions marked with
 letters. There are actually only 88 problems.

 
 A multiway tree is composed of a root element and a (possibly empty) set of successors which
 are multiway trees themselves. A multiway tree is never empty. The set of successor trees is
 sometimes called a forest.
  
                              (a)
                            / | \
                          (f) (c) (b)
                           | / \
                          (g) (d) (e)
 
 Problem 70B
 
 (*) Check whether a given term represents a multiway tree.
 
 In Prolog or Lisp, one writes a predicate to check this.
 
 Example in Prolog:
 ?- istree(t(a,[t(f,[t(g,[])]),t(c,[]),t(b,[t(d,[]),t(e,[])])])).
 Yes
  
 In F#, we define multiway trees as a type.

type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>

  type: 'T list
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<List<'T>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.Generic.IEnumerable<'T>
  implements: System.Collections.IEnumerable
val tree1 : char Tree

Full name: Snippet.tree1

  type: char Tree
  implements: System.IEquatable<char Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<char Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable


Some example trees:
val tree2 : char Tree

Full name: Snippet.tree2

  type: char Tree
  implements: System.IEquatable<char Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<char Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val tree3 : char Tree

Full name: Snippet.tree3

  type: char Tree
  implements: System.IEquatable<char Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<char Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val tree4 : char Tree

Full name: Snippet.tree4

  type: char Tree
  implements: System.IEquatable<char Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<char Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val tree5 : char Tree

Full name: Snippet.tree5

  type: char Tree
  implements: System.IEquatable<char Tree>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<char Tree>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
let rec nnodes = function
    | Node (_, []) -> 1
    | Node (_, xs) ->
        let t = xs |> List.sumBy (nnodes)
        1 + t
let string2Tree str =
    let chars = str |> List.ofSeq
    let rec loop chars stack =
        match chars with
            | '^'::xs ->
                match stack with
                    | [x] -> x
                    | tx::Node(y, ty)::stack' -> loop xs (Node(y, ty @ [tx])::stack')
                    | [] -> failwith "malformed text"
            | x::xs -> loop xs (Node(x,[])::stack)
            | [] -> failwith "malformed text"
    loop chars []

let tree2String tree =
    let rec loop tree =
        match tree with
            | Node(a, []) -> a.ToString() + "^"
            | Node(a, xs) -> a.ToString() + (xs |> List.fold(fun acc x -> acc + loop x) "") + "^"
    loop tree
let rec ipl tree =
    let rec loop depth = function
        | Node(a, []) -> depth
        | Node(a, xs) -> depth + (xs |> List.sumBy( fun x -> loop (depth+1) x))
    loop 0 tree
let bottom_up tree =
    let rec loop = function
        | Node(a, []) -> a.ToString()
        | Node(a, xs) -> (xs |> List.fold( fun acc x -> acc + (loop x) ) "") + a.ToString()
    loop tree
let treeltl str = str |> List.ofSeq |> List.filter((<>) ' ')

let displayLisp tree =
    let rec loop = function
        | Node(a, []) -> a.ToString()
        | Node(a, xs) -> "(" + a.ToString() + (xs |> List.fold( fun acc x -> acc + " " + (loop x) ) "") + ")"
    loop tree

let lisp2Tree str =
    let tokens = treeltl str
    let rec loop tokens stack =
        match tokens with
            | ')'::xs ->
                match stack with
                    | [x] -> x
                    | tx::Node(y, ty)::stack' -> loop xs (Node(y, ty @ [tx])::stack')
                    | [] -> failwith "malformed text"
            | '('::x::xs -> loop xs (Node(x,[])::stack)
            | x::xs ->
                match stack with
                    | [] -> loop xs [Node(x,[])]
                    | Node(y,t)::stack -> loop xs (Node(y,t @ [Node(x,[])])::stack)
            | [] -> stack |> List.head
    loop tokens []

More information

Link: http://fssnip.net/au
Posted: 2 years ago
Author: Cesar Mendoza (website)
Tags: Ninety-Nine F# Problems, tutorial, F#, trees