lemma div_mod_imp_eq: ‹(a :: nat) div n = b div n ⟹ a mod n = b mod n ⟹ a = b›
by (metis div_mult_mod_eq)
lemma string_of_digit_inj:
assumes ‹a ≠ (b :: nat)› ‹a < 10› ‹b < 10›
shows ‹string_of_digit a ≠ string_of_digit b›
proof -
have ‹a ∈ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}›
using ‹a < 10›
by auto
thus ?thesis
using ‹a ≠ b› ‹b < 10›
by auto (auto split: if_splits simp: string_of_digit_def)
qed
lemma shows_prec_nat: ‹shows_prec p n '''' = (if n < 10 then string_of_digit n
else shows_prec p (n div 10) '''' @ string_of_digit (n mod 10))›
unfolding shows_prec_nat_def
proof (induction p n rule: showsp_nat.induct)
case (1 p n)
then show ?case
unfolding shows_string_def showsp_nat.simps[of p n]
by (auto simp: shows_prec_append[symmetric] shows_prec_nat_def[symmetric])
qed
lemma show_nat: ‹show n = (if n < 10 then string_of_digit n
else show (n div 10) @ string_of_digit (n mod 10))›
using shows_prec_nat .
lemma show_nat_induct:
‹(⋀n. (⋀z. ¬ n < 10 ⟹ z ∈ range (shows_string (string_of_digit (n mod 10))) ⟹ P (n div 10)) ⟹ P n) ⟹ P n›
by (rule showsp_nat.induct) blast
lemma length_string_of_digit[simp]: ‹length (string_of_digit n) = 1›
unfolding string_of_digit_def
by auto
lemma len_show_ge10: ‹(n :: nat) ≥ 10 ⟹ length (show n) ≥ 2›
unfolding show_nat[of n] show_nat[of ‹(n div 10)›]
by auto
lemma len_show_lt10: ‹(n :: nat) < 10 ⟹ length (show n) = 1›
unfolding show_nat[of n]
by auto
lemma
fixes a b :: nat
assumes ‹a ≠ b›
shows ‹show a ≠ show b›
using assms
proof (induction a arbitrary: b rule: show_nat_induct)
case (1 n)
hence ?case if ‹¬n < 10› ‹¬b < 10›
using that div_mod_imp_eq[of n 10 b] string_of_digit_inj[of ‹n mod 10› ‹b mod 10›]
by (cases ‹n div 10 = b div 10›) (auto simp: show_nat[of n] show_nat[of b])
moreover have ?case if ‹n < 10› ‹b < 10›
using 1 string_of_digit_inj that
by (auto simp: show_nat[of n] show_nat[of b])
moreover have ?case if ‹((n :: nat) < 10) ≠ ((b :: nat) < 10)›
using that len_show_ge10[of n] len_show_lt10[of b] len_show_ge10[of b] len_show_lt10[of n]
by auto
ultimately show ?case
by blast
qed