仅使用基本的lisp递归查找并返回列表中的模式

时间:2017-10-28 04:32:39

标签: recursion functional-programming pattern-matching lisp

我需要编写的函数有两个参数:模式(p)和列表(L)。我想找到包含模式的列表部分以及模式之后的所有内容。如果模式不在列表中,则返回nil。

示例:

输入:(find_pattern'(h e l p)'(i e e e e p p e e s))

输出:'(h e l p p l e s e)

我只能使用基本的lisp函数(cond,car,cdr,cons,null,eq,/ =)。它需要递归,不能使用setq等。

我的策略:

我推理的案例是:

p = nil,L = nil:如果模式位于列表的末尾,则会发生这种情况,因此,返回nil

p = nil,L =(none-nil value):如果pattern位于列表的中间,则返回L

p =(非零值),L = nil:未找到模式返回nil

p =(非零值),L =(非零值):如果p和L的汽车相同,则递归调用p和L的cdr。如果它们不相同,用p和L的cdr递归调用。

我的尝试:

(defun find_pattern (p L)
    (cond((null p) 
                  (cond ((null L) nil) ; p = nil, L = nil
                        (T L)))        ; p = nil, L != nil
         ((T 
                  (cond ((null L) nil) ; p != nil, L = nil
                        ((eq (car p), (car L)) ; p!= nil, L != nil
                         (cons ((car L) (find_pattern (cdr p) (cdr L))))))

)

如果没有运行,我已经看到了一些问题:

如果我发现部分模式匹配,我永远不会回到完整模式。因此,诸如'(a b c)'(d a b d a b c)之类的输入会得到错误的结果。此外,部分结果也会附加到列表中。

有人能让我朝着正确的方向前进吗?当我遇到部分模式时,如何返回搜索完整模式?

1 个答案:

答案 0 :(得分:0)

这应该适用于Common Lisp - 我在这里使用的技术是在助手中传递src的副本,以跟踪当前的搜索位置

(defun find-pattern-helper (xs ys src)
  (cond ((null xs)
         src)
        ((null ys)
         nil)
        ((eq (car xs) (car ys))
         (find-pattern-helper (cdr xs) (cdr ys) src))
        (T
         (find-pattern-helper pat (cdr src) (cdr src)))))

(defun find-pattern (pat src)
  (find-pattern-helper pat src src))

或者在这里它是在Racket ...我有点咂Lisp所以这是我唯一可以在

中测试它的东西
#lang racket

(define (find-pattern pat src)
  (let loop ((xs pat) (ys src) (src src))
    (cond ((null? xs)
           src)
          ((null? ys)
           '())
          ((eq? (car xs) (car ys))
           (loop (cdr xs) (cdr ys) src))
          (#t
           (loop pat (cdr src) (cdr src))))))

(find-pattern '(h e l p) '(i n e e d h e l p p l e a s e))
;; => '(h e l p p l e a s e)

(find-pattern '() '(h a y s t a c k))
;; => '(h a y s t a c k)

(find-pattern '(h a y s t a c k) '(h a y))
;; => '()