Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return string and code optimisation in F#

How to modify below code to Return "string" so that returned output displayed on my MVC page and also would like to accept enteredChar from user.

Is there better way to do create this pyramid?

Current code:

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)

Output:

     A
    ABA
   ABCBA
  ABCDCBA
 ABCDEDCBA
ABCDEFEDCBA
like image 947
swapneel Avatar asked Mar 05 '26 14:03

swapneel


2 Answers

A few small optimizations could be:

  • Use StringBuilder instead of printf which is quite slow with long strings.
  • Use Array instead of List since Array works better with String.

Here is a version producing a pyramid string, which is kept closely to your code:

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"
like image 130
pad Avatar answered Mar 07 '26 06:03

pad


As an alternative to Daniel's solution, you can achieve what you want with minimal changes to the code logic. Instead of using printf that writes the output to the console, you can use Printf.bprintf which writes the output to a specified StringBuilder. Then you can simply get the resulting string from the StringBuilder.

The modified function will look like this. I added parameter str and replaced printf with Printf.bprintf str (and printfn with bprintf together with additional \n char):

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" " " 

To call the function, you first create StringBuilder and then pass it to myfunc in every call. At the end, you can get the result using ToString method:

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

I think Daniel's solution looks nicer, but this is the most direct way to tunr your printing code into a string-building code (and it can be done, pretty much, using Search & Replace).

like image 40
Tomas Petricek Avatar answered Mar 07 '26 07:03

Tomas Petricek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!