<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Josué Isai Hernández Sánchez</title>
    <description>The latest articles on DEV Community by Josué Isai Hernández Sánchez (@josueisaihs).</description>
    <link>https://dev.to/josueisaihs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F542922%2F1e4292f0-1989-45c3-b7c5-bd10a7377af2.jpg</url>
      <title>DEV Community: Josué Isai Hernández Sánchez</title>
      <link>https://dev.to/josueisaihs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/josueisaihs"/>
    <language>en</language>
    <item>
      <title>Validador de Paréntesis</title>
      <dc:creator>Josué Isai Hernández Sánchez</dc:creator>
      <pubDate>Thu, 09 Mar 2023 02:29:26 +0000</pubDate>
      <link>https://dev.to/josueisaihs/validador-de-parentesis-4na3</link>
      <guid>https://dev.to/josueisaihs/validador-de-parentesis-4na3</guid>
      <description>&lt;p&gt;En este artículo presentaré mi propuesta de implementación de un algoritmo para verificar si una cadena de caracteres que contiene diversos tipos de brackets (paréntesis, llaves y corchetes cuadrados) está bien formada o no. El algoritmo usa una pila para verificar si los corchetes están balanceados o no.&lt;/p&gt;

&lt;p&gt;El método principal se llama sentinel y toma una cadena de caracteres que contiene los corchetes como argumento. La clase BracketSentinel define tres métodos principales:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BracketSentinel:
    def __init__(self, *args, **kargs):
        pass

    def isOpen(self, bracket):
        pass

     def closeCorrectly(self, lastOpenBracket, bracketClose):
        pass

    def run(self, brackets):
        pass

    def sentinel(self, brackets, showError = False):
        pass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El método &lt;strong&gt;init&lt;/strong&gt;() es el constructor de la clase y se utiliza para inicializar la lista de corchetes. La lista de corchetes se define como un diccionario con dos claves: "open" y "close". La clave "open" contiene una tupla de caracteres que representan los corchetes de apertura, mientras que la clave "close" contiene otro diccionario que mapea cada corchete de apertura a su respectivo corchete de cierre.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def __init__(self, *args, **kwargs):
        super(BracketSentinel, self).__init__(*args, **kwargs)
        self.brackets = {
            "open": ("(", "{", "["),
            "close": {
                "(": ")",
                "[": "]",
                "{": "}"
            }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El método isOpen(self, bracket) verifica si el corchete pasado como argumento es un corchete de apertura o no. Devuelve True si el corchete es un corchete de apertura y False en caso contrario.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def isOpen(self, bracket):
        return bracket in self.brackets["open"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Por otro parte, el método closeCorrectly(self, lastOpenBracket, bracketClose) verifica si el último corchete abierto en la pila tiene un corchete de cierre correcto o no. Toma como argumentos el último corchete abierto y el corchete de cierre que se está evaluando en la cadena de caracteres. Devuelve True si el corchete de cierre es correcto y False en caso contrario.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; def closeCorrectly(self, lastOpenBracket, bracketClose):
        return bracketClose == self.brackets["close"][lastOpenBracket]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El método run(self, brackets) es el núcleo del algoritmo de verificación de corchetes. Toma una cadena de caracteres que contiene corchetes como argumento y devuelve True si los corchetes están balanceados y False en caso contrario. El método utiliza una pila para verificar si los corchetes están balanceados. Recorre la cadena de caracteres de izquierda a derecha y agrega cada corchete de apertura a la pila. Si encuentra un corchete de cierre, verifica si el último corchete abierto en la pila tiene el corchete de cierre correcto o no. Si el corchete de cierre es correcto, elimina el último corchete abierto de la pila. Si la pila no está vacía al final del recorrido, significa que los corchetes no están balanceados y devuelve False. Si la pila está vacía al final del recorrido, significa que los corchetes están balanceados y devuelve True.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def run(self, brackets):
        stack = []
        for bracket in brackets:
            if self.isOpen(bracket):
                stack.append(bracket)
            elif stack.__len__() &amp;gt; 0 and self.closeCorrectly(stack[-1], bracket):
                del stack[-1]
            else:
                return False
        else:
            return stack.__len__() == 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El método sentinel(self, brackets, showError = False) es una extensión del método run(self, brackets). Además de verificar si los corchetes están balanceados, este método también marca los corchetes que están mal formados. Si encuentra un corchete mal formado, lo marca con un "^" debajo del corchete en la cadena de caracteres y agrega el índice del corchete mal formado a la lista de errores. Al final, devuelve True si los corchetes están balanceados y False en caso contrario. Si el parámetro opcional showError se establece en True, muestra la cadena de caracteres de entrada con los corchetes mal formados marcados con un “^” debajo del corchete correspondiente.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def sentinel(self, brackets, showError = False):
        sintaxSuccessfull = True
        errors = []
        stack = []
        for index, bracket in enumerate(brackets):
            if self.isOpen(bracket):
                stack.append(bracket)
            elif stack.__len__() &amp;gt; 0 and self.closeCorrectly(stack[-1], bracket):
                del stack[-1]
            else:
                sintaxSuccessfull = sintaxSuccessfull and False
                errors.append(index)
        else:
            sintaxSuccessfull = sintaxSuccessfull and stack.__len__() == 0

        y = list(" " * brackets.__len__())
        for i in errors:
            y[i] = "^"
        print("\n", *list(brackets), "\n", *y)
        return sintaxSuccessfull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finalmente, la clase BracketSentinel define un algoritmo para verificar si una cadena de caracteres que contiene corchetes está bien formada o no. El algoritmo utiliza una pila para verificar si los corchetes están balanceados. El método sentinel es una extensión del método principal run que también marca los corchetes mal formados en la cadena de caracteres de entrada.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Pruebas Unitarias&lt;br&gt;
El código muestra cómo se pueden implementar pruebas unitarias en Python utilizando el módulo unittest para comprobar la funcionalidad de una clase que verifica si una cadena de corchetes está bien formada.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
&lt;a href="https://github.com/josueisaihs/PythonPractice"&gt;https://github.com/josueisaihs/PythonPractice&lt;/a&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>algorithms</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Flippind Matrix</title>
      <dc:creator>Josué Isai Hernández Sánchez</dc:creator>
      <pubDate>Wed, 01 Mar 2023 22:19:40 +0000</pubDate>
      <link>https://dev.to/josueisaihs/flippind-matrix-439a</link>
      <guid>https://dev.to/josueisaihs/flippind-matrix-439a</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;He de admitir que llegar a la solución final me llevó más tiempo de análisis, que de código. El problema Flipping Matrix, enuncia lo siguiente:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sean inventó un juego que involucra una matriz donde cada celda de la matriz contiene un número entero. Puede invertir cualquiera de sus filas o columnas cualquier número de veces. El objetivo del juego es maximizar la suma de los elementos en la submatriz ubicada en el cuadrante superior izquierdo de la matriz.&lt;br&gt;
Dadas las configuraciones iniciales de las matrices, ayude a Sean a invertir las filas y columnas de cada matriz de la mejor manera posible para que la suma de los elementos en el cuadrante superior izquierdo de la matriz sea máxima.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Básicamente, el problema consiste en encontrar el valor máximo de cada submatriz. Esta submatriz está delimitada por un de tamaño “nxn” y los números posibles son aquellos que se encuentran en las posiciones inversas de esa submatriz, tanto en filas como en columnas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solución Inicial
&lt;/h2&gt;

&lt;p&gt;La solución propuesta utiliza solo dos bucles para recorrer todas las filas y columnas dentro del cuadrado morado y una función que identifica el número máximo entre las cuatro posiciones posibles para cada submatriz. La función compara el valor del cuadrado superior izquierdo, superior derecho, inferior izquierdo e inferior derecho y devuelve el valor máximo de los cuatro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flippingMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;max_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;top_left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;top_right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;bottom_left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;bottom_right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;max_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top_left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom_left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom_right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;max_total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;max_val&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max_total&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El código proporcionado implementa una función llamada flippingMatrix que toma una matriz cuadrada de números y devuelve el valor máximo que se puede obtener al hacer "flip" de los valores de una submatriz de 2x2 en la matriz original. El "flip" significa cambiar los valores de la submatriz con sus correspondientes simétricos en la matriz. A continuación, explico línea a línea al algoritmo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;n = len(matrix)//2&lt;/code&gt; - Calcula la mitad de la longitud de la matriz y la asigna a la variable n. Esto se utiliza más adelante para delimitar la submatriz 2x2 que se utiliza para hacer el "flip".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_total = 0&lt;/code&gt; - Inicializa la variable max_total a cero. Esta variable se utiliza para almacenar la suma del valor máximo de cada submatriz 2x2 que se considera.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for i in range(n):&lt;/code&gt; - Comienza un bucle que se ejecuta n veces. Este bucle itera sobre las filas de la submatriz 2x2.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for j in range(n):&lt;/code&gt; - Dentro del bucle anterior, comienza otro bucle que se ejecuta n veces. Este bucle itera sobre las columnas de la submatriz 2x2.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top_left = matrix[i][j]&lt;/code&gt; - Calcula el valor del elemento en la esquina superior izquierda de la submatriz 2x2 y lo asigna a la variable top_left.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top_right = matrix[i][n*2-1-j]&lt;/code&gt; - Calcula el valor del elemento en la esquina superior derecha de la submatriz 2x2 y lo asigna a la variable top_right.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bottom_left = matrix[n*2-1-i][j]&lt;/code&gt; - Calcula el valor del elemento en la esquina inferior izquierda de la submatriz 2x2 y lo asigna a la variable bottom_left.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bottom_right = matrix[n*2-1-i][n*2-1-j]&lt;/code&gt; - Calcula el valor del elemento en la esquina inferior derecha de la submatriz 2x2 y lo asigna a la variable bottom_right.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_val = max(top_left, top_right, bottom_left, bottom_right)&lt;/code&gt; - Calcula el valor máximo entre los cuatro valores de la submatriz 2x2 y lo asigna a la variable max_val.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_total += max_val&lt;/code&gt; - Añade el valor máximo de la submatriz 2x2 a la variable max_total.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;return max_total&lt;/code&gt; - Devuelve el valor total máximo obtenido al hacer "flip" de los valores de una submatriz de 2x2 en la matriz original.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;En resumen, el código implementa una solución eficiente para el problema de “flip” de una matriz 2D y utiliza la función &lt;br&gt;
&lt;code&gt;max&lt;/code&gt; para obtener el valor máximo de una submatriz de 2x2 en cada iteración del bucle anidado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recomendación
&lt;/h2&gt;

&lt;p&gt;En mi &lt;a href="https://medium.com/@josueisaihs/problema-flippind-matrix-7cd8e38aadb8" rel="noopener noreferrer"&gt;arículo&lt;/a&gt; explico como optimizar la solución 1.&lt;/p&gt;

&lt;p&gt;Y en mi &lt;a href="https://github.com/josueisaihs/PythonPractice/tree/main/FlippingTheMatrix" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; podrás descargar el código y las pruebas, además de ver soluciones a otros problemas.&lt;/p&gt;

</description>
      <category>motivation</category>
      <category>watercooler</category>
    </item>
  </channel>
</rss>
