0

演習として書いたランレングス エンコーディング コードがあります。

let rle s = 
    s
    |> List.map (fun x -> (x, 1))
    |> List.fold (fun acc x -> 
        match acc with 
            | [] -> [(x, 1)]
            | h::(x, n) -> h::(x, n+1)
            | h -> h::(x, 1)
        )
    |> List.map (fun (x, n) -> 
        match n with
            | 1 -> x.ToString()
            | _ -> x.ToString() + n.ToString()
        )

パターンh::(x, n) -> h::(x, n+1)はコンパイルに失敗します。

誰かが理由を知っていますか?

4

3 に答える 3

3

RLE (笑顔)

let rle (s: string) = 
  let bldr = System.Text.StringBuilder()
  let rec start = function
    | [] -> ()
    | c :: s -> count (1, c) s
  and count (n, c) = function
    | c1 :: s when c1 = c -> count (n+1, c) s
    | s -> Printf.bprintf bldr "%d%c" n c; start s
  start (List.ofSeq s)
  bldr.ToString()

let s1 = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
let s2 = "12W1B12W3B24W1B14W"

rle s1 = s2 |> printfn "%b" //"true"
于 2013-02-12T21:07:27.123 に答える
2

これはあなたの質問への回答ではありませんが、私は退屈していたので、もう少し有益な実装を作成しました。Visual Studio または MonoDevelop のデバッガーを使用して、ステップ実行してください。

let rec private rleRec encoded lastChar count charList =
    match charList with
    | [] ->
        // No more chars left to process, but we need to
        // append the current run before returning.
        let encoded' = (count, lastChar) :: encoded

        // Reverse the encoded list so it's in the correct
        // order, then return it.
        List.rev encoded'

    | currentChar :: charList' ->
        // Does the current character match the
        // last character to be processed?
        if currentChar = lastChar then
            // Just increment the count and recurse.
            rleRec encoded currentChar (count + 1) charList'
        else
            // The current character is not the same as the last.
            // Append the character and run-length for the previous
            // character to the 'encoded' list, then start a new run
            // with the current character.
            rleRec ((count, lastChar) :: encoded) currentChar 1 charList'

let rle charList =
    // If the list is empty, just return an empty list
    match charList with
    | [] -> []
    | hd :: tl ->
        // Call the implementation of the RLE algorithm.
        // The initial run starts with the first character in the list.
        rleRec [] hd 1 tl

let rleOfString (str : string) =
    rle (List.ofSeq str)

let rec printRle encoded =
    match encoded with
    | [] ->
        printfn ""
    | (length, c) :: tl ->
        printf "%i%O" length c
        printRle tl

let printRleOfString = rleOfString >> printRle

コードを F# Interactive に貼り付け、ウィキペディアのランレングス エンコーディングの例を使用します。

> printRleOfString "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";;
12W1B12W3B24W1B14W
val it : unit = ()
于 2013-02-12T20:01:07.243 に答える
2

::パターン マッチの 2 番目の引数は でなければならないため、コンパイルできませんlistが、ここではタプルです。一般的に、あなたは と を誤解しているようheadですtail。head は最上位の要素で、tail は後続の要素のリストです。基本的にそれらを交換すると、トリックが実行されます。

|> List.fold (fun acc x -> 
    match acc with 
        | [] -> [(x, 1)]
        | (x0, n)::t when x0=x -> (x0, n+1)::t
        | t -> (x, 1)::t
    )
    []

注 1: @pad が気づいたように、List.foldもう 1 つの引数、つまり「ブートストラップ」アキュムレータを開始する必要があります。明らかに、それは単なる空のリストである必要があります[]
注 2: を直接一致させることはできませんx。代わりに、それを にバインドしてx0と比較x0xます。
注 3: 空のリストに一致[]させる必要はありません。最後のパターンで問題なく機能するからです。

于 2013-02-12T18:58:52.433 に答える