我在编写一些代码时遇到了一些麻烦,但我无法找到错误。编程语言在计划中,问题如下:
只留下不重复的元素。 例如:(a b a a c c) - > (a b)
我写了下面的代码。
(define x '(a b a a a c c))
(display x)
(define z '())
(define (removeReps y)
(if (null? y)
'()
(if( = (car y) (removeReps (cdr y))) '() (append z (car y)))))
(removeReps x)
(display z)
对于完全披露,这是一项家庭作业,但我无法解决。
谢谢。
答案 0 :(得分:1)
解决方案不是 简单,你必须跟踪迭代时找到的前一个元素,并且还有一个标志,告诉你前一个元素是否出现过多次。这是我的镜头,假设输入列表是非空的(如果输入列表为空,则处理大小写的情况很简单,留下作为读者的练习):
(define (removeReps lst)
; we need some extra parameters, use a named let for iteration
(let loop ([lst (cdr lst)] ; list to process, assuming non-empty
[prev (car lst)] ; pick first as "previous" value
[first #t]) ; flag: is this the first element in sequence?
(cond ((null? lst) ; if we reached the end of the list
(if first ; edge case: handle last element
(list prev) ; if it was the first in sequence add it
'())) ; otherwise skip it and end list
; if current element equals previous element
((equal? (car lst) prev)
; skip it, advance recursion and update flag
(loop (cdr lst) prev #f))
; new element, if previous element had exactly one repetition
(first
; add it to output, advance recursion, update prev and flag
(cons prev (loop (cdr lst) (car lst) #t)))
; new element, if previous element had more than one repetition
(else
; skip it, advance recursion, update prev and flag
(loop (cdr lst) (car lst) #t)))))
<强>更新强>
我真的很喜欢@ chris在Haskell中的实现:更高级别并使用现有过程而不是显式递归,它适用于空列表并且转换为Scheme并不太难(它在Scheme中比在Haskell中更冗长,虽然。)这是使用Racket和SRFI-1的span
程序的另一种选择,看看@ chris的答案,看看它是如何工作的解释:
(require srfi/1) ; import `span`
(define (group lst)
(match lst
['() '()]
[(cons x xs)
(let-values (((ys zs) (span (curry equal? x) xs)))
(cons (cons x ys) (group zs)))]))
(define (removeReps lst)
(filter-map (lambda (x) (and (= (length x) 1) (first x)))
(group lst)))
或者更便携,不使用特定于球拍的程序和特殊表格:
(require srfi/1) ; import `span`
(define (group lst)
(if (null? lst)
'()
(let ((x (car lst))
(xs (cdr lst)))
(let-values (((ys zs) (span (lambda (e) (equal? e x)) xs)))
(cons (cons x ys)
(group zs))))))
(define (removeReps lst)
(map car
(filter (lambda (x) (= (length x) 1))
(group lst))))
让我们用一些边缘情况测试程序 - 它可以按照预期的任何上述实现工作:
(removeReps '(a b a a a c c))
=> '(a b)
(removeReps '(x a a x b b x c c x))
=> '(x x x x)
(removeReps '(a a a))
=> '()
(removeReps '(a b b c c))
=> '(a)
(removeReps '(a a b b c c d))
=> '(d)
答案 1 :(得分:1)
另一个似乎处理测试用例的递归解决方案。
;rep is the last repeated elem, input is the input list and first is boolean
(define notrepeatedrec
(lambda (rep input first)
(cond ((null? input) (if (eq? first #t) (list rep) '()))
((eq? rep (car input)) (notrepeatedrec (car input) (cdr input) #f))
(else (if (eq? first #t)
(cons rep (notrepeatedrec (car input) (cdr input) #t))
(notrepeatedrec (car input) (cdr input) #t))))))
;helper function to start the recursion
(define notrepeated
(lambda (lst)
(notrepeatedrec '() lst #f)))
答案 2 :(得分:0)
另一种可能的解决方案如下
import Data.List
removeDups :: Eq a => [a] -> [a]
removeDups = map head . filter ((== 1) . length) . group
用Haskell编写并使用库函数group
,length
,(==)
,filter
,head
和map
。
由于以上内容可能不会过于可读,我将逐步完成定义
首先是构成上述定义的各个部分的文字描述
现在有些代码。只要它们相等就可以将列表中的元素组合在一起的函数定义如下(抱歉,我使用Haskell语法,因为我不熟悉scheme,但它应该很容易翻译) :
group :: Eq a -> [a] -> [[a]]
group [] = []
group (x:xs) = (x:ys) : group zs
where (ys, zs) = span (== x) xs
其中span
是另一个库函数,给定一些谓词p
,将其输入列表拆分为元素 all 的初始段,满足p
和列表的其余部分。为完整起见,可以定义如下
span :: (a -> Bool) -> [a] -> ([a], [a])
span _ [] = ([], [])
span p xs@(x:xs')
| p x = let (ys, zs) = span p xs' in (x:ys, zs)
| otherwise = ([], xs)
map
,filter
和head
比那些更加标准,我确信它们是方案库的一部分(可能是group
)
我想我的主要观点是,一旦将问题分解为小块子问题(使用某些预定义函数)并将结果合并,解决方案就很容易了。
答案 3 :(得分:0)
在Common Lisp中,我将堆栈apis用于列表:
(defun elim-dup (l)
(if (null l)
nil
(progn
(setf new ())
(dolist (x l)
(setq elem (pop l))
(if (not (member elem new))
(push elem new)))
new)))
如果您更喜欢原始订单,请添加:
(reverse new)
为了避免破坏原始列表,您必须使用第n个元素而不是pop(并维护计数器)。流行更直接但更具破坏性。
答案 4 :(得分:0)
以下几行可能是可以接受的:
;; expr list -> list
;; produce a list where leading elements equal to EXPR have been dropped
(define (drop-in-front elt list)
(cond [(null? list) list] ; empty list, we're done
[(equal? elt (first list)) ; first element matches
(drop-in-front elt (rest list))] ; drop and repeat
[#t list])) ; no match, we're done
;; list -> list
;; produce a list where blocks of repeated elements have been dropped
(define (remove-repeated list)
(cond [(or (null? list) ; empty list
(null? (cdr list))) ; or list with one element
list] ; we're done
[(equal? (first list)
(second list)) ; two matching elements in front
(remove-repeated ; continue with
(drop-in-front (first list) ; list where block in front
(rest list)))] ; has been dropped
[#t ; first elt different from snd
(cons (first list) ; stick it in front of
(remove-repeated (rest list)))])) ; cleaned up rest of list
我真诚地希望你的课程能尽快提供一些风格指南。
如果有机会,请尝试查看Introduction to Systematic Program Design的讲座或查看How to Design Programs。