1use std::ops::{Index, IndexMut};
2pub trait Op<T> {
3 fn r#do(&mut self, status: &mut T);
4 fn undo(&mut self, status: &mut T);
5}
6impl<T> Op<T> for (){
7 fn r#do(&mut self, _: &mut T){}
8 fn undo(&mut self, _: &mut T){}
9}
10#[derive(Copy, Clone)]
11pub struct Add<I, V>(pub I, pub V);
12impl<T: IndexMut<I>, I: Copy, V: Copy> Op<T> for Add<I, V>
13where
14 <T as Index<I>>::Output: std::ops::SubAssign<V> + std::ops::AddAssign<V>,
15{
16 #[inline(always)]
17 fn r#do(&mut self, status: &mut T) {
18 status[self.0] += self.1
19 }
20 #[inline(always)]
21 fn undo(&mut self, status: &mut T) {
22 status[self.0] -= self.1
23 }
24}
25#[derive(Copy, Clone)]
26pub struct Assign<I, V>(pub I, pub V);
27impl<T:Index<I, Output = V>+IndexMut<I>, I: Copy, V: Copy+Sized> Op<T> for Assign<I, V> where {
28 #[inline(always)]
29 fn r#do(&mut self, status: &mut T) {
30 std::mem::swap(&mut status[self.0] , &mut self.1)
31 }
32 #[inline(always)]
33 fn undo(&mut self, status: &mut T) {
34 std::mem::swap(&mut status[self.0] , &mut self.1)
35 }
36}
37
38
39
40#[derive(Copy, Clone)]
41pub struct Chain<I:Op<T>, V:Op<T>,T>(I, V,[T;0]);
42impl<T> Chain<(),(),T>{
43 pub fn new()->Chain<(),(),T>{
44 Chain((),(),[])
45 }
46}
47impl<I:Op<T>, V:Op<T>,T> Chain<I, V,T>{
48 pub fn chain<W:Op<T>>(self,op:W)->Chain<Chain<I, V,T>,W,T>{
49 Chain(self,op,[])
50 }
51}
52impl<I:Op<T>, V:Op<T>,T> Op<T> for Chain<I,V,T>{
53 #[inline(always)]
54 fn r#do(&mut self, status: &mut T){
55 self.0.r#do(status);
56 self.1.r#do(status);
57 }
58 #[inline(always)]
59 fn undo(&mut self, status: &mut T){
60 self.1.undo(status);
61 self.0.undo(status);
62 }
63}
64pub struct DFS<
65 'a,
66 I,
67 C: Index<I,Output:Sized> + IndexMut<I>,
68 O: Op<C>,
69 V: FnOnce(&C) -> bool,
70 W: FnOnce(&C) -> X,
71 X: IntoIterator<Item = O>,
72> where <C as Index<I>>::Output:Sized{
73 status: &'a mut C,
74 check: V,
75 get_all_ops: W,
76 op: O,
77 _i:[I;0],
78}
79impl<
80 'a,
81 I,
82 C: Index<I,Output:Sized> + IndexMut<I> + std::fmt::Debug,
83 O: Op<C>,
84 V: Copy + FnOnce(&C) -> bool, W: Copy + FnOnce(&C) -> X,
86 X: IntoIterator<Item = O>,
87 > DFS<'a,I, C, O, V, W, X>
88{
89 pub fn new(
90 status: &'a mut C,
91 check: V,
92 get_all_ops: W,
93 op: O,
94 ) -> Self {
95 Self {
96 status,
97 check,
98 get_all_ops,
99 op,_i:[]
100 }
101 }
102 pub fn dfs<'b>(&'b mut self)
103 where
104 'a: 'b,
105 {
106 if (self.check)(self.status) {
107 return;
108 }
109 for op in (self.get_all_ops)(self.status) {
110 let mut next = self.forward(op);
111 next.dfs();
112 }
113 }
114 pub fn dfs_early_stop<'b>(&'b mut self) -> bool
115 where
116 'a: 'b,
117 {
118 if (self.check)(self.status) {
119 return true;
120 }
121 for op in (self.get_all_ops)(self.status) {
122 let mut next = self.forward(op);
123 if next.dfs_early_stop() {
124 return true;
125 }
126 }
127 false
128 }
129 pub fn forward<'b: 'c, 'c>(&'b mut self, mut op: O) -> DFS<'b,I, C, O, V, W, X>
130 where
131 'b: 'c,
132 {
133 op.r#do(self.status);
134 DFS {
135 status: self.status,
136 check: self.check,
137 get_all_ops: self.get_all_ops,
138 op,_i:[]
139 }
140 }
141}
142impl<
143 'a,
144 I,
145 C: Index<I,Output:Sized> + IndexMut<I>,
146 O: Op<C>,
147 V: FnOnce(&C) -> bool,
148 W: FnOnce(&C) -> X,
149 X: IntoIterator<Item = O>,
150 > Drop for DFS<'a,I, C, O, V, W, X>
151{
152 fn drop(&mut self) {
153 self.op.undo(self.status)
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn it_works() {
163 const N: usize = 3;
164 {
165 let mut s = [0i32; 2 * N + 1];
166 s[0] = N as i32;
167 let mut a = DFS::<usize,_,_,_,_,_>::new(
168 &mut s,
169 |s: &[i32; 2 * N + 1]| {
170 if s[0] == 0 {
171 eprintln!("{s:?}");
172 true
173 } else {
174 false
175 }
176 },
177 |s: &[i32; 2 * N + 1]| {
178 let a = s[0];
179 (1..2 * N as i32 - a)
180 .filter_map(move |x| {
181 if s[x as usize] + s[(1 + a + x) as usize] == 0 {
182 Some(Chain::new().chain(Add(x as usize,a)).chain(Add((1+a+x) as usize,a)).chain(Add(0,-1)))
183 } else {
184 None
185 }
186 })
187 .collect::<Vec<_>>()
188 },
189 Chain::new().chain(Add(0,1)).chain(Add(0,1)).chain(Add(0,-2)),
190 );
191 a.dfs();
192 a.dfs_early_stop();
193 }
194 }
195
196 #[test]
197 fn op_works(){
198 let mut a=[0,1,2,3,4,5];
199 let mut b=Add(0,1);
200 b.r#do(&mut a);
201 assert!(a==[1,1,2,3,4,5]);
202 #[derive(Copy, Clone)]
203 struct Swap<I>(I, I);
204 impl Op<[i32;6]> for Swap<usize> {
205 #[inline(always)]
206 fn r#do(&mut self, status: &mut [i32;6]) {
207 status.swap(self.0,self.1)
208 }
209 #[inline(always)]
210 fn undo(&mut self, status: &mut [i32;6]) {
211 status.swap(self.0,self.1)
212 }
213 }
214 let mut c=Swap(4,5);
215 c.r#do(&mut a);
216 assert!(a==[1,1,2,3,5,4]);
217 let mut d=Assign(5,8);
218 d.r#do(&mut a);
219 assert!(a==[1,1,2,3,5,8]);
220 let mut chain=Chain::new().chain(b).chain(c).chain(d);
221 chain.undo(&mut a);
222 assert!(a==[0,1,2,3,4,5]);
223 }
224}