在计划中找到中位数的函数

时间:2014-11-26 19:34:54

标签: scheme racket

我是Scheme新手,我正在使用Dr.Racket试图找到列表的中位数。

如果列表L的长度是奇数,则函数median返回列表中的中值元素。如果L的长度是偶数,则函数median返回0.示例

(median ‘(1)) returns 1
(median ‘(1 2)) returns 0
(median ‘(1 2 3)) returns 2
(median ‘( 1 2 3 4) returns 0

我只能使用:

  • 空?
  • CDR
  • 否则
  • =
  • +
  • 中值
  • COND
  • 如果
  • 用户定义的名称(对于我的变量)
  • 整数文字
  • 括号

我们不允许使用两个功能。它应该类似(define median (lambda (<list L followed by parameters of your choice initially set to zero>) (cond ))),它应该只有一个递归函数。所有辅助参数必须是数字(不是列表),并且初始值应设置为零。例如,如果L是‘(1 2 3 4)并决定使用一个额外的辅助参数,则应将中位数称为(median '(1 2 3 4) 0 )

中位数将列表分成两组,长度相等。这是中位数的定义属性:如果中位数之前的元素数等于后面的元素数,那么元素就是中位数。因此,为了找到中值,对于每个列表元素,需要计算在给定元素之前的元素的数量和成功它的元素的数量。如果这两个数字相同,则找到中位数。问题表示涉及以下变量: - 列表L; - 目标元素(潜在中位数),比如说“目标”; - 一个计数器,用于表示目标前面元素的数量,比如count1 - 一个计数器,用于计算目标后面元素的数量,比如count2,我想出了这样的结果:

(define median(lambda (list target count1 count2 loop )
  (cond
  ((null? list)(if (= count1 count2) target 0))
  ((if (= loop 1)
  (if (= target (median (cdr list) target count1 (+ 1 count2) 1 ))
  target
  (median (cdr list) (car list) (+ count1 1) 0 1 )
  ))))))

但我被困在这里......任何人都可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

如果我很好地阅读了你的约束,那么应该这样做:

(define median
  (lambda (lst pass cnt1 cnt2)
    (cond
      ; pass 0 = initial call - call pass 1 then pass 2
      ((= pass 0) (median lst 2 (median lst 1 0 0) 0))
      ; pass 1 = determine the position of the median (-1 or n//2)
      ((= pass 1) (if (null? lst)
                      (if (= cnt1 cnt2) -1 (sub1 cnt1))
                      (median (cdr lst) 1 (add1 cnt2) cnt1)))
      ; pass 2 = find element
      (else       (cond
                    ((eqv? cnt1 -1) 0)
                    ((eqv? cnt1 0) (car lst))
                    (else (median (cdr lst) 2 (sub1 cnt1) 0)))))))

它基本上有3个传球,有些参数对于不同的传球有不同的含义,所以你当然不会在现实世界中写下这样的东西。

测试:

> (median '(1) 0 0 0)
1
> (median '(1 2) 0 0 0)
0
> (median '(1 2 3) 0 0 0)
2
> (median '(1 2 3 4) 0 0 0)
0
> (median '(1 2 3 4 5) 0 0 0)
3