Sunday, July 18, 2010

Dynamically changing format statements in the F# ISE

This had me stuck yesterday – how to change the width of  some formatted printf output. In the end with a bit of searching I realised the TextWriterFormat member gives you a way to define the format such that you can change it in your program. An example is a better viewer for the Pascals Triangle sequence generator I made recently – all related to a school math project. Also – where does it tell you that to print a % you need to double it? Why didn’t they do as with speech marks and use a leading \?

let rec PascalsTriangle = seq {
yield [1];
for aLine in PascalsTriangle
->
let
newLine =
aLine
|> Seq.pairwise
|> Seq.map (fun (x,y) -> x+y)
|> Seq.toList
List.append (1::newLine) [1]
}

PascalsTriangle |> Seq.take 10
//|> Seq.iter (fun i -> printfn "%A" i)
|> Seq.iter (fun v
->
v |> Seq.iter (fun w -> printf "%3i" w)
printfn
""
)

// smarten up the printing...
let samplePT = PascalsTriangle |> Seq.take 12
let maxDigits = (Seq.concat samplePT |> Seq.max).ToString().Length
let numberFormatter digits = Printf.TextWriterFormat<int->unit>(sprintf "%%%dd" digits)
let spaceFormatter digits = Printf.TextWriterFormat<string->unit>(sprintf "%%%ds" digits)
let rows = Seq.length samplePT
samplePT |> Seq.iteri ( fun u v
->
for
i in 1..((rows / 1) - u)
do
printf (spaceFormatter ((int)((maxDigits+1)/2)))
" "
v |> Seq.iter (fun w -> printf (numberFormatter (maxDigits+1)) w)
printfn
""
)


The output is like this:


                      1

                    1   1


                  1   2   1


                1   3   3   1


              1   4   6   4   1


            1   5  10  10   5   1


          1   6  15  20  15   6   1


        1   7  21  35  35  21   7   1


      1   8  28  56  70  56  28   8   1


    1   9  36  84 126 126  84  36   9   1


  1  10  45 120 210 252 210 120  45  10   1


1  11  55 165 330 462 462 330 165  55  11   1


Wish I knew how to do this in WPF…



Wish I knew a better way to post into the blog…

No comments: