@@ -827,6 +827,14 @@ rewrite drop_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
827827by rewrite drop0 drop_size.
828828qed.
829829
830+ lemma drop_catl [' a] (s1 s2 : ' a list) (i : int) :
831+ i <= size s1 => drop i (s1 ++ s2) = drop i s1 ++ s2.
832+ proof. by move=> ?; rewrite drop_cat_le iftrue. qed.
833+
834+ lemma drop_catr [' a] (s1 s2 : ' a list) (i : int) :
835+ size s1 <= i => drop i (s1 ++ s2) = drop (i - size s1) s2.
836+ proof. by move=> ?; rewrite drop_cat iffalse // ltzNge. qed.
837+
830838lemma drop_size_cat n (s1 s2 : ' a list):
831839 size s1 = n => drop n (s1 ++ s2) = s2.
832840proof. by move=> <-; rewrite drop_cat subzz ltzz drop0. qed.
@@ -902,6 +910,14 @@ rewrite take_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
902910by rewrite take0 take_size cats0.
903911qed.
904912
913+ lemma take_catl [' a] (s1 s2 : ' a list) (i : int) :
914+ i <= size s1 => take i (s1 ++ s2) = take i s1.
915+ proof. by move=> ?; rewrite take_cat_le iftrue. qed.
916+
917+ lemma take_catr [' a] (s1 s2 : ' a list) (i : int) :
918+ size s1 <= i => take i (s1 ++ s2) = s1 ++ take (i - size s1) s2.
919+ proof. by move=> ?; rewrite take_cat iffalse // ltzNge. qed.
920+
905921lemma take_size_cat n (s1 s2 : ' a list):
906922 size s1 = n => take n (s1 ++ s2) = s1.
907923proof. by move=> <-; rewrite take_cat subzz ltzz take0 cats0. qed.
@@ -916,6 +932,37 @@ qed.
916932lemma cat_take_drop n (s : ' a list): take n s ++ drop n s = s.
917933proof. by elim: s n=> /#. qed.
918934
935+ lemma takeD [' a] (s : ' a list) (i j : int ) :
936+ 0 <= i => 0 <= j => take (i + j) s = take i s ++ take j (drop i s).
937+ proof.
938+ move=> ge0_i ge0_j; case : (size s <= i) => [sz_le|/ltzNge sz_lt].
939+ - by rewrite drop_oversize // = cats0 !take_oversize //#.
940+ rewrite -{1 }[s](cat_take_drop i) take_cat.
941+ by rewrite size_take // sz_lt /= iffalse 1:/# addrAC.
942+ qed.
943+
944+ lemma size_eqD [' a] (m n : int) (s : ' a list) :
945+ 0 <= m => 0 <= n => size s = m + n =>
946+ exists s1 s2, (size s1 = m /\ size s2 = n) /\ s = s1 ++ s2.
947+ proof.
948+ move=> ge0_m ge0_n szs; exists (take m s) (drop m s).
949+ by rewrite cat_take_drop /= !(size_take, size_drop) // #.
950+ qed.
951+
952+ lemma drop_take [' a] (s : ' a list) (i j : int ) :
953+ 0 <= i => 0 <= j => drop i (take j s) = take (j-i) (drop i s).
954+ proof.
955+ move=> ge0_i ge0_j; case : (j < i) => [lt_ji|/lezNgt le_ij].
956+ - rewrite (take_le0 (j-i)) 1 :/# drop_oversize // .
957+ by apply/(lez_trans j)/ltzW => // ; apply/size_take_le.
958+ case : (i < size s) => [lti|]; last first.
959+ - move=> /lezNgt lei; rewrite !drop_oversize // =.
960+ by rewrite &(lez_trans _ _ _ _ lei) size_take // #.
961+ rewrite {1 }(_ : j = i + (j - i)) 1 :addzCA // .
962+ rewrite takeD ~-1 :// # drop_catr // 1:&(size_take_le) //.
963+ by rewrite drop_le0 // size_take // lti.
964+ qed.
965+
919966lemma mem_drop n (s:' a list) x: mem (drop n s) x => mem s x.
920967proof. by rewrite -{2}[s](cat_take_drop n) mem_cat=>->. qed.
921968
@@ -951,6 +998,14 @@ move=> i [ge0_i lti]; rewrite nth_cat size_take //= lt_n_s /=.
951998smt (nth_take nth_drop).
952999qed.
9531000
1001+ lemma drop_take1_nth ['a] (x0 : ' a) (s : ' a list) (i : int ) :
1002+ 0 <= i < size s => take 1 (drop i s) = [nth x0 s i].
1003+ proof.
1004+ move=> [ge0_i lti]; rewrite -{1 }[s](cat_take_insert_drop x0 i) // .
1005+ rewrite drop_cat_le size_take // lti /=.
1006+ by rewrite drop_oversize 1 :size_take // 1:lti //= take0.
1007+ qed.
1008+
9541009lemma splitPr (xs : ' a list) (x : ' a): mem xs x =>
9551010 exists s1, exists s2, xs = s1 ++ x :: s2.
9561011proof.
@@ -2548,9 +2603,14 @@ lemma mkseqS f n : 0 <= n =>
25482603 mkseq<:' a> f (n + 1) = rcons (mkseq f n) (f n).
25492604proof. by move=> ge0_n; rewrite /mkseq iotaSr //= map_rcons. qed.
25502605
2551- lemma mkseqSr [' a] (f : int -> ' a) n : 0 <= n => mkseq f (n + 1) = f 0 :: mkseq (f \o ((+)%Int 1)) n.
2606+ lemma mkseqSr [' a] (f : int -> ' a) n : 0 <= n =>
2607+ mkseq f (n + 1) = f 0 :: mkseq (f \o ((+)%Int 1)) n.
25522608proof. by move => le0n; rewrite /mkseq iotaS //= map_comp -iota_addl. qed.
25532609
2610+ lemma mkseqSr_minus [' a] (f : int -> ' a) (n : int) :
2611+ 0 < n => mkseq f n = f 0 :: mkseq (f \o (+) 1) (n - 1).
2612+ proof. by move=> gt0_n; rewrite (mkseqSr _ (n-1)) //#. qed.
2613+
25542614lemma mkseq_add (f : int -> ' a) n m : 0 <= n => 0 <= m =>
25552615 mkseq f (n+m) = mkseq f n ++ mkseq (fun i => f (n+i)) m.
25562616proof.
@@ -2801,6 +2861,9 @@ proof.
28012861 by rewrite !flatten_cons ih catA.
28022862qed.
28032863
2864+ lemma flatten1 [' a] (x : ' a list) : flatten [x] = x.
2865+ proof. by rewrite flatten_cons flatten_nil cats0. qed.
2866+
28042867lemma flatten_rcons (s : ' a list list) (x : ' a list) :
28052868 flatten (rcons s x) = flatten s ++ x.
28062869proof. by rewrite -cats1 flatten_cat flatten_seq1. qed.
@@ -2929,6 +2992,46 @@ rewrite (_ : max 0 k = k) 1:/# //; elim: k ge0_k => [|k ge0_k ih].
29292992by rewrite nseqS // flatten_cons count_cat /#.
29302993qed.
29312994
2995+ lemma size_flatten_ctt [' a] (n : int ) (s : ' a list list) :
2996+ (forall x, x \i n s => size x = n)
2997+ => size (flatten s) = n * (size s).
2998+ proof.
2999+ move=> sz_s; rewrite size_flatten (iffLR _ _ (eq_in_map _ (fun _ => n) _)) //.
3000+ by elim: {sz_s} s => //= s @/sumz /= ->; rewrite mulzDr.
3001+ qed.
3002+
3003+ lemma drop_flatten_ctt [' a] (m n : int ) (s : ' a list list) :
3004+ (forall x, x \i n s => size x = m)
3005+ => drop (m * n) (flatten s) = flatten (drop n s).
3006+ proof.
3007+ move=> hsz; case: (m < 0) => [lt0_m|/lezNgt ge0_m].
3008+ - have ->>//: s = []; apply: contraLR lt0_m.
3009+ case: s hsz => // x s /(_ x _) // <- _.
3010+ by rewrite ltzNge /= size_ge0.
3011+ elim/natind: n s hsz => [n le0_n|n ge0_n ih] s hsz.
3012+ - by rewrite !drop_le0 //#.
3013+ rewrite mulzDr /=; case: s hsz => // x s hsz.
3014+ rewrite flatten_cons drop_cat hsz // iffalse 1:/#.
3015+ rewrite -addrA /= iffalse 1:/# &(ih) => ??.
3016+ by apply: hsz => /=; right.
3017+ qed.
3018+
3019+ lemma take_flatten_ctt [' a] (m n : int ) (s : ' a list list) :
3020+ (forall x, x \i n s => size x = m)
3021+ => take (m * n) (flatten s) = flatten (take n s).
3022+ proof.
3023+ move=> hsz; case: (m < 0) => [lt0_m|/lezNgt ge0_m].
3024+ - have ->>//: s = []; apply: contraLR lt0_m.
3025+ case: s hsz => // x s /(_ x _) // <- _.
3026+ by rewrite ltzNge /= size_ge0.
3027+ elim/natind: n s hsz => [n le0_n|n ge0_n ih] s hsz.
3028+ - by rewrite !take_le0 //#.
3029+ rewrite mulzDr /=; case: s hsz => // x s hsz.
3030+ rewrite flatten_cons take_cat hsz // iffalse 1:/#.
3031+ rewrite -addrA /= iffalse 1:/# ih // => ??.
3032+ by apply: hsz => /=; right.
3033+ qed.
3034+
29323035lemma perm_eq_pair [' a ' b] (s : (' a * ' b) list) : uniq s => perm_eq s
29333036 (flatten
29343037 (map (fun a => filter (fun xy : _ * _ => xy.`1 = a) s)
0 commit comments