Recent

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

Petrus Vorster

  • Full Member
  • ***
  • Posts: 239
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: 437
  • 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: 18764
  • To Europe: simply sell USA bonds: dollar collapses
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
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Petrus Vorster

  • Full Member
  • ***
  • Posts: 239
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: 1094
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: 426
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: 1094
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: 1290
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