按照模式排序方案

时间:2013-08-08 11:47:05

标签: sorting scheme dutch-national-flag-problem

一点帮助,伙计们。 如何根据特定模式对列表进行排序 一个例子是排序R,W,B的列表,其中R首先出现然后是W然后是B. 像(sortf '(W R W B R W B B))(R R W W W B B B)

之类的东西

非常感谢任何答案。

4 个答案:

答案 0 :(得分:3)

这是Dutch national flag problem的功能版本。以下是我的两分钱 - 使用sort程序,O(n log n)复杂度:

(define sortf
  (let ((map '#hash((R . 0) (W . 1) (B . 2))))
    (lambda (lst)
      (sort lst
            (lambda (x y) (<= (hash-ref map x) (hash-ref map y)))))))

使用filter O(4n)复杂度:

(define (sortf lst)
  (append (filter (lambda (x) (eq? x 'R)) lst)
          (filter (lambda (x) (eq? x 'W)) lst)
          (filter (lambda (x) (eq? x 'B)) lst)))

partitionO(3n)复杂度::

一起使用
(define (sortf lst)
  (let-values (((reds others)
                (partition (lambda (x) (eq? x 'R)) lst)))
    (let-values (((whites blues)
                  (partition (lambda (x) (eq? x 'W)) others)))
      (append reds whites blues))))

上述解决方案以函数式编程风格编写,创建了一个带有答案的新列表。如果我们将输入表示为向量,则允许构造最优O(n)单通道命令解决方案,该向量允许通过索引引用元素。事实上,这就是问题的原始表述是如何解决的:

(define (swap! vec i j)
  (let ((tmp (vector-ref vec i)))
    (vector-set! vec i (vector-ref vec j))
    (vector-set! vec j tmp)))

(define (sortf vec)
  (let loop ([i 0]
             [p 0]
             [k (sub1 (vector-length vec))])
    (cond [(> i k) vec]
          [(eq? (vector-ref vec i) 'R)
           (swap! vec i p)
           (loop (add1 i) (add1 p) k)]
          [(eq? (vector-ref vec i) 'B)
           (swap! vec i k)
           (loop i p (sub1 k))]
          [else (loop (add1 i) p k)])))

请注意,之前的解决方案会就地改变输入向量。它很优雅,按预期工作:

(sortf (vector 'W 'R 'W 'B 'R 'W 'B 'B 'R))
=> '#(R R R W W W B B B)

答案 1 :(得分:2)

这是一种不使用sort或更高阶函数的解决方案。 (即没有任何乐趣) 这不是真正的排序,但它解决了你的问题,而不使用排序。 named letcase是此解决方案中最具异国情调的形式。

除非要求不使用sort,否则我不会这样做。我认为lepple's answer既优雅又易于理解。

这个解决方案是O(n)所以它可能比其他球数更多的球更快。

#!r6rs
(import (rnrs base))

(define (sort-flag lst)
  ;; count iterates over lst and counts Rs, Ws, and Bs
  (let count ((lst lst) (rs 0) (ws 0) (bs 0))
    (if (null? lst)
        ;; When counting is done build makes a list of
        ;; Rs, Ws, and Bs using the frequency of the elements
        ;; The building is done in reverse making the loop a tail call
        (let build ((symbols '(B W R))
                    (cnts (list bs ws rs))
                    (tail '()))
          (if (null? symbols)
              tail ;; result is done
              (let ((element (car symbols)))
                (let build-element ((cnt (car cnts))
                                    (tail tail))
                  (if (= cnt 0)
                      (build (cdr symbols)
                             (cdr cnts)
                             tail)
                      (build-element (- cnt 1) 
                                     (cons element tail)))))))
        (case (car lst)
          ((R) (count (cdr lst) (+ 1 rs) ws bs)) 
          ((W) (count (cdr lst) rs (+ 1 ws) bs)) 
          ((B) (count (cdr lst) rs ws (+ 1 bs)))))))

答案 2 :(得分:1)

查找例如

(define sort-lookup '((R . 1)(W . 2)(B . 3)))

(define (sort-proc a b)
  (< (cdr (assq a sort-lookup))
     (cdr (assq b sort-lookup))))

(list-sort sort-proc '(W R W B R W B B))

Runnable R6RS(IronScheme)解决方案:http://eval.ironscheme.net/?id=110

答案 3 :(得分:1)

您只需使用内置排序或已有的排序,并使用自定义谓词。

(define (follow-order lst)
 (lambda (x y)
  (let loop ((inner lst))
  (cond ((null? inner) #f) 
        ((equal? x (car inner)) #t)
        ((equal? y (car inner)) #f)
        (else (loop (cdr inner)))))))

(排序'(W R W B R W B)(按顺序'(R W B)))

;值50:(r r w w w b b)