SelectDigitWithGivenProbabilities [ digits_, prob_ ] :=
Module [{i, r, sumOfProbabilitiesUpToI},
   r = Random  []; 
   i = 0;
   sumOfProbabilitiesUpToI = 0;
   While [sumOfProbabilitiesUpToI < r && i < Length[prob],
      i = i + 1;
      sumOfProbabilitiesUpToI =        
         sumOfProbabilitiesUpToI + prob [[i]];
    ];
   digits [[i]]
]        

StreamOfDigits [ digits_, prob_, n_ ] :=
Module [{j},
   Table [SelectDigitWithGivenProbabilities [ digits, prob ], {j,1,n}]
]

digits = {"A", "B", "C", "D", "E"};
prob = {0.9, .06, .015, .015, .01};

GETDIGITSNUMBER = 0;
SeedRandom [Floor [1000 * SessionTime[]]];

GetADigit [] :=
Module [{},
   GETDIGITSNUMBER = GETDIGITSNUMBER + 1;
   If [Mod [GETDIGITSNUMBER, 100 + 1] == 0,
         "EOF",
      SelectDigitWithGivenProbabilities [digits, prob]
   ]
]


MyEncoding [] :=
Module[{buffer, newdigit, result},
   buffer = {};
   result = {};
   While [buffer != {"EOF"},
      newdigit = GetADigit [];
      (* Print [];
       Print ["Digit Read =", newdigit]; *)
      buffer  = Append [buffer, newdigit];
      If [buffer [[1]] == "B",
            result = Join [result, {1,1,1,0,1,1}];
            buffer = Take[buffer, 1 - Length [buffer]],
      If [buffer [[1]] == "C",
            result = Join [result, {1,1,1,1,0}];
            buffer = Take[buffer, 1 - Length [buffer]],
      If [buffer [[1]] == "D",
            result = Join [result, {1,1,1,1,1,0}];
            buffer = Take[buffer, 1 - Length [buffer]],
      If [buffer [[1]] == "E",
            result = Join [result, {1,1,1,1,1,1}];
            buffer = Take[buffer, 1 - Length [buffer]],
      If [Length [buffer] >= 2 && 
          Take [buffer, 1] == {"A"} && 
          buffer [[2]] != "A",
            result = Join [result, {1,1,1,0,1,0}];
            buffer = Take [buffer, 1 - Length [buffer]],
      If [Length [buffer] >= 3 &&
          Take [buffer, 2] == {"A", "A"} &&
          buffer [[3]] != "A",
            result = Join [result , {1,1,1,0,0}];
            buffer = Take [buffer, 2 - Length [buffer]],
      If [Length[buffer] >= 4 &&
          Take [buffer, 3] == {"A","A","A"} &&
          buffer [[4]] != "A",
            result = Join [result, {1,1,0}];
            buffer = Take [buffer, 3 - Length [buffer]],
      If [Length[buffer] >= 5 &&
          Take [buffer, 4] == {"A","A","A","A"} &&
          buffer [[5]] != "A",    
            result = Join [result, {1,0}];
            buffer = Take [buffer, 4 - Length [buffer]],
      If [Length [buffer] >= 5 &&
          Take [buffer, 5] == {"A","A","A","A","A"},
             result = Join [result, {0}];
             buffer = Take [buffer, 5 - Length [buffer]]
      ]]]]]]]]];
      (* Print ["Buffer =", buffer];
       Print ["Encoded =", result]; *)
  ];        
  result
]

