Recent

Author Topic: Convert this Python code pls.  (Read 602 times)

Petrus Vorster

  • Jr. Member
  • **
  • Posts: 99
Convert this Python code pls.
« on: April 25, 2025, 09:02:19 am »
Hi All

I have this function in Basic and Python, but I am too much of a Newby on Pascal to get this accurate.
It creates a function that validates S10 Tracking numbers used by the entire planet's Postal systems.
I tried the AI converter, but it completely ignore the weights and thus have a very wrong validation.

If anyone could perhaps be so kind and have a peek, I would appreciate it greatly.
Code: Pascal  [Select][+][-]
  1. def get_check_digit(num: int) -> int:
  2.     """Get S10 check digit."""
  3.     weights = [8, 6, 4, 2, 3, 5, 9, 7]
  4.     sum = 0
  5.     for i, digit in enumerate(f"{num:08}"):
  6.         sum += weights[i] * int(digit)
  7.     sum = 11 - (sum % 11)
  8.     if sum == 10:
  9.         sum = 0
  10.     elif sum == 11:
  11.         sum = 5
  12.     return sum

Thank you greatly for all the assistance.

-Peter

tr_escape

  • Sr. Member
  • ****
  • Posts: 435
  • sector name toys | respect to spectre
    • Github:
Re: Convert this Python code pls.
« Reply #1 on: April 25, 2025, 09:12:22 am »
I just asked to deepseek:

Here's a Pascal implementation of the S10 tracking number check digit calculation function that matches the logic of your Python/Basic code:

pascal
Code: Pascal  [Select][+][-]
  1. function GetCheckDigit(num: Integer): Integer;
  2. var
  3.   weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  4.   numStr: string;
  5.   i, sum: Integer;
  6. begin
  7.   sum := 0;
  8.   // Format the number as 8-digit string with leading zeros
  9.   numStr := Format('%.8d', [num]);
  10.  
  11.   // Make sure we don't exceed the string length or weights array
  12.   for i := 1 to 8 do
  13.   begin
  14.     sum := sum + weights[i-1] * StrToInt(numStr[i]);
  15.   end;
  16.  
  17.   sum := 11 - (sum mod 11);
  18.  
  19.   if sum = 10 then
  20.     Result := 0
  21.   else if sum = 11 then
  22.     Result := 5
  23.   else
  24.     Result := sum;
  25. end;
  26.  
Explanation:
Weights array: Same as in Python, using Pascal's array syntax

String formatting: Format('%.8d', [num]) ensures the number is 8 digits with leading zeros

Loop: Pascal strings are 1-indexed, so we adjust the array access accordingly

Check digit calculation: Same logic as Python:

Calculate weighted sum

Compute 11 - (sum mod 11)

Handle special cases (10 → 0, 11 → 5)

Usage example:
pascal
Code: Pascal  [Select][+][-]
  1. var
  2.   checkDigit: Integer;
  3. begin
  4.   checkDigit := GetCheckDigit(12345678);
  5.   WriteLn('Check digit is: ', checkDigit);
  6. end.
This should give you the exact same results as your Python implementation. The key difference is handling Pascal's 1-based string indexing versus Python's 0-based indexing.

Thaddy

  • Hero Member
  • *****
  • Posts: 16945
  • Ceterum censeo Trump esse delendam
Re: Convert this Python code pls.
« Reply #2 on: April 25, 2025, 09:26:49 am »
If you ask the right questions to deepseek I got this:
Code: Pascal  [Select][+][-]
  1. uses
  2.   sysutils;
  3.  
  4. function GetCheckDigit(num: Integer): Integer;
  5. var
  6.   weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  7.   i, sum: Integer;
  8.   numStr: string;
  9. begin
  10.   sum := 0;
  11.   numStr := num.ToString.Insert(0, StringOfChar('0', 8 - num.ToString.Length));
  12.  
  13.   for i := 0 to High(weights) do
  14.     sum := sum + weights[i] * numStr.Chars[i].ToInteger;
  15.  
  16.   sum := 11 - (sum mod 11);
  17.   Result := IfThen(sum = 10, 0, IfThen(sum = 11, 5, sum));
  18. end;
Which is wrong
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Petrus Vorster

  • Jr. Member
  • **
  • Posts: 99
Re: Convert this Python code pls.
« Reply #3 on: April 25, 2025, 09:28:26 am »
Thanks mate.

I ended up there too eventually.
What I did not see was that formatting for the Integer to allow leading zeros.
That I did not know ever existed for an Integer.

It should be downhill from here all the way.

Regards, Peter

ccrause

  • Hero Member
  • *****
  • Posts: 1015
Re: Convert this Python code pls.
« Reply #4 on: April 25, 2025, 12:22:55 pm »
The algorithm is defined in terms of decimal digits which can be easily implemented without the intermediate step of converting to/from text representation:
Code: Pascal  [Select][+][-]
  1. function GetCheckDigit2(num: Integer): Integer;
  2. const
  3.   weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  4. var
  5.   i, sum: Integer;
  6. begin
  7.   // Sanity check
  8.   if (num > 99999999) or (num < 0) then
  9.     Exit(-1);
  10.  
  11.   sum := 0;
  12.   for i := 7 to 0 do
  13.   begin
  14.     sum := sum + weights[i] * (num mod 10);
  15.     num := num div 10;
  16.   end;
  17.  
  18.   sum := 11 - (sum mod 11);
  19.   if sum = 10 then
  20.     Result := 0
  21.   else if sum = 11 then
  22.     Result := 5
  23.   else
  24.     Result := sum;
  25. end;

LV

  • Sr. Member
  • ****
  • Posts: 272
Re: Convert this Python code pls.
« Reply #5 on: April 25, 2025, 05:02:50 pm »
The algorithm is defined in terms of decimal digits which can be easily implemented without the intermediate step of converting to/from text representation:

It looks like the function GetCheckDigit2(num: Integer): Integer; is giving errors.   :-[

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. function GetCheckDigit1(num: Integer): Integer;
  7. const
  8.   weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  9. var
  10.   s: string;
  11.   i, digit, total: Integer;
  12. begin
  13.   s := Format('%.8d', [num]);
  14.   if Length(s) > 8 then
  15.     s := Copy(s, 1, 8);
  16.  
  17.   total := 0;
  18.   for i := 1 to 8 do
  19.   begin
  20.     digit := Ord(s[i]) - Ord('0');
  21.     total := total + weights[i-1] * digit;
  22.   end;
  23.  
  24.   total := 11 - (total mod 11);
  25.  
  26.   if total = 10 then
  27.     total := 0
  28.   else if total = 11 then
  29.     total := 5;
  30.  
  31.   Result := total;
  32. end;
  33.  
  34. function GetCheckDigit2(num: Integer): Integer;
  35. const
  36. weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  37. var
  38. i, sum: Integer;
  39. begin
  40.   // Sanity check
  41.   if (num > 99999999) or (num < 0) then
  42. Exit(-1);
  43.  
  44. sum := 0;
  45.   for i := 7 to 0 do
  46.   begin
  47. sum := sum + weights[i] * (num mod 10);
  48. num := num div 10;
  49.   end;
  50.  
  51. sum := 11 - (sum mod 11);
  52.   if sum = 10 then
  53. Result := 0
  54.   else if sum = 11 then
  55. Result := 5
  56.   else
  57. Result := sum;
  58. end;
  59.  
  60. procedure test_check_digit(num: Integer; expected: Integer);
  61. var
  62.   result1, result2: Integer;
  63. begin
  64.   result1 := GetCheckDigit1(num);
  65.   Write('Test 1 for num=', num:10, ': ');
  66.   if result1 = expected then
  67.     WriteLn('Passed')
  68.   else
  69.     WriteLn('FAILED (got ', result1, ', expected ', expected, ')');
  70.  
  71.  
  72.       result2 := GetCheckDigit2(num);
  73.       Write('Test 2 for num=', num:10, ': ');
  74.       if result2 = expected then
  75.         WriteLn('Passed')
  76.       else
  77.         WriteLn('FAILED (got ', result2, ', expected ', expected, ')');
  78. end;
  79.  
  80. begin
  81.   test_check_digit(0,          5);
  82.   test_check_digit(1,          4);
  83.   test_check_digit(10,         2);
  84.   test_check_digit(99999999,   5);
  85.   test_check_digit(12345678,   5);
  86.   test_check_digit(87654321,   6);
  87.   test_check_digit(11111111,   5);
  88.   test_check_digit(22222222,   5);
  89.   test_check_digit(10000000,   3);
  90.   ReadLn;
  91. end.
  92.  

output:

Code: Text  [Select][+][-]
  1. Test 1 for num=         0: Passed
  2. Test 2 for num=         0: Passed
  3. Test 1 for num=         1: Passed
  4. Test 2 for num=         1: FAILED (got 5, expected 4)
  5. Test 1 for num=        10: Passed
  6. Test 2 for num=        10: FAILED (got 5, expected 2)
  7. Test 1 for num=  99999999: Passed
  8. Test 2 for num=  99999999: Passed
  9. Test 1 for num=  12345678: Passed
  10. Test 2 for num=  12345678: Passed
  11. Test 1 for num=  87654321: Passed
  12. Test 2 for num=  87654321: FAILED (got 5, expected 6)
  13. Test 1 for num=  11111111: Passed
  14. Test 2 for num=  11111111: Passed
  15. Test 1 for num=  22222222: Passed
  16. Test 2 for num=  22222222: Passed
  17. Test 1 for num=  10000000: Passed
  18. Test 2 for num=  10000000: FAILED (got 5, expected 3)
  19.  

Updated: Expected values ​​are taken from the Python code results (see above).
« Last Edit: April 25, 2025, 05:22:19 pm by LV »

ccrause

  • Hero Member
  • *****
  • Posts: 1015
Re: Convert this Python code pls.
« Reply #6 on: April 25, 2025, 06:15:35 pm »
It looks like the function GetCheckDigit2(num: Integer): Integer; is giving errors.   :-[

Indeed, thanks for checking! I should have used downto in the for loop >:(. Fixed version (it passes all the test values in @LV's post):
Code: Pascal  [Select][+][-]
  1. function GetCheckDigit2(num: Integer): Integer;
  2. const
  3.   weights: array[0..7] of Integer = (8, 6, 4, 2, 3, 5, 9, 7);
  4. var
  5.   i, sum: Integer;
  6. begin
  7.   // Sanity check
  8.   if (num > 99999999) or (num < 0) then
  9.     Exit(-1);
  10.  
  11.   sum := 0;
  12.   for i := 7 downto 0 do
  13.   begin
  14.     sum := sum + weights[i] * (num mod 10);
  15.     num := num div 10;
  16.   end;
  17.  
  18.   sum := 11 - (sum mod 11);
  19.   if sum = 10 then
  20.     Result := 0
  21.   else if sum = 11 then
  22.     Result := 5
  23.   else
  24.     Result := sum;
  25. end;

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1266
Re: Convert this Python code pls.
« Reply #7 on: April 27, 2025, 02:56:08 am »
hello,
performance comparison (see attachment) between python and lazarus for the function checkDigit using python4Lazarus and EpikTimer.
Code :
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Res : Variant;
  4.   resu : Integer;
  5. begin
  6.   EpikTimer1.Clear;
  7.   EpikTimer1.Start;
  8.   PythonEngine1.ExecStrings( Memo1.Lines );
  9.   EpikTimer1.Stop;
  10.   Memo2.Append('PythonEngine ExeStrings : ' + EpikTimer1.ElapsedStr);
  11.   EpikTimer1.Clear;
  12.   EpikTimer1.Start;
  13.   Res := MainModule.get_check_digit(12345678);
  14.   EpikTimer1.Stop;
  15.   Memo2.Append('Res : ' + EpikTimer1.ElapsedStr);
  16.   Memo2.Append('Résultat : ' + Res);
  17.   EpikTimer1.Clear;
  18.   EpikTimer1.Start;
  19.   resu := GetCheckDigit1(12345678);
  20.   EpikTimer1.Stop;
  21.   Memo2.Append('resu : ' + EpikTimer1.ElapsedStr);
  22.   Memo2.Append('resu checkDigit1 : ' + InttoStr(resu));
  23.   EpikTimer1.Clear;
  24.   EpikTimer1.Start;
  25.   resu := GetCheckDigit2(12345678);
  26.   EpikTimer1.Stop;
  27.   Memo2.Append('resu : ' + EpikTimer1.ElapsedStr);
  28.   Memo2.Append('resu checkDigit2 : ' + InttoStr(resu));
  29. end;

Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

 

TinyPortal © 2005-2018