comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@attbi.com>
Subject: Real data for a change in the assignment operators and Bounded_String discussions.
Date: Fri, 04 Jul 2003 03:41:50 GMT
Date: 2003-07-04T03:41:50+00:00	[thread overview]
Message-ID: <3F04F778.5090305@attbi.com> (raw)

"Mr. Wideman" <mrwideman@insightbb.com> posted the following message to
sci.crypt.random-numbers, which has nothing to do with solving secret 
messages but generating secure random number sequences:

========================================================================

(Maybe related to primes or the magic hexagon - also the result will
be in English using the 26 letter alphabet)

1713167174342128171514138189312
3328481316215188174182917819139
9198181712743151518167123321815
3419371816421839151471821218332
8415137933719383167187431713719
2991771571431333719341915183337
13719

=========================================================================

There are no zeros and lots of ones.  I thought that it might be a 
system like the one used by Col. Abel that had one and two digit 
sequences.  So I wrote a quick program (less than 4 hours, including 
dinner and a break to watch the fireworks from the back steps. ;-) to 
print out some statistics:

count_digits message.txt

   There were 191 digits.

   0=  0  1= 58  2= 14  3= 32  4= 13  5=  9  6=  5  7= 23  8= 21  9= 16

  00=  0 01=  0 02=  0 03=  0 04=  0 05=  0 06=  0 07=  0 08=  0 09=  0
  10=  0 11=  0 12=  5 13=  8 14=  3 15=  9 16=  5 17=  8 18= 12 19=  8
  20=  0 21=  6 22=  0 23=  2 24=  0 25=  0 26=  0 27=  1 28=  3 29=  2
  30=  0 31=  7 32=  3 33=  8 34=  3 35=  0 36=  0 37=  7 38=  2 39=  2
  40=  0 41=  5 42=  2 43=  4 44=  0 45=  0 46=  0 47=  1 48=  1 49=  0
  50=  0 51=  7 52=  0 53=  1 54=  0 55=  0 56=  0 57=  1 58=  0 59=  0
  60=  0 61=  0 62=  1 63=  0 64=  1 65=  0 66=  0 67=  3 68=  0 69=  0
  70=  0 71= 16 72=  0 73=  0 74=  4 75=  0 76=  0 77=  1 78=  1 79=  1
  80=  0 81= 10 82=  2 83=  4 84=  2 85=  0 86=  0 87=  1 88=  1 89=  1
  90=  0 91=  6 92=  1 93=  5 94=  0 95=  0 96=  0 97=  0 98=  1 99=  2

The fact that 1 never follows 1 even though it it the most frequent 
letter seems very suspicious, so I'll probably work back and forth to 
come up with 1 and 2 digit representations that make sense, then try to 
solve it as a simple substitution.  If my assumptions are right there 
should be at least a hundred characters, which should be plenty.

But I wanted to talk about the Ada program I wrote:

-----------------------------------------------------------------------------------------

with Ada.Text_IO;
with Ada.Command_Line;
procedure Count_Digits is -- A program to count the digits and digit
                   -- pairs in a string.  Other charaters are ignored.
   function Get_Data return String is
     use Ada.Text_IO;
     use Ada.Command_Line;
     Input_File: File_Type;

     function Recur return String is
       Buffer: String(1..80);
       Last_Char: Integer;
     begin
       Get_Line(Input_File,Buffer,Last_Char);
       if End_Of_File(Input_File)
       then return Buffer(1..Last_Char);
       else return Buffer(1..Last_Char) & Recur;
       end if;
     end Recur;

   begin
     Open(Input_File,In_File,Argument(1));
     return Recur;
     Close(Input_File);
   end Get_Data;

   procedure Inc (Counter: in out Integer);
   pragma Inline(Inc);

   procedure Inc (Counter: in out Integer) is
   begin Counter := Counter + 1; end Inc;

   Data: String := Get_Data;
   Total: Integer;
   Previous: Character;
   Single: array(Character range '0'..'9') of Integer := (others => 0);
   Digraphs: array(Character range '0'..'9',
      Character range '0'..'9') of Integer := (others => (others => 0));
   Start: Integer := Data'First;

   procedure Print_Data is
     use Ada.Text_IO;
     use Ada.Command_Line;
     Output_File: File_Type;
     package Int_IO is new Integer_IO(Integer);
   begin
     if Argument_Count > 1 then
       Open(Output_File, Out_File, Argument(2));
       Set_Output(Output_File);
     end if;
     New_Line;
     Put_Line("  There were" & Integer'Image(Total) & " digits.");
     New_Line;
     for I in Character range '0'..'9' loop
       Put( "  " & I & '=');
       Int_IO.Put(Single(I),3);
     end loop;
     New_Line(2);

     for I in Character range '0'..'9' loop
       for J in Character range '0'..'9' loop
         Put( ' ' & I & J & '=');
         Int_IO.Put(Digraphs(I,J),3);
       end loop;
       New_Line;
     end loop;
     New_Line;

     if Is_Open(Output_File)
     then
       Set_Output(Standard_Output);
       Close(Output_File);
     end if;
   end Print_Data;

begin

   -- seed Digraph counting...
   while Data(Start) not in '0'..'9' loop
     Start := Start + 1;
   end loop;
   Total := 1; -- first character found
   Previous := Data(Start);
   Inc(Single(Data(Start)));

   -- main loop
   for I in Start+1.. Data'Last loop
     if Data(I) in '0'..'9'
     then
       Inc(Total);
       Inc(Single(Data(I)));
       Inc(Digraphs(Previous,Data(I)));
       Previous := Data(I);
     end if;
   end loop;

   Print_Data;

end Count_Digits;

----------------------------------------------------------------------------------------------

First, let me get deal with the Bounded_String argument.  This program 
is the sort of program whene some people think that Bounded_String is 
needed.  I probably would have used a line at a time loop if I expected 
to deal with hundreds of lines of input.  But as you can see, I read all 
the text data recursively, then splice it together into one String 
return VALUE.  Which goes here:

   Data: String := Get_Data;

The recursive function that does the splicing of lines is ten lines 
long.  Note that if a line is longer than 80 characters, Recur will read 
it in more than one bite.  But I don't have to worry about the layout of 
the input data.  (Just whether the counts will get too high and mess up 
my neat output formatting.)  You just CANNOT code like this in C or many 
other languages.  (I can imagine trying to write that code in C, with 
mallocs, frees, searches for nul (strlen) and copies all over the place. 
  Ouch!)  End of Bounded_String discussion.

Now onto the assignment operators.  At first I thought this code would 
be a poster child for the idem proposal.  But it was worth it to me to 
write:

   procedure Inc (Counter: in out Integer);
   pragma Inline(Inc);

   procedure Inc (Counter: in out Integer) is
   begin Counter := Counter + 1; end Inc;

I probably could have written the Inc operation as a one-liner and left 
off the declaration and the pragma Inline(Inc); but it was easier to 
write it than to figure out if it was worth the effort.  As you can see 
from the formatting, I definitely belong to the "if the code is 
unreadable it is wrong" school.  The same goes for the pragma Inline in 
this case--it was easier to put it in than justify leaving it out.

I also could have had pragma Inline for Get_Data and Print_Data, but my 
style is to leave out pragma Inline for procedures or functions that are 
called once and let the compiler figure it out.  Of course, a pragma 
Inline for Recur would be unlikely to accomplish much.  The same 
argument applies to closing the Input_File and Output_File.  It is not 
really needed, but it documents that I am finished using them.

Should Inc be predefined as a procudure?  (In addition to as an 
attribute function.)  No.  It is clearly easier to declare the version 
of Inc that I want, than to remember where it is defined, what the 
parameters are and so on.  And I certainly don't want to discuss that in 
ARG or WG9 meetings for something where the desired functionality fits 
in one line.

I don't expect this to end the discussion on these two issues, but I 
hope it helps.  The three calls in a row to Inc are much clearer than:

       Total := Total + 1;
       Single(Data(I)) := Single(Data(I)) + 1;
       Digraphs(Previous,Data(I))) := Digraphs(Previous,Data(I)) + 1;

But part of what makes it much clearer is having the definition of Inc 
right there.  And certainly any argument that

       Total +:= 1;  -- or perhaps
       Total := idem + 1; -- or whatever

is "better" than:

       Inc(Total);

is crazy.  If you count characters, the line with the fancy new operator 
is one character longer. Not that this is an APL contest to do something 
with the fewest characters.  The real win is that the procedure call has 
fewer parts to understand: a procedure call with one parameter, and 
requires no language extensions.

-- 

                                                   Robert I. Eachus

�In an ally, considerations of house, clan, planet, race are 
insignificant beside two prime questions, which are: 1. Can he shoot? 2. 
Will he aim at your enemy?� -- from the Laiden novels by Sharon Lee and 
Steve Miller.




             reply	other threads:[~2003-07-04  3:41 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-04  3:41 Robert I. Eachus [this message]
2003-07-05  1:29 ` Inc (was: Real data for a change in the assignment operators and Bounded_String discussions. ) Alexander Kopilovitch
2003-07-07 21:31   ` Gautier Write-only
2003-07-07 21:35     ` Inc (was: Real data for a change in the assignment operators and Larry Kilgallen
2003-07-08  3:53       ` Gautier Write-only
2003-07-08 20:50       ` Alexander Kopilovitch
2003-07-07 21:42     ` Inc (was: Real data for a change in the assignment operators and Bounded_String discussions. ) Vinzent Hoefler
2003-07-08  4:04       ` Gautier Write-only
2003-07-07  4:27 ` Real data for a change in the assignment operators and Bounded_String discussions Hyman Rosen
2003-07-07  9:27   ` Georg Bauhaus
2003-07-07  9:41     ` Georg Bauhaus
2003-07-07 14:29       ` Hyman Rosen
2003-07-07 17:29         ` Georg Bauhaus
2003-07-07 19:01           ` Hyman Rosen
2003-07-07 15:49       ` Robert I. Eachus
2003-07-07 13:46     ` Hyman Rosen
2003-07-07 16:03       ` Robert I. Eachus
2003-07-07 18:52         ` Hyman Rosen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox