Jump to content

Check Italy Fiscal Code: Controllo Codice Fiscale


Efo74
 Share

Recommended Posts

;*****************************************************************************************************************
Func Controllo_CodiceFiscale($CFis)
;*****************************************************************************************************************
;Restituisce: true se il Codice fiscale è corretto
    Dim $i,$p,$d
    Dim $SumDisp=0,$Sumpari=0
    Dim $SumTot=0,$Check
    Dim $Resto[27]
$CFis = StringUpper($CFis)
    If StringLen($CFis) <> 16 Then
       Return False
 EndIf
    $Resto[1] = "A"
    $Resto[2] = "B"
    $Resto[3] = "C"
    $Resto[4] = "D"
    $Resto[5] = "E"
    $Resto[6] = "F"
    $Resto[7] = "G"
    $Resto[8] = "H"
    $Resto[9] = "I"
    $Resto[10] = "J"
    $Resto[11] = "K"
    $Resto[12] = "L"
    $Resto[13] = "M"
    $Resto[14] = "N"
    $Resto[15] = "O"
    $Resto[16] = "P"
    $Resto[17] = "Q"
    $Resto[18] = "R"
    $Resto[19] = "S"
    $Resto[20] = "T"
    $Resto[21] = "U"
    $Resto[22] = "V"
    $Resto[23] = "W"
    $Resto[24] = "X"
    $Resto[25] = "Y"
    $Resto[26] = "Z"
    For $i = 2 To 14 Step 2
  $retn = StringMid($CFis, $i, 1)
        Select
  Case $retn="0"
   $p = 0
  Case $retn="1"
   $p = 1
  Case $retn="2"
   $p = 2
  Case $retn="3"
   $p = 3
  Case $retn="4"
   $p = 4
  Case $retn="5"
   $p = 5
  Case $retn="6"
   $p = 6
  Case $retn="7"
   $p = 7
  Case $retn="8"
   $p = 8
  Case $retn="9"
   $p = 9
  Case $retn="A"
   $p = 0
  Case $retn="B"
   $p = 1
  Case $retn="C"
   $p = 2
  Case $retn="D"
   $p = 3
  Case $retn="E"
   $p = 4
  Case $retn="F"
   $p = 5
  Case $retn="G"
   $p = 6
  Case $retn="H"
   $p = 7
  Case $retn="I"
   $p = 8
  Case $retn="J"
   $p = 9
  Case $retn="K"
   $p = 10
  Case $retn="L"
   $p = 11
  Case $retn="M"
   $p = 12
  Case $retn="N"
   $p = 13
  Case $retn="O"
   $p = 14
  Case $retn="P"
   $p = 15
  Case $retn="Q"
   $p = 16
  Case $retn="R"
   $p = 17
  Case $retn="S"
   $p = 18
  Case $retn="T"
   $p = 19
  Case $retn="U"
   $p = 20
  Case $retn="V"
   $p = 21
  Case $retn="W"
   $p = 22
  Case $retn="X"
   $p = 23
  Case $retn="Y"
   $p = 24
  Case $retn="Z"
   $p = 25
        EndSelect
        $Sumpari = $Sumpari + $p
    Next
    For $i = 1 To 15 Step 2
  $retn = StringMid($CFis, $i, 1)
        Select
   Case $retn="0"
    $d = 1
            Case $retn="1"
    $d = 0
            Case $retn="2"
    $d = 5
            Case $retn="3"
    $d = 7
            Case $retn="4"
    $d = 9
            Case $retn="5"
    $d = 13
            Case $retn="6"
    $d = 15
            Case $retn="7"
    $d = 17
            Case $retn="8"
    $d = 19
            Case $retn="9"
    $d = 21
            Case $retn="A"
    $d = 1
            Case $retn="B"
    $d = 0
            Case $retn="C"
    $d = 5
            Case $retn="D"
    $d = 7
            Case $retn="E"
    $d = 9
            Case $retn="F"
    $d = 13
            Case $retn="G"
    $d = 15
            Case $retn="H"
    $d = 17
            Case $retn="I"
    $d = 19
            Case $retn="J"
    $d = 21
            Case $retn="K"
    $d = 2
            Case $retn="L"
    $d = 4
            Case $retn="M"
    $d = 18
            Case $retn="N"
    $d = 20
            Case $retn="O"
    $d = 11
            Case $retn="P"
    $d = 3
            Case $retn="Q"
    $d = 6
            Case $retn="R"
    $d = 8
            Case $retn="S"
    $d = 12
            Case $retn="T"
    $d = 14
            Case $retn="U"
    $d = 16
            Case $retn="V"
    $d = 10
            Case $retn="W"
    $d = 22
            Case $retn="X"
    $d = 25
            Case $retn="Y"
    $d = 24
            Case $retn="Z"
    $d = 23
        EndSelect
        $SumDisp = $SumDisp + $d
    Next
    $SumTot = $Sumpari + $SumDisp
    $Check = $Resto[Mod($SumTot,26) + 1]
    If $Check = StringUpper(StringRight($CFis, 1)) Then
       Return True
    Else
       Return False
    EndIf
EndFunc

Edited by Melba23

Efo74, Please use Code tags - put [autoit] before and [/autoit] after your posted code. :)

Reason: added code tags

Edited by Melba23

:rolleyes:

Link to comment
Share on other sites

The $resto array can be easily eliminated, if the one line using it is changed to

$Check = Asc(Mod($SumTot,26) + 64)

The first case statement converts char 0-9 to number 0-9, and A-Z to 0-25. Easier and safer with Asc, range check, and add one of two offsets.

The second case statement is strange. I can't see the logic in the conversion. The real problem is this style is prone to typo error, and you have to test every value.

Richard

Italian: ;Restituisce: true se il Codice fiscale è corretto

English: ;Return true if the financial code is correct

Edited by RichardL
Link to comment
Share on other sites

I think the code would improve much more if you would delegate the responsibility of finding correct number value for a char to another function. Whether you use switch statement or a asc/chr thing does not really matter. There is something to be said for consistently using switch statements, since the second rule is random and does not follow any logic (dispari rule).

This is the reasoning behind why I said it is difficult to clean up dramatically.

Edited by Manadar
Link to comment
Share on other sites

Here a shorter version:

ConsoleWrite(Controllo_CodiceFiscale2("RSSMRA50A01F205R") & @LF)

;*****************************************************************************************************************
Func Controllo_CodiceFiscale2($CFis)
    ;*****************************************************************************************************************
    ;Restituisce: true se il Codice fiscale è corretto
    Local $i, $p, $d
    Local $SumDisp = 0, $Sumpari = 0
    Local $SumTot = 0, $Check
    Local $Resto[27]
    $CFis = StringUpper($CFis)
    If StringLen($CFis) <> 16 Then Return False

    $aCFis = StringSplit($CFis, "")
    For $i = 1 To $aCFis[0]
        Switch Mod($i, 2)
            Case 1
                $asc = Asc($aCFis[$i])
                Switch $asc
                    Case 48, 65
                        $d = 1
                    Case 49, 66
                        $d = 0
                    Case 50, 67
                        $d = 5
                    Case 51, 68
                        $d = 7
                    Case 52, 69
                        $d = 9
                    Case 53, 70
                        $d = 13
                    Case 54, 71
                        $d = 15
                    Case 55, 72
                        $d = 17
                    Case 56, 73
                        $d = 19
                    Case 57, 74
                        $d = 21
                    Case 75
                        $d = 2
                    Case 76
                        $d = 4
                    Case 77
                        $d = 18
                    Case 78
                        $d = 20
                    Case 79
                        $d = 11
                    Case 80
                        $d = 3
                    Case 81
                        $d = 6
                    Case 82
                        $d = 8
                    Case 83
                        $d = 12
                    Case 84
                        $d = 14
                    Case 85
                        $d = 16
                    Case 86
                        $d = 10
                    Case 87
                        $d = 22
                    Case 88
                        $d = 25
                    Case 89
                        $d = 24
                    Case 90
                        $d = 23
                EndSwitch
                $SumDisp += $d
            Case 0
                If $i < 15 Then
                    $asc = Asc($aCFis[$i])
                    Switch $asc
                        Case 48 To 57
                            $p = $asc - 48
                        Case Else
                            $p = $asc - 65
                    EndSwitch
                    $Sumpari += $p
                EndIf
        EndSwitch
    Next

    $SumTot = $Sumpari + $SumDisp

    $Check = Chr(65 + Mod($SumTot, 26))
    If $Check = $aCFis[$aCFis[0]] Then Return True

    Return False
EndFunc   ;==>Controllo_CodiceFiscale

I didn't find the any logic with the even numbers...

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

A bit shorter if we only count line numbers

; Author: UEZ, mod by martin
; Topic Title: Check Italy Fiscal Code: Controllo Codice Fiscale - AutoIt Forums
; Post URL: http://www.autoitscript.com/forum/topic/136159-check-italy-fiscal-code-controllo-codice-fiscale/page__view__findpost__p__951307

$aOdds = StringSplit("48,1,65,1,49,0,66,0,50,5,67,5,51,7,68,7,52,9,69,9,53,13,70,13,54,15,71,15,55,17,72,17,56,19,73,19,57,21,74,21,75,2,76,4,77,18,78,20,79,11," & _
        "80, 3, 81, 6, 82, 8, 83, 12, 84, 14, 85, 16, 86, 10, 87, 22, 88, 25, 89, 24, 90, 23", ',')
        

ConsoleWrite(Controllo_CodiceFiscale2("RSSMRA50A01F205R") & @LF)

;*****************************************************************************************************************
Func Controllo_CodiceFiscale2($CFis)
    ;*****************************************************************************************************************
    ;Restituisce: true se il Codice fiscale è corretto
    Local $i, $p, $d
    Local $SumDisp = 0, $Sumpari = 0
    Local $SumTot = 0, $Check
    Local $Resto[27]
    $CFis = StringUpper($CFis)
    If StringLen($CFis) <> 16 Then Return False

    $aCFis = StringSplit($CFis, "")
    For $i = 1 To $aCFis[0]
        Switch Mod($i, 2)
            Case 1
                $asc = Asc($aCFis[$i])
                For $k = 1 To $aOdds[0] Step 2
                    If $asc = $aOdds[$k] Then
                        $d = $aOdds[$k + 1]
                        ExitLoop
                    EndIf
                Next
                 
                $SumDisp += $d
            Case 0
                If $i < 15 Then
                    $asc = Asc($aCFis[$i])
                    Switch $asc
                        Case 48 To 57
                            $p = $asc - 48
                        Case Else
                            $p = $asc - 65
                    EndSwitch
                    $Sumpari += $p
                EndIf
        EndSwitch
    Next

    $SumTot = $Sumpari + $SumDisp

    $Check = Chr(65 + Mod($SumTot, 26))
    If $Check = $aCFis[1] Then Return True

    Return False
EndFunc   ;==>Controllo_CodiceFiscale2
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Here my next version inspired by martin :)

$code = "RSSMVA50A01F205R"
ConsoleWrite(Controllo_CodiceFiscale2($code) & @LF)

;*****************************************************************************************************************
Func Controllo_CodiceFiscale2($CFis)
;*****************************************************************************************************************
    ;Restituisce: true se il Codice fiscale è corretto
    Local $i, $p, $d, $SumDisp = 0, $Sumpari = 0, $SumTot = 0, $Check, $Resto[27]
    If StringLen($CFis) <> 16 Then Return False
    Local $aValD[43] = [1, 0, 5, 7 , 9, 13, 15, 17, 19, 21, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23]
    Local $aValP[43] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
    $aCFis = StringSplit(StringUpper($CFis), "")
    For $i = 1 To $aCFis[0]
        Switch Mod($i, 2)
            Case 1
                $SumDisp += $aValD[Asc($aCFis[$i]) - 48]
            Case 0
                If $i < 15 Then $Sumpari += $aValP[Asc($aCFis[$i]) - 48]
        EndSwitch
    Next
    $Check = Chr(65 + Mod($Sumpari + $SumDisp, 26))
    If $Check = $aCFis[$aCFis[0]] Then Return True
    Return False
EndFunc   ;==>Controllo_CodiceFiscale

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Ok, I found the bug!

Instead of reading StringRight() I read StringLeft() on final check.

Please try it again!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

UEZ, I hate you for ignoring my note on "better code" and just made the "shorter code"! Naturally, I want to try to write shorter code too.

So therefore: Screw readability and let's get WET.

$code = "RSSMRA85T10A562S"
ConsoleWrite(Controllo_CodiceFiscale2($code) & @LF)
$code = "RSSMRA85T19A562S"
ConsoleWrite(Controllo_CodiceFiscale2($code) & @CRLF)

Func Controllo_CodiceFiscale2($CFis)
    Local $aValD[43] = [1, 0, 5, 7 , 9, 13, 15, 17, 19, 21, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23], $aValP[43] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], $SumDisp = 0, $Sumpari = 0
    $aCFis = StringSplit(StringUpper($CFis), "")
    For $i = 1 To $aCFis[0]
        If Mod($i, 2) Then $SumDisp += $aValD[Asc($aCFis[$i]) - 48]
        If $i < 15 And Not Mod($i, 2) Then $Sumpari += $aValP[Asc($aCFis[$i]) - 48]
    Next
    Return (Chr(65 + Mod($Sumpari + $SumDisp, 26)) = $aCFis[$aCFis[0]]) And (StringLen($CFis) = 16)
EndFunc
Edited by Manadar
Link to comment
Share on other sites

...

This is the reasoning behind why I said it is difficult to clean up dramatically.

It wasn't too difficult if you have the right idea. :)

UEZ, I hate you for ignoring my note on "better code" and just made the "shorter code"! Naturally, I want to try to write shorter code too.

...

In this case "better code" = shorter code! ;)

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

It wasn't too difficult if you have the right idea. :)

In this case "better code" = shorter code! ;)

I'm not sure if you're joking here or not.

Just be aware that most of the code following your first post is just as poorly written as the OPs code. Remember what matters here, readability, understandability, maintainability, etc. Everything after your first post goes downhill quickly. My last is rock bottom? Or almost.. maybe.

Edited by Manadar
Link to comment
Share on other sites

I was not talking about my 1st idea because my 1st attempt was just a quick idea and yes it is not much better then the op's one!

I was talking about my 2nd idea!

But I cannot see on your code in post #14 what is yours?

Br,

UEZ :)

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

UEZ, I believe you are trolling.

@czardas,

I personally put efficiency and stability above readabiliity. Sometimes it produces more code, and at other times not.

The principal requirement about software is that it fits the requirements of that software. The principal requirement about code is that it produces the software fitting the requirements.

Efficiency and stability are primarily attributes about software, not about code. In your post you are talking about the software attributes versus the readability code attribute. Software attributes are dependent on the requirements. Prioritizing efficiency and stability over other factors with disregard of the requirements of that software produces software which does not fit the requirements and/or is not on time and/or over budget.

Efficiency is also not a requirement of software. It's not a specific enough to be a requirement. You cannot measure objectively whether a software is efficient. You cannot measure the time it takes for the program to respond to a specified button press and call it 'efficient enough' according to requirements which do not state what efficiency is and how it should be measured.

Then there are properties about code which are universal among all software. One more time for you, from good code -> Fun code: Readable, Understandable, Maintainable, Self-Explanatory, Idiomatic, Efficient, Optimized, Elegant, Hackvalue. But this is more of a joke with truth than a good guideline.

Edited by Manadar
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...