「「1から9までの数字を一回ずつ使って2010にする」の検算」の検算2
お世話になっております。
一昨日の「1から9までの数字を一回ずつ使って2010にする」の検算は、小数の計算に問題があるという指摘を受けました。(http://takanory.net/takalog/1192)
解き方も教えていただきましたが、自分でもやってみないとダメだろうと思い、分数クラスを作って解いてみました。
結果、すべて2010という答えが出ました。
以下、コードです。
fraction.py
# -*- coding: sjis -*- class Fraction(object): @staticmethod def parse(s): assert isinstance(s, str) if '.' in s: numerator = s.replace('.', '') splitted = s.split('.') denominator = 10 ** len(splitted[1]) return Fraction(int(numerator), int(denominator)) else: return Fraction(int(s)) def __init__(self, numerator, denominator=1): assert denominator != 0 assert isinstance(numerator, int) assert isinstance(denominator, int) self._num = numerator self._den = denominator euc = self._euc() assert isinstance(euc, int) self._num = int(self._num / euc) self._den = int(self._den / euc) def __add__(self, another): assert isinstance(another, Fraction) new_den = self._den * another._den new_self_num = self._num * another._den new_another_num = another._num * self._den new_num = new_self_num + new_another_num return Fraction(new_num, new_den) def __sub__(self, another): assert isinstance(another, Fraction) new_den = self._den * another._den new_self_num = self._num * another._den new_another_num = another._num * self._den new_num = new_self_num - new_another_num return Fraction(new_num, new_den) def __mul__(self, another): assert isinstance(another, Fraction) new_num = self._num * another._num new_den = self._den * another._den return Fraction(new_num, new_den) def __div__(self, another): assert isinstance(another, Fraction) reversed_num = another._den reversed_den = another._num return self * Fraction(reversed_num, reversed_den) def __truediv__(self, another): return self.__div__(another) def __eq__(self, another): if not isinstance(another, Fraction): return False numIsEqual = self._num == another._num denIsEqual = self._den == another._den if numIsEqual and denIsEqual: return True else: return False def __str__(self): num = self._num den = self._den return ('%d/%d' % (num, den)).strip('/1') def __repr__(self): return str(self) def _euc(self): m = 0 n = 0 if self._num >= self._den: m = self._num n = self._den else: m = self._den n = self._num if n == 0: return m while True: temp = m % n if temp == 0: return n else: m = n n = temp import unittest as UT class FractionTestCase(UT.TestCase): def setUp(self): self.one_3rd = Fraction(1, 3) self.one_2nd = Fraction(1, 2) def testCalculate(self): expected = Fraction(1) calculated = (Fraction(1) / Fraction(3)) * Fraction(3) self.assertEqual(expected, calculated) def testAdd(self): answer = self.one_3rd + self.one_2nd self.assertEqual(answer, Fraction(5, 6)) answer = self.one_3rd + self.one_3rd self.assertEqual(answer, Fraction(6, 9)) def testSub(self): answer = self.one_3rd - self.one_2nd self.assertEqual(answer, Fraction(-1, 6)) def testMul(self): answer = self.one_3rd * self.one_2nd self.assertEqual(answer, Fraction(1, 6)) def testDiv(self): answer = self.one_3rd / self.one_2nd self.assertEqual(answer, Fraction(2, 3)) def testEqual(self): self.assertEqual(Fraction(1), Fraction(1)) self.assertNotEqual(Fraction(1), 1) self.assertNotEqual(Fraction(1), None) def testParse(self): self.assertEqual(Fraction.parse('100'), Fraction(100)) self.assertEqual(Fraction.parse('100.1'), Fraction(1001, 10)) self.assertEqual(Fraction.parse('.1'), Fraction(1, 10)) if __name__ == '__main__': # run unittest UT.main()
src.py
# -*- coding: sjis -*- import httplib, re from fraction import * REGEX = re.compile("^2010 = (.+?)$", re.M) REGEX_NUM = re.compile(r"([\.0-9]+)") conn = None try: conn = httplib.HTTPConnection('www.thesamet.com') conn.request('GET', '2010.txt') res = conn.getresponse() body = res.read() equal_count = 0 total_count = 0 for matched in REGEX.findall(body): cmd = matched cmd = REGEX_NUM.sub(r"Fraction.parse('\1')", cmd) result = eval(cmd) if Fraction(2010) == result: equal_count += 1 total_count += 1 print cmd + ':' + str(result) print 'eq/total %d/%d' % (equal_count, total_count) finally: if conn: conn.close()
以上