// codesnip-guard: GameAnalyzer #[cfg_attr(any(),rustfmt::skip)]pub use self::game_analyzer::*;#[cfg_attr(any(),rustfmt::skip)]mod game_analyzer{use super::{Dyadic,Graph,Neighbor,TopologicalSortExt,UsizeGraph,VertexMap};use std::{borrow::Borrow,collections::{HashMap,HashSet},hash::Hash,marker::PhantomData,ops::ControlFlow};pub use graph::*;pub use impartial::*;pub use partisan::*;pub use scoring::*;pub use value::GameValue;mod graph{use super::{EvaluatedMove,GameAnalysis,GameAnalyzer,GameOutcome,GameSum,GameValue,Graph,HashMap,HashSet,Misere,Neighbor,TopologicalSortExt,UsizeGraph,VertexMap,game_mex};use std::{cmp::Reverse,collections::VecDeque};pub struct ImpartialGraph<'g,G>where G:Graph+VertexMap>{graph:&'g G,index:Option>,grundy:Vec>,outcomes:[GraphOutcomes;2],generalized_grundy:Vec>,sums:GraphSums}struct GraphIndexwhere G:Graph+VertexMap>{indices:G::Vmap,edges:Vec>,reverse:Vec>}#[derive(Default)]struct GraphSums{indices:HashMap,usize>,outcomes:GraphOutcomes}#[derive(Default)]struct GraphOutcomes{values:Vec,winning:Vec>}impl GameAnalyzer{#[doc=" Uses the graph's shared moves for both players. Query vertices must be"]#[doc=" valid inputs to the graph's `VertexMap` operations."]pub fn impartial_graph(self,graph:&G)->GameAnalyzer>where G:Graph+VertexMap>{GameAnalyzer{game:ImpartialGraph{graph,index:None,grundy:Vec::new(),outcomes:std::array::from_fn(|_|GraphOutcomes::default()),generalized_grundy:Vec::new(),sums:GraphSums::default()}}}}impl<'g,G>GameAnalyzer>where G:Graph+VertexMap>{pub fn grundy(&mut self)->GameAnalysis<'_,ImpartialGraph<'g,G>,G::Vertex,u64>{GameAnalysis::new(&mut self.game,ImpartialGraph::grundy)}pub fn value(&mut self)->GameAnalysis<'_,ImpartialGraph<'g,G>,G::Vertex,GameValue>{GameAnalysis::new(&mut self.game,|g,s|GameValue::nimber(g.grundy(s)))}pub fn outcome(&mut self)->GameAnalysis<'_,ImpartialGraph<'g,G>,G::Vertex,GameOutcome>{GameAnalysis::new(&mut self.game,|g,s|g.outcome(s,false))}pub fn misere(&mut self)->Misere<'_,ImpartialGraph<'g,G>>{Misere{game:&mut self.game}}pub fn sum(&mut self)->GameSum<'_,ImpartialGraph<'g,G>>{GameSum{game:&mut self.game}}pub fn clear_cache(&mut self){self.game.grundy.clear();self.game.outcomes=std::array::from_fn(|_|GraphOutcomes::default());self.game.generalized_grundy.clear();self.game.sums=GraphSums::default();}}impl<'a,'g,G>Misere<'a,ImpartialGraph<'g,G>>where G:Graph+VertexMap>{pub fn outcome(self)->GameAnalysis<'a,ImpartialGraph<'g,G>,G::Vertex,GameOutcome,true>{GameAnalysis::new(self.game,|g,s|g.outcome(s,true))}}impl<'a,'g,G>GameSum<'a,ImpartialGraph<'g,G>>where G:Graph+VertexMap>{pub fn grundy(self)->GameAnalysis<'a,ImpartialGraph<'g,G>,[G::Vertex],u64>{GameAnalysis::new(self.game,ImpartialGraph::sum_grundy)}}impl<'a,'g,G,const MISERE:bool>GameSum<'a,ImpartialGraph<'g,G>,MISERE>where G:Graph+VertexMap>{#[doc=" Normal play combines generalized Grundy values, including cyclic positions."]#[doc=" Misere explores the sum graph, which can grow exponentially in the component count."]pub fn outcome(self)->GameAnalysis<'a,ImpartialGraph<'g,G>,[G::Vertex],GameOutcome,MISERE>{GameAnalysis::new(self.game,|g,s|g.sum_outcome(s,MISERE))}}impl<'g,S,L,G,V,const MISERE:bool,E>GameAnalysis<'_,ImpartialGraph<'g,G>,S,V,MISERE,E>where S:Copy,G:Graph+VertexMap>,E:FnMut(&mut ImpartialGraph<'g,G>,&S)->V{#[doc=" Values describe the destination position; outcomes are for the next player."]pub fn moves(&mut self,state:&S)->Vec>{self.game.prepare();self.game.index_of(*state);self.game.graph.neighbors(*state).map(|next|{let value=self.eval(&next.to);EvaluatedMove{next,value}}).collect()}}implGameAnalysis<'_,ImpartialGraph<'_,G>,S,u64>where S:Copy,G:Graph+VertexMap>{pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.prepare();self.game.index_of(*state);self.game.graph.neighbors(*state).filter(|next|self.eval(&next.to)==0).collect()}}implGameAnalysis<'_,ImpartialGraph<'_,G>,S,GameValue>where S:Copy,G:Graph+VertexMap>{pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.prepare();self.game.index_of(*state);self.game.graph.neighbors(*state).filter(|next|self.eval(&next.to).as_nimber()==Some(0)).collect()}}implGameAnalysis<'_,ImpartialGraph<'_,G>,S,GameOutcome,MISERE>where S:Copy,G:Graph+VertexMap>{#[doc=" Moves to losing positions. To avoid cycling among winning positions,"]#[doc=" repeatedly use `best_move`, which follows the retrograde proof."]pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.prepare();self.game.index_of(*state);self.game.graph.neighbors(*state).filter(|next|self.eval(&next.to)==GameOutcome::Lose).collect()}#[doc=" A move that guarantees termination when winning, or preserves a draw."]#[doc=" Returns `None` at terminal or losing positions."]pub fn best_move(&mut self,state:&S)->Option>{let outcome=self.eval(state);if outcome==GameOutcome::Lose{return None;}let game=&self.game;let root=game.index_of(*state);let result=&game.outcomes[usize::from(MISERE)];let winner=result.winning[root];for next in game.graph.neighbors(*state){let id=game.index_of(next.to);if Some(id)==winner||outcome==GameOutcome::Draw&&result.values[id]==GameOutcome::Draw{return Some(next);}}None}}#[allow(clippy::type_complexity)]impl<'g,S,L,G,V,const MISERE:bool,E>GameAnalysis<'_,ImpartialGraph<'g,G>,[S],V,MISERE,E>where S:Copy,G:Graph+VertexMap>,E:FnMut(&mut ImpartialGraph<'g,G>,&[S])->V{pub fn moves(&mut self,state:&[S])->Vec,(usize,L),V>>{self.eval(state);let mut result=Vec::new();for(i,&component)in state.iter().enumerate(){for next in self.game.graph.neighbors(component){let mut to=state.to_vec();to[i]=next.to;let value=self.eval(&to);result.push(EvaluatedMove{next:Neighbor::new(to,(i,next.label)),value});}}result}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,ImpartialGraph<'_,G>,[S],u64>where S:Copy,G:Graph+VertexMap>{pub fn winning_moves(&mut self,state:&[S])->Vec,(usize,L)>>{let xor=self.eval(state);let mut result=Vec::new();if xor==0{return result;}for(i,component)in state.iter().enumerate(){let target=xor^self.game.grundy(component);for next in self.game.graph.neighbors(*component){if self.game.grundy(&next.to)==target{let mut to=state.to_vec();to[i]=next.to;result.push(Neighbor::new(to,(i,next.label)));}}}result}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,ImpartialGraph<'_,G>,[S],GameOutcome,MISERE>where S:Copy,G:Graph+VertexMap>{#[doc=" Moves to losing positions; use `best_move` to avoid cycling."]pub fn winning_moves(&mut self,state:&[S])->Vec,(usize,L)>>{if state.is_empty(){return Vec::new();}if let[single]=state{let mut query:GameAnalysis<'_,_,S,GameOutcome,MISERE>=GameAnalysis::new(self.game,|g:&mut ImpartialGraph<'_,G>,s|{g.outcome(s,MISERE)});return query.winning_moves(single).into_iter().map(|next|Neighbor::new(vec![next.to],(0,next.label))).collect();}if self.eval(state)!=GameOutcome::Win{return Vec::new();}let mut indices=self.game.sum_indices(state);let game=&self.game;let mut xor=0;let mut infinite=0;if!MISERE{for&v in&indices{if let Some((value,_))=game.generalized_grundy[v]{xor^=value;}else{infinite+=1;}}}let mut result=Vec::new();for(i,&component)in state.iter().enumerate(){let source=indices[i];for next in game.graph.neighbors(component){indices[i]=game.index_of(next.to);let wins=if MISERE{let key=GraphSums::canonical(indices.clone(),&game.index.as_ref().unwrap().edges);game.sums.outcomes.values[game.sums.indices[&key]]==GameOutcome::Lose}else if let Some((value,_))=game.generalized_grundy[indices[i]]{match game.generalized_grundy[source]{Some((g,_))=>infinite==0&&xor^g==value,None=>infinite==1&&xor==value,}}else{false};if wins{let mut to=state.to_vec();to[i]=next.to;result.push(Neighbor::new(to,(i,next.label)));}}indices[i]=source;}result}#[doc=" A move that guarantees termination when winning, or preserves a draw."]#[doc=" Returns `None` at terminal or losing positions."]pub fn best_move(&mut self,state:&[S])->Option,(usize,L)>>{if state.is_empty(){return None;}if let[single]=state{let mut query:GameAnalysis<'_,_,S,GameOutcome,MISERE>=GameAnalysis::new(self.game,|g:&mut ImpartialGraph<'_,G>,s|{g.outcome(s,MISERE)});return query.best_move(single).map(|next|Neighbor::new(vec![next.to],(0,next.label)));}let outcome=self.eval(state);if outcome==GameOutcome::Lose{return None;}let mut indices=self.game.sum_indices(state);let game=&self.game;if MISERE{let key=GraphSums::canonical(indices.clone(),&game.index.as_ref().unwrap().edges);let winner=game.sums.outcomes.winning[game.sums.indices[&key]];for(i,&component)in state.iter().enumerate(){let original=indices[i];for next in game.graph.neighbors(component){indices[i]=game.index_of(next.to);let key=GraphSums::canonical(indices.clone(),&game.index.as_ref().unwrap().edges);let id=game.sums.indices[&key];if Some(id)==winner||outcome==GameOutcome::Draw&&game.sums.outcomes.values[id]==GameOutcome::Draw{let mut to=state.to_vec();to[i]=next.to;return Some(Neighbor::new(to,(i,next.label)));}}indices[i]=original;}return None;}let mut xor=0;let mut infinite=None;let mut multiple=false;for(i,&v)in indices.iter().enumerate(){if let Some((value,_))=game.generalized_grundy[v]{xor^=value;}else if infinite.replace(i).is_some(){multiple=true;break;}}if outcome==GameOutcome::Draw{let i=infinite.unwrap();let v=indices[i];let edges=&game.index.as_ref().unwrap().edges;let target=(!multiple).then(| |{let values=edges[v].iter().filter_map(|&u|game.generalized_grundy[u].map(|(g,_)|g)).collect();game_mex(values)});if target.is_none_or(|g|g==xor){let to=edges[v].iter().copied().find(|&u|{game.generalized_grundy[u].is_none()&&target.is_none_or(|g|{!edges[u].iter().any(|&w|{game.generalized_grundy[w].is_some_and(|(value,_)|value==g)})})}).unwrap();let next=game.graph.neighbors(state[i]).find(|next|game.index_of(next.to)==to).unwrap();let mut to=state.to_vec();to[i]=next.to;return Some(Neighbor::new(to,(i,next.label)));}xor^=target.unwrap();infinite=None;}let(i,target)=if let Some(i)=infinite{(i,xor)}else{let(i,(g,_))=indices.iter().enumerate().filter_map(|(i,&v)|game.generalized_grundy[v].map(|g|(i,g))).filter(|(_,(g,_))|g^xor<*g).max_by_key(|&(i,g)|(g,Reverse(i)))?;(i,g^xor)};let next=game.graph.neighbors(state[i]).filter_map(|next|{let(g,counter)=game.generalized_grundy[game.index_of(next.to)]?;(g==target).then_some((next,counter))}).min_by_key(|&(_,counter)|counter)?.0;let mut to=state.to_vec();to[i]=next.to;Some(Neighbor::new(to,(i,next.label)))}}implImpartialGraph<'_,G>where G:Graph+VertexMap>{fn grundy(&mut self,state:&G::Vertex)->u64{self.prepare();let root=self.index_of(*state);let index=self.index.as_ref().unwrap();self.grundy.resize(index.edges.len(),None);if let Some(value)=self.grundy[root]{return value;}let mut active=HashSet::from([root]);let mut stack=vec![(root,index.edges[root].iter())];while let Some((v,moves))=stack.last_mut(){if let Some(&u)=moves.next(){if self.grundy[u].is_none(){assert!(active.insert(u),"cycle in a finite game");stack.push((u,index.edges[u].iter()));}}else{let values=index.edges[*v].iter().map(|&u|self.grundy[u].unwrap()).collect();self.grundy[*v]=Some(game_mex(values));active.remove(v);stack.pop();}}self.grundy[root].unwrap()}fn outcome(&mut self,state:&G::Vertex,misere:bool)->GameOutcome{self.prepare();let index=self.index.as_ref().unwrap();let outcome=&mut self.outcomes[usize::from(misere)];if outcome.values.is_empty(){outcome.extend(&index.edges,&index.reverse,misere);}self.outcomes[usize::from(misere)].values[self.index_of(*state)]}fn sum_grundy(&mut self,state:&[G::Vertex])->u64{state.iter().fold(0,|value,s|value^self.grundy(s))}fn sum_outcome(&mut self,state:&[G::Vertex],misere:bool)->GameOutcome{match state{[]=>return GameOutcome::from_win(misere),[single]=>return self.outcome(single,misere),_=>{}}let indices=self.sum_indices(state);if!misere{self.solve_generalized_grundy();return self.sum_normal_outcome(&indices);}let edges=&self.index.as_ref().unwrap().edges;let root=self.sums.prepare(indices,edges);self.sums.outcomes.values[root]}fn sum_normal_outcome(&self,state:&[usize])->GameOutcome{let mut xor=0;let mut infinite=None;for&v in state{if let Some((value,_))=self.generalized_grundy[v]{xor^=value;}else if infinite.replace(v).is_some(){return GameOutcome::Draw;}}if let Some(v)=infinite{let can_win=self.index.as_ref().unwrap().edges[v].iter().any(|&u|self.generalized_grundy[u].is_some_and(|(value,_)|value==xor));if can_win{GameOutcome::Win}else{GameOutcome::Draw}}else if xor==0{GameOutcome::Lose}else{GameOutcome::Win}}fn sum_indices(&mut self,state:&[G::Vertex])->Vec{self.prepare();state.iter().map(|&s|self.index_of(s)).collect()}fn prepare(&mut self){if self.index.is_some(){return;}let vertices:Vec<_>=self.graph.vertices().collect();let mut indices=self.graph.construct_vmap(| |None);for(i,&v)in vertices.iter().enumerate(){self.graph.vmap_set(&mut indices,v,Some(i));}let mut edges=vec![Vec::new();vertices.len()];let mut reverse=vec![Vec::new();vertices.len()];let mut seen=vec![None;vertices.len()];for(i,&v)in vertices.iter().enumerate(){for next in self.graph.neighbors(v){let j=self.graph.vmap_get(&indices,next.to).expect("vertex is not enumerated by the graph");if seen[j]!=Some(i){seen[j]=Some(i);edges[i].push(j);reverse[j].push(i);}}}self.index=Some(GraphIndex{indices,edges,reverse});}fn index_of(&self,v:G::Vertex)->usize{self.graph.vmap_get(&self.index.as_ref().unwrap().indices,v).expect("vertex is not enumerated by the graph")}fn solve_generalized_grundy(&mut self){let index=self.index.as_ref().unwrap();let n=index.edges.len();if self.generalized_grundy.len()==n{return;}let mut values:Vec>=vec![None;n];let reverse=UsizeGraph::new(n,|v:usize|index.reverse[v].iter().map(|&u|(u,())));let order=reverse.topological_sort();if order.len()==n{for(counter,v)in order.into_iter().enumerate(){let mex=self.grundy.get(v).copied().flatten().unwrap_or_else(| |{let options=index.edges[v].iter().map(|&u|values[u].unwrap().0).collect();game_mex(options)});values[v]=Some((mex,counter));}self.generalized_grundy=values;return;}let mut queue:VecDeque<_>=order.into();let mut queued=vec![false;n];for&v in&queue{queued[v]=true;}for(v,pending)in queued.iter_mut().enumerate(){if!*pending{*pending=true;queue.push_back(v);}}let mut counter=0;let mut options=vec![HashSet::new();n];let mut mexes=vec![0;n];while let Some(v)=queue.pop_front(){queued[v]=false;let mex=mexes[v];let ready=index.edges[v].iter().all(|&u|values[u].is_some()||options[u].contains(&mex));if!ready{continue;}values[v]=Some((mex,counter));counter+=1;for&u in&index.reverse[v]{if values[u].is_some(){continue;}let inserted=options[u].insert(mex);if inserted{while options[u].contains(&mexes[u]){mexes[u]+=1;}}if mex,components:&[Vec])->usize{let state=Self::canonical(state,components);if let Some(&root)=self.indices.get(&state){return root;}let root=self.outcomes.values.len();self.indices.insert(state.clone(),root);let mut edges=vec![Vec::new()];let mut reverse=vec![Vec::new()];let mut pending=VecDeque::from([(root,state)]);while let Some((v,state))=pending.pop_front(){for(i,&component)in state.iter().enumerate(){if i!=0&&state[i-1]==component{continue;}for&next in&components[component]{let mut to=state.clone();to[i]=next;let to=Self::canonical(to,components);let u=*self.indices.entry(to).or_insert_with_key(|to|{let u=root+edges.len();pending.push_back((u,to.clone()));edges.push(Vec::new());reverse.push(Vec::new());u});edges[v-root].push(u);}}edges[v-root].sort_unstable();edges[v-root].dedup();for&u in&edges[v-root]{if u>=root{reverse[u-root].push(v);}}}self.outcomes.extend(&edges,&reverse,true);root}fn canonical(mut state:Vec,components:&[Vec])->Vec{state.retain(|&v|!components[v].is_empty());state.sort_unstable();state}}impl GraphOutcomes{fn extend(&mut self,edges:&[Vec],reverse:&[Vec],misere:bool){let start=self.values.len();self.values.resize(start+edges.len(),GameOutcome::Draw);self.winning.resize(start+edges.len(),None);let mut remaining:Vec<_>=edges.iter().map(Vec::len).collect();let mut queue=VecDeque::new();for(i,next)in edges.iter().enumerate(){let v=start+i;if next.is_empty(){self.values[v]=GameOutcome::from_win(misere);}else if start!=0{for&u in next{if u{self.values[v]=GameOutcome::Win;self.winning[v]=Some(u);break;}GameOutcome::Win=>remaining[v-start]-=1,GameOutcome::Draw=>{}}}}if self.values[v]==GameOutcome::Draw&&remaining[v-start]==0{self.values[v]=GameOutcome::Lose;}}if self.values[v]!=GameOutcome::Draw{queue.push_back(v);}}while let Some(v)=queue.pop_front(){for&u in&reverse[v-start]{if self.values[u]!=GameOutcome::Draw{continue;}if self.values[v]==GameOutcome::Lose{self.values[u]=GameOutcome::Win;self.winning[u]=Some(v);queue.push_back(u);}else{remaining[u-start]-=1;if remaining[u-start]==0{self.values[u]=GameOutcome::Lose;queue.push_back(u);}}}}}}}mod impartial{use super::{ControlFlow,EvaluatedMove,GameAnalysis,GameAnalyzer,GameOutcome,GameSum,GameValue,Hash,HashMap,HashSet,Misere,Neighbor,canonical_sum,game_mex,memoized_game,memoized_wins};pub struct Impartial{moves:F,grundy:HashMap,outcomes:[HashMap;2],sums:HashMap,bool>,sum_ids:HashMap}impl GameAnalyzer{#[allow(clippy::type_complexity)]pub fn impartial(self,mut moves:F)->GameAnalyzerstd::iter::MapNeighbor>>>where F:FnMut(&S)->I,I:IntoIterator{let label:fn(S)->Neighbor=|to|Neighbor::new(to,());self.impartial_moves(move|s:&S|moves(s).into_iter().map(label))}pub fn impartial_moves(self,moves:F)->GameAnalyzer>where F:FnMut(&S)->I,I:IntoIterator>{GameAnalyzer{game:Impartial{moves,grundy:HashMap::new(),outcomes:std::array::from_fn(|_|HashMap::new()),sums:HashMap::new(),sum_ids:HashMap::new()}}}}implGameAnalyzer>{pub fn misere(&mut self)->Misere<'_,Impartial>{Misere{game:&mut self.game}}pub fn sum(&mut self)->GameSum<'_,Impartial>{GameSum{game:&mut self.game}}pub fn clear_cache(&mut self){self.game.grundy.clear();self.game.outcomes.iter_mut().for_each(HashMap::clear);self.game.sums.clear();self.game.sum_ids.clear();}}implGameAnalyzer>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn grundy(&mut self)->GameAnalysis<'_,Impartial,S,u64>{GameAnalysis::new(&mut self.game,Impartial::grundy)}pub fn value(&mut self)->GameAnalysis<'_,Impartial,S,GameValue>{GameAnalysis::new(&mut self.game,|g,s|GameValue::nimber(g.grundy(s)))}pub fn outcome(&mut self)->GameAnalysis<'_,Impartial,S,GameOutcome>{GameAnalysis::new(&mut self.game,|g,s|g.outcome(s,false))}#[doc=" `combine` receives each move's label and the value of its destination."]#[allow(clippy::type_complexity)]pub fn fold(&mut self,mut combine:C)->GameAnalysis<'_,Impartial,S,V,false,impl FnMut(&mut Impartial,&S)->V>where V:Clone,C:FnMut(&S,&[(L,V)])->V{let mut cache=HashMap::new();GameAnalysis::new(&mut self.game,move|game:&mut Impartial,state:&S|{memoized_game(state,&mut cache,&mut HashSet::new(),&mut|s|{ControlFlow::Continue(((game.moves)(s).into_iter().map(|n|(n.to,n.label)),Vec::new()))},&mut|_,moves|moves.next(),&mut|values,label,value|{values.push((label,value));ControlFlow::Continue(())},&mut|s,values|combine(s,&values))})}}impl<'a,S,L,F,I>Misere<'a,Impartial>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn outcome(self)->GameAnalysis<'a,Impartial,S,GameOutcome,true>{GameAnalysis::new(self.game,|g,s|g.outcome(s,true))}}impl<'a,S,L,F,I>GameSum<'a,Impartial>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn grundy(self)->GameAnalysis<'a,Impartial,[S],u64>{GameAnalysis::new(self.game,Impartial::sum_grundy)}}impl<'a,S,L,F,I,const MISERE:bool>GameSum<'a,Impartial,MISERE>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn outcome(self)->GameAnalysis<'a,Impartial,[S],GameOutcome,MISERE>{GameAnalysis::new(self.game,|g,s|g.sum_outcome(s,MISERE))}}implGameAnalysis<'_,Impartial,S,V,MISERE,E>where F:FnMut(&S)->I,I:IntoIterator>,E:FnMut(&mut Impartial,&S)->V{pub fn moves(&mut self,state:&S)->Vec>{(self.game.moves)(state).into_iter().map(|next|{let value=self.eval(&next.to);EvaluatedMove{next,value}}).collect()}}implGameAnalysis<'_,Impartial,S,u64>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.winning_moves(state,false).collect()}}implGameAnalysis<'_,Impartial,S,GameValue>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.winning_moves(state,false).collect()}}implGameAnalysis<'_,Impartial,S,GameOutcome,MISERE>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn winning_moves(&mut self,state:&S)->Vec>{self.game.winning_moves(state,MISERE).collect()}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,Impartial,[S],V,MISERE,E>where S:Clone,F:FnMut(&S)->I,I:IntoIterator>,E:FnMut(&mut Impartial,&[S])->V{pub fn moves(&mut self,state:&[S])->Vec,(usize,L),V>>{let mut result=Vec::new();for(i,component)in state.iter().enumerate(){for next in(self.game.moves)(component){let mut to=state.to_vec();to[i]=next.to;let value=self.eval(&to);result.push(EvaluatedMove{next:Neighbor::new(to,(i,next.label)),value});}}result}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,Impartial,[S],u64>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn winning_moves(&mut self,state:&[S])->Vec,(usize,L)>>{self.game.sum_winning_moves(state)}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,Impartial,[S],GameOutcome,MISERE>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{pub fn winning_moves(&mut self,state:&[S])->Vec,(usize,L)>>{if let[single]=state{return self.game.winning_moves(single,MISERE).map(|next|Neighbor::new(vec![next.to],(0,next.label))).collect();}if!MISERE{return self.game.sum_winning_moves(state);}let mut result=Vec::new();for(i,component)in state.iter().enumerate(){for next in(self.game.moves)(component){let mut to=state.to_vec();to[i]=next.to;if self.eval(&to)==GameOutcome::Lose{result.push(Neighbor::new(to,(i,next.label)));}}}result}}implImpartialwhere S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>{fn grundy(&mut self,state:&S)->u64{memoized_game(state,&mut self.grundy,&mut HashSet::new(),&mut|s|{if self.outcomes[0].get(s)==Some(&false){return ControlFlow::Break(0);}let moves=(self.moves)(s).into_iter().map(|n|(n.to,()));ControlFlow::Continue((moves,Vec::new()))},&mut|_,moves|moves.next(),&mut|values,(),value|{values.push(value);ControlFlow::Continue(())},&mut|_,values|game_mex(values))}fn outcome(&mut self,state:&S,misere:bool)->GameOutcome{let win=memoized_wins(state,&mut self.outcomes[usize::from(misere)],|s|{if!misere&&let Some(&value)=self.grundy.get(s){return ControlFlow::Break(value!=0);}let moves=(self.moves)(s).into_iter().map(|n|n.to);ControlFlow::Continue(moves)},|_,moves|moves.next(),misere);GameOutcome::from_win(win)}fn winning_moves(&mut self,state:&S,misere:bool)->impl Iterator>{(self.moves)(state).into_iter().filter(move|next|{if!misere&&let Some(&value)=self.grundy.get(&next.to){value==0}else{self.outcome(&next.to,misere)==GameOutcome::Lose}})}fn sum_grundy(&mut self,state:&[S])->u64{match state{[]=>return 0,[single]=>return self.grundy(single),_=>{}}let(xor,odd)=self.reduce_sum(state);odd.into_iter().fold(xor,|value,s|value^self.grundy(s))}#[allow(clippy::type_complexity)]fn sum_winning_moves(&mut self,state:&[S])->Vec,(usize,L)>>{let xor=self.sum_grundy(state);let mut result=Vec::new();if xor==0{return result;}for(i,component)in state.iter().enumerate(){let target=xor^self.grundy(component);for next in(self.moves)(component){if self.grundy(&next.to)==target{let mut to=state.to_vec();to[i]=next.to;result.push(Neighbor::new(to,(i,next.label)));}}}result}fn sum_outcome(&mut self,state:&[S],misere:bool)->GameOutcome{if state.is_empty(){return GameOutcome::from_win(misere);}if let[single]=state{return self.outcome(single,misere);}let win=if misere{if let Some(&win)=self.sums.get(state){win}else{memoized_wins(&canonical_sum(state.to_vec(),&mut self.sum_ids),&mut self.sums,|_|ControlFlow::Continue((0,None)),|s,(i,moves)|{while*i(&self,state:&'a[S])->(u64,HashSet<&'a S>){let mut xor=0;let mut odd=HashSet::new();for s in state{if let Some(&value)=self.grundy.get(s){xor^=value;}else if self.outcomes[0].get(s)!=Some(&false)&&!odd.insert(s){odd.remove(s);}}(xor,odd)}}}mod partisan{use super::{ControlFlow,EvaluatedMove,GameAnalysis,GameAnalyzer,GameSum,GameValue,Hash,HashMap,HashSet,Misere,Neighbor,PartisanOutcome,Player,canonical_sum,memoized_game,memoized_wins};use std::cmp::Ordering;pub struct Partisan{left:FL,right:FR,values:HashMap,outcomes:[HashMap<(S,Player),bool>;2],sums:[HashMap<(Vec,Player),bool>;2],sum_ids:HashMap}impl GameAnalyzer{#[allow(clippy::type_complexity)]pub fn partisan(self,mut left:FL,mut right:FR)->GameAnalyzerstd::iter::MapNeighbor>,impl FnMut(&S)->std::iter::MapNeighbor>>>where FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator,IR:IntoIterator{let label:fn(S)->Neighbor=|to|Neighbor::new(to,());self.partisan_moves(move|s:&S|left(s).into_iter().map(label),move|s:&S|right(s).into_iter().map(label))}pub fn partisan_moves(self,left:FL,right:FR)->GameAnalyzer>where FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{GameAnalyzer{game:Partisan{left,right,values:HashMap::new(),outcomes:std::array::from_fn(|_|HashMap::new()),sums:std::array::from_fn(|_|HashMap::new()),sum_ids:HashMap::new()}}}}implGameAnalyzer>{pub fn misere(&mut self)->Misere<'_,Partisan>{Misere{game:&mut self.game}}pub fn sum(&mut self)->GameSum<'_,Partisan>{GameSum{game:&mut self.game}}pub fn clear_cache(&mut self){self.game.values.clear();self.game.outcomes.iter_mut().for_each(HashMap::clear);self.game.sums.iter_mut().for_each(HashMap::clear);self.game.sum_ids.clear();}}implGameAnalyzer>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{pub fn value(&mut self)->GameAnalysis<'_,Partisan,S,GameValue>{GameAnalysis::new(&mut self.game,Partisan::value)}pub fn outcome(&mut self)->GameAnalysis<'_,Partisan,S,PartisanOutcome>{GameAnalysis::new(&mut self.game,|g,s|g.outcome(s,false))}#[doc=" `combine` receives all Left options followed by all Right options."]#[allow(clippy::type_complexity)]pub fn fold(&mut self,mut combine:C)->GameAnalysis<'_,Partisan,S,V,false,impl FnMut(&mut Partisan,&S)->V>where V:Clone,C:FnMut(&S,&[(Player,L,V)])->V{let mut cache=HashMap::new();GameAnalysis::new(&mut self.game,move|game:&mut Partisan,state:&S|{memoized_game(state,&mut cache,&mut HashSet::new(),&mut|s|{let moves=(game.left)(s).into_iter().map(|n|(n.to,(Player::Left,n.label))).chain((game.right)(s).into_iter().map(|n|(n.to,(Player::Right,n.label))));ControlFlow::Continue((moves,Vec::new()))},&mut|_,moves|moves.next(),&mut|values,(player,label),value|{values.push((player,label,value));ControlFlow::Continue(())},&mut|s,values|combine(s,&values))})}}impl<'a,S,L,FL,FR,IL,IR>Misere<'a,Partisan>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{pub fn outcome(self)->GameAnalysis<'a,Partisan,S,PartisanOutcome,true>{GameAnalysis::new(self.game,|g,s|g.outcome(s,true))}}impl<'a,S,L,FL,FR,IL,IR>GameSum<'a,Partisan>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{pub fn value(self)->GameAnalysis<'a,Partisan,[S],GameValue>{GameAnalysis::new(self.game,|g,state:&[S]|{state.iter().map(|s|g.value(s)).sum()})}}impl<'a,S,L,FL,FR,IL,IR,const MISERE:bool>GameSum<'a,Partisan,MISERE>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{#[doc=" Explores reachable sum positions, including the player to move."]#[doc=" Reuses cached sums of numbers, ups, nimbers and switches in normal play."]pub fn outcome(self)->GameAnalysis<'a,Partisan,[S],PartisanOutcome,MISERE>{GameAnalysis::new(self.game,|g,s|{match(g.sum_wins(s,Player::Left,MISERE),g.sum_wins(s,Player::Right,MISERE)){(true,true)=>PartisanOutcome::Next,(false,false)=>PartisanOutcome::Previous,(true,false)=>PartisanOutcome::Left,(false,true)=>PartisanOutcome::Right,}})}}implGameAnalysis<'_,Partisan,S,V,MISERE,E>where FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>,E:FnMut(&mut Partisan,&S)->V{#[doc=" Values describe the destination game for both choices of starting player."]pub fn moves(&mut self,state:&S,player:Player)->Vec>{partisan_moves(&mut self.game.left,&mut self.game.right,state,player).map(|next|{let value=self.eval(&next.to);EvaluatedMove{next,value}}).collect()}}implGameAnalysis<'_,Partisan,S,GameValue>where FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{pub fn compare(&mut self,left:&S,right:&S)->Option{self.eval(left).partial_cmp(&self.eval(right))}#[doc=" Undominated moves for the selected player; incomparable alternatives remain."]pub fn undominated_moves(&mut self,state:&S,player:Player)->Vec>{let moves=self.moves(state,player);let preferred=if player==Player::Left{Ordering::Greater}else{Ordering::Less};let best=moves.iter().try_fold(None,|best,m|{let(q,k,n)=m.value.as_number_up_nimber()?;let pair=(q,k);Some(Some(match best{Some((previous,nimber))=>match pair.cmp(&previous){Ordering::Equal=>(previous,if nimber==Some(n){nimber}else{None}),order if order==preferred=>(pair,Some(n)),_=>(previous,nimber),},None=>(pair,Some(n)),}))});if let Some(best)=best{return moves.into_iter().filter(|m|{let(q,k,n)=m.value.as_number_up_nimber().unwrap();best.is_some_and(|((b,l),nimber)|{q==b&&(k==l||k.abs_diff(l)==1&&nimber==Some(n^1))})}).map(|m|m.next).collect();}let mut dominated=vec![false;moves.len()];for i in 0..moves.len(){if dominated[i]{continue;}for j in i+1..moves.len(){if dominated[j]{continue;}let order=moves[i].value.partial_cmp(&moves[j].value);if order==Some(preferred){dominated[j]=true;}else if order==Some(preferred.reverse()){dominated[i]=true;break;}}}moves.into_iter().zip(dominated).filter(|(_,d)|!d).map(|(m,_)|m.next).collect()}}implGameAnalysis<'_,Partisan,S,PartisanOutcome,MISERE>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{#[doc=" Whether the selected starting player can force a win."]pub fn wins(&mut self,state:&S,player:Player)->bool{self.game.wins(state,player,MISERE)}pub fn winning_moves(&mut self,state:&S,player:Player)->Vec>{partisan_moves(&mut self.game.left,&mut self.game.right,state,player).filter(|next|!self.game.wins(&next.to,player.opponent(),MISERE)).collect()}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,Partisan,[S],V,MISERE,E>where S:Clone,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>,E:FnMut(&mut Partisan,&[S])->V{pub fn moves(&mut self,state:&[S],player:Player)->Vec,(usize,L),V>>{let mut result=Vec::new();for(i,component)in state.iter().enumerate(){for next in partisan_moves(&mut self.game.left,&mut self.game.right,component,player){let mut to=state.to_vec();to[i]=next.to;let value=self.eval(&to);result.push(EvaluatedMove{next:Neighbor::new(to,(i,next.label)),value});}}result}}#[allow(clippy::type_complexity)]implGameAnalysis<'_,Partisan,[S],PartisanOutcome,MISERE>where S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{#[doc=" Whether the selected starting player can force a win."]pub fn wins(&mut self,state:&[S],player:Player)->bool{self.game.sum_wins(state,player,MISERE)}pub fn winning_moves(&mut self,state:&[S],player:Player)->Vec,(usize,L)>>{let mut result=Vec::new();for(i,component)in state.iter().enumerate(){for next in partisan_moves(&mut self.game.left,&mut self.game.right,component,player){let mut to=state.to_vec();to[i]=next.to;if!self.game.sum_wins(&to,player.opponent(),MISERE){result.push(Neighbor::new(to,(i,next.label)));}}}result}}implPartisanwhere S:Clone+Eq+Hash,FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{fn value(&mut self,state:&S)->GameValue{memoized_game(state,&mut self.values,&mut HashSet::new(),&mut|s|{let moves=(self.left)(s).into_iter().map(|n|(n.to,Player::Left)).chain((self.right)(s).into_iter().map(|n|(n.to,Player::Right)));ControlFlow::Continue((moves,(Vec::new(),Vec::new())))},&mut|_,moves|moves.next(),&mut|(left,right),player,value|{if player==Player::Left{left.push(value)}else{right.push(value)}ControlFlow::Continue(())},&mut|_,(left,right)|GameValue::from_options(left,right))}fn outcome(&mut self,state:&S,misere:bool)->PartisanOutcome{match(self.wins(state,Player::Left,misere),self.wins(state,Player::Right,misere)){(true,true)=>PartisanOutcome::Next,(false,false)=>PartisanOutcome::Previous,(true,false)=>PartisanOutcome::Left,(false,true)=>PartisanOutcome::Right,}}fn wins(&mut self,state:&S,player:Player,misere:bool)->bool{let key=(state.clone(),player);memoized_wins(&key,&mut self.outcomes[usize::from(misere)],|(s,p)|{if!misere&&let Some(value)=self.values.get(s){return ControlFlow::Break(value.wins(*p));}let next_player=p.opponent();let moves=partisan_moves(&mut self.left,&mut self.right,s,*p).map(move|n|(n.to,next_player));ControlFlow::Continue(moves)},|_,moves|moves.next(),misere)}fn sum_wins(&mut self,state:&[S],player:Player,misere:bool)->bool{match state{[]=>return misere,[single]=>return self.wins(single,player,misere),_=>{}}let mut normalize=|mut state:Vec|{if!misere{state.retain(|s|{if let Some(value)=self.values.get(s){return value.as_nimber()!=Some(0);}let mut key=(s.clone(),Player::Left);if self.outcomes[0].get(&key)!=Some(&false){return true;}key.1=Player::Right;self.outcomes[0].get(&key)!=Some(&false)});}canonical_sum(state,&mut self.sum_ids)};let state=normalize(state.to_vec());match state.as_slice(){[]=>return misere,[single]=>return self.wins(single,player,misere),_=>{}}let key=(state,player);memoized_wins(&key,&mut self.sums[usize::from(misere)],|(s,p)|{if!misere&&s.iter().all(|s|{self.values.get(s).is_some_and(|g|g.as_switch_sum().is_some())}){let value:GameValue=s.iter().map(|s|self.values[s].clone()).sum();return ControlFlow::Break(value.wins(*p));}if!misere&&(!self.values.is_empty()||!self.outcomes[0].is_empty()){let mut all_lose=true;let mut all_opponent_lose=true;let mut can_win=false;for s in s{let(mut win,mut opponent_win)=(None,None);if!self.outcomes[0].is_empty(){let mut key=(s.clone(),*p);win=self.outcomes[0].get(&key).copied();key.1=p.opponent();opponent_win=self.outcomes[0].get(&key).copied();}if let Some(value)=self.values.get(s){win.get_or_insert_with(| |value.wins(*p));opponent_win.get_or_insert_with(| |value.wins(p.opponent()));}can_win=can_win&&opponent_win==Some(false)||all_opponent_lose&&win==Some(true);all_lose&=win==Some(false);all_opponent_lose&=opponent_win==Some(false);if!all_lose&&!all_opponent_lose&&!can_win{break;}}if all_lose||can_win{return ControlFlow::Break(can_win);}}ControlFlow::Continue((0,None))},|(s,p),(i,moves)|{while*i(left:&mut FL,right:&mut FR,state:&S,player:Player)->impl Iterator>+usewhere FL:FnMut(&S)->IL,FR:FnMut(&S)->IR,IL:IntoIterator>,IR:IntoIterator>{let(left,right)=match player{Player::Left=>(Some(left(state).into_iter()),None),Player::Right=>(None,Some(right(state).into_iter())),};left.into_iter().flatten().chain(right.into_iter().flatten())}}mod scoring{use super::{ControlFlow,EvaluatedMove,GameAnalysis,GameAnalyzer,Hash,HashMap,HashSet,Neighbor,memoized_game};#[derive(Debug,Clone,Copy,PartialEq,Eq)]pub enum Turn{Same,Other}#[derive(Debug,Clone,Copy,PartialEq,Eq)]pub struct ScoreMove{pub next:Neighbor,pub reward:i64,pub turn:Turn}pub struct Scoring{moves:F,terminal:T,scores:HashMap}impl GameAnalyzer{#[doc=" Scores and rewards are measured for the player whose turn it is."]#[doc=" `terminal` returns `Some(score)` at terminal states and `None` elsewhere."]pub fn scoring(self,moves:F,terminal:T)->GameAnalyzer>where F:FnMut(&S)->I,I:IntoIterator>,T:FnMut(&S)->Option{GameAnalyzer{game:Scoring{moves,terminal,scores:HashMap::new()}}}}implGameAnalyzer>{pub fn clear_cache(&mut self){self.game.scores.clear();}}implGameAnalyzer>where S:Clone+Eq+Hash,F:FnMut(&S)->I,I:IntoIterator>,T:FnMut(&S)->Option{pub fn score(&mut self)->GameAnalysis<'_,Scoring,S,i64>{GameAnalysis::new(&mut self.game,|g,state|{memoized_game(state,&mut g.scores,&mut HashSet::new(),&mut|s|{if let Some(value)=(g.terminal)(s){return ControlFlow::Break(value);}let moves=(g.moves)(s).into_iter().map(|m|(m.next.to,(m.reward,m.turn)));ControlFlow::Continue((moves,None))},&mut|_,moves|moves.next(),&mut|best:&mut Option,(reward,turn),child|{let value=match turn{Turn::Same=>reward+child,Turn::Other=>reward-child,};*best=Some(best.map_or(value,|b|b.max(value)));ControlFlow::Continue(())},&mut|_,best|best.expect("nonterminal scoring state has no moves"))})}}implGameAnalysis<'_,Scoring,S,i64>where F:FnMut(&S)->I,I:IntoIterator>,T:FnMut(&S)->Option{#[doc=" Values include the reward and are measured for the current player."]pub fn moves(&mut self,state:&S)->Vec>{self.evaluated_moves(state).collect()}pub fn best_moves(&mut self,state:&S)->Vec>{let mut result=Vec::new();let mut best=None;for m in self.evaluated_moves(state){if best.is_none_or(|best|m.value>best){result.clear();best=Some(m.value);}if best==Some(m.value){result.push(m.next);}}result}fn evaluated_moves(&mut self,state:&S)->impl Iterator>{let terminal=(self.game.terminal)(state).is_some();let mut moves=(!terminal).then(| |(self.game.moves)(state).into_iter()).into_iter().flatten().peekable();assert!(terminal||moves.peek().is_some(),"nonterminal scoring state has no moves");moves.map(|m|{let child=self.eval(&m.next.to);let value=match m.turn{Turn::Same=>m.reward+child,Turn::Other=>m.reward-child,};EvaluatedMove{next:m.next,value}})}}}mod value{use super::{Dyadic,PartisanOutcome,Player,game_mex};use std::{cmp::Ordering,collections::HashMap,fmt,hash::{DefaultHasher,Hash,Hasher},iter::Sum,ops::{Add,Neg,Sub},rc::Rc};#[doc=" A canonical finite normal-play game. Numbers use `Dyadic`."]#[doc=" `PartialOrd` is the game order: `None` means fuzzy, not a numeric approximation."]#[doc=""]#[doc=" ```"]#[doc=" use competitive::algorithm::GameValue;"]#[doc=" let zero = GameValue::from(0);"]#[doc=" let star = GameValue::nimber(1);"]#[doc=" let up = GameValue::from_options([zero.clone()], [star.clone()]);"]#[doc=" assert!(up > zero);"]#[doc=" assert_eq!(star.partial_cmp(&zero), None);"]#[doc=" assert_eq!(star.clone() + star, zero);"]#[doc=" ```"]#[derive(Clone)]pub struct GameValue(GameValueNode);#[derive(Clone)]enum GameValueNode{NumberUpNimber(Dyadic,i64,u64),Switches(Rc),Options(Dyadic,Rc<(Vec,Vec)>)}impl PartialEq for GameValueNode{fn eq(&self,rhs:&Self)->bool{match(self,rhs){(Self::NumberUpNimber(a,k,n),Self::NumberUpNimber(b,l,m))=>{a==b&&k==l&&n==m}(Self::Switches(a),Self::Switches(b))=>{Rc::ptr_eq(a,b)||a.number==b.number&&a.up==b.up&&a.nimber==b.nimber&&a.temperatures[a.start..]==b.temperatures[b.start..]}(Self::Options(q,a),Self::Options(r,b))=>q==r&&Rc::ptr_eq(a,b),_=>false,}}}impl Eq for GameValueNode{}impl Hash for GameValueNode{fn hash(&self,state:&mut H)where H:Hasher{match self{Self::NumberUpNimber(q,k,n)=>(q,k,n).hash(state),Self::Switches(v)=>(v.number,v.up,v.nimber,v.fingerprint).hash(state),Self::Options(q,v)=>{Rc::as_ptr(v).hash(state);if q.numerator()!=0{q.hash(state);}}}}}#[derive(Clone)]struct GameValueSwitches{number:Dyadic,up:i64,nimber:u64,temperatures:Rc>>,start:usize,fingerprint:u64}impl GameValue{pub fn nimber(value:u64)->Self{Self::number_up_nimber(0.into(),0,value)}#[doc=" Constructs `number + up * ↑ + *nimber` without expanding options."]pub fn number_up_nimber(number:Dyadic,up:i64,nimber:u64)->Self{Self(GameValueNode::NumberUpNimber(number,up,nimber))}pub fn as_number(&self)->Option>{match self.0{GameValueNode::NumberUpNimber(n,0,0)=>Some(n),_=>None,}}pub fn as_nimber(&self)->Option{match self.0{GameValueNode::NumberUpNimber(q,0,n)if q.numerator()==0=>Some(n),_=>None,}}#[doc=" Returns `(q, n)` when the value is `q + *n`."]pub fn as_number_nimber(&self)->Option<(Dyadic,u64)>{match self.0{GameValueNode::NumberUpNimber(q,0,n)=>Some((q,n)),_=>None,}}#[doc=" Returns `(q, k, n)` when the value is `q + k↑ + *n`."]pub fn as_number_up_nimber(&self)->Option<(Dyadic,i64,u64)>{match self.0{GameValueNode::NumberUpNimber(q,k,n)=>Some((q,k,n)),_=>None,}}#[doc=" Returns `(q, k, n, temperatures)` for `q + k↑ + *n + Σ{t|-t}`."]#[doc=" Temperatures are positive and strictly decreasing; the slice may be empty."]#[allow(clippy::type_complexity)]pub fn as_switch_sum(&self)->Option<(Dyadic,i64,u64,&[Dyadic])>{match&self.0{GameValueNode::NumberUpNimber(q,k,n)=>Some((*q,*k,*n,&[])),GameValueNode::Switches(value)=>Some((value.number,value.up,value.nimber,&value.temperatures[value.start..])),_=>None,}}pub fn outcome(&self)->PartisanOutcome{match self.partial_cmp(&Self::from(0)){Some(Ordering::Greater)=>PartisanOutcome::Left,Some(Ordering::Less)=>PartisanOutcome::Right,Some(Ordering::Equal)=>PartisanOutcome::Previous,None=>PartisanOutcome::Next,}}#[doc=" Whether the selected starting player can force a win."]pub fn wins(&self,player:Player)->bool{match player{Player::Left=>!self.leq(&Self::from(0)),Player::Right=>!Self::from(0).leq(self),}}#[doc=" Removes dominated and reversible options."]pub fn from_options(left:impl IntoIterator,right:impl IntoIterator)->Self{Self::from_options_memoized(left.into_iter().collect(),right.into_iter().collect(),&mut HashMap::new())}pub fn options(&self,player:Player)->impl Iterator+'_{let mut offset=Dyadic::from(0);let(single,nimbers,general)=match&self.0{GameValueNode::NumberUpNimber(n,0,0)=>{let option=if n.exponent()==0{match player{Player::Left if n.numerator()>0=>Some(Dyadic::from(n.numerator()-1)),Player::Right if n.numerator()<0=>Some(Dyadic::from(n.numerator()+1)),_=>None,}}else{let numerator=(n.numerator()>>1)+i64::from(player==Player::Right);Some(Dyadic::new(numerator,n.exponent()-1))};(option.map(Self::from),None,&[][..])}GameValueNode::NumberUpNimber(q,0,n)=>(None,Some((*q,*n)),&[][..]),GameValueNode::NumberUpNimber(q,k,1)if matches!((*k,player),(1,Player::Left)|(-1,Player::Right))=>{(None,Some((*q,2)),&[][..])}GameValueNode::NumberUpNimber(q,k,n)=>{let sign=if*k>0{1}else{-1};let moves_to_number=(*k>0)==(player==Player::Left);let option=if moves_to_number{Self::from(*q)}else{Self::number_up_nimber(*q,k-sign,n^1)};(Some(option),None,&[][..])}GameValueNode::Switches(value)=>{let temperatures=&value.temperatures[value.start..];let t=if player==Player::Left{temperatures[0]}else{-temperatures[0]};let option=if temperatures.len()==1{Self::number_up_nimber(value.number+t,value.up,value.nimber)}else{Self(GameValueNode::Switches(Rc::new(GameValueSwitches{number:value.number+t,start:value.start+1,fingerprint:value.fingerprint^Self::temperature_hash(temperatures[0]),..(**value).clone()})))};(Some(option),None,&[][..])}GameValueNode::Options(q,options)=>{offset=*q;let(left,right)=&**options;let moves=if player==Player::Left{left}else{right};(None,None,moves.as_slice())}};single.into_iter().chain(nimbers.into_iter().flat_map(|(q,n)|(0..n).map(move|m|Self::number_up_nimber(q,0,m)))).chain(general.iter().map(move|g|g.translated(offset)))}fn from_options_memoized(mut left:Vec,mut right:Vec,cache:&mut HashMap>)->Self{loop{if left.iter().chain(&right).all(|g|g.as_number().is_some()){let l=left.iter().filter_map(Self::as_number).max();let r=right.iter().filter_map(Self::as_number).min();if let Some(n)=Dyadic::simplest_between(l,r){return n.into();}let(l,r)=(l.unwrap(),r.unwrap());if l==r{return Self::number_up_nimber(l,0,1);}let(sum,difference)=(l+r,l-r);let temperature=Dyadic::new(difference.numerator(),difference.exponent()+1);return Self::from_switches(Dyadic::new(sum.numerator(),sum.exponent()+1),0,0,vec![temperature],Self::temperature_hash(temperature));}if!right.is_empty()&&let Some((number,_))=left.first().and_then(Self::as_number_nimber){let nimber=|g:&Self|{g.as_number_nimber().filter(|&(q,_)|q==number).map(|(_,n)|n)};let l:Option>=left.iter().map(nimber).collect();let r:Option>=right.iter().map(nimber).collect();if let(Some(l),Some(r))=(l,r){let value=game_mex(l);if value==game_mex(r){return Self::number_up_nimber(number,0,value);}}}for(moves,replies,sign)in[(&left,&right,1),(&right,&left,-1)]{if replies.len()!=1{continue;}if let Some((q,k,n))=replies[0].as_number_up_nimber(){if moves.len()==1&&moves[0].as_number()==Some(q)&&(k==0||k.signum()==sign){return Self::number_up_nimber(q,k+sign,n^1);}if k==0&&n==0&&moves.len()==2{let a=moves[0].as_number_nimber();let b=moves[1].as_number_nimber();if(a==Some((q,0))&&b==Some((q,1)))||(a==Some((q,1))&&b==Some((q,0))){return Self::number_up_nimber(q,sign,1);}}}}if left.len()==1&&right.len()==1&&let(Some((a,k,n,ts)),Some((b,l,m,us)))=(left[0].as_switch_sum(),right[0].as_switch_sum())&&k==l&&n==m&&ts==us&&a>b{let(sum,difference)=(a+b,a-b);let temperature=Dyadic::new(difference.numerator(),difference.exponent()+1);if ts.first().is_none_or(|&t|temperature>t){return Self::from_switches(Dyadic::new(sum.numerator(),sum.exponent()+1),k,n,std::iter::once(temperature).chain(ts.iter().copied()).collect(),Self::temperature_hash(temperature)^left[0].switch_hash());}}let count=left.len()+right.len();Self::remove_dominated(&mut left,Player::Left,cache);Self::remove_dominated(&mut right,Player::Right,cache);if count!=left.len()+right.len(){continue;}let options=Rc::new((left,right));let game=Self(GameValueNode::Options(0.into(),options.clone()));let mut reversible=Vec::new();for player in[Player::Left,Player::Right]{let moves=match player{Player::Left=>&options.0,Player::Right=>&options.1,};for(i,g)in moves.iter().enumerate(){if let Some((q,n))=g.as_number_nimber()&&n>1{let number=Self::from(q);let(lower,upper)=match player{Player::Left=>(&game,&number),Player::Right=>(&number,&game),};if lower.leq_memoized(upper,cache)&&!upper.leq_memoized(lower,cache){continue;}}if let Some(reply)=g.options(player.opponent()).find(|r|match player{Player::Left=>r.leq_memoized(&game,cache),Player::Right=>game.leq_memoized(r,cache),}){reversible.push((player,i,reply));}}}if reversible.is_empty(){return game;}drop(game);(left,right)=Rc::unwrap_or_clone(options);for(player,i,reply)in reversible.into_iter().rev(){let moves=if player==Player::Left{&mut left}else{&mut right};moves.remove(i);moves.extend(reply.options(player));}}}fn leq(&self,rhs:&Self)->bool{self.leq_memoized(rhs,&mut HashMap::new())}fn leq_memoized(&self,rhs:&Self,cache:&mut HashMap>)->bool{if let(Some((a,k,n,ts)),Some((b,l,m,us)))=(self.as_switch_sum(),rhs.as_switch_sum()){let mut number=a;let mut odd=false;for t in Self::switch_difference(ts,us){if!odd&&number>=b||odd&&number<=b{return odd;}number=if odd{number-t}else{number+t};odd=!odd;}return match number.cmp(&b){Ordering::Less=>true,Ordering::Greater=>false,Ordering::Equal=>{let up=if odd{l-k}else{k-l};let nimber=n^m;let wins=up>0||up==0&&nimber!=0||up==-1&&nimber==1;wins==odd}};}if let(GameValueNode::Options(a,g),GameValueNode::Options(b,h))=(&self.0,&rhs.0)&&Rc::ptr_eq(g,h){return a<=b;}let offset=-self.number_offset();let left=self.translated(offset).0;let right=rhs.translated(offset).0;if let Some(&value)=cache.get(&left).and_then(|row|row.get(&right)){return value;}let mut sides=[(self,rhs,Player::Left),(rhs,self,Player::Right)];if self.as_switch_sum().is_some(){sides.swap(0,1);}let value=sides.into_iter().all(|(game,other,player)|{let mut preferred=|a:&Self,b:&Self|match player{Player::Left=>b.leq_memoized(a,cache),Player::Right=>a.leq_memoized(b,cache),};if let GameValueNode::NumberUpNimber(q,0,n)=game.0&&n!=0{let number=Self::from(q);!preferred(&number,other)&&(preferred(other,&number)||!game.options(player).skip(1).any(|g|preferred(&g,other)))}else{!game.options(player).any(|g|preferred(&g,other))}});cache.entry(left).or_default().insert(right,value);value}fn negated(&self,cache:&mut HashMap)->Self{match&self.0{GameValueNode::NumberUpNimber(q,k,n)=>Self::number_up_nimber(-*q,-*k,*n),GameValueNode::Switches(value)=>{Self(GameValueNode::Switches(Rc::new(GameValueSwitches{number:-value.number,up:-value.up,..(**value).clone()})))}GameValueNode::Options(q,options)=>{let key=Rc::as_ptr(options)as usize;if let Some(value)=cache.get(&key){return value.translated(-*q);}let(left,right)=&**options;let value=Self(GameValueNode::Options(0.into(),Rc::new((right.iter().map(|g|g.negated(cache)).collect(),left.iter().map(|g|g.negated(cache)).collect()))));cache.insert(key,value.clone());value.translated(-*q)}}}fn sum(&self,rhs:&Self,cache:&mut HashMap<(GameValueNode,GameValueNode),Self>,comparisons:&mut HashMap>)->Self{if let(GameValueNode::NumberUpNimber(a,k,n),GameValueNode::NumberUpNimber(b,l,m))=(&self.0,&rhs.0){return Self::number_up_nimber(*a+*b,k+l,n^m);}if let Some(q)=self.as_number(){return rhs.translated(q);}if let Some(q)=rhs.as_number(){return self.translated(q);}if let(Some((a,k,n,ts)),Some((b,l,m,us)))=(self.as_switch_sum(),rhs.as_switch_sum()){return Self::from_switches(a+b,k+l,n^m,Self::switch_difference(ts,us).collect(),self.switch_hash()^rhs.switch_hash());}let(a,b)=(self.number_offset(),rhs.number_offset());if a.numerator()!=0||b.numerator()!=0{return self.translated(-a).sum(&rhs.translated(-b),cache,comparisons).translated(a+b);}let mut key=(self.0 .clone(),rhs.0 .clone());let swap=match(&key.0,&key.1){(GameValueNode::Options(_,a),GameValueNode::Options(_,b))=>{Rc::as_ptr(a)>Rc::as_ptr(b)}(GameValueNode::Options(..),_)=>true,_=>false,};if swap{std::mem::swap(&mut key.0,&mut key.1);}if let Some(value)=cache.get(&key){return value.clone();}let mut options=|player|{let mut moves=Vec::new();for g in self.options(player){moves.push(g.sum(rhs,cache,comparisons));}for g in rhs.options(player){moves.push(self.sum(&g,cache,comparisons));}moves};let value=Self::from_options_memoized(options(Player::Left),options(Player::Right),comparisons);cache.insert(key,value.clone());value}fn number_offset(&self)->Dyadic{match&self.0{GameValueNode::NumberUpNimber(q,..)|GameValueNode::Options(q,_)=>*q,GameValueNode::Switches(v)=>v.number,}}fn translated(&self,number:Dyadic)->Self{if number.numerator()==0{return self.clone();}match&self.0{GameValueNode::NumberUpNimber(q,k,n)=>Self::number_up_nimber(*q+number,*k,*n),GameValueNode::Switches(v)=>{Self(GameValueNode::Switches(Rc::new(GameValueSwitches{number:v.number+number,..(**v).clone()})))}GameValueNode::Options(q,options)=>{Self(GameValueNode::Options(*q+number,options.clone()))}}}fn temperature_hash(t:Dyadic)->u64{let mut hasher=DefaultHasher::new();t.hash(&mut hasher);hasher.finish()}fn switch_hash(&self)->u64{match&self.0{GameValueNode::NumberUpNimber(..)=>0,GameValueNode::Switches(v)=>v.fingerprint,GameValueNode::Options(..)=>unreachable!(),}}fn from_switches(q:Dyadic,k:i64,n:u64,temperatures:Vec>,fingerprint:u64)->Self{if temperatures.is_empty(){Self::number_up_nimber(q,k,n)}else{Self(GameValueNode::Switches(Rc::new(GameValueSwitches{number:q,up:k,nimber:n,fingerprint,temperatures:Rc::new(temperatures),start:0})))}}fn switch_difference<'a>(mut left:&'a[Dyadic],mut right:&'a[Dyadic])->impl Iterator>+'a{std::iter::from_fn(move| |{while let(Some(a),Some(b))=(left.first(),right.first()){if a!=b{break;}left=&left[1..];right=&right[1..];}if left.first(),player:Player,cache:&mut HashMap>){let mut retained=vec![true;options.len()];for i in 0..options.len(){let dominated=(0..options.len()).any(|j|{i!=j&&retained[j]&&match player{Player::Left=>options[i].leq_memoized(&options[j],cache),Player::Right=>options[j].leq_memoized(&options[i],cache),}});retained[i]=!dominated;}let mut retained=retained.into_iter();options.retain(|_|retained.next().unwrap());}}impl Fromfor GameValue{fn from(value:i64)->Self{Dyadic::from(value).into()}}impl From>for GameValue{fn from(value:Dyadic)->Self{Self::number_up_nimber(value,0,0)}}impl Neg for GameValue{type Output=Self;fn neg(self)->Self{self.negated(&mut HashMap::new())}}impl Add for GameValue{type Output=Self;fn add(self,rhs:Self)->Self{self.sum(&rhs,&mut HashMap::new(),&mut HashMap::new())}}impl Sub for GameValue{type Output=Self;fn sub(self,rhs:Self)->Self{if self.0==rhs.0{Self::from(0)}else{self+-rhs}}}impl Sum for GameValue{fn sum(iter:I)->Self where I:Iterator{let(mut number,mut up,mut nimber)=(Dyadic::from(0),0,0);let mut temperatures=Vec::new();let mut fingerprint=0;let mut general=Self::from(0);for value in iter{if let Some((q,k,n,ts))=value.as_switch_sum(){number=number+q;up+=k;nimber^=n;temperatures.extend_from_slice(ts);fingerprint^=value.switch_hash();}else{general=general+value;}}temperatures.sort_unstable_by(|a,b|b.cmp(a));let mut retained=0;for i in 0..temperatures.len(){if retained>0&&temperatures[retained-1]==temperatures[i]{retained-=1;}else{temperatures[retained]=temperatures[i];retained+=1;}}temperatures.truncate(retained);let value=Self::from_switches(number,up,nimber,temperatures,fingerprint);if general.as_nimber()==Some(0){value}else{value+general}}}impl PartialEq for GameValue{fn eq(&self,rhs:&Self)->bool{match(&self.0,&rhs.0){(GameValueNode::NumberUpNimber(a,k,n),GameValueNode::NumberUpNimber(b,l,m))=>{return a==b&&k==l&&n==m;}(GameValueNode::Switches(_),GameValueNode::Switches(_))=>{return self.0==rhs.0;}_=>{}}let mut cache=HashMap::new();self.leq_memoized(rhs,&mut cache)&&rhs.leq_memoized(self,&mut cache)}}impl Eq for GameValue{}impl PartialOrd for GameValue{fn partial_cmp(&self,rhs:&Self)->Option{let mut cache=HashMap::new();match(self.leq_memoized(rhs,&mut cache),rhs.leq_memoized(self,&mut cache)){(true,true)=>Some(Ordering::Equal),(true,false)=>Some(Ordering::Less),(false,true)=>Some(Ordering::Greater),(false,false)=>None,}}}impl fmt::Display for GameValue{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{if let Some((q,k,n,temperatures))=self.as_switch_sum(){let mut separator="";if q.numerator()!=0||k==0&&n==0&&temperatures.is_empty(){write!(f,"{q}")?;separator="+";}if k!=0{f.write_str(separator)?;if k.unsigned_abs()!=1{write!(f,"{}",k.unsigned_abs())?;}f.write_str(if k>0{"↑"}else{"↓"})?;separator="+";}if n!=0{write!(f,"{separator}*")?;if n!=1{write!(f,"{n}")?;}separator="+";}for t in temperatures{write!(f,"{separator}{{{t}|{}}}",-*t)?;separator="+";}return Ok(());}f.write_str("{")?;for(separator,player)in[("",Player::Left),("|",Player::Right)]{f.write_str(separator)?;for(i,g)in self.options(player).enumerate(){if i>0{f.write_str(",")?;}write!(f,"{g}")?;}}f.write_str("}")}}impl fmt::Debug for GameValue{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{fmt::Display::fmt(self,f)}}}#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]pub enum Player{Left,Right}impl Player{pub fn opponent(self)->Self{match self{Self::Left=>Self::Right,Self::Right=>Self::Left,}}}#[doc=" Outcome for the player whose turn it is. A draw is an infinite play."]#[derive(Debug,Clone,Copy,PartialEq,Eq)]pub enum GameOutcome{Win,Draw,Lose}impl GameOutcome{fn from_win(win:bool)->Self{if win{Self::Win}else{Self::Lose}}}#[derive(Debug,Clone,Copy,PartialEq,Eq)]pub enum PartisanOutcome{Next,Previous,Left,Right}#[derive(Debug,Clone,PartialEq,Eq)]pub struct GameMismatch{pub state:S,pub expected:V,pub actual:V}#[derive(Debug,Clone,PartialEq,Eq)]pub struct EvaluatedMove{pub next:Neighbor,pub value:V}#[doc=" Owns a fixed game definition and reusable analysis caches."]#[doc=" Move generators may collect statistics, but must keep the rules unchanged."]#[doc=" Closure-based games must be finite and acyclic; detected cycles panic."]#[doc=" Outcome queries stop exploring a position once a winning move is found."]#[doc=" Use `impartial_graph` for Win/Draw/Lose analysis of cyclic graphs."]#[doc=""]#[doc=" ```"]#[doc=" use competitive::algorithm::{GameAnalyzer, GameOutcome};"]#[doc=" let mut nim = GameAnalyzer::new().impartial(|&n: &usize| 0..n);"]#[doc=" assert_eq!(nim.grundy().eval(&3), 3);"]#[doc=" assert_eq!(nim.sum().grundy().eval(&[3, 3]), 0);"]#[doc=" assert_eq!(nim.misere().outcome().eval(&1), GameOutcome::Lose);"]#[doc=" assert_eq!(nim.outcome().eval(&1), GameOutcome::Win);"]#[doc=" assert_eq!(nim.grundy().verify(0..10, |&n| n as u64), None);"]#[doc=" ```"]#[derive(Default)]pub struct GameAnalyzer{game:G}impl GameAnalyzer{pub fn new()->Self{Self::default()}}pub struct GameAnalysis<'a,G,S,V,const MISERE:bool=false,F=fn(&mut G,&S)->V>where S:?Sized{game:&'a mut G,evaluate:F,marker:PhantomDataV>}impl<'a,G,S,V,const MISERE:bool,F>GameAnalysis<'a,G,S,V,MISERE,F>where S:?Sized,F:FnMut(&mut G,&S)->V{pub fn eval(&mut self,state:&S)->V{(self.evaluate)(self.game,state)}#[doc=" Keeps the input items, their order and duplicates; dependency states are omitted."]pub fn table(&mut self,states:impl IntoIterator)->Vec<(T,V)>where T:Borrow{states.into_iter().map(|state|{let value=self.eval(state.borrow());(state,value)}).collect()}#[doc=" Returns the first mismatch in input order, or `None` if the range agrees."]pub fn verify(&mut self,states:impl IntoIterator,mut expected:impl FnMut(&S)->V)->Option>where T:Borrow,V:PartialEq{for state in states{let expected=expected(state.borrow());let actual=self.eval(state.borrow());if actual!=expected{return Some(GameMismatch{state,expected,actual});}}None}fn new(game:&'a mut G,evaluate:F)->Self{Self{game,evaluate,marker:PhantomData}}}pub struct Misere<'a,G>{game:&'a mut G}pub struct GameSum<'a,G,const MISERE:bool=false>{game:&'a mut G}impl<'a,G>Misere<'a,G>{pub fn sum(self)->GameSum<'a,G,true>{GameSum{game:self.game}}}impl<'a,G>GameSum<'a,G>{pub fn misere(self)->GameSum<'a,G,true>{GameSum{game:self.game}}}fn game_mex(mut values:Vec)->u64{for i in 0..values.len(){while values[i](mut state:Vec,ids:&mut HashMap)->Vecwhere S:Clone+Eq+Hash{for s in&state{if!ids.contains_key(s){ids.insert(s.clone(),ids.len());}}state.sort_unstable_by_key(|s|ids[s]);state}fn memoized_game(state:&S,cache:&mut HashMap,active:&mut HashSet,expand:&mut impl FnMut(&S)->ControlFlow,advance:&mut impl FnMut(&S,&mut I)->Option<(S,T)>,feed:&mut impl FnMut(&mut A,T,V)->ControlFlow,finish:&mut impl FnMut(&S,A)->V)->V where S:Clone+Eq+Hash,V:Clone{if let Some(value)=cache.get(state){return value.clone();}assert!(active.insert(state.clone()),"cycle in a finite game");let value=match expand(state){ControlFlow::Break(value)=>value,ControlFlow::Continue((mut moves,mut accumulator))=>'search:{while let Some((next,edge))=advance(state,&mut moves){let child=memoized_game(&next,cache,active,expand,advance,feed,finish);if let ControlFlow::Break(value)=feed(&mut accumulator,edge,child){break 'search value;}}finish(state,accumulator)}};active.remove(state);cache.insert(state.clone(),value.clone());value}fn memoized_wins(state:&S,cache:&mut HashMap,mut expand:impl FnMut(&S)->ControlFlow,mut advance:impl FnMut(&S,&mut I)->Option,misere:bool)->bool where S:Clone+Eq+Hash{memoized_game(state,cache,&mut HashSet::new(),&mut|s|expand(s).map_continue(|moves|(moves,false)),&mut|s,moves|advance(s,moves).map(|next|(next,())),&mut|has_moves,(),child|{*has_moves=true;if child{ControlFlow::Continue(())}else{ControlFlow::Break(true)}},&mut|_,has_moves|!has_moves&&misere)}} // codesnip-guard: ClosureGraph #[cfg_attr(any(),rustfmt::skip)]pub use self::closure::{ClosureGraph,UsizeGraph};#[cfg_attr(any(),rustfmt::skip)]mod closure{use super::{DirectedGraph,Graph,Neighbor,VertexMap};use std::{collections::HashMap,hash::Hash,iter::Map,marker::PhantomData,ops::Range};pub struct UsizeGraph{vsize:usize,adj:Fa}implUsizeGraph{pub fn new(vsize:usize,adj:Fa)->Self{Self{vsize,adj}}}implGraph for UsizeGraphwhere I:Iterator,Fa:Fn(usize)->I{type Vertex=usize;type Label=T;type Vertices<'g>=Rangewhere Fa:'g;type Neighbors<'g>=MapNeighbor>where Fa:'g;#[inline]fn vsize(&self)->usize{self.vsize}#[inline]fn vertices(&self)->Self::Vertices<'_>{0..self.vsize}#[inline]fn neighbors(&self,vertex:Self::Vertex)->Self::Neighbors<'_>{(self.adj)(vertex).map(Into::into)}}implDirectedGraph for UsizeGraphwhere UsizeGraph:Graph{}implVertexMapfor UsizeGraphwhere Self:Graph{type Vmap=Vec;#[inline]fn construct_vmap(&self,f:F)->Self::Vmap where F:FnMut()->T{let mut v=Vec::with_capacity(self.vsize);v.resize_with(self.vsize,f);v}#[inline]fn vmap_get<'a>(&self,map:&'a Self::Vmap,vid:Self::Vertex)->&'a T{&map[vid]}#[inline]fn vmap_get_mut<'a>(&self,map:&'a mut Self::Vmap,vid:Self::Vertex)->&'a mut T{&mut map[vid]}}pub struct ClosureGraph{vs:Fv,adj:Fa,_marker:PhantomDataV>}implClosureGraph{pub fn new(vs:Fv,adj:Fa)->Self{Self{vs,adj,_marker:PhantomData}}}implGraph for ClosureGraphwhere V:Eq+Copy,Iv:Iterator,Fv:Fn()->Iv,Ia:Iterator,Fa:Fn(V)->Ia{type Vertex=V;type Label=T;type Vertices<'g>=Iv where V:'g,Fv:'g,Fa:'g;type Neighbors<'g>=MapNeighbor>where V:'g,Fv:'g,Fa:'g;#[inline]fn vsize(&self)->usize{(self.vs)().count()}#[inline]fn vertices(&self)->Self::Vertices<'_>{(self.vs)()}#[inline]fn neighbors(&self,vertex:Self::Vertex)->Self::Neighbors<'_>{(self.adj)(vertex).map(Into::into)}}implDirectedGraph for ClosureGraphwhere Self:Graph{}implVertexMapfor ClosureGraphwhere V:Eq+Copy+Hash,T:Clone,Self:Graph{type Vmap=(HashMap,T);#[inline]fn construct_vmap(&self,mut f:F)->Self::Vmap where F:FnMut()->T{(HashMap::new(),f())}#[inline]fn vmap_get<'a>(&self,(map,val):&'a Self::Vmap,vid:Self::Vertex)->&'a T{map.get(&vid).unwrap_or(val)}#[inline]fn vmap_get_mut<'a>(&self,(map,val):&'a mut Self::Vmap,vid:Self::Vertex)->&'a mut T{map.entry(vid).or_insert_with(| |val.clone())}}} // codesnip-guard: Dyadic #[cfg_attr(any(),rustfmt::skip)]pub use self::dyadic::Dyadic;#[cfg_attr(any(),rustfmt::skip)]mod dyadic{use super::{One,Signed,Zero};use std::{cmp::Ordering,fmt,ops::{Add,Neg,Sub}};#[doc=" A reduced `numerator / 2^exponent`."]#[derive(Clone,Copy,PartialEq,Eq,Hash)]pub struct Dyadic{numerator:T,exponent:u32}implDyadic{pub fn numerator(self)->T{self.numerator}pub fn exponent(self)->u32{self.exponent}}implDyadicwhere T:Signed{pub fn new(mut numerator:T,mut exponent:u32)->Self{let two=T::one()+T::one();if numerator.is_zero(){exponent=0;}while exponent>0&&(numerator%two).is_zero(){numerator/=two;exponent-=1;}Self{numerator,exponent}}#[doc=" The simplest number strictly between the bounds; absent bounds are unbounded."]#[doc=" Returns `None` for an empty interval."]pub fn simplest_between(left:Option,right:Option)->Option{if left.zip(right).is_some_and(|(l,r)|l>=r){return None;}if left.is_none_or(|l|l.numeratorT::zero()){return Some(Self::zero());}let negative=right.is_some_and(|r|r.numerator<=T::zero());let(lower,upper)=if negative{(-right.unwrap(),left.map(Neg::neg))}else{(left.unwrap(),right)};let two=T::one()+T::one();for exponent in 0..{let floor=if exponentFromfor Dyadicwhere T:Signed{fn from(numerator:T)->Self{Self::new(numerator,0)}}implZero for Dyadicwhere T:Signed{fn zero()->Self{T::zero().into()}}implOne for Dyadicwhere T:Signed{fn one()->Self{T::one().into()}}implDefault for Dyadicwhere T:Signed{fn default()->Self{Self::zero()}}implNeg for Dyadicwhere T:Signed{type Output=Self;fn neg(self)->Self{Self{numerator:-self.numerator,exponent:self.exponent}}}implAdd for Dyadicwhere T:Signed{type Output=Self;fn add(self,rhs:Self)->Self{let exponent=self.exponent.max(rhs.exponent);let two=T::one()+T::one();let left=self.numerator*two.pow(exponent-self.exponent);let right=rhs.numerator*two.pow(exponent-rhs.exponent);Self::new(left+right,exponent)}}implSub for Dyadicwhere T:Signed{type Output=Self;fn sub(self,rhs:Self)->Self{self+-rhs}}implOrd for Dyadicwhere T:Signed{fn cmp(&self,rhs:&Self)->Ordering{let exponent=self.exponent.max(rhs.exponent);let two=T::one()+T::one();let left=self.numerator*two.pow(exponent-self.exponent);let right=rhs.numerator*two.pow(exponent-rhs.exponent);left.cmp(&right)}}implPartialOrd for Dyadicwhere T:Signed{fn partial_cmp(&self,rhs:&Self)->Option{Some(self.cmp(rhs))}}implfmt::Display for Dyadicwhere T:Signed{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{if self.exponent==0{write!(f,"{}",self.numerator)}else{let two=T::one()+T::one();write!(f,"{}/{}",self.numerator,two.pow(self.exponent))}}}implfmt::Debug for Dyadicwhere T:Signed{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{fmt::Display::fmt(self,f)}}} // codesnip-guard: Graph #[cfg_attr(any(),rustfmt::skip)]pub use self::graph_base::*;#[cfg_attr(any(),rustfmt::skip)]mod graph_base{#[doc=" A neighboring vertex and the label of the arc used to reach it."]#[derive(Debug,Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Hash)]pub struct Neighbor{pub to:V,pub label:L}implNeighbor{#[inline]pub fn new(to:V,label:L)->Self{Self{to,label}}}implFrom<(V,L)>for Neighbor{#[inline]fn from((to,label):(V,L))->Self{Self::new(to,label)}}#[doc=" A finite graph whose outgoing arcs can be iterated without allocation."]pub trait Graph{type Vertex:Copy+Eq;type Label;type Vertices<'g>:Iteratorwhere Self:'g;type Neighbors<'g>:Iterator>where Self:'g;fn vsize(&self)->usize;fn vertices(&self)->Self::Vertices<'_>;fn neighbors(&self,vertex:Self::Vertex)->Self::Neighbors<'_>;}#[doc=" A graph whose adjacency relation represents directed arcs."]pub trait DirectedGraph:Graph{}pub trait VertexMap:Graph{type Vmap;fn construct_vmap(&self,f:F)->Self::Vmap where F:FnMut()->T;fn vmap_get<'a>(&self,map:&'a Self::Vmap,vertex:Self::Vertex)->&'a T;fn vmap_get_mut<'a>(&self,map:&'a mut Self::Vmap,vertex:Self::Vertex)->&'a mut T;#[inline]fn vmap_set(&self,map:&mut Self::Vmap,vertex:Self::Vertex,value:T){*self.vmap_get_mut(map,vertex)=value;}}pub trait EdgeMap:Graph{type Emap;fn construct_emap(&self,f:F)->Self::Emap where F:FnMut()->T;fn emap_get<'a>(&self,map:&'a Self::Emap,eid:Self::Label)->&'a T;fn emap_get_mut<'a>(&self,map:&'a mut Self::Emap,eid:Self::Label)->&'a mut T;#[inline]fn emap_set(&self,map:&mut Self::Emap,eid:Self::Label,value:T){*self.emap_get_mut(map,eid)=value;}}} // codesnip-guard: array #[cfg_attr(any(),rustfmt::skip)]mod array{#[macro_export]macro_rules!array{[@inner$data:ident=[$init:expr;$len:expr]]=>{{use::std::mem::{ManuallyDrop,MaybeUninit};let mut$data:[MaybeUninit<_>;$len]=unsafe{MaybeUninit::uninit().assume_init()};$init;#[repr(C)]union __Transmuter{src:ManuallyDrop<[MaybeUninit;N]>,dst:ManuallyDrop<[T;N]>,}ManuallyDrop::into_inner(unsafe{__Transmuter{src:ManuallyDrop::new($data)}.dst})}};[||$e:expr;$len:expr]=>{$crate::array![@inner data=[data.iter_mut().for_each(|item|*item=MaybeUninit::new($e));$len]]};[|$i:pat_param|$e:expr;$len:expr]=>{$crate::array![@inner data=[data.iter_mut().enumerate().for_each(|($i,item)|*item=MaybeUninit::new($e));$len]]};[$e:expr;$len:expr]=>{{let e=$e;$crate::array![||Clone::clone(&e);$len]}};}} // codesnip-guard: bounded #[cfg_attr(any(),rustfmt::skip)]pub use self::bounded::Bounded;#[cfg_attr(any(),rustfmt::skip)]mod bounded{#[doc=" Trait for max/min bounds"]pub trait Bounded:Sized+PartialOrd{fn maximum()->Self;fn minimum()->Self;fn is_maximum(&self)->bool{self==&Self::maximum()}fn is_minimum(&self)->bool{self==&Self::minimum()}fn set_maximum(&mut self){*self=Self::maximum()}fn set_minimum(&mut self){*self=Self::minimum()}}macro_rules!impl_bounded_num{($($t:ident)*)=>{$(impl Bounded for$t{fn maximum()->Self{$t::MAX}fn minimum()->Self{$t::MIN}})*};}impl_bounded_num!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64);macro_rules!impl_bounded_tuple{(@impl$($T:ident)*)=>{impl<$($T:Bounded),*>Bounded for($($T,)*){fn maximum()->Self{($(<$T as Bounded>::maximum(),)*)}fn minimum()->Self{($(<$T as Bounded>::minimum(),)*)}}};(@inner$($T:ident)*,)=>{impl_bounded_tuple!(@impl$($T)*);};(@inner$($T:ident)*,$U:ident$($Rest:ident)*)=>{impl_bounded_tuple!(@impl$($T)*);impl_bounded_tuple!(@inner$($T)*$U,$($Rest)*);};($T:ident$($Rest:ident)*)=>{impl_bounded_tuple!(@inner$T,$($Rest)*);};}impl_bounded_tuple!(A B C D E F G H I J);impl Bounded for(){fn maximum()->Self{}fn minimum()->Self{}}impl Bounded for bool{fn maximum()->Self{true}fn minimum()->Self{false}}implBounded for Optionwhere T:Bounded{fn maximum()->Self{Some(::maximum())}fn minimum()->Self{None}}implBounded for std::cmp::Reversewhere T:Bounded{fn maximum()->Self{std::cmp::Reverse(::minimum())}fn minimum()->Self{std::cmp::Reverse(::maximum())}}} // codesnip-guard: integer #[cfg_attr(any(),rustfmt::skip)]pub use self::integer::{BinaryRepr,ExtendedGcd,IntBase,Saturating,Saturatingable,Signed,Unsigned,Wrapping,Wrappingable};#[cfg_attr(any(),rustfmt::skip)]mod integer{use super::{Bounded,One,Scan,ScanSource,Zero};use std::{convert::TryFrom,fmt::{self,Display},iter::{Product,Sum},ops::{Add,AddAssign,BitAnd,BitAndAssign,BitOr,BitOrAssign,BitXor,BitXorAssign,Div,DivAssign,Mul,MulAssign,Neg,Not,Rem,RemAssign,Shl,ShlAssign,Shr,ShrAssign,Sub,SubAssign},str::FromStr};#[doc=" Trait for basic primitive integer operations."]pub trait IntBase:Copy+Bounded+Zero+One+Eq+Ord+Default+FromStr+Display+Add+Sub+Mul+Div+Rem+AddAssign+SubAssign+MulAssign+DivAssign+RemAssign+Sum+Product{type Error;fn div_euclid(self,rhs:Self)->Self;fn rem_euclid(self,rhs:Self)->Self;fn pow(self,exp:u32)->Self;fn from_str_radix(src:&str,radix:u32)->Result;fn ilog(self,base:Self)->u32;fn ilog2(self)->u32;fn ilog10(self)->u32;fn isqrt(self)->Self;fn midpoint(self,rhs:Self)->Self;}macro_rules!impl_int_base{($($t:ty)*)=>{$(impl IntBase for$t{type Error=std::num::ParseIntError;fn div_euclid(self,rhs:Self)->Self{self.div_euclid(rhs)}fn rem_euclid(self,rhs:Self)->Self{self.rem_euclid(rhs)}fn pow(self,exp:u32)->Self{self.pow(exp)}fn from_str_radix(src:&str,radix:u32)->Result{Self::from_str_radix(src,radix)}fn ilog(self,base:Self)->u32{self.ilog(base)}fn ilog2(self)->u32{self.ilog2()}fn ilog10(self)->u32{self.ilog10()}fn isqrt(self)->Self{self.isqrt()}fn midpoint(self,rhs:Self)->Self{self.midpoint(rhs)}})*};}impl_int_base!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);#[doc=" extended_gcd(a,b): ax + by = g = gcd(a,b)"]pub struct ExtendedGcd{#[doc=" gcd"]pub g:T::Unsigned,pub x:T,pub y:T}#[doc=" Trait for unsigned integer operations."]pub trait Unsigned:IntBase{type Signed:Signed;fn signed(self)->Self::Signed;fn abs_diff(self,other:Self)->Self;fn div_ceil(self,rhs:Self)->Self;fn is_power_of_two(self)->bool;fn next_power_of_two(self)->Self;fn is_multiple_of(self,rhs:Self)->bool;fn next_multiple_of(self,rhs:Self)->Self;fn gcd(self,other:Self)->Self;fn lcm(self,other:Self)->Self{if self.is_zero()&&other.is_zero(){Self::zero()}else{self/self.gcd(other)*other}}fn mod_inv(self,modulo:Self)->Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");if modulo.is_one(){return Self::zero();}let(mut a,mut b)=(self,modulo);let(mut u,mut v)=(Self::one(),Self::zero());let mut negative=true;while!a.is_zero(){let k=b/a;v+=k*u;b-=k*a;std::mem::swap(&mut u,&mut v);std::mem::swap(&mut b,&mut a);negative=!negative;}debug_assert!(b.is_one(),"not coprime");if negative{v.mod_neg(modulo)}else{v}}fn mod_add(self,rhs:Self,modulo:Self)->Self;fn mod_sub(self,rhs:Self,modulo:Self)->Self;fn mod_mul(self,rhs:Self,modulo:Self)->Self;fn mod_neg(self,modulo:Self)->Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");debug_assert!(self{type Unsigned:Unsigned;fn unsigned(self)->Self::Unsigned;fn abs(self)->Self;fn abs_diff(self,other:Self)->Self::Unsigned;fn is_negative(self)->bool;fn is_positive(self)->bool;fn signum(self)->Self;fn extgcd(self,other:Self)->ExtendedGcd{let(mut a,mut b)=(self,other);let(mut u,mut v,mut x,mut y)=(Self::one(),Self::zero(),Self::zero(),Self::one());while!a.is_zero(){let k=b/a;x-=k*u;y-=k*v;b-=k*a;std::mem::swap(&mut x,&mut u);std::mem::swap(&mut y,&mut v);std::mem::swap(&mut b,&mut a);}if b.is_negative(){b=-b;x=-x;y=-y;}ExtendedGcd{g:b.unsigned(),x,y}}}macro_rules!impl_unsigned_signed{($([$($tt:tt)*])*)=>{$(impl_unsigned_signed!($($tt)*);)*};($unsigned:ident$signed:ident$upperty:ident)=>{impl_unsigned_signed!(@inner$unsigned$signed fn mod_mul(self,rhs:Self,modulo:Self)->Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");(self as$upperty*rhs as$upperty%modulo as$upperty)as$unsigned});};(u128 i128)=>{impl_unsigned_signed!(@inner u128 i128 fn mod_mul(self,rhs:Self,modulo:Self)->Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");const MASK64:u128=0xffff_ffff_ffff_ffff;let(au,ad)=(self>>64,self&MASK64);let(bu,bd)=(rhs>>64,rhs&MASK64);let p0=ad*bd%modulo;let p2=au*bu%modulo;let mut x=[p0 as u64,(p0>>64)as u64,p2 as u64,(p2>>64)as u64,];let p1=(au*bd%modulo).mod_add(ad*bu%modulo,modulo);let(p1_lo,p1_hi)=((p1&MASK64)as u64,(p1>>64)as u64);let(s1,c1)=x[1].overflowing_add(p1_lo);x[1]=s1 as u64;let(s2,c2)=x[2].overflowing_add(p1_hi+c1 as u64);x[2]=s2 as u64;let(s3,_)=x[3].overflowing_add(c2 as u64);x[3]=s3 as u64;rem_u256_by_u128(x,modulo)});};(@inner$unsigned:ident$signed:ident$mod_mul:item)=>{impl Unsigned for$unsigned{type Signed=$signed;fn signed(self)->Self::Signed{self as Self::Signed}fn abs_diff(self,other:Self)->Self{self.abs_diff(other)}fn div_ceil(self,rhs:Self)->Self{self.div_ceil(rhs)}fn is_power_of_two(self)->bool{self.is_power_of_two()}fn next_power_of_two(self)->Self{self.next_power_of_two()}fn is_multiple_of(self,rhs:Self)->bool{self.is_multiple_of(rhs)}fn next_multiple_of(self,rhs:Self)->Self{self.next_multiple_of(rhs)}fn gcd(self,other:Self)->Self{let(mut a,mut b)=(self,other);if a.is_zero()||b.is_zero(){return a|b;}let u=a.trailing_zeros();let v=b.trailing_zeros();a>>=u;b>>=v;let k=u.min(v);while a!=b{if a>=a.trailing_zeros();}a<Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");debug_assert!(self=modulo){s.wrapping_sub(modulo)}else{s}}fn mod_sub(self,rhs:Self,modulo:Self)->Self{debug_assert!(!modulo.is_zero(),"modulo must be non-zero");debug_assert!(selfSelf::Unsigned{self as Self::Unsigned}fn abs_diff(self,other:Self)->Self::Unsigned{self.abs_diff(other)}fn abs(self)->Self{self.abs()}fn is_negative(self)->bool{self.is_negative()}fn is_positive(self)->bool{self.is_positive()}fn signum(self)->Self{self.signum()}}};}impl_unsigned_signed!([u8 i8 u16][u16 i16 u32][u32 i32 u64][u64 i64 u128][u128 i128][usize isize u128]);fn rem_u256_by_u128(u:[u64;4],v:u128)->u128{#[inline(always)]fn sub_with_borrow_u64(lhs:u64,rhs:u64,borrow:bool)->(u64,bool){let(res,overflow)=lhs.overflowing_sub(rhs);if borrow{let(res,overflow_borrow)=res.overflowing_sub(1);(res,overflow|overflow_borrow)}else{(res,overflow)}}debug_assert!(v!=0);let v_hi=(v>>64)as u64;if v_hi==0{let d=v as u64 as u128;let mut rem:u128=0;for&w in u.iter().rev(){rem=(rem<<64|w as u128)%d;}return rem;}let v_lo=v as u64;let v_shift=v_hi.leading_zeros();let(vn1,vn0)=if v_shift==0{(v_hi,v_lo)}else{let hi=v_hi<>(64-v_shift);let lo=v_lo<>(64-v_shift);un[2]=u[2]<>(64-v_shift);un[3]=u[3]<>(64-v_shift);un[4]=u[3]>>(64-v_shift);}for j in(0..=2).rev(){let num=(un[j+2]as u128)<<64|un[j+1]as u128;let(mut qhat,mut rhat)={let d=vn1 as u128;let q=(num/d).min(u64::MAX as u128);(q as u64,(num-q*d).min(u64::MAX as u128)as u64)};while qhat as u128*vn0 as u128>(rhat as u128)<<64|un[j]as u128{qhat-=1;let t=rhat as u128+vn1 as u128;if t>=1u128<<64{break;}rhat=t as u64;}let p0=qhat as u128*vn0 as u128;let p1=qhat as u128*vn1 as u128;let(p0_hi,p0_lo)=((p0>>64)as u64,p0 as u64);let(p1_hi,p1_lo)=((p1>>64)as u64,p1 as u64);let(r0,borrow)=sub_with_borrow_u64(un[j],p0_lo,false);un[j]=r0;let(r1,borrow1)=sub_with_borrow_u64(un[j+1],p0_hi,borrow);let(r1,borrow2)=sub_with_borrow_u64(r1,p1_lo,false);let borrow=borrow1||borrow2;un[j+1]=r1;let(r2,borrow)=sub_with_borrow_u64(un[j+2],p1_hi,borrow);un[j+2]=r2;assert!(!borrow);}((un[1]as u128)<<64|un[0]as u128)>>v_hi.leading_zeros()}#[doc=" Trait for operations of integer in binary representation."]pub trait BinaryRepr:Sized+Not+BitAnd+BitOr+BitXor+Shl+Shr+BitAndAssign+BitOrAssign+BitXorAssign+ShlAssign+ShrAssign{fn count_ones(self)->Size;fn count_zeros(self)->Size;fn leading_ones(self)->Size;fn leading_zeros(self)->Size;fn reverse_bits(self)->Self;fn rotate_left(self,n:Size)->Self;fn rotate_right(self,n:Size)->Self;fn swap_bytes(self)->Self;fn trailing_ones(self)->Size;fn trailing_zeros(self)->Size;}macro_rules!impl_binary_repr{($($t:ty)*)=>{$(impl BinaryRepr for$t{fn count_ones(self)->u32{self.count_ones()}fn count_zeros(self)->u32{self.count_zeros()}fn leading_ones(self)->u32{self.leading_ones()}fn leading_zeros(self)->u32{self.leading_zeros()}fn reverse_bits(self)->Self{self.reverse_bits()}fn rotate_left(self,n:u32)->Self{self.rotate_left(n)}fn rotate_right(self,n:u32)->Self{self.rotate_right(n)}fn swap_bytes(self)->Self{self.swap_bytes()}fn trailing_ones(self)->u32{self.trailing_ones()}fn trailing_zeros(self)->u32{self.trailing_zeros()}})*};}impl_binary_repr!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);macro_rules!impl_binop{(impl<$T:ident>$Trait:ident$impl:ident for$t:ty)=>{impl<$T>$Trait for$t where$T:$Trait,{type Output=Self;fn$impl(self,rhs:Self)->Self::Output{Self($Trait::$impl(self.0,rhs.0))}}impl<$T>$Trait<$T>for$t where$T:$Trait,{type Output=Self;fn$impl(self,rhs:$T)->Self::Output{Self($Trait::$impl(self.0,rhs))}}};}macro_rules!impl_opassign{(impl<$T:ident>$Trait:ident$impl:ident for$t:ty)=>{impl<$T>$Trait for$t where$T:$Trait,{fn$impl(&mut self,rhs:Self){$Trait::$impl(&mut self.0,rhs.0)}}impl<$T>$Trait<$T>for$t where$T:$Trait,{fn$impl(&mut self,rhs:$T){$Trait::$impl(&mut self.0,rhs)}}};(impl<$T:ident>$Trait:ident$impl:ident for$t:ty=>$F:ident$f:ident)=>{impl<$T>$Trait for$t where$t:$F+Copy,{fn$impl(&mut self,rhs:Self){*self=$F::$f(*self,rhs);}}impl<$T>$Trait<$T>for$t where$t:$F<$T,Output=$t>+Copy,{fn$impl(&mut self,rhs:$T){*self=$F::$f(*self,rhs);}}};}#[derive(Default,PartialEq,Eq,PartialOrd,Ord,Hash,Clone,Copy)]#[repr(transparent)]#[doc=" Wrapper type of arithmetic `saturating_*` operations."]pub struct Saturating(pub T);pub trait Saturatingable:Sized where Saturating:Copy+Bounded+Zero+One+Eq+Ord+Default+FromStr+Display+Add>+Sub>+Mul>+Div>+Rem>+BitAnd>+BitOr>+BitXor>+Shl>+Shr>+AddAssign+SubAssign+MulAssign+DivAssign+RemAssign+BitAndAssign+BitOrAssign+BitXorAssign+ShlAssign+ShrAssign+Not>+Add>+Sub>+Mul>+Div>+Rem>+BitAnd>+BitOr>+BitXor>+AddAssign+SubAssign+MulAssign+DivAssign+RemAssign+BitAndAssign+BitOrAssign+BitXorAssign{fn to_saturating(self)->Saturating{Saturating(self)}fn from_saturating(s:Saturating)->Self{s.0}}implfmt::Debug for Saturatingwhere T:fmt::Debug{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{T::fmt(&self.0,f)}}implBounded for Saturatingwhere T:Bounded{fn maximum()->Self{Self(T::maximum())}fn minimum()->Self{Self(T::minimum())}}implZero for Saturatingwhere T:Zero{fn zero()->Self{Self(T::zero())}}implOne for Saturatingwhere T:One{fn one()->Self{Self(T::one())}}implFromStr for Saturatingwhere T:FromStr{type Err=T::Err;fn from_str(s:&str)->Result{T::from_str(s).map(Self)}}implDisplay for Saturatingwhere T:Display{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{T::fmt(&self.0,f)}}implScan for Saturatingwhere T:Scan{type Output=Self;fn scan(iter:&mut I)->Option{T::scan(iter).map(Self)}}impl_binop!(implDiv div for Saturating);impl_binop!(implRem rem for Saturating);impl_binop!(implBitAnd bitand for Saturating);impl_binop!(implBitOr bitor for Saturating);impl_binop!(implBitXor bitxor for Saturating);impl_opassign!(implAddAssign add_assign for Saturating =>Add add);impl_opassign!(implSubAssign sub_assign for Saturating =>Sub sub);impl_opassign!(implMulAssign mul_assign for Saturating =>Mul mul);impl_opassign!(implDivAssign div_assign for Saturating);impl_opassign!(implRemAssign rem_assign for Saturating);impl_opassign!(implBitAndAssign bitand_assign for Saturating);impl_opassign!(implBitOrAssign bitor_assign for Saturating);impl_opassign!(implBitXorAssign bitxor_assign for Saturating);implNot for Saturatingwhere T:Not{type Output=Self;fn not(self)->Self::Output{Self(Not::not(self.0))}}macro_rules!impl_int_base_for_saturating{($($t:ty)*)=>{$(impl Saturatingable for$t{}impl Add for Saturating<$t>{type Output=Self;fn add(self,rhs:Self)->Self::Output{Self(self.0 .saturating_add(rhs.0))}}impl Add<$t>for Saturating<$t>{type Output=Self;fn add(self,rhs:$t)->Self::Output{Self(self.0 .saturating_add(rhs))}}impl Sub for Saturating<$t>{type Output=Self;fn sub(self,rhs:Self)->Self::Output{Self(self.0 .saturating_sub(rhs.0))}}impl Sub<$t>for Saturating<$t>{type Output=Self;fn sub(self,rhs:$t)->Self::Output{Self(self.0 .saturating_sub(rhs))}}impl Mul for Saturating<$t>{type Output=Self;fn mul(self,rhs:Self)->Self::Output{Self(self.0 .saturating_mul(rhs.0))}}impl Mul<$t>for Saturating<$t>{type Output=Self;fn mul(self,rhs:$t)->Self::Output{Self(self.0 .saturating_mul(rhs))}}impl Sum for Saturating<$t>{fn sum>(iter:I)->Self{iter.fold(Self::zero(),|acc,x|acc+x)}}impl Product for Saturating<$t>{fn product>(iter:I)->Self{iter.fold(Self::one(),|acc,x|acc*x)}}impl IntBase for Saturating<$t>{type Error=<$t as IntBase>::Error;fn div_euclid(self,rhs:Self)->Self{Self(self.0 .div_euclid(rhs.0))}fn rem_euclid(self,rhs:Self)->Self{Self(self.0 .rem_euclid(rhs.0))}fn pow(self,exp:u32)->Self{Self(self.0 .saturating_pow(exp))}fn from_str_radix(src:&str,radix:u32)->Result{<$t as IntBase>::from_str_radix(src,radix).map(Self)}fn ilog(self,base:Self)->u32{self.0 .ilog(base.0)}fn ilog2(self)->u32{self.0 .ilog2()}fn ilog10(self)->u32{self.0 .ilog10()}fn isqrt(self)->Self{Self(self.0 .isqrt())}fn midpoint(self,rhs:Self)->Self{Self(self.0 .midpoint(rhs.0))}}impl From<$t>for Saturating<$t>{fn from(t:$t)->Self{Self(t)}})*};}impl_int_base_for_saturating!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);macro_rules!impl_unsigned_signed_for_saturating{($($unsigned:ident$signed:ident)*)=>{$(impl Unsigned for Saturating<$unsigned>{type Signed=Saturating<$signed>;fn signed(self)->Self::Signed{Saturating(TryFrom::try_from(self.0).ok().unwrap_or_else($signed::maximum))}fn abs_diff(self,other:Self)->Self{Self(self.0 .abs_diff(other.0))}fn div_ceil(self,rhs:Self)->Self{Self(self.0 .div_ceil(rhs.0))}fn is_power_of_two(self)->bool{self.0 .is_power_of_two()}fn next_power_of_two(self)->Self{Self(self.0 .next_power_of_two())}fn is_multiple_of(self,rhs:Self)->bool{self.0 .is_multiple_of(rhs.0)}fn next_multiple_of(self,rhs:Self)->Self{Self(self.0 .next_multiple_of(rhs.0))}fn gcd(self,other:Self)->Self{Self(self.0 .gcd(other.0))}fn mod_add(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_add(rhs.0,modulo.0))}fn mod_sub(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_sub(rhs.0,modulo.0))}fn mod_mul(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_mul(rhs.0,modulo.0))}}impl Signed for Saturating<$signed>{type Unsigned=Saturating<$unsigned>;fn unsigned(self)->Self::Unsigned{Saturating(TryFrom::try_from(self.0).ok().unwrap_or_else($unsigned::minimum))}fn abs(self)->Self{Self(self.0 .saturating_abs())}fn abs_diff(self,other:Self)->Self::Unsigned{Saturating(self.0 .abs_diff(other.0))}fn is_negative(self)->bool{self.0 .is_negative()}fn is_positive(self)->bool{self.0 .is_positive()}fn signum(self)->Self{Self(self.0 .signum())}}impl Neg for Saturating<$signed>{type Output=Self;fn neg(self)->Self::Output{Self(self.0 .saturating_neg())}})*};}impl_unsigned_signed_for_saturating!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);macro_rules!impl_binary_repr_for_saturating{($($t:ty)*)=>{$(impl Shlfor Saturating<$t>{type Output=Self;fn shl(self,rhs:u32)->Self::Output{Self(self.0 .checked_shl(rhs).unwrap_or(0))}}impl Shrfor Saturating<$t>{type Output=Self;fn shr(self,rhs:u32)->Self::Output{Self(self.0 .checked_shr(rhs).unwrap_or(0))}}impl ShlAssignfor Saturating<$t>{fn shl_assign(&mut self,rhs:u32){*self=Shl::shl(*self,rhs);}}impl ShrAssignfor Saturating<$t>{fn shr_assign(&mut self,rhs:u32){*self=Shr::shr(*self,rhs);}}impl BinaryRepr for Saturating<$t>{fn count_ones(self)->u32{self.0 .count_ones()}fn count_zeros(self)->u32{self.0 .count_zeros()}fn leading_ones(self)->u32{self.0 .leading_ones()}fn leading_zeros(self)->u32{self.0 .leading_zeros()}fn reverse_bits(self)->Self{Self(self.0 .reverse_bits())}fn rotate_left(self,n:u32)->Self{Self(self.0 .rotate_left(n))}fn rotate_right(self,n:u32)->Self{Self(self.0 .rotate_right(n))}fn swap_bytes(self)->Self{Self(self.0 .swap_bytes())}fn trailing_ones(self)->u32{self.0 .trailing_ones()}fn trailing_zeros(self)->u32{self.0 .trailing_zeros()}})*};}impl_binary_repr_for_saturating!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);#[derive(Default,PartialEq,Eq,PartialOrd,Ord,Hash,Clone,Copy)]#[repr(transparent)]#[doc=" Wrapper type of arithmetic `wrapping_*` operations."]pub struct Wrapping(pub T);pub trait Wrappingable:Sized where Wrapping:Copy+Bounded+Zero+One+Eq+Ord+Default+FromStr+Display+Add>+Sub>+Mul>+Div>+Rem>+BitAnd>+BitOr>+BitXor>+Shl>+Shr>+AddAssign+SubAssign+MulAssign+DivAssign+RemAssign+BitAndAssign+BitOrAssign+BitXorAssign+ShlAssign+ShrAssign+Not>+Add>+Sub>+Mul>+Div>+Rem>+BitAnd>+BitOr>+BitXor>+AddAssign+SubAssign+MulAssign+DivAssign+RemAssign+BitAndAssign+BitOrAssign+BitXorAssign{fn to_wrapping(self)->Wrapping{Wrapping(self)}fn from_wrapping(w:Wrapping)->Self{w.0}}implfmt::Debug for Wrappingwhere T:fmt::Debug{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{T::fmt(&self.0,f)}}implBounded for Wrappingwhere T:Bounded{fn maximum()->Self{Self(T::maximum())}fn minimum()->Self{Self(T::minimum())}}implZero for Wrappingwhere T:Zero{fn zero()->Self{Self(T::zero())}}implOne for Wrappingwhere T:One{fn one()->Self{Self(T::one())}}implFromStr for Wrappingwhere T:FromStr{type Err=T::Err;fn from_str(s:&str)->Result{T::from_str(s).map(Self)}}implDisplay for Wrappingwhere T:Display{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{T::fmt(&self.0,f)}}implScan for Wrappingwhere T:Scan{type Output=Self;fn scan(iter:&mut I)->Option{T::scan(iter).map(Self)}}impl_binop!(implBitAnd bitand for Wrapping);impl_binop!(implBitOr bitor for Wrapping);impl_binop!(implBitXor bitxor for Wrapping);impl_opassign!(implAddAssign add_assign for Wrapping =>Add add);impl_opassign!(implSubAssign sub_assign for Wrapping =>Sub sub);impl_opassign!(implMulAssign mul_assign for Wrapping =>Mul mul);impl_opassign!(implDivAssign div_assign for Wrapping =>Div div);impl_opassign!(implRemAssign rem_assign for Wrapping =>Rem rem);impl_opassign!(implBitAndAssign bitand_assign for Wrapping);impl_opassign!(implBitOrAssign bitor_assign for Wrapping);impl_opassign!(implBitXorAssign bitxor_assign for Wrapping);implNot for Wrappingwhere T:Not{type Output=Self;fn not(self)->Self::Output{Self(Not::not(self.0))}}macro_rules!impl_int_base_for_wrapping{($($t:ty)*)=>{$(impl Wrappingable for$t{}impl Add for Wrapping<$t>{type Output=Self;fn add(self,rhs:Self)->Self::Output{Self(self.0 .wrapping_add(rhs.0))}}impl Add<$t>for Wrapping<$t>{type Output=Self;fn add(self,rhs:$t)->Self::Output{Self(self.0 .wrapping_add(rhs))}}impl Sub for Wrapping<$t>{type Output=Self;fn sub(self,rhs:Self)->Self::Output{Self(self.0 .wrapping_sub(rhs.0))}}impl Sub<$t>for Wrapping<$t>{type Output=Self;fn sub(self,rhs:$t)->Self::Output{Self(self.0 .wrapping_sub(rhs))}}impl Mul for Wrapping<$t>{type Output=Self;fn mul(self,rhs:Self)->Self::Output{Self(self.0 .wrapping_mul(rhs.0))}}impl Mul<$t>for Wrapping<$t>{type Output=Self;fn mul(self,rhs:$t)->Self::Output{Self(self.0 .wrapping_mul(rhs))}}impl Div for Wrapping<$t>{type Output=Self;fn div(self,rhs:Self)->Self::Output{Self(self.0 .wrapping_div(rhs.0))}}impl Div<$t>for Wrapping<$t>{type Output=Self;fn div(self,rhs:$t)->Self::Output{Self(self.0 .wrapping_div(rhs))}}impl Rem for Wrapping<$t>{type Output=Self;fn rem(self,rhs:Self)->Self::Output{Self(self.0 .wrapping_rem(rhs.0))}}impl Rem<$t>for Wrapping<$t>{type Output=Self;fn rem(self,rhs:$t)->Self::Output{Self(self.0 .wrapping_rem(rhs))}}impl Sum for Wrapping<$t>{fn sum>(iter:I)->Self{iter.fold(Self::zero(),|acc,x|acc+x)}}impl Product for Wrapping<$t>{fn product>(iter:I)->Self{iter.fold(Self::one(),|acc,x|acc*x)}}impl IntBase for Wrapping<$t>{type Error=<$t as IntBase>::Error;fn div_euclid(self,rhs:Self)->Self{Self(self.0 .wrapping_div_euclid(rhs.0))}fn rem_euclid(self,rhs:Self)->Self{Self(self.0 .wrapping_rem_euclid(rhs.0))}fn pow(self,exp:u32)->Self{Self(self.0 .wrapping_pow(exp))}fn from_str_radix(src:&str,radix:u32)->Result{<$t as IntBase>::from_str_radix(src,radix).map(Self)}fn ilog(self,base:Self)->u32{self.0 .ilog(base.0)}fn ilog2(self)->u32{self.0 .ilog2()}fn ilog10(self)->u32{self.0 .ilog10()}fn isqrt(self)->Self{Self(self.0 .isqrt())}fn midpoint(self,rhs:Self)->Self{Self(self.0 .midpoint(rhs.0))}}impl From<$t>for Wrapping<$t>{fn from(t:$t)->Self{Self(t)}})*};}impl_int_base_for_wrapping!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);macro_rules!impl_unsigned_signed_for_wrapping{($($unsigned:ident$signed:ident)*)=>{$(impl Unsigned for Wrapping<$unsigned>{type Signed=Wrapping<$signed>;fn signed(self)->Self::Signed{Wrapping(self.0 .signed())}fn abs_diff(self,other:Self)->Self{Self(self.0 .abs_diff(other.0))}fn div_ceil(self,rhs:Self)->Self{Self(self.0 .div_ceil(rhs.0))}fn is_power_of_two(self)->bool{self.0 .is_power_of_two()}fn next_power_of_two(self)->Self{Self(self.0 .next_power_of_two())}fn is_multiple_of(self,rhs:Self)->bool{self.0 .is_multiple_of(rhs.0)}fn next_multiple_of(self,rhs:Self)->Self{Self(self.0 .next_multiple_of(rhs.0))}fn gcd(self,other:Self)->Self{Self(self.0 .gcd(other.0))}fn mod_add(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_add(rhs.0,modulo.0))}fn mod_sub(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_sub(rhs.0,modulo.0))}fn mod_mul(self,rhs:Self,modulo:Self)->Self{Self(self.0 .mod_mul(rhs.0,modulo.0))}}impl Signed for Wrapping<$signed>{type Unsigned=Wrapping<$unsigned>;fn unsigned(self)->Self::Unsigned{Wrapping(self.0 .unsigned())}fn abs(self)->Self{Self(self.0 .wrapping_abs())}fn abs_diff(self,other:Self)->Self::Unsigned{Wrapping(self.0 .abs_diff(other.0))}fn is_negative(self)->bool{self.0 .is_negative()}fn is_positive(self)->bool{self.0 .is_positive()}fn signum(self)->Self{Self(self.0 .signum())}}impl Neg for Wrapping<$signed>{type Output=Self;fn neg(self)->Self::Output{Self(self.0 .wrapping_neg())}})*};}impl_unsigned_signed_for_wrapping!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);macro_rules!impl_binary_repr_for_wrapping{($($t:ty)*)=>{$(impl Shlfor Wrapping<$t>{type Output=Self;fn shl(self,rhs:u32)->Self::Output{Self(self.0 .wrapping_shl(rhs))}}impl Shrfor Wrapping<$t>{type Output=Self;fn shr(self,rhs:u32)->Self::Output{Self(self.0 .wrapping_shr(rhs))}}impl ShlAssignfor Wrapping<$t>{fn shl_assign(&mut self,rhs:u32){*self=Shl::shl(*self,rhs);}}impl ShrAssignfor Wrapping<$t>{fn shr_assign(&mut self,rhs:u32){*self=Shr::shr(*self,rhs);}}impl BinaryRepr for Wrapping<$t>{fn count_ones(self)->u32{self.0 .count_ones()}fn count_zeros(self)->u32{self.0 .count_zeros()}fn leading_ones(self)->u32{self.0 .leading_ones()}fn leading_zeros(self)->u32{self.0 .leading_zeros()}fn reverse_bits(self)->Self{Self(self.0 .reverse_bits())}fn rotate_left(self,n:u32)->Self{Self(self.0 .rotate_left(n))}fn rotate_right(self,n:u32)->Self{Self(self.0 .rotate_right(n))}fn swap_bytes(self)->Self{Self(self.0 .swap_bytes())}fn trailing_ones(self)->u32{self.0 .trailing_ones()}fn trailing_zeros(self)->u32{self.0 .trailing_zeros()}})*};}impl_binary_repr_for_wrapping!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);} // codesnip-guard: scanner #[cfg_attr(any(),rustfmt::skip)]pub use self::scanner::*;#[cfg_attr(any(),rustfmt::skip)]mod scanner{use std::{iter::{FromIterator,from_fn,repeat_with},marker::PhantomData};pub fn read_stdin_all()->String{use std::io::Read as _;let mut s=String::new();std::io::stdin().read_to_string(&mut s).expect("io error");s}pub fn read_stdin_all_unchecked()->String{use std::io::Read as _;let mut buf=Vec::new();std::io::stdin().read_to_end(&mut buf).expect("io error");unsafe{String::from_utf8_unchecked(buf)}}pub fn read_all(mut reader:impl std::io::Read)->String{let mut s=String::new();reader.read_to_string(&mut s).expect("io error");s}pub fn read_all_unchecked(mut reader:impl std::io::Read)->String{let mut buf=Vec::new();reader.read_to_end(&mut buf).expect("io error");unsafe{String::from_utf8_unchecked(buf)}}pub fn read_stdin_line()->String{let mut s=String::new();std::io::stdin().read_line(&mut s).expect("io error");s}pub trait Scan:Sized{type Output;fn scan(source:&mut S)->Option;fn scan_vec(source:&mut S,size:usize,capacity:usize)->Vec{let mut values=Vec::with_capacity(capacity.max(size));values.extend((0..size).map(|_|source.scan::()));values}}pub trait MarkedScan:Sized{type Output;fn mscan(self,source:&mut S)->Option;}pub trait ScanSource:Sized{#[doc=" Reads a token under the source's input requirements."]#[doc=" Checked sources return `None` at EOF; unchecked sources require available input."]fn next_token(&mut self)->Option<&str>;#[doc=" Skips separators without consuming the next token."]#[inline]fn skip_whitespace(&mut self){}#[inline]fn read_u8(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_u16(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_u32(&mut self)->Option{self.next_token()?.parse().ok()}fn read_u32_vec(&mut self,size:usize,capacity:usize)->Vec{let mut values=Vec::with_capacity(capacity.max(size));values.extend((0..size).map(|_|self.scan::()));values}#[inline]fn read_u64(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_u128(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_usize(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_i8(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_i16(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_i32(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_i64(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_i128(&mut self)->Option{self.next_token()?.parse().ok()}#[inline]fn read_isize(&mut self)->Option{self.next_token()?.parse().ok()}#[doc=" Panics if reading fails."]#[inline]fn scan(&mut self)->T::Output{T::scan(self).expect("scan error")}#[doc=" Panics if reading fails."]#[inline]fn mscan(&mut self,marker:T)->T::Output{marker.mscan(self).expect("scan error")}fn scan_vec(&mut self,size:usize,capacity:usize)->Vec{if size==0{self.skip_whitespace();}T::scan_vec(self,size,capacity)}#[inline]fn iter(&mut self)->ScannerIter<'_,Self,T>{ScannerIter{inner:self,_marker:PhantomData}}}#[derive(Clone,Debug)]pub struct Scanner<'a,I:Iterator=std::str::SplitAsciiWhitespace<'a>>{iter:I}impl<'a>Scanner<'a>{pub fn new(s:&'a str)->Self{Self{iter:s.split_ascii_whitespace()}}}impl<'a,I:Iterator>Scanner<'a,I>{pub fn new_from_iter(iter:I)->Self{Self{iter}}}impl<'a,I:Iterator>ScanSource for Scanner<'a,I>{fn next_token(&mut self)->Option<&str>{self.iter.next()}}macro_rules!impl_scan{($($t:ty)*)=>{$(impl Scan for$t{type Output=Self;fn scan(iter:&mut I)->Option{iter.next_token()?.parse::<$t>().ok()}})*};}impl_scan!(char f32 f64 String);macro_rules!impl_integer_scan{($($t:ty=>$read:ident),*$(,)?)=>{$(impl Scan for$t{type Output=Self;#[inline]fn scan(source:&mut S)->Option{source.$read()}})*};}impl_integer_scan!(u8=>read_u8,u16=>read_u16,u64=>read_u64,u128=>read_u128,usize=>read_usize,i8=>read_i8,i16=>read_i16,i32=>read_i32,i64=>read_i64,i128=>read_i128,isize=>read_isize,);impl Scan for u32{type Output=Self;#[inline]fn scan(source:&mut S)->Option{source.read_u32()}fn scan_vec(source:&mut S,size:usize,capacity:usize)->Vec{source.read_u32_vec(size,capacity)}}macro_rules!impl_scan_tuple{(@impl$($T:ident)*)=>{impl<$($T:Scan),*>Scan for($($T,)*){type Output=($(<$T as Scan>::Output,)*);fn scan(_iter:&mut It)->Option{Some(($(<$T as Scan>::scan(_iter)?,)*))}}};(@inner$($T:ident)*,)=>{impl_scan_tuple!(@impl$($T)*);};(@inner$($T:ident)*,$U:ident$($Rest:ident)*)=>{impl_scan_tuple!(@impl$($T)*);impl_scan_tuple!(@inner$($T)*$U,$($Rest)*);};($($T:ident)*)=>{impl_scan_tuple!(@inner,$($T)*);};}impl_scan_tuple!(A B C D E F G H I J K);pub struct ScannerIter<'a,S,T>{inner:&'a mut S,_marker:PhantomDataT>}implIterator for ScannerIter<'_,S,T>{type Item=T::Output;#[inline]fn next(&mut self)->Option{T::scan(self.inner)}}#[doc=" scan a value with Scanner"]#[doc=""]#[doc=" - `scan_value!(scanner, ELEMENT)`"]#[doc=""]#[doc=" ELEMENT :="]#[doc=" - `$ty`: Scan"]#[doc=" - `&str`: borrowed token; the source stays borrowed until its last use"]#[doc=" - `@$expr`: MarkedScan"]#[doc=" - `$ty = $expr`: MarkedScan"]#[doc=" - `[ELEMENT; $expr]`: vector"]#[doc=" - `[$ty; $len; capacity $capacity]`: vector with reserved capacity"]#[doc=" - `[ELEMENT; const $expr]`: array"]#[doc=" - `[ELEMENT]`: iterator"]#[doc=" - `[ELEMENT; iter $expr]`: iterator of the specified length"]#[doc=" - `($(ELEMENT)*,)`: tuple"]#[macro_export]macro_rules!scan_value{(@repeat$scanner:expr,[$($t:tt)*]$len:expr)=>{{$crate::scan_value!(@iter$scanner,[$($t)*]$len).collect::>()}};(@repeat$scanner:expr,[$($t:tt)*])=>{{::std::iter::repeat_with(||$crate::scan_value!(@inner$scanner,[]$($t)*))}};(@iter$scanner:expr,[$($t:tt)*]$len:expr)=>{{let size=$len;if size==0{$scanner.skip_whitespace();}$crate::scan_value!(@repeat$scanner,[$($t)*]).take(size)}};(@array$scanner:expr,[$($t:tt)*]$len:expr)=>{{if$len==0{$scanner.skip_whitespace();}$crate::array![||$crate::scan_value!(@inner$scanner,[]$($t)*);$len]}};(@tuple$scanner:expr,[$([$($args:tt)*])*])=>{($($($args)*,)*)};(@sparen$scanner:expr,[]@$e:expr;$($t:tt)*)=>{$crate::scan_value!(@sparen$scanner,[@$e]$($t)*)};(@sparen$scanner:expr,[]($($tt:tt)*);$($t:tt)*)=>{$crate::scan_value!(@sparen$scanner,[($($tt)*)]$($t)*)};(@sparen$scanner:expr,[][$($tt:tt)*];$($t:tt)*)=>{$crate::scan_value!(@sparen$scanner,[[$($tt)*]]$($t)*)};(@sparen$scanner:expr,[]$ty:ty=$e:expr;$($t:tt)*)=>{$crate::scan_value!(@sparen$scanner,[$ty=$e]$($t)*)};(@sparen$scanner:expr,[]$ty:ty;$($t:tt)*)=>{$crate::scan_value!(@sparen$scanner,[$ty]$($t)*)};(@sparen$scanner:expr,[]$($args:tt)*)=>{$crate::scan_value!(@repeat$scanner,[$($args)*])};(@sparen$scanner:expr,[$($args:tt)+]const$len:expr)=>{$crate::scan_value!(@array$scanner,[$($args)+]$len)};(@sparen$scanner:expr,[$($args:tt)+]iter$len:expr)=>{$crate::scan_value!(@iter$scanner,[$($args)+]$len)};(@sparen$scanner:expr,[$($args:tt)+]$len:expr;capacity$capacity:expr)=>{{let size=$len;let capacity=$capacity;$scanner.scan_vec::<$($args)+>(size,capacity)}};(@sparen$scanner:expr,[$($args:tt)+]$len:expr)=>{$crate::scan_value!(@repeat$scanner,[$($args)+]$len)};(@$tag:ident$scanner:expr,[[$($args:tt)*]])=>{$($args)*};(@$tag:ident$scanner:expr,[$($args:tt)*]@$e:expr$(,$($t:tt)*)?)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[$scanner.mscan($e)]]$(,$($t)*)?)};(@$tag:ident$scanner:expr,[$($args:tt)*]($($tuple:tt)*)$($t:tt)*)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[$crate::scan_value!(@tuple$scanner,[]$($tuple)*)]]$($t)*)};(@$tag:ident$scanner:expr,[$($args:tt)*][$($tt:tt)*]$($t:tt)*)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[$crate::scan_value!(@sparen$scanner,[]$($tt)*)]]$($t)*)};(@$tag:ident$scanner:expr,[$($args:tt)*]&str$(,$($t:tt)*)?)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[$scanner.next_token().expect("scan error")]]$(,$($t)*)?)};(@$tag:ident$scanner:expr,[$($args:tt)*]$ty:ty=$e:expr$(,$($t:tt)*)?)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[{let _tmp:$ty=$scanner.mscan($e);_tmp}]]$(,$($t)*)?)};(@$tag:ident$scanner:expr,[$($args:tt)*]$ty:ty$(,$($t:tt)*)?)=>{$crate::scan_value!(@$tag$scanner,[$($args)*[$scanner.scan::<$ty>()]]$(,$($t)*)?)};(@$tag:ident$scanner:expr,[$($args:tt)*],$($t:tt)*)=>{$crate::scan_value!(@$tag$scanner,[$($args)*]$($t)*)};(@$tag:ident$scanner:expr,[$($args:tt)*])=>{::std::compile_error!(::std::stringify!($($args)*))};(src=$src:expr,$($t:tt)*)=>{{let mut __scanner=Scanner::new($src);$crate::scan_value!(@inner __scanner,[]$($t)*)}};(iter=$iter:expr,$($t:tt)*)=>{{let mut __scanner=Scanner::new_from_iter($iter);$crate::scan_value!(@inner __scanner,[]$($t)*)}};($scanner:expr,$($t:tt)*)=>{$crate::scan_value!(@inner$scanner,[]$($t)*)}}#[doc=" scan and bind values with Scanner"]#[doc=""]#[doc=" - `scan!(scanner, $($pat $(: ELEMENT)?),*)`"]#[macro_export]macro_rules!scan{(@assert$p:pat)=>{};(@assert$($p:tt)*)=>{::std::compile_error!(::std::concat!("expected pattern, found `",::std::stringify!($($p)*),"`"));};(@pat$scanner:expr,[][])=>{};(@pat$scanner:expr,[][],$($t:tt)*)=>{$crate::scan!(@pat$scanner,[][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]$x:ident$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*$x][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]::$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*::][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]&$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*&][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]($($x:tt)*)$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*($($x)*)][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][][$($x:tt)*]$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*[$($x)*]][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]{$($x:tt)*}$($t:tt)*)=>{$crate::scan!(@pat$scanner,[$($p)*{$($x)*}][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]:$($t:tt)*)=>{$crate::scan!(@ty$scanner,[$($p)*][]$($t)*)};(@pat$scanner:expr,[$($p:tt)*][]$($t:tt)*)=>{$crate::scan!(@let$scanner,[$($p)*][usize]$($t)*)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*]@$e:expr$(,$($t:tt)*)?)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*@$e]$(,$($t)*)?)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*]($($x:tt)*)$($t:tt)*)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*($($x)*)]$($t)*)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*][$($x:tt)*]$($t:tt)*)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*[$($x)*]]$($t)*)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*]&str$(,$($t:tt)*)?)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*&str]$(,$($t)*)?)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*]$ty:ty=$e:expr$(,$($t:tt)*)?)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*$ty=$e]$(,$($t)*)?)};(@ty$scanner:expr,[$($p:tt)*][$($tt:tt)*]$ty:ty$(,$($t:tt)*)?)=>{$crate::scan!(@let$scanner,[$($p)*][$($tt)*$ty]$(,$($t)*)?)};(@let$scanner:expr,[$($p:tt)*][$($tt:tt)*]$($t:tt)*)=>{$crate::scan!{@assert$($p)*}let$($p)* =$crate::scan_value!($scanner,$($tt)*);$crate::scan!(@pat$scanner,[][]$($t)*)};(src=$src:expr,$($t:tt)*)=>{let mut __scanner=Scanner::new($src);$crate::scan!(@pat __scanner,[][]$($t)*)};(iter=$iter:expr,$($t:tt)*)=>{let mut __scanner=Scanner::new_from_iter($iter);$crate::scan!(@pat __scanner,[][]$($t)*)};($scanner:expr,$($t:tt)*)=>{$crate::scan!(@pat$scanner,[][]$($t)*)}}#[doc=" define enum scan rules"]#[doc=""]#[doc=" # Example"]#[doc=" ```rust"]#[doc=" # use competitive::{define_enum_scan, tools::{CharsWithBase, Scan, ScanSource, Scanner, Usize1}};"]#[doc=" define_enum_scan! {"]#[doc=" enum Query: u8 {"]#[doc=" 0 => Noop,"]#[doc=" 1 => Args { i: Usize1, s: char },"]#[doc=" 9 => Complex { n: usize, c: [(usize, Vec = CharsWithBase('a')); n] },"]#[doc=" }"]#[doc=" }"]#[doc=" ```"]#[macro_export]macro_rules!define_enum_scan{(@field_ty@repeat[$($t:tt)*]$($len:expr)?)=>{Vec<$crate::define_enum_scan!(@field_ty$($t)*)>};(@field_ty@array[$($t:tt)*]$len:expr)=>{[$crate::define_enum_scan!(@field_ty$($t)*);$len]};(@field_ty@tuple[$([$($args:tt)*])*])=>{($($($args)*,)*)};(@field_ty@sparen[]($($tt:tt)*);$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@sparen[($($tt)*)]$($t)*)};(@field_ty@sparen[][$($tt:tt)*];$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@sparen[[$($tt)*]]$($t)*)};(@field_ty@sparen[]$ty:ty=$e:expr;$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@sparen[$ty=$e]$($t)*)};(@field_ty@sparen[]$ty:ty;$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@sparen[$ty]$($t)*)};(@field_ty@sparen[]$($args:tt)*)=>{$crate::define_enum_scan!(@field_ty@repeat[$($args)*])};(@field_ty@sparen[$($args:tt)+]const$len:expr)=>{$crate::define_enum_scan!(@field_ty@array[$($args)+]$len)};(@field_ty@sparen[$($args:tt)+]$len:expr)=>{$crate::define_enum_scan!(@field_ty@repeat[$($args)+]$len)};(@field_ty@$tag:ident[$($args:tt)*]($($tuple:tt)*)$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@$tag[$($args)*[$crate::define_enum_scan!(@field_ty@tuple[]$($tuple)*)]]$($t)*)};(@field_ty@$tag:ident[$($args:tt)*][$($tt:tt)*]$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@$tag[$($args)*[$crate::define_enum_scan!(@field_ty@sparen[]$($tt)*)]]$($t)*)};(@field_ty@$tag:ident[$($args:tt)*]$ty:ty=$e:expr$(,$($t:tt)*)?)=>{$crate::define_enum_scan!(@field_ty@$tag[$($args)*[$ty]]$(,$($t)*)?)};(@field_ty@$tag:ident[$($args:tt)*]$ty:ty$(,$($t:tt)*)?)=>{$crate::define_enum_scan!(@field_ty@$tag[$($args)*[<$ty as Scan>::Output]]$(,$($t)*)?)};(@field_ty@$tag:ident[$($args:tt)*],$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@$tag[$($args)*]$($t)*)};(@field_ty@$tag:ident[[$($args:tt)*]])=>{$($args)*};(@field_ty@$tag:ident[$($args:tt)*])=>{::std::compile_error!(::std::stringify!($($args)*))};(@field_ty$($t:tt)*)=>{$crate::define_enum_scan!(@field_ty@inner[]$($t)*)};(@tag_expr raw,$iter:ident)=>{ScanSource::next_token($iter)?};(@tag_expr$d:ty,$iter:ident)=>{<$d as Scan>::scan($iter)?};(@variant([$($attr:tt)*]$vis:vis$T:ident$d:tt)[$($vars:tt)*])=>{$crate::define_enum_scan!{@def$($attr)*$vis enum$T:$d{$($vars)*}}};(@variant$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident{$($fs:tt)*}$($rest:tt)*)=>{$crate::define_enum_scan!{@field$ctx[$($vars)*]$p=>$v[]$($fs)*;$($rest)*}};(@variant$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident$($rest:tt)*)=>{$crate::define_enum_scan!{@variant$ctx[$($vars)*$p=>$v,]$($rest)*}};(@variant$ctx:tt[$($vars:tt)*],$($rest:tt)*)=>{$crate::define_enum_scan!{@variant$ctx[$($vars)*]$($rest)*}};(@endfield$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*][$f:ident:$($spec:tt)*],$($rest:tt)*)=>{$crate::define_enum_scan!{@field$ctx[$($vars)*]$p=>$v[$($fs)*[$f:$($spec)*]]$($rest)*}};(@endfield$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*][$f:ident:$($spec:tt)*];$($rest:tt)*)=>{$crate::define_enum_scan!{@variant$ctx[$($vars)*$p=>$v{$($fs)*[$f:$($spec)*]},]$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*];$($rest:tt)*)=>{$crate::define_enum_scan!{@variant$ctx[$($vars)*$p=>$v{$($fs)*},]$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:($($tuple:tt)*)$sep:tt$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:($($tuple)*)]$sep$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:[$($x:tt)*]$sep:tt$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:[$($x)*]]$sep$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:$ty:ty=$e:expr,$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:$ty=$e],$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:$ty:ty;$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:$ty];$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:$ty:ty=$e:expr;$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:$ty=$e];$($rest)*}};(@field$ctx:tt[$($vars:tt)*]$p:pat=>$v:ident[$($fs:tt)*]$f:ident:$ty:ty,$($rest:tt)*)=>{$crate::define_enum_scan!{@endfield$ctx[$($vars)*]$p=>$v[$($fs)*][$f:$ty],$($rest)*}};(@def$(#[$attr:meta])*$vis:vis enum$T:ident:$d:tt{$($p:pat=>$v:ident$({$([$f:ident:$($spec:tt)*])*})?,)*})=>{$(#[$attr])*$vis enum$T{$($v$({$($f:$crate::define_enum_scan!(@field_ty$($spec)*)),*})?),*}impl Scan for$T{type Output=Self;fn scan(iter:&mut I)->Option{let tag=$crate::define_enum_scan!(@tag_expr$d,iter);match tag{$($p=>{$($(let$f=$crate::scan_value!((*iter),$($spec)*);)*)?Some($T::$v$({$($f),*})?)}),*_=>None,}}}};($(#[$attr:meta])*$vis:vis enum$T:ident:raw{$($body:tt)*})=>{$crate::define_enum_scan!{@variant([$(#[$attr])*]$vis$T raw)[]$($body)*}};($(#[$attr:meta])*$vis:vis enum$T:ident:$d:ty{$($body:tt)*})=>{$crate::define_enum_scan!{@variant([$(#[$attr])*]$vis$T$d)[]$($body)*}};}#[derive(Debug,Copy,Clone)]pub enum Usize1{}impl Scan for Usize1{type Output=usize;fn scan(iter:&mut I)->Option{::scan(iter)?.checked_sub(1)}}#[derive(Debug,Copy,Clone)]pub struct CharWithBase(pub char);impl MarkedScan for CharWithBase{type Output=usize;fn mscan(self,iter:&mut I)->Option{Some((::scan(iter)?as u8-self.0 as u8)as usize)}}#[derive(Debug,Copy,Clone)]pub enum Chars{}impl Scan for Chars{type Output=Vec;fn scan(iter:&mut I)->Option{Some(iter.next_token()?.chars().collect())}}#[derive(Debug,Copy,Clone)]pub struct CharsWithBase(pub char);impl MarkedScan for CharsWithBase{type Output=Vec;fn mscan(self,iter:&mut I)->Option{Some(iter.next_token()?.chars().map(|c|(c as u8-self.0 as u8)as usize).collect())}}#[derive(Debug,Copy,Clone)]pub enum Byte1{}impl Scan for Byte1{type Output=u8;fn scan(iter:&mut I)->Option{let bytes=iter.next_token()?.as_bytes();assert_eq!(bytes.len(),1);Some(bytes[0])}}#[derive(Debug,Copy,Clone)]pub struct ByteWithBase(pub u8);impl MarkedScan for ByteWithBase{type Output=usize;fn mscan(self,iter:&mut I)->Option{Some((::scan(iter)?as u8-self.0)as usize)}}#[derive(Debug,Copy,Clone)]pub enum Bytes{}impl Scan for Bytes{type Output=Vec;fn scan(iter:&mut I)->Option{Some(iter.next_token()?.bytes().collect())}}#[derive(Debug,Copy,Clone)]pub struct BytesWithBase(pub u8);impl MarkedScan for BytesWithBase{type Output=Vec;fn mscan(self,iter:&mut I)->Option{Some(iter.next_token()?.bytes().map(|c|(c-self.0)as usize).collect())}}#[derive(Debug,Copy,Clone)]pub struct Collect::Output>>where T:Scan,B:FromIterator<::Output>{size:usize,_marker:PhantomData(T,B)>}implCollectwhere T:Scan,B:FromIterator<::Output>{pub fn new(size:usize)->Self{Self{size,_marker:PhantomData}}}implMarkedScan for Collectwhere T:Scan,B:FromIterator<::Output>{type Output=B;fn mscan(self,iter:&mut I)->Option{if self.size==0{iter.skip_whitespace();}repeat_with(| |::scan(iter)).take(self.size).collect()}}#[derive(Debug,Copy,Clone)]pub struct SizedCollect::Output>>where T:Scan,B:FromIterator<::Output>{_marker:PhantomData(T,B)>}implScan for SizedCollectwhere T:Scan,B:FromIterator<::Output>{type Output=B;fn scan(iter:&mut I)->Option{let size=usize::scan(iter)?;if size==0{iter.skip_whitespace();}repeat_with(| |::scan(iter)).take(size).collect()}}#[derive(Debug,Copy,Clone)]pub struct Splittedwhere T:Scan{pat:P,_marker:PhantomDataT>}implSplittedwhere T:Scan{pub fn new(pat:P)->Self{Self{pat,_marker:PhantomData}}}implMarkedScan for Splittedwhere T:Scan{type Output=Vec<::Output>;fn mscan(self,iter:&mut I)->Option{let mut iter=Scanner::new_from_iter(iter.next_token()?.split(self.pat));Some(from_fn(| |::scan(&mut iter)).collect())}}implMarkedScan for Splittedwhere T:Scan{type Output=Vec<::Output>;fn mscan(self,iter:&mut I)->Option{let mut iter=Scanner::new_from_iter(iter.next_token()?.split(self.pat));Some(from_fn(| |::scan(&mut iter)).collect())}}implMarkedScan for F where F:Fn(&str)->Option{type Output=T;fn mscan(self,iter:&mut I)->Option{self(iter.next_token()?)}}} // codesnip-guard: topological_sort #[cfg_attr(any(),rustfmt::skip)]pub use self::topological_sort::TopologicalSortExt;#[cfg_attr(any(),rustfmt::skip)]mod topological_sort{use super::{DirectedGraph,VertexMap};pub trait TopologicalSortExt:DirectedGraph{fn topological_sort(&self)->Vecwhere Self:VertexMap{let mut indegree=self.construct_vmap(| |0);for u in self.vertices(){for neighbor in self.neighbors(u){*self.vmap_get_mut(&mut indegree,neighbor.to)+=1;}}let mut stack=self.vertices().filter(|&u|*self.vmap_get(&indegree,u)==0).collect::>();let mut order=Vec::with_capacity(self.vsize());while let Some(u)=stack.pop(){order.push(u);for neighbor in self.neighbors(u){let indegree=self.vmap_get_mut(&mut indegree,neighbor.to);*indegree-=1;if*indegree==0{stack.push(neighbor.to);}}}order}}implTopologicalSortExt for G where G:DirectedGraph+?Sized{}} // codesnip-guard: zero_one #[cfg_attr(any(),rustfmt::skip)]pub use self::zero_one::{One,Zero};#[cfg_attr(any(),rustfmt::skip)]mod zero_one{pub trait Zero:Sized{fn zero()->Self;#[inline]fn is_zero(&self)->bool where Self:PartialEq{self==&Self::zero()}#[inline]fn set_zero(&mut self){*self=Self::zero();}}pub trait One:Sized{fn one()->Self;#[inline]fn is_one(&self)->bool where Self:PartialEq{self==&Self::one()}#[inline]fn set_one(&mut self){*self=Self::one();}}macro_rules!impl_zero_one{($({$(<$T:ident:$Bound:ident>)?$Trait:ident$method:ident$($t:ty)*,$e:expr})*)=>{$(impl_zero_one!(@impl[$(<$T:$Bound>)?]$Trait$method[$($t)*],$e);)*};(@impl[<$T:ident:$Bound:ident>]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl<$T:$Bound>$Trait for$t{fn$method()->Self{$e}})*};(@impl[]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl$Trait for$t{fn$method()->Self{$e}})*};}impl_zero_one!({Zero zero u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,0}{Zero zero f32 f64,0.}{One one u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,1}{One one f32 f64,1.}{Zero zero std::num::Wrapping,Self(T::zero())}{One one std::num::Wrapping,Self(T::one())});}