Cod sursa(job #954951)

Utilizator mgntMarius B mgnt Data 30 mai 2013 15:28:26
Problema Abc2 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 22.46 kb

// http://infoarena.ro/problema/abc2
// 
// Folosesc abordarea de aici:
// http://www.infoarena.ro/job_detail/98260?action=view-source
// 
// Construiesc un trie.
// Schimb trie-ul, într-un dfa.
// Identific pozițiile candidat, cu dfa-ul.
// 
// Timpul pentru construirea trie-ului:  O(z·n)
// Timpul pentru schimbarea trie-ului, în dfa: O(z·n·w)
// Timpul pentru identificarea pozițiiloe candidat, cu dfa-ul: O(m).
// z - numărul cuvintelor, z ≤ 50 000
// n - lungimea fiecărui cuvânt, n ≤ 20
// w - cardinalul mulțimii literelor folosite de cuvinte, w = 3
// m - numărul literelor din textul antic, m ≤ 10 000 000
// .
// 
// O(max(m,z·n·w, z·n)
// .

// http://www.infoarena.ro/job_detail/98260?action=view-source
// awesome

#include <cstddef>
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
#include <set>
// cstring declares ::std::strlen
#include <cstring>

namespace abc2
{

size_t  const thew  = 3; // the w constant
size_t  const thew1 = (1+thew);
size_t  const maxn  = 50000;
size_t  const maxc  = 20;
size_t  const maxc2 = 2+maxc;
size_t  const maxv  = (maxn*maxc);
size_t  const maxv2 = (2+maxv);
size_t  const maxm  = 10000000;
size_t  const maxm2 = (2+maxm);

typedef  ::std::size_t  abcf_node[thew1];
typedef  ::std::size_t  bft_queue[maxv2];


typedef  int unsigned  uint32; // may be more than 32

/// \brief  All the data used to solve the problem.
///         The input and extra space used for computing the output.
struct  abc2_data
{ /// \brief  Space to store the ancient text.
  char  m_text_symbols[maxm2];
  /// \brief  The length of the ancient text.
  size_t  m_text_size;
  
  /// \brief  Space to store all the words in the Makako language
  ///         , one word after the other, with no separator.
  char  m_words_symbols[maxv2];
  ///        The number of words in the Makako language.
  ::std::size_t  m_number_of_words;
  ///        The length of each word in the Makako language.
  ::std::size_t  m_word_size;
  
  /// \brief  The trie.
  /// 
  /// m_nodes[x][i]    == y ↔ (x) --['a'+i]-->(y), i=0..thew-1
  /// m_nodes[x][thew]  ≠ 0 ↔ x is a leaf in the trie
  ::std::size_t  m_trie[maxv2][thew1];
  
  /// \brief  The dfa.
  /// 
  /// m_nodes[x][i]    == y ↔ (x) --['a'+i]-->(y), i=0..thew-1
  /// m_nodes[x][thew]  ≠ 0 ↔ x is a final state in the dfa
  ::std::size_t  m_dfa[maxv2][thew1];
  
  /// \brief  The queue used in the breadth-first-traversal
  ///         of states of the dfa.
  ::std::size_t  m_bft[maxv2];
  
  /// \brief  Number of occurrences;
  ::std::size_t  m_number_of_occurrences;
  
} // struct abc2_state
;

// ______________________________________________________________________________

/// \brief  Constructs the trie, from the words.
class trie_build_processing
{ private:
  
  abc2_data  & m_data;
  
  public:
  
  trie_build_processing
  ( abc2_data  & data
  )
  throw()
  : m_data(data)
  { this->build_trie();
  }
  
  private:
  
  void
  build_trie
  ()
  throw()
  ;
  
} // class trie_build_processing
;

void
trie_build_processing::build_trie
()
throw()
{ //  Interation for all words:
  ::std::size_t           s = 0; // The number of nodes in the trie.
  ::std::size_t           i;
  abc2_data             & d    = this->m_data;
  abcf_node             * trie = d.m_trie;
  ::std::size_t     const z    = d.m_number_of_words;
  ::std::size_t     const n    = d.m_word_size;
  char                  * p    = d.m_words_symbols; // the current word
  // Iteration for a word:
  ::std::size_t           x; // position in the trie
  ::std::size_t           j; // position in the current word
  ::std::size_t           c; // current symbol in the current word
  ::std::size_t           y; // next position in the trie
  // Iteration for symbols.
  ::std::size_t           t;
  
  for(t=0; thew > t; ++t)
  { trie[s][t] = 0; }
  trie[s][thew] = 0; // not a leaf
  ++s;
  
  for(i=0; z>i; ++i)
  { // Add current word, into the trie.
    x = 0;
    for(j=0; n>j; ++j)
    { c  = p[j]; // c is 0, 1, or 2.
      y = trie[x][c];
      if(0 == y)
      { for(t=0; thew > t; ++t)
        { trie[s][t] = 0; }
        trie[s][thew] = 0; // not a leaf
        trie[x][c] = s; y = s; ++s;
      }
      
      x = y;
    }
    
    trie[x][thew] = 1; // a leaf
    
    // Update position of the current word.
    p += n;
  }
  
}

// ______________________________________________________________________________



// ###############################################################################
// ###############################################################################
// ###############################################################################




// Ce proprietăți are automatul finit determinist, cu care vom determina
// pozițiile în T, unde se regăsesc șiruri de simboluri din P?
// 
// _______________________________________________________________________________
// Σ este o mulțime finită, oarecare.
// Σ* - șirurilor finite peste Σ.
// ε  - șirul fără nici o componentă.
// ε ∈ Σ* .    Σ+ = Σ* ∖ {ε}.
// 
// P ⊂ Σ+ este o mulțime finită.
// ( P e mulțimea șirurilor pe care le căutăm în șirul T. )
// 
// x ∈ Σ+, y ∈ Σ+, i ∈ ℤ, S ⊂ Σ+, S mulțime finită
// λ(x)   : lungimea șirului x.
// α(x,i) : prefixul de lungime i, al lui șirului x, atunci când 0 ≤ i ≤ λ(x)
// ω(x,i) : sufixul de lungime i, al șirului x, atunci când 0 ≤ i ≤ λ(x)
// ω(x,0) = ε
// x ⊏ y  : (  ( λ(y) > λ(x) ) ∧ ( x = α(y,λ(x)) )  )
// x ⊐ y  : (  ( λ(y) > λ(x) ) ∧ ( x = ω(y,λ(x)) )  )
// σ(y) = { x ∈ Σ+ | x ⊐ y }
// π(S) = { x ∈ Σ+ | ∃ y ∈ S (x ⊏ y) }
// 
// β(x) = ω(x,max { 0 } ∪ { i ∈ ℤ | 1≤ i ≤ λ(x) ∧ ω(x,i) ∈ π(P) }), ∀ x ∈ Σ+
// _______________________________________________________________________________
// 
// Fie D = (Q,Σ,δ,q₀,F) automatul finit construit de acest program.
// 
// γ : Σ* → Q, astfel încât γ(ε)  = q₀, și ∀ σ ∈ Σ* ∀ c ∈ Σ  γ(σc) = δ(γ(σ),c)
// τ : Σ* → ℘(Q), astfel încât τ(ε) = {q₀}, și ∀ σ∈Σ* ∀c∈Σ τ(σc) = τ(σ) ∪ {γ(σc) }
// 
// D are următoarele proprietăți:
//  
//  ▪ q₀ = 0
//    
//  ▪ ∀ q ∈ Q ( ( q₀ = q ) ∨ ( ∃ x ∈ π(P) ∪ P (q = γ(x)) )  )
//    
//  ▪ ∀ x ∈ P ( τ(x) = 1 + λ(x) )
//    
//  ▪ ∀ x ∈ π(P) ∀ c ∈ Σ ( ((xc ∉ π(P) ) ∧ (xc ∉ P)) → (δ(γ(x),c) = γ(β(xc)) )  )
// 
// _______________________________________________________________________________
// Care sunt proprietățiile funcției β?
// 
// Pentru x ∈ π(P) ∪ P, c ∈ Σ, următoarele sunt proprietăți ale funcției β:
//    
//  ▪ β(x)c ∈ π(P) → β(xc) = β(x)c
//    
//  ▪ β(x)c ∉ π(P) → β(xc) = ε



// ###############################################################################
// ###############################################################################
// ###############################################################################



// _______________________________________________________________________________
// The breadth first traversal is needed to compute β, because the breadth
// first traversal explores nodes x, before node y, if the path from the root
// to node x, has fewer edges than the path from the root, to node y.
// 
// Consider the example:
//    P = { cccccccbaaaaaa
//        , aaaaaaaaaaaaaa
//        }
// What is the function β, for P.
//  β(cccccccbaa) = aa
//  It is not possible to derive aa, from cccccccbaa ∈ P alone.
//  The value aa is derived from aaaaaaaaaaaaaa ∈ P.
//  
// This is what the breadh first traversal does:    it prepares values
// needed for computing β, using the recurrence relation.


/// \brief  Constructs the dfa, from the trie.
class dfa_build_processing
{ private:
  
  abc2_data  & m_data;
  
  public:
  
  dfa_build_processing
  ( abc2_data  & data
  )
  throw()
  : m_data(data)
  { this->build_dfa();
  }
  
  private:
  
  void
  build_dfa
  ()
  throw()
  ;
  
} // class dfa_build_processing
;

void
dfa_build_processing::build_dfa // method
()
throw()
{ abc2_data      & d    = this->m_data; // data / context
  abcf_node      * trie = d.m_trie;     // the trie
  abcf_node      * dfa  = d.m_dfa;      // the dfa
  bft_queue      & qa   = d.m_bft;      // queue array
  ::std::size_t    qs   = 0;            // queue size
  ::std::size_t    qi   = 0;            // queue index
  ::std::size_t    x;                   // current state
  ::std::size_t    i;                   // trie: [ x -- [i] --> y ]
  ::std::size_t    y;                   // trie: [ x -- [i] --> y ]
  ::std::size_t    t;                   // x=γ(w), t = γ(β(w·i)), for some w ∈ Σ*
  ::std::size_t    j;                   //  dfa: [ y --[j] --> z  ]
  ::std::size_t    z;                   //  dfa: [ y --[j] --> z  ]
  
  for(i=0; thew>i; ++i)
  { dfa[0][i] = 0; }
  
  qa[0] = 0; qi = 0; qs = 1;
  while(qs > qi) // while
  { x = qa[qi]; ++qi; // Extract state from the bft queue.
    
    dfa[x][thew] = trie[x][thew]; // ≠ 0: final state
    
    for(i=0; thew>i; ++i) // for-1
    { y = trie[x][i];
      
      if(0 != y) // if-1
      { qa[qs] = y; ++qs;
        
        t = dfa[x][i]; // Read t, from dfa[x][i].
        dfa[x][i] = y; // Write final value in dfa[x][i].
        
        for(j=0; thew>j; ++j) // for-2
        { z = trie[t][j];
          if(0 == z)
          { z = dfa[t][j]; }
          
          dfa[y][j] = z; // "Write t", in dfa[y][j].
          
        } // for-2
        
      } // if-1
      
    } // for-1
    
  } // while
  
} // method


// ______________________________________________________________________________

/// \brief  Solves the abc2 problem.
class solver
{ private:
  
  abc2_data  & m_data;
  
  public:
  
  solver
  ( abc2_data  & data
  )
  : m_data(data)
  { this->process_words();
    this->count_number_of_occurrences();
  }
  
  private:
  
  void
  process_words
  ()
  ;
  
  void
  count_number_of_occurrences
  ()
  throw()
  ;
} // class solver
;

void
solver::process_words
()
{ // A two pass algorithm for building the dfa used for
  // the multiple pattern matching problem.
  
  abc2_data  & d = this->m_data;
  
  // Construct the trie, from words.
  trie_build_processing  trie_build_processing_object(d);
         // The constructor needs to be evaluated on trie_build_processing_object
         // because its evaluation contains side effects: it changes the state of
         // the m_data object.
  (void) trie_build_processing_object;
  // Construct the dfa, from trie.
  dfa_build_processing  dfa_build_processing_object(d);
         // Same reasoning about side-effects assures that
         // the constructor needs to be evaluated on dfa_build_processing_object.
  (void) dfa_build_processing_object;
}

void
solver::count_number_of_occurrences
()
throw()
{ // Count occurrences, using the dfa.
  abc2_data               & d        = m_data;
  char                    * q        = d.m_text_symbols;
  size_t                    m        = d.m_text_size;
  size_t                    i;         
  size_t                    c;         
  abcf_node               * dfa      = d.m_dfa;
  size_t                    x        = 0;
  size_t                    y;         
  size_t                    num      = 0; // The number of occurrences.
  bool                      match;     
  
  for(i=0 ; m>i; ++i)
  { c = q[i]; // one of 0,1,...,thew-1.
    y = dfa[x][c];
    match = (0 != (dfa[y][thew]) );
    if(match)
    { ++num; }
    x = y;
  }
  
  // no-throw, no-fail
  ::std::size_t  & ans = d.m_number_of_occurrences;
  ans = num;
}

// ______________________________________________________________________________

/// \brief  Shifts input from 'a', 'b', 'c', to '\0x0', '\0x1', '\0x2'
class input_translation
{ private:

  /// \brief  The abc2 data.
  abc2_data  & m_data;
  /// \brief  Processing was successful (data was valid).
  bool  m_ok;
  
  public:
  
  input_translation
  ( abc2_data  & data
  , bool       & ok
  )
  throw()
  ;
  
  private:
  
  bool
  shift_input
  ()
  throw()
  ;
  
  static
  bool
  shift_sz // sz- string zero; in-place
  ( char  * sz
  )
  throw
  ()
  ;
  
} // class input_translation
;

input_translation::input_translation
( abc2_data  & data
, bool       & ok
)
throw()
: m_data(data)
, m_ok(this->shift_input() )
{ ok = m_ok;
}

bool
input_translation::shift_input
()
throw()
{ bool         ok;   
  abc2_data  & d   = this->m_data;
  char       * q   = d.m_text_symbols;
  char       * p   = d.m_words_symbols;
  
  ok = this->shift_sz(q);
  if( !ok)
  { return false; } // Failure.
  
  ok = this->shift_sz(p);
  if( !ok)
  { return false; } // Failure.
  
  return true; // Success.
}

bool
input_translation::shift_sz
( char  * p
)
throw()
{ bool  ok;  
  char  c  = ( *p);
  
  while('\0' != c)
  { ok = (('a' <= c) && ('c' >= c));
    if( !ok)
    { return false; } // Failure.
    
    c = c - 'a'; (*p) = c; ++p; c = ( *p);
  }
  
  return true; // Success.
}

// ______________________________________________________________________________

/// \brief  Verifies if the string is an abc string.
class string_is_an_abc_string
{ private:
  /// \brief  The string.
  char  * m_p;
  /// \brief  The length of the string.
  size_t  m_k;
  /// \brief  Is an abc string.
  bool    m_is_an_abc_string;
   
  public:
   
  string_is_an_abc_string
  ( char    * p
  , size_t    k
  )
  : m_p(p)
  , m_k(k)
  , m_is_an_abc_string(is_an_abc_string() )
  {}
   
  private:
   
  bool
  is_an_abc_string
  ()
  const
  throw()
  ;
   
  public:
   
  operator
  bool
  ()
  throw()
  { return m_is_an_abc_string; }
   
} // class string_is_an_abc_string
;
 
bool
string_is_an_abc_string::is_an_abc_string
()
const
throw()
{ char    * p = m_p;
  size_t    k = m_k;
   
  size_t    i;
  char      c;
  bool      ok;
  for(i=0; k>i; ++i)
  { c = p[i];
    ok = (     ('a' == c)
            || ('b' == c)
            || ('c' == c)
         )
         ;
    if( !ok)
    { return false; } // It is not an abc string.
  }
   
  return true; // It is an abc string.
}
 
// ______________________________________________________________________________

/// \brief  Reads the Makoko language.
class makako_language_reader
{ private:
  /// \brief  Reference to the input stream.
  ::std::istream  & m_is;
  /// \brief  Reference to the abc2 data.
  abc2_data       & m_data;
  /// \brief  Reference to the input is not valid variable.
  bool            & m_input_is_not_valid;
  /// \brief  Reference to the io-error-occurred variable.
  bool            & m_io_error_occurred;
  /// \brief  Processing was successful.
  bool              m_ok;
   
  public:
   
  makako_language_reader
  ( ::std::istream  & is
  , abc2_data       & data
  , bool            & input_is_not_valid
  , bool            & io_error_occurred
  , bool            & ok
  )
  throw()
  ;
   
  private:
   
  bool
  read_the_makako_language
  ()
  throw()
  ;
   
  bool
  read_word
  ( char    * p
  , size_t  & k
  )
  throw()
  ;
   
  bool
  read_the_last_line
  ()
  throw()
  ;
   
} // class makako_language_reader
;
 
makako_language_reader::makako_language_reader
( ::std::istream  & is
, abc2_data       & data
, bool            & input_is_not_valid
, bool            & io_error_occurred
, bool            & ok
)
throw()
: m_is(is)
, m_data(data)
, m_input_is_not_valid(input_is_not_valid)
, m_io_error_occurred(io_error_occurred)
, m_ok(read_the_makako_language() )
{ ok = m_ok;
}
 
bool
makako_language_reader::read_the_makako_language
()
throw()
{ bool  ok;
   
  abc2_data  & d   = this->m_data;
  char       * p   = d.m_words_symbols;
  size_t       len;
   
  // Read first word.
   
  ok = this->read_word(p, len);
  if( !ok)
  { return false; } // Failure.
   
  bool    const first_is_empty = (0>=len);
  // Read remaining words.
   
   
  size_t  const len0 = len;
  size_t        i    = 1;
  while((maxn > i) && (0<len))
  { p += len0;
    ok = this->read_word(p, len);
    if( !ok)
    { return false; } // Failure.
     
    ok = ((len0 == len) || (0 == len));
    if( !ok)
    { return false; }
     
    ++i;
  }
   
  // Read last line.
   
  if(0 != len)
  { ok = read_the_last_line();
    if( !ok)
    { return false; } // Failure.
  }
  else
  { if(false == first_is_empty)
    { --i; }
  }
   
  // no-throw, no-fail
  ::std::size_t  & number_of_words =
    d.m_number_of_words;
  ::std::size_t  & word_size =
    d.m_word_size;
  number_of_words = i;
  word_size       = len0;
   
  return true; // Success.
}
 
bool
makako_language_reader::read_word
( char    * p
, size_t  & k
)
throw()
{ ::std::istream  & is = this->m_is;
   
  bool  ok;
  bool  withSeparator = true;
   
  is.getline(p, maxc2);
  ok = is.good();
  if( !ok)
  { ok = is.eof();
    if( !ok)
    { m_io_error_occurred = true;
      return false; // Failure.
    }
    withSeparator = false;
  }
   
  // Compute len, line lenth.
  ::std::streamsize  tmp = is.gcount();
  if(0 > tmp)
  { m_io_error_occurred = true;
    return false; // Failure.
  }
   
  if(0 < tmp)
  { if(withSeparator)
    { --tmp; }
  }
   
  size_t  len = static_cast<size_t>(tmp);
  p[len] = '\0'; // Only for "(gdb) print p".
  ok = (len<=maxc);
  if( !ok)
  { m_input_is_not_valid = true;
    return false; // Failure.
  }
   
  ok = string_is_an_abc_string(p, len);
  if( !ok)
  { m_input_is_not_valid = true;
    return false; // Failure.
  }
   
  // no-throw, no-fail
  k = len;
  return true; // Success.
}
 
bool
makako_language_reader::read_the_last_line
()
throw()
{ ::std::istream  & is = m_is;
  bool              ok;
  bool              withSeparator = true;
   
  // Read line, into variable space.
   
  char  space[2];
   
  is.getline(space, 2);
   
  ok = is.good();
  if( !ok)
  { ok = is.eof();
    if( !ok)
    { m_io_error_occurred = true;
      return false; // Failure.
    }
    withSeparator = false;
  }
   
  // Compute line length, into variable len.
   
  ::std::streamsize  tmp = is.gcount();
   
  if(0 > tmp)
  { m_io_error_occurred = true;
    return false; // Failure.
  }
   
  if(0 < tmp)
  { if(withSeparator)
    { --tmp; }
  }
   
  ::std::size_t  len = static_cast< ::std::size_t>(tmp);
  space[len] = '\0'; // Only for "(gdb) print space".
   
  ok = (0 == len);
  if( !ok)
  { m_input_is_not_valid = true;
    return true; // Failure.
  }
   
  return true; // Success.
}

// ______________________________________________________________________________
 
/// \brief  Reads the input.
class input_reader
{ private:
   
  /// \brief  The abc2 data.
  abc2_data  & m_data;
  /// \brief  Input is not valid.
  /// 
  ///  This data member is initialized
  ///  , only when processing is not successful.
  bool  m_input_is_not_valid;
  /// \brief  Input error occurred.
  ///
  ///  This data member is initialized
  ///  , only when processing is not successful.
  bool  m_io_error_occurred;
  /// \brief  Processing is successful.
  bool  m_ok;
   
  public:
   
  input_reader
  ( abc2_data  & data
  , bool       & ok
  )
  : m_data(data)
  , m_ok(read_input() )
  { ok = m_ok;
  }
   
  private:
   
  bool
  read_input
  ()
  throw()
  ;
   
  bool
  read_the_ancient_text
  ( ::std::istream  & is
  )
  throw()
  ;
   
  bool
  read_all_the_words_in_the_makako_language
  ( ::std::istream  & is
  )
  throw()
  ;
   
} // class input reader.
;
 
bool
input_reader::read_input
()
throw()
{ bool  ok;
   
  ::std::ifstream  is("abc2.in");
  ok = is.good();
  if( !ok)
  { m_io_error_occurred = true;
    return false;
  }
   
  ok = this->read_the_ancient_text(is);
  if( !ok)
  { return false; } // Failure.
   
  ok = this->read_all_the_words_in_the_makako_language(is);
  if( !ok)
  { return false; } // Failure.
   
  return true; // Success.
}
 
bool
input_reader::read_the_ancient_text
( ::std::istream  & is
)
throw()
{ abc2_data  & d = this->m_data;
  char       * p = d.m_text_symbols;
  // Read line.
   
  bool  withSeparator = true;
   
  is.getline(p, maxm2);
  bool  ok = is.good();
  if( !ok)
  { ok = is.eof();
    if( !ok)
    { m_io_error_occurred = true;
      return false; // Failure.
    }
    withSeparator = false;
  }
   
  // Compute line length.
   
  ::std::streamsize  tmp = is.gcount();
  if(0 > tmp)
  { m_io_error_occurred = true;
    return false; // Failure.
  }
   
  if(0 < tmp)
  { if(withSeparator)
    { --tmp; }
  }
   
  ::std::size_t  len =
    static_cast< ::std::size_t>(tmp);
  p[len] = '\0';
  ok = (len <= maxm);
  if( !ok)
  { m_input_is_not_valid = true;
    return false; // Failure.
  }
   
  ok = string_is_an_abc_string(p, len);
  if( !ok)
  { m_input_is_not_valid = true;
    return false; // Failure.
  }
   
  ::std::size_t  & text_size =
    d.m_text_size;
   
  // no-throw, no-fail
  text_size = len;
   
  return true; // Success.
}
 
bool
input_reader::read_all_the_words_in_the_makako_language
( ::std::istream  & is
)
throw()
{ bool  ok;
  makako_language_reader
    reader
      ( is
      , m_data
      , m_input_is_not_valid
      , m_io_error_occurred
      , ok
      )
      ;
   
  if( !ok)
  { return false; } // Failure.
   
  return true; // Success.
}

// ______________________________________________________________________________

/// \brief  Writes output.
class output_writer
{ private:
  
  /// \brief  The abc2 data.
  abc2_data  & m_data;
  /// \brief  Processing was successful.
  bool         m_ok;
  
  public:
  
  output_writer
  ( abc2_data  & data
  , bool       & ok
  )
  : m_data(data)
  , m_ok(write_output() )
  { ok = m_ok;
  }
  
  private:
  
  bool
  write_output
  ()
  throw()
  ;
  
} // class output_writer
;

bool
output_writer::write_output
()
throw()
{ bool  ok;
  
  ::std::ofstream  os("abc2.out");
  ok = os.good();
  if( !ok)
  { return false; } // Failure.
  
  abc2_data  & d = this->m_data;
  size_t const  & number_of_occurrences =
    d.m_number_of_occurrences;
  
  os << number_of_occurrences << ::std::endl;
  ok = os.good();
  if( !ok)
  { return false; } // Failure.
  
  return true; // Success.
}

} // namespace abc2


/// The spaced used by the program.
static
::abc2::abc2_data
s_data;

/// Because the abc2_data is plain old data
/// , the construction of s_data is guaranteed
///   not to throw a c++ exception
/// .

bool
solve_the_abc2_problem
()
{ ::abc2::abc2_data  & d = s_data;
  
  bool  ok;
  
  ::abc2::input_reader  r(d, ok);
  if( !ok)
  { return false; } // Failure.    No input.
  (void) r;
  
  ::abc2::input_translation t(d, ok);
  if( !ok)
  { return false; } // Failure.   Bad input.
  (void) t;
  
  ::abc2::solver  s(d);
  (void) s;
  
  ::abc2::output_writer  w(d, ok);
  if( !ok)
  { return false; } // Failure.   No output.
  
  return true; // Success.
}

int
main
()
{ int  status;
  try
  { bool  ok     = solve_the_abc2_problem();
          status = ( ok ? 0 : 1 );
  }
  catch ( ... )
  { status = 2;
  }
  
  return status;
}