How to validate a CPF using a function in R? [closed]

3

I'm trying to improve the @Rui Barradas code that is posted here as a response, but the same does not work for some situations. After debugging the code, I understand that the problem is in the cpf_validar function, since cpf_dig_controle works well, even entering 9 digits and cpf_gerar is ok for me. I already moved in a few lines, but I did not succeed. If anyone can make any contribution:

# gerar digito de controle a partir de 8 digitos
cpf_dig_controle <- function(y){
v1 <- 0L
v2 <- 0L
z <- as.integer(rev(strsplit(as.character(y), "")[[1]]))
for(i in seq_along(z)){
v1 <- v1 + z[i]*(9 - (i %% 10))
v2 <- v2 + z[i]*(9 - ((i + 1) %% 10))
}
v1 <- (v1 %% 11) %% 10
v2 <- v2 + v1*9
v2 <- (v2 %% 11) %% 10
c(v1, v2)
}

# gerar CPF
cpf_gerar <- function(x){
g <- function(y, v){
z <- strsplit(as.character(y), "")[[1]]
z <- as.integer(c(z, v))
res <- sprintf(fmt = "%d%d%d.%d%d%d.%d%d%d-%02d",
               z[1], z[2], z[3], z[4], z[5],
               z[6], z[7], z[8], z[9], z[10])
res
}
v <- lapply(x, cpf_dig_controle)
result <- sapply(seq_along(x), function(i) g(x[i], v[[i]]))
result
}

# cpf gerado
cpf <- cpf_gerar(c("01861932", "01234567","12345678","11511611"))
cpf

# validar cpf
cpf_validar <- function(x){
f <- function(y){
z <- unlist(strsplit(y, "\."))
v <- substr(z[3], 3, 6)
v <- as.integer(unlist(strsplit(v, "-")))
z[3] <- substr(z[3], 1, 2)
z <- as.integer(paste(z, collapse = ""))
list(x = z, v = v)
}
result <- lapply(x, f)
valido <- lapply(result, function(r) unlist(lapply(r$x, 
cpf_dig_controle)))
valido <- sapply(seq_along(valido), function(i)
result[[i]]$v[1] == valido[[i]][1] & result[[i]]$v[2] == valido[[i]][2]
)
valido
}

#cpfs gerados pela função cpf_dig_controle a partir de 8 digitos
cpf_validar(c("018.619.323-00","012.345.673-02","123.456.786- 
02","115.116.111-04"))

#cpf válido, porém a função o qualifica como FALSE
cpf_validar("288.065.030-57")
    
asked by anonymous 09.10.2018 / 04:34

1 answer

3

I made changes to the three functions created by @Rui Barradas in this post .

I modified the generator algorithm of the verifier digits because when I placed my CPF, the generated values did not hit. The new algorithm I used was that of site .

cpf_dig_controle <- function(y){
 v1 <- 0L
  v2 <- 0L
  num <- is.numeric(y)
  z <- as.integer(strsplit(as.character(y), "")[[1]])
  n <- length(z)
  if(num){
    if(n == 7){
      z <- c(0, z, sample(0:9, 1))
    } else{
      if(n == 8){
        z <- c(0, z)
      } else{
        z <- z
      }
    }
  } else{
    if(n == 8){
      z <- c(z, sample(0:9, 1))
    } else{
      z <- z
    }
  }
  for(i in seq_along(z)){
    v1 <- v1 + z[i]*(11-i)
    v2 <- v2 + z[i]*(12-i)
  }
  v1 <- v1 %% 11
  if(v1 < 2){
    v1 <- 0
  } else{
    v1 <- 11 - v1
  }
  v2 <- v2 + 2*v1
  v2 <- v2 %% 11
  if(v2 < 2){
    v2 <- 0
  } else{
    v2 <- 11 - v2
  }
  c(v1, v2)
}

I changed the cpf_gerar function because it always put the number 0 as the first one after the dash (-) in the CPF.

 cpf_gerar <- function(x){
   g <- function(y, v){
     num <- is.numeric(y)
     z <- as.integer(strsplit(as.character(y), "")[[1]])
     n <- length(z)
     if(num){
       if(n == 7){
         z <- c(0, z, sample(0:9, 1))
       } else{
         if(n == 8){
           z <- c(0, z)
         } else{
           z <- z
         }
       }
     } else{
       if(n == 8){
         z <- c(z, sample(0:9, 1))
       } else{
         z <- z
       }
     }
     z <- as.integer(c(z, v))
     res <- sprintf(fmt = "%d%d%d.%d%d%d.%d%d%d-%d%d",
                    z[1], z[2], z[3], z[4], z[5], z[6], z[7], z[8], z[9], z[10], z[11])
     res
   }
   v <- lapply(x, cpf_dig_controle)
   result <- sapply(seq_along(x), function(i) g(x[i], v[[i]]))
   result
 }

Finally, I took into account the changes made in the two functions above to modify cpf_validar .

cpf_validar <- function(x){
  f <- function(y){
    z <- unlist(strsplit(y, "\."))
    v <- substr(z[3], 5, 6)
    v <- as.integer(unlist(strsplit(v, "")))
    z[3] <- substr(z[3], 1, 3)
    z <- as.integer(paste(z, collapse = ""))
    list(x = z, v = v)
  }
  result <- lapply(x, f)
  valido <- lapply(result, function(r) unlist(lapply(r$x, cpf_dig_controle)))
  valido <- sapply(seq_along(valido), function(i)
    result[[i]]$v[1] == valido[[i]][1] & result[[i]]$v[2] == valido[[i]][2]
  )
  valido
}

When performing the test with cpf's that you are sure are valid and were giving FALSE in old functions and after changes to validate 0 as first digit, I get:

cpf_validar("288.065.030-57")
[1] TRUE

cpf_gerar("018619326")
[1] "018.619.326-26"
cpf_gerar(018619326)
[1] "018.619.326-26"
cpf_validar("018.619.326-26")
[1] TRUE

cpf_gerar("012345678")
[1] "012.345.678-90"
cpf_gerar(012345678)
[1] "012.345.678-90"
cpf_validar("012.345.678-90")
[1] TRUE
    
10.10.2018 / 15:21