This commit is contained in:
Vladimir Lemus 2023-05-03 19:11:46 -06:00
parent be9502de44
commit 1a86b71152
8 changed files with 454 additions and 0 deletions

5
entsal.hs Normal file
View File

@ -0,0 +1,5 @@
act :: IO (Char,Char)
act = do x <- getChar
getChar
y <- getChar
return (x,y)

58
fun.hs Normal file
View File

@ -0,0 +1,58 @@
pari :: Integral a => a -> Bool
pari n = n `mod` 2 == 0
divi :: Int -> [a] -> ([a],[a])
divi n xs = (take n xs, drop n xs)
reste :: [Float] -> [Float] -> [Float]
reste xs ys = zipWith (-) xs ys
absol :: Int -> Int
absol n = if n >= 0 then n else -n
signi :: Int -> String
signi n = if n < 0 then "negativo" else
if n == 0 then "cero" else "positivo"
signg :: Int -> String
signg n | n < 0 = "negativo"
| n > 0 = "positivo"
|otherwise = "cero"
cabeza :: (a,b) -> a
cabeza (x,_) = x
prob :: [Char] -> Bool
prob ['a',_,_] = True
prob _ = False
cabezo :: [a] -> a
cabezo (x:_) =x
suma :: Int -> Int -> Int
suma = \x -> (\y -> x+y)
consta :: a -> (b -> a)
consta x = \_ -> x
impa :: Int -> [Int]
impa n = map f [0..n-1]
where f x = x*2 + 1
impa2 :: Int -> [Int]
impa2 n = map (\x -> x*2 + 1) [0..n-1]
tam :: [a] -> Int
tam xs = sum [1| _ <- xs]
factores :: Int -> [Int]
factores n = [x | x <- [1..n], n `mod` x == 0]
primo :: Int -> Bool
primo n = factores n == [1,n]
primos :: Int -> [Int]
primos n = [x | x <- [2..n], primo x]
busca :: Eq a => a -> [(a,b)] -> [b]
busca k t = [v | (k',v) <- t, k==k']

BIN
patrones.pdf Normal file

Binary file not shown.

188
patrones.tex Normal file
View File

@ -0,0 +1,188 @@
\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[spanish]{babel}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{hyperref}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{caption}
\usepackage{multicol}
\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{automata,positioning,arrows}
\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
\definecolor{darkblue}{rgb}{0,0,.75}
\lstdefinestyle{mystyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen},
keywordstyle=\color{magenta},
numberstyle=\tiny\color{codegray},
stringstyle=\color{codepurple},
basicstyle=\ttfamily\footnotesize,
breakatwhitespace=false,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showspaces=false,
showstringspaces=false,
showtabs=false,
tabsize=2
}
\lstset{style=mystyle}
\lstloadlanguages{Matlab} %use listings with Matlab for Pseudocode
\lstnewenvironment{PseudoCode}[1][]
{\lstset{language=Matlab,basicstyle=\scriptsize, keywordstyle=\color{darkblue},numbers=left,xleftmargin=.04\textwidth,#1}}
{}
\renewcommand{\rmdefault}{ptm}
%\usepackage[all,cmtip]{xy}
%\usepackage{graphicx}
\author{Programación funcional para la física computacional}
\title{Patrones}
\begin{document}
\maketitle
\section*{Identificación de patrones}
La identificación de patrones es una de las funciones básicas de un lenguaje de programación. Al estudiar las computadoras como objeto teórico antes de llegar a los modelos computacionales, que ya vimos en una sección anterior, se estudian mecanismos más sencillos, regularmente llamados \emph{sub-Turing}, ya que no llegan a la potencia de de una máquina de Turing o el cálculo $\lambda$, pero pueden verse como casos específicos de esos modelos.
Estos niveles de modelos computacionales han sido estratificados por el lingüista Noam Chomsky. La jerarquía de Chomsky pone el siguiente orden:
\begin{enumerate}
\item Lenguajes regulares
\item Gramáticas independientes de contexto
\item Gramáticas sin restricciones
\end{enumerate}
El último nivel es el que puede identificarse completo con una máquina de Turing o el cálculo $\lambda$, los niveles inferiores pueden perfectamente simularse por una máquina de Turing, pero esos modelos no pueden simular toda máquina de Turing.
El primer nivel son las expresiones regulares, que están ligadas a la identificación de patrones. Las expresiones regulares son aceptadas por autómatas finitos deterministas, la forma más sencilla de mostrar que un lenguaje es regular es construyendo un autómata de este tipo. Un autómata finito determinista se define como:
\newtheorem{defi}{Definición}
\begin{defi}
Un autómata finito determinista es la quinteta
\begin{equation*}
M = (Q,\Sigma,\delta,s,F)
\end{equation*}
\begin{itemize}
\item $Q$ el conjunto finito de estados;
\item $\Sigma$ conjunto finito, alfabeto de entrada;
\item $\delta : Q\times \Sigma \rightarrow Q$ la función de transición;
\item $s\in Q$ es el estado inicial;
\item $F\subseteq Q$, los estados de aceptación o estados finales.
\end{itemize}
\end{defi}
Ya sea que se defina cada uno de los elementos o que se dibuje un diagrama como se muestra en la figura \ref{fig:auto}. Lo relevante es que pueden identificarse cadenas infinitas y de longitud infinita con sólo unos pocos estados y transiciones, misma que a su vez es la limitación para poder identificar cadenas en los lenguajes por arriba en la jerarquía de Chomsky. No hay más memoria que el estado en el que se encuentra.
\begin{figure}
\begin{center}
\begin{tikzpicture}
\node[state,initial,initial text= inicio] (S) {$S$};
\node[state,right=of S] (1) {$1$};
\node[state,right=of 1] (2) {$2$};
\node[state,right=of 2] (3) {$3$};
\node[state,accepting,right=of 3] (4) {$4$};
%\node[state,accepting, right=of 4] (4) {$5$};
\path [-stealth,thick]
(S) edge [left] node [yshift=0.3cm]{$a$} (1)
edge [loop above] node{$b$} ()
(1) edge [left] node [yshift=0.3cm]{$b$} (2)
edge [loop below] node{$a$} ()
(2) edge [bend right] node[yshift=0.3cm]{$b$} (S)
edge [right] node[yshift=0.3cm]{$a$} (3)
(3) edge [bend left] node[yshift=-0.3cm]{$a$} (1)
edge [right] node[yshift=-0.3cm]{$b$} (4)
(4) edge [loop above] node{$a,b$}();
\end{tikzpicture}
\end{center}
\caption{Automata finito determinista que acepta el lenguaje $\{ w\in\{ a,b \}^* \mid w \text{ contiene la subcadena } abab\}$.}
\label{fig:auto}
\end{figure}
Para identificar patrones en un lenguaje de programación debemos tomar en cuenta:
\begin{itemize}
\item Ser cuidadoso con mayúsculas y minúsculas, como carcateres son distintos y la identificación será distinta.
\item Usar escapes para caracteres especiales
\begin{itemize}
\item Caracteres de control ($\backslash t$, $\backslash n$, $\backslash r$.)
\item Caracteres numéricos (octal $\backslash nnn$, hexadecimal $\backslash xnn$, \textit{unicode} $\backslash unnnn$)
\item Caracteres especiales de escape ($\backslash ($)
\end{itemize}
\item Caracteres comodín: $.$, $\backslash w$, $\backslash s$,...
\item Anclas : \^, $\$ $, $*$
\end{itemize}
Para identificar patrones en \emph{haskell} necesitamos importar una librería, no está definido por \emph{default} en el lenguaje.
\begin{lstlisting}{language=Haskell}
import Text.Regex.Posix
let vocals = ``[aeiou]''
``Enunciado prueba'' =~ vocales :: Bool
``Enunciado prueba'' =~ vocales :: Int
``Enunciado prueba'' =~ vocales :: String
``Enunciado prueba'' =~ vocales :: (String,String,String)
\end{lstlisting}
Lo mismo se puede hacer con números, un ejemplo que puede parecer útil es hacer un programa que identifique un número de teléfono con un formato definido.
\begin{lstlisting}{language=Haskell}
let tel = "\\([0-9]{3}\\)[0-9]{3}\\-[0-9]{4}"
"Mi numero de telefono es: (555)643-1212"=~ tel :: String
\end{lstlisting}
Nota como se hace la identificación de patrones de acuerdo a lo mencionado líneas arriba.
De manera similar para identificar patrones en \emph{python}
\begin{lstlisting}{language=Python}
import re
vocales = "[aeiou]"
re.search(vocales, "Enunciado de ejemplo")
re.search(vocales,"Enunciado de ejemplo").group()
\end{lstlisting}
Las funcionalidades necesarias están en la librería \emph{re} (de \emph{regular expressions}), al igual que en \emph{haskell} se definen los patrones \emph{vocales}. Pero la diferencia está en que si simplemente se aplica el método \emph{re.search(vocales, ``Enunciado de ejemplo'')} lo que regresa es un objeto coincidente, en lugar del objeto que se busca. Para obtenerlo debe además escribirse otra línea idéntica pero finalizando con \emph{.group()}. Pero además de la búsqueda se puede trabajar con cincidencias
\begin{lstlisting}{language=Python}
import re
vocales = "[aeiou]"
re.match(vocales, "Enunciado de prueba")
re.match("E","Enunciado de ejemplo")
re.findall(vocales, "Enunciado de prueba")
\end{lstlisting}
Aún trabajando más con la identificación de patrones
\begin{lstlisting}{language=Python}
import re
sPrueba = "Esta es\tuna cadena de prueba.\nA fuerzas"
espacio = "[\s]"
re.split(espacio,sPrueba)
\end{lstlisting}
Lo que hace el programa es dividir la cadena en todas las subcadenas que se encuentran entre espacios, sea un espacio simple, un tabulador o un salto de línea.
\end{document}

BIN
recursion.pdf Normal file

Binary file not shown.

161
recursion.tex Normal file
View File

@ -0,0 +1,161 @@
\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[spanish]{babel}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{hyperref}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{caption}
\usepackage{multicol}
\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{automata,positioning,arrows}
\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
\definecolor{darkblue}{rgb}{0,0,.75}
\lstdefinestyle{mystyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen},
keywordstyle=\color{magenta},
numberstyle=\tiny\color{codegray},
stringstyle=\color{codepurple},
basicstyle=\ttfamily\footnotesize,
breakatwhitespace=false,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showspaces=false,
showstringspaces=false,
showtabs=false,
tabsize=2
}
\lstset{style=mystyle}
\lstloadlanguages{Matlab} %use listings with Matlab for Pseudocode
\lstnewenvironment{PseudoCode}[1][]
{\lstset{language=Matlab,basicstyle=\scriptsize, keywordstyle=\color{darkblue},numbers=left,xleftmargin=.04\textwidth,#1}}
{}
\renewcommand{\rmdefault}{ptm}
%\usepackage[all,cmtip]{xy}
%\usepackage{graphicx}
\author{Programación funcional para la física computacional}
\title{Recursión}
\begin{document}
\maketitle
\section*{Funciones bien definidas}
Una de las ventajas de la programación funcional es que, al basarse en funciones, se alienta a que la usuaria defina nuevas a conveniencia. Pero estas funciones deben estar bien definidas para evitar problemas al ejecutarse. Para nadie es raro el clásico problema de la división de dos números enteros que regresa una resultado en principio mal pues regresa un número natural a menos que se le indique por algún comando especial.
Para evitar tener que manejar distintos comandos extras, en \emph{haskell} podemos decir que tipo de datos acepta y cuales regresa desde la misma definición de la función.
Ejemplos de como se pudedn definir nuevas funciones a partir de viejas funciones (ya en la librería de \emph{haskell})
\begin{itemize}
\item Una función que indica si el número dado es par, es decir, toma como valor un entero de precisión variable (Integral) y regresa un \emph{booleano}.
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=1,lastline=2,language=haskell]{fun.hs}
\item La función que divide una lista en sus primeros $n$ elementos y los restantes, recibe una lista y regresa una lista de listas
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=4,lastline=6,language=haskell]{fun.hs}
\item La función que resta los elementos correspondientes de cada lista
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=7,lastline=9,language=haskell]{fun.hs}
\end{itemize}
Pero podemos usar algunas cosas dentro del lenguaje para definir funciones más allá, por ejemplo, usando expresiones condicionales (cosa común en la definición de funciones en \emph{python} y que también está en \emph{haskell})
\begin{itemize}
\item Expresiones condicionales para definir la función que regresa el valor absoluto de un entero
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=10,lastline=12,language=haskell]{fun.hs}
\item Expresiones condicionales anidadas para que regrese el signo del número dado (como cadena)
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=13,lastline=16,language=haskell]{fun.hs}
\end{itemize}
Ya hemos trabajado un poco con comprensión de listas, aunque no hemos visto mucho detalle. Lo que sabemos es que podemos usar \emph{guardas} tal como se usan para definir conjuntos en matemáticas. Facilitan y reducen el tamaño de las definiciones, volvemos a definir la función de líneas arriba pero ahora de manera más sencilla:
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=17,lastline=21,language=haskell]{fun.hs}
La sección pasada vimos reconocimiento de patrones, no era tan sencillo para \emph{haskell}, pero realmente esta la funcionalidad incluida en algunas de sus operaciones. Por ejemplo en las operaciones \emph{booleanas} del tipo \emph{True \&\& False} lo que hace el lenguaje es reconocer los patrones y asociarlos a las operaciones lógicas. Pero hay otros casos de reconocimiento de patrones
\begin{itemize}
\item Patrones en eneadas
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=22,lastline=24,language=haskell]{fun.hs}
\item Lista de patrones
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=25,lastline=28,language=haskell]{fun.hs}
\item Lista de patrones con el constructor
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=29,lastline=31,language=haskell]{fun.hs}
\end{itemize}
Como ya saben también podemos hacer uso de las definiciones con cálculo $\lambda$. El clásico ejemplo de definir la suma:
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=32,lastline=34,language=haskell]{fun.hs}
Definir funciones sólo por su estructura, sin tener que hacer alguna operación algebraica, en este caso sólo por el orden en que se dan los valores de entrada
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=35,lastline=37,language=haskell]{fun.hs}
Incluso se pueden llamar a otras funciones dentro de la definición de la función, como en el siguiente caso:
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=38,lastline=41,language=haskell]{fun.hs}
O haciendo el mismo caso desde un nivel aún más básico
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=42,lastline=44,language=haskell]{fun.hs}
Pero además este tipo de definiciones de funciones facilita definir operadores nuevos, por lo regular llamados \emph{secciones}. La estructura en que se definen, de distintas formas, se muestra a continuación:
\begin{align*}
(\#)\ =& \ \setminus x\ ->\ (\setminus y\ ->\ x\ \# y) \\
(x\ \#)\ =& \setminus y\ ->\ x\ \# y \\
(\#\ y)\ =& \setminus x\ ->\ x\ \# y
\end{align*}
El primer caso espera dos entradas para operar con el nuevo operador, las dos últimas espera sólo una entrada para operar por la derecha o izquierda, respectivamente (podría ser un operador no conmutativo, así que el orden importa).
En ocasiones es complicado definir un nuevo operador, muchos de los símbolos ya están tomados por el sistema. Algunas de las funciones compactas propias de \emph{haskell} definidas a partir de \emph{secciones}:
\begin{itemize}
\item $(+)$ la suma que ya usamos
\item $(1+)$ la función sucesor (la que suma $1$ al único número dado)
\item $(1/)$ el inverso de un número
\item $(*2)$ el doble de un número
\item $(/2)$ la mitad de un número
\end{itemize}
\section*{Comprensión de listas}
Otro tema que ya hemos pasado de rápido es la comprensión de listas, veamos más a detalle. La idea más directa es que estaos definiendo conjuntos de una manera que se asemeja mucho a la notación matemática. Las \emph{guardas}, que se escriben ``$\mid$'' funcionan como un \emph{tal que} al leer la descripción.
\begin{itemize}
\item Podemos tener el caso donde hacemos una lista de parejas, nos da todas las posibles combinaciones de parejas: $[(x,y) \mid x<- [1,2,3],\ y <- [4,5]]$
\item Si cambiamos el ordenamiento en la definición, obtendremos las mismas parejas, pero con distinto orden: $[(x,y) \mid y <- [4,5],\ x<- [1,2,3]]$
\end{itemize}
Podemos definir una función (que realmente ya existe en \emph{haskell}) para conocer la longitud de una lista, pero a partir de comprensión de listas:
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=45,lastline=47,language=haskell]{fun.hs}
Un ejemplo que ya se saben obtener los números primos entre $1$ y $n$, pero no de forma perezosa. Lo primero es identificar los factores de cada número entre $1$ y $n$
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=48,lastline=50,language=haskell]{fun.hs}
Agregamos para obtener los números primos a partir de la función ya definida para obtener los factores, todo hecho a partir de comprensión de listas. Lo que hace la función \emph{primo} es llamar a la anterior función \emph{factores} que da como resultado una lista y comparar si esa lista tiene como únicos factores al $1$ y al mismo número, respondiendo un \emph{verdadero} o \emph{falso}.
Posteriormente la función \emph{primo} es llamada dentro de la comprensión de listas de la función \emph{primos} que nos regresará la lista de números entre $2$ y $n$ siempre y cuando el número cumpla con la condición de la función \emph{primo}.
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=51,lastline=56,language=haskell]{fun.hs}
Para buscar valores dentro de listas de parejas, podemos definir una función, algo parecida a lo que se hizo para la función \emph{primo}, comparamos las entradas de la lista, si la primera entrada de la pareja es igual al valor dado entonces nos regresa el o los valores con los que forma pareja.
\lstinputlisting[basicstyle=\ttfamily\scriptsize,firstline=57,lastline=59,language=haskell]{fun.hs}
Una función que hemos utilizado y no nos hemos detenido mucho en ver a detalle es \emph{zip}. Esta función espera recibir dos listas y forma una lista de parejas, asociando los miembros correspondientes de cada lista
\begin{equation*}
zip\ ['a','b','c']\ [1,2,3,4] \rightarrow [('a',1),('b',2),('c',3)]
\end{equation*}
\subsection*{Cifrado del César}
\end{document}

BIN
tarea3.pdf Normal file

Binary file not shown.

42
tarea3.tex Normal file
View File

@ -0,0 +1,42 @@
\documentclass[10pt,a4paper]{article}
\usepackage[spanish]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{amsfonts}
\usepackage{amssymb}
%\usepackage{braket}
\author{Programación funcional para la física computacional}
\title{Tarea 3}
\begin{document}
\maketitle
\begin{enumerate}
\item Define las operaciones para el \emph{data} de vectores como vimos en clase para \emph{haskell}:
\begin{itemize}
\item Suma, resta vectorial
\item Producto (por izquierda y derecha) y división escalar
\item Producto punto y producto cruz vectorial
\item Norma de un vector
\end{itemize}
\item Implementa el algoritmo de Euclides como una función recursiva. Para dos números enteros positivos calcula el máximo común divisor de la siguiente manera:
\begin{itemize}
\item Si los número son iguales, ese número es el máximo común divisor
\item De lo contrario al número mayor se le resta el menor y el proceso se repite con el resultado hasta que se obtiene un número menor a los dos.
\end{itemize}
\item Haciendo uso de las definiciones para vectores que diste en el primer ejercicio calcula la fuerza de Lorentz que siente un electrón (carga de $1.6\times 10^{-19} coulombs$) que viaja a una velocidad de $(1.1\times 10^3) \hat{\i} + (1.2\times 10^3) \hat{\j} + 0\hat{k}\ km/s$ en un campo magnético de $0\hat{\i} + (1.3\times10^{-2})\hat{\j} + (0.1\times 10^{-2}) \hat{k}$ Teslas.
\begin{equation*}
\vec{F}=q(\frac{1}{c}\vec{v}\times \vec{B})
\end{equation*}
\item Define una función para calcular la resistencia electrica (en \emph{ohms}) de un material
\begin{equation*}
R= \rho \frac{\ell}{S}
\end{equation*}
\noindent donde $\rho$ es la resistividad del material en $\Omega m$, $\ell$ es la longitud del matrerial en $m$ y $S$ la sección transversal en $m^2$.
Usando esta función usala como argumento a otra para calcular la corriente eléctrica para un voltaje dado.
¿Cuál sería la corriente que pasa por una varilla de cobre de $20$ metros de longitud y $5$ cm de sección transversal si se le aplica un voltaje de $100$ volts? La resitividad del cobre es $1.71\times 10^{-8}\Omega m$ a temperaturas entre los ${20}^{\circ}C$ y ${25}^{\circ}C$, consideralo en ese rango.
\item Define una función que pase de números naturales a binarios y viceversa en el orden correcto.
\end{enumerate}
\end{document}