Scheme 递归子列表?功能
我似乎不知道如何编写一个正确的uscheme(mitscheme的派生)函数,该函数将返回布尔值,无论列表是否包含较小的列表 这是我写的Scheme 递归子列表?功能,scheme,Scheme,我似乎不知道如何编写一个正确的uscheme(mitscheme的派生)函数,该函数将返回布尔值,无论列表是否包含较小的列表 这是我写的 (define sublist? (xs ys) (if (= xs '()) #t (if (= ys '()) #f (if (= (car xs) (car ys)) (sublist? (cdr xs) (cdr ys))
(define sublist? (xs ys)
(if (= xs '())
#t
(if (= ys '())
#f
(if (= (car xs) (car ys))
(sublist? (cdr xs) (cdr ys))
(sublist? xs (cdr ys))
)
)
)
)
除了这一个测试用例外,它通过了我的大多数测试用例
(sublist? '(a b c) '(1 2 a 3 b 4 c 5 6))
;; this returns true while it's supposed to return false
测试用例要求子列表是连续的,中间没有随机元素
我有点纠结于如何纠正这个问题。还有其他人有想法吗 问题在于,您的算法过于急切,一旦找到两个相等的元素,它会立即丢弃该元素并继续检查。事实上,仅仅找到两个相等的元素是不够的,因为如果算法发现不完全匹配,它可能不得不回溯 表示这种算法的最简单方法是使用一个helper函数,该函数确定子列表是否在列表中的给定位置匹配。然后,
子列表?
函数将遍历较大列表中的每个位置以查找匹配项
以下是我的实现:
(define (sublist? xs ys)
(define (sublist-equal? xs ys)
(cond
((null? xs) #t)
((null? ys) #f)
((equal? (car xs) (car ys))
(sublist-equal? (cdr xs) (cdr ys)))
(else #f)))
(cond
((null? xs) #t)
((null? ys) #f)
((sublist-equal? xs ys) #t)
(else (sublist? xs (cdr ys)))))
注意内部的子列表equal?
helper函数
我还使用cond
而不是嵌套的if
表达式,因为在这种情况下应该真正使用cond
来表示这种逻辑。此外,我使用equal?
而不是=
,因为它是我所知道的大多数方案,=
用于数值比较(我不知道您的可能不同)。这是我的版本“没有辅助函数”。但它确实使用了两个嵌套循环:
(define (sublist? needle haystack)
(if (null? needle)
#t
(let ((first (car needle)))
(let outer ((cur haystack))
(define (next)
(outer (cdr cur)))
(cond ((null? cur) #f)
((eqv? (car cur) first)
(let inner ((lhs (cdr needle))
(rhs (cdr cur)))
(cond ((null? lhs) #t)
((null? rhs) (next))
((eqv? (car lhs) (car rhs))
(inner (cdr lhs) (cdr rhs)))
(else (next)))))
(else (next)))))))
在没有辅助函数的情况下可以这样做吗?这非常有效。我希望有一个没有助手功能的版本。谢谢你的帮助!很好的代码,但我的作业说它必须是递归的,而不是迭代的。从技术上讲,你的版本也是迭代的(Alexis的版本也是如此)。;-)但我会看看我能做些什么。
(define sublist? (xs ys)
(cond ((= xs '()) #t) ;;cond easier to read than
((= ys '()) #f) ;;nested if statements
((and (= (car xs) (car ys))
;;need to check for more than singleton match
(or (null? (cdr xs))
(and (not (null? (cdr ys)))
(= (cadr xs) (cadr ys))
(sublist? (cdr xs) (cdr ys)))))) ;not tail call
;;this cond clause has no second part,
;;the first will return #t or #f
;;will backtrack if #f is propagated up the stack.
(else (sublist? xs (cdr ys)))) ; tail call