Algoritmo - Basico

Buen dia a todos, estoy haciendo un Algoritmo para el calculo de unos
caracteres de control, se que es algo basico, pero si alguien tiene
alguna sugerencia, se lo agradeceria:

1.- Los Caracteres del nombre de una persona los convierto a su valor
ASCII y en funcion de cada caracter, hago ciertas operaciones:

datos = “JUAN PEREZ”
datos_ascii = “”
datos.each_byte do |c|
case c
when 65…73 then x = c - 54
when 74…82 then x = c - 53
when 209 then x = 10
when 83…90 then x = c - 48
end
datos_ascii << x.to_s
end

Con este metodo guardo en mi variable “datos_ascii” el nombre de la
persona ya convertido a ascii.

Ahora lo que necesito es mutiplicar y acumular los valores del nombre,
ejemplo:

datos_ascii = 123456789

total = 121 + 233 + 244 + 255 +… + 89*9

Si alguien tiene alguna sugerencia, se los agradeceria

NOTA: la longitud del resultado convertido varia en funcion de la
longitud del nombre de la persona.

2008/7/13 Luis M. [email protected]:

datos_ascii = 123456789

total = 121 + 233 + 244 + 255 +… + 89*9

Seguro que es por falta de cafeina, pero no veo la relacion entre
ambas cosas. Puedes partir de un datos_ascii que tenga un numero sin
regularidad en las cifras como 523700041 y explicar como se calcula el
total a partir de el?

A mi también me debe faltar cafeína. :slight_smile:
Pon un ejemplo real por favor

El día 13 de julio de 2008 11:42, Xavier N. [email protected]
escribió:

Hola, disculpen la vaga descripcion, ya estaba algo cansado cuando
escribi este Post. Explico un poco…

En Mexico existe algo que se llama RFC (Registro Federal de
Contribuyentes) y se le asigna a cada persona en funcion de su nombre y
su fecha de nacimiento, consta de 4 Letras del Nombre + 6 Digitos de la
fecha de nacimiento + 3 Caracteres de Control… estos ultimos
caracteres se generan en base a un algoritmo en funcion del nombre de la
persona… y lo primero que se hace es convertir los caracteres del
Nombre en su valor Ascii y dependiendo de la letra que sea, se le resta
cierto valor y se va guardando como una cadena de caracteres, ejemplo:

Si la persona se llama JUAN, seria:
J = 74 -53 = 21
U = 85 -48 = 37
A = 65 -54 = 11
N = 78 -53 = 25

JUAN = 21371125

Hasta aqui todo va bien… En lo siguiente es donde me atore…necesito
multiplicar los valores del resultado en pares y acumularlos, del
siguiente modo

Como JUAN = 21371125, entonces
RESULTADO = 211 + 133 + 377 + 711 + 111 + 122 + 25*5

del RESULTADO tomo los 3 primeros caracteres y seria la clave final

Espero haberlo explicado un poco mejor… Saludos, y gracias por sus
comentarios

2008/7/13 Luis M. [email protected]:

case c

longitud del nombre de la persona.

Posted via http://www.ruby-forum.com/.


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es

Por lo que entiendo de tu (pobre) descripción el algoritmo convierte
las letras mayúsculas en números de 2 cifras:

A → 11, B → 12, … I → 19, J → 21, K → 22, …, R → 29, S →
35, T → 36, … Z → 42

A parte de los saltos esos extraños para evitar el 20, y del 30 al 34,
también pareces convertir el 209 (que voy a interpretar que es la Ñ
mayúscula en ISO-8859-1) en 10.

Después parece que cada uno de los números en los que se transforman
las letras los multiplicas por su posición en la cadena, aunque con el
ejemplo que has podría tambien ser que cada dígito de la cadena
resultante lo multiplicas por un número que, sinceramente, no creo que
nadie sepa de donde viene. Voy a suponer que la valida es la primera
versión.

Yo lo haría así:

require ‘enumerator’
def nombre2numero(nombre)

Creamos un enumerador para #each_byte

enum = nombre.enum_for(:each_byte)

Convertimos la cadena en un array de valores

valores = enum.map { |c|
case c

Esta síntaxis de Ruby hace a tu programa más entendible

when ?A…?I then c - 54
when ?J…?R then c - 53
when ?S…?Z then c - 48
when 209 then 10 # Ñ mayúscula (incluye el comentario, el que venga
detrás lo agradecerá)
end
end

Creamos otro enumerado para #each_with_index

enum = valores.enum_for(:each_with_index)

Utilizamos inject para sumar todos los valores (item.first) y

multiplicar por

la posición (item.last)

enum.inject(0) { |acc, item| acc + item.first*(item.last + 1) }
end

Creo que eso te daría el valor que quieres, pero como dicen los
compañeros, una pregunta más clara hubiese ayudado un montón a que la
gente estuviera más dispuesta a responderte.

Suerte.

2008/7/14 Luis M. [email protected]:

cierto valor y se va guardando como una cadena de caracteres, ejemplo:
multiplicar los valores del resultado en pares y acumularlos, del
siguiente modo

Como JUAN = 21371125, entonces
RESULTADO = 211 + 133 + 377 + 711 + 111 + 122 + 25*5

del RESULTADO tomo los 3 primeros caracteres y seria la clave final

Espero haberlo explicado un poco mejor… Saludos, y gracias por sus
comentarios

Entonces mi solución sería esta otra:

require ‘enumerator’

def nombre2numero(nombre)

Creamos un enumerador para #each_byte

enum = nombre.enum_for(:each_byte)

Convertimos la cadena en un array de valores

valores = enum.inject([]) do |acc, c|
v = case c
# Esta síntaxis de Ruby hace a tu programa más entendible
when ?A…?I then c - 54
when ?J…?R then c - 53
when ?S…?Z then c - 48
when 209 then 10 # Ñ mayúscula (incluye el comentario, el que
venga
# detrás lo agradecerá)
end
# Guardamos los digitos por separado en el array.
acc + v.divmod(10)
end

#each_cons nos devuelve de 2 en 2 elementos del array, avanzando de

uno

en uno

enum = valores.enum_for(:each_cons, 2)

Utilizamos inject para sumar todos los valores

n = enum.inject(0) { |acc, v| acc + (v.first*10 + v.last) * v.last }

No veo forma más elegante de conseguir el paso final que esta

n.to_s[0…2].to_i
end

Suerte.

On Jul 14, 2008, at 10:04 AM, Daniel R. Troitiño wrote:

Entonces mi solución sería esta otra:

Bonita solución. La he metido en un pastie y he puesto un test para
confirmar que funciona.

http://pastie.textmate.org/private/bmusau0jkqpqkyctfafeqq

2008/7/14 Luis M. [email protected]:

Como JUAN = 21371125, entonces
RESULTADO = 211 + 133 + 377 + 711 + 111 + 122 + 25*5

del RESULTADO tomo los 3 primeros caracteres y seria la clave final

Hay varias maneras de hacer esa cuenta, esta es una:

juan = ‘21371125’
juan_digits = juan.split(//).map(&:to_i)

total = 0
juan_digits.each_cons(2) do |a, b|
total += (a*10 + b)*b
end