use std:: fmt ;
#[derive( PartialEq,Eq,Debug,Clone)]
enum Couleur{
Rouge,
Verte,
Blanche,
Jaune,
Bleue
}
impl Couleur{
fn inc( self) - > Couleur{
match self{
Couleur:: Rouge => { let r= Couleur:: Verte ;
r} ,
Couleur:: Verte => { let r= Couleur:: Blanche ;
r} ,
Couleur:: Blanche => { let r= Couleur:: Jaune ;
r} ,
Couleur:: Jaune => { let r= Couleur:: Bleue ;
r} ,
Couleur:: Bleue => Couleur:: Rouge
}
}
}
#[derive( PartialEq,Eq,Debug,Clone)]
enum Nationalite{
Anglais,
Suedois,
Danois,
Norvegien,
Allemand
}
impl Nationalite{
fn inc( self) - > Nationalite{
match self{
Nationalite:: Anglais => { let r= Nationalite:: Suedois ;
r} ,
Nationalite:: Suedois => { let r= Nationalite:: Danois ;
r} ,
Nationalite:: Danois => { let r= Nationalite:: Norvegien ;
r} ,
Nationalite:: Norvegien => { let r= Nationalite:: Allemand ;
r} ,
Nationalite:: Allemand => Nationalite:: Anglais
}
}
}
#[derive( PartialEq,Eq,Debug,Clone)]
enum Boisson{
The,
Cafe,
Lait,
Biere,
Eau
}
impl Boisson{
fn inc( self) - > Boisson{
match self{
Boisson:: The => { let r= Boisson:: Cafe ;
r} ,
Boisson:: Cafe => { let r= Boisson:: Lait ;
r} ,
Boisson:: Lait => { let r= Boisson:: Biere ;
r} ,
Boisson:: Biere => { let r= Boisson:: Eau ;
r} ,
Boisson:: Eau => Boisson:: The
}
}
}
#[derive( PartialEq,Eq,Debug,Clone)]
enum Cigarette{
PallMall,
Dunhills,
Blends,
BleueMasters,
Prince,
}
impl Cigarette{
fn inc( self) - > Cigarette{
match self{
Cigarette:: PallMall => { let r= Cigarette:: Dunhills ;
r} ,
Cigarette:: Dunhills => { let r= Cigarette:: Blends ;
r} ,
Cigarette:: Blends => { let r= Cigarette:: BleueMasters ;
r} ,
Cigarette:: BleueMasters => { let r= Cigarette:: Prince ;
r} ,
Cigarette:: Prince => Cigarette:: PallMall
}
}
}
#[derive( PartialEq,Eq,Debug,Clone)]
enum Animaux{
Chien,
Oiseaux,
Chats,
Chevaux,
PoissonRouge
}
impl Animaux{
fn inc( self) - > Animaux{
match self{
Animaux:: Chien => { let r= Animaux:: Oiseaux ;
r} ,
Animaux:: Oiseaux => { let r= Animaux:: Chats ;
r} ,
Animaux:: Chats => { let r= Animaux:: Chevaux ;
r} ,
Animaux:: Chevaux => { let r= Animaux:: PoissonRouge ;
r} ,
Animaux:: PoissonRouge => Animaux:: Chien
}
}
}
#[derive(Debug,Clone)]
struct Maison{
couleur : Couleur,
nationalite : Nationalite,
boisson : Boisson,
cigarette : Cigarette,
animaux : Animaux
}
impl Maison{
fn inc( self) - > Maison{
match self{
Maison { couleur : Couleur:: Bleue ,
nationalite : Nationalite:: Allemand ,
boisson : Boisson:: Eau ,
cigarette : Cigarette:: Prince ,
animaux : Animaux:: PoissonRouge
} =>
{
Maison{ couleur : Couleur:: Bleue .inc ( ) , nationalite : Nationalite:: Allemand .inc ( ) , boisson : Boisson:: Eau .inc ( ) , cigarette : Cigarette:: Prince .inc ( ) , animaux : Animaux:: PoissonRouge .inc ( ) }
} ,
Maison { couleur : Couleur:: Bleue ,
nationalite : Nationalite:: Allemand ,
boisson : Boisson:: Eau ,
cigarette : Cigarette:: Prince ,
animaux : e
} =>
{
Maison{ couleur : Couleur:: Bleue .inc ( ) , nationalite : Nationalite:: Allemand .inc ( ) , boisson : Boisson:: Eau .inc ( ) , cigarette : Cigarette:: Prince .inc ( ) , animaux : e.inc ( ) }
} ,
Maison { couleur : Couleur:: Bleue ,
nationalite : Nationalite:: Allemand ,
boisson : Boisson:: Eau ,
cigarette : d,
animaux : e
} =>
{
Maison{ couleur : Couleur:: Bleue .inc ( ) , nationalite : Nationalite:: Allemand .inc ( ) , boisson : Boisson:: Eau .inc ( ) , cigarette : d.inc ( ) , animaux : e}
} ,
Maison { couleur : Couleur:: Bleue ,
nationalite : Nationalite:: Allemand ,
boisson : c,
cigarette : d,
animaux : e
} =>
{
Maison{ couleur : Couleur:: Bleue .inc ( ) , nationalite : Nationalite:: Allemand .inc ( ) , boisson : c.inc ( ) , cigarette : d, animaux : e}
} ,
Maison { couleur : Couleur:: Bleue ,
nationalite : b,
boisson : c,
cigarette : d,
animaux : e
} =>
{
Maison{ couleur : Couleur:: Bleue .inc ( ) , nationalite : b.inc ( ) , boisson : c, cigarette : d, animaux : e}
} ,
Maison { couleur : a,
nationalite : b,
boisson : c,
cigarette : d,
animaux : e
} =>
{
Maison{ couleur : a.inc ( ) , nationalite : b, boisson : c, cigarette : d, animaux : e}
}
}
} // fn inc maison
} // impl Maison
fn origin( ) - > Maison{
let m= Maison { couleur : Couleur:: Rouge , nationalite : Nationalite:: Anglais , boisson : Boisson:: The , cigarette : Cigarette:: PallMall , animaux : Animaux:: Chien } ;
m
}
/*impl Iterator for Maison {
type Item = Maison;
fn next(&mut self) -> Option<Maison> {
let n=(*self).inc();
Some(n)
}
}*/
#[derive(Debug)]
struct HypotheseVector( Vec< Maison> ,Vec< Maison> ,Vec< Maison> ,Vec< Maison> ,Vec< Maison> ) ;
fn full_possibility( ) - > HypotheseVector{
let mut r= HypotheseVector( Vec:: new ( ) ,Vec:: new ( ) ,Vec:: new ( ) ,Vec:: new ( ) ,Vec:: new ( ) ) ;
let mut o= origin( ) ;
let nb_boucle= 5 * 5 * 5 * 5 * 5 ;
for _ in 0 ..nb_boucle {
//println!("> {:?}", o);
match r{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
a.push ( o.clone ( ) ) ;
b.push ( o.clone ( ) ) ;
c.push ( o.clone ( ) ) ;
d.push ( o.clone ( ) ) ;
e.push ( o.clone ( ) ) ;
}
}
o= o.inc ( ) ;
}
r
}
//1. L'Anglais vit dans la maison rouge.
fn r1_anglais_rouge< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : Couleur:: Rouge , nationalite : Nationalite:: Anglais , boisson : _, cigarette : _, animaux : _} => true ,
Maison { couleur : _, nationalite : Nationalite:: Anglais , boisson : _, cigarette : _, animaux : _} => false ,
Maison { couleur : Couleur:: Rouge , nationalite : _, boisson : _, cigarette : _, animaux : _} => false ,
_ => true
}
}
//2. Le Suédois élève des chiens.
fn r2_suedois_chien< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _, nationalite : Nationalite:: Suedois , boisson : _, cigarette : _, animaux : Animaux:: Chien } => true ,
Maison { couleur : _, nationalite : Nationalite:: Suedois , boisson : _, cigarette : _, animaux : _} => false ,
Maison { couleur : _, nationalite : _, boisson : _, cigarette : _, animaux : Animaux:: Chien } => false ,
_ => true
}
}
//3. Le Danois boit du thé.
fn r3_danois_the< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _, nationalite : Nationalite:: Danois , boisson : Boisson:: The , cigarette : _, animaux : _} => true ,
Maison { couleur : _, nationalite : Nationalite:: Danois , boisson : _, cigarette : _, animaux : _} => false ,
Maison { couleur : _, nationalite : _, boisson : Boisson:: The , cigarette : _, animaux : _} => false ,
_ => true
}
}
//5. Le propriétaire de la maison verte boit du café.
fn r5_verte_cafe< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : Couleur:: Verte , nationalite : _, boisson : Boisson:: Cafe , cigarette : _, animaux : _} => true ,
Maison { couleur : _, nationalite : _, boisson : Boisson:: Cafe , cigarette : _, animaux : _} => false ,
Maison { couleur : Couleur:: Verte , nationalite : _, boisson : _, cigarette : _, animaux : _} => false ,
_ => true
}
}
//6. Le fumeur de Pall Mall élève des oiseaux.
fn r6_pallmall_oiseau< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _, nationalite : _, boisson : _, cigarette : Cigarette:: PallMall , animaux : Animaux:: Oiseaux } => true ,
Maison { couleur : _, nationalite : _, boisson : _, cigarette : _, animaux : Animaux:: Oiseaux } => false ,
Maison { couleur : _, nationalite : _, boisson : _, cigarette : Cigarette:: PallMall , animaux : _} => false ,
_ => true
}
}
//7. Le propriétaire de la maison jaune fume des Dunhills.
fn r7_jaune_dunhills< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : Couleur:: Jaune , nationalite : _, boisson : _, cigarette : Cigarette:: Dunhills , animaux : _} => true ,
Maison { couleur : Couleur:: Jaune , nationalite : _, boisson : _, cigarette : _, animaux : _} => false ,
Maison { couleur : _, nationalite : _, boisson : _, cigarette : Cigarette:: Dunhills , animaux : _} => false ,
_ => true
}
}
//12. L'homme qui fume des Blue Masters boit de la bière.
fn r12_bluemaster_biere< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _ , nationalite : _ , boisson : Boisson:: Biere , cigarette : Cigarette:: BleueMasters , animaux : _} => true ,
Maison { couleur : _ , nationalite : _ , boisson : Boisson:: Biere , cigarette : _ , animaux : _} => false ,
Maison { couleur : _ , nationalite : _ , boisson : _ , cigarette : Cigarette:: BleueMasters , animaux : _} => false ,
_ => true
}
}
//13. L'Allemand fume des Prince.
fn r13_allemand_prince< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _ , nationalite : Nationalite:: Allemand , boisson : _ , cigarette : Cigarette:: Prince , animaux : _} => true ,
Maison { couleur : _ , nationalite : Nationalite:: Allemand , boisson : _ , cigarette : _ , animaux : _} => false ,
Maison { couleur : _ , nationalite : _ , boisson : _ , cigarette : Cigarette:: Prince , animaux : _} => false ,
_ => true
}
}
//1. L'Anglais vit dans la maison rouge.
//2. Le Suédois élève des chiens.
//3. Le Danois boit du thé.
//5. Le propriétaire de la maison verte boit du café.
//6. Le fumeur de Pall Mall élève des oiseaux.
//7. Le propriétaire de la maison jaune fume des Dunhills.
//12. L'homme qui fume des Blue Masters boit de la bière.
//13. L'Allemand fume des Prince.
//4. La maison verte est juste à gauche de la maison blanche.
//8. L'homme qui vit dans la maison du centre boit du lait.
//9. Le Norvégien vit dans la première maison.
//10. L'homme qui fume des Blends vit à côté de celui qui élève des chats.
//11. L'homme qui élève des chevaux vit à côté du fumeur de Dunhills.
//14. Le Norvégien vit à côté de la maison bleue.
//15. L'homme qui fume des Blends a un voisin qui boit de l'eau.
fn has_a_norvegien< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _ , nationalite : Nationalite:: Norvegien , boisson : _ , cigarette : _ , animaux : _ } => true ,
_ => false
}
}
fn has_lait< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : _ , nationalite : _ , boisson : Boisson:: Lait , cigarette : _ , animaux : _ } => true ,
_ => false
}
}
fn has_bleue< 'r> (input : &' r Maison ) - > bool {
match * input{
Maison { couleur : Couleur:: Bleue , nationalite : _ , boisson : _ , cigarette : _ , animaux : _ } => true ,
_ => false
}
}
fn has_couleur< 'r> (input : &' r Maison, coul : Couleur ) - > bool {
match * input{
Maison { couleur : ref x , nationalite : _ , boisson : _ , cigarette : _ , animaux : _ } => coul== * x
}
}
fn has_nationalite< 'r> (input : &' r Maison, coul : Nationalite ) - > bool {
match * input{
Maison { couleur : _ , nationalite : ref x , boisson : _ , cigarette : _ , animaux : _ } => coul== * x
}
}
fn has_boisson< 'r> (input : &' r Maison, coul : Boisson ) - > bool {
match * input{
Maison { couleur : _ , nationalite : _ , boisson : ref x , cigarette : _ , animaux : _ } => coul== * x
}
}
fn has_cigarette< 'r> (input : &' r Maison, coul : Cigarette ) - > bool {
match * input{
Maison { couleur : _ , nationalite : _ , boisson : _ , cigarette : ref x , animaux : _ } => coul== * x
}
}
fn has_animaux< 'r> (input : &' r Maison, coul : Animaux ) - > bool {
match * input{
Maison { couleur : _ , nationalite : _ , boisson : _ , cigarette : _ , animaux : ref x } => coul== * x
}
}
fn vec_has< F> ( v : & Vec< Maison> ,rule : F) - > bool
where F: Fn( & Maison) - > bool {
for f in v.iter ( ) {
if rule( & f) { return true }
}
false
}
fn vec_string( v : & Vec< Maison> ) - > String{
let mut r= String:: new ( ) ;
for f in v.iter ( ) {
let ot= format! ( "{:?}\n " ,f) ;
r.push_str ( & ot) ;
}
r
}
impl fmt:: Display for HypotheseVector {
fn fmt( & self, f: & mut fmt:: Formatter ) - > fmt:: Result {
match * self{
HypotheseVector( ref a,ref b,ref c,ref d,ref e) => {
write! ( f,"\n ++++++Maison 1++++++\n {}\n ++++++Maison 2++++++\n {}\n ++++++Maison 3++++++\n {}\n ++++++Maison 4++++++\n {}\n ++++++Maison 5++++++\n {}" ,vec_string( a) ,vec_string ( b) ,vec_string ( c) ,vec_string ( d) , vec_string ( e) )
}
}
}
}
impl HypotheseVector{
fn count_determinant ( & mut self ) - > usize{
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
a.len ( ) + b.len ( ) + c.len ( ) + d.len ( ) + e.len ( )
}
}
}
fn constraint_voisin_keep_unique_as_single< F> ( & mut self,rule1 : F)
where F: Fn( & Maison) - > bool {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
let ba= vec_has( & a,| x: & Maison| rule1( x) ) ;
let bb= vec_has( & b,| x: & Maison| rule1( x) ) ;
let bc= vec_has( & c,| x: & Maison| rule1( x) ) ;
let bd= vec_has( & d,| x: & Maison| rule1( x) ) ;
let be= vec_has( & e,| x: & Maison| rule1( x) ) ;
let the_one= match ( ba,bb,bc,bd,be) {
( true ,false ,false ,false ,false ) => Some( a) ,
( false ,true ,false ,false ,false ) => Some( b) ,
( false ,false ,true ,false ,false ) => Some( c) ,
( false ,false ,false ,true ,false ) => Some( d) ,
( false ,false ,false ,false ,true ) => Some( e) ,
_ => None
} ;
match the_one{
Some( k) => {
k.retain ( | x: & Maison| rule1( x) ) ; }
None=> { }
}
}
}
}
fn constraint_voisin_keep_not_in_or_voisin_in< F,G> ( & mut self,rule1 : F,rule2 : G)
where F: Fn( & Maison) - > bool , G: Fn( & Maison) - > bool {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
let ba= vec_has( & a,| x: & Maison| rule1( x) ) ;
let bb= vec_has( & b,| x: & Maison| rule1( x) ) ;
let bc= vec_has( & c,| x: & Maison| rule1( x) ) ;
let bd= vec_has( & d,| x: & Maison| rule1( x) ) ;
let be= vec_has( & e,| x: & Maison| rule1( x) ) ;
a.retain ( | x: & Maison| ! rule2( x) || bb) ;
b.retain ( | x: & Maison| ! rule2( x) || ba || bc) ;
c.retain ( | x: & Maison| ! rule2( x) || bb || bd) ;
d.retain ( | x: & Maison| ! rule2( x) || bc || be) ;
e.retain ( | x: & Maison| ! rule2( x) || bd ) ;
}
}
}
fn constraint_voisin_gauche_droite< F,G> ( & mut self,rule1 : F,rule2 : G)
where F: Fn( & Maison) - > bool , G: Fn( & Maison) - > bool {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
let ba= vec_has( & a,| x: & Maison| rule1( x) ) ;
let bb= vec_has( & b,| x: & Maison| rule1( x) ) ;
let bc= vec_has( & c,| x: & Maison| rule1( x) ) ;
let bd= vec_has( & d,| x: & Maison| rule1( x) ) ;
//let be=vec_has(&e,|x: &Maison| rule1(x));
a.retain ( | x: & Maison| ! rule2( x) ) ;
b.retain ( | x: & Maison| ! rule2( x) || ba) ;
c.retain ( | x: & Maison| ! rule2( x) || bb) ;
d.retain ( | x: & Maison| ! rule2( x) || bc) ;
e.retain ( | x: & Maison| ! rule2( x) || bd ) ;
//let da=vec_has(&a,|x: &Maison| rule2(x));
let db= vec_has( & b,| x: & Maison| rule2( x) ) ;
let dc= vec_has( & c,| x: & Maison| rule2( x) ) ;
let dd= vec_has( & d,| x: & Maison| rule2( x) ) ;
let de= vec_has( & e,| x: & Maison| rule2( x) ) ;
a.retain ( | x: & Maison| ! rule1( x) || db) ;
b.retain ( | x: & Maison| ! rule1( x) || dc) ;
c.retain ( | x: & Maison| ! rule1( x) || dd) ;
d.retain ( | x: & Maison| ! rule1( x) || de) ;
e.retain ( | x: & Maison| ! rule1( x) ) ;
}
}
}
fn constraint_voisin< F,G> ( & mut self,rule1 : F,rule2 : G)
where F: Fn( & Maison) - > bool , G: Fn( & Maison) - > bool {
self.constraint_voisin_keep_not_in_or_voisin_in ( | x: & Maison| rule1( x) ,| x: & Maison| rule2( x) ) ;
self.constraint_voisin_keep_not_in_or_voisin_in ( | x: & Maison| rule2( x) ,| x: & Maison| rule1( x) ) ;
}
//4. La maison verte est juste à gauche de la maison blanche.
//8. L'homme qui vit dans la maison du centre boit du lait.
//9. Le Norvégien vit dans la première maison.
//10. L'homme qui fume des Blends vit à côté de celui qui élève des chats.
//11. L'homme qui élève des chevaux vit à côté du fumeur de Dunhills.
//14. Le Norvégien vit à côté de la maison bleue.
//15. L'homme qui fume des Blends a un voisin qui boit de l'eau.
//4. La maison verte est juste à gauche de la maison blanche.
fn r4_maison_verte_gauche_blanche< 'cl, ' a> ( & mut self ) - > ( ) {
self.constraint_voisin_gauche_droite ( | x: & Maison| has_couleur( x,Couleur:: Verte ) ,| x: & Maison| has_couleur( x,Couleur:: Blanche ) ) ;
}
//8. L'homme qui vit dans la maison du centre boit du lait.
fn r8_centre_lait< 'cl, ' a> ( & mut self ) - > ( ) {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
a.retain ( | x: & Maison| ! has_lait( x) ) ;
b.retain ( | x: & Maison| ! has_lait( x) ) ;
c.retain ( | x: & Maison| has_lait( x) ) ;
d.retain ( | x: & Maison| ! has_lait( x) ) ;
e.retain ( | x: & Maison| ! has_lait( x) ) ;
}
}
}
//9. Le Norvégien vit dans la première maison.
fn r9_norvegien_premiere< 'cl, ' a> ( & mut self ) - > ( ) {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
a.retain ( | x: & Maison| has_a_norvegien( x) ) ;
b.retain ( | x: & Maison| ! has_a_norvegien( x) ) ;
c.retain ( | x: & Maison| ! has_a_norvegien( x) ) ;
d.retain ( | x: & Maison| ! has_a_norvegien( x) ) ;
e.retain ( | x: & Maison| ! has_a_norvegien( x) ) ;
}
}
}
//10. L'homme qui fume des Blends vit à côté de celui qui élève des chats.
fn r10_blends_voisin_chats< 'cl, ' a> ( & mut self ) - > ( ) {
self.constraint_voisin ( | x: & Maison| has_cigarette( x,Cigarette:: Blends ) ,| x: & Maison| has_animaux( x,Animaux:: Chats ) ) ;
}
//11. L'homme qui élève des chevaux vit à côté du fumeur de Dunhills.
fn r11_chevaux_voisin_dunhills< 'cl, ' a> ( & mut self ) - > ( ) {
self.constraint_voisin ( | x: & Maison| has_cigarette( x,Cigarette:: Dunhills ) ,| x: & Maison| has_animaux( x,Animaux:: Chevaux ) ) ;
}
//14. Le Norvégien vit à côté de la maison bleue.
fn r14_norvegien_cote_maison_bleue< 'cl, ' a> ( & mut self ) - > ( ) {
self.constraint_voisin ( | x: & Maison| has_a_norvegien( x) ,| x: & Maison| has_bleue( x) ) ;
}
//15. L'homme qui fume des Blends a un voisin qui boit de l'eau.
fn r15_blend_voisin_eau< 'cl, ' a> ( & mut self ) - > ( ) {
self.constraint_voisin ( | x: & Maison| has_cigarette( x,Cigarette:: Blends ) ,| x: & Maison| has_boisson( x,Boisson:: Eau ) ) ;
}
fn apply< F> ( & mut self,rule : F)
where F: Fn( & Maison) - > bool {
match * self{
HypotheseVector( ref mut a,ref mut b,ref mut c,ref mut d,ref mut e) => {
a.retain ( | x: & Maison| rule( x) ) ;
b.retain ( | x: & Maison| rule( x) ) ;
c.retain ( | x: & Maison| rule( x) ) ;
d.retain ( | x: & Maison| rule( x) ) ;
e.retain ( | x: & Maison| rule( x) ) ;
}
}
}
fn simple_constraints( & mut self) {
self.apply ( r1_anglais_rouge) ;
self.apply ( r2_suedois_chien) ;
self.apply ( r3_danois_the) ;
self.apply ( r5_verte_cafe) ;
self.apply ( r6_pallmall_oiseau) ;
self.apply ( r7_jaune_dunhills) ;
self.apply ( r12_bluemaster_biere) ;
self.apply ( r13_allemand_prince) ;
}
fn other_constraintes( & mut self) {
self.r4_maison_verte_gauche_blanche ( ) ;
self.r8_centre_lait ( ) ;
self.r9_norvegien_premiere ( ) ;
self.r10_blends_voisin_chats ( ) ;
self.r11_chevaux_voisin_dunhills ( ) ;
self.r14_norvegien_cote_maison_bleue ( ) ;
self.r15_blend_voisin_eau ( ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_couleur( x,Couleur:: Verte ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_couleur( x,Couleur:: Blanche ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_couleur( x,Couleur:: Jaune ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_couleur( x,Couleur:: Bleue ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_couleur( x,Couleur:: Rouge ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_nationalite( x,Nationalite:: Suedois ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_nationalite( x,Nationalite:: Danois ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_nationalite( x,Nationalite:: Anglais ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_nationalite( x,Nationalite:: Norvegien ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_nationalite( x,Nationalite:: Allemand ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_boisson( x,Boisson:: Eau ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_boisson( x,Boisson:: The ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_boisson( x,Boisson:: Cafe ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_boisson( x,Boisson:: Biere ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_boisson( x,Boisson:: Lait ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_cigarette( x,Cigarette:: Dunhills ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_cigarette( x,Cigarette:: PallMall ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_cigarette( x,Cigarette:: Blends ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_cigarette( x,Cigarette:: BleueMasters ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_cigarette( x,Cigarette:: Prince ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_animaux( x,Animaux:: Oiseaux ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_animaux( x,Animaux:: Chien ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_animaux( x,Animaux:: Chevaux ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_animaux( x,Animaux:: Chats ) ) ;
self.constraint_voisin_keep_unique_as_single ( | x: & Maison| has_animaux( x,Animaux:: PoissonRouge ) ) ;
}
}
pub fn main( ) - > ( ) {
println! ( "Einstein enigma program" ) ;
let mut h= full_possibility( ) ;
println! ( "> determinant de base : {} " ,h.count_determinant ( ) ) ;
h.simple_constraints ( ) ;
//println!("> {}", h);
//println!("> determinant apres contraintes simples : {} ",h.count_determinant());
let mut count_apply= 0 ;
loop{
count_apply= count_apply+ 1 ;
let prev_det= h.count_determinant ( ) ;
//println!("-------------------------------");
//println!("-------------------------------");
//println!("-------------------------------");
//println!("-------------------------------");
//println!("-------------------------------");
h.other_constraintes ( ) ;
//println!("{}", h);
println! ( "determinant : {} : apres {} application des regles " ,h.count_determinant ( ) , count_apply) ;
if prev_det== h.count_determinant ( ) { break ; }
}
println! ( "------------ FIN DU PROGRAMME -----------" ) ;
println! ( "determinant : {} : apres {} application des regles " ,h.count_determinant ( ) , count_apply) ;
println! ( "{}" , h) ;
}
dXNlIHN0ZDo6Zm10OwoKCiNbZGVyaXZlKCBQYXJ0aWFsRXEsRXEsRGVidWcsQ2xvbmUpXQplbnVtIENvdWxldXJ7CglSb3VnZSwKCVZlcnRlLAoJQmxhbmNoZSwKCUphdW5lLAoJQmxldWUKfQppbXBsIENvdWxldXJ7CglmbiBpbmMoc2VsZikgLT4gQ291bGV1cnsKCQkgICAgbWF0Y2ggc2VsZnsKCgkgICAgCUNvdWxldXI6OlJvdWdlID0+e2xldCByPUNvdWxldXI6OlZlcnRlOyAKCSAgICAJcn0sCgkgICAgCUNvdWxldXI6OlZlcnRlID0+e2xldCByPUNvdWxldXI6OkJsYW5jaGU7CgkgICAgCSByfSwKCSAgICAJQ291bGV1cjo6QmxhbmNoZSA9PntsZXQgcj1Db3VsZXVyOjpKYXVuZTsgCgkgICAgCXJ9LAoJICAgIAlDb3VsZXVyOjpKYXVuZSA9PntsZXQgcj1Db3VsZXVyOjpCbGV1ZTsKCSAgICAJIHJ9LAoJICAgIAlDb3VsZXVyOjpCbGV1ZSA9PkNvdWxldXI6OlJvdWdlCgkgICAgfQoJfQp9CgojW2Rlcml2ZSggUGFydGlhbEVxLEVxLERlYnVnLENsb25lKV0KZW51bSBOYXRpb25hbGl0ZXsKCUFuZ2xhaXMsCglTdWVkb2lzLAoJRGFub2lzLAoJTm9ydmVnaWVuLAoJQWxsZW1hbmQKfQppbXBsIE5hdGlvbmFsaXRlewoJZm4gaW5jKHNlbGYpIC0+IE5hdGlvbmFsaXRlewoJCSAgICBtYXRjaCBzZWxmewoKCSAgICAJTmF0aW9uYWxpdGU6OkFuZ2xhaXMgPT57bGV0IHI9TmF0aW9uYWxpdGU6OlN1ZWRvaXM7IAoJICAgIAlyfSwKCSAgICAJTmF0aW9uYWxpdGU6OlN1ZWRvaXMgPT57bGV0IHI9TmF0aW9uYWxpdGU6OkRhbm9pczsKCSAgICAJIHJ9LAoJICAgIAlOYXRpb25hbGl0ZTo6RGFub2lzID0+e2xldCByPU5hdGlvbmFsaXRlOjpOb3J2ZWdpZW47IAoJICAgIAlyfSwKCSAgICAJTmF0aW9uYWxpdGU6Ok5vcnZlZ2llbiA9PntsZXQgcj1OYXRpb25hbGl0ZTo6QWxsZW1hbmQ7CgkgICAgCSByfSwKCSAgICAJTmF0aW9uYWxpdGU6OkFsbGVtYW5kID0+TmF0aW9uYWxpdGU6OkFuZ2xhaXMKCSAgICB9Cgl9Cn0KCiNbZGVyaXZlKCBQYXJ0aWFsRXEsRXEsRGVidWcsQ2xvbmUpXQplbnVtIEJvaXNzb257CglUaGUsCglDYWZlLAoJTGFpdCwKCUJpZXJlLAoJRWF1Cn0KCmltcGwgQm9pc3NvbnsKCWZuIGluYyhzZWxmKSAtPiBCb2lzc29uewoJCSAgICBtYXRjaCBzZWxmewoKCSAgICAJQm9pc3Nvbjo6VGhlID0+e2xldCByPUJvaXNzb246OkNhZmU7IAoJICAgIAlyfSwKCSAgICAJQm9pc3Nvbjo6Q2FmZSA9PntsZXQgcj1Cb2lzc29uOjpMYWl0OwoJICAgIAkgcn0sCgkgICAgCUJvaXNzb246OkxhaXQgPT57bGV0IHI9Qm9pc3Nvbjo6QmllcmU7IAoJICAgIAlyfSwKCSAgICAJQm9pc3Nvbjo6QmllcmUgPT57bGV0IHI9Qm9pc3Nvbjo6RWF1OwoJICAgIAkgcn0sCgkgICAgCUJvaXNzb246OkVhdSA9PkJvaXNzb246OlRoZQoJICAgIH0KCX0KfQoKI1tkZXJpdmUoIFBhcnRpYWxFcSxFcSxEZWJ1ZyxDbG9uZSldCmVudW0gQ2lnYXJldHRlewoJUGFsbE1hbGwsCglEdW5oaWxscywKCUJsZW5kcywKCUJsZXVlTWFzdGVycywKCVByaW5jZSwKfQppbXBsIENpZ2FyZXR0ZXsKCWZuIGluYyhzZWxmKSAtPiBDaWdhcmV0dGV7CgkJICAgIG1hdGNoIHNlbGZ7CgoJICAgIAlDaWdhcmV0dGU6OlBhbGxNYWxsID0+e2xldCByPUNpZ2FyZXR0ZTo6RHVuaGlsbHM7IAoJICAgIAlyfSwKCSAgICAJQ2lnYXJldHRlOjpEdW5oaWxscyA9PntsZXQgcj1DaWdhcmV0dGU6OkJsZW5kczsKCSAgICAJIHJ9LAoJICAgIAlDaWdhcmV0dGU6OkJsZW5kcyA9PntsZXQgcj1DaWdhcmV0dGU6OkJsZXVlTWFzdGVyczsgCgkgICAgCXJ9LAoJICAgIAlDaWdhcmV0dGU6OkJsZXVlTWFzdGVycyA9PntsZXQgcj1DaWdhcmV0dGU6OlByaW5jZTsKCSAgICAJIHJ9LAoJICAgIAlDaWdhcmV0dGU6OlByaW5jZSA9PkNpZ2FyZXR0ZTo6UGFsbE1hbGwKCSAgICB9Cgl9Cn0KCiNbZGVyaXZlKCBQYXJ0aWFsRXEsRXEsRGVidWcsQ2xvbmUpXQplbnVtIEFuaW1hdXh7CglDaGllbiwKCU9pc2VhdXgsCglDaGF0cywKCUNoZXZhdXgsCglQb2lzc29uUm91Z2UKfQppbXBsIEFuaW1hdXh7CglmbiBpbmMoc2VsZikgLT4gQW5pbWF1eHsKCQkgICAgbWF0Y2ggc2VsZnsKCgkgICAgCUFuaW1hdXg6OkNoaWVuID0+e2xldCByPUFuaW1hdXg6Ok9pc2VhdXg7IAoJICAgIAlyfSwKCSAgICAJQW5pbWF1eDo6T2lzZWF1eCA9PntsZXQgcj1BbmltYXV4OjpDaGF0czsKCSAgICAJIHJ9LAoJICAgIAlBbmltYXV4OjpDaGF0cyA9PntsZXQgcj1BbmltYXV4OjpDaGV2YXV4OyAKCSAgICAJcn0sCgkgICAgCUFuaW1hdXg6OkNoZXZhdXggPT57bGV0IHI9QW5pbWF1eDo6UG9pc3NvblJvdWdlOwoJICAgIAkgcn0sCgkgICAgCUFuaW1hdXg6OlBvaXNzb25Sb3VnZSA9PkFuaW1hdXg6OkNoaWVuCgkgICAgfQoJfQp9CgojW2Rlcml2ZShEZWJ1ZyxDbG9uZSldCnN0cnVjdCBNYWlzb257Cgljb3VsZXVyIDogQ291bGV1ciwKCW5hdGlvbmFsaXRlIDogTmF0aW9uYWxpdGUsCglib2lzc29uIDogQm9pc3NvbiwKCWNpZ2FyZXR0ZSA6IENpZ2FyZXR0ZSwKCWFuaW1hdXggOiBBbmltYXV4Cn0KCgoKCmltcGwgTWFpc29uewoKCglmbiBpbmMoc2VsZikgLT4gTWFpc29uewoJCgoJCSAgICBtYXRjaCBzZWxmewoKCgkJICAgIAlNYWlzb24ge2NvdWxldXIgOiBDb3VsZXVyOjpCbGV1ZSwKCQkgICAgCSBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZCwKCQkgICAgCSAgYm9pc3NvbiA6IEJvaXNzb246OkVhdSwKCQkgICAgCSAgIGNpZ2FyZXR0ZSA6IENpZ2FyZXR0ZTo6UHJpbmNlLAoJCSAgICAJICAgIGFuaW1hdXggOiBBbmltYXV4OjpQb2lzc29uUm91Z2UKCQkgICAgCSAgICB9ID0+CgkJICAgIAl7CgkJICAgIAkgCU1haXNvbntjb3VsZXVyIDogQ291bGV1cjo6QmxldWUuaW5jKCksIG5hdGlvbmFsaXRlIDogTmF0aW9uYWxpdGU6OkFsbGVtYW5kLmluYygpLCBib2lzc29uIDogQm9pc3Nvbjo6RWF1LmluYygpLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OlByaW5jZS5pbmMoKSwgYW5pbWF1eCA6IEFuaW1hdXg6OlBvaXNzb25Sb3VnZS5pbmMoKX0KCQkgICAgCSB9LAkKCgkJICAgIAlNYWlzb24ge2NvdWxldXIgOiBDb3VsZXVyOjpCbGV1ZSwKCQkgICAgCSBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZCwKCQkgICAgCSAgYm9pc3NvbiA6IEJvaXNzb246OkVhdSwKCQkgICAgCSAgIGNpZ2FyZXR0ZSA6IENpZ2FyZXR0ZTo6UHJpbmNlLAoJCSAgICAJICAgIGFuaW1hdXggOiBlCgkJICAgIAkgICAgfSA9PgoJCSAgICAJewoJCSAgICAJIAlNYWlzb257Y291bGV1ciA6IENvdWxldXI6OkJsZXVlLmluYygpLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZC5pbmMoKSwgYm9pc3NvbiA6IEJvaXNzb246OkVhdS5pbmMoKSwgY2lnYXJldHRlIDogQ2lnYXJldHRlOjpQcmluY2UuaW5jKCksIGFuaW1hdXggOiBlLmluYygpfQoJCSAgICAJIH0sCQkKCgoJCSAgICAJTWFpc29uIHtjb3VsZXVyIDogQ291bGV1cjo6QmxldWUsCgkJICAgIAkgbmF0aW9uYWxpdGUgOiBOYXRpb25hbGl0ZTo6QWxsZW1hbmQsCgkJICAgIAkgIGJvaXNzb24gOiBCb2lzc29uOjpFYXUsCgkJICAgIAkgICBjaWdhcmV0dGUgOiBkLAoJCSAgICAJICAgIGFuaW1hdXggOiBlCgkJICAgIAkgICAgfSA9PgoJCSAgICAJewoJCSAgICAJIAlNYWlzb257Y291bGV1ciA6IENvdWxldXI6OkJsZXVlLmluYygpLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZC5pbmMoKSwgYm9pc3NvbiA6IEJvaXNzb246OkVhdS5pbmMoKSwgY2lnYXJldHRlIDogZC5pbmMoKSwgYW5pbWF1eCA6IGV9CgkJICAgIAkgfSwJCSAgICAKCgkJICAgIAlNYWlzb24ge2NvdWxldXIgOiBDb3VsZXVyOjpCbGV1ZSwKCQkgICAgCSBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZCwKCQkgICAgCSAgYm9pc3NvbiA6IGMsCgkJICAgIAkgICBjaWdhcmV0dGUgOiBkLAoJCSAgICAJICAgIGFuaW1hdXggOiBlCgkJICAgIAkgICAgfSA9PgoJCSAgICAJewoJCSAgICAJIAlNYWlzb257Y291bGV1ciA6IENvdWxldXI6OkJsZXVlLmluYygpLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZC5pbmMoKSwgYm9pc3NvbiA6IGMuaW5jKCksIGNpZ2FyZXR0ZSA6IGQsIGFuaW1hdXggOiBlfQoJCSAgICAJIH0sCgoJCSAgICAJTWFpc29uIHtjb3VsZXVyIDogQ291bGV1cjo6QmxldWUsCgkJICAgIAkgbmF0aW9uYWxpdGUgOiBiLAoJCSAgICAJICBib2lzc29uIDogYywKCQkgICAgCSAgIGNpZ2FyZXR0ZSA6IGQsCgkJICAgIAkgICAgYW5pbWF1eCA6IGUKCQkgICAgCSAgICB9ID0+CgkJICAgIAl7CgkJICAgIAkgCU1haXNvbntjb3VsZXVyIDogQ291bGV1cjo6QmxldWUuaW5jKCksIG5hdGlvbmFsaXRlIDogYi5pbmMoKSwgYm9pc3NvbiA6IGMsIGNpZ2FyZXR0ZSA6IGQsIGFuaW1hdXggOiBlfQoJCSAgICAJIH0sCgkJICAgIAkgCgoJCSAgICAJTWFpc29uIHtjb3VsZXVyIDogYSwKCQkgICAgCSBuYXRpb25hbGl0ZSA6IGIsCgkJICAgIAkgIGJvaXNzb24gOiBjLAoJCSAgICAJICAgY2lnYXJldHRlIDogZCwKCQkgICAgCSAgICBhbmltYXV4IDogZQoJCSAgICAJICAgIH0gPT4KCQkgICAgCXsKCQkgICAgCSAJTWFpc29ue2NvdWxldXIgOiBhLmluYygpLCBuYXRpb25hbGl0ZSA6IGIsIGJvaXNzb24gOiBjLCBjaWdhcmV0dGUgOiBkLCBhbmltYXV4IDogZX0KCQkgICAgCSB9CgkJICAgCgoJICAgIH0KCgkgICAgCgl9IC8vIGZuIGluYyBtYWlzb24KCn0JLy8gaW1wbCBNYWlzb24KCglmbiBvcmlnaW4oKSAtPiBNYWlzb257CglsZXQgbT0gTWFpc29uIHsgY291bGV1ciA6IENvdWxldXI6OlJvdWdlLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbmdsYWlzLCBib2lzc29uIDogQm9pc3Nvbjo6VGhlLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OlBhbGxNYWxsLCBhbmltYXV4IDogQW5pbWF1eDo6Q2hpZW4gfTsKCW0KCX0KCi8qaW1wbCBJdGVyYXRvciBmb3IgTWFpc29uIHsKdHlwZSBJdGVtID0gTWFpc29uOwogICAgZm4gbmV4dCgmbXV0IHNlbGYpIC0+IE9wdGlvbjxNYWlzb24+IHsKICAgICAgICBsZXQgbj0oKnNlbGYpLmluYygpOwogICAgICAgIFNvbWUobikKICAgIH0KfSovCQoKI1tkZXJpdmUoRGVidWcpXQpzdHJ1Y3QgSHlwb3RoZXNlVmVjdG9yKFZlYzxNYWlzb24+LFZlYzxNYWlzb24+LFZlYzxNYWlzb24+LFZlYzxNYWlzb24+LFZlYzxNYWlzb24+KTsKCgpmbiBmdWxsX3Bvc3NpYmlsaXR5KCkgLT4gSHlwb3RoZXNlVmVjdG9yewoJbGV0IG11dCByPUh5cG90aGVzZVZlY3RvcihWZWM6Om5ldygpLFZlYzo6bmV3KCksVmVjOjpuZXcoKSxWZWM6Om5ldygpLFZlYzo6bmV3KCkpOwoKCWxldCBtdXQgbz1vcmlnaW4oKSA7CglsZXQgbmJfYm91Y2xlPTUqNSo1KjUqNSA7Cglmb3IgXyBpbiAwLi5uYl9ib3VjbGV7CgkJLy9wcmludGxuISgiPiB7Oj99Iiwgbyk7CgkJbWF0Y2ggcnsKCQkJSHlwb3RoZXNlVmVjdG9yKHJlZiBtdXQgYSxyZWYgbXV0IGIscmVmIG11dCBjLHJlZiBtdXQgZCxyZWYgbXV0IGUpID0+IHsKCQkJCWEucHVzaChvLmNsb25lKCkpOwoJCQkJYi5wdXNoKG8uY2xvbmUoKSk7CgkJCQljLnB1c2goby5jbG9uZSgpKTsKCQkJCWQucHVzaChvLmNsb25lKCkpOwoJCQkJZS5wdXNoKG8uY2xvbmUoKSk7CgoJCQl9CgoJCX0KCQlvPW8uaW5jKCk7CgoJfQoKCXIKfQoKLy8xLiBMJ0FuZ2xhaXMgdml0IGRhbnMgbGEgbWFpc29uIHJvdWdlLgoJCWZuIHIxX2FuZ2xhaXNfcm91Z2U8J3I+IChpbnB1dCA6ICYnciBNYWlzb24gKSAtPiBib29sIHsKCQkgICAgbWF0Y2ggKmlucHV0ewoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6IENvdWxldXI6OlJvdWdlLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbmdsYWlzLCBib2lzc29uIDogXywgY2lnYXJldHRlIDogXywgYW5pbWF1eCA6IF99ID0+ICB0cnVlLAoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6IF8sIG5hdGlvbmFsaXRlIDogTmF0aW9uYWxpdGU6OkFuZ2xhaXMsIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBfLCBhbmltYXV4IDogX30gPT4gZmFsc2UsCgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogQ291bGV1cjo6Um91Z2UsIG5hdGlvbmFsaXRlIDogXywgYm9pc3NvbiA6IF8sIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOiBffSA9PiAgZmFsc2UsCgkJICAgIAlfID0+ICB0cnVlCgoJCSAgICB9CgkJfQoKLy8yLiBMZSBTdcOpZG9pcyDDqWzDqHZlIGRlcyBjaGllbnMuCgkJZm4gcjJfc3VlZG9pc19jaGllbjwncj4gKGlucHV0IDogJidyIE1haXNvbiApIC0+IGJvb2wgewoJCSAgICBtYXRjaCAqaW5wdXR7CgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogXywgbmF0aW9uYWxpdGUgOiBOYXRpb25hbGl0ZTo6U3VlZG9pcywgYm9pc3NvbiA6IF8sIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOiBBbmltYXV4OjpDaGllbn0gPT4gIHRydWUsCgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogXywgbmF0aW9uYWxpdGUgOiBOYXRpb25hbGl0ZTo6U3VlZG9pcywgYm9pc3NvbiA6IF8sIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOl99ID0+ICBmYWxzZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IF8sIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBfLCBhbmltYXV4IDogQW5pbWF1eDo6Q2hpZW59ID0+ICBmYWxzZSwKCQkgICAgCV8gPT4gIHRydWUKCgkJICAgIH0KCQl9CQkKCi8vMy4gTGUgRGFub2lzIGJvaXQgZHUgdGjDqS4KCQlmbiByM19kYW5vaXNfdGhlPCdyPiAoaW5wdXQgOiAmJ3IgTWFpc29uICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpEYW5vaXMsIGJvaXNzb24gOiBCb2lzc29uOjpUaGUsIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOiBffSA9PiAgdHJ1ZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpEYW5vaXMsIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBfLCBhbmltYXV4IDogX30gPT4gIGZhbHNlLAoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6IF8sIG5hdGlvbmFsaXRlIDogXywgYm9pc3NvbiA6IEJvaXNzb246OlRoZSwgY2lnYXJldHRlIDogXywgYW5pbWF1eCA6IF99ID0+ICBmYWxzZSwKCQkgICAgCV8gPT4gIHRydWUKCgkJICAgIH0KCQl9CQkJCi8vNS4gTGUgcHJvcHJpw6l0YWlyZSBkZSBsYSBtYWlzb24gdmVydGUgYm9pdCBkdSBjYWbDqS4KCQlmbiByNV92ZXJ0ZV9jYWZlPCdyPiAoaW5wdXQgOiAmJ3IgTWFpc29uICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBDb3VsZXVyOjpWZXJ0ZSwgbmF0aW9uYWxpdGUgOiBfLCBib2lzc29uIDogQm9pc3Nvbjo6Q2FmZSwgY2lnYXJldHRlIDogXywgYW5pbWF1eCA6IF99ID0+ICB0cnVlLAoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6IF8sIG5hdGlvbmFsaXRlIDogXywgYm9pc3NvbiA6IEJvaXNzb246OkNhZmUsIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOiBffSA9PiAgZmFsc2UsCgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogQ291bGV1cjo6VmVydGUsIG5hdGlvbmFsaXRlIDogXywgYm9pc3NvbiA6IF8sIGNpZ2FyZXR0ZSA6IF8sIGFuaW1hdXggOiBffT0+ICBmYWxzZSwKCQkgICAgCV8gPT4gIHRydWUKCgkJICAgIH0KCQl9CQoKLy82LiBMZSBmdW1ldXIgZGUgUGFsbCBNYWxsIMOpbMOodmUgZGVzIG9pc2VhdXguCgkJZm4gcjZfcGFsbG1hbGxfb2lzZWF1PCdyPiAoaW5wdXQgOiAmJ3IgTWFpc29uICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IF8sIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OlBhbGxNYWxsLCBhbmltYXV4IDogQW5pbWF1eDo6T2lzZWF1eH0gPT4gIHRydWUsCgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogXywgbmF0aW9uYWxpdGUgOiBfLCBib2lzc29uIDogXywgY2lnYXJldHRlIDogXywgYW5pbWF1eCA6IEFuaW1hdXg6Ok9pc2VhdXh9ID0+ICBmYWxzZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IF8sIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OlBhbGxNYWxsLCBhbmltYXV4IDogX309PiAgZmFsc2UsCgkJICAgIAlfID0+ICB0cnVlCgoJCSAgICB9CgkJfQkJCgovLzcuIExlIHByb3ByacOpdGFpcmUgZGUgbGEgbWFpc29uIGphdW5lIGZ1bWUgZGVzIER1bmhpbGxzLiAKCQlmbiByN19qYXVuZV9kdW5oaWxsczwncj4gKGlucHV0IDogJidyIE1haXNvbiApIC0+IGJvb2wgewoJCSAgICBtYXRjaCAqaW5wdXR7CgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDogQ291bGV1cjo6SmF1bmUsIG5hdGlvbmFsaXRlIDogXywgYm9pc3NvbiA6IF8sIGNpZ2FyZXR0ZSA6IENpZ2FyZXR0ZTo6RHVuaGlsbHMsIGFuaW1hdXggOiBffSA9PiAgdHJ1ZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBDb3VsZXVyOjpKYXVuZSwgbmF0aW9uYWxpdGUgOiBfLCBib2lzc29uIDogXywgY2lnYXJldHRlIDogXywgYW5pbWF1eCA6IF99ID0+ICBmYWxzZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfLCBuYXRpb25hbGl0ZSA6IF8sIGJvaXNzb24gOiBfLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OkR1bmhpbGxzLCBhbmltYXV4IDogX309PiAgZmFsc2UsCgkJICAgIAlfID0+ICB0cnVlCgoJCSAgICB9CgkJfQkJCQkKCi8vMTIuIEwnaG9tbWUgcXVpIGZ1bWUgZGVzIEJsdWUgTWFzdGVycyBib2l0IGRlIGxhIGJpw6hyZS4JCQoJCWZuIHIxMl9ibHVlbWFzdGVyX2JpZXJlPCdyPiAoaW5wdXQgOiAmJ3IgTWFpc29uICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOl8gIAksIG5hdGlvbmFsaXRlIDogXyAJLCBib2lzc29uIDogQm9pc3Nvbjo6QmllcmUgCSwgY2lnYXJldHRlIDogQ2lnYXJldHRlOjpCbGV1ZU1hc3RlcnMJLCBhbmltYXV4IDogX30gPT4gIHRydWUsCgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDpfIAksIG5hdGlvbmFsaXRlIDogXyAJLCBib2lzc29uIDogQm9pc3Nvbjo6QmllcmUgCSwgY2lnYXJldHRlIDogXyAJCQkJCQksIGFuaW1hdXggOiBffSAgPT4gIGZhbHNlLAoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6XyAJLCBuYXRpb25hbGl0ZSA6IF8gCSwgYm9pc3NvbiA6IF8JCQkJLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OkJsZXVlTWFzdGVycyAJLCBhbmltYXV4IDogX30gPT4gIGZhbHNlLAoJCSAgICAJXyA9PiAgdHJ1ZQoKCQkgICAgfQoJCX0JCgovLzEzLiBMJ0FsbGVtYW5kIGZ1bWUgZGVzIFByaW5jZS4gCgkJZm4gcjEzX2FsbGVtYW5kX3ByaW5jZTwncj4gKGlucHV0IDogJidyIE1haXNvbiApIC0+IGJvb2wgewoJCSAgICBtYXRjaCAqaW5wdXR7CgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDpfICAJLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpBbGxlbWFuZCAJLCBib2lzc29uIDogXyAJLCBjaWdhcmV0dGUgOiBDaWdhcmV0dGU6OlByaW5jZQkJCQkJCSwgYW5pbWF1eCA6IF99ID0+ICB0cnVlLAoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6XyAgCSwgbmF0aW9uYWxpdGUgOiBOYXRpb25hbGl0ZTo6QWxsZW1hbmQgCSwgYm9pc3NvbiA6IF8gCSwgY2lnYXJldHRlIDogXwkJCQkJCQkJCQksIGFuaW1hdXggOiBffSAgID0+ICBmYWxzZSwKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOl8gIAksIG5hdGlvbmFsaXRlIDogXwkJCQkJIAksIGJvaXNzb24gOiBfIAksIGNpZ2FyZXR0ZSA6IENpZ2FyZXR0ZTo6UHJpbmNlCQkJCQkJLCBhbmltYXV4IDogX30gID0+ICBmYWxzZSwKCQkgICAgCV8gPT4gIHRydWUKCgkJICAgIH0KCQl9CQoKLy8xLiBMJ0FuZ2xhaXMgdml0IGRhbnMgbGEgbWFpc29uIHJvdWdlLgovLzIuIExlIFN1w6lkb2lzIMOpbMOodmUgZGVzIGNoaWVucy4KLy8zLiBMZSBEYW5vaXMgYm9pdCBkdSB0aMOpLgovLzUuIExlIHByb3ByacOpdGFpcmUgZGUgbGEgbWFpc29uIHZlcnRlIGJvaXQgZHUgY2Fmw6kuCi8vNi4gTGUgZnVtZXVyIGRlIFBhbGwgTWFsbCDDqWzDqHZlIGRlcyBvaXNlYXV4LgovLzcuIExlIHByb3ByacOpdGFpcmUgZGUgbGEgbWFpc29uIGphdW5lIGZ1bWUgZGVzIER1bmhpbGxzLiAKLy8xMi4gTCdob21tZSBxdWkgZnVtZSBkZXMgQmx1ZSBNYXN0ZXJzIGJvaXQgZGUgbGEgYmnDqHJlLgovLzEzLiBMJ0FsbGVtYW5kIGZ1bWUgZGVzIFByaW5jZS4gCQoKLy80LiBMYSBtYWlzb24gdmVydGUgZXN0IGp1c3RlIMOgIGdhdWNoZSBkZSBsYSBtYWlzb24gYmxhbmNoZS4KLy84LiBMJ2hvbW1lIHF1aSB2aXQgZGFucyBsYSBtYWlzb24gZHUgY2VudHJlIGJvaXQgZHUgbGFpdC4gCi8vOS4gTGUgTm9ydsOpZ2llbiB2aXQgZGFucyBsYSBwcmVtacOocmUgbWFpc29uLiAKLy8xMC4gTCdob21tZSBxdWkgZnVtZSBkZXMgQmxlbmRzIHZpdCDDoCBjw7R0w6kgZGUgY2VsdWkgcXVpIMOpbMOodmUgZGVzIGNoYXRzLiAKLy8xMS4gTCdob21tZSBxdWkgw6lsw6h2ZSBkZXMgY2hldmF1eCB2aXQgw6AgY8O0dMOpIGR1IGZ1bWV1ciBkZSBEdW5oaWxscy4gCi8vMTQuIExlIE5vcnbDqWdpZW4gdml0IMOgIGPDtHTDqSBkZSBsYSBtYWlzb24gYmxldWUuIAovLzE1LiBMJ2hvbW1lIHF1aSBmdW1lIGRlcyBCbGVuZHMgYSB1biB2b2lzaW4gcXVpIGJvaXQgZGUgbCdlYXUuCQoKCgoJCWZuIGhhc19hX25vcnZlZ2llbjwncj4gKGlucHV0IDogJidyIE1haXNvbiApIC0+IGJvb2wgewoJCSAgICBtYXRjaCAqaW5wdXR7CgkJICAgIAlNYWlzb24geyBjb3VsZXVyIDpfICAJLCBuYXRpb25hbGl0ZSA6IE5hdGlvbmFsaXRlOjpOb3J2ZWdpZW4gCSwgYm9pc3NvbiA6IF8gCSwgY2lnYXJldHRlIDogXwkJCQkJCSwgYW5pbWF1eCA6IF8JCQkJIH0gPT4gIHRydWUsCgkJICAgIAlfID0+ICBmYWxzZQoKCQkgICAgfQoJCX0JCgkJZm4gaGFzX2xhaXQ8J3I+IChpbnB1dCA6ICYnciBNYWlzb24gKSAtPiBib29sIHsKCQkgICAgbWF0Y2ggKmlucHV0ewoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6XyAgCSwgbmF0aW9uYWxpdGUgOiBfIAksIGJvaXNzb24gOiBCb2lzc29uOjpMYWl0IAksIGNpZ2FyZXR0ZSA6IF8JCQkJCQksIGFuaW1hdXggOiBfCQkJCSB9ID0+ICB0cnVlLAoJCSAgICAJXyA9PiAgZmFsc2UKCgkJICAgIH0KCQl9CQkKCQlmbiBoYXNfYmxldWU8J3I+IChpbnB1dCA6ICYnciBNYWlzb24gKSAtPiBib29sIHsKCQkgICAgbWF0Y2ggKmlucHV0ewoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6Q291bGV1cjo6QmxldWUgIAksIG5hdGlvbmFsaXRlIDogXyAJLCBib2lzc29uIDogXyAJLCBjaWdhcmV0dGUgOiBfCQkJCQkJLCBhbmltYXV4IDogXwkJCQkgfSA9PiAgdHJ1ZSwKCQkgICAgCV8gPT4gIGZhbHNlCgoJCSAgICB9CgkJfQkJCQkKCgkJZm4gaGFzX2NvdWxldXI8J3I+IChpbnB1dCA6ICYnciBNYWlzb24sIGNvdWwgOiBDb3VsZXVyICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiByZWYgeCAJLCBuYXRpb25hbGl0ZSA6IF8gCSwgYm9pc3NvbiA6IF8gCSwgY2lnYXJldHRlIDogXwkJCQkJCSwgYW5pbWF1eCA6IF8JCQkJIH0gPT4gIGNvdWw9PSp4CgoJCSAgICB9CgkJfQoJCWZuIGhhc19uYXRpb25hbGl0ZTwncj4gKGlucHV0IDogJidyIE1haXNvbiwgY291bCA6IE5hdGlvbmFsaXRlICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfIAksIG5hdGlvbmFsaXRlIDogcmVmIHggCSwgYm9pc3NvbiA6IF8gCSwgY2lnYXJldHRlIDogXwkJCQkJCSwgYW5pbWF1eCA6IF8JCQkJIH0gPT4gIGNvdWw9PSp4CgoJCSAgICB9CgkJfQkJCgkJZm4gaGFzX2JvaXNzb248J3I+IChpbnB1dCA6ICYnciBNYWlzb24sIGNvdWwgOiBCb2lzc29uICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfIAksIG5hdGlvbmFsaXRlIDogXyAJLCBib2lzc29uIDogcmVmIHggCSwgY2lnYXJldHRlIDogXwkJCQkJCSwgYW5pbWF1eCA6IF8JCQkJIH0gPT4gIGNvdWw9PSp4CgoJCSAgICB9CgkJfQkKCQlmbiBoYXNfY2lnYXJldHRlPCdyPiAoaW5wdXQgOiAmJ3IgTWFpc29uLCBjb3VsIDogQ2lnYXJldHRlICkgLT4gYm9vbCB7CgkJICAgIG1hdGNoICppbnB1dHsKCQkgICAgCU1haXNvbiB7IGNvdWxldXIgOiBfIAksIG5hdGlvbmFsaXRlIDogXyAJLCBib2lzc29uIDogIF8JLCBjaWdhcmV0dGUgOiByZWYgeAkJCQkJLCBhbmltYXV4IDogXwkJCQkgfSA9PiAgY291bD09KngKCgkJICAgIH0KCQl9CQkKCQlmbiBoYXNfYW5pbWF1eDwncj4gKGlucHV0IDogJidyIE1haXNvbiwgY291bCA6IEFuaW1hdXggKSAtPiBib29sIHsKCQkgICAgbWF0Y2ggKmlucHV0ewoJCSAgICAJTWFpc29uIHsgY291bGV1ciA6IF8gCSwgbmF0aW9uYWxpdGUgOiBfIAksIGJvaXNzb24gOiBfIAksIGNpZ2FyZXR0ZSA6IF8JCQkJCQksIGFuaW1hdXggOiByZWYgeAkJCQkgfSA9PiAgY291bD09KngKCgkJICAgIH0KCQl9CQkJCgoJCWZuIHZlY19oYXM8Rj4odiA6ICZWZWM8TWFpc29uPixydWxlIDogRikgLT4gYm9vbAoJCXdoZXJlIEY6IEZuKCZNYWlzb24pIC0+IGJvb2x7CgoJCQkgICAgZm9yIGYgaW4gdi5pdGVyKCkgewoJCQkgICAgICAgIGlmIHJ1bGUoJmYpIHtyZXR1cm4gdHJ1ZX0KCQkJICAgIH0KCgkJCSAgICBmYWxzZQoKCQl9CQkKCgpmbiB2ZWNfc3RyaW5nKHYgOiAmVmVjPE1haXNvbj4pLT4gU3RyaW5newoJbGV0IG11dCByPVN0cmluZzo6bmV3KCk7CgoJCQkgICAgZm9yIGYgaW4gdi5pdGVyKCkgewoJCQkgICAgCWxldCBvdD1mb3JtYXQhKCJ7Oj99XG4iLGYpOwoJCQkgICAgICAgIHIucHVzaF9zdHIoJm90KTsKCQkJICAgIH0KCXIKCQp9CgppbXBsIGZtdDo6RGlzcGxheSBmb3IgSHlwb3RoZXNlVmVjdG9yIHsKICAgIGZuIGZtdCgmc2VsZiwgZjogJm11dCBmbXQ6OkZvcm1hdHRlcikgLT4gZm10OjpSZXN1bHQgewoJCW1hdGNoICpzZWxmewoJCUh5cG90aGVzZVZlY3RvcihyZWYgYSxyZWYgYixyZWYgYyxyZWYgZCxyZWYgZSkgPT4gewoJCSAgICAJd3JpdGUhKGYsIlxuKysrKysrTWFpc29uIDErKysrKytcbiB7fVxuKysrKysrTWFpc29uIDIrKysrKytcbiB7fVxuKysrKysrTWFpc29uIDMrKysrKytcbiB7fVxuKysrKysrTWFpc29uIDQrKysrKytcbiB7fVxuKysrKysrTWFpc29uIDUrKysrKytcbiB7fSIsdmVjX3N0cmluZyhhKSx2ZWNfc3RyaW5nIChiKSx2ZWNfc3RyaW5nIChjKSx2ZWNfc3RyaW5nIChkKSwgdmVjX3N0cmluZyAoZSkpCgoJCQl9CgoJCX0KICAgIH0KfQoKCmltcGwgSHlwb3RoZXNlVmVjdG9yewoKCWZuIGNvdW50X2RldGVybWluYW50ICggJm11dCBzZWxmICkgLT4gdXNpemV7CgkJbWF0Y2ggKnNlbGZ7CgkJSHlwb3RoZXNlVmVjdG9yKHJlZiBtdXQgYSxyZWYgbXV0IGIscmVmIG11dCBjLHJlZiBtdXQgZCxyZWYgbXV0IGUpID0+IHsKCQkJCWEubGVuKCkrYi5sZW4oKStjLmxlbigpK2QubGVuKCkrZS5sZW4oKQoKCQkJfQoKCQl9CgoKCX0KCglmbiBjb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGU8Rj4oJm11dCBzZWxmLHJ1bGUxIDogRikKCQl3aGVyZSBGOiBGbigmTWFpc29uKSAtPiBib29sewoKCQkJbWF0Y2ggKnNlbGZ7CgkJCUh5cG90aGVzZVZlY3RvcihyZWYgbXV0IGEscmVmIG11dCBiLHJlZiBtdXQgYyxyZWYgbXV0IGQscmVmIG11dCBlKSA9PiB7CgkJCQkJbGV0IGJhPXZlY19oYXMoJmEsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCQkJCQlsZXQgYmI9dmVjX2hhcygmYix8eDogJk1haXNvbnwgcnVsZTEoeCkpOwoJCQkJCWxldCBiYz12ZWNfaGFzKCZjLHx4OiAmTWFpc29ufCBydWxlMSh4KSk7CgkJCQkJbGV0IGJkPXZlY19oYXMoJmQsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCQkJCQlsZXQgYmU9dmVjX2hhcygmZSx8eDogJk1haXNvbnwgcnVsZTEoeCkpOwoKCgkJCQkJbGV0IHRoZV9vbmU9IG1hdGNoIChiYSxiYixiYyxiZCxiZSl7CgkJCQkJCQkodHJ1ZSxmYWxzZSxmYWxzZSxmYWxzZSxmYWxzZSkgPT4gU29tZShhKSwKCQkJCQkJCShmYWxzZSx0cnVlLGZhbHNlLGZhbHNlLGZhbHNlKSA9PiBTb21lKGIpLAoJCQkJCQkJKGZhbHNlLGZhbHNlLHRydWUsZmFsc2UsZmFsc2UpID0+IFNvbWUoYyksCgkJCQkJCQkoZmFsc2UsZmFsc2UsZmFsc2UsdHJ1ZSxmYWxzZSkgPT4gU29tZShkKSwKCQkJCQkJCShmYWxzZSxmYWxzZSxmYWxzZSxmYWxzZSx0cnVlKSA9PiBTb21lKGUpLAoJCQkJCQkJXyA9PiBOb25lCgkJCQkJfTsKCgkJCQkJbWF0Y2ggdGhlX29uZXsKCQkJCQkJU29tZShrKT0+ewoJCQkJCQkJay5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUxKHgpKTt9CgkJCQkJCU5vbmU9PiB7fQoJCQkJCX0KCQkJCX0KCgkJCX0KCgkJfQkKCglmbiBjb25zdHJhaW50X3ZvaXNpbl9rZWVwX25vdF9pbl9vcl92b2lzaW5faW48RixHPigmbXV0IHNlbGYscnVsZTEgOiBGLHJ1bGUyIDogRykKCXdoZXJlIEY6IEZuKCZNYWlzb24pIC0+IGJvb2wsIEc6IEZuKCZNYWlzb24pIC0+IGJvb2x7CgoJCW1hdGNoICpzZWxmewoJCUh5cG90aGVzZVZlY3RvcihyZWYgbXV0IGEscmVmIG11dCBiLHJlZiBtdXQgYyxyZWYgbXV0IGQscmVmIG11dCBlKSA9PiB7CgkJCQlsZXQgYmE9dmVjX2hhcygmYSx8eDogJk1haXNvbnwgcnVsZTEoeCkpOwoJCQkJbGV0IGJiPXZlY19oYXMoJmIsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCQkJCWxldCBiYz12ZWNfaGFzKCZjLHx4OiAmTWFpc29ufCBydWxlMSh4KSk7CgkJCQlsZXQgYmQ9dmVjX2hhcygmZCx8eDogJk1haXNvbnwgcnVsZTEoeCkpOwoJCQkJbGV0IGJlPXZlY19oYXMoJmUsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCgkJCQlhLnJldGFpbih8eDogJk1haXNvbnwgIXJ1bGUyKHgpIHx8IAkJYmIpOwoJCQkJYi5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMih4KSB8fCBiYSB8fCAJYmMpOwoJCQkJYy5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMih4KSB8fCBiYiB8fCAJYmQpOwoJCQkJZC5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMih4KSB8fCBiYyB8fCAJYmUpOwoJCQkJZS5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMih4KSB8fCBiZCApOwoJCQl9CgoJCX0KCgl9CQkKCglmbiBjb25zdHJhaW50X3ZvaXNpbl9nYXVjaGVfZHJvaXRlPEYsRz4oJm11dCBzZWxmLHJ1bGUxIDogRixydWxlMiA6IEcpCgl3aGVyZSBGOiBGbigmTWFpc29uKSAtPiBib29sLCBHOiBGbigmTWFpc29uKSAtPiBib29sewoKCQltYXRjaCAqc2VsZnsKCQlIeXBvdGhlc2VWZWN0b3IocmVmIG11dCBhLHJlZiBtdXQgYixyZWYgbXV0IGMscmVmIG11dCBkLHJlZiBtdXQgZSkgPT4gewoJCQkJbGV0IGJhPXZlY19oYXMoJmEsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCQkJCWxldCBiYj12ZWNfaGFzKCZiLHx4OiAmTWFpc29ufCBydWxlMSh4KSk7CgkJCQlsZXQgYmM9dmVjX2hhcygmYyx8eDogJk1haXNvbnwgcnVsZTEoeCkpOwoJCQkJbGV0IGJkPXZlY19oYXMoJmQsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCQkJCS8vbGV0IGJlPXZlY19oYXMoJmUsfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCgkJCQlhLnJldGFpbih8eDogJk1haXNvbnwgIXJ1bGUyKHgpKTsKCQkJCWIucmV0YWluKHx4OiAmTWFpc29ufCAhcnVsZTIoeCkgfHwgYmEpOwoJCQkJYy5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMih4KSB8fCBiYik7CgkJCQlkLnJldGFpbih8eDogJk1haXNvbnwgIXJ1bGUyKHgpIHx8IGJjKTsKCQkJCWUucmV0YWluKHx4OiAmTWFpc29ufCAhcnVsZTIoeCkgfHwgYmQgKTsKCgkJCQkvL2xldCBkYT12ZWNfaGFzKCZhLHx4OiAmTWFpc29ufCBydWxlMih4KSk7CgkJCQlsZXQgZGI9dmVjX2hhcygmYix8eDogJk1haXNvbnwgcnVsZTIoeCkpOwoJCQkJbGV0IGRjPXZlY19oYXMoJmMsfHg6ICZNYWlzb258IHJ1bGUyKHgpKTsKCQkJCWxldCBkZD12ZWNfaGFzKCZkLHx4OiAmTWFpc29ufCBydWxlMih4KSk7CgkJCQlsZXQgZGU9dmVjX2hhcygmZSx8eDogJk1haXNvbnwgcnVsZTIoeCkpOwkKCgkJCQlhLnJldGFpbih8eDogJk1haXNvbnwgIXJ1bGUxKHgpIHx8IGRiKTsKCQkJCWIucmV0YWluKHx4OiAmTWFpc29ufCAhcnVsZTEoeCkgfHwgZGMpOwoJCQkJYy5yZXRhaW4ofHg6ICZNYWlzb258ICFydWxlMSh4KSB8fCBkZCk7CgkJCQlkLnJldGFpbih8eDogJk1haXNvbnwgIXJ1bGUxKHgpIHx8IGRlKTsKCQkJCWUucmV0YWluKHx4OiAmTWFpc29ufCAhcnVsZTEoeCkpOwoJCQl9CgoJCX0KCgl9CQkKCgoJZm4gY29uc3RyYWludF92b2lzaW48RixHPigmbXV0IHNlbGYscnVsZTEgOiBGLHJ1bGUyIDogRykKCXdoZXJlIEY6IEZuKCZNYWlzb24pIC0+IGJvb2wsIEc6IEZuKCZNYWlzb24pIC0+IGJvb2x7CgoKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfbm90X2luX29yX3ZvaXNpbl9pbih8eDogJk1haXNvbnwgcnVsZTEoeCksfHg6ICZNYWlzb258IHJ1bGUyKHgpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfbm90X2luX29yX3ZvaXNpbl9pbih8eDogJk1haXNvbnwgcnVsZTIoeCksfHg6ICZNYWlzb258IHJ1bGUxKHgpKTsKCX0JCgovLzQuIExhIG1haXNvbiB2ZXJ0ZSBlc3QganVzdGUgw6AgZ2F1Y2hlIGRlIGxhIG1haXNvbiBibGFuY2hlLgovLzguIEwnaG9tbWUgcXVpIHZpdCBkYW5zIGxhIG1haXNvbiBkdSBjZW50cmUgYm9pdCBkdSBsYWl0LiAKLy85LiBMZSBOb3J2w6lnaWVuIHZpdCBkYW5zIGxhIHByZW1pw6hyZSBtYWlzb24uIAovLzEwLiBMJ2hvbW1lIHF1aSBmdW1lIGRlcyBCbGVuZHMgdml0IMOgIGPDtHTDqSBkZSBjZWx1aSBxdWkgw6lsw6h2ZSBkZXMgY2hhdHMuIAovLzExLiBMJ2hvbW1lIHF1aSDDqWzDqHZlIGRlcyBjaGV2YXV4IHZpdCDDoCBjw7R0w6kgZHUgZnVtZXVyIGRlIER1bmhpbGxzLiAKLy8xNC4gTGUgTm9ydsOpZ2llbiB2aXQgw6AgY8O0dMOpIGRlIGxhIG1haXNvbiBibGV1ZS4gCi8vMTUuIEwnaG9tbWUgcXVpIGZ1bWUgZGVzIEJsZW5kcyBhIHVuIHZvaXNpbiBxdWkgYm9pdCBkZSBsJ2VhdS4JCQoKLy80LiBMYSBtYWlzb24gdmVydGUgZXN0IGp1c3RlIMOgIGdhdWNoZSBkZSBsYSBtYWlzb24gYmxhbmNoZS4KCWZuIHI0X21haXNvbl92ZXJ0ZV9nYXVjaGVfYmxhbmNoZTwnY2wsICdhPiAoICZtdXQgc2VsZiApIC0+ICgpewoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fZ2F1Y2hlX2Ryb2l0ZSh8eDogJk1haXNvbnwgaGFzX2NvdWxldXIoeCxDb3VsZXVyOjpWZXJ0ZSksfHg6ICZNYWlzb258IGhhc19jb3VsZXVyKHgsQ291bGV1cjo6QmxhbmNoZSkpOwoKCgl9CgovLzguIEwnaG9tbWUgcXVpIHZpdCBkYW5zIGxhIG1haXNvbiBkdSBjZW50cmUgYm9pdCBkdSBsYWl0LiAKCWZuIHI4X2NlbnRyZV9sYWl0PCdjbCwgJ2E+ICggJm11dCBzZWxmICkgLT4gKCl7CgkJbWF0Y2ggKnNlbGZ7CgkJSHlwb3RoZXNlVmVjdG9yKHJlZiBtdXQgYSxyZWYgbXV0IGIscmVmIG11dCBjLHJlZiBtdXQgZCxyZWYgbXV0IGUpID0+IHsKCQkJCWEucmV0YWluKHx4OiAmTWFpc29ufCAhaGFzX2xhaXQoeCkpOwoJCQkJYi5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfbGFpdCh4KSk7CgkJCQljLnJldGFpbih8eDogJk1haXNvbnwgaGFzX2xhaXQoeCkpOwoJCQkJZC5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfbGFpdCh4KSk7CgkJCQllLnJldGFpbih8eDogJk1haXNvbnwgIWhhc19sYWl0KHgpKTsKCgkJCX0KCgkJfQoKCgl9CgovLzkuIExlIE5vcnbDqWdpZW4gdml0IGRhbnMgbGEgcHJlbWnDqHJlIG1haXNvbi4gCQoJZm4gcjlfbm9ydmVnaWVuX3ByZW1pZXJlPCdjbCwgJ2E+ICggJm11dCBzZWxmICkgLT4gKCl7CgkJbWF0Y2ggKnNlbGZ7CgkJSHlwb3RoZXNlVmVjdG9yKHJlZiBtdXQgYSxyZWYgbXV0IGIscmVmIG11dCBjLHJlZiBtdXQgZCxyZWYgbXV0IGUpID0+IHsKCQkJCWEucmV0YWluKHx4OiAmTWFpc29ufCBoYXNfYV9ub3J2ZWdpZW4oeCkpOwoJCQkJYi5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfYV9ub3J2ZWdpZW4oeCkpOwoJCQkJYy5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfYV9ub3J2ZWdpZW4oeCkpOwoJCQkJZC5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfYV9ub3J2ZWdpZW4oeCkpOwoJCQkJZS5yZXRhaW4ofHg6ICZNYWlzb258ICFoYXNfYV9ub3J2ZWdpZW4oeCkpOwoKCQkJfQoKCQl9Cgl9Ci8vMTAuIEwnaG9tbWUgcXVpIGZ1bWUgZGVzIEJsZW5kcyB2aXQgw6AgY8O0dMOpIGRlIGNlbHVpIHF1aSDDqWzDqHZlIGRlcyBjaGF0cy4gCglmbiByMTBfYmxlbmRzX3ZvaXNpbl9jaGF0czwnY2wsICdhPiAoICZtdXQgc2VsZiApIC0+ICgpewoJCXNlbGYuY29uc3RyYWludF92b2lzaW4ofHg6ICZNYWlzb258IGhhc19jaWdhcmV0dGUoeCxDaWdhcmV0dGU6OkJsZW5kcyksfHg6ICZNYWlzb258IGhhc19hbmltYXV4KHgsQW5pbWF1eDo6Q2hhdHMpKTsKCX0JCi8vMTEuIEwnaG9tbWUgcXVpIMOpbMOodmUgZGVzIGNoZXZhdXggdml0IMOgIGPDtHTDqSBkdSBmdW1ldXIgZGUgRHVuaGlsbHMuIAoJZm4gcjExX2NoZXZhdXhfdm9pc2luX2R1bmhpbGxzPCdjbCwgJ2E+ICggJm11dCBzZWxmICkgLT4gKCl7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbih8eDogJk1haXNvbnwgaGFzX2NpZ2FyZXR0ZSh4LENpZ2FyZXR0ZTo6RHVuaGlsbHMpLHx4OiAmTWFpc29ufCBoYXNfYW5pbWF1eCh4LEFuaW1hdXg6OkNoZXZhdXgpKTsKCX0JCgovLzE0LiBMZSBOb3J2w6lnaWVuIHZpdCDDoCBjw7R0w6kgZGUgbGEgbWFpc29uIGJsZXVlLiAJCglmbiByMTRfbm9ydmVnaWVuX2NvdGVfbWFpc29uX2JsZXVlPCdjbCwgJ2E+ICggJm11dCBzZWxmICkgLT4gKCl7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbih8eDogJk1haXNvbnwgaGFzX2Ffbm9ydmVnaWVuKHgpLHx4OiAmTWFpc29ufCBoYXNfYmxldWUoeCkpOwoJfQoKLy8xNS4gTCdob21tZSBxdWkgZnVtZSBkZXMgQmxlbmRzIGEgdW4gdm9pc2luIHF1aSBib2l0IGRlIGwnZWF1LgoJZm4gcjE1X2JsZW5kX3ZvaXNpbl9lYXU8J2NsLCAnYT4gKCAmbXV0IHNlbGYgKSAtPiAoKXsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luKHx4OiAmTWFpc29ufCBoYXNfY2lnYXJldHRlKHgsQ2lnYXJldHRlOjpCbGVuZHMpLHx4OiAmTWFpc29ufCBoYXNfYm9pc3Nvbih4LEJvaXNzb246OkVhdSkpOwoJfQkKCglmbiBhcHBseTxGPigmbXV0IHNlbGYscnVsZSA6IEYpCgl3aGVyZSBGOiBGbigmTWFpc29uKSAtPiBib29sewoKCQltYXRjaCAqc2VsZnsKCQlIeXBvdGhlc2VWZWN0b3IocmVmIG11dCBhLHJlZiBtdXQgYixyZWYgbXV0IGMscmVmIG11dCBkLHJlZiBtdXQgZSkgPT4gewoJCQkJYS5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUoeCkpOwoJCQkJYi5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUoeCkpOwoJCQkJYy5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUoeCkpOwoJCQkJZC5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUoeCkpOwoJCQkJZS5yZXRhaW4ofHg6ICZNYWlzb258IHJ1bGUoeCkpOwoKCQkJfQoKCQl9CgoJfQoKCWZuIHNpbXBsZV9jb25zdHJhaW50cygmbXV0IHNlbGYpewoJCXNlbGYuYXBwbHkocjFfYW5nbGFpc19yb3VnZSk7CgkJc2VsZi5hcHBseShyMl9zdWVkb2lzX2NoaWVuKTsKCQlzZWxmLmFwcGx5KHIzX2Rhbm9pc190aGUpOwoJCXNlbGYuYXBwbHkocjVfdmVydGVfY2FmZSk7CgkJc2VsZi5hcHBseShyNl9wYWxsbWFsbF9vaXNlYXUpOwoJCXNlbGYuYXBwbHkocjdfamF1bmVfZHVuaGlsbHMpOwoJCXNlbGYuYXBwbHkocjEyX2JsdWVtYXN0ZXJfYmllcmUpOwoJCXNlbGYuYXBwbHkocjEzX2FsbGVtYW5kX3ByaW5jZSk7CgoKCX0JCgoKCWZuIG90aGVyX2NvbnN0cmFpbnRlcygmbXV0IHNlbGYpewoJCXNlbGYucjRfbWFpc29uX3ZlcnRlX2dhdWNoZV9ibGFuY2hlKCk7CgkJc2VsZi5yOF9jZW50cmVfbGFpdCgpOwoJCXNlbGYucjlfbm9ydmVnaWVuX3ByZW1pZXJlKCk7CgkJc2VsZi5yMTBfYmxlbmRzX3ZvaXNpbl9jaGF0cygpOwoJCXNlbGYucjExX2NoZXZhdXhfdm9pc2luX2R1bmhpbGxzKCk7CgkJc2VsZi5yMTRfbm9ydmVnaWVuX2NvdGVfbWFpc29uX2JsZXVlKCk7CgkJc2VsZi5yMTVfYmxlbmRfdm9pc2luX2VhdSgpOwoKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2NvdWxldXIoeCxDb3VsZXVyOjpWZXJ0ZSkpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfY291bGV1cih4LENvdWxldXI6OkJsYW5jaGUpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2NvdWxldXIoeCxDb3VsZXVyOjpKYXVuZSkpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfY291bGV1cih4LENvdWxldXI6OkJsZXVlKSk7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGUofHg6ICZNYWlzb258IGhhc19jb3VsZXVyKHgsQ291bGV1cjo6Um91Z2UpKTsKCgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGUofHg6ICZNYWlzb258IGhhc19uYXRpb25hbGl0ZSh4LE5hdGlvbmFsaXRlOjpTdWVkb2lzKSk7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGUofHg6ICZNYWlzb258IGhhc19uYXRpb25hbGl0ZSh4LE5hdGlvbmFsaXRlOjpEYW5vaXMpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX25hdGlvbmFsaXRlKHgsTmF0aW9uYWxpdGU6OkFuZ2xhaXMpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX25hdGlvbmFsaXRlKHgsTmF0aW9uYWxpdGU6Ok5vcnZlZ2llbikpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfbmF0aW9uYWxpdGUoeCxOYXRpb25hbGl0ZTo6QWxsZW1hbmQpKTsJCQoKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2JvaXNzb24oeCxCb2lzc29uOjpFYXUpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2JvaXNzb24oeCxCb2lzc29uOjpUaGUpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2JvaXNzb24oeCxCb2lzc29uOjpDYWZlKSk7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGUofHg6ICZNYWlzb258IGhhc19ib2lzc29uKHgsQm9pc3Nvbjo6QmllcmUpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2JvaXNzb24oeCxCb2lzc29uOjpMYWl0KSk7CQkJCgoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfY2lnYXJldHRlKHgsQ2lnYXJldHRlOjpEdW5oaWxscykpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfY2lnYXJldHRlKHgsQ2lnYXJldHRlOjpQYWxsTWFsbCkpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfY2lnYXJldHRlKHgsQ2lnYXJldHRlOjpCbGVuZHMpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2NpZ2FyZXR0ZSh4LENpZ2FyZXR0ZTo6QmxldWVNYXN0ZXJzKSk7CgkJc2VsZi5jb25zdHJhaW50X3ZvaXNpbl9rZWVwX3VuaXF1ZV9hc19zaW5nbGUofHg6ICZNYWlzb258IGhhc19jaWdhcmV0dGUoeCxDaWdhcmV0dGU6OlByaW5jZSkpOwkJCgoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfYW5pbWF1eCh4LEFuaW1hdXg6Ok9pc2VhdXgpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2FuaW1hdXgoeCxBbmltYXV4OjpDaGllbikpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfYW5pbWF1eCh4LEFuaW1hdXg6OkNoZXZhdXgpKTsKCQlzZWxmLmNvbnN0cmFpbnRfdm9pc2luX2tlZXBfdW5pcXVlX2FzX3NpbmdsZSh8eDogJk1haXNvbnwgaGFzX2FuaW1hdXgoeCxBbmltYXV4OjpDaGF0cykpOwoJCXNlbGYuY29uc3RyYWludF92b2lzaW5fa2VlcF91bmlxdWVfYXNfc2luZ2xlKHx4OiAmTWFpc29ufCBoYXNfYW5pbWF1eCh4LEFuaW1hdXg6OlBvaXNzb25Sb3VnZSkpOwkKCX0KfQoKCgpwdWIgZm4gbWFpbigpLT4oKXsKCglwcmludGxuISgiRWluc3RlaW4gZW5pZ21hIHByb2dyYW0iKTsKCgoJbGV0IG11dCBoPWZ1bGxfcG9zc2liaWxpdHkoKTsKCXByaW50bG4hKCI+IGRldGVybWluYW50IGRlIGJhc2UgOiB7fSAiLGguY291bnRfZGV0ZXJtaW5hbnQoKSk7CgoJaC5zaW1wbGVfY29uc3RyYWludHMoKTsKCS8vcHJpbnRsbiEoIj4ge30iLCBoKTsKCgkvL3ByaW50bG4hKCI+IGRldGVybWluYW50IGFwcmVzIGNvbnRyYWludGVzIHNpbXBsZXMgOiB7fSAiLGguY291bnRfZGV0ZXJtaW5hbnQoKSk7CgoJbGV0IG11dCBjb3VudF9hcHBseT0wOwoKCSBsb29wewoJCWNvdW50X2FwcGx5PWNvdW50X2FwcGx5KzE7CgkJbGV0IHByZXZfZGV0PWguY291bnRfZGV0ZXJtaW5hbnQoKTsKCQkvL3ByaW50bG4hKCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIik7CgkJLy9wcmludGxuISgiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSIpOwoJCS8vcHJpbnRsbiEoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0iKTsKCQkvL3ByaW50bG4hKCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIik7CgkJLy9wcmludGxuISgiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSIpOwoKCQloLm90aGVyX2NvbnN0cmFpbnRlcygpOwoJCS8vcHJpbnRsbiEoInt9IiwgaCk7CgkJcHJpbnRsbiEoImRldGVybWluYW50IDoge30gOiAgYXByZXMge30gYXBwbGljYXRpb24gZGVzIHJlZ2xlcyAiLGguY291bnRfZGV0ZXJtaW5hbnQoKSwgY291bnRfYXBwbHkpOwoKCQlpZiBwcmV2X2RldD09aC5jb3VudF9kZXRlcm1pbmFudCgpIHticmVhazt9CgoJfQoJcHJpbnRsbiEoIi0tLS0tLS0tLS0tLSBGSU4gRFUgUFJPR1JBTU1FIC0tLS0tLS0tLS0tIik7CglwcmludGxuISgiZGV0ZXJtaW5hbnQgOiB7fSA6ICBhcHJlcyB7fSBhcHBsaWNhdGlvbiBkZXMgcmVnbGVzICIsaC5jb3VudF9kZXRlcm1pbmFudCgpLCBjb3VudF9hcHBseSk7CglwcmludGxuISgie30iLCBoKTsKCgoKfQoKCg==