取り出してはいけない1個の数字はいくつ?

※記法については『算数の問題文の記法のまとめ【随時更新】 - 算数の問題文の記法を考える』を読んでください。


【1999年度ジュニア算数オリンピックトライアル問題1問目】
1から9までの数字が1こずつあります。この中から8この数字を取り出して、その和が39になるようにしたいとおもいます。取り出してはいけない1この数字はいくつですか。


【記法化】

num_group := {1, 2, 3, 4, 5, 6, 7, 8, 9};

実行;

pick_num_group := 被りなしで8つ移動 := num_group.every;

実行;

pick_num_group.合計 == 39;
answer == num_group.1個;
print(answer);


【工夫】

num_group := {1, 2, 3, 4, 5, 6, 7, 8, 9};

実行;

answer == num_group.合計 - 39;

実行;

除去(num_group, answer);

実行;

num_group.合計 == 39;
print(answer)

8個取り出した数字の和が39になれば良いだけなので、
「pick_num_group := 被りなしで8つ移動 := num_group.every;
 実行;
 pick_num_group.合計 == 39;」
の部分は丸々不要。合計39移動≒合計39引き算に置き換えた。ただしその後に検算は必要になる。
自分としてもスッキリしないけど、分類としてはやらなくて良い演算過程の省略となるんじゃないか(あるいは未整理だが全体の利用か?)。これで9つから被りなしで8つ選ぶ、つまり9通りの試行が、結果的に1通りになった。

お兄さんは何才になったのでしょうか?

※記法については『算数の問題文の記法のまとめ【随時更新】 - 算数の問題文の記法を考える』を読んでください。


【1997年度ジュニア算数オリンピックトライアル問題1問目】
ぼくのお兄さんは、西暦ABCD年の生れです。
1997年の今年、ぼくのお兄さんの年令は、A+B+C+Dになりました。ぼくのお兄さんは何才になったのでしょうか。


【記法化】

Aは0から9の整数である;
Bは0から9の整数である;
Cは0から9の整数である;
Dは0から9の整数である;
birth_year == 1000*A + 100*B + 10*C + D;
1997 - birth_year == age;
age == A + B + C + D;

実行;

print(age);


【工夫】

Aは0から9の整数である;
Bは0から9の整数である;
Cは0から9の整数である;
Dは0から9の整数である;
birth_year == 1000*A + 100*B + 10*C + D;
1997 - birth_year == age;
age == A + B + C + D;

A.最小 + B.最小 + C.最小 + D.最小 <= age <= A.最大 + B.最大 + C.最大 + D.最大;

age→birth_yearの順番で実行;

print(age);

どうだろう。「A.最小 + B.最小 + C.最小 + D.最小 <= age <= A.最大 + B.最大 + C.最大 + D.最大;」は、内部ですでに実行されているべきな気もする。10の4乗通りageが用意される所を、これならば37通りにまで削減できる。

また、実行に際しても、A、B、C、Dの順番で基準にしていったら10の4乗通り実行される所を、これならば37通りに削減できるのではないか。しかし例えば「age==1」と仮定した実行時に、定数を優先的に処理して「1000*A + 100*B + 10*C + D == 1997 - 1;」と実行される所までは良いとして、「A == 1; B == 9; C == 9; D == 6;」と自動的に仮定される所まで行くだろうか。人間からすれば「1996」は「1000*1 + 100*9 + 10*9 + 6」であり、ABCDが0から9である以上は、例えば「10*B」が1の位や100の位に入り込むことはないと分かるのだが。

また、そもそも「age→birth_yearの順番で実行;」の段階で、「A.最小 + B.最小 + C.最小 + D.最小 <= age <= A.最大 + B.最大 + C.最大 + D.最大;」という制約を基準に処理される必要があり、「age == A + B + C + D;」という制約が入り込んではいけない。これも問題だ。

解答を見る限りでは、これらの工夫により計算量を削減していた。