Funções ZZ em J (comentadas)

Como o Aurélio está atualizando as Funções ZZ, resolvi pegar apenas duas e convertê-las para J.

zzsenha

Primeiro a zzsenha. Ela é chamada com um valor e retorna uma senha de no mínimo seis caracteres  quaisquer e não repetidos. A versão atual foi modificada com opções pro, etc. Peguei a versão antiga.

zzsenha=: verb define
alpha=.'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
maximo=.#alpha
assert. y<:maximo
if. y<6 do. y=.6 end.
(y?maximo) { alpha
)

Bem, vamos ver como interpretar cada linha do verbo que criamos (coloquei os links para a definição de alguns verbos do J utilizados bem como os seus nomes quem quiser saber mais; lembrando que podem ter funcionamento diferente para um ou dois argumentos:

zzsenha=: verb define
É o início da definição do verbo para ser utilizado posteriormente.

Copula Global =:

alpha=. ‘0123…xyz’
É o vetor de onde pegaremos os caracteres para compor a senha (poderíamos ter definido como alpha=.a.{~;48 65 97(+i.)&.>10 26 26).

Copula Local =.

maximo=. # alpha
É a quantidade de caracteres existente no vetor alpha (#alpha retorna o número de itens em alpha).

Tally #

assert. y <: maximo
Como não queremos elementos repetidos, o tamanho da senha desejada deverá ser menor ou igual a quantidade de itens em alpha.

Less Or Equal <:
assert.

if. y<6 do. y=. 6 end.
Foi estipulado que o tamanho mínimo da senha deverá ser de 6 caracteres (lembrando que os parâmetros são x verbo y)

if.

(y ? maximo) { alpha
A primeira parte, (y?maximo), irá gerar y números aleatórios e não repetidos entre 0 e maximo-1 e irá pegá-los do vetor alpha.

Deal ?
From {

)
Encerra a definição do verbo.

Exemplo de utilização:

  zzsenha 5
PRfleU
  zzsenha 12
gG3HVLD5yJAd
  zzsenha 12
5qwLuW78xDPn
  zzsenha 12
LpsOquRZfIWE
  zzsenha 20
HR962vrf5GAhzIN0eJqW

zzcpf

Agora a definição em J da função zzcpf. Optei por não gerar um CPF aleatório e apenas conferir se o CPF enviado está correto. Só por curiosidade, a geração de nove números aleatórios entre 0 e 9 para criar um CPF para depois gerar os dígitos verificadores seria dado pela frase ?9$10. O CPF enviado como parâmetro é no formato 27742221250, isto é, um número inteiro sem os caracteres da formatação .

zzcpf=: 3 : 0
cpf=."."0":x:y
assert. 11=#cpf
base=.9{.cpf
d1=.11-11|+/(2+i._9)*base
d1=.d1*d1<10
d2=.11-11|+/(2+i._10)*base,d1
d2=.d2*d2<10
ok=.*/cpf=base,d1,d2
)

zzcpf=: 3 : 0
Outra forma de definição do verbo. Em vez de verb define eu uso 3:0. (maiores explicações nos manuais)

cpf=. “. “0 “: x: y
Como decidi enviar o CPF como um número, é necessário separar cada algarismo e colocá-o em uma posição de um vetor para facilitar as multiplicações para o cálculo dos dígitos verificadores. Primeiro certificamos que o argumento será tratado como precisão estendida para termos certeza que trabalharemos com todos os dígitos e não na forma exponencial (1.231e11). Convertemos o número para uma string. Convertemos novamente para numérico “. pegando cada célula individual “0 gerando assim um vetor CPF onde cada elemento corresponde a um número e não apenas a conversão do nũmero original. Ficaria 2 7 7 4 2 2 2 1 2 5 0.

Extended Precision x:
Default Format “:
Numbers “.
Rank “0

assert. 11 = # cpf
Igual ao procedimento de zzsenha. O número do CPF informado deverá possuir 11 dígitos ou gera um erro.

base=. 9 {. cpf
Criamos o vetor base contendo os 9 primeiros elementos do CPF informado. Ficaria 2 7 7 4 2 2 2 1 2

Take {.

d1=. 11 – 11 | +/ (2+i._9) * base
Cálculo do primeiro dígito verificador. Primeiro multiplicamos cada dígito por 10,9,8,..2. Como i.3 gera uma sequencia 0 1 2 e i._3 gera 2 1 0, geramos um vetor de 8 a 0 e somamos 2 para que corresponda ao vetor que desejamos que é de 10 até 2. Colocamos entre parenteses para que seja avaliada primeiro, caso contrário iremos multiplicar o vetor base por _9 já que a avaliação da expressão é da direita para a esquerda. Depois somamos o resultado obtido pela multiplicação, pegamos o resto do valor obtido dividido por 11 e, finalmente subtraímos o resultado de 11. Para uma melhor explicação, veja zzcpf.

Negative Sign _
Times *
Integers i.
Residue |
Insert / (+/)
Minus

d1=. d1 * d1 < 10
O dígito verificador deve ser menor que 10. Caso seja maior que 10 é assumido zero. Em vez de compara o valor com 10, resolvi utilizar o ‘menor que’. Se a comparação for verdadeira, retorna 1 e, se falsa, retorna 0. Basta multiplicar o valor pela comparação d1<10 para obtermos o mesmo valor ou zero.

Less Than <

d2=. 11 – 11 | +/ (2 + i._10) * base , d1
O cálculo do segundo dígito verificador é igual ao do primeiro com a diferença que o primeiro dígito entrará no cálculo e o vetor para multiplicar inicia em 11 e decresce até 2. Basta acrescentar o primeiro digito ao vetor base.

Append ,

d2=. d2 * d2 < 10
O mesmo procedimento utilizado no primeiro dígito verificador.

ok=. */ cpf = base , d1 , d2
Finalmente é feita a comparação entre o cpf informado mais a base acrescida dos dois dígitos verificadores. Como a comparação de vetores em J é efetuada em cada elemento retornando um vetor de 0’s e 1’s se eu multiplicar os elementos terei 1 apenas se todos os elementos forem iguais e retornarem 1. Se algum elemento for diferente, retorna 0 que irá anular a multiplicação.

Equal =

)
Encerra a definição do verbo.

Exemplo de utilização:

  zzcpf 53321223570
1
  zzcpf 87376595880
1
  zzcpf 11869471600
0
   zzcpf 1234
|assertion failure: zzcpf
|   11=#cpf

Bem, por enquanto era isso. É claro que ainda existe espaço para alterar os verbos (funções) para um comportamento semelhante as originais, isto é, gerar um CPF aleatório, gerar senhas com outros caracteres dependendo da informações passadas, etc.

=-=-=-=-=
Powered by Blogilo

Anúncios