Excel列名変換問題で第2回社内プログラミングコンテストを開催してみた
Perl 書けないので Ruby と Python で書いた。あとコマンドラインで引数渡して……という部分は省いて、それぞれ単純な関数にしてある。
Ruby
# encoding: UTF-8
CHARS = ('A'..'Z').to_a
def number_to_char(number)
raise ArgumentError if number < 1
result = ''
while number > 0
number, remainder = (number - 1).divmod(26)
result.prepend(CHARS[remainder])
end
result
end
def char_to_number(char)
raise ArgumentError unless char =~ /^[A-Z]*$/
char.each_char.inject(0) { |sum, c| sum * 26 + CHARS.index(c) + 1 }
end
input = 'XFD'
number = char_to_number(input)
char = number_to_char(number)
puts "Input: #{input} to Number: #{number} to Char: #{char}"
Ruby 1.9.3 で確認。
Python
# -*- coding: utf-8 -*-
import string
import re
from functools import reduce
CHARS = string.ascii_uppercase
def number_to_char(number):
if number < 0: raise ValueError
result = ''
while number > 0:
number, remainder = divmod(number - 1, 26)
result = CHARS[remainder] + result
return result
def char_to_number(char):
if not re.match(r'^[A-Z]*$', char): raise ValueError
return reduce(lambda sum, c: sum * 26 + CHARS.index(c) + 1, char, 0)
input = 'XFD'
number = char_to_number(input)
char = number_to_char(number)
print("Input: {0} to Number: {1} to Char: {2}".format(input, number, char))
Python 2.7.2、Python 3.2.2 で確認。
最初に Ruby の方を大体制限時間内で書いて、あとから友だちの Rubyist、@hidachinoiro に教えてもらったりしてリファクタリング。その後 Python に移植。
Perl で書くともっと難しそう。Ruby 最初からいろいろできて便利。Python は Ruby と同じことするのに3つもモジュールをインポートしてる1 けど、やろうと思えばモジュール使わずに同じ機能を実装できる。コードの量は増える。
プログラミングコンテストとしては現実にありそうな良問だと思う。ただ慣れてる人ならもっと簡単に解けそう。