How to compute the number of times pattern in one

2019-03-01 01:23发布

I am stuck up in a Scheme program for about 5 hours. The program that I am working on should take two lists as input and then compute the number of times the pattern within the first list appears on the second list.

For example : > (patt '(b c) '(a b c d e b c)) ==> answer = 2

(patt '(a b c) '(a b c a b c d e a b c c c)) ==> answer = 3

(patt '((a b) c) '(a b (a b) c d e b c)) ==> answer = 1

Below is the code that I have till now.

(define (patt lis1 lis2)
  (cond
    ((null? lis1) 0)
    ((null? lis2) 0)
    [(and (> (length lis1) 1) (eq? (car lis1) (car lis2))) (patt (cdr lis1) (cdr lis2))]
    ((eq? (car lis1) (car lis2)) (+ 1 (patt lis1 (cdr lis2))))
    (else (patt lis1 (cdr lis2)))
    ))

Can someone please help me solve this. Thanks!

4条回答
2楼-- · 2019-03-01 01:48

Consider the subproblem of testing if a list starts with another list.

Then do this for every suffix of the list. Sum up the count of matches.

If you want non overlapping occurrences, you can have the prefix match, return the suffix of the list so that you can skip over the matching part.

Also use equals? for structural equality, not eq? which is for identity.

查看更多
Fickle 薄情
3楼-- · 2019-03-01 01:53
(define (patt list1 list2)
  (let ([patt_length (length list1)])
    (let loop ([loop_list list2]
               [sum 0])
      (if (>= (length loop_list) patt_length)
          (if (equal? list1 (take loop_list patt_length))
              (loop (cdr loop_list) (add1 sum))
              (loop (cdr loop_list) sum))
          sum))))
查看更多
兄弟一词,经得起流年.
4楼-- · 2019-03-01 02:09

After giving this homework problem a little time to marinate, I don't see the harm in posting additional answers -

(define (count pat xs)
  (cond ((empty? xs)
         0)
        ((match pat xs)
         (+ 1 (count pat (cdr xs))))
        (else
         (count pat (cdr xs)))))

(define (match pat xs)
  (cond ((empty? pat)
         #t)
        ((empty? xs)
         #f)
        ((and (list? pat)
              (list? xs))
         (and (match (car pat) (car xs))
              (match (cdr pat) (cdr xs))))
        (else
         (eq? pat xs))))

(count '(a b c) '(a b c a b c d e a b c c c)) ;; 3

(count '((a b) c) '(a b (a b) c d e b c)) ;; 1

(count '(a a) '(a a a a)) ;; 3
查看更多
做自己的国王
5楼-- · 2019-03-01 02:13

You need to divide the problem into parts:

(define (prefix? needle haystack)
  ...)

(prefix? '() '(a b c))        ; ==> #t
(prefix? '(a) '(a b c))       ; ==> #t
(prefix? '(a b c) '(a b c))   ; ==> #t
(prefix? '(a b c d) '(a b c)) ; ==> #f
(prefix? '(b) '(a b c))       ; ==> #t

(define (count-occurences needle haystack)
  ...)

So with this you can imagine searching for the pattern (count-occurences '(a a) '(a a a a)). When it is found from the first element you need to search again on the next. Thus so that the result is 3 for the (a a a a) since the matches overlap. Every sublist except when it's the empty list involves using prefix?

Good luck!

查看更多
登录 后发表回答