この場合、「帰納的に」を「反復回数にわたる帰納」と解釈します。
これを行うには、最初にいわゆるloop-invariantを確立します。この場合、ループ不変条件は次のとおりです。
count
k
より小さいインデックスで割り切れる数の数を格納しますi
。
この不変条件は、ループの入り口で保持され、ループの後 ( when i = n
)が配列全体でcount
割り切れる値の数を保持することを保証します。k
誘導は次のようになります。
基本ケース: ループ不変式はループ エントリで保持されます (0 回の反復後)
は 0 に等しいためi
、 より小さいインデックスを持つ要素はありませんi
。したがって、 より小さいインデックスを持つ要素i
は で割り切れませんk
。したがって、count
は 0 に等しいので、不変式が成り立ちます。
帰納仮説:ループの先頭で不変条件が成り立つと仮定します。
帰納的ステップ:ループ本体の底で不変条件が成り立つことを示します。
本体が実行された後、i
1 ずつインクリメントされています。ループの最後で保持されるループ不変条件については、count
それに応じて調整されている必要があります。
a[i]
(新しい) よりも小さいインデックスを持つ要素 ( ) がもう 1 つあるためi
、が で割り切れるcount
場合 (およびその場合にのみ) は 1 ずつインクリメントされるべきであり、これはまさに if ステートメントによって保証されます。a[i]
k
したがって、本体が実行された後もループ不変条件が保持されます。
Qed。
Hoare ロジックでは、(形式的に) 次のように証明されています (明確にするために while ループとして書き直しています)。
{ I }
{ I[0 / i] }
i = 0
{ I }
while (i < n)
{ I ∧ i < n }
if (check(a[i], k) = true)
{ I[i + 1 / i] ∧ check(a[i], k) = true }
{ I[i + 1 / i][count + 1 / count] }
count = count + 1
{ I[i + 1 / i] }
{ I[i + 1 / i] }
i = i + 1
{ I }
{ I ∧ i ≮ n }
{ count = ∑ 0 x < n; 1 if a[x] ∣ k, 0 otherwise. }
(不変I
式) は次のとおりです。
count
= ∑<sub>x < i a[x]
∣<em>k の場合は 1、それ以外の場合は 0。
(任意の 2 つの連続するアサーション行 ( {...}
) には、証明義務 (最初のアサーションは次のアサーションを含意する必要があります) があります。これは、読者の演習として残しておきます ;-)