2

以下のコードを「文字列」を返すように変更して、出力を MVC ページに表示し、enteredCharユーザーから受け入れたいと思うようにする方法。

このピラミッドを作成するより良い方法はありますか?

現在のコード:

let enteredChar = 'F' // As Interactive window doesn't support to Read Input
let mylist = ['A'..enteredChar] 
let mylistlength = mylist |> List.length
let myfunc i x tlist1 =
    (for j = 0 to mylistlength-i-2 do printf "%c" ' ')
    let a1 = [for p in tlist1  do if p < x then yield p]
    for p in a1 do printf "%c" p
    printf "%c" x
    let a2 = List.rev a1
    for p in a2 do printf "%c" p
    printfn "%s" " "

mylist |> List.iteri(fun i x -> myfunc i x mylist)

出力:

     A
    ABA
   ABCBA
  ABCDCBA
 ABCDEDCBA
ABCDEFEDCBA
4

5 に答える 5

4

いくつかの小さな最適化は次のとおりです。

  • StringBuilder代わりにwhich を使用するprintfと、長い文字列ではかなり遅くなります。
  • sinceArrayの代わりに使用してください。ListArrayString

これはピラミッド文字列を生成するバージョンで、コードに密接に保持されています。

open System
open System.Text

let generateString c = 
    let sb = StringBuilder()             
    let generate i x arr =
        String.replicate (Array.length arr-i-1) " " |> sb.Append |> ignore
        let a1 = Array.filter (fun p -> p < x) arr
        String(a1) |> sb.Append |> ignore
        sb.Append x |> ignore
        String(Array.rev a1) |> sb.Append |> ignore
        sb.AppendLine " " |> ignore

    let arr = [|'A'..c|]               
    arr |> Array.iteri(fun i x -> generate i x arr)
    sb.ToString()

generateString 'F' |> printfn "%s"
于 2012-07-06T15:51:55.360 に答える
2
let pyramid (ch:char) = 
  let ar = [| 'A'..ch |]
  let len = ar.Length
  Array.mapi
    (fun i ch -> 
      let ar = ar.[0..i]
      String.replicate (len - i - 1) " " + new string(ar) + new string((Array.rev ar).[1..]))
    ar
  |> String.concat "\n" 

pyramid 'F' |> printfn "%s"
于 2012-07-07T01:53:28.973 に答える
2

あなたの質問を理解した場合 (これはおそらくCode Reviewに属します)、関数を書き直す 1 つの方法を次に示します。

let showPyramid (output: TextWriter) lastChar =
  let chars = [|'A' .. lastChar|]

  let getRowChars n = 
    let rec loop acc i =
      [|
        if i < n then let c = chars.[i] in yield c; yield! loop (c::acc) (i+1)
        else yield! List.tail acc
      |]
    loop [] 0

  let n = chars.Length
  for r = 1 to n do 
    output.WriteLine("{0}{1}{0}", String(' ', n - r), String(getRowChars r))

showPyramid Console.Out 'F'

または、文字列に出力する

use output = new StringWriter()
showPyramid output 'F'
let pyramid = output.ToString()

編集

トーマスの答えを見た後、あなたの質問で「文字列を返す」をスキップしたことに気付きました。コードを更新し、例を追加して、それを行う方法を示しました。

于 2012-07-06T15:39:20.567 に答える
2

これは、機能構成の良いデモンストレーションと思われる別のアプローチです。ここでの回答の中で、それが最短の解決策だと思います。:)

let charsToString = Seq.map string >> String.concat String.Empty
let pyramid lastChar =
    let src = '-'::['A'..lastChar] |> List.toArray
    let len = Array.length src - 1

    fun row col -> row-abs(col-len+1)+1 |> max 0 |> Array.get src   // (1)
    >> Seq.init (len*2-1) >> charsToString                          // (2)
    |> Seq.init len                                                 // (3)

pyramid 'X' |> Seq.iter (printfn "%s")
  • まず、初期データの異常な配列を生成します。その要素[0]には、スペースまたは必要な区切り文字が含まれています。-私はデバッグ目的でダッシュ ( ) を好みました。
  • この(1)行は、配置する文字を計算する関数を作成します。の結果は、(および配置される char がある) またはzeronegativerow-abs(col-len+1)+1のいずれかであり、スペースが必要です。ステートメントがないことに注意してください。関数 内に隠されています。ifmax
  • 行は、個々の行を生成する関数を構成(2)します。int -> string
  • この(3)行は、シーケンス初期化子の引数として上記の関数を渡します。

3 行は、より冗長な方法で記述できます。

    let genCell row col = row-abs(col-len+1)+1 |> max 0 |> Array.get src 
    let genRow = genCell >> Seq.init (len*2-1) >> charsToString
    Seq.init len genRow

NotegenRowは関数構成のため、正式な引数を必要としません: 引数は にバインドされgenCell、単一の引数の関数を返します。まさにSeq.init必要なものです。

于 2012-07-07T14:27:32.680 に答える
2

ダニエルのソリューションの代替として、コード ロジックへの変更を最小限に抑えて、目的を達成できます。printfthat を使用して出力をコンソールに書き込む代わりに、Printf.bprintfwhich を使用して出力を指定された に書き込むことができますStringBuilder。次に、結果の文字列をStringBuilder.

変更された関数は次のようになります。パラメータを追加し、 (および追加の文字と一緒に)str置き換えました:printfPrintf.bprintf strprintfnbprintf\n

let myfunc i x tlist1 str = 
    (for j = 0 to mylistlength-i-2 do Printf.bprintf str "%c" ' ') 
    let a1 = [for p in tlist1  do if p < x then yield p] 
    for p in a1 do Printf.bprintf str "%c" p 
    Printf.bprintf str "%c" x 
    let a2 = List.rev a1 
    for p in a2 do Printf.bprintf str "%c" p 
    Printf.bprintf str "%s\n" " " 

関数を呼び出すには、最初に作成してから、すべての呼び出しでにStringBuilder渡します。最後に、メソッドmyfuncを使用して結果を取得できます。ToString

let str = StringBuilder()
mylist |> List.iteri(fun i x -> myfunc i x mylist str) 
str.ToString()

ダニエルのソリューションの方が見栄えが良いと思いますが、これは印刷コードを文字列構築コードに変換する最も直接的な方法です (ほとんどの場合、検索と置換を使用して実行できます)。

于 2012-07-06T15:46:14.527 に答える