Longest chain of element in lisp

后端 未结 1 895
说谎
说谎 2021-01-21 10:15

Statement: Sind the longest chain of character and return it. Ex: input: \'(1 2 2 3 3 3 4 4 4 4 5 6 ) ouput: \'(4 4 4 4)

Problem: I can m

相关标签:
1条回答
  • 2021-01-21 11:09

    The trick is to keep four things as you walk down the list:

    • the current chain (note: you can build these backwards, since all the elements are the same!);
    • how long it is;
    • the longest chain you've seen;
    • how long that was.

    Then you make decisions based on whether the element you are looking at is the same as the first element in the current chain (still building the same chain) or not (starting a new chain) and, if you are still building the same chain, whether that chain is now the longest.

    Like this:

    (define (longest-chain l)
      (let lc-loop ([tail l]
                    [current-length 0]
                    [current-chain '()]
                    [longest-length 0]
                    [longest-chain '()])
        (cond [(null? tail)
               ;; we're done: return the longest chain
               longest-chain]
              [(and (not (null? current-chain))
                    (eqv? (first tail) (first current-chain)))
               ;; building on a current chain
               (let ([chain (cons (first tail) current-chain)]
                     [chain-length (+ 1 current-length)])
                 (if (> chain-length longest-length)
                     ;; the current chain is now the longest
                     (lc-loop (rest tail)
                              chain-length chain
                              chain-length chain)
                     ;; it's not the longest yet
                     (lc-loop (rest tail)
                              chain-length chain
                              longest-length longest-chain)))]
              [else
               ;; starting a new chain
               (lc-loop (rest tail)
                        1 (list (first tail))
                        longest-length longest-chain)])))
    

    For extra points: if there is more than one longest chain, which one does this function return? How could you change that so it makes the other choice? Or even a random choice!


    Note the above version of the function uses named let, which is a standard construct in Scheme. If you don't want to use that you can just turn it into an explicit function:

    (define (longest-chain l)
      (define (lc-loop tail
                       current-length current-chain
                       longest-length longest-chain)
        (cond [(null? tail)
               ;; we're done: return the longest chain
               longest-chain]
              [(and (not (null? current-chain))
                    (eqv? (first tail) (first current-chain)))
               ;; building on a current chain
               (let ([chain (cons (first tail) current-chain)]
                     [chain-length (+ 1 current-length)])
                 (if (> chain-length longest-length)
                     ;; the current chain is now the longest
                     (lc-loop (rest tail)
                              chain-length chain
                              chain-length chain)
                     ;; it's not the longest yet
                     (lc-loop (rest tail)
                              chain-length chain
                              longest-length longest-chain)))]
              [else
               ;; starting a new chain
               (lc-loop (rest tail)
                        1 (list (first tail))
                        longest-length longest-chain)]))
      (lc-loop l 0 '() 0 '()))
    

    This is entirely equivalent to the above version. If you're not happy with internal defines, then you can turn lc-loop into a top-level definition.

    0 讨论(0)
提交回复
热议问题