Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Created December 21, 2011 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save missingfaktor/1507246 to your computer and use it in GitHub Desktop.
Save missingfaktor/1507246 to your computer and use it in GitHub Desktop.
! A simple program that generates Excel spreadsheet column id corresponding to given column number.
! For example:
! 14 - N
! 26 - Z
! 27 - AA
! 29 - AC
USING: kernel math math.ranges sequences strings ;
IN: excel-columns
! Use the following after 'alphabet' definition to make it a compile time constant.
! << \ alphabet alphabet define-constant >>
: alphabet ( -- seq ) CHAR: A CHAR: Z [a,b] ;
: nth-char ( n -- char ) 25 + 26 mod alphabet nth 1string ;
: break-26 ( m -- n o ) 26 /mod ;
: column-id ( i -- str ) dup 26 <= [ nth-char ] [ break-26 [ column-id ] bi@ append ] if ;
: test-run ( -- ) 1000 [1,b] [ dup column-id 2array . ] each ;
MAIN: test-run
import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.Instances
import qualified Data.Vector as V
-- Y U NO IN STANDARD LIBRARY????!!!!
if' :: Bool -> a -> a -> a
if' cond x y = if cond then x else y
alphabet :: Vector Char
alphabet = V.enumFromTo 'A' 'Z'
nthChar :: Int -> String
nthChar = (:[]) . (alphabet V.!) . (`mod` 26) . (+ 25)
break26 :: Int -> (Int, Int)
break26 = (`divMod` 26)
columnId :: Int -> String
columnId = if' <$> (<= 26) <*> nthChar <*> uncurry (++) . join (***) columnId . break26
main :: IO ()
main = forM_ [1..100] (print . (id &&& columnId))
@DanielOberg
Copy link

There is a tool for it. :D

daniel@Macbook ~ % pointfree -v "\x y -> (y \`div\` x, y \`mod\` x)"
Transformed to pointfree style:
ap (ap . ((,) .) . flip div) (flip mod)
let break26' = (ap (ap . ((,) .) . flip div) (flip mod)) 26

@missingfaktor
Copy link
Author

@DanielOberg: Yes, I know about that tool. (It's the same thing as lambdabot's @pl, right?) I meant, can you write something that can be "read"? Sections of (.) don't count (as I said here: http://missingfaktor.blogspot.com/2011/12/sections-of.html). I wrote the columnId definition without any help from lambdabot, and I find it readable. The data flow is easy to visualize. Can we do something like that for break26?

@DanielOberg
Copy link

We can simplify it a bit without much effort:

(ap ((&&&) . flip div) (flip mod)) 26

@missingfaktor
Copy link
Author

@DanielOberg: That one looks cool. Thanks!

@chris-taylor
Copy link

To write break26 while only using 26 once, why not write

let break26 = (`divMod` 26)

@missingfaktor
Copy link
Author

@chris-taylor: Thanks. I wasn't aware of that function. Turns out Factor has /mod as well. Will update the snippets accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment