(12C) Luhn algorithm - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Software Libraries (/forum-10.html) +--- Forum: General Software Library (/forum-13.html) +--- Thread: (12C) Luhn algorithm (/thread-10535.html) |
(12C) Luhn algorithm - pinkman - 04-18-2018 06:29 PM Ho, referring to the wikipedia page of the Luhn algorithm, I propose an implementation for the 12c. How to use it ? As the 12c has only 10 significant digits, we'll have to split the credit card number into 2 parts. (Ex: 1234 5678 9012 3456 will be split in 12345678 and 90123456) After having entered the code, clear the registries 0 and 1 and then enter the right part of the number. (Ex: 90123456) Then hit R/S until it displays 0 (don't forget to hit R/S if there were leading zeros). You can then enter the left part of the number. (Ex: 12345678) Then hit R/S until it displays 0 (don't forget to hit R/S if there were leading zeros). The Luhn key is in REG 0 => RCL 0 If it is a multiple of 10, your Luhn key is OK. The number of processed digits is in REG 1. To test : 543210 => 15 in REG 0 (Luhn KO) 543215 => 20 in REG 0 (Luhn OK) Looking forward to reading you. Thibault Code:
RE: (12C) Luhn algorithm - Dieter - 04-23-2018 08:19 AM (04-18-2018 06:29 PM)pinkman Wrote: referring to the wikipedia page of the Luhn algorithm, I propose an implementation for the 12c. Another example of putting the 12C's limited programming capabilites to good use. ;-) Here is a significantly shorter version that takes advantage of two simple tricks that can also be useful for other applications: 1. In your program the change between odd and even digit positions is done by checking if the index is divisible by 2. Afterwards the digit is doubled or not. My program toggles R1 between 0 and 2 (via R1 := 2 – R1). If it's zero the doubling is skipped, otherwise the factor 2 is already in X. 2. The original program calculates the digit sum of a two-digit result in a very straightforward way: divide x by 10, take the integer part, calculate the remainder, and add both. But since x does not exceed 18 the digit sum can also be calculated by subtracting 9 if x exceeds 9. This was implemented in the HP41 program in the General Forum's Luhn thread. Here the code sequence was Code: ... This means: if after doubling x is less than 9 (i.e. 0, 2, 4, 6 or 8) don't subtract anything (CLX –), and if it is ≥ 9 (i.e. 10, 12, 14, 16 or 18) subtract 9 to get 1, 3, 5, 7 or 9 as the digit sum. Now HP's lower end programmables do not feature an X>Y? test. X≤Y? and X=0? is all they have. But there is a way. If one test is followed by another one which always tests false (!), the first test command is inverted! So an X≤Y? followed by an X=0? in effect is an X>Y? as long as X is not zero. Here X always is 9, so X=0? always tests false and we get an X>Y? test as desired. Here is the complete program: Code: 01 1 Initialize with 0 STO 0 2 STO 1 With two additional steps the program can be modified so that the initialization can be done with 0 ST0 0 STO 1 or even a simple CLEAR REG. If you like this better here is an alternate version: Code: 01 1 In either case then proceed as with the original program. Note: the number of processed digits here is not stored in R1. Hint: INT LSTX FRAC is one step shorter than ENTER INT X<>Y FRAC. ;-) Also note the dummy ENTER in line 22 or 20 that neutralizes the following R↓. Yes, a GTO would have done it just as well. Dieter RE: (12C) Luhn algorithm - pinkman - 04-24-2018 08:00 AM Thanks Dieter!! I'm ashamed I forgot to use LastX, and I'm really impressed with your optimizations. The 9 comparison with a combination of both x<=y and x=0 is a good sample of knowledge sharing. I did not want to use a toggle to identify the odd/even case, because of the advantage of having a counter of digits processed. I found a new solution based on the deterministic result of dividing by 2 any integer: 0 or 0.5. Thus multiplying by 2 and adding 1 gives a factor suitable for any digit to process, without using a test. The code might be a bit slower, but shorter and easy to read and maintain (no gto). Same usage: clear R0 and R1, enter the first (max 10) lower digits, then r/s for each digit including leading zeros, then enter the next digits, r/s again... Result in R0, number of processed digits in R1. If R0 is 10*N then Luhn is OK. Code:
RE: (12C) Luhn algorithm - Dieter - 04-24-2018 06:35 PM (04-24-2018 08:00 AM)pinkman Wrote: I did not want to use a toggle to identify the odd/even case, because of the advantage of having a counter of digits processed. I found a new solution based on the deterministic result of dividing by 2 any integer: 0 or 0.5. Thus multiplying by 2 and adding 1 gives a factor suitable for any digit to process, without using a test. First of all: you can save two steps if you have the "1" in line 16 followed by a STO+1. This way the counter is incremented en passant and you can delete the three steps near the end that do it now. Regarding the method of calculating a factor (1 or 2) from the R1 counter: I had a similar idea, and avoiding tests and GTOs is something I really like. In this case it could even be done with two steps less: Code: ... The e^x turns a 0 into 1, so the digit is divided by either 0,5 (=doubled) or 1 (unchanged). But... sometimes even good ideas don't work. All this would be fine, even with four steps saved, IF the 12C had an X<Y? test as originally shown in your listing (I now see you corrected this). But in fact the 12C features an X≤Y? test. This way the digit 9 will not get processed correctly. Since 9 ≤ 9 the test is true, so X=0? is also tested, which is false, so the CLX is not executed and the result is zero (9 – 9). So this method is not an option here. HP25 users: this is your moment! You can implement the idea above with the following code sequence, since your calculator sports an X≥Y? test: Code: RCL 1 Note: be sure to add an ENTER as the first line, or even better something useful like FIX 0. If you don't the following 10 may be appended to your input. This is one of the HP25's ..."special features". Owners of HP calculators with the common eight test commands may replace the X≥Y? with an X≠Y? X>Y? sequence. Yes, that's another trick from the olden days... ;-) Dieter RE: (12C) Luhn algorithm - Dieter - 04-24-2018 07:40 PM (04-18-2018 06:29 PM)pinkman Wrote: referring to the wikipedia page of the Luhn algorithm, I propose an implementation for the 12c. Here is a version for a special application of the Luhn algorithm. The latter is often used to add a check digit to a locomotive's class/serial number. The German Federal Railways have been using this method since 50 years now, which maybe is a good reason to introduce this special program version. ;-) Code: 01 STO 0 Usage: Enter the six-digit vehicle number (class and serial number) and the program adds the check digit (right of the decimal point). Example: 103 118 => 103.118,6 111 111 => 111.111,1 You can also use this program to calculate the check digit for other numbers with up to nine digits: 123456789 => 123.456.789,7 If you replace line 38...40 with "10 x" only the check digit is returned and up to 10 digits can be processed. In this case you may also replace the initial STO 0 with FIX 0. ;-) Dieter RE: (12C) Luhn algorithm - pinkman - 04-24-2018 08:27 PM (04-24-2018 06:35 PM)Dieter Wrote: First of all: you can save two steps if you have the "1" in line 16 followed by a STO+1. This way the counter is incremented en passant and you can delete the three steps near the end that do it now.Yes!! (04-24-2018 06:35 PM)Dieter Wrote: But... sometimes even good ideas don't work. All this would be fine, even with four steps saved, IF the 12C had an X<Y? test as originally shown in your listing (I now see you corrected this). But in fact the 12C features an X≤Y? test. This way the digit 9 will not get processed correctly. Since 9 ≤ 9 the test is true, so X=0? is also tested, which is false, so the CLX is not executed and the result is zero (9 – 9). So this method is not an option here.Whoo, lack of test on my side! There is another way to avoid the >9 test: add the 2 numbers, even if there is a leading zero. This can be done with: Code:
So I decided to store 10 in R2, to spare 2 lines. New code is: Code:
This time I think it has been tested! Same usage, but now R2 is used. Result in R0, counter in R1. RE: (12C) Luhn algorithm - Dieter - 04-25-2018 07:22 AM (04-24-2018 08:27 PM)pinkman Wrote: There is another way to avoid the >9 test: add the 2 numbers, even if there is a leading zero. It can also be done with the >9 test. Here is a version that processes the complete number, so you don't have to press R/S several times: Code: 01 1 R1 is returned in Y and R0 in X. Simply check if the last digit is zero. Yes, with a few more steps the program could also do this. The code up to line 28 works like the previous versions, so it's even one step shorter. And R2 is not required. ;-) Dieter RE: (12C) Luhn algorithm - pinkman - 04-25-2018 02:52 PM Great! |