Link to home
Start Free TrialLog in
Avatar of Jegajothy vythilingam
Jegajothy vythilingamFlag for United States of America

asked on

USPS Address Correction Service (ACS) - Check Digit Sum code

I have to implement a check digit sum number for this address correction service.  When a alpha+number is given, it should convert to this check digit algorithm  Eg if I input ID1234, the check digit sum would be :
ID12343

The specifications to generate this result is contained in the attached file.  I would like to invite all Gurus and anyone or everyone to give a try on this assignment. I would award 1,000 points if the rules allow it.
Also the project seems to interesting but my expertise does not allow me to try it.
Thanks.

Extract-from-pub8a.doc
Avatar of Jegajothy vythilingam
Jegajothy vythilingam
Flag of United States of America image

ASKER

I edited a typo in the above question
Option Explicit

Private Sub Command1_Click()
        MsgBox CheckSumString("JLSTMS6796")
        MsgBox CheckSumString("TMS1112/62")
       
End Sub


Private Function CheckSumString(ByVal strText As String) As String
    Dim b() As Byte
    Dim i As Integer
    Dim strDigits As String
    Dim intTotal As Integer
   
    strText = Replace(strText, " ", "")
    strText = StrConv(strText, vbUpperCase)
    b = StrConv(strText, vbFromUnicode)
    For i = 0 To UBound(b)
        b(i) = b(i) And 15
    Next
   
    For i = 0 To UBound(b) Step 2
        b(i) = b(i) * 2
    Next
   
    For i = 0 To UBound(b)
        strDigits = strDigits & b(i)
    Next
   
    For i = 1 To Len(strDigits)
        intTotal = intTotal + CInt(Mid$(strDigits, i, 1))
    Next
   
   
    CheckSumString = strText & CStr(10 - CInt(Right$(CStr(intTotal), 1)))
   
   
End Function
Avatar of evilrix
A C version...

BTW: Example 3 for MOD10 appears to be wrong.
#include <stdio.h>
#include <string.h>
 
int calc(char * pcur1)
{
	int total = 0;
	char * pcur2 = pcur1;
	int idx = 1;
 
	while(*pcur1)
	{
		if(' ' == *pcur1)
		{
			if(pcur2 < pcur1) pcur2 = pcur1;
			while(*pcur2 && ' ' == *pcur2) ++ pcur2;
			*pcur1 = *pcur2;
			*pcur2 = ' ';
		}
 
		if(*pcur1)
		{
			*pcur1 &= 0x0F;
			if(idx % 2) *pcur1 *= 2;
			total += (*pcur1)/10;
			total += (*pcur1)%10;
			++idx;
			++pcur1;
		}
	}
 
	return 10 - (total%10);
}
 
 
 
typedef char BUFFER[20];
 
int main()
{
	char *testdata[] = {
		"J L S T M S 6 7 9 6",
		"T M S 1 1 1 2 / 6 2",
		"2 1 8 X N 9 1 L M S" /* The documentation for this one seems wrong!!! */
	};
 
	size_t const testdata_len = sizeof(testdata) / sizeof(testdata[0]);
 
	size_t idx = 0;
	for( ; idx < testdata_len; ++idx)
	{
		BUFFER td;
		strcpy(td, testdata[idx]);
		printf("Keyline: %s (Check Digit = %d)\n", testdata[idx], calc(td));
	}
 
	return 0;
}

Open in new window

This is for Paul Hews' code:
Testing of different keylines gave wrong results.  This is the test data used.  Could you please check and let me know if your code is correctly implemented :
                                    Result by Access      Result by Keyline
MsgBox CheckSumString("ABC999MM/32")      ABC999MM/321      PASS
MsgBox CheckSumString("ANIT0281")            ANIT028110                          pass
MsgBox CheckSumString("0012////8")            012////81                        PASS
MsgBox CheckSumString("811NIS0001119")      811NIS00011190      PASS
MsgBox CheckSumString("12345678907")      123456789072      PASS
MsgBox CheckSumString("09876543213")      098765432137      PASS
                                                      
MsgBox CheckSumString("218XN91LMS")      218XN91LMS5      FAIL SHOULD BE 4
MsgBox CheckSumString("123456")            1234569            PASS
MsgBox CheckSumString("ID235")            ID2359            PASS
MsgBox CheckSumString("QWERTY")            QWERTY1            PASS
MsgBox CheckSumString("218XN91LMS")               218XN91LMS5                          FAIL SHOULD BE 5 GAVE A DIFF ANSWER EACH TIME
MsgBox CheckSumString("JLSTMS6796")      JLSTMS67969      PASS
MsgBox CheckSumString("TMS1112/62")      TMS1112/623      PASS

There is a program called KEYLINE.EXE that is available at the USPS site and if you wish you coudl email me and I will email this program to you.  This program spits out the result for any value that you type in.
Also I have the original publication by USPS which is in pdf forwat, so I could also email this to you.

Thanks.
What about the C code I provided? You did put this in the C Zone.
BTW: Did you see the note I made in my code?
"2 1 8 X N 9 1 L M S" /* The documentation for this one seems wrong!!! */

The example in the documentation is inconsistent with itself (look at the example, it seems to go wrong in the bit where it adds the values together).

You state: -

MsgBox CheckSumString("218XN91LMS") 218XN91LMS5 FAIL SHOULD BE 4
MsgBox CheckSumString("218XN91LMS") 218XN91LMS5 FAIL SHOULD BE 5 GAVE A DIFF

There seems to be some inconsistency here, no?

My C code generates the output below. I believe 5 to be the correct result for the above.
Keyline: J L S T M S 6 7 9 6 (Check Digit = 9)
Keyline: T M S 1 1 1 2 / 6 2 (Check Digit = 3)
Keyline: 2 1 8 X N 9 1 L M S (Check Digit = 5)

Open in new window

The keyline app mentioned above gives 4.  But I'm with evilrix, it's not consistent with the MOD 10 method stated in the docs.

>it seems to go wrong in the bit where it adds the values together).

Exactly.  Here's the example from the docs:

Weighted Value 4 1 16 8 28 9 2 12 26 3
Sum 4 +1 +1+6 +8 +1+0 +9 +2 +1+2 +2+6 +3 = 46

The sum given above is not based on the weighted digits.  The 1 and 0 should be 2 and 9  The actual sum is
4+1+1+6+8+2+8+9+2+1+2+2+6+3 = 55

And the check digit should be 5.
Both of you are right.  There is a typo on my part.
When the keyline 218XN91LMS is input, the answer should be 218XN91LMS4
This is what the documentation of the USPS gives as to test our code.
Thanks.

EvilRix : Would you be able to give me your solution in VB code please, so that I coudl test your algorithm too.
Thanks.
>Both of you are right.  There is a typo on my part.

Looks to me like a mistake in the documentation, not on your part.  The algorithm as stated in the docs returns a check digit of 5 not 4  (See post above which references the documentation.)
>> EvilRix : Would you be able to give me your solution in VB code please, so that I could test your algorithm too.
I don't know VB - sorry. You posted this in the C Zone as well as the VB Zone so I think it was reasonable for me to assume you could work with a C solution.
ASKER CERTIFIED SOLUTION
Avatar of PaulHews
PaulHews
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> Somehow missed the note about the letter "N":
Ooo, me too but since the OP seems to want a VB solution I'll not attempt to fix it -- unless a C solution is confirmed as an acceptable alternative.
My salutations to Paul.  This guy Paul is a Genius to be able to write this complicated code.
Can I suggest that next time you don't put a Q in an unrelated Zone. I spent 1/2 hour writing the C code !!!
Evilrix,
My apologies.
Jothy
>> My apologies
No worries.
Thanks.
evilrix, whenever I see a question posted in two disparate zones, I try to check the question history before spending any amount of time working the question.  The new question wizard often suggests some pretty weird zone combinations.
>> The new question wizard often suggests some pretty weird zone combinations.
Understood. It was just a little frustrating spending time writing and testing code for, ostensibly, no good reason. No harm done though. I guess we can all learn something from this :)

Cheers.

-Rx.