#!/usr/bin/env stack {- stack script --resolver lts-16.27 --install-ghc --ghc-options -Wall --ghc-options -Wno-unused-imports --ghc-options -Wno-name-shadowing -} {-# language NoImplicitPrelude #-} {-# language DuplicateRecordFields #-} import Rebase.Prelude import Control.Lens import Data.Ratio import Text.Printf formatFeet :: RealFrac a => a -> String formatFeet 0 = "0" formatFeet l = unwords $ toList (feet f) ++ toList (inches i n d) where feet 0 = Nothing feet f = Just $ printf "%d'" f inches 0 0 _ = Nothing inches i 0 _ = Just $ printf "%d\"" i inches 0 n d = Just $ printf "%d/%d\"" n d inches i n d = Just $ printf "%d %d/%d\"" i n d n = numerator t d = denominator t (f, i, t) = toCarpenter l toCarpenter :: RealFrac a => a -> (Int, Int, Ratio Int) toCarpenter l = (feet, div r 32, mod r 32 % 32) where (feet, r) = divMod (round $ l * 32) (32 * 12) type Inches = Rational boardLength, boardThickness, kickerHeight, availableSpace :: Inches boardLength = 6 * 12 boardThickness = 5/8 kickerHeight = 4 + 1/2 numHorizontals, numShelves :: Int numShelves = length shelves numHorizontals = numShelves + 1 availableSpace = boardLength - kickerHeight - (toRational numHorizontals) * boardThickness shelves :: [Inches] shelves = map (* availableSpace) $ map (% 18) [4, 4, 4, 3, 3] positions, positions' :: [Inches] positions = map sum $ (tail . inits) $ concatMap (: [boardThickness]) $ kickerHeight : shelves positions' = map (boardLength -) positions main :: IO () main = do -- assert $ sum shelves == 1 mapM_ putStrLn $ formatFeet <$> positions putStrLn "" mapM_ putStrLn $ formatFeet <$> positions' return ()