Created
June 5, 2015 04:44
-
-
Save neilmayhew/3f0bd8ac60feccef526a to your computer and use it in GitHub Desktop.
Print trees of factors of integers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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