Excel列名変換問題やってみた。

Excel列名変換問題で第2回社内プログラミングコンテストを開催してみた(前編) - give IT a try

最初にperlでやってみてから、haskellでもだいたいおんなじ感じで書いてみた。
haskellの方は出入力とかよくわかんない。

use strict;
use warnings;
use utf8;

sub col_conv {
    my $str = shift;
    my $n   = shift;

    if(length($str) == 0) {
        return $n;
    }

    $n *= 26;
    $n += ord($str) - ord('A') + 1;

    return
        col_conv(
            substr($str, 1),
            $n );
}

sub conv_col {
    my $str = shift;
    my $n   = shift;
    # my $rem = $n % 26;
    my $rem = ($n + 25) % 26;
    # my $left = ($n - $rem) / 26;
    my $left = ($n - $rem - 1) / 26;

    if($n == 0) {
        return $str;
    } else {
        return
            conv_col(
                chr($rem - 1 + ord('A')) . $str,
                $left );
    }
}

my $type = $ARGV[0];
my $input = $ARGV[1];

if($type == 0) {
    print col_conv($input, 0), "\n";
} else {
    print conv_col("", $input), "\n";
}
import Data.Char
import System

colConv' :: String -> Int -> Int
colConv' [] n = n
colConv' (x:xs) n = colConv' xs n'
    where
        n' = n * 26 + ord(x) - ord('A') + 1
colConv strs = colConv' strs 0

convCol' :: String -> Int -> String
convCol' strs 0 = strs
convCol' strs n =
        convCol' (s : strs) left 
        where
            an = ord('A')
            -- rem = n `mod` 26
            rem = (n + 25) `mod` 26
            s = chr(rem - 1 + an)
            -- left = (n - rem) `div` 26
            left = (n - rem - 1) `div` 26
convCol = convCol' ""

main = do
    args <- getArgs
    let [cvtype, input] = args
    if (read cvtype::Int) == 0
        then putStrLn $ show $ colConv input
        else putStrLn $ convCol $ (read input::Int)

[追記]convColの方でバグがあったので修正[/追記]