逆FizzBuzz問題
最近ぞっぷりと linq に染まっていたので、関数の入れ子をより気持ち悪く感じて困る. python にも組み込み linq を誰か.
from itertools import count, cycle, islice, ifilter def FizzBuzz(): seq = [None, None, "Fizz", None, "Buzz", "Fizz", None, None, "Fizz", "Buzz", None, "Fizz", None, None, "FizzBuzz"] for i, e in enumerate(cycle(seq)): if e == None: yield i + 1 else: yield e def skip(itrerable, count): return islice(itrerable, count, None) def take(itrerable, count): return islice(itrerable, count) def InverseFizzBuzz(seq): def work(start, count): i = start c = count a = [] for x in skip(FizzBuzz(), start - 1): if c == 0: l = i - start return (a, l, range(start, start + l)) if not isinstance(x, int): a += [x] c -= 1 i += 1 start_list = { "Fizz": [3, 6, 9, 12], "Buzz": [5, 10], "FizzBuzz": [15] } if len(seq) == 0: return None if not (seq[0] in start_list): return None candidates = list(ifilter(lambda x: x[0] == seq, [work(i, len(seq)) for i in start_list[seq[0]]])) if len(candidates) == 0: return None else: return list(sorted(candidates, cmp = lambda x, y: x[1] - y[1]))[0][2] assert InverseFizzBuzz(["Fizz"]) == range(3, 4) assert InverseFizzBuzz(["Buzz"]) == range(5, 6) assert InverseFizzBuzz(["Fizz", "Buzz"]) == range(9, 11) assert InverseFizzBuzz(["Buzz", "Fizz"]) == range(5, 7) assert InverseFizzBuzz(["Fizz", "Buzz", "Fizz"]) == range(3, 7) assert InverseFizzBuzz(["Buzz", "Fizz", "Buzz"]) == None assert InverseFizzBuzz(["Fizz", "Fizz"]) == range(6, 10) assert InverseFizzBuzz(["Fizz", "Fizz", "Buzz"]) == range(6, 11)
追記: 無駄があった・・・
def InverseFizzBuzz(seq): def work(start, count): i = start c = count a = [] for x in skip(FizzBuzz(), start - 1): if c == 0: l = i - start return (a, l, range(start, start + l)) if not isinstance(x, int): a += [x] c -= 1 i += 1 candidates = list(ifilter(lambda x: x[0] == seq, [work(i, len(seq)) for i in [3, 5, 6, 9, 10, 12, 15]])) if len(candidates) == 0: return None else: return list(sorted(candidates, cmp = lambda x, y: x[1] - y[1]))[0][2]