11use crate :: utils:: graphs:: graph:: Graph ;
22use std:: collections:: { HashMap , HashSet , VecDeque } ;
3+ use std:: fmt:: Debug ;
34use std:: hash:: Hash ;
45
56pub trait IsEnd < T > {
@@ -24,7 +25,7 @@ pub struct AllPaths<'a, T: 'a> {
2425
2526impl < ' a , T > From < & ' a Graph < T > > for AllPaths < ' a , T >
2627where
27- T : Eq + Hash + Copy + PartialEq ,
28+ T : Eq + Hash + Copy + PartialEq + Debug ,
2829{
2930 fn from ( graph : & ' a Graph < T > ) -> Self {
3031 Self :: new ( move |p : T | graph. neighbours ( & p) )
@@ -33,15 +34,15 @@ where
3334
3435impl < ' a , T > From < & ' a HashMap < T , Vec < T > > > for AllPaths < ' a , T >
3536where
36- T : Eq + Hash + Copy + PartialEq ,
37+ T : Eq + Hash + Copy + PartialEq + Debug ,
3738{
3839 fn from ( value : & ' a HashMap < T , Vec < T > > ) -> Self {
3940 Self :: new ( move |p : T | value. get ( & p) . unwrap ( ) . to_vec ( ) )
4041 }
4142}
4243impl < ' a , T > AllPaths < ' a , T >
4344where
44- T : Eq + Hash + Copy ,
45+ T : Eq + Hash + Copy + Debug ,
4546{
4647 pub fn new ( adjacency : impl Fn ( T ) -> Vec < T > + ' a ) -> Self {
4748 Self {
8889 path. pop_back ( ) ;
8990 visited. remove ( & from) ;
9091 }
92+
93+ pub fn count_paths < E > (
94+ & self ,
95+ start : T ,
96+ end : E ,
97+ should_count_path : impl Fn ( & VecDeque < T > ) -> bool ,
98+ ) -> usize
99+ where
100+ E : IsEnd < T > ,
101+ {
102+ let mut visited = HashSet :: new ( ) ;
103+ let mut path = VecDeque :: new ( ) ;
104+
105+ self . visit_and_count ( start, & end, & mut visited, & mut path, & should_count_path)
106+ }
107+
108+ fn visit_and_count < E , F > (
109+ & self ,
110+ from : T ,
111+ end : & E ,
112+ visited : & mut HashSet < T > ,
113+ path : & mut VecDeque < T > ,
114+ should_count_path : & F ,
115+ ) -> usize
116+ where
117+ E : IsEnd < T > ,
118+ F : Fn ( & VecDeque < T > ) -> bool ,
119+ {
120+ let mut count = 0usize ;
121+
122+ visited. insert ( from) ; // probably is not needed for graph
123+ path. push_back ( from) ;
124+
125+ if end. is_end ( & from) {
126+ if should_count_path ( path) {
127+ count += 1 ;
128+ }
129+ } else {
130+ for p in ( self . adjacency ) ( from) {
131+ if !visited. contains ( & p) {
132+ count += self . visit_and_count ( p, end, visited, path, should_count_path) ;
133+ }
134+ }
135+ }
136+
137+ path. pop_back ( ) ;
138+ visited. remove ( & from) ;
139+
140+ count
141+ }
91142}
92143
93144#[ cfg( test) ]
0 commit comments