1-- Divisibility by three is decided by the sum of the decimal digits2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.NumberTheory.DigitSum8import Divisibility9import Core.List1011-- A list of digits, least significant first, and the number it writes.12def digitsValue (ds : List(ℕ)) →Nat13| [] =>014| d :: rest => add(d, mul(10, digitsValue(rest)))1516def digitSum (ds : List(ℕ)) →Nat17| [] =>018| d :: rest => add(d, digitSum(rest))1920theorem digitsValue.nil21shows digitsValue([]) =022proof23simp2425theorem digitsValue.cons (d : Nat) (rest : List(ℕ))26shows digitsValue(d :: rest) = d +10* digitsValue(rest)27proof28unfold digitsValue29rfl3031theorem digitSum.nil32shows digitSum([]) =033proof34simp3536theorem digitSum.cons (d : Nat) (rest : List(ℕ))37shows digitSum(d :: rest) = d + digitSum(rest)38proof39unfold digitSum40rfl4142-- A number exceeds its digit sum by a multiple of three, because every power43-- of ten is one more than a multiple of three.44theorem digitsValue.digitSum_difference (ds : List(ℕ))45shows∃ k, Nat(k) ∧ digitsValue(ds) = digitSum(ds) +3* k46proof47induction ds48| List.nil =>49have zeroNat : Nat(0) bytypecheck50refine⟨0, zeroNat, ?_⟩51rw [digitsValue.nil, digitSum.nil]52compute53| List.cons(d, rest) using ih =>54obtain⟨k, kNat, equation⟩:= ih55have witnessNat : Nat(3* digitSum(rest) +10* k) bytypecheck56refine⟨3* digitSum(rest) +10* k, witnessNat, ?_⟩57rw [digitsValue.cons, digitSum.cons, equation]58have ten : 10=3*3+1bycompute59rw ten60ring6162-- Three divides a number exactly when it divides the sum of its digits.63theorem digitsValue.three_divides_iff (ds : List(ℕ))64shows3 ∣ digitsValue(ds) ↔3 ∣ digitSum(ds)65proof66obtain⟨k, kNat, equation⟩:= digitsValue.digitSum_difference at ds with*67haveself:= divides.reflexive with*68have multiple := divides.multiply_right with*69rw equation70constructor71 . intro whole72exact divides.add_cancel_right at3, digitSum(ds), 3* k with*73 . intro digits74exact divides.add with*75