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
jegajothyretiredAsked:
Who is Participating?
 
PaulHewsConnect With a Mentor Commented:
Somehow missed the note about the letter "N":

Note: The value of letter N in an odd position, when weighted, becomes
14 x 2 = 28. The digits 2 and 8 are added, yielding 10. This sum is then
further rendered as 1 + 0, not the sum of 10.
Option Explicit
 
Private Sub Command1_Click()
    Dim vArrayTest As Variant
    Dim i As Integer
    Dim strTest As String
 
    vArrayTest = Array("ABC999MM/321", _
    "ANIT0281", _
    "0012////8", _
    "811NIS0001119", _
    "12345678907", _
    "1234569", _
    "ID2359", _
    "QWERTY1", _
    "218XN91LMS4", _
    "TMS1112/623")
    
    
    For i = 0 To UBound(vArrayTest)
        strTest = vArrayTest(i)
        If CheckSumString(Left(strTest, Len(strTest) - 1)) = strTest Then
            Debug.Print strTest & " PASS"
        Else
            Debug.Print strTest & "FAIL " & CheckSumString(Left(strTest, Len(strTest) - 1))
        End If
    Next
    
 
       
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)
        If b(i) = 28 And i Mod 2 = 0 Then
'            Debug.Print strText, i, b(i)
            strDigits = strDigits & "10"
'            Debug.Print
        Else
            strDigits = strDigits & b(i)
        End If
    Next
    
'    Debug.Print "Digits: " & strDigits
   
    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
 
Private Sub Command2_Click()
    Dim i As Integer
    For i = Asc("/") To Asc("Z")
        Debug.Print Chr(i), i And 15
    Next
End Sub

Open in new window

0
 
jegajothyretiredAuthor Commented:
I edited a typo in the above question
0
 
PaulHewsCommented:
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
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
evilrixSenior Software Engineer (Avast)Commented:
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

0
 
jegajothyretiredAuthor Commented:
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.
0
 
evilrixSenior Software Engineer (Avast)Commented:
What about the C code I provided? You did put this in the C Zone.
0
 
evilrixSenior Software Engineer (Avast)Commented:
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

0
 
PaulHewsCommented:
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.
0
 
jegajothyretiredAuthor Commented:
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.
0
 
PaulHewsCommented:
>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.)
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> 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.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> 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.
0
 
jegajothyretiredAuthor Commented:
My salutations to Paul.  This guy Paul is a Genius to be able to write this complicated code.
0
 
evilrixSenior Software Engineer (Avast)Commented:
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 !!!
0
 
jegajothyretiredAuthor Commented:
Evilrix,
My apologies.
Jothy
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> My apologies
No worries.
Thanks.
0
 
PaulHewsCommented:
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.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> 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.
0
All Courses

From novice to tech pro — start learning today.