Pesquisar este blog

Livros Recomendados

terça-feira, 23 de fevereiro de 2021

URI (BEECROWD) - 1769 - CPF 1 - Ad-Hoc - C e C++

Problema relacionados aos cálculos envolvidos no CPF (Cadastro de Pessoa Física) são sempre interessantes! O problema "CPF 1" é um desses, então vamos ver como podemos resolvê-lo!

Plataforma: URI (BEECROWD)

Problema1769

Enunciado:

Você foi contratado pelas Indústrias Udilandenses (INUDIL) para desenvolver uma maneira de verificar se o Cadastro de Pessoa Física (CPF) indicado por um cliente era válido ou não. Conversando com amigos, você chegou à conclusão de que um CPF seria válido se a soma de todos os seus dígitos resultasse em número múltiplo de 11. Após verificação minuciosa, você descobriu que essa maneira só funciona em cerca de 80% dos casos, e você precisa de mais do que isso para garantir a qualidade do seu trabalho. Após pesquisar mais, você descobriu que dos 11 dígitos do CPF, os dois últimos são verificadores e dependem dos 9 dígitos anteriores. Vamos introduzir alguma notação. Considere um CPF com os seguintes dígitos

a1a2a. a4a5a. a7a8a- b1b2

Para descobrirmos o dígito b1, procedemos da seguinte maneira: multiplicamos o primeiro por 1, o segundo por 2, o terceiro por 3, o quarto por 4 e vamos assim até multiplicarmos o nono por 9. Então, somamos tudo isto. Após termos somado tudo, dividimos por 11. O dígito b1 será o resto da divisão (ou 0, caso o resto seja 10).

Para o segundo dígito verificador, temos o seguinte: multiplicamos o primeiro por 9, o segundo por 8, o terceiro por 7, o quarto por 6 e vamos assim até multiplicarmos o nono por 1. Então, somamos tudo isto e dividimos por 11. O dígito b2 será o resto da divisão (ou 0, caso o resto seja 10).

Sabendo que isso vale para 100% dos CPFs, sua missão é implementar um programa que, dado um CPF, diga se ele é válido ou não.

Linguagens: C e C++

Solução:

As primeiras soluções aqui apresentadas convertem os dígitos do CPF para um array digitos. Depois disso, uma variável acumuladora (ac) obtém o somatório do dígito atual multiplicado pela sua posição. Depois disso, calcula o valor do primeiro dígito verificador e repete o processo, dessa vez aplicando também ao último dígito. Se estes dois valores não forem iguais aos últimos dois dígitos do CPF lido, então o CPF será inválido.

Código em C:

#include <stdio.h>
int main() {
    char cpf[15];
    int digitos[11], ac, i, j;
    while (scanf("%s", cpf) != EOF) {
        ac = 0;
        for (i = 0, j = 0; i < 11; i ++)
            if (i != 3 && i != 7)
                digitos[j++] = cpf[i] - '0';
        for (i = 0; i < 9; i++)
            ac += digitos[i] * (i + 1);
        ac %= 11;
        digitos[9] = (ac == 10? 0 : ac);
        ac = 0;
        for (i = 0; i < 9; i++)
            ac += digitos[i] * (9 - i);
        ac %= 11;
        digitos[10] = (ac == 10? 0 : ac);
        printf("CPF ");
        if (digitos[9] != cpf[12] - '0' || digitos[10] != cpf[13] - '0')
            printf("in");
        printf("valido\n");
    }
    return 0;
}

Código em C++:

#include <algorithm>
#include <iostream>
using namespace std;
int main() {
    string cpf;
    int digitos[11], ac;
    while (cin >> cpf) {
        ac = 0;
        cpf.erase(remove(cpf.begin(), cpf.end(), '.'), cpf.end());
        cpf.erase(remove(cpf.begin(), cpf.end(), '-'), cpf.end());
        for (int i = 0; i < 9; i++) {
            digitos[i] = cpf[i] - '0';
            ac += digitos[i] * (i + 1);
        }
        ac %= 11;
        digitos[9] = (ac == 10? 0 : ac);
        ac = 0;
        for (int i = 0; i < 9; i++) {
            ac += digitos[i] * (9 - i);
        }
        ac %= 11;
        digitos[10] = (ac == 10? 0 : ac);
        cout << "CPF ";
        if (digitos[9] != cpf[9] - '0' || digitos[10] != cpf[10] - '0')
            cout << "in";
        cout << "valido" << endl;
    }
    return 0;
}

Solução alternativa em C++:
Aqui a ideia foi acumular o somatório dos valores multiplicados pelos respectivos índices nas variáveis sum e sum2, verificando depois os restos com as condições (sum%11 == (str[12]-'0') or sum%11 == (str[12]-'0'+10)) and (sum2%11 == (str[13]-'0') or sum2%11 == (str[13]-'0'+10)) para saber se o CPF é válido ou não.

 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
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
 
int main() {
	string str;
	while(cin >> str){
		int sum = 0;
		sum += (str[0]-'0')*1;
		sum += (str[1]-'0')*2;
		sum += (str[2]-'0')*3;
		sum += (str[4]-'0')*4;
		sum += (str[5]-'0')*5;
		sum += (str[6]-'0')*6;
		sum += (str[8]-'0')*7;
		sum += (str[9]-'0')*8;
		sum += (str[10]-'0')*9;

		int sum2 = 0;
		sum2 += (str[0]-'0')*9;
		sum2 += (str[1]-'0')*8;
		sum2 += (str[2]-'0')*7;
		sum2 += (str[4]-'0')*6;
		sum2 += (str[5]-'0')*5;
		sum2 += (str[6]-'0')*4;
		sum2 += (str[8]-'0')*3;
		sum2 += (str[9]-'0')*2;
		sum2 += (str[10]-'0')*1;
		
		if( (sum%11 == (str[12]-'0') or sum%11 == (str[12]-'0'+10)) and
		    (sum2%11 == (str[13]-'0') or sum2%11 == (str[13]-'0'+10))){
			cout << "CPF valido"<<endl;
		}
		else{
			cout << "CPF invalido"<<endl;
		}
	}
}

Nenhum comentário:

Postar um comentário

Postagem em destaque

URI (BEECROWD) - 2158 - Helping Uncle Cláudio (Ajudando o Tio Cláudio) - Matemática - C, C++ e Haskell

Buenas! Estou aqui mais uma vez para resolver um problema de Matemática! Agora tenho resolvido alguns dessa categoria, pra que vocês possam ...

Postagens mais visitadas