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
The trick is to keep four things as you walk down the list:
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 define
s, then you can turn lc-loop
into a top-level definition.