hirohirohirohirosのブログ

地方国立大学に通う情報系学部4年

Atcoder 灰diff埋め ABC079C 振り返り

atcoder problemsを見て,灰diffで未ACの問題を解いていきます.灰diffは簡単な問題も多いので,一部を抜粋して

ABC079 C - Train Ticket【AC】

 見るからに冗長なコードになっているのが残念です.

S = input()
A, B, C, D = int(S[0]), int(S[1]), int(S[2]), int(S[3])

for i in range(2**3):
    ans = A
    anslis = []
    if (i >> 0) & 1:
        ans += B
        anslis.append("+")
    else:
        ans -= B
        anslis.append("-")
    if (i >> 1) & 1:
        ans += C
        anslis.append("+")
    else:
        ans -= C
        anslis.append("-")
    if (i >> 2) & 1:
        ans += D
        anslis.append("+")
    else:
        ans -= D
        anslis.append("-")

    if ans == 7:
        print(f"{A}{anslis[0]}{B}{anslis[1]}{C}{anslis[2]}{D}=7")
        break

 AC後に全ての提出からこの問題を解いた他のコードを見てみました.パッと見た感じ一番シンプルに書かれていたのがこのコードです.

import itertools
def find_eq(abcd):
    a, b, c, d = abcd
    ops = ("+", "-")
    for op1, op2, op3 in itertools.product(ops, repeat=3):
        eq = a + op1 + b + op2 + c + op3 + d
        if eval(eq) == 7:
            return eq + "=7"

 このコードから学んだ事はいくつもあります.まず,

a,b,c,d = x

と書くことで文字列を自動的にアンパック(?)する事が出来るということです.シンプルにこう書くことで実装出来るということは初めて知りました.

x = ("+", "-")
for i, j, k in itertools.product(x, repeat=3):
    print(i, j, k)

>> +++
>> ++-
>> +-+
>> ...
  1. と-の組み合わせをどう記述するかが一番の悩みどころでしたがitertoolsを使う事でこんなにシンプルに書けるとは知りませんでした.
eval("1+1")
>> 2

演算子+, -をどうやって式に組み込むか分からずにif文をダラダラ書く事になってしまいましたが,eval関数を使えば良いと知りました.eval関数は引数を式として評価するらしく,文字列を引数に入れても式として評価され数字の結果が返ってきます.
この問題はdiff337でしたが,昔の問題と言うこともあり学ぶ所が多く良かったです.