Joshi - Bitácora de aprendizajes

El diario público de una persona que le gusta aprender

*Atento a sus indicaciones, señor Superior, presento el informe detallado del caso, incluyendo tanto fragmentos de conversaciones y comentarios personales para contextualizar los eventos. *

El 9 de agosto, a las 10:00 am, Raúl Hernández salió de su casa en Chignahuapan, sin despedirse de su madre. “Iba mas arreglado que de costumbre” comenta ella “Zapatos lustrados, camisa planchada, inluso un toque de loción. Pensé que tenía una cita. Una hora después me mandó un audio diciendo 'Voy a Tetela, llego en la tarde'… le pregunté por qué, pero… (traga saliva, conteniendo las lágrimas) ya no me contestó”

A las 8:00 pm, tras múltiples llamadas perdidas y mensajes sin respuesta, la señora Hernández avisó a la policía. Su preocupación natural era aún mayor: era “Luna Recia,” y desde hacía dos meses, en los días de luna llena, aparecían cadáveres descuartizados en la zona.

Sin embargo, a la policía las preocupaciones de la señora Hernández le parecieron infundadas. “No hay conexión,” le dijeron, en un vano intento de calmarla.

Fue entonces cuando la señora Hernández nos contrató. ¿Por qué iría a Tetela, a 40 km de su hogar? ¿Con quién pensaba reunirse? Pedí entrar a su habitación en busca de respuestas.

La habitación, ordenada en apariencia, tenía libros por doquier. La mayoría eran de historia. Cuando abrí su laptop —la contraseña fue fácil de romper—, lo interesante no fueron los archivos, sino las búsquedas recientes: “Tetela,” “Teteles,” “sacrificios humanos en Mesoamérica,” “Archivo General de las Indias.” ¿Qué estaba buscando realmente? “Tetele” viene del náhuatl y significa “Montículo.” Estos vestigios prehispánicos, de 600 a 1000 años de antigüedad según investigué en la propia computadora de Raúl, son estructuras piramidales usadas para adorar a dioses antiguos o como tumbas. Algunos son solo montones de tierra, otros en mejor estado siguen cubiertos de hierba. Tetela, lugar donde abundan los teteles. El Archivo General de las Indias documenta todos los territorios que tenía el imperio español en el siglo XVI.

En redes sociales no tenía muchos amigos y publicaba relativamente poco. Pero encontré un comentario que hizo a una publicación titulada “Hallan otro cuerpo en Tetela de Ocampo,” fechado el 10 de julio. Raúl escribía: “Los cadáveres aparecen en los Teteles, ¿Podría haber relación entre los crímenes y estos sitios? ¿Por qué no vigilar estos montículos? Tal vez el asesino tenga una fijación con ellos.” De este comentario surgía una conversación privada fechada el 28 de julio, con un perfil ya eliminado, identificado solo como “unknown.”

Unknown: “Raúl, concuerdo contigo. Vivo cerca de un montículo y tengo miedo. Mi esposo, que es policía, me ha mostrado fotos alarmantes.” Raúl: “Lo sé, pero no tengo más información para escribir sobre esto.” Unknown: “Puedo darte más datos, pero prefiero que vengas en persona.” Raúl: “No me parece prudente.” Unknown: “Lo entiendo, pero no quiero arriesgar la vida de mi esposo enviando todo por aquí.” Al final, Raúl aceptó la reunión. La dirección que encontré reavivó las esperanzas de la señora Hernández, quien decidió acompañarme, esperando encontrar algo. Para no aumentar el sufrimiento de la señora Hernández, omití en ese momento mencionar el audio de casi 15 minutos que Raúl se había enviado a sí mismo en su cliente de mensajería el día de su desaparición. Me pongo en la piel de Raúl y, junto a su madre, recreo lo más fielmente posible lo que pudo ser el recorrido hacia ese lugar. Salimos a las 10:00 am y tomamos el camión a las 11:00 am, para partir a la misma hora que él. Veo a Raúl rememorando en su celular los asesinatos anteriores: El 13 de junio, justo en luna llena, se encontró el cuerpo desmembrado de un repartidor de pan de 27 años en un montículo de un campo de maíz, causando alarma en la población. El viaje en camión es rápido. Desde Chignahuapan, se cruza una cordillera perteneciente a la Sierra Madre Oriental y el valle que le sigue para llegar a las faldas del cerro Tzotolo desde donde, dicen los lugareños, se ven al amanecer los destellos del Golfo de México, si no fuera porque en esta época del año está cubierto de neblina. Ahí, envuelto entre un tupido cúmulo de árboles de bosque templado, se encuentra la histórica Tetela de Ocampo.

El 10 de julio (luna llena de nuevo) apareció otro cadáver descuartizado, el de una estilista de 40 años. Su hija, desesperada, llamó a la policía después de que esta recibiera una llamada de su madre diciéndole “hija” entre llanto y colgando repentinamente. El cuerpo fue hallado en otro montículo al otro lado del pueblo.

Es irónico cómo este lugar, tan orgulloso de su historia, olvida partes de ella. Recuerdan con fervor a sus antepasados luchando contra los franceses, reclamando su lugar en la batalla del 5 de mayo, pero dejan en el olvido las ruinas prehispánicas, testigos mudos de asesinatos y desmembramientos.

Tomamos una combi hacia el lugar indicado, escoltados por una patrulla del ayuntamiento. Las casas se vuelven escasas y los campos de cultivo crecen. La milpa ya tiene la altura de un niño. Veo los Teteles repartidos en distintas parcelas. El destino indica uno de estos, particularmente bien conservado. Cerca de este hay una pequeña construcción de adobe. Bajo del auto y me pongo los audífonos.

—Hola… ¿tú eres…? —Sí, yo te contacté. —Este Tetele está muy bien conservado. —Me sorprende que sin ser de aquí, sepas lo que son. —Me… me gusta la historia. Siempre quise visitar lugares arqueológicos que salen en los libros, pero… no he tenido oportunidad. —Y buscaste más cerca. Ruinas olvidadas. —Sí. —¿Qué sentiste cuando viste un Tetele por primera vez? —Pues… cuando vi uno quedé mudo ante su presencia. No era un simple montón de piedras; en su forma áspera y desgastada hay algo… ¿inquietante? —Son los ecos de las ruinas. Silencio, el micrófono capta una ligera ráfaga de aire. Después la mujer vuelve a hablar. —Mira, el cuerpo de la estilista es Coyolxauhqui, la luna desmembrada. La hermana mayor de Huitzilopochtli que quería matarle al nacer. La voz de Raúl se quiebra, pareciera ahogarse. La voz femenina suspira. —¿No me crees? Observa. (Se escucha el sonido de un libro de pasta dura abrirse, de manos pasando sus hojas.) La misma posición de las manos, las piernas, y la cabeza. Silencio. —Sígueme, pasemos adentro. Mi esposo y mi padre no tardan en llegar, ellos podrán darte más detalles.

Se alcanzan a distinguir los sonidos de los pasos. 15 pasos. Los mismos que doy hasta la puerta.

Se escucha el rechinar de sillas de madera arrastradas por el suelo, pero aquí no hay ninguna silla ni mueble.

-Yo creo que el asesino es un fanático de los rituales antiguos- dice Raúl. – ¿Fanático? No, solo humano. Creer en un Dios o en Dioses o hacer rituales es completamente humano. ¿Humano? Creer es parte de nuestra naturaleza. Mi padre nos pagó la carrera de historia para no olvidar el pasado, porque estudiar historia es estudiar esa faceta de la humanidad que son sus creencias. En Yucatán, los mayas seguían luchando en el siglo XIX porque una cruz en llamas les hablaba. A tres horas de aquí, en Coacuila, la gente aún ofrece ofrendas a un cerro para evitar desgracias. Mi padre trabajó para una empresa en Ixtaczoquitlán, en Veracruz, en ella hay una pirámide oculta entre plantas y árboles para evitar que el INAH la reclame. Aun así, los trabajadores le dejan ofrendas como llaveros, aguardiente, fruta que entierran cerca de su base para protección. Mira, mi padre y esposo han llegado.

Se alcanzan a distinguir pasos y movimientos de sillas.

-¿Como estás?– dice una voz profunda y algo gutural. La temblorosa voz de Raúl responde -Bien, señor. – -¿Mi hija ya te presentó al niño? -¿Que? -¿Qué? ¿No venia a conocerlo M….? -Estaba por presentárselo. -Lo encontré en una melga hace muchos años. ¡Pesa muchísimo! Tuvimos que cargarlo entre mi hermano y yo para llevarlo a casa. Está hecho de piedra de Rio, no muy común en esta zona. Su mirada es profunda; las plumas de su escudo parecen tan reales que parecieran moverse con el viento… Se escucha un golpe. -¡Despertó! Está arriba, ¿Gustas ir a verlo? Miro hacia arriba. Tablas de madera. Hay un tapanco3 al que se accede por una escalera. -No creo que… -Tienes que verlo… Es magnifico. -No debería..

Silencio. Los golpes en el tapanco se perciben con mas fuerza. -DEBES VERLO Surge un violento ruido de las sillas, rechinando y cayendo. Después pasos apresurados y una respiración agitada. Luego nada. El audio ha terminado. El tapanco está vacío. Excepto por un detalle. Encuentro entre las uniones del piso de tablas un cuchillo de obsidiana que adjunto con este informe. Tras contarle a la señora Hernández sobre el audio, me pidió los fragmentos de la voz Raúl para escucharlos cuando lo extrañe. Le regalé mis audífonos por cortesía. “Mi hijo evitó más muertes”, dijo. Y es que desde su desaparición no ha habido más desmembramientos en luna recia.

Programita para valorar seguridad de contraseña | POO

Sigamos sufriendo con POO. La idea que se me ocurrió hacer esta vez es un programa que le pida al usuario su contraseña, y le responda que el nivel de seguridad de esta. Mis criterios de evaluación serán muy básicos.

Planeemos nuestro programa:

  1. Defino clase como HowSecurePass
  2. ¿Que variables de instancia crearé para el constructor? Se me ocurren las siguientes:
    • un array vacío para guardar la contraseña del usuario (cada elemento del array será un elemento de la contraseña)
    • @esLetra para almacenar el número de elementos de la contraseña que sean letras.
    • @esNumero para almacenar el número de elementos de la contraseña que sean números.
    • @esSimbolo para almacenar el número de elementos de la contraseña que sean símbolos
    • @calificacion Donde guardaré la ponderación de puntos que evalúan que tan segura es la contraseña
  3. Método para pedirle la contraseña al usuario, y guardarla en la variable userPass
  4. Método para evaluar la seguridad de la contraseña del usuario:
    1. Primero de pasar el string de la contraseña que metió al usuario al array
    2. Después, como primer rasgo, evaluaremos la longitud de la contraseña.
    3. inmediatamente procederemos a evaluar los elementos de la contraseña convertida en array:
      • Si el elemento es una letra, @esLetra aumenta 1
      • Si el elemento es un número, @esNumero aumenta 1
      • Si el elemento es un símbolo, @esSimbolo aumenta 1
  5. Imprimimos calificación y definimos un mensaje de acuerdo a la calificación obtenida:
    • Si el puntaje es 5, Tu contraseña es completamente segura
    • Si el puntaje está entre 2 y 4, Debes mejorar la seguridad de tu contraseña
    • Si es menor a 2, ¡Cambia esa contraseña!

Desarrollemos nuestro programa:

class HowSecurePass
	# Creando mi constructor con las siguientes variables
	def initialize
		@evaluatePass=[]
		@esLetra = 0
		@esNumero = 0
		@esSimbolo = 0
		@calificacion = 0
	end
	
	# Defino un método para recibir la contraseña del usuario
	def userPass
		print "Dame tu contraseña "
		gets.chomp
	end
	
	
	#Método para evaluar seguridad de la contraseña
	def evaluator(userPass)
		# Pasar el string de la contraseña al array @evaluatePass
		@evaluatePass = userPass.chars # El método chars se encarga de hacer el trabajito de la conversión ^^'
		puts @evaluatePass
		
		=begin
		 Para no hacerme bolas, la variable contarCaracteres guarda la contraseña
		 en string para poder contar el número de elementos, ahorita
		  que lo pienso, pude simplemente contar los elementos del array... Duuuuh!!
		=end
		contarCaracteres = userPass
		
		# Evaluamos la longitud de la contraseña
		case contarCaracteres.length
		when 9..Float::INFINITY
			puts "Longitud adecuada"
			@calificacion += 2
		when 5..7
			puts "Podrías hacerla mas larga"
			@calificacion += 1
		else
			puts "LONGITUD INADECUADA"
		end
		
		# Que cosa tan hermosa es el case, ni yo me lo creo, es muy simple de entender y trabajar.
		
		#Evaluamos los elementos que componen la contraseña
		# NOTA MENTAL: APRENDER REGEX
		# Para hacerlo usaremos each do, un ciclo iterativo para ir recorriendo cada elemento de nuestro array
		@evaluatePass.each do |elemento|
		if elemento.match?(/[a-zA-Z]/) # Verifica si el elemento es una letra 
			@esLetra += 1
		elsif elemento.match?(/\d/) # Verifica si el elemento es un dígito
			@esNumero += 1
		else # Si no es una letra ni un número, se considera un símbolo
			@esSimbolo += 1
		end
		
		end
		
		# Trabajamos con los puntajes y hacemos los comentarios correspondientes
		
		puts "Tu contraseña tiene letras" if @esLetra > 0; @calificacion += 1 if @esLetra > 0
		puts "Tu contraseña tiene numeros" if @esNumero > 0; @calificacion += 1 if @esNumero > 0
		puts "Tu contraseña tiene simbolos" if @esSimbolo > 0; @calificacion += 1 if @esSimbolo > 0

# ¡Pero que hermosa forma de hacer los IF's! Ruby permite  poner primero la expresión y luego el if, como si fuera una oración hablada "Escribe esto si pasa esto" eso es genial, el ";" permite hacer un salto de line invisible para escribir la siguiente linea de código en la linea actual. 



		# Damos calificación
		print "Tienes #{@calificacion} de calificación, por lo tanto creemos que "
		
		case @calificacion
		when 5 then puts "TU CONTRASEÑA ES COMPLETAMENTE SEGURA"
		when 2..4 then puts "DEBES MEJORAR LA SEGURIDAD DE TU CONTRASEÑA"
		else puts "CAMBIA ESA CONTRASEÑA YA!!"
		end
end


end

#Ya creamos nuestro molde, ahora creemos el objeto particular

nuevaContra= HowSecurePass.new
evaluar = nuevaContra.userPass
nuevaContra.evaluator(evaluar)

Me siento satisfecho, no sé aún que tan bien he aplicado la POO en este ejercicio pero siento que he progresado.

NOTA MENTAL: Procuraré entrenar mas arduamente para mejorar mis habilidades de programación ^^'

Sufriendo con POO

El paradigma de POO (Programación Orientada a Objetos) siempre ha sido un problema para mí, debido la instrucción desordenada que recibí y que yo he continuado en programación. En la escuela aprendí a moverme con soltura en PHP pero siempre desde el paradigma procedimental, declarando y guardando variables... pero el POO solo lo vi de manera abstracta (mejor dicho conceptual; exposiciones de clase) lo que siempre ha sido para mi un reto, porque en programación se aprende practicando.

En internet también encontrar material para ejercitarse como el que yo requería es difícil. Los ejemplos siempre son muy ¿Simples? ¿No aplicables? Soy un cabeza dura, lo reconozco, aprendo a base de equivocarme una y otra vez. Así que se me ocurrió que ya que estoy aprendiendo Ruby, resolver los problemas clásicos de programación pero siguiendo en la medida que pueda los lineamientos de POO.

¿Que haremos hoy?

Sistemita que devuelve cambio

Un usuario ingresa una cantidad en el prompt y el programa se encarga de devolverle esa cantidad en billetes y monedas de distintas denominaciones

Le tengo cariño a este ejercicio porque fue el primer ejercicio donde en verdad me entretuve mentalmente en la escuela y no en mi casa con libros de la biblioteca.

Planteomoslo en paradigma POO

NOTA No tengo formación académica que me respalde, todo lo que hago es lo que creo que es y luego a base de golpes y metidas de pata me voy corrigiendo, así que no duda de mi, lector anónimo.

En POO debemos pensar primero en crear un molde genérico del programa, del que después iremos creando objetos específicos.

*Ese molde se llama CLASE*

class DarEfectivo
	# Aquí todo el código del molde 

end

En Ruby, siempre que se crea un objeto nuevo, busca un método llamado initialize y lo ejecuta.

initialize vendría siendo lo que en otros lenguajes conocen como constructor citando a Wikipedia:

En Programación Orientada a Objetos (POO), un constructor es una subrutina cuya misión es inicializar un objeto de una clase. En el constructor se asignan los valores iniciales del nuevo objeto.

Entonces, hagamos nuestro constructor, en este caso las variables que inicializaré serán dos arrays donde estarán almacenados las denominaciones de billetes y monedas.

Repito, fue la forma en que yo resolví el ejercicio y la forma en la que, de momento, he entendido el concepto.

Quedaría de esta forma:

class DarEfectivo

	def initialize
		@billetes =[1000,500,200,100,50,20]
		@monedas = [10,5,2,1]
	end

end

¡Ya tenemos nuestro molde! Pero aun está incompleto. debemos darle métodos.

Yo lo entendí de esta forma:

Un objeto tiene atributos y métodos. los atributos son como sus características, los métodos, en cambio, son las acciones que el objeto puede realizar.

En este caso, ¿Que acciones debe realizar nuestra clase para poder ayudarle al usuario con su cambio?

  • recibir datos del usuario.
  • devolver esos datos en billetes y monedas de distinta denominacion.

Por tanto, esos serán los dos métodos que crearemos:

Método 1: recibir datos del usuario


class DarEfectivo

#constructor
	def initialize
		@billetes =[1000,500,200,100,50,20]
		@monedas = [10,5,2,1]
	end

	# recibir datos del usuario
	def cantidad
		print "Dame un cantidad: "
		gets.chomp.to_i
	end

end

Método 2: Devolver el resultado

Esta parte ya es mas familiar para mí ^^' y es que debemos resolver el ejercicio en sí. Le dí un par de vueltas (En la prepa lo resolvimos a bese de puro if y else anidado pues era el tema de la clase) y se me ocurrió usar each do que usamos con los números primos (NOTA MENTAL: convertir el programita de numeros primos a POO)

Lo que vamos a hacer es:

  1. Recorrer el array elemento por elemento (Comenzando con los de mayor denominación)
  2. Si la cantidad que ingresó el usuario es mayor o igual a la denominación del billete (elemento del array):
    1. obtener la cantidad de billetes de esa denominación que pueden acompletar la cantidad (una división entera)
    2. Si el resultado de esa división entera es mayor que uno, se imprimirá el texto “billetes de” (mas de un billete), de lo contrario se imprimirá el texto “billete de” (para ser mas agradable y natural al usuario)
  3. La variable cantidad se actualiza al resultado de la división modular entre el billete con el que se le aplicó la división entera. Es decir, obtener el sobrante, el cual se reutilizará con el siguiente elemento del array.
  4. Si la cantidad no es mayor o igual al elemento del array en el que se encuentre, se pasa al siguiente elemento.
  5. Cuando termine el array de @billetes, nos seguimos con el array de @monedas, que tendrá exactamente el mismo comportamiento que el anterior array.

Quizá en código se entienda mejor mi soliloquio ^^'

class DarEfectivo
# Constructor
def initialize
	@billetes =[1000,500,200,100,50,20]
	@monedas = [10,5,2,1]
end

# Recibir datos del usuario
def cantidad
	print "Dame un cantidad: "
	gets.chomp.to_i
end

# Devolver la cantidad en billetes y monedas de distinta denominación.
def cambio(cantidad)
	
	@billetes.each do |billete|
		if cantidad >= billete 
		print "#{cantidad.div(billete)} " 
		unless cantidad.div(billete) != 1 then puts "billete de #{billete}" else puts "billetes de #{billete}" end
		cantidad=cantidad % billete
		end
	end
	
	@monedas.each do |moneda|
		if cantidad >= moneda 
		print "#{cantidad.div(moneda)} " 
		unless cantidad.div(moneda) != 1 then puts "moneda de #{moneda}" else puts "monedas de #{moneda}" end
		
		end
	end
	
end



end

Podemos notar algo interesante a diferencia del anterior método, y es que en def cantidad no pasamos ningún parámetro, a diferencia de def cambio(cantidad). Esto de pasar parámetros significa que hay métodos que necesitan un parámetro externo para trabajar.

Ahora sí, hemos terminado nuestro molde. Hora de crear un objeto para que nuestro usuario interactué con él.

# Creamos un objeto llamado mi_efectivo, a partir de la clase DarEfectivo.new
mi_efectivo = DarEfectivo.new

# La variable cantidad_ingresada guardará el valor que el usuario escriba en el método cantidad, que mandamos a llamar desde nuestro objeto creado.
cantidad_ingresada = mi_efectivo.cantidad


# ejecutamos el método cambio pasándole el valor de la variable cantidad_ingresada
mi_efectivo.cambio(cantidad_ingresada)	

y ¡voila! nuestro programa funciona.

Programita para identificar números primos.

Se me está haciendo tedioso aprender por temas, empezaré a probar por retos. Es decir, hoy quiero crear un programita que me siga si un número es primo o no. Es obvio que usaré condicionales, A partir de ahí, no sé. Veamos como lo soluciono.


Condicional 1

Crear programa donde de acuerdo al número que nos escriba el usuario, el programa nos diga is este número es menor, igual o mayor a 10

print "Ingresa un número: "
num = gets.chomp.to_i  #Ruby lee el número, le quitamos los caracteres ocultos y lo convertimos a entero.

if num < 10 # Si num es menor que diez..
	puts "El numero es menor a 10" # imprimes esto
elsif num == 10 # De lo contrario, si num es identico a 10
	puts "El número es igual a 10" # imprimes esto
else # De lo contrario
	puts "el número es mayor a 10" # Haces esto
end

Muy simple ¿No?

Intentemos hacer los siguiente:

EJERCICIO Identificando números primos con lo aprendido.

Recuerdo la criba de Eratostónes como una forma de identificar números primos. Lo que quiero hacer es un programa donde yo inserte un número y me diga si es primo o no, para deducirlo iré dividiendo el número entre los primeros 10 números primos, si no es divisible entre ninguno de ellos, daremos por hecho que es primo (Solo para practicar)

Intento de Solución 1
# EJERCICIO-3-Condicionales-2.rb
# IDENTIFICANDO NÚMEROS PRIMOS

print "Dame un número: "
num = gets.chomp.to_i

#Haremos uso de la divisińn modular.

if num.modulo(2) != 0 && num.modulo(3) != 0 && num.modulo(5) != 0 && num.modulo(7) != 0 && num.modulo(11) != 0 && num.modulo(13) != 0 && num.modulo(17) != 0 && num.modulo(19) != 0 && num.modulo(23) != 0 && num.modulo(29) != 0 && num.modulo(31) != 0
puts "El número #{num} es primo." 
else
puts "El número #{num} NO es primo." 
# Hasta aqui todo bien, sin embargo, en caso de que no sea primo, quiero que me diga entre que números es divisible.

unless num.modulo(2) != 0 then puts "Porque es divisible entre 2" end
unless num.modulo(3) != 0 then puts "Porque es divisible entre 3" end
unless num.modulo(5) != 0 then puts "Porque es divisible entre 5" end
unless num.modulo(7) != 0 then puts "Porque es divisible entre 7" end
unless num.modulo(11) != 0 then puts "Porque es divisible entre 11" end
unless num.modulo(13) != 0 then puts "Porque es divisible entre 13" end
unless num.modulo(17) != 0 then puts "Porque es divisible entre 17" end
unless num.modulo(19) != 0 then puts "Porque es divisible entre 19" end
unless num.modulo(23) != 0 then puts "Porque es divisible entre 23" end
unless num.modulo(29) != 0 then puts "Porque es divisible entre 29" end
unless num.modulo(31) != 0 then puts "Porque es divisible entre 31" end



end

Funciona genial!!!! Pero no me gustan las ultimas lineas es repetitivo y aburrido, siento que debe haber otra forma “Mas elegante de resolverlo”. Se me ocurre hacerlo con arrays.

*Un arreglo o array es una lista ordenada de elementos de cualquier tipo.*

Se me ocurre guardar todos los elementos a dividir en un arreglo y después que solo se opere con todos sus elementos internos.

el arreglo tendría la siguiente forma:

divisores = [2,3,5,7,11,13,17,19,23,29,31]

Intento de Solución 2

# IDENTIFICANDO NÚMEROS PRIMOS

print "Dame un número: "
num = gets.chomp.to_i

#Haremos uso de la divisińn modular.

if num.modulo(2) != 0 && num.modulo(3) != 0 && num.modulo(5) != 0 && num.modulo(7) != 0 && num.modulo(11) != 0 && num.modulo(13) != 0 && num.modulo(17) != 0 && num.modulo(19) != 0 && num.modulo(23) != 0 && num.modulo(29) != 0 && num.modulo(31) != 0
puts "El número #{num} es primo." 
else
puts "El número #{num} NO es primo." 
# Hasta aqui todo bien, sin embargo, en caso de que no sea primo, quiero que me diga entre que números es divisible.

# Haré un array para hacer el recorrido de divisiones
divisores = [2,3,5,7,11,13,17,19,23,29,31]

divisores.each do |divisor|
	if num.modulo(divisor) == 0 then puts "Porque es divisible entre #{divisor}" end
end

Ahora funciona con menos líneas de código ^^'... ¡ Y hemos hecho nuestra primeras iteraciones!

El método each acepta un bloque de código y lo ejecuta por cada elemento de la lista que se ira mandando a llamar con la variable definida entre los || (algunos les dicen pipes, no sé como se llaman realmente estos símbolos)

es decir: Por cada elemento en la lista, divisor va tomando su valor y se ejecuta la expresión > if num.modulo(divisor) == 0 then puts “Porque es divisible entre #{divisor}” end

Me ha entrado la curiosidad ¿Podría usar el array, y el método each para hacer mas elegante el if?

Intento de Solución 3

Conseguí esto:

# IDENTIFICANDO NÚMEROS PRIMOS

print "Dame un número: "
num = gets.chomp.to_i

#Haremos uso de la divisińn modular.

# Haré un array para hacer el recorrido de divisiones
divisores = [2,3,5,7,11,13,17,19,23,29,31]
variableContador = 0
divisores.each do |divisor|
	if num.modulo(divisor) == 0 then puts "Es divisible entre #{divisor}" else variableContador += 1 end
end

if variableContador != divisores.count then puts "Por lo tanto el número #{num} NO es primo" else puts "El número #{num} es primo" end

Estoy seguro que debe haber soluciones mas elegantes, pero como un tipo al que la programación siempre le ha dado quebraderos de cabeza, me siento muy a gusto con el resultado ^^'

Convirtiendo cadenas de texto a números

Todo bien hasta ahora, sin embargo lo único que estamos haciendo es imprimir los valores que recibimos. Aún no operamos con ellos.

Supongamos que queremos crear un programa dónde nosotros le demos el precio neto de un producto, y el programa nos devuelva el precio con IVA (Impuesto de Valor Agregado), sabiendo que el IVA equivale al 16%... ¿Cómo podríamos hacerlo?

EJERCICIO-2-CalculadoradeIVA-v1-rb

print "CALCULADORA DE IVA\n"
IVA = 0.16

print "Dame un precio: "
precio = gets.to_f
# El método to_f es el que se encarga de transformar el string en un número flotante.

#imprimimos el precio neto
puts "PRECIO: $#{precio}"

#calculamos el impuesto
puts "IVA: $#{precio*IVA}"

#calculamos el precio final o precio al público
puts "PRECIO AL PÚBLICO: $#{precio + (precio*IVA)}"

Como podemos ver, gets por defecto lo que recibe del usuario los usa como una cadena, pero si mandamos a llamar to_f (to float. convertir a flotante) hace la conversión correspondiente, obvio, si es un número, si fuera un texto, por ejemplo “oso”, el valor generado de la conversión sería 0.

Dentro de puts o print podemos usar algo así como caracteres no imprimibles, por ejemplo:

  • “\n” que significa Salto de línea
  • “\t” que significa Tabulador

Juguemos con Ruby

Me auto-inventé el siguiente ejercicio:

Le pediremos al usuario algunos datos y con el armaremos un texto, los datos a solicitar son su nombre y su edad para registrarse en sistema “x”

Solución 1

print "REGISTRO DE USUARIOS \n Para poder continuar necesitaremos algunos datos suyos \n"
print "\t ¿Cuál es tu nombre?  "
nombre=gets()
print "\t ¿Cuantos años tienes?  "
edad=gets()
print "\t CARGANDO DATOS... \n "

print "Bienvenido #{nombre} al parecer tienes #{edad} años de edad. \n Ahora estás dado de alta en nuestro sistema \n BIENVENIDO"

Sin embargo, no me sentí a gusto con la salida.

REGISTRO DE USUARIOS 
 Para poder continuar necesitaremos alguno datos suyos 
	 ¿Cuál es tu nombre?  jorge
	 ¿Cuantos años tienes?  24
	 CARGANDO DATOS... 
 Bienvenido jorge  <<<<<<<<<<
 al parecer tienes 24  <<<<<<<<
 años de edad. 
 Ahora estás dado de alta en nuestro sistema 
 BIENVENIDO%    

¡Da un salto de línea, justo después de embeber la variable! ¿Por qué hace tal cosa?

Investigando al respecto aprendí lo siguiente:

  • gets() guarda los datos como string (cadena de texto) y, intentando ser bueno con nosotros Le agrega un \n al final por defecto (Recordemos que \n y \t son caracteres no imprimibles)

  • Esto lo podemos visualizar con p p es un método que nos permite visualizar justamente esos caracteres no imprimibles que puede haber en ciertos lugares

en el ejemplo anterior si agrego lo siguiente:

print "\t ¿Cuál es tu nombre?  "
nombre=gets()
p nombre

y al ejecutarlo escribiera “jorge” nos devolvería:

"jorge/n"

que es lo que en verdad se guardó en la variable nombre.

  • Para guiar los caracteres no imprimibles y hacer que el código se vea como yo quiera, usaremos gets.chomp que se encarga de quitar los caracteres no imprimibles a gets.

El código nos quedará entonces de la siguiente forma:

print "REGISTRO DE USUARIOS \n Para poder continuar necesitaremos alguno datos suyos \n"
print "\t ¿Cuál es tu nombre?  "
nombre=gets.chomp
p nombre
print "\t ¿Cuantos años tienes?  "
edad=gets.chomp
p edad
print "\t CARGANDO DATOS... \n "

print "Bienvenido #{nombre} al parecer tienes #{edad} años de edad. \n Ahora estás dado de alta en nuestro sistema \n BIENVENIDO"

y nuestra salida será la siguiente:

REGISTRO DE USUARIOS 
 Para poder continuar necesitaremos alguno datos suyos 
	 ¿Cuál es tu nombre?  jorge
"jorge"
	 ¿Cuantos años tienes?  12
"12"
	 CARGANDO DATOS... 
 Bienvenido jorge al parecer tienes 12 años de edad. 
 Ahora estás dado de alta en nuestro sistema 
 BIENVENIDO    

Dejé p en el código después de usar gets.chomp para ver como en esta ocasión nuestras variables aparecen sin caracteres no imprimibles.

Lo escribí hace unos meses después de una decepción amorosa. Es también una especie homenaje a Idea Vilariño, por la forma de los versos (cortos y contundentes). La poesía no es mi fuerte, pero eso no me quita las ganas de practicarla.

No será

No será,

No seremos,

la noche marca

una frontera infinita

entre nosotros hoy,

entre nosotros mañana

y siempre.

No será,

No seremos,

y el canto de la golondrina

se apaga.

Tu no estás

Yo no estoy,

Jamas estaremos...

Mi primera historia publicada. La cortedad tiene una excusa; el reto del certamen en el que participé era crear un cuento con exactamente 300 palabras. Felicitado por unos y detestado por más, fue mi primer acercamiento al mundo de la escritura. Este es el resultado. ___________

“Dime que eres tú...” me dice Bertha con sus ojos de mujer ilusionada. Respondo afirmativamente moviendo mi adolorida cabeza con dificultad. Ella sonríe satisfecha. Hemos desaparecido a Víctor sin dejar evidencias. Me pregunto cuántos amantes han logrado el mismo cometido a través de la historia, pero no recuerdo ninguno. Tal vez porque el crimen perfecto jamás se divulga.

La conocí en una feria de tecnología a la que Víctor asistía por motivos de trabajo. Los dos andaban por caminos distintos y Bertha se topó conmigo. “Conectamos”, y me llevó a su casa antes de que el llegara. “Jamás había hecho esto” me decía excitada, mientras la besaba con delicadeza... Curiosamente, le sorprendió más que le preparara un café y se lo llevara a la cama. “¿Dónde estabas hace quince años?” murmuró y me tomó de la mano para llevarme al armario. “No escapes” dijo. Y yo no escapé... Así, cuando su marido no estaba y ella tenía tiempo, escapaba del trabajo y disfrutaba de mí.

Cuando nadie estaba, yo exploraba las habitaciones, ordenaba sus pertenencias, y me conectaba a Internet para leer y aprender lo que quisiera... la tranquilidad me lo permitía. También descubrí que Víctor quería a Bertha, pero se había cansado de conquistarla. Siempre le regalaba algún detalle o le dejaba notas en cualquier lugar, diciéndole lo mucho que la amaba y que tuviera un buen día. Pero ella no devolvía el cariño que él le daba. Ella solo quería a alguien a su disposición, como yo. Por eso no me sorprendí cuando me dijo que lo matáramos. Yo le propuse algo completamente distinto, a lo que ella respondió de mala gana que mientras nos deshiciéramos de él, accedería.

Hoy, en la cena, Bertha colocó un sedante en la copa de Víctor. Puedo imaginar lo sucedido porque la conozco a la perfección. Nerviosa por su inexperiencia, tiembla a la hora quitar el cuero cabelludo con ayuda de tijeras y bisturí. Hace gestos a la hora de taladrar el cráneo, mientras algunas gotas de sangre manchan el piso y salpican su rostro y el libro de anatomía que compró para guiarse. Se asquea a la hora de enterrar mi circuito de conciencia en el carnoso cerebro de su esposo….

Ahora suspiramos los dos mientras destrozamos aquella piel de neopreno, esos órganos de polímero, los sensores emotivos y circuitos integrados. Ahora yo soy Víctor y siempre estaré a su servicio. ___________

Comencemos con el pie derecho aprendiendo Ruby, es decir, creando nuestro clásico Hola Mundo

1-HolaMundo.rb

puts 'Hello World'

Esto simplemente nos imprimirá en la consola cuando lo ejecutemos:

>>> ~ ruby HolaMundo.rb
Hello World

Podemos notar que puts nos funciona como un “muestra en pantalla lo siguiente”


Hagamos un programita mas complejo:

2-HelloName.rb

print('Escribe tu nombre: ')
name=gets()
puts("Hola #{name}")

En este caso el programita se encarga de pedirle al usuario su nombre con el método gets() el cual para poderlo usar lo guardamos en la variable name desúues lo imprimimos en pantalla con puts

En consola se vería mas o menos así:

>>> ~ ruby 2-HElloName.rb
Escribe tu nombre: Joshi
Hola Joshi

¿Cuál es la diferencia entre print y puts?

puts hace un salto de línea automático, mientras que print no.

PUTS

ejemplo-ImprimiendoConPuts.rb

puts "Hello World"
puts "How are you?"

Nos devuelve lo siguiente:

>>> ~ ruby ejemplo-ImprimiendoConPuts.rb
Hello World
How are you?

PRINT

ejemplo-ImprimiendoConPrint.rb

print "Hello World"
print "How are you?"

Nos devuelve lo siguiente:

>>> ~ ruby ejemplo-ImprimiendoConPrint.rb
Hello WorldHow are you?

¿Cuál es la gramática correcta?

Me sacó un poco de quicio ver que en el primer ejemplo se usa puts con comillas simples, mientras que mas abajo se uso con comillas dobles, y en otro caso tanto print como puts usaron paréntesis y dentro de ellos comillas dobles. ¿Cual es la forma correcta de escribir?

Investigando un poco descubrí que Ruby es un lenguaje muy permisivo pero tiene sus reglas, no tengo la verdad absoluta, recuerda que estoy aprendiendo pero por ahora podemos inferir lo siguiente:

  • Comillas simples y comillas dobles se pueden usar por igual, siempre y cuando no introduzcamos variables. Si usamos variables, las comillas simples nos imprimirán el texto tal cual sin distinguir la variable insertada, en ese caso lo correcto es usar comillas dobles. Es decir: Usar comillas dobles permite embeber o concatenar variables y quizá algunas otras cosillas interesantes. Las comillas simples, imprimen tal cual lo que hay dentro de ellas.
  • En el caso de los paréntesis no encontré mucho, quizá a futuro encuentre algo más

gets()

Es el método con el cual nosotros hacemos que Ruby reciba datos del usuario


#{name}

Es la forma de embeber o concatenar variables en Ruby, recordemos que para que funcione con puts debe estar dentro de comillas dobles.