Skip to content

Instantly share code, notes, and snippets.

@neilmayhew
Created June 5, 2015 04:44
Show Gist options
  • Save neilmayhew/3f0bd8ac60feccef526a to your computer and use it in GitHub Desktop.
Save neilmayhew/3f0bd8ac60feccef526a to your computer and use it in GitHub Desktop.
Print trees of factors of integers
// Display trees of factors of integers
// Tree type
type 'a Tree =
| Branch of 'a * 'a Tree * 'a Tree
| Leaf of 'a
// Computation of Trees of factors
let divisor n =
let top = int << sqrt << float << abs <| n
let divides a b = a % b = 0
List.find <| divides n <| List.rev [1 .. top]
let rec factorTree n =
let x = divisor n
let y = n / x
if x = 1 || y = 1
then Leaf n
else Branch (n, factorTree x, factorTree y)
// Utility functions
// Like the standard map2 but works with lists on unequal length
// d, e are default values that can be appended to either of the lists
let rec map2' f (d, e) = function
| x::xs, y::ys -> f x y :: map2' f (d, e) (xs, ys)
| x::xs, ys -> f x e :: map2' f (d, e) (xs, ys)
| xs, y::ys -> f d y :: map2' f (d, e) (xs, ys)
| _, _ -> []
let product = Seq.fold ( * ) 1
let factorial n = product [1..n]
let (^^) = pown // Integer power
let isEven n = n % 2 = 0
// Formatting of Trees
let pad n = String.replicate n " "
let position w s i = String.concat "" [pad i; s; pad <| w - i - String.length s]
let centre w s = position w s <| (w - String.length s) / 2
let rec width = function
| Leaf a -> String.length (string a)
| Branch (a, l, r) -> width l + 1 + width r
let rec render = function
| Leaf a -> [string a]
| Branch (a, l, r) as this ->
let w = width this
let label = centre w <| string a
let arms = centre w <| if isEven << String.length <| string a then "/\\" else "/ \\"
let (dl, dr) = (pad <| width l, pad <| width r)
let splice l r = String.concat " " [l; r]
let children = map2' splice (dl, dr) (render l, render r)
label :: arms :: children
let show = String.concat "\n" << render
// Main
[<EntryPoint>]
let main args =
let nums =
if not << Array.isEmpty <| args
then Array.map int args
else [| 1040 // Small tree
; factorial 12 // Large tree
; 1510259 * (2^^10) // Unbalanced tree
|]
let printTree = printfn "%s\n" << show << factorTree
Array.iter printTree nums
0 // Program exit value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment