#include <algorithm>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
namespace gtc
{
/*****************************************************************************
* class _base_graph *
*****************************************************************************/
template < typename K, typename W, typename T>
class _base_graph
{
protected :
_base_graph( )
{
}
_base_graph( size_t n) ;
_base_graph( size_t n, const K& k) ;
template < typename F>
_base_graph( size_t n, F f) ;
public :
void add_node( const K& k) ;
void add_node( const K& k, const T& t) ;
std:: size_t order( )
{
return nod.size ( ) ;
}
size_t size( )
{
return edg.size ( ) ;
}
T& operator[ ] ( const K& k) ;
class iterator
{
friend class _base_graph< K, W, T> ;
public :
iterator& operator++ ( )
{
++ it;
return * this ;
}
iterator operator++ ( int )
{
iterator i = ( * this ) ;
++ it;
return i;
}
iterator& operator-- ( )
{
-- it;
return * this ;
}
iterator operator-- ( int )
{
iterator i = ( * this ) ;
-- it;
return i;
}
std:: pair < const K, T> & operator* ( )
{
return * it;
}
std:: pair < const K, T> * operator- > ( )
{
return & ( * it) ;
}
bool operator== ( const iterator& i)
{
return it == i.it ;
}
bool operator! = ( const iterator& i)
{
return it ! = i.it ;
}
private :
typename std:: map < K, T> :: iterator begin, end;
typename std:: map < K, T> :: iterator it;
} ;
virtual iterator begin( ) ;
virtual iterator end( ) ;
virtual iterator find( const K& k) ;
class edge
{
public :
edge( const K& k1, const K& k2, const W& w = 0 ) :
ky1( k1) , ky2( k2) , wt( w)
{
}
bool operator== ( const edge& e) const
{
return key1( ) == e.key1 ( ) && key2( ) == e.key2 ( ) ;
}
bool operator! = ( const edge& e) const
{
return key1( ) ! = e.key1 ( ) || key2( ) ! = e.key2 ( ) ;
}
const K& key1( ) const
{
return ky1;
}
const K& key2( ) const
{
return ky2;
}
const K& key( const K& k) ;
K& weight( )
{
return wt;
}
private :
K ky1;
K ky2;
W wt;
} ;
virtual bool is_edge( const K& k1, const K& k2) = 0 ;
class edge_iterator
{
friend class _base_graph< K, W, T> ;
public :
edge_iterator& operator++ ( ) ;
edge_iterator operator++ ( int ) ;
edge_iterator& operator-- ( ) ;
edge_iterator operator-- ( int ) ;
edge& operator* ( )
{
return * it;
}
edge* operator- > ( )
{
return & ( * it) ;
}
bool operator== ( const edge_iterator& i)
{
return it == i.it ;
}
bool operator! = ( const edge_iterator& i)
{
return it ! = i.it ;
}
private :
typename std:: list < edge> :: iterator begin, end;
typename std:: list < edge> :: iterator it;
K key;
} ;
edge_iterator begin( const K& k) ;
edge_iterator end( const K& k) ;
template < typename F>
F BFS( const K& k, F f) ;
template < typename F>
F DFS( const K& k, F f) ;
protected :
std:: map < K, T> nod;
std:: list < edge> edg;
} ;
template < typename K, typename W, typename T>
_base_graph< K, W, T> :: _base_graph( size_t n)
{
K key( 1 ) ;
for ( size_t i = 0 ; i < n; i++ )
nod[ key++ ] = T( ) ;
}
template < typename K, typename W, typename T>
_base_graph< K, W, T> :: _base_graph( size_t n, const K& k)
{
K key( k) ;
for ( size_t i = 0 ; i < n; i++ )
nod[ key++ ] = T( ) ;
}
template < typename K, typename W, typename T>
template < typename F>
_base_graph< K, W, T> :: _base_graph( size_t n, F f)
{
for ( size_t i = 0 ; i < n; i++ )
nod[ f( ) ] = T( ) ;
}
template < typename K, typename W, typename T>
void _base_graph< K, W, T> :: add_node ( const K& k)
{
if ( nod.find ( k) ! = nod.end ( ) )
throw std:: string ( "_base_graph::add_node - node already exists" ) ;
nod[ k] = T( ) ;
}
template < typename K, typename W, typename T>
void _base_graph< K, W, T> :: add_node ( const K& k, const T& t)
{
if ( nod.find ( k) ! = nod.end ( ) )
throw std:: string ( "_base_graph::add_node - node already exists" ) ;
nod[ k] = t;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: iterator _base_graph< K, W, T> :: begin ( )
{
iterator i;
i.begin = nod.begin ( ) ;
i.end = nod.end ( ) ;
i.it = i.begin ;
return i;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator _base_graph< K, W, T> :: begin ( const K& k)
{
edge_iterator i;
i.begin = edg.begin ( ) ;
i.end = edg.end ( ) ;
i.key = k;
i.it = i.begin ;
while ( i.it ! = i.end && i.it - > key1( ) ! = i.key && i.it - > key2( ) ! = i.key )
{
i.it ++ ;
}
return i;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: iterator _base_graph< K, W, T> :: end ( )
{
iterator i;
i.begin = nod.begin ( ) ;
i.end = nod.end ( ) ;
i.it = i.end ;
return i;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator _base_graph< K, W, T> :: end ( const K& k)
{
edge_iterator i;
i.begin = edg.begin ( ) ;
i.end = edg.end ( ) ;
i.key = k;
i.it = i.end ;
return i;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: iterator _base_graph< K, W, T> :: find ( const K& k)
{
iterator i;
i.begin = nod.begin ( ) ;
i.end = nod.end ( ) ;
i.it = nod.find ( k) ;
return i;
}
template < typename K, typename W, typename T>
template < typename F>
F _base_graph< K, W, T> :: BFS ( const K& k, F f)
{
K cur;
std:: queue < K> q;
std:: set < K> v;
q.push ( k) ;
v.insert ( k) ;
while ( ! q.empty ( ) )
{
cur = q.front ( ) ;
q.pop ( ) ;
f( cur) ;
for ( iterator i = begin( ) ; i ! = end( ) ; i++ )
if ( is_edge( cur, i- > first) )
if ( v.find ( i- > first) == v.end ( ) )
{
q.push ( i- > first) ;
v.insert ( i- > first) ;
}
}
return f;
}
template < typename K, typename W, typename T>
template < typename F>
F _base_graph< K, W, T> :: DFS ( const K& k, F f)
{
K cur = k;
std:: set < K> v;
std:: stack < K> s;
do
{
if ( v.find ( cur) == v.end ( ) )
{
f( cur) ;
s.push ( cur) ;
v.insert ( cur) ;
}
iterator i = begin( ) ;
while ( i ! = end( ) && v.find ( i- > first) ! = v.end ( ) )
i++ ;
if ( i ! = end( ) )
cur = i- > first;
else
{
s.pop ( ) ;
if ( ! s.empty ( ) )
cur = s.top ( ) ;
}
}
while ( ! s.empty ( ) ) ;
return f;
}
template < typename K, typename W, typename T>
T& _base_graph< K, W, T> :: operator [ ] ( const K& k)
{
if ( nod.find ( k) == nod.end ( ) )
throw std:: string ( "_base_graph::operator[] - node does not exist" ) ;
return nod[ k] ;
}
template < typename K, typename W, typename T>
const K& _base_graph< K, W, T> :: edge :: key ( const K& k)
{
if ( k ! = key1( ) && k ! = key2( ) )
throw std:: string ( "graph::edge::key - key supplied is invalid" ) ;
return k == key1( ) ? key2( ) : key1( ) ;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator & _base_graph< K, W, T> :: edge_iterator :: operator ++ ( )
{
++ it;
while ( it ! = end && it- > key1( ) ! = key && it- > key2( ) ! = key)
++ it;
return * this ;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator _base_graph< K, W, T> :: edge_iterator :: operator ++ ( int )
{
edge_iterator tmp = * this ;
++ it;
while ( it ! = end && it- > key1( ) ! = key && it- > key2( ) ! = key)
++ it;
return tmp;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator & _base_graph< K, W, T> :: edge_iterator :: operator -- ( )
{
-- it;
while ( it ! = begin && it- > key1( ) ! = key && it- > key2( ) ! = key)
-- it;
if ( it == begin)
while ( it ! = end && it- > key1( ) ! = key && it- > key2( ) ! = key)
++ it;
return * this ;
}
template < typename K, typename W, typename T>
typename _base_graph< K, W, T> :: edge_iterator _base_graph< K, W, T> :: edge_iterator :: operator -- ( int )
{
edge_iterator tmp = * this ;
-- it;
while ( it ! = begin && it- > key1( ) ! = key && it- > key2( ) ! = key)
-- it;
if ( it == begin)
while ( it ! = end && it- > key1( ) ! = key && it- > key2( ) ! = key)
++ it;
return tmp;
}
/*****************************************************************************
* class graph *
*****************************************************************************/
template < typename K, typename T = void * >
class graph : public _base_graph< K, void * , T>
{
public :
graph( ) : _base_graph< K, void * , T> ( )
{
}
graph( size_t n) : _base_graph< K, void * , T> ( n)
{
}
graph( size_t n, const K& k) : _base_graph< K, void * , T> ( n, k)
{
}
template < typename F>
graph( size_t n, F f) : _base_graph< K, void * , T> ( n, f)
{
}
void add_edge( const K& k1, const K& k2) ;
bool is_edge( const K& k1, const K& k2) ;
void remove_edge( const K& k1, const K& k2) ;
} ;
template < typename K, typename T>
void graph< K, T> :: add_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
// Store lower key value in first key of edge
if ( k1 < k2)
this- > edg.push_back ( edge( k1, k2) ) ;
else
this- > edg.push_back ( edge( k2, k1) ) ;
}
template < typename K, typename T>
bool graph< K, T> :: is_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "is_edge: Node does not exist" ) ;
if ( k1 < k2)
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) ! = this- > edg.end ( ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k2, k1) ) ! = this- > edg.end ( ) ;
}
template < typename K, typename T>
void graph< K, T> :: remove_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
if ( k1 < k2)
this- > edg.remove ( edge( k1, k2) ) ;
else
this- > edg.remove ( edge( k2, k1) ) ;
}
/*****************************************************************************
* class wgraph *
*****************************************************************************/
template < typename K, typename W, typename T = void * >
class wgraph : public _base_graph< K, W, T>
{
public :
wgraph( ) : _base_graph< K, W, T> ( )
{
}
wgraph( size_t n) : _base_graph< K, W, T> ( n)
{
}
wgraph( size_t n, const K& k) : _base_graph< K, W, T> ( n, k)
{
}
template < typename F>
wgraph( size_t n, F f) : _base_graph< K, W, T> ( n, f)
{
}
void add_edge( const K& k1, const K& k2, const W& w) ;
bool is_edge( const K& k1, const K& k2) ;
void remove_edge( const K& k1, const K& k2) ;
W& weight( const K& k1, const K& k2) ;
} ;
template < typename K, typename W, typename T>
void wgraph< K, W, T> :: add_edge ( const K& k1, const K& k2, const W& w)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
// Store lower key value in first key of edge
if ( k1 < k2)
this- > edg.push_back ( edge( k1, k2, w) ) ;
else
this- > edg.push_back ( edge( k2, k1, w) ) ;
}
template < typename K, typename W, typename T>
bool wgraph< K, W, T> :: is_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "is_edge: Node does not exist" ) ;
if ( k1 < k2)
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) ! = this- > edg.end ( ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k2, k1) ) ! = this- > edg.end ( ) ;
}
template < typename K, typename W, typename T>
void wgraph< K, W, T> :: remove_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
if ( k1 < k2)
this- > edg.remove ( edge( k1, k2) ) ;
else
this- > edg.remove ( edge( k2, k1) ) ;
}
template < typename K, typename W, typename T>
W& wgraph< K, W, T> :: weight ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "weight: Node does not exist" ) ;
if ( ! is_edge( k1, k2) )
throw std:: string ( "weight: Edge does not exist" ) ;
if ( k1 < k2)
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) - > weight( ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k2, k1) ) - > weight( ) ;
}
/*****************************************************************************
* class digraph *
*****************************************************************************/
template < typename K, typename T = void * >
class digraph : public _base_graph< K, void * , T>
{
public :
digraph( ) : _base_graph< K, void * , T> ( )
{
}
digraph( size_t n) : _base_graph< K, void * , T> ( n)
{
}
digraph( size_t n, const K& k) : _base_graph< K, void * , T> ( n, k)
{
}
template < typename F>
digraph( size_t n, F f) : _base_graph< K, void * , T> ( n, f)
{
}
void add_edge( const K& k1, const K& k2) ;
bool is_edge( const K& k1, const K& k2) ;
void remove_edge( const K& k1, const K& k2) ;
} ;
template < typename K, typename T>
void digraph< K, T> :: add_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
this- > edg.push_back ( edge( k1, k2) ) ;
}
template < typename K, typename T>
bool digraph< K, T> :: is_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "is_edge: Node does not exist" ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) ! = this- > edg.end ( ) ;
}
template < typename K, typename T>
void digraph< K, T> :: remove_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
this- > edg.remove ( edge( k1, k2) ) ;
}
/*****************************************************************************
* class wdigraph *
*****************************************************************************/
template < typename K, typename W, typename T = void * >
class wdigraph : public _base_graph< K, W, T>
{
public :
wdigraph( ) : _base_graph< K, W, T> ( )
{
}
wdigraph( size_t n) : _base_graph< K, W, T> ( n)
{
}
wdigraph( size_t n, const K& k) : _base_graph< K, W, T> ( n, k)
{
}
template < typename F>
wdigraph( size_t n, F f) : _base_graph< K, W, T> ( n, f)
{
}
void add_edge( const K& k1, const K& k2, const W& w) ;
bool is_edge( const K& k1, const K& k2) ;
void remove_edge( const K& k1, const K& k2) ;
W& weight( const K& k1, const K& k2) ;
} ;
template < typename K, typename W, typename T>
void wdigraph< K, W, T> :: add_edge ( const K& k1, const K& k2, const W& w)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
this- > edg.push_back ( edge( k1, k2, w) ) ;
}
template < typename K, typename W, typename T>
bool wdigraph< K, W, T> :: is_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "is_edge: Node does not exist" ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) ! = this- > edg.end ( ) ;
}
template < typename K, typename W, typename T>
void wdigraph< K, W, T> :: remove_edge ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "add_edge: Node does not exist" ) ;
this- > edg.remove ( edge( k1, k2) ) ;
}
template < typename K, typename W, typename T>
W& wdigraph< K, W, T> :: weight ( const K& k1, const K& k2)
{
if ( this- > nod.find ( k1) == this- > nod.end ( ) || this- > nod.find ( k2) == this- > nod.end ( ) )
throw std:: string ( "weight: Node does not exist" ) ;
if ( ! is_edge( k1, k2) )
throw std:: string ( "weight: Edge does not exist" ) ;
return std:: find ( this- > edg.begin ( ) , this- > edg.end ( ) , edge( k1, k2) ) - > weight( ) ;
}
} // namespace gtc
int main( )
{
gtc:: graph < int > g;
return 0 ;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGxpc3Q+CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPHN0YWNrPgojaW5jbHVkZSA8c3RyaW5nPgoKbmFtZXNwYWNlIGd0Ywp7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogY2xhc3MgX2Jhc2VfZ3JhcGggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CmNsYXNzIF9iYXNlX2dyYXBoCnsKcHJvdGVjdGVkOgoKICAgIF9iYXNlX2dyYXBoKCkKICAgIHsKICAgIH0KCiAgICBfYmFzZV9ncmFwaChzaXplX3Qgbik7CgogICAgX2Jhc2VfZ3JhcGgoc2l6ZV90IG4sIGNvbnN0IEsmIGspOwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGPgogICAgX2Jhc2VfZ3JhcGgoc2l6ZV90IG4sIEYgZik7CgpwdWJsaWM6CiAgICB2b2lkIGFkZF9ub2RlKGNvbnN0IEsmIGspOwoKICAgIHZvaWQgYWRkX25vZGUoY29uc3QgSyYgaywgY29uc3QgVCYgdCk7CgogICAgc3RkOjpzaXplX3Qgb3JkZXIoKQogICAgewogICAgICAgIHJldHVybiBub2Quc2l6ZSgpOwogICAgfQoKICAgIHNpemVfdCBzaXplKCkKICAgIHsKICAgICAgICByZXR1cm4gZWRnLnNpemUoKTsKICAgIH0KCgogICAgVCYgb3BlcmF0b3JbXSAoY29uc3QgSyYgayk7CgogICAgY2xhc3MgaXRlcmF0b3IKICAgIHsKICAgICAgICBmcmllbmQgY2xhc3MgX2Jhc2VfZ3JhcGg8SywgVywgVD47CiAgICBwdWJsaWM6CgogICAgICAgIGl0ZXJhdG9yJiBvcGVyYXRvcisrKCkKICAgICAgICB7CiAgICAgICAgICAgICsraXQ7CiAgICAgICAgICAgIHJldHVybiAqdGhpczsKICAgICAgICB9CgogICAgICAgIGl0ZXJhdG9yIG9wZXJhdG9yKysoaW50KQogICAgICAgIHsKICAgICAgICAgICAgaXRlcmF0b3IgaSA9ICgqdGhpcyk7CiAgICAgICAgICAgICsraXQ7CiAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgIH0KCiAgICAgICAgaXRlcmF0b3ImIG9wZXJhdG9yLS0oKQogICAgICAgIHsKICAgICAgICAgICAgLS1pdDsKICAgICAgICAgICAgcmV0dXJuICp0aGlzOwogICAgICAgIH0KCiAgICAgICAgaXRlcmF0b3Igb3BlcmF0b3ItLShpbnQpCiAgICAgICAgewogICAgICAgICAgICBpdGVyYXRvciBpID0gKCp0aGlzKTsKICAgICAgICAgICAgLS1pdDsKICAgICAgICAgICAgcmV0dXJuIGk7CiAgICAgICAgfQoKICAgICAgICBzdGQ6OnBhaXI8Y29uc3QgSywgVD4mIG9wZXJhdG9yKigpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gKml0OwogICAgICAgIH0KCiAgICAgICAgc3RkOjpwYWlyPGNvbnN0IEssIFQ+KiBvcGVyYXRvci0+ICgpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gJigqaXQpOwogICAgICAgIH0KCiAgICAgICAgYm9vbCBvcGVyYXRvcj09KGNvbnN0IGl0ZXJhdG9yJiBpKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIGl0ID09IGkuaXQ7CiAgICAgICAgfQoKICAgICAgICBib29sIG9wZXJhdG9yIT0oY29uc3QgaXRlcmF0b3ImIGkpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gaXQgIT0gaS5pdDsKICAgICAgICB9CgogICAgcHJpdmF0ZToKICAgICAgICB0eXBlbmFtZSBzdGQ6Om1hcDxLLCBUPjo6aXRlcmF0b3IgYmVnaW4sIGVuZDsKICAgICAgICB0eXBlbmFtZSBzdGQ6Om1hcDxLLCBUPjo6aXRlcmF0b3IgaXQ7CiAgICB9OwoKICAgIHZpcnR1YWwgaXRlcmF0b3IgYmVnaW4oKTsKCiAgICB2aXJ0dWFsIGl0ZXJhdG9yIGVuZCgpOwoKICAgIHZpcnR1YWwgaXRlcmF0b3IgZmluZChjb25zdCBLJiBrKTsKCiAgICBjbGFzcyBlZGdlCiAgICB7CiAgICBwdWJsaWM6CgogICAgICAgIGVkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyLCBjb25zdCBXJiB3ID0gMCkgOgogICAgICAgIGt5MShrMSksIGt5MihrMiksIHd0KHcpCiAgICAgICAgewogICAgICAgIH0KCiAgICAgICAgYm9vbCBvcGVyYXRvcj09KGNvbnN0IGVkZ2UmIGUpIGNvbnN0CiAgICAgICAgewogICAgICAgICAgICByZXR1cm4ga2V5MSgpID09IGUua2V5MSgpICYmIGtleTIoKSA9PSBlLmtleTIoKTsKICAgICAgICB9CgogICAgICAgIGJvb2wgb3BlcmF0b3IhPShjb25zdCBlZGdlJiBlKSBjb25zdAogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIGtleTEoKSAhPSBlLmtleTEoKSB8fCBrZXkyKCkgIT0gZS5rZXkyKCk7CiAgICAgICAgfQoKICAgICAgICBjb25zdCBLJiBrZXkxKCkgY29uc3QKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBreTE7CiAgICAgICAgfQoKICAgICAgICBjb25zdCBLJiBrZXkyKCkgY29uc3QKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBreTI7CiAgICAgICAgfQoKCiAgICAgICAgY29uc3QgSyYga2V5KGNvbnN0IEsmIGspOwoKICAgICAgICBLJiB3ZWlnaHQoKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIHd0OwogICAgICAgIH0KCiAgICBwcml2YXRlOgogICAgICAgIEsga3kxOwogICAgICAgIEsga3kyOwogICAgICAgIFcgd3Q7CiAgICB9OwoKICAgIHZpcnR1YWwgYm9vbCBpc19lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikgPSAwOwoKICAgIGNsYXNzIGVkZ2VfaXRlcmF0b3IKICAgIHsKICAgICAgICBmcmllbmQgY2xhc3MgX2Jhc2VfZ3JhcGg8SywgVywgVD47CiAgICBwdWJsaWM6CiAgICAgICAgZWRnZV9pdGVyYXRvciYgb3BlcmF0b3IrKygpOwogICAgICAgIGVkZ2VfaXRlcmF0b3Igb3BlcmF0b3IrKyhpbnQpOwogICAgICAgIGVkZ2VfaXRlcmF0b3ImIG9wZXJhdG9yLS0oKTsKICAgICAgICBlZGdlX2l0ZXJhdG9yIG9wZXJhdG9yLS0oaW50KTsKCiAgICAgICAgZWRnZSYgb3BlcmF0b3IqKCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAqaXQ7CiAgICAgICAgfQoKICAgICAgICBlZGdlKiBvcGVyYXRvci0+ICgpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gJigqaXQpOwogICAgICAgIH0KCiAgICAgICAgYm9vbCBvcGVyYXRvcj09KGNvbnN0IGVkZ2VfaXRlcmF0b3ImIGkpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gaXQgPT0gaS5pdDsKICAgICAgICB9CgogICAgICAgIGJvb2wgb3BlcmF0b3IhPShjb25zdCBlZGdlX2l0ZXJhdG9yJiBpKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIGl0ICE9IGkuaXQ7CiAgICAgICAgfQoKICAgIHByaXZhdGU6CiAgICAgICAgdHlwZW5hbWUgc3RkOjpsaXN0PGVkZ2U+OjppdGVyYXRvciBiZWdpbiwgZW5kOwogICAgICAgIHR5cGVuYW1lIHN0ZDo6bGlzdDxlZGdlPjo6aXRlcmF0b3IgaXQ7CgogICAgICAgIEsga2V5OwogICAgfTsKCiAgICBlZGdlX2l0ZXJhdG9yIGJlZ2luKGNvbnN0IEsmIGspOwoKICAgIGVkZ2VfaXRlcmF0b3IgZW5kKGNvbnN0IEsmIGspOwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGPgogICAgRiBCRlMoY29uc3QgSyYgaywgRiBmKTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRj4KICAgIEYgREZTKGNvbnN0IEsmIGssIEYgZik7Cgpwcm90ZWN0ZWQ6CiAgICBzdGQ6Om1hcDxLLCBUPiBub2Q7CiAgICBzdGQ6Omxpc3Q8ZWRnZT4gZWRnOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+Cl9iYXNlX2dyYXBoPEssIFcsIFQ+OjpfYmFzZV9ncmFwaChzaXplX3QgbikKewogICAgSyBrZXkoMSk7CgogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgbm9kW2tleSsrXSA9IFQoKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+Cl9iYXNlX2dyYXBoPEssIFcsIFQ+OjpfYmFzZV9ncmFwaChzaXplX3QgbiwgY29uc3QgSyYgaykKewogICAgSyBrZXkoayk7CgogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgbm9kW2tleSsrXSA9IFQoKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CnRlbXBsYXRlIDx0eXBlbmFtZSBGPgpfYmFzZV9ncmFwaDxLLCBXLCBUPjo6X2Jhc2VfZ3JhcGgoc2l6ZV90IG4sIEYgZikKewogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgbm9kW2YoKV0gPSBUKCk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgp2b2lkIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjphZGRfbm9kZShjb25zdCBLJiBrKQp7CiAgICBpZiAobm9kLmZpbmQoaykgIT0gbm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJfYmFzZV9ncmFwaDo6YWRkX25vZGUgLSBub2RlIGFscmVhZHkgZXhpc3RzIik7CiAgICBub2Rba10gPSBUKCk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgp2b2lkIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjphZGRfbm9kZShjb25zdCBLJiBrLCBjb25zdCBUJiB0KQp7CiAgICBpZiAobm9kLmZpbmQoaykgIT0gbm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJfYmFzZV9ncmFwaDo6YWRkX25vZGUgLSBub2RlIGFscmVhZHkgZXhpc3RzIik7CiAgICBub2Rba10gPSB0Owp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46Oml0ZXJhdG9yIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjpiZWdpbigpCnsKICAgIGl0ZXJhdG9yIGk7CiAgICBpLmJlZ2luID0gbm9kLmJlZ2luKCk7CiAgICBpLmVuZCA9IG5vZC5lbmQoKTsKCiAgICBpLml0ID0gaS5iZWdpbjsKCiAgICByZXR1cm4gaTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CnR5cGVuYW1lIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjplZGdlX2l0ZXJhdG9yIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjpiZWdpbihjb25zdCBLJiBrKQp7CiAgICBlZGdlX2l0ZXJhdG9yIGk7CiAgICBpLmJlZ2luID0gZWRnLmJlZ2luKCk7CiAgICBpLmVuZCA9IGVkZy5lbmQoKTsKICAgIGkua2V5ID0gazsKCiAgICBpLml0ID0gaS5iZWdpbjsKICAgIHdoaWxlIChpLml0ICE9IGkuZW5kICYmIGkuaXQtPmtleTEoKSAhPSBpLmtleSAmJiBpLml0LT5rZXkyKCkgIT0gaS5rZXkpCiAgICB7CiAgICAgICAgaS5pdCsrOwogICAgfQoKICAgIHJldHVybiBpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46Oml0ZXJhdG9yIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjplbmQoKQp7CiAgICBpdGVyYXRvciBpOwogICAgaS5iZWdpbiA9IG5vZC5iZWdpbigpOwogICAgaS5lbmQgPSBub2QuZW5kKCk7CgogICAgaS5pdCA9IGkuZW5kOwoKICAgIHJldHVybiBpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVkZ2VfaXRlcmF0b3IgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVuZChjb25zdCBLJiBrKQp7CiAgICBlZGdlX2l0ZXJhdG9yIGk7CiAgICBpLmJlZ2luID0gZWRnLmJlZ2luKCk7CiAgICBpLmVuZCA9IGVkZy5lbmQoKTsKICAgIGkua2V5ID0gazsKCiAgICBpLml0ID0gaS5lbmQ7CgogICAgcmV0dXJuIGk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgp0eXBlbmFtZSBfYmFzZV9ncmFwaDxLLCBXLCBUPjo6aXRlcmF0b3IgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmZpbmQoY29uc3QgSyYgaykKewogICAgaXRlcmF0b3IgaTsKICAgIGkuYmVnaW4gPSBub2QuYmVnaW4oKTsKICAgIGkuZW5kID0gbm9kLmVuZCgpOwogICAgaS5pdCA9IG5vZC5maW5kKGspOwoKICAgIHJldHVybiBpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdGVtcGxhdGUgPHR5cGVuYW1lIEY+CkYgX2Jhc2VfZ3JhcGg8SywgVywgVD46OkJGUyhjb25zdCBLJiBrLCBGIGYpCnsKICAgIEsgY3VyOwogICAgc3RkOjpxdWV1ZTxLPiBxOwogICAgc3RkOjpzZXQ8Sz4gdjsKCiAgICBxLnB1c2goayk7CiAgICB2Lmluc2VydChrKTsKCiAgICB3aGlsZSAoIXEuZW1wdHkoKSkKICAgIHsKCiAgICAgICAgY3VyID0gcS5mcm9udCgpOwogICAgICAgIHEucG9wKCk7CiAgICAgICAgZihjdXIpOwoKICAgICAgICBmb3IgKGl0ZXJhdG9yIGkgPSBiZWdpbigpOyBpICE9IGVuZCgpOyBpKyspCiAgICAgICAgICAgIGlmIChpc19lZGdlKGN1ciwgaS0+Zmlyc3QpKQogICAgICAgICAgICAgICAgaWYgKHYuZmluZChpLT5maXJzdCkgPT0gdi5lbmQoKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBxLnB1c2goaS0+Zmlyc3QpOwogICAgICAgICAgICAgICAgICAgIHYuaW5zZXJ0KGktPmZpcnN0KTsKICAgICAgICAgICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZjsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CnRlbXBsYXRlIDx0eXBlbmFtZSBGPgpGIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjpERlMoY29uc3QgSyYgaywgRiBmKQp7CiAgICBLIGN1ciA9IGs7CiAgICBzdGQ6OnNldDxLPiB2OwogICAgc3RkOjpzdGFjazxLPiBzOwoKICAgIGRvCiAgICB7CiAgICAgICAgaWYgKHYuZmluZChjdXIpID09IHYuZW5kKCkpCiAgICAgICAgewogICAgICAgICAgICBmKGN1cik7CiAgICAgICAgICAgIHMucHVzaChjdXIpOwogICAgICAgICAgICB2Lmluc2VydChjdXIpOwogICAgICAgIH0KICAgICAgICBpdGVyYXRvciBpID0gYmVnaW4oKTsKICAgICAgICB3aGlsZSAoaSAhPSBlbmQoKSAmJiB2LmZpbmQoaS0+Zmlyc3QpICE9IHYuZW5kKCkpCiAgICAgICAgICAgIGkrKzsKICAgICAgICBpZiAoaSAhPSBlbmQoKSkKICAgICAgICAgICAgY3VyID0gaS0+Zmlyc3Q7CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgcy5wb3AoKTsKICAgICAgICAgICAgaWYgKCFzLmVtcHR5KCkpCiAgICAgICAgICAgICAgICBjdXIgPSBzLnRvcCgpOwogICAgICAgIH0KICAgIH0KICAgIHdoaWxlICghcy5lbXB0eSgpKTsKCiAgICByZXR1cm4gZjsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+ClQmIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjpvcGVyYXRvcltdIChjb25zdCBLJiBrKQp7CiAgICBpZiAobm9kLmZpbmQoaykgPT0gbm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJfYmFzZV9ncmFwaDo6b3BlcmF0b3JbXSAtIG5vZGUgZG9lcyBub3QgZXhpc3QiKTsKICAgIHJldHVybiBub2Rba107Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgpjb25zdCBLJiBfYmFzZV9ncmFwaDxLLCBXLCBUPjo6ZWRnZTo6a2V5KGNvbnN0IEsmIGspCnsKICAgIGlmIChrICE9IGtleTEoKSAmJiBrICE9IGtleTIoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiZ3JhcGg6OmVkZ2U6OmtleSAtIGtleSBzdXBwbGllZCBpcyBpbnZhbGlkIik7CgogICAgcmV0dXJuIGsgPT0ga2V5MSgpID8ga2V5MigpIDoga2V5MSgpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVkZ2VfaXRlcmF0b3ImIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjplZGdlX2l0ZXJhdG9yOjpvcGVyYXRvcisrKCkKewogICAgKytpdDsKICAgIHdoaWxlIChpdCAhPSBlbmQgJiYgaXQtPmtleTEoKSAhPSBrZXkgJiYgaXQtPmtleTIoKSAhPSBrZXkpCiAgICAgICAgKytpdDsKCiAgICByZXR1cm4gKnRoaXM7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgp0eXBlbmFtZSBfYmFzZV9ncmFwaDxLLCBXLCBUPjo6ZWRnZV9pdGVyYXRvciBfYmFzZV9ncmFwaDxLLCBXLCBUPjo6ZWRnZV9pdGVyYXRvcjo6b3BlcmF0b3IrKyhpbnQpCnsKICAgIGVkZ2VfaXRlcmF0b3IgdG1wID0gKnRoaXM7CgogICAgKytpdDsKICAgIHdoaWxlIChpdCAhPSBlbmQgJiYgaXQtPmtleTEoKSAhPSBrZXkgJiYgaXQtPmtleTIoKSAhPSBrZXkpCiAgICAgICAgKytpdDsKCiAgICByZXR1cm4gdG1wOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVkZ2VfaXRlcmF0b3ImIF9iYXNlX2dyYXBoPEssIFcsIFQ+OjplZGdlX2l0ZXJhdG9yOjpvcGVyYXRvci0tKCkKewogICAgLS1pdDsKICAgIHdoaWxlIChpdCAhPSBiZWdpbiAmJiBpdC0+a2V5MSgpICE9IGtleSAmJiBpdC0+a2V5MigpICE9IGtleSkKICAgICAgICAtLWl0OwogICAgaWYgKGl0ID09IGJlZ2luKQogICAgICAgIHdoaWxlIChpdCAhPSBlbmQgJiYgaXQtPmtleTEoKSAhPSBrZXkgJiYgaXQtPmtleTIoKSAhPSBrZXkpCiAgICAgICAgICAgICsraXQ7CgogICAgcmV0dXJuICp0aGlzOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KdHlwZW5hbWUgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVkZ2VfaXRlcmF0b3IgX2Jhc2VfZ3JhcGg8SywgVywgVD46OmVkZ2VfaXRlcmF0b3I6Om9wZXJhdG9yLS0oaW50KQp7CiAgICBlZGdlX2l0ZXJhdG9yIHRtcCA9ICp0aGlzOwoKICAgIC0taXQ7CiAgICB3aGlsZSAoaXQgIT0gYmVnaW4gJiYgaXQtPmtleTEoKSAhPSBrZXkgJiYgaXQtPmtleTIoKSAhPSBrZXkpCiAgICAgICAgLS1pdDsKICAgIGlmIChpdCA9PSBiZWdpbikKICAgICAgICB3aGlsZSAoaXQgIT0gZW5kICYmIGl0LT5rZXkxKCkgIT0ga2V5ICYmIGl0LT5rZXkyKCkgIT0ga2V5KQogICAgICAgICAgICArK2l0OwoKICAgIHJldHVybiB0bXA7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBjbGFzcyBncmFwaCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBUID0gdm9pZCo+CiAgICAgICAgY2xhc3MgZ3JhcGggOiBwdWJsaWMgX2Jhc2VfZ3JhcGg8Sywgdm9pZCosIFQ+CnsKcHVibGljOgoKICAgIGdyYXBoKCkgOiBfYmFzZV9ncmFwaDxLLCB2b2lkKiwgVD4oKQogICAgewogICAgfQoKICAgIGdyYXBoKHNpemVfdCBuKSA6IF9iYXNlX2dyYXBoPEssIHZvaWQqLCBUPihuKQogICAgewogICAgfQoKICAgIGdyYXBoKHNpemVfdCBuLCBjb25zdCBLJiBrKSA6IF9iYXNlX2dyYXBoPEssIHZvaWQqLCBUPihuLCBrKQogICAgewogICAgfQoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGPgogICAgZ3JhcGgoc2l6ZV90IG4sIEYgZikgOiBfYmFzZV9ncmFwaDxLLCB2b2lkKiwgVD4obiwgZikKICAgIHsKICAgIH0KCiAgICB2b2lkIGFkZF9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7CgogICAgYm9vbCBpc19lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7CgogICAgdm9pZCByZW1vdmVfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIpOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFQ+CnZvaWQgZ3JhcGg8SywgVD46OmFkZF9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiYWRkX2VkZ2U6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKCiAgICAvLyBTdG9yZSBsb3dlciBrZXkgdmFsdWUgaW4gZmlyc3Qga2V5IG9mIGVkZ2UKICAgIGlmIChrMSA8IGsyKQogICAgICAgIHRoaXMtPmVkZy5wdXNoX2JhY2soZWRnZShrMSwgazIpKTsKICAgIGVsc2UKICAgICAgICB0aGlzLT5lZGcucHVzaF9iYWNrKGVkZ2UoazIsIGsxKSk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBUPgpib29sIGdyYXBoPEssIFQ+Ojppc19lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiaXNfZWRnZTogTm9kZSBkb2VzIG5vdCBleGlzdCIpOwogICAgCiAgICBpZiAoazEgPCBrMikKICAgICAgICByZXR1cm4gc3RkOjpmaW5kKHRoaXMtPmVkZy5iZWdpbigpLCB0aGlzLT5lZGcuZW5kKCksIGVkZ2UoazEsIGsyKSkgIT0gdGhpcy0+ZWRnLmVuZCgpOwogICAgcmV0dXJuIHN0ZDo6ZmluZCh0aGlzLT5lZGcuYmVnaW4oKSwgdGhpcy0+ZWRnLmVuZCgpLCBlZGdlKGsyLCBrMSkpICE9IHRoaXMtPmVkZy5lbmQoKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFQ+CnZvaWQgZ3JhcGg8SywgVD46OnJlbW92ZV9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiYWRkX2VkZ2U6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKCiAgICBpZiAoazEgPCBrMikKICAgICAgICB0aGlzLT5lZGcucmVtb3ZlKGVkZ2UoazEsIGsyKSk7CiAgICBlbHNlCiAgICAgICAgdGhpcy0+ZWRnLnJlbW92ZShlZGdlKGsyLCBrMSkpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogY2xhc3Mgd2dyYXBoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVCA9IHZvaWQqPgogICAgICAgIGNsYXNzIHdncmFwaCA6IHB1YmxpYyBfYmFzZV9ncmFwaDxLLCBXLCBUPgp7CnB1YmxpYzoKCiAgICB3Z3JhcGgoKSA6IF9iYXNlX2dyYXBoPEssIFcsIFQ+KCkKICAgIHsKICAgIH0KCiAgICB3Z3JhcGgoc2l6ZV90IG4pIDogX2Jhc2VfZ3JhcGg8SywgVywgVD4obikKICAgIHsKICAgIH0KCiAgICB3Z3JhcGgoc2l6ZV90IG4sIGNvbnN0IEsmIGspIDogX2Jhc2VfZ3JhcGg8SywgVywgVD4obiwgaykKICAgIHsKICAgIH0KCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRj4KICAgIHdncmFwaChzaXplX3QgbiwgRiBmKSA6IF9iYXNlX2dyYXBoPEssIFcsIFQ+KG4sIGYpCiAgICB7CiAgICB9CgogICAgdm9pZCBhZGRfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIsIGNvbnN0IFcmIHcpOwoKICAgIGJvb2wgaXNfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIpOwoKICAgIHZvaWQgcmVtb3ZlX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKTsKCiAgICBXJiB3ZWlnaHQoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKTsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgp2b2lkIHdncmFwaDxLLCBXLCBUPjo6YWRkX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyLCBjb25zdCBXJiB3KQp7CiAgICBpZiAodGhpcy0+bm9kLmZpbmQoazEpID09IHRoaXMtPm5vZC5lbmQoKSB8fCB0aGlzLT5ub2QuZmluZChrMikgPT0gdGhpcy0+bm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJhZGRfZWRnZTogTm9kZSBkb2VzIG5vdCBleGlzdCIpOwoKICAgIC8vIFN0b3JlIGxvd2VyIGtleSB2YWx1ZSBpbiBmaXJzdCBrZXkgb2YgZWRnZQogICAgaWYgKGsxIDwgazIpCiAgICAgICAgdGhpcy0+ZWRnLnB1c2hfYmFjayhlZGdlKGsxLCBrMiwgdykpOwogICAgZWxzZQogICAgICAgIHRoaXMtPmVkZy5wdXNoX2JhY2soZWRnZShrMiwgazEsIHcpKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CmJvb2wgd2dyYXBoPEssIFcsIFQ+Ojppc19lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiaXNfZWRnZTogTm9kZSBkb2VzIG5vdCBleGlzdCIpOwoKICAgIGlmIChrMSA8IGsyKQogICAgICAgIHJldHVybiBzdGQ6OmZpbmQodGhpcy0+ZWRnLmJlZ2luKCksIHRoaXMtPmVkZy5lbmQoKSwgZWRnZShrMSwgazIpKSAhPSB0aGlzLT5lZGcuZW5kKCk7CiAgICByZXR1cm4gc3RkOjpmaW5kKHRoaXMtPmVkZy5iZWdpbigpLCB0aGlzLT5lZGcuZW5kKCksIGVkZ2UoazIsIGsxKSkgIT0gdGhpcy0+ZWRnLmVuZCgpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4Kdm9pZCB3Z3JhcGg8SywgVywgVD46OnJlbW92ZV9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiYWRkX2VkZ2U6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKCiAgICBpZiAoazEgPCBrMikKICAgICAgICB0aGlzLT5lZGcucmVtb3ZlKGVkZ2UoazEsIGsyKSk7CiAgICBlbHNlCiAgICAgICAgdGhpcy0+ZWRnLnJlbW92ZShlZGdlKGsyLCBrMSkpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4KVyYgd2dyYXBoPEssIFcsIFQ+Ojp3ZWlnaHQoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKQp7CiAgICBpZiAodGhpcy0+bm9kLmZpbmQoazEpID09IHRoaXMtPm5vZC5lbmQoKSB8fCB0aGlzLT5ub2QuZmluZChrMikgPT0gdGhpcy0+bm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJ3ZWlnaHQ6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKICAgIGlmICghaXNfZWRnZShrMSwgazIpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJ3ZWlnaHQ6IEVkZ2UgZG9lcyBub3QgZXhpc3QiKTsKCiAgICBpZiAoazEgPCBrMikKICAgICAgICByZXR1cm4gc3RkOjpmaW5kKHRoaXMtPmVkZy5iZWdpbigpLCB0aGlzLT5lZGcuZW5kKCksIGVkZ2UoazEsIGsyKSktPndlaWdodCgpOwogICAgcmV0dXJuIHN0ZDo6ZmluZCh0aGlzLT5lZGcuYmVnaW4oKSwgdGhpcy0+ZWRnLmVuZCgpLCBlZGdlKGsyLCBrMSkpLT53ZWlnaHQoKTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIGNsYXNzIGRpZ3JhcGggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFQgPSB2b2lkKj4KICAgICAgICBjbGFzcyBkaWdyYXBoIDogcHVibGljIF9iYXNlX2dyYXBoPEssIHZvaWQqLCBUPgp7CnB1YmxpYzoKCiAgICBkaWdyYXBoKCkgOiBfYmFzZV9ncmFwaDxLLCB2b2lkKiwgVD4oKQogICAgewogICAgfQoKICAgIGRpZ3JhcGgoc2l6ZV90IG4pIDogX2Jhc2VfZ3JhcGg8Sywgdm9pZCosIFQ+KG4pCiAgICB7CiAgICB9CgogICAgZGlncmFwaChzaXplX3QgbiwgY29uc3QgSyYgaykgOiBfYmFzZV9ncmFwaDxLLCB2b2lkKiwgVD4obiwgaykKICAgIHsKICAgIH0KCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRj4KICAgIGRpZ3JhcGgoc2l6ZV90IG4sIEYgZikgOiBfYmFzZV9ncmFwaDxLLCB2b2lkKiwgVD4obiwgZikKICAgIHsKICAgIH0KCiAgICB2b2lkIGFkZF9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7CgogICAgYm9vbCBpc19lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7CgogICAgdm9pZCByZW1vdmVfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIpOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFQ+CnZvaWQgZGlncmFwaDxLLCBUPjo6YWRkX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKQp7CiAgICBpZiAodGhpcy0+bm9kLmZpbmQoazEpID09IHRoaXMtPm5vZC5lbmQoKSB8fCB0aGlzLT5ub2QuZmluZChrMikgPT0gdGhpcy0+bm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJhZGRfZWRnZTogTm9kZSBkb2VzIG5vdCBleGlzdCIpOwoKICAgIHRoaXMtPmVkZy5wdXNoX2JhY2soZWRnZShrMSwgazIpKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFQ+CmJvb2wgZGlncmFwaDxLLCBUPjo6aXNfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIpCnsKICAgIGlmICh0aGlzLT5ub2QuZmluZChrMSkgPT0gdGhpcy0+bm9kLmVuZCgpIHx8IHRoaXMtPm5vZC5maW5kKGsyKSA9PSB0aGlzLT5ub2QuZW5kKCkpCiAgICAgICAgdGhyb3cgc3RkOjpzdHJpbmcoImlzX2VkZ2U6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKCiAgICByZXR1cm4gc3RkOjpmaW5kKHRoaXMtPmVkZy5iZWdpbigpLCB0aGlzLT5lZGcuZW5kKCksIGVkZ2UoazEsIGsyKSkgIT0gdGhpcy0+ZWRnLmVuZCgpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVD4Kdm9pZCBkaWdyYXBoPEssIFQ+OjpyZW1vdmVfZWRnZShjb25zdCBLJiBrMSwgY29uc3QgSyYgazIpCnsKICAgIGlmICh0aGlzLT5ub2QuZmluZChrMSkgPT0gdGhpcy0+bm9kLmVuZCgpIHx8IHRoaXMtPm5vZC5maW5kKGsyKSA9PSB0aGlzLT5ub2QuZW5kKCkpCiAgICAgICAgdGhyb3cgc3RkOjpzdHJpbmcoImFkZF9lZGdlOiBOb2RlIGRvZXMgbm90IGV4aXN0Iik7CgogICAgdGhpcy0+ZWRnLnJlbW92ZShlZGdlKGsxLCBrMikpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogY2xhc3Mgd2RpZ3JhcGggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVCA9IHZvaWQqPgogICAgICAgIGNsYXNzIHdkaWdyYXBoIDogcHVibGljIF9iYXNlX2dyYXBoPEssIFcsIFQ+CnsKcHVibGljOgoKICAgIHdkaWdyYXBoKCkgOiBfYmFzZV9ncmFwaDxLLCBXLCBUPigpCiAgICB7CiAgICB9CgogICAgd2RpZ3JhcGgoc2l6ZV90IG4pIDogX2Jhc2VfZ3JhcGg8SywgVywgVD4obikKICAgIHsKICAgIH0KCiAgICB3ZGlncmFwaChzaXplX3QgbiwgY29uc3QgSyYgaykgOiBfYmFzZV9ncmFwaDxLLCBXLCBUPihuLCBrKQogICAgewogICAgfQoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGPgogICAgd2RpZ3JhcGgoc2l6ZV90IG4sIEYgZikgOiBfYmFzZV9ncmFwaDxLLCBXLCBUPihuLCBmKQogICAgewogICAgfQoKICAgIHZvaWQgYWRkX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyLCBjb25zdCBXJiB3KTsKCiAgICBib29sIGlzX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKTsKCiAgICB2b2lkIHJlbW92ZV9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7CgogICAgVyYgd2VpZ2h0KGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMik7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSywgdHlwZW5hbWUgVywgdHlwZW5hbWUgVD4Kdm9pZCB3ZGlncmFwaDxLLCBXLCBUPjo6YWRkX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyLCBjb25zdCBXJiB3KQp7CiAgICBpZiAodGhpcy0+bm9kLmZpbmQoazEpID09IHRoaXMtPm5vZC5lbmQoKSB8fCB0aGlzLT5ub2QuZmluZChrMikgPT0gdGhpcy0+bm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJhZGRfZWRnZTogTm9kZSBkb2VzIG5vdCBleGlzdCIpOwoKICAgIHRoaXMtPmVkZy5wdXNoX2JhY2soZWRnZShrMSwgazIsIHcpKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CmJvb2wgd2RpZ3JhcGg8SywgVywgVD46OmlzX2VkZ2UoY29uc3QgSyYgazEsIGNvbnN0IEsmIGsyKQp7CiAgICBpZiAodGhpcy0+bm9kLmZpbmQoazEpID09IHRoaXMtPm5vZC5lbmQoKSB8fCB0aGlzLT5ub2QuZmluZChrMikgPT0gdGhpcy0+bm9kLmVuZCgpKQogICAgICAgIHRocm93IHN0ZDo6c3RyaW5nKCJpc19lZGdlOiBOb2RlIGRvZXMgbm90IGV4aXN0Iik7CgogICAgcmV0dXJuIHN0ZDo6ZmluZCh0aGlzLT5lZGcuYmVnaW4oKSwgdGhpcy0+ZWRnLmVuZCgpLCBlZGdlKGsxLCBrMikpICE9IHRoaXMtPmVkZy5lbmQoKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEssIHR5cGVuYW1lIFcsIHR5cGVuYW1lIFQ+CnZvaWQgd2RpZ3JhcGg8SywgVywgVD46OnJlbW92ZV9lZGdlKGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygiYWRkX2VkZ2U6IE5vZGUgZG9lcyBub3QgZXhpc3QiKTsKCiAgICB0aGlzLT5lZGcucmVtb3ZlKGVkZ2UoazEsIGsyKSk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBLLCB0eXBlbmFtZSBXLCB0eXBlbmFtZSBUPgpXJiB3ZGlncmFwaDxLLCBXLCBUPjo6d2VpZ2h0KGNvbnN0IEsmIGsxLCBjb25zdCBLJiBrMikKewogICAgaWYgKHRoaXMtPm5vZC5maW5kKGsxKSA9PSB0aGlzLT5ub2QuZW5kKCkgfHwgdGhpcy0+bm9kLmZpbmQoazIpID09IHRoaXMtPm5vZC5lbmQoKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygid2VpZ2h0OiBOb2RlIGRvZXMgbm90IGV4aXN0Iik7CiAgICBpZiAoIWlzX2VkZ2UoazEsIGsyKSkKICAgICAgICB0aHJvdyBzdGQ6OnN0cmluZygid2VpZ2h0OiBFZGdlIGRvZXMgbm90IGV4aXN0Iik7CgogICAgcmV0dXJuIHN0ZDo6ZmluZCh0aGlzLT5lZGcuYmVnaW4oKSwgdGhpcy0+ZWRnLmVuZCgpLCBlZGdlKGsxLCBrMikpLT53ZWlnaHQoKTsKfQoKfSAvLyBuYW1lc3BhY2UgZ3RjCgoKaW50IG1haW4oKQp7CiAgICBndGM6OmdyYXBoPGludD4gZzsKICAgIHJldHVybiAwOwp9