-
Notifications
You must be signed in to change notification settings - Fork 830
Expand file tree
/
Copy pathLemmas.lean
More file actions
4683 lines (3779 loc) · 184 KB
/
Lemmas.lean
File metadata and controls
4683 lines (3779 loc) · 184 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/-
Copyright (c) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kim Morrison
-/
module
prelude
public import Init.Data.List.ToArray
import all Init.Data.List.Control
import all Init.Data.Array.Basic
import all Init.Data.Array.Bootstrap
public import Init.Data.Nat.Lemmas
public import Init.Data.Nat.MinMax
import Init.ByCases
import Init.Data.Array.DecidableEq
import Init.Data.Bool
import Init.Data.Fin.Lemmas
import Init.Data.List.Find
import Init.Data.List.Nat.Basic
import Init.Data.List.Nat.Modify
import Init.Data.List.Nat.TakeDrop
import Init.Data.List.Range
import Init.Data.List.Zip
import Init.Data.Nat.Linear
import Init.Data.Nat.Simproc
import Init.Data.Option.Lemmas
import Init.Data.Prod
import Init.Omega
import Init.TacticsExtra
public section
/-!
## Theorems about `Array`.
-/
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
namespace Array
/-! ## Preliminaries -/
/-! ### toList -/
@[simp] theorem toList_inj {xs ys : Array α} : xs.toList = ys.toList ↔ xs = ys := by
cases xs; cases ys; simp
@[simp] theorem toList_eq_nil_iff {xs : Array α} : xs.toList = [] ↔ xs = #[] := by
cases xs <;> simp
@[simp, grind =] theorem mem_toList_iff {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := by
cases xs <;> simp
@[simp, grind =] theorem length_toList {xs : Array α} : xs.toList.length = xs.size := rfl
theorem eq_toArray : xs = List.toArray as ↔ xs.toList = as := by
cases xs
simp
theorem toArray_eq : List.toArray as = xs ↔ as = xs.toList := by
cases xs
simp
/-! ### empty -/
@[simp] theorem empty_eq {xs : Array α} : #[] = xs ↔ xs = #[] := by
cases xs <;> simp
@[grind =] theorem size_empty : (#[] : Array α).size = 0 := rfl
/-! ### size -/
theorem size_singleton {x : α} : #[x].size = 1 := by
simp
theorem eq_empty_of_size_eq_zero (h : xs.size = 0) : xs = #[] := by
cases xs
simp_all
grind_pattern eq_empty_of_size_eq_zero => xs.size where
guard xs.size = 0
theorem ne_empty_of_size_eq_add_one (h : xs.size = n + 1) : xs ≠ #[] := by
cases xs
simpa using List.ne_nil_of_length_eq_add_one h
theorem ne_empty_of_size_pos (h : 0 < xs.size) : xs ≠ #[] := by
cases xs
simpa using List.ne_nil_of_length_pos h
@[simp] theorem size_eq_zero_iff : xs.size = 0 ↔ xs = #[] :=
⟨eq_empty_of_size_eq_zero, fun h => h ▸ rfl⟩
theorem eq_empty_iff_size_eq_zero : xs = #[] ↔ xs.size = 0 :=
size_eq_zero_iff.symm
theorem size_pos_of_mem {a : α} {xs : Array α} (h : a ∈ xs) : 0 < xs.size := by
cases xs
simp only [List.mem_toArray] at h
simpa using List.length_pos_of_mem h
grind_pattern size_pos_of_mem => a ∈ xs, xs.size
theorem exists_mem_of_size_pos {xs : Array α} (h : 0 < xs.size) : ∃ a, a ∈ xs := by
cases xs
simpa using List.exists_mem_of_length_pos h
theorem size_pos_iff_exists_mem {xs : Array α} : 0 < xs.size ↔ ∃ a, a ∈ xs :=
⟨exists_mem_of_size_pos, fun ⟨_, h⟩ => size_pos_of_mem h⟩
theorem exists_mem_of_size_eq_add_one {xs : Array α} (h : xs.size = n + 1) : ∃ a, a ∈ xs := by
cases xs
simpa using List.exists_mem_of_length_eq_add_one h
theorem size_pos_iff {xs : Array α} : 0 < xs.size ↔ xs ≠ #[] :=
Nat.pos_iff_ne_zero.trans (not_congr size_eq_zero_iff)
theorem size_eq_one_iff {xs : Array α} : xs.size = 1 ↔ ∃ a, xs = #[a] := by
cases xs
simpa using List.length_eq_one_iff
/-! ## L[i] and L[i]? -/
theorem getElem?_eq_none_iff {xs : Array α} : xs[i]? = none ↔ xs.size ≤ i := by
simp
theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.size ≤ i := by
simp
theorem getElem?_eq_none {xs : Array α} (h : xs.size ≤ i) : xs[i]? = none := by
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]? where
guard xs.size ≤ i
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..
theorem getElem?_eq_some_iff {xs : Array α} : xs[i]? = some b ↔ ∃ h : i < xs.size, xs[i] = b :=
_root_.getElem?_eq_some_iff
theorem getElem_of_getElem? {xs : Array α} : xs[i]? = some a → ∃ h : i < xs.size, xs[i] = a :=
getElem?_eq_some_iff.mp
theorem some_eq_getElem?_iff {xs : Array α} : some b = xs[i]? ↔ ∃ h : i < xs.size, xs[i] = b := by
rw [eq_comm, getElem?_eq_some_iff]
theorem some_getElem_eq_getElem?_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
(some xs[i] = xs[i]?) ↔ True := by
simp
theorem getElem?_eq_some_getElem_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
(xs[i]? = some xs[i]) ↔ True := by
simp
theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x ↔ xs[i]? = some x := by
simp only [getElem?_eq_some_iff]
exact ⟨fun w => ⟨h, w⟩, fun h => h.2⟩
theorem getElem_eq_getElem?_get {xs : Array α} {i : Nat} (h : i < xs.size) :
xs[i] = xs[i]?.get (by simp [h]) := by
simp
theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} :
xs[i]?.getD d = if p : i < xs.size then xs[i]'p else d := by
if h : i < xs.size then
simp [h]
else
have p : i ≥ xs.size := Nat.le_of_not_gt h
simp [h]
@[simp] theorem getElem?_empty {i : Nat} : (#[] : Array α)[i]? = none := rfl
set_option backward.isDefEq.respectTransparency false in
theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) :
have : i < (xs.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt]
(xs.push x)[i] = xs[i] := by
rw [Array.size] at h
simp only [push, ← getElem_toList, List.concat_eq_append, List.getElem_append_left, h]
@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by
simp only [push, ← getElem_toList, List.concat_eq_append]
rw [List.getElem_append_right] <;> simp
@[grind =] theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).size) :
(xs.push x)[i] = if h : i < xs.size then xs[i] else x := by
by_cases h' : i < xs.size
· simp [getElem_push_lt, h']
· simp at h
simp [Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
@[grind =] theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size then some x else xs[i]? := by
simp [getElem?_def, getElem_push]
(repeat' split) <;> first | rfl | omega
theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by
simp
theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a := by
simp
@[grind =]
theorem getElem?_singleton {a : α} {i : Nat} : #[a][i]? = if i = 0 then some a else none := by
simp [List.getElem?_singleton]
theorem ext_getElem? {xs ys : Array α} (h : ∀ i : Nat, xs[i]? = ys[i]?) : xs = ys := by
rcases xs with ⟨xs⟩
rcases ys with ⟨ys⟩
simpa using List.ext_getElem? (by simpa using h)
/-! ### pop -/
@[simp] theorem pop_empty : (#[] : Array α).pop = #[] := rfl
@[simp] theorem pop_push {xs : Array α} {x : α} : (xs.push x).pop = xs := by simp [pop]
@[simp, grind =] theorem getElem_pop {xs : Array α} {i : Nat} (h : i < xs.pop.size) :
xs.pop[i] = xs[i]'(by simp at h; omega) := by
rcases xs with ⟨xs⟩
simp [List.getElem_dropLast]
@[grind =] theorem getElem?_pop {xs : Array α} {i : Nat} :
xs.pop[i]? = if i < xs.size - 1 then xs[i]? else none := by
rcases xs with ⟨xs⟩
simp [List.getElem?_dropLast]
theorem back_pop {xs : Array α} (h) :
xs.pop.back h =
xs[xs.size - 2]'(by simp at h; omega) := by
rcases xs with ⟨xs⟩
simp [List.getLast_dropLast]
theorem back?_pop {xs : Array α} :
xs.pop.back? = if xs.size ≤ 1 then none else xs[xs.size - 2]? := by
rcases xs with ⟨xs⟩
simp [List.getLast?_dropLast]
@[simp] theorem pop_append_of_ne_empty {xs : Array α} {ys : Array α} (h : ys ≠ #[]) :
(xs ++ ys).pop = xs ++ ys.pop := by
rcases xs with ⟨xs⟩
rcases ys with ⟨ys⟩
simp only [List.append_toArray, List.pop_toArray, mk.injEq]
rw [List.dropLast_append_of_ne_nil (by simpa using h)]
/-! ### push -/
@[simp] theorem push_empty : #[].push x = #[x] := rfl
@[simp] theorem push_ne_empty {a : α} {xs : Array α} : xs.push a ≠ #[] := by
cases xs
simp
@[simp] theorem push_ne_self {a : α} {xs : Array α} : xs.push a ≠ xs := by
cases xs
simp
@[simp] theorem ne_push_self {a : α} {xs : Array α} : xs ≠ xs.push a := by
rw [ne_eq, eq_comm]
simp
theorem back_eq_of_push_eq {a b : α} {xs ys : Array α} (h : xs.push a = ys.push b) : a = b := by
cases xs
cases ys
simp only [List.push_toArray, mk.injEq] at h
replace h := List.append_inj_right' h (by simp)
simpa using h
theorem push_eq_push {a b : α} {xs ys : Array α} : xs.push a = ys.push b ↔ a = b ∧ xs = ys := by
cases xs
cases ys
simp [And.comm]
theorem pop_eq_of_push_eq {a b : α} {xs ys : Array α} (h : xs.push a = ys.push b) : xs = ys :=
(push_eq_push.1 h).2
theorem push_inj_left {a : α} {xs ys : Array α} : xs.push a = ys.push a ↔ xs = ys :=
⟨pop_eq_of_push_eq, fun h => by simp [h]⟩
theorem push_inj_right {a b : α} {xs : Array α} : xs.push a = xs.push b ↔ a = b :=
⟨back_eq_of_push_eq, fun h => by simp [h]⟩
theorem exists_push_of_ne_empty {xs : Array α} (h : xs ≠ #[]) :
∃ (ys : Array α) (a : α), xs = ys.push a := by
rcases xs with ⟨xs⟩
simp only [ne_eq, mk.injEq] at h
exact ⟨(xs.take (xs.length - 1)).toArray, xs.getLast h, by simp⟩
theorem ne_empty_iff_exists_push {xs : Array α} :
xs ≠ #[] ↔ ∃ (ys : Array α) (a : α), xs = ys.push a :=
⟨exists_push_of_ne_empty, fun ⟨_, _, eq⟩ => eq.symm ▸ push_ne_empty⟩
theorem exists_push_of_size_pos {xs : Array α} (h : 0 < xs.size) :
∃ (ys : Array α) (a : α), xs = ys.push a := by
replace h : xs ≠ #[] := size_pos_iff.mp h
exact exists_push_of_ne_empty h
theorem size_pos_iff_exists_push {xs : Array α} :
0 < xs.size ↔ ∃ (ys : Array α) (a : α), xs = ys.push a :=
⟨exists_push_of_size_pos, fun ⟨_, _, eq⟩ => by simp [eq]⟩
theorem exists_push_of_size_eq_add_one {xs : Array α} (h : xs.size = n + 1) :
∃ (ys : Array α) (a : α), xs = ys.push a :=
exists_push_of_size_pos (by simp [h])
theorem eq_push_pop_back!_of_size_ne_zero [Inhabited α] {xs : Array α} (h : xs.size ≠ 0) :
xs = xs.pop.push xs.back! := by
apply ext
· simp [Nat.sub_add_cancel (Nat.zero_lt_of_ne_zero h)]
· intro i h h'
if hlt : i < xs.pop.size then
rw [getElem_push_lt (h:=hlt), getElem_pop]
else
have heq : i = xs.pop.size :=
Nat.le_antisymm (size_pop .. ▸ Nat.le_pred_of_lt h) (Nat.le_of_not_gt hlt)
cases heq
rw [getElem_push_eq, back!]
simp [← getElem!_pos]
theorem eq_push_of_size_ne_zero {xs : Array α} (h : xs.size ≠ 0) :
∃ (bs : Array α) (c : α), xs = bs.push c :=
let _ : Inhabited α := ⟨xs[0]⟩
⟨xs.pop, xs.back!, eq_push_pop_back!_of_size_ne_zero h⟩
theorem singleton_inj : #[a] = #[b] ↔ a = b := by
simp
/-! ### replicate -/
@[simp, grind =] theorem size_replicate {n : Nat} {v : α} : (replicate n v).size = n :=
List.length_replicate ..
@[simp] theorem toList_replicate : (replicate n a).toList = List.replicate n a := by
simp only [replicate]
@[simp, grind =] theorem replicate_zero : replicate 0 a = #[] := rfl
@[grind =]
theorem replicate_succ : replicate (n + 1) a = (replicate n a).push a := by
apply toList_inj.1
simp [List.replicate_succ']
@[simp, grind =] theorem getElem_replicate {n : Nat} {v : α} {i : Nat} (h : i < (replicate n v).size) :
(replicate n v)[i] = v := by simp [← getElem_toList]
@[grind =] theorem getElem?_replicate {n : Nat} {v : α} {i : Nat} :
(replicate n v)[i]? = if i < n then some v else none := by
simp [getElem?_def]
/-! ### mem -/
@[grind ←]
theorem not_mem_empty (a : α) : ¬ a ∈ #[] := by simp
@[simp, grind =] theorem mem_push {xs : Array α} {x y : α} : x ∈ xs.push y ↔ x ∈ xs ∨ x = y := by
simp only [mem_def]
simp
theorem mem_or_eq_of_mem_push {a b : α} {xs : Array α} :
a ∈ xs.push b → a ∈ xs ∨ a = b := Array.mem_push.mp
-- This pattern may be excessively general:
-- it fires anytime we ae thinking about membership of arrays,
-- and constructing a list via `push`, even if the elements are unrelated.
-- Nevertheless in practice it is quite helpful!
grind_pattern mem_or_eq_of_mem_push => xs.push b, a ∈ xs
theorem mem_push_self {xs : Array α} {x : α} : x ∈ xs.push x :=
mem_push.2 (Or.inr rfl)
theorem eq_push_append_of_mem {xs : Array α} {x : α} (h : x ∈ xs) :
∃ (as bs : Array α), xs = as.push x ++ bs ∧ x ∉ as:= by
rcases xs with ⟨xs⟩
obtain ⟨as, bs, h, w⟩ := List.eq_append_cons_of_mem (mem_def.1 h)
simp only at h
obtain rfl := h
exact ⟨as.toArray, bs.toArray, by simp, by simpa using w⟩
theorem mem_push_of_mem {xs : Array α} {x : α} (y : α) (h : x ∈ xs) : x ∈ xs.push y :=
mem_push.2 (Or.inl h)
-- The argument `xs : Array α` is intentionally explicit,
-- as a tactic may generate `h` without determining `xs`.
theorem exists_mem_of_ne_empty (xs : Array α) (h : xs ≠ #[]) : ∃ x, x ∈ xs := by
simpa using List.exists_mem_of_ne_nil xs.toList (by simpa using h)
theorem eq_empty_iff_forall_not_mem {xs : Array α} : xs = #[] ↔ ∀ a, a ∉ xs := by
cases xs
simp [List.eq_nil_iff_forall_not_mem]
@[simp] theorem mem_dite_empty_left {x : α} [Decidable p] {xs : ¬ p → Array α} :
(x ∈ if h : p then #[] else xs h) ↔ ∃ h : ¬ p, x ∈ xs h := by
split <;> simp_all
@[simp] theorem mem_dite_empty_right {x : α} [Decidable p] {xs : p → Array α} :
(x ∈ if h : p then xs h else #[]) ↔ ∃ h : p, x ∈ xs h := by
split <;> simp_all
@[simp] theorem mem_ite_empty_left {x : α} [Decidable p] {xs : Array α} :
(x ∈ if p then #[] else xs) ↔ ¬ p ∧ x ∈ xs := by
split <;> simp_all
@[simp] theorem mem_ite_empty_right {x : α} [Decidable p] {xs : Array α} :
(x ∈ if p then xs else #[]) ↔ p ∧ x ∈ xs := by
split <;> simp_all
theorem eq_of_mem_singleton (h : a ∈ #[b]) : a = b := by
simpa using h
theorem mem_singleton {a b : α} : a ∈ #[b] ↔ a = b := by simp
theorem forall_mem_push {p : α → Prop} {xs : Array α} {a : α} :
(∀ x, x ∈ xs.push a → p x) ↔ p a ∧ ∀ x, x ∈ xs → p x := by
cases xs
simp [or_comm, forall_eq_or_imp]
theorem forall_mem_ne {a : α} {xs : Array α} : (∀ a' : α, a' ∈ xs → ¬a = a') ↔ a ∉ xs :=
⟨fun h m => h _ m rfl, fun h _ m e => h (e.symm ▸ m)⟩
theorem forall_mem_ne' {a : α} {xs : Array α} : (∀ a' : α, a' ∈ xs → ¬a' = a) ↔ a ∉ xs :=
⟨fun h m => h _ m rfl, fun h _ m e => h (e.symm ▸ m)⟩
theorem exists_mem_empty (p : α → Prop) : ¬ (∃ x, ∃ _ : x ∈ #[], p x) := nofun
theorem forall_mem_empty (p : α → Prop) : ∀ (x) (_ : x ∈ #[]), p x := nofun
theorem exists_mem_push {p : α → Prop} {a : α} {xs : Array α} :
(∃ x, ∃ _ : x ∈ xs.push a, p x) ↔ p a ∨ ∃ x, ∃ _ : x ∈ xs, p x := by
simp only [mem_push, exists_prop]
constructor
· rintro ⟨x, (h | rfl), h'⟩
· exact .inr ⟨x, h, h'⟩
· exact .inl h'
· rintro (h | ⟨x, h, h'⟩)
· exact ⟨a, by simp, h⟩
· exact ⟨x, .inl h, h'⟩
theorem forall_mem_singleton {p : α → Prop} {a : α} : (∀ (x) (_ : x ∈ #[a]), p x) ↔ p a := by
simp only [mem_singleton, forall_eq]
theorem mem_empty_iff (a : α) : a ∈ (#[] : Array α) ↔ False := by simp
theorem mem_singleton_self (a : α) : a ∈ #[a] := by simp
theorem mem_of_mem_push_of_mem {a b : α} {xs : Array α} : a ∈ xs.push b → b ∈ xs → a ∈ xs := by
cases xs
simp only [List.push_toArray, List.mem_toArray, List.mem_append, List.mem_singleton]
rintro (h | rfl)
· intro _
exact h
· exact id
theorem eq_or_ne_mem_of_mem {a b : α} {xs : Array α} (h' : a ∈ xs.push b) :
a = b ∨ (a ≠ b ∧ a ∈ xs) := by
if h : a = b then
exact .inl h
else
simp only [mem_push, h, or_false] at h'
exact .inr ⟨h, h'⟩
theorem ne_empty_of_mem {a : α} {xs : Array α} (h : a ∈ xs) : xs ≠ #[] := by
cases xs
simp [List.ne_nil_of_mem (by simpa using h)]
theorem mem_of_ne_of_mem {a y : α} {xs : Array α} (h₁ : a ≠ y) (h₂ : a ∈ xs.push y) : a ∈ xs := by
simpa [h₁] using h₂
theorem ne_of_not_mem_push {a b : α} {xs : Array α} (h : a ∉ xs.push b) : a ≠ b := by
simp only [mem_push, not_or] at h
exact h.2
theorem not_mem_of_not_mem_push {a b : α} {xs : Array α} (h : a ∉ xs.push b) : a ∉ xs := by
simp only [mem_push, not_or] at h
exact h.1
theorem not_mem_push_of_ne_of_not_mem {a y : α} {xs : Array α} : a ≠ y → a ∉ xs → a ∉ xs.push y :=
mt ∘ mem_of_ne_of_mem
theorem ne_and_not_mem_of_not_mem_push {a y : α} {xs : Array α} : a ∉ xs.push y → a ≠ y ∧ a ∉ xs := by
simp +contextual
theorem getElem_of_mem {a} {xs : Array α} (h : a ∈ xs) : ∃ (i : Nat) (h : i < xs.size), xs[i]'h = a := by
cases xs
simp [List.getElem_of_mem (by simpa using h)]
theorem getElem?_of_mem {a} {xs : Array α} (h : a ∈ xs) : ∃ i : Nat, xs[i]? = some a :=
let ⟨n, _, e⟩ := getElem_of_mem h; ⟨n, e ▸ getElem?_eq_getElem _⟩
theorem mem_of_getElem {xs : Array α} {i : Nat} {h} {a : α} (e : xs[i] = a) : a ∈ xs := by
subst e
simp
theorem mem_of_getElem? {xs : Array α} {i : Nat} {a : α} (e : xs[i]? = some a) : a ∈ xs :=
let ⟨_, e⟩ := getElem?_eq_some_iff.1 e; e ▸ getElem_mem ..
theorem mem_iff_getElem {a} {xs : Array α} : a ∈ xs ↔ ∃ (i : Nat) (h : i < xs.size), xs[i]'h = a :=
⟨getElem_of_mem, fun ⟨_, _, e⟩ => e ▸ getElem_mem ..⟩
theorem mem_iff_getElem? {a} {xs : Array α} : a ∈ xs ↔ ∃ i : Nat, xs[i]? = some a := by
simp [getElem?_eq_some_iff, mem_iff_getElem]
theorem exists_mem_iff_exists_getElem {P : α → Prop} {xs : Array α} :
(∃ x ∈ xs, P x) ↔ ∃ (i : Nat), ∃ (hi : i < xs.size), P (xs[i]) := by
cases xs; simp [List.exists_mem_iff_exists_getElem]
theorem forall_mem_iff_forall_getElem {P : α → Prop} {xs : Array α} :
(∀ x ∈ xs, P x) ↔ ∀ (i : Nat) (hi : i < xs.size), P (xs[i]) := by
cases xs; simp [List.forall_mem_iff_forall_getElem]
@[deprecated forall_mem_iff_forall_getElem (since := "2026-01-29")]
theorem forall_getElem {xs : Array α} {p : α → Prop} :
(∀ (i : Nat) h, p (xs[i]'h)) ↔ ∀ a, a ∈ xs → p a := by
exact forall_mem_iff_forall_getElem.symm
/-! ### isEmpty -/
@[grind =] theorem isEmpty_empty : (#[] : Array α).isEmpty = true := rfl
@[simp, grind =] theorem isEmpty_push {xs : Array α} : (xs.push x).isEmpty = false := by
rcases xs with ⟨xs⟩
simp
@[simp, grind =] theorem isEmpty_toList {xs : Array α} : xs.toList.isEmpty = xs.isEmpty := by
rcases xs with ⟨_ | _⟩ <;> simp
theorem isEmpty_eq_false_iff_exists_mem {xs : Array α} :
xs.isEmpty = false ↔ ∃ x, x ∈ xs := by
cases xs
simpa using List.isEmpty_eq_false_iff_exists_mem
@[simp] theorem isEmpty_iff {xs : Array α} : xs.isEmpty ↔ xs = #[] := by
cases xs <;> simp
@[grind →]
theorem empty_of_isEmpty {xs : Array α} (h : xs.isEmpty) : xs = #[] := Array.isEmpty_iff.mp h
@[simp] theorem isEmpty_eq_false_iff {xs : Array α} : xs.isEmpty = false ↔ xs ≠ #[] := by
cases xs <;> simp
theorem isEmpty_iff_size_eq_zero {xs : Array α} : xs.isEmpty ↔ xs.size = 0 := by
rw [isEmpty_iff, size_eq_zero_iff]
/-! ### Decidability of bounded quantifiers -/
instance {xs : Array α} {p : α → Prop} [DecidablePred p] :
Decidable (∀ x, x ∈ xs → p x) :=
decidable_of_iff (∀ (i : Nat) h, p (xs[i]'h)) (by
simp only [mem_iff_getElem, forall_exists_index]
exact
⟨by rintro w _ i h rfl; exact w i h, fun w i h => w _ i h rfl⟩)
instance {xs : Array α} {p : α → Prop} [DecidablePred p] :
Decidable (∃ x, x ∈ xs ∧ p x) :=
decidable_of_iff (∃ (i : Nat), ∃ (h : i < xs.size), p (xs[i]'h)) (by
simp [mem_iff_getElem]
exact
⟨by rintro ⟨i, h, w⟩; exact ⟨_, ⟨i, h, rfl⟩, w⟩, fun ⟨_, ⟨i, h, rfl⟩, w⟩ => ⟨i, h, w⟩⟩)
/-! ### any / all -/
theorem anyM_eq_anyM_loop [Monad m] {p : α → m Bool} {as : Array α} {start stop} :
anyM p as start stop = anyM.loop p as (min stop as.size) (Nat.min_le_right ..) start := by
simp only [anyM, Nat.min_def]; split <;> rfl
theorem anyM_stop_le_start [Monad m] {p : α → m Bool} {as : Array α} {start stop}
(h : min stop as.size ≤ start) : anyM p as start stop = pure false := by
rw [anyM_eq_anyM_loop, anyM.loop, dif_neg (Nat.not_lt.2 h)]
theorem anyM_loop_cons [Monad m] {p : α → m Bool} {a : α} {as : List α} {stop start : Nat}
(h : stop + 1 ≤ (a :: as).length) :
anyM.loop p ⟨a :: as⟩ (stop + 1) h (start + 1) =
anyM.loop p ⟨as⟩ stop (by simpa using h) start := by
rw [anyM.loop]
conv => rhs; rw [anyM.loop]
split <;> rename_i h'
· simp only [Nat.add_lt_add_iff_right] at h'
rw [dif_pos h', anyM_loop_cons]
simp
· rw [dif_neg]
omega
@[simp, grind =] theorem anyM_toList [Monad m] {p : α → m Bool} {as : Array α} :
as.toList.anyM p = as.anyM p :=
match as with
| ⟨[]⟩ => by simp [anyM, anyM.loop]
| ⟨a :: as⟩ => by
simp only [List.anyM, anyM, List.size_toArray, List.length_cons, Nat.le_refl, ↓reduceDIte]
rw [anyM.loop, dif_pos (by omega)]
congr 1
funext b
split
· simp
· simp only [Bool.false_eq_true, ↓reduceIte]
rw [anyM_loop_cons]
simpa [anyM] using anyM_toList
-- Auxiliary for `any_iff_exists`.
theorem anyM_loop_iff_exists {p : α → Bool} {as : Array α} {start stop} (h : stop ≤ as.size) :
(anyM.loop (m := Id) (pure <| p ·) as stop h start).run = true ↔
∃ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop ∧ p as[i] = true := by
unfold anyM.loop
split <;> rename_i h₁
· dsimp
split <;> rename_i h₂
· simp only [true_iff, Id.run_pure]
refine ⟨start, by omega, by omega, by omega, h₂⟩
· rw [anyM_loop_iff_exists]
constructor
· rintro ⟨i, hi, ge, lt, h⟩
have : start ≠ i := by rintro rfl; omega
exact ⟨i, by omega, by omega, lt, h⟩
· rintro ⟨i, hi, ge, lt, h⟩
have : start ≠ i := by rintro rfl; erw [h] at h₂; simp_all
exact ⟨i, by omega, by omega, lt, h⟩
· simp
omega
termination_by stop - start
-- This could also be proved from `SatisfiesM_anyM_iff_exists` in `Batteries.Data.Array.Init.Monadic`
theorem any_iff_exists {p : α → Bool} {as : Array α} {start stop} :
as.any p start stop ↔ ∃ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop ∧ p as[i] := by
dsimp [any, anyM]
split
· rw [anyM_loop_iff_exists (p := p)]
· rw [anyM_loop_iff_exists]
constructor
· rintro ⟨i, hi, ge, _, h⟩
exact ⟨i, by omega, by omega, by omega, h⟩
· rintro ⟨i, hi, ge, _, h⟩
exact ⟨i, by omega, by omega, by omega, h⟩
@[simp] theorem any_eq_true {p : α → Bool} {as : Array α} :
as.any p = true ↔ ∃ (i : Nat) (_ : i < as.size), p as[i] := by
simp [any_iff_exists]
@[simp] theorem any_eq_false {p : α → Bool} {as : Array α} :
as.any p = false ↔ ∀ (i : Nat) (_ : i < as.size), ¬p as[i] := by
rw [Bool.eq_false_iff, Ne, any_eq_true]
simp
@[simp, grind =] theorem any_toList {p : α → Bool} {as : Array α} : as.toList.any p = as.any p := by
rw [Bool.eq_iff_iff, any_eq_true, List.any_eq_true]
simp only [List.mem_iff_getElem, getElem_toList]
exact ⟨fun ⟨_, ⟨i, w, rfl⟩, h⟩ => ⟨i, w, h⟩, fun ⟨i, w, h⟩ => ⟨_, ⟨i, w, rfl⟩, h⟩⟩
theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} :
allM p as = (! ·) <$> anyM ((! ·) <$> p ·) as := by
dsimp [allM, anyM]
simp
@[simp, grind =] theorem allM_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} :
as.toList.allM p = as.allM p := by
rw [allM_eq_not_anyM_not]
rw [← anyM_toList]
rw [List.allM_eq_not_anyM_not]
theorem all_eq_not_any_not {p : α → Bool} {as : Array α} {start stop} :
as.all p start stop = !(as.any (!p ·) start stop) := by
dsimp [all, allM]
rfl
theorem all_iff_forall {p : α → Bool} {as : Array α} {start stop} :
as.all p start stop ↔ ∀ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop → p as[i] := by
rw [all_eq_not_any_not]
suffices ¬(as.any (!p ·) start stop = true) ↔
∀ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop → p as[i] by
simp_all
simp only [any_iff_exists, Bool.not_eq_eq_eq_not, Bool.not_true, not_exists, not_and,
Bool.not_eq_false, and_imp]
@[simp] theorem all_eq_true {p : α → Bool} {as : Array α} :
as.all p = true ↔ ∀ (i : Nat) (_ : i < as.size), p as[i] := by
simp [all_iff_forall]
@[simp] theorem all_eq_false {p : α → Bool} {as : Array α} :
as.all p = false ↔ ∃ (i : Nat) (_ : i < as.size), ¬p as[i] := by
rw [Bool.eq_false_iff, Ne, all_eq_true]
simp
@[simp, grind =] theorem all_toList {p : α → Bool} {as : Array α} : as.toList.all p = as.all p := by
rw [Bool.eq_iff_iff, all_eq_true, List.all_eq_true]
simp only [List.mem_iff_getElem, getElem_toList]
constructor
· intro w i h
exact w as[i] ⟨i, h, getElem_toList h⟩
· rintro w x ⟨i, h, rfl⟩
exact w i h
theorem all_eq_true_iff_forall_mem {xs : Array α} : xs.all p ↔ ∀ x, x ∈ xs → p x := by
simp only [← all_toList, List.all_eq_true, mem_def]
/-- Variant of `anyM_toArray` with a side condition on `stop`. -/
@[simp] theorem _root_.List.anyM_toArray' [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} {stop}
(h : stop = l.toArray.size) :
l.toArray.anyM p 0 stop = l.anyM p := by
subst h
rw [← anyM_toList]
/-- Variant of `any_toArray` with a side condition on `stop`. -/
@[simp] theorem _root_.List.any_toArray' {p : α → Bool} {l : List α} {stop}
(h : stop = l.toArray.size) :
l.toArray.any p 0 stop = l.any p := by
subst h
rw [any_toList]
/-- Variant of `allM_toArray` with a side condition on `stop`. -/
@[simp] theorem _root_.List.allM_toArray' [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} {stop}
(h : stop = l.toArray.size) :
l.toArray.allM p 0 stop = l.allM p := by
subst h
rw [← allM_toList]
/-- Variant of `all_toArray` with a side condition on `stop`. -/
@[simp] theorem _root_.List.all_toArray' {p : α → Bool} {l : List α} {stop}
(h : stop = l.toArray.size) :
l.toArray.all p 0 stop = l.all p := by
subst h
rw [all_toList]
@[grind =] theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
l.toArray.anyM p = l.anyM p := by
rw [← anyM_toList]
@[grind =] theorem _root_.List.any_toArray {p : α → Bool} {l : List α} : l.toArray.any p = l.any p := by
rw [any_toList]
@[grind =] theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
l.toArray.allM p = l.allM p := by
rw [← allM_toList]
@[grind =] theorem _root_.List.all_toArray {p : α → Bool} {l : List α} : l.toArray.all p = l.all p := by
rw [all_toList]
/-- Variant of `any_eq_true` in terms of membership rather than an array index. -/
theorem any_eq_true' {p : α → Bool} {as : Array α} :
as.any p = true ↔ (∃ x, x ∈ as ∧ p x) := by
cases as
simp
/-- Variant of `any_eq_false` in terms of membership rather than an array index. -/
theorem any_eq_false' {p : α → Bool} {as : Array α} :
as.any p = false ↔ ∀ x, x ∈ as → ¬p x := by
rw [Bool.eq_false_iff, Ne, any_eq_true']
simp
/-- Variant of `all_eq_true` in terms of membership rather than an array index. -/
theorem all_eq_true' {p : α → Bool} {as : Array α} :
as.all p = true ↔ (∀ x, x ∈ as → p x) := by
cases as
simp
/-- Variant of `all_eq_false` in terms of membership rather than an array index. -/
theorem all_eq_false' {p : α → Bool} {as : Array α} :
as.all p = false ↔ ∃ x, x ∈ as ∧ ¬p x := by
rw [Bool.eq_false_iff, Ne, all_eq_true']
simp
@[grind =]
theorem any_eq {xs : Array α} {p : α → Bool} : xs.any p = decide (∃ i : Nat, ∃ h, p (xs[i]'h)) := by
by_cases h : xs.any p
· simp_all [any_eq_true]
· simp_all [any_eq_false]
/-- Variant of `any_eq` in terms of membership rather than an array index. -/
theorem any_eq' {xs : Array α} {p : α → Bool} : xs.any p = decide (∃ x, x ∈ xs ∧ p x) := by
by_cases h : xs.any p
· simp_all [any_eq_true', -any_eq_true]
· simp only [Bool.not_eq_true] at h
simp only [h]
simp only [any_eq_false'] at h
simpa using h
@[grind =]
theorem all_eq {xs : Array α} {p : α → Bool} : xs.all p = decide (∀ i, (_ : i < xs.size) → p xs[i]) := by
by_cases h : xs.all p
· simp_all [all_eq_true]
· simp only [Bool.not_eq_true] at h
simp only [h]
simp only [all_eq_false] at h
simpa using h
/-- Variant of `all_eq` in terms of membership rather than an array index. -/
theorem all_eq' {xs : Array α} {p : α → Bool} : xs.all p = decide (∀ x, x ∈ xs → p x) := by
by_cases h : xs.all p
· simp_all [all_eq_true', -all_eq_true]
· simp only [Bool.not_eq_true] at h
simp only [h]
simp only [all_eq_false'] at h
simpa using h
theorem decide_exists_mem {xs : Array α} {p : α → Prop} [DecidablePred p] :
decide (∃ x, x ∈ xs ∧ p x) = xs.any p := by
simp [any_eq']
theorem decide_forall_mem {xs : Array α} {p : α → Prop} [DecidablePred p] :
decide (∀ x, x ∈ xs → p x) = xs.all p := by
simp [all_eq']
@[simp, grind =] theorem _root_.List.contains_toArray [BEq α] {l : List α} {a : α} :
l.toArray.contains a = l.contains a := by
simp [Array.contains, List.any_beq]
theorem _root_.List.elem_toArray [BEq α] {l : List α} {a : α} :
Array.elem a l.toArray = List.elem a l := by
simp [Array.elem]
theorem any_beq [BEq α] {xs : Array α} {a : α} : (xs.any fun x => a == x) = xs.contains a := by
cases xs
simp [List.any_beq]
/-- Variant of `any_beq` with `==` reversed. -/
theorem any_beq' [BEq α] [PartialEquivBEq α] {xs : Array α} :
(xs.any fun x => x == a) = xs.contains a := by
simp only [BEq.comm, any_beq]
theorem all_bne [BEq α] {xs : Array α} : (xs.all fun x => a != x) = !xs.contains a := by
cases xs
simp [List.all_bne]
/-- Variant of `all_bne` with `!=` reversed. -/
theorem all_bne' [BEq α] [PartialEquivBEq α] {xs : Array α} :
(xs.all fun x => x != a) = !xs.contains a := by
simp only [bne_comm, all_bne]
theorem mem_of_contains_eq_true [BEq α] [LawfulBEq α] {a : α} {as : Array α} : as.contains a = true → a ∈ as := by
cases as
simp
theorem contains_eq_true_of_mem [BEq α] [ReflBEq α] {a : α} {as : Array α} (h : a ∈ as) :
as.contains a = true := by
cases as
simpa using List.elem_eq_true_of_mem (Array.mem_toList_iff.mpr h)
@[simp] theorem elem_eq_contains [BEq α] {a : α} {xs : Array α} :
elem a xs = xs.contains a := by
simp [elem]
@[grind =] theorem contains_empty [BEq α] : (#[] : Array α).contains a = false := by simp
theorem elem_iff [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
elem a xs = true ↔ a ∈ xs := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem⟩
@[grind =]
theorem contains_iff_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
xs.contains a = true ↔ a ∈ xs := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem⟩
@[deprecated contains_iff_mem (since := "2025-10-26")]
theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
xs.contains a = true ↔ a ∈ xs := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem⟩
instance [BEq α] [LawfulBEq α] (a : α) (as : Array α) : Decidable (a ∈ as) :=
decidable_of_decidable_of_iff elem_iff
theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
elem a xs = decide (a ∈ xs) := by rw [Bool.eq_iff_iff, elem_iff, decide_eq_true_iff]
@[simp, grind =] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
xs.contains a = decide (a ∈ xs) := by rw [← elem_eq_contains, elem_eq_mem]
@[grind =] theorem any_empty [BEq α] {p : α → Bool} : (#[] : Array α).any p = false := by simp
@[grind =] theorem all_empty [BEq α] {p : α → Bool} : (#[] : Array α).all p = true := by simp
/-- Variant of `any_push` with a side condition on `stop`. -/
@[simp, grind =] theorem any_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
(xs.push a).any p 0 stop = (xs.any p || p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem any_push {xs : Array α} {a : α} {p : α → Bool} :
(xs.push a).any p = (xs.any p || p a) :=
any_push' (by simp)
/-- Variant of `all_push` with a side condition on `stop`. -/
@[simp, grind =] theorem all_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
(xs.push a).all p 0 stop = (xs.all p && p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem all_push {xs : Array α} {a : α} {p : α → Bool} :
(xs.push a).all p = (xs.all p && p a) :=
all_push' (by simp)
@[simp] theorem contains_push [BEq α] {xs : Array α} {a : α} {b : α} :
(xs.push a).contains b = (xs.contains b || b == a) := by
simp [contains]
/-! ### set -/
@[simp] theorem getElem_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} :
(xs.set i v)[i]'(by simp [h]) = v := by
cases xs
simp
@[simp] theorem getElem?_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} :
(xs.set i v)[i]? = some v := by simp [h]
@[simp] theorem getElem_set_ne {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat}
(pj : j < xs.size) (h : i ≠ j) :
(xs.set i v)[j]'(by simp [*]) = xs[j] := by
simp only [set, ← getElem_toList, List.getElem_set_ne h]
@[simp] theorem getElem?_set_ne {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat}
(ne : i ≠ j) : (xs.set i v)[j]? = xs[j]? := by
by_cases h : j < xs.size <;> simp [ne, h]
@[grind =] theorem getElem_set {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat}
(h : j < (xs.set i v).size) :
(xs.set i v)[j] = if i = j then v else xs[j]'(by simpa using h) := by
simp at h
by_cases p : i = j <;> simp [p, h]
@[grind =] theorem getElem?_set {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat} :
(xs.set i v)[j]? = if i = j then some v else xs[j]? := by
split <;> simp_all
@[simp] theorem set_getElem_self {xs : Array α} {i : Nat} (h : i < xs.size) :
xs.set i xs[i] = xs := by
cases xs
simp
theorem set_push {xs : Array α} {x y : α} {h} :
(xs.push x).set i y = if _ : i < xs.size then (xs.set i y).push x else xs.push y := by
ext j hj
· split <;> simp
· split
· simp only [getElem_set, getElem_push, size_set]
split
· rw [dif_pos]
omega
· split <;> rfl
· simp only [getElem_set, getElem_push]
split
· rw [dif_neg]
omega
· simp_all only [size_set, size_push, dite_false]
split
· rfl
· simp at h
omega
@[grind _=_]
theorem set_pop {xs : Array α} {x : α} {i : Nat} (h : i < xs.pop.size) :
xs.pop.set i x h = (xs.set i x (by simp at h; omega)).pop := by
ext i h₁ h₂
· simp
· simp [getElem_set]
@[simp] theorem set_eq_empty_iff {xs : Array α} {i : Nat} {a : α} {h : i < xs.size} :
xs.set i a = #[] ↔ xs = #[] := by
cases xs <;> cases i <;> simp [set]
theorem set_comm (a b : α)
{i j : Nat} {xs : Array α} {hi : i < xs.size} {hj : j < (xs.set i a).size} (h : i ≠ j) :
(xs.set i a).set j b = (xs.set j b (by simpa using hj)).set i a (by simpa using hi) := by
cases xs
simp [List.set_comm _ _ h]
@[simp]
theorem set_set (a : α) {b : α} {xs : Array α} {i : Nat} (h : i < xs.size) :
(xs.set i a).set i b (by simpa using h) = xs.set i b := by
cases xs
simp
theorem mem_set {xs : Array α} {i : Nat} (h : i < xs.size) {a : α} :
a ∈ xs.set i a := by
simp [mem_iff_getElem]
exact ⟨i, (by simpa using h), by simp⟩
theorem mem_or_eq_of_mem_set
{xs : Array α} {i : Nat} {a b : α} {w : i < xs.size} (h : a ∈ xs.set i b) : a ∈ xs ∨ a = b := by
cases xs
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a ∈ xs.set i b
/-! ### setIfInBounds -/
@[simp, grind =] theorem setIfInBounds_empty {i : Nat} {a : α} :
#[].setIfInBounds i a = #[] := rfl
@[simp, grind =] theorem set!_eq_setIfInBounds : set! xs i v = setIfInBounds xs i v := rfl
@[grind =]
theorem setIfInBounds_def (xs : Array α) (i : Nat) (a : α) :
xs.setIfInBounds i a = if h : i < xs.size then xs.set i a else xs := rfl
@[simp, grind =] theorem size_setIfInBounds {xs : Array α} {i : Nat} {a : α} :
(xs.setIfInBounds i a).size = xs.size := by
if h : i < xs.size then
simp [setIfInBounds, h]
else
simp [setIfInBounds, h]
@[grind =] theorem getElem_setIfInBounds {xs : Array α} {i : Nat} {a : α} {j : Nat}
(hj : j < xs.size) :
(xs.setIfInBounds i a)[j]'(by simp [hj]) = if i = j then a else xs[j] := by
simp only [setIfInBounds]
split