
{
  2003 MO P-I-4

  Petr Baudis
  OKTAVA, gymnazium Ad Fontes Jihlava

  Trivialnim resenim ulohy by bylo pouziti ctyr registru. V kazdem bychom
  si udrzovali pocet nalezenych jednotlivych pismen a nakonec bychom postupne
  snizovali vsechny registry, pricemz stav Accept by nastal v pripade, ze
  posledni nenulovy registr je ten pro pismeno 'a'.

  Ovsem vzhledem k tomu, ze do kazdeho registru muzeme ulozit libovolne cele
  cislo, mohli bychom zkusit nejakym vhodnym zpusobem ulozit vsechna ctyri
  cisla do registru jedineho. K tomu muzeme vyuzit poznatek, ze mocniny
  prvocisel (nenuloveho nezaporneho celeho radu) se vzajemne nedeli. Muzeme
  tedy vlastne vyjadrit obsah vsech ctyrech registru jako soucin n-tych mocnin
  vhodnych prvocisel. Nad takovymto zpusobem ukladani cisel pak snadno
  nadefinujeme operace Inc i Dec, coz je vse, co potrebujeme.

  Pouzijeme tedy jeden registr pro ukladani hodnoty, druhy registr budeme
  potrebovat jako pomocny.

  PS: Doufam ze to je validni pascalovska syntax a neni tam moc Cckoismu. ;-)
}

var
  vstup: char;
  nasobitko, maska: byte; { pokud je malo pameti, tyto dve promnene lze sloucit}
  zbytek: byte;
  nula2, nula3, nula5, nula7: byte;

begin
  { pripravime si storage registr }
  Inc(R[0]); { := 1; }

  Read (vstup);
  while (vstup <> '$') do
    begin
      { kolika budeme nasobit? }
      if (vstup = 'a') then
        begin
          nasobitko := 2;
        end
      else if (vstup = 'b') then
        begin
          nasobitko := 3;
        end
      else if (vstup = 'c') then
        begin
          nasobitko := 5;
        end
      else if (vstup = 'd') then
        begin
          nasobitko := 7;
        end;
      {}

      { do aux registru si ulozime nasobitko*R[0] }
      { tim vynulujeme R[0] }
      while (not Zero (R[0])) do
        begin
          while (nasobitko > 0) do
            begin
              Dec (nasobitko);
              Inc (R[1]);
            end;
          {}
          Dec (R[0]);
        end;

      { prelijeme obsah z R[1] do R[0] }
      { tim vynulujeme R[1] }
      while (not Zero (R[1])) do
        begin
          Inc (R[0]);
          Dec (R[1]);
        end;

      Read (vstup);
    end;
  {}

  { postupne ted budeme odebirat z R[0] ze vsech virtualnich registru, tedy
    nejdrive 2*3*5*7, ovsem postupne z teto masky budeme ubirat jiz nulove
    virtualni registry; pokud v masce zustane jen 2, vyhrali jsme, pokud z
    masky 2 zmizi, mame smulu }
  maska := 2*3*5*7;
  while true do
    begin
      { R[0] = R[1] * maska | zbytek }
      zbytek := 0;
      while (not Zero (R[0])) do
        begin
          Inc (zbytek);
          if (zbytek > maska) then
            begin
              zbytek := 1;
              Inc (R[1]);
            end;
          Dec (R[0]);
        end;
      {}

      if (zbytek = maska) then
        begin
          { nezmenila se (ne)nulovost registru, pokracujeme rovnou dal }
          while (not Zero (R[1])) do
            begin
              Inc (R[0]);
              Dec (R[1]);
            end;
          {}
        end
      else
        begin
	  { obsah nejakeho vregistru dosahl nuly, takze ho musime odstranit
            z masky; nova maska bude normalizovany zbytek }

          { zbytek normalizujeme tak, ze odstranime vsechny vyssi mocniny }
          maska := 1;
          if (zbytek mod 2) maska := maska * 2;
          if (zbytek mod 3) maska := maska * 3;
          if (zbytek mod 5) maska := maska * 5;
          if (zbytek mod 7) maska := maska * 7;

	  { zajimavy obsah? }
	  if (maska = 2) then
	    Accept;
	  if (maska mod 2 <> 0) then
	    Reject;

          { na novou masku budeme testovat soucasny zbytek }
          while (zbytek > 0) do
            begin
              Inc (R[0]);
              Dec (zbytek);
            end;
          {}

          { vynulujeme si R[1] }
          while (not Zero (R[1])) do
            Dec (R[1]);
        end;
      {}
    end;
  {}
end.
