checksum calculation (perl?)

I'm using AIX 4.3.2 with ksh and would like to set up an alphanumeric paging script which is compatible with the New Zealand Telecom TAP protocol, which uses a checksum of the message to verify its accuracy.  To achieve this, I would like a script (perferably perl) which performs the following:

1. Take as input, a file which may include printable and "unprintable" characters.

2. Produce as output, a number which is the sum of the ASCII values of all the charaters in the file.

Eg: If the file contains:
This would add up as follows:
Char   ASCII
  1      49
  2      50
  3      51
  \n     10
  A      65
  \n     10
Total:  235
So, the output should be 235 (decimal).

If you've done that, here's an optional part for extra points:
1. Take the last 12 bits of the above.
2. Convert each group of 4 bits into the ASCII chars 48 ("0") to 63 ("?").
Eg: In the case of a checksum like 12667 (decimal), this converts to binary:
  11 0001 0111 1011
The last 12 bits are:
  0001 0111 1011
Or in decimal:
  1 7 11
And you can just add 48 (decimal) to each of these to get:
  49 55 59
Which can be represented by ASCII chars:
  1 7 ;
So the output should be:

I will probably "reject" non-perl answers until I give up waiting for perl answers, since perl is my preference.

LVL 12
Who is Participating?
maxkirConnect With a Mentor Commented:
Check this code ...


$file = "file.bin";
open(F, $file);
$/ = undef;
    $sum = 0;
    for( $i=0; $i<length($_); $i++)
        $sum += ord( substr($_, $i, 1) );

# Now checksum in $sum;

$t1 = $sum & 15   + 48;
$t2 = $sum & 240  + 48;
$t3 = $sum & 3840 + 48;

$result = chr($t3) . chr($t2) . chr($t1);
print $result;
perl -0777 -ne 'print unpack"%32C*",$_' file
perl -0777 -ne 'print "000\n"^pack"C*",map{hex}split//,sprintf"%03x",unpack"%12C*",$_' file.bin
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

tel2Author Commented:
maxkir & ozo,

Thanks for your good answers and sorry for the delay in checking them out.

I didn't intentionally "Accept" maxkir's answer, I think the EE system must time-out and auto-accept answers after so much time.  IS THAT CORRECT?

ozo's first answer satisfied the compulsory part of my question, so he deserved full points for that.

When I ran maxkir's script, which was attempting to answer both parts, but in the "123\nA\n" example, it gave me: "  +" (ie: space, space, +), instead of the correct answer: "0>;".
Your script looks good, is much more readable than ozo's, and obviously took some work, and I thank you for that, but I think it must have a bug (either that, or I tested it wrongly).  Anyway, you sort-of deserve the points you received, for the time you spent.

ozo later gave another of his cryptic specials, which gives me a full and  correct result.  Well done ozo, and thanks.  Some day I hope to understand your code.

I will open a dummy question titled "Points for ozo (Q.10254245)" so I can award ozo points.

Thanks to both of you for your time.
Is there some part of the code that you don't understand?
I'd hope one could learn something from understanding it.
tel2Author Commented:
Although I'm a programmer, I've never seen such a cryptic (or concise/powerful) language as Perl.

I basically don't understand any of your script, starting with the "-0777".

If you could spare the time to break it down and explain it, I'd be most grateful.  If you want points for that, let me know what it's worth first.

-0777 is explained in
perldoc perlrun

unpack, sprintf, split, map, hex, pack, and print are explained in
perldoc -f print
perldoc -f pack

^ is explained in
perldoc perlop

If you want any furthur explaination after reading the documentation, you can ask for clarification of whatever is unclear.
You can also experiment yourself to see what it's doing at each step.
e.g. try just
perl -0777 -ne 'print sprintf"%03x",unpack"%12C*",$_' file.bin
which prints the sum in hexadecimal
tel2Author Commented:
Thanks heaps ozo.
Good to have you on the team!
perl -0777 -pe '($_=sprintf"%03x\n",unpack"%12C*",$_)=~tr/0-9a-f/0-?/' file.bin
All Courses

From novice to tech pro — start learning today.