LISP Exercice Fam Tr

时间:2014-09-10 17:39:34

标签: lisp common-lisp

Family Tree Exercise

我试图像这样做这个练习:

(defconstant *family-tree* 
  '((father Barack Pat) (mother Michelle Pat)
    (father GeorgeW Peter) (mother Laura Peter)
    (father GeogerH James (mother Barbara James) 
    (father Bill Jane) (mother Hillary Jane) 
    (father James Mark) (mother Jane Mark) 
    (father Peter Mary) (mother Pat Mary) 
    (father Mark John) (mother Mary John))))

但我不确定这是不是最好的方法。而且,我不知道如何创建功能"父母"和#34;祖父母"。我非常感谢任何帮助。感谢

2 个答案:

答案 0 :(得分:3)

您构建了一个关联记录列表,这是解决此问题的有效方法。这类似于未编制索引的数据库表的结构。您可以使用树结构以及回溯搜索,但实现起来更复杂,并且对于一小组结果,效率增益不会太大。

另外,考虑到这个问题并不需要你单独查看母亲和父亲,而只是父母,将父母双方都记录下来可能会更有效率

(defconstant *family-tree*
  '((john mark mary)
    (mark james jane)
    (james georgeh barbara)
    ; and so on ...
   ))

鉴于这种结构,让我们编写一些访问函数

(defun child (record)
  "This function returns the child in a family tree record. 
    For example (child '(john mark mary)) returns JOHN"
    (car record))

(defun parents (record)
  "This function returns the parents in a family record.
   For example (cdr '(john mark mary)) returns (MARK MARY)"
   (cdr record))

(defun find-record (family-tree person)
  "This function returns the record of which PERSON is the CHILD.
   For example (find-record 'john '((mark james jane) (john mark mary))) 
   returns (JOHN MARK MARY)"
  (find-if (lambda (record) (eql (child record) person)) family-tree))

现在使用这些访问器我们可以编写父函数

(defun parents (family-tree person)
  (parents (find-record family-tree person)))

现在找到祖父母,你需要找到每个父母的父母。

(defun grandparents (family-tree person)
    (apply #'append
           (mapcar (lambda (parent) (parents family-tree parent)
                   (parents family-tree person))))

现在最后一个函数有点复杂,所以让我们来解释一下。为了找到祖父母,你需要先找到你正在寻找的人的父母,这是最底线(parents family-tree person)。这将导致父母列表,因此对于该列表中的每个父母,我们需要找到他们的父母(父母的父母= =祖父母),因此我们使用mapcar在每个父母上调用(parent family-tree parent)结果。最后,我们将得到一个包含2个列表的列表,因此我们需要append将它们放入一个列表中。

答案 1 :(得分:3)

您可能希望从婴儿步骤开始:

(defun make-person (name &optional father mother)
  (cons name (cons father mother)))

现在您可以创建家谱:

(defconstant *family-tree* 
  (make-person 'john
     (make-person 'mark 
       (make-person 'james
         ...)
       (make-person 'jane
         ...))
     (make-person 'mary
       (make-person ...)
       (make-person ...))))

在树中查找某人需要递归:

(defun find-person (tree name)
  (if (eq (car tree) name)
      tree
      (or (find-person (cadr tree) name)
          (find-person (cddr tree) name))))

您实际上可以将cadr替换为father-tree,将cddr替换为mother-tree。 (您也可以定义tree-name来呼叫car)。

现在应该很容易找到父母和祖父母:

(defun parents (tree name)
   (let ((person (find-person tree name)))
     (list (caadr person) ; or (tree-name (tree-father person))
           (caddr person)))) ; or ...