Zulip Chat Archive
Stream: Is there code for X?
Topic: giving a value a name, for `induction`
David Renshaw (Sep 06 2023 at 19:30):
import Mathlib.Data.Nat.Digits
import Mathlib.Data.Nat.Parity
theorem Nat.digits_add'
(b : ℕ) (hb : 1 < b) (x y : ℕ) (hxb : x < b) (hx0 : x ≠ 0) :
Nat.digits b (x * b ^ (Nat.digits b y).length + y) =
Nat.digits b y ++ [x] := by
-- I want to do induction on the list `Nat.digits b y`. These
-- next two lines are to give that value a name. Is there
-- a nicer way to accomplish this?
have hd : ∃ ds, ds = Nat.digits b y := exists_eq
obtain ⟨ds, hd⟩ := hd
revert x y
induction ds with
| nil => sorry
| cons d ds ih => sorry
David Renshaw (Sep 06 2023 at 19:32):
I find myself doing this dance often:
- construct a trivial existential
- immediately unpack it
The point is that I need the value to have a name so that I can do induction
with it.
Is there a better way to do this?
Alex J. Best (Sep 06 2023 at 19:33):
You can do induction Nat.digits b y with
, is that what you are asking for?
David Renshaw (Sep 06 2023 at 19:35):
That fails because of the revert x y
line.
David Renshaw (Sep 06 2023 at 19:35):
y
is no longer in context there
Alex J. Best (Sep 06 2023 at 19:38):
Ah sorry, does
induction Nat.digits b y generalizing x y with
get you what you want? (maybe I should think about whats actually needed to prove this..)
David Renshaw (Sep 06 2023 at 19:39):
for what it's worth, the complete proof is here: https://github.com/dwrensha/math-puzzles-in-lean4/blob/3a2c6843f13d53e45edbd553045e78c512b1664f/MathPuzzles/Usa2003Q1.lean#L21-L53
David Renshaw (Sep 06 2023 at 19:39):
I'm just trying to clean it up before maybe PR'ing it to mathlib
David Renshaw (Sep 06 2023 at 19:46):
when I try induction Nat.digits b y generalizing x y with
, I end up unable to prove the nil
branch, because I need y
to be zero and that information has now been lost
Alex J. Best (Sep 06 2023 at 19:52):
-- lemma for mathlib?
theorem Nat.digits_add'
(b : ℕ) (hb : 1 < b) (x y : ℕ) (hxb : x < b) (hx0 : x ≠ 0) :
Nat.digits b (x * b ^ (Nat.digits b y).length + y) =
Nat.digits b y ++ [x] := by
induction' hy : Nat.digits b y generalizing x y hxb hx0
case nil =>
have hyy : y = 0 := Nat.digits_eq_nil_iff_eq_zero.mp hy
rw[hyy]
simp
exact Nat.digits_of_lt b x hx0 hxb
case cons d ds ih =>
rw[List.length_cons, Nat.pow_succ, List.cons_append]
have hyp : 0 < y := by
by_contra H
replace H : y = 0 := Nat.eq_zero_of_nonpos y H
rw[H] at hy
simp at hy
have h3 := Nat.digits_def' hb hyp
have hdd := hy.symm
rw[h3] at hdd
have h4 : d = y % b := by aesop
have h5 : ds = Nat.digits b (y/b) := by aesop
have h2 := ih x (y/b) hxb hx0 h5.symm
rw[h5] at h2
have h6 : 0 < x * (b ^ List.length ds * b) + y := by positivity
rw[Nat.digits_def' hb h6]
rw[←Nat.mul_assoc]
congr
· rw[Nat.add_mod, Nat.mul_mod_left, zero_add, Nat.mod_mod]
exact h4.symm
· rw[h5,← h2]
congr
have hbz : 0 < b := Nat.zero_lt_one.trans hb
rw[Nat.add_div hbz]
have h6: ¬ (b ≤ y % b) := Nat.not_le.mpr (Nat.mod_lt y hbz)
simp[h6]
rw[Nat.mul_div_left _ hbz]
Alex J. Best (Sep 06 2023 at 19:53):
I'm not sure that the default induction tactic supports this, but you can use induction'
instead which has a slightly different syntax
Bhavik Mehta (Sep 06 2023 at 20:54):
This isn't quite what you were looking for but this can be proved much more simply:
theorem Nat.digits_add'
(b : ℕ) (hb : 1 < b) (x y : ℕ) (hxb : x < b) (hx0 : x ≠ 0) :
Nat.digits b (x * b ^ (Nat.digits b y).length + y) =
Nat.digits b y ++ [x] := by
have : x * b ^ (Nat.digits b y).length + y = ofDigits b (Nat.digits b y ++ [x])
· simp [ofDigits_append, ofDigits_digits, add_comm, mul_comm]
rw [this, digits_ofDigits _ hb]
· simpa [forall_and, or_imp, hxb] using fun _ => digits_lt_base hb
· simpa
David Renshaw (Sep 06 2023 at 21:27):
wow!
David Renshaw (Sep 07 2023 at 03:23):
I opened a PR for a slight generalization of this theorem:
https://github.com/leanprover-community/mathlib4/pull/6999
Last updated: Dec 20 2023 at 11:08 UTC