|
Translate
jueves, 21 de mayo de 2020
Libros Gratuitos de Java Code Geek
miércoles, 20 de mayo de 2020
martes, 19 de mayo de 2020
Design patterns
Quiero recomendar una pagina de patrones de diseño que esta buenisima, trae una descripción de casi todos los patrones con ejemplos y código. El codigo esta en deferentes lenguajes.
Dejo link : https://refactoring.guru/design-patterns
lunes, 18 de mayo de 2020
Juego de Serie en C# con .net core
Cuando quiero aprender un nuevo lenguaje desarrollo un juego de series, es decir aparece una serie con un valor faltante y el jugador debe completarlo.
Uno de los requerimientos no funcionales es que se pueda agregar una serie nueva fácilmente, para cumplirlo vamos a utilizar las ventajas de herencia y polimorfismo.
Vamos a desarrollar este juego en C# para ello creamos el proyecto con :
Vamos a desarrollar este juego en C# para ello creamos el proyecto con :
$ dotnet new console -lang C#
Empecemos desarrollo de la serie, la serie tiene como responsabilidad generarse y si lo hacemos de esta manera podemos utilizar la potencia del polimorfismo, para que no quede acoplado la generación de la serie con el desarrollo del juego:
Luego de esto abrimos nuestro editor favorito, podemos utilizar visual code.
using System;
namespace dotNetSecuencia.model
{
public abstract class Secuencia
{
protected int[] nros = new int[4];
public Secuencia() {
this.generar();
}
public int[] Nro {
get {
return nros;
}
}
public abstract void generar();
}
}
Ahora vamos a ver las implementaciones de secuencia:
using System;
namespace dotNetSecuencia.model
{
public class SecuenciaPar : Secuencia
{
public override void generar() {
int semilla = new Random ().Next (99) * 2;
for (int i = 0; i<4; i++) {
this.nros[i] = (semilla + i * 2);
}
}
}
}
Y ahora la secuencia Impar:
using System;
namespace dotNetSecuencia.model
{
public class SecuenciaImpar : Secuencia
{
public override void generar() {
int semilla = new Random ().Next (99) * 2;
for (int i = 0; i<4; i++) {
this.nros[i] = (semilla + i * 2) + 1;
}
}
}
}
Y ahora la secuencia Fibonacci :
using System;
namespace dotNetSecuencia.model
{
public class SecuenciaFibonacci : Secuencia
{
public override void generar() {
int until = new Random ().Next (15);
this.nros[0] = 0;
this.nros[1] = 1;
this.nros[2] = 1;
this.nros[3] = 2;
for (int i = 0; i<until; i++) {
this.nros[0] = this.nros[1];
this.nros[1] = this.nros[2];
this.nros[2] = this.nros[3];
this.nros[3] = this.nros[1] + this.nros[2];
}
}
}
}
Ahora vamos a ver el juego, este tiene la responsabilidad de verificar si el usuario acertó y tambien debe llevar los puntos:
using System;
namespace dotNetSecuencia.model
{
public class Juego
{
private int puntaje = 0;
private Secuencia secuencia = null;
public Juego()
{
this.generarSecuencia();
}
public int Nro1 {
get {
return this.secuencia.Nro[0];
}
}
public int Nro2 {
get {
return this.secuencia.Nro[1];
}
}
public int Nro4 {
get {
return this.secuencia.Nro[3];
}
}
public int Puntaje {
get {
return this.puntaje;
}
}
public void generarSecuencia()
{
int semilla = new Random ().Next (3);
switch (semilla)
{
case 0 :
this.secuencia = new SecuenciaPar();
break;
case 1 :
this.secuencia = new SecuenciaImpar();
break;
default:
this.secuencia = new SecuenciaFibonacci();
break;
}
}
public bool isOk(int valor) {
bool result = false;
if (this.secuencia.Nro[2] == valor) {
this.puntaje++;
result = true;
} else {
this.puntaje--;
}
this.generarSecuencia();
return result;
}
}
}
Ahora programemos la interfaz por consola por supuesto :
using System;
using dotNetSecuencia.model;
namespace dotNetSecuencia
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Bienvenido !!");
Juego juego = new Juego();
String respuestaStr;
do {
Console.WriteLine("La secuencia es : ");
Console.WriteLine(" " + juego.Nro1 + " " + juego.Nro2 + " __ " + juego.Nro4 );
respuestaStr = Console.ReadLine();
int respuesta = Convert.ToInt32(respuestaStr);
if (juego.isOk(respuesta)) {
Console.WriteLine("Ganaste!! Tu puntaje es " + juego.Puntaje);
} else {
Console.WriteLine("Perdiste!! Tu puntaje es " + juego.Puntaje);
}
Console.WriteLine("Quieres seguir Jugando [n/s] ? ");
respuestaStr = Console.ReadLine();
} while (respuestaStr != "n");
}
}
}
Y eso es todo!!! a jugar se a dicho!!
Dejo el repositorio git:
sábado, 16 de mayo de 2020
Coconut, programación funcional simple, elegante en python
¿Por qué usar Coconut? Coconut está hecho para ser útil. Coconut mejora el repertorio de los programadores de Python para incluir las herramientas de la programación funcional moderna, de tal manera que esas herramientas sean fáciles de usar e inmensamente poderosas; es decir, Coconut hace a la programación funcional lo que Python hizo a la programación imperativa. Y el código Coconut se ejecuta igual en cualquier versión de Python.
Instalar Coconut es tan fácil como
instalando Python,
abriendo una línea de comandos,
y escribir:
pip install coconut
Veamos un poco de código:
Un "hola mundo" :
"hello, world!" |> print
lambdas:
x -> x ** 2
pattern-matching:
match [head] + tail in [0, 1, 2, 3]:
print(head, tail)
composición de funciones:
(f..g..h)(x, y, z)
Data types:
data Empty()
data Leaf(n)
data Node(l, r)
def size(Empty()) = 0
addpattern def size(Leaf(n)) = 1
addpattern def size(Node(l, r)) = size(l) + size(r)
Sin, más dejo link:
http://coconut-lang.org/Funciones recursivas en listas parte 2
Seguimos con Funciones recursivas en listas
Si deseamos realizar una operación en cada elemento de una lista map es la función indicada. map aplica una función a cada elemento de una lista
map f [x0,x1,x2] -- > [f x0, f x1, f x2]
map es una de las herramientas más utilizadas en programación funcional. Un estilo común es definir un conjunto de cálculos simples usando el map y componerlos.
map f (map g xs) = map (f . g) xs
Map se puede definir de esta manera:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
Una iteración sobre una lista para producir un valor se llama pliegue y existen varias variaciones: plegado desde la izquierda, plegado desde la derecha y varias variaciones que tienen que ver con la "inicialización" y algunas variaciones más avanzadas.
Los pliegues pueden parecer difíciles al principio, pero son extremadamente poderosos y se usan mucho. Y en realidad no son muy complicados.
foldl se pliega desde la izquierda y ed como una iteración en una lista, de izquierda a derecha.
Una aplicación típica es por ejemplo, foldl f z xs
Donde z es un valor inicial
El argumento xs :: [a] es una lista de valores que combinamos sistemáticamente utilizando la función proporcionada f
Una intuición útil: piense en el argumento z :: b como un "acumulador".
La función f toma el valor actual del acumulador y un elemento de lista, y da el nuevo valor del acumulador.
foldl :: (b-> a-> b) -> b -> [a] -> b
Similar a foldl, pero funciona de derecha a izquierda
foldr :: (a -> b -> b) -> b -> [a] -> b
Hemos visto que una lista [x0, x1, x2] también se puede escribir como
x0: x1: x2: []
cons (:) sobre una lista usando la lista vacía [] como el acumulador da:
foldr (:) [] [x0, x1, x2]
->
x0: x1: x2: []
¡Esto es idéntico a construir la lista usando (:) y []! Podemos formalizar esta relación de la siguiente manera:
foldr cons [] xs = xs
Veamos algunos ejemplos:
suma xs = foldr (+) 0 xs
producto xs = foldr (*) 1 xs
De hecho, podemos "factorizar" las x que aparecen a la derecha de cada lado de la ecuación, y escribir:
sum = foldr (+) 0
producto = foldr (*) 1
(Esto a veces se denomina estilo "point free" porque está programando únicamente con las funciones; los datos no se mencionan directamente).
viernes, 15 de mayo de 2020
Funciones recursivas en listas
- Escribir funciones utilizando definiciones recursivas que atraviesan la estructura de la lista.
- Utilizar funciones estandar.
Se prefiere el segundo enfoque, pero las funciones estándar de procesamiento de listas deben definirse, y esas definiciones usan el primer enfoque (definiciones recursivas).
Se crea una lista a partir de la lista vacía [] y la función cons :: a → [a] → [a] la cual se puede escribir con ":"
Una lista se puede definir como :
- [] o
- (x: xs) para algunas x (el encabezado de la lista) y xs (la cola) donde (x: xs)
La lista esta definida de forma recursiva, el caso base de la recursión es [], el caso de recursión (o inducción) es (x: xs).
La longitud de una lista se puede calcular de forma recursiva de la siguiente manera:
length :: [a] -> Int -- function type
length [] = 0 -- base case
length (x:xs) = 1 + length xs -- recursion case
filter recibe un predicado (una función que da un resultado booleano) y una lista, y devuelve una lista de los elementos que satisfacen el predicado.
filter :: (a->Bool) -> [a] -> [a]
filter (<5) [3,9,2,12,6,4] -- > [3,2,4]
La podemos definir así:
filter :: (a -> Bool) -> [a] -> [a]
filter pred [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs
Muchos cálculos que serían calculados con bucles for / while en un lenguaje imperativo se expresan naturalmente como cálculos de lista en un lenguaje funcional.
En Haskell tenemos:
- Map : Realizar un cálculo en cada elemento de una lista
- Foldl: Iterar sobre una lista, de izquierda a derecha
- Foldr: Iterar sobre una lista, de derecha a izquierda
Es una buena práctica usar estas tres funciones cuando corresponda
Podemos expresar un gran cálculo "encadenando" una secuencia de funciones que realizan cálculos más pequeños. Por ejemplo tenemos un argumento de tipo a, aplicamos una función g :: a−> b, obteniendo un resultado intermedio de tipo b luego aplicamos una función f :: b−> c al resultado intermedio, obteniendo el resultado final de tipo c. El cómputo completo (primero g, luego f) se escribe como f∘g. Esta es la notación matemática tradicional; solo recuerda que en f∘g, las funciones se usan en orden de derecha a izquierda.
Haskell utiliza el . como operador de composición de funciones
(.) :: (b->c) -> (a->b) -> a -> c
(f . g) x = f (g x)
lunes, 11 de mayo de 2020
Tutorial de Python, Guía básica de Python en español
Reza la página:
"Este tutorial de Python es una introducción a los principales aspectos y características del lenguaje. El tutorial sirve de guía de inicio para dar los primeros pasos con Python, familiarizarse con su sintaxis, conocer los principales tipos de datos y entender algunos conceptos clave.
¿Para quién es este tutorial Python?
En principio, el tutorial es apto para todos los públicos. Si nunca has programado en Python, te servirá para aprender lo básico del lenguaje. Por el contrario, si ya lo conoces y/o has desarrollado alguna aplicación con él, te será útil para reforzar conceptos y descubrir cosas nuevas que quizá desconozcas."
No tengo más que acotar, dejo link : https://j2logo.com/python/tutorial/?fbclid=IwAR2igqihfrqMMr1ZnqR5hgx3ZUkwE2OmYBz-FBmPQrnRRCyJeoVv1s4Nd0k
domingo, 10 de mayo de 2020
HumanOS
Dejo link:
http://humanos.uci.cu/
Juego de adivinanzas en Haskell
Vamos a ser un juego de adivinanzas. Va a haber una palabra que el jugador debe adivinar. Para cada turno del juego, el jugador adivina una sola letra. Si esa letra es correcta, las letras adivinadas se muestran en los lugares correctos de la palabra. Si esa letra es incorrecta, el usuario pierde una estrella. Una vez que el usuario no tiene estrellas, ha perdido el juego. Sin embargo, si el usuario adivina todas las letras de la palabra, ha ganado el juego, como el ahorcado.
Comience creando un archivo de texto vacío llamado ahorcado.hs: la extensión hs es para indicar que este archivo contiene el código fuente de Haskell.
El corazón del juego consiste en verificar las conjeturas del jugador. Queremos saber si la suposición fue correcta. Este resultado es un valor Bool, ya sea verdadero o falso. Necesitamos actualizar la palabra mostrada, si la suposición fue correcta, reemplazando los guiones apropiados en la palabra mostrada con el carácter correctamente adivinado. Por lo tanto, el tipo de resultado de la función es un par (Bool, String). El primer elemento del par es el resultado de la suposición. El segundo elemento es la Cadena que se mostrará al usuario para la próxima ronda.
Ahora, la función de verificación necesita saber:
Comience creando un archivo de texto vacío llamado ahorcado.hs: la extensión hs es para indicar que este archivo contiene el código fuente de Haskell.
El corazón del juego consiste en verificar las conjeturas del jugador. Queremos saber si la suposición fue correcta. Este resultado es un valor Bool, ya sea verdadero o falso. Necesitamos actualizar la palabra mostrada, si la suposición fue correcta, reemplazando los guiones apropiados en la palabra mostrada con el carácter correctamente adivinado. Por lo tanto, el tipo de resultado de la función es un par (Bool, String). El primer elemento del par es el resultado de la suposición. El segundo elemento es la Cadena que se mostrará al usuario para la próxima ronda.
Ahora, la función de verificación necesita saber:
- La palabra secreta, una cadena
- La palabra que se muestra en pantalla o real, también una cadena
- El carácter elegido por el jugador.
Estas son las entradas a la función de verificación. Entonces ahora podemos establecer el tipo de la función:
check :: String -> String -> Char -> (Bool, String)
La nueva palabra que se mostrará será:
[(if x==c then c else y) | (x,y) <- zip word display]
Esta es una lista de comprensión, donde seleccionamos cada letra de la palabra real o de la pantalla anterior. La palabra es texto sin formato, mientras que la pantalla comienza con todos los caracteres discontinuos.
La siguiente función que definiremos es la función de giro. Esta es la función que se llamará cada vez que sea el turno del jugador para ingresar un caracter. Primero debemos comprobar cuántas conjeturas le quedan al jugador:
if n == 0
Si quedan algunas conjeturas, entonces necesitamos ver si el jugador completo la palabra o no:
if word == display
Entonces tendremos dos verificaciones if, cada una seguida de mensajes de estado putStrLn y el final de la secuencia de llamada a la función (ya que es el final del juego). Sin embargo, si ninguna de las condiciones es verdadera, entonces el jugador puede tomar un turno, por lo que llamamos a otra función para obtener otro personaje de la entrada del usuario.
Tenga en cuenta que hay una forma más ordenada de escribir la función de giro, utilizando Haskell guards, pero no vamos a utilizarlas para simplificar el programa.
¿Cuál es el tipo de mkguess? ¿Puedes resolverlo y agregarlo antes de la definición de la función? Tomamos una línea de entrada del usuario, pero solo usamos el primer carácter para la suposición. Esto fallará si el usuario simplemente presiona ENTER sin escribir ningún carácter, ya que q será una cadena vacía.
Bien, ahora solo necesitamos una función de nivel superior:
Esta función toma dos argumentos, el primero es la palabra a adivinar y el segundo es el número de conjeturas incorrectas que el jugador tiene permitido.
Pongamos todas estas cuatro funciones en un archivo de texto, llamado starman.hs
Guarde el archivo, luego inicie ghci quizás escribiendo ghci en un símbolo del sistema de DOS, ejecutando WinGHCi o escribiendo ghci en una ventana de terminal (macOS o Linux).
Si está en el directorio correcto, es decir, en el que guardó starman.hs, debería poder escribir
:l starman.hs
y el programa debería cargarse. Dirá algo como:
Prelude> :l ahorcado.hs
[1 of 1] Compiling Main ( ahorcado.hs, interpreted )
Ok, one module loaded.
Starman "funcionalmente" 5
y comienza a jugar el juego! Volverá a la solicitud de GHCi cuando se complete la función starman.
Y Listo!!
check :: String -> String -> Char -> (Bool, String)
Siempre es útil determinar primero el tipo de función. Esto enfoca su atención en lo que se supone que debe calcular la función, y qué datos necesita para hacerlo. Los buenos ingenieros de software hacen las especificaciones antes de la implementación.
¿Cómo será el cuerpo de la función de verificación? La suposición del jugador es correcta si y solo si el carácter elegido c está en la palabra secreta. Entonces la suposición es correcta si :
c palabra `elem`
¿Cómo será el cuerpo de la función de verificación? La suposición del jugador es correcta si y solo si el carácter elegido c está en la palabra secreta. Entonces la suposición es correcta si :
c palabra `elem`
La nueva palabra que se mostrará será:
[(if x==c then c else y) | (x,y) <- zip word display]
Esta es una lista de comprensión, donde seleccionamos cada letra de la palabra real o de la pantalla anterior. La palabra es texto sin formato, mientras que la pantalla comienza con todos los caracteres discontinuos.
check :: String -> String -> Char -> (Bool, String)
check word display c
= (c `elem` word, [if x==c
then c
else y | (x,y) <- zip word display])
La siguiente función que definiremos es la función de giro. Esta es la función que se llamará cada vez que sea el turno del jugador para ingresar un caracter. Primero debemos comprobar cuántas conjeturas le quedan al jugador:
if n == 0
Si quedan algunas conjeturas, entonces necesitamos ver si el jugador completo la palabra o no:
if word == display
Entonces tendremos dos verificaciones if, cada una seguida de mensajes de estado putStrLn y el final de la secuencia de llamada a la función (ya que es el final del juego). Sin embargo, si ninguna de las condiciones es verdadera, entonces el jugador puede tomar un turno, por lo que llamamos a otra función para obtener otro personaje de la entrada del usuario.
turn :: String -> String -> Int -> IO ()
turn word display n =
do if n==0
then putStrLn "You lose"
else if word==display
then putStrLn "You win!"
else mkguess word display n
mkguess word display n =
do putStrLn (display ++ " " ++ take n (repeat '*'))
putStr " Enter your guess: "
q <- getLine
let (correct, display') = check word display (q!!0)
let n' = if correct then n else n-1
turn word display' n'
Bien, ahora solo necesitamos una función de nivel superior:
starman :: String -> Int -> IO ()
starman word n = turn word ['-' | x <- word] n
Pongamos todas estas cuatro funciones en un archivo de texto, llamado starman.hs
Guarde el archivo, luego inicie ghci quizás escribiendo ghci en un símbolo del sistema de DOS, ejecutando WinGHCi o escribiendo ghci en una ventana de terminal (macOS o Linux).
Si está en el directorio correcto, es decir, en el que guardó starman.hs, debería poder escribir
:l starman.hs
y el programa debería cargarse. Dirá algo como:
Prelude> :l ahorcado.hs
[1 of 1] Compiling Main ( ahorcado.hs, interpreted )
Ok, one module loaded.
Starman "funcionalmente" 5
y comienza a jugar el juego! Volverá a la solicitud de GHCi cuando se complete la función starman.
Y Listo!!
miércoles, 6 de mayo de 2020
El estado del ecosistema del desarrollador 2019
Sin más dejo el link: https://www.jetbrains.com/es-es/lp/devecosystem-2019/
martes, 5 de mayo de 2020
Swift es como Kotlin
Quiero compartir una pagina que compara Swift con Kotlin.
Lo comparto porque hasta esta pagina, no me parecían similares pero son igualitos :D
Dejo link: http://nilhcem.com/swift-is-like-kotlin/
lunes, 4 de mayo de 2020
Libro gratuito de Scala
Quiero compartir el siguiente libro de Alvin Alexander que es gratuito y esta bueno. El libro tiene aproximadamente 225 páginas y proporciona una breve pero completa introducción al lenguaje Scala. Según el autor.
Sin más dejo el link: https://alvinalexander.com/scala/scala-book-free/
Ejemplo de pattern matching en Scala
La idea es que tenemos que saber si un string (en realidad lo hice con lista de caracteres) tiene sus paréntesis balanceados. Onda si abre uno lo tiene que cerrar y por supuesto, no puede comenzar cerrando.
Veamos como podemos solucionar esto en Scala:
def balance(palabra : List[Char]) : Boolean = {
def balanceAux(palabra : List[Char], n : Int) : Int = palabra match {
case List() => n
case '('::tail => balanceAux(tail, n + 1)
case ')'::tail => if (n == 0) -1 else balanceAux(tail, n - 1)
case _::tail => balanceAux(tail, n)
}
balanceAux(palabra, 0) == 0
}
Se puede ver que el ultimo case tiene el valor que no es un paréntesis, cualquier otra letra y esto lo decimos con "_"
Es un ejemplo bastante pavo, pero podemos ver la potencia que tiene Pattern matching
Veamos como podemos solucionar esto en Scala:
def balance(palabra : List[Char]) : Boolean = {
def balanceAux(palabra : List[Char], n : Int) : Int = palabra match {
case List() => n
case '('::tail => balanceAux(tail, n + 1)
case ')'::tail => if (n == 0) -1 else balanceAux(tail, n - 1)
case _::tail => balanceAux(tail, n)
}
balanceAux(palabra, 0) == 0
}
Se puede ver que el ultimo case tiene el valor que no es un paréntesis, cualquier otra letra y esto lo decimos con "_"
Es un ejemplo bastante pavo, pero podemos ver la potencia que tiene Pattern matching
Suscribirse a:
Entradas (Atom)