<?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>Forem: Axel Espinosa</title>
    <description>The latest articles on Forem by Axel Espinosa (@fromchiapasdev).</description>
    <link>https://forem.com/fromchiapasdev</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%2F186583%2F9cef57b1-206b-4316-9880-0fe5907f987f.jpeg</url>
      <title>Forem: Axel Espinosa</title>
      <link>https://forem.com/fromchiapasdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fromchiapasdev"/>
    <language>en</language>
    <item>
      <title>Why you keep attacking npm?</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 12 May 2026 22:39:43 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/why-you-keep-attacking-npm-4a53</link>
      <guid>https://forem.com/fromchiapasdev/why-you-keep-attacking-npm-4a53</guid>
      <description>&lt;p&gt;Honestly, it's exhausting to wake up and find out there's yet another attack on the npm ecosystem.&lt;/p&gt;

&lt;p&gt;Socket shared &lt;a href="https://x.com/SocketSecurity/status/2054048025081737446" rel="noopener noreferrer"&gt;via social media&lt;/a&gt; that they identified compromised packages — some of them were TanStack.&lt;/p&gt;

&lt;p&gt;Why are attackers so obsessed with npm? Seriously, can you stop already?&lt;/p&gt;

&lt;p&gt;If you still use npm and haven't disabled post-scripts, you're in serious danger.&lt;/p&gt;

&lt;p&gt;Go and disable that right now.&lt;/p&gt;

&lt;p&gt;Start using pnpm. Version 11 disables this functionality by default. Of course, some packages still need post-scripts, and in those cases you should manually review and authorize them.&lt;/p&gt;

&lt;p&gt;Also, there are tools you can use before installing a package: Socket's &lt;a href="https://docs.socket.dev/docs/socket-firewall-free" rel="noopener noreferrer"&gt;sfw&lt;/a&gt; and &lt;a href="https://github.com/lirantal/npq" rel="noopener noreferrer"&gt;npq&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hope this helps.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>npm</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Can you stop attacking #npm packages? I'm scared of installing packages. Now it's time to switch 100% to PNPM...</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 12 May 2026 22:21:32 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/can-you-stop-attacking-npm-packages-im-scared-of-installing-packages-now-its-time-to-switch-1aa4</link>
      <guid>https://forem.com/fromchiapasdev/can-you-stop-attacking-npm-packages-im-scared-of-installing-packages-now-its-time-to-switch-1aa4</guid>
      <description></description>
      <category>node</category>
      <category>discuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>¿Qué son los Stacks (LIFO)?</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Fri, 08 May 2026 21:22:09 +0000</pubDate>
      <link>https://forem.com/aws/estructuras-de-datos-que-son-los-stacks-lifo-1d0n</link>
      <guid>https://forem.com/aws/estructuras-de-datos-que-son-los-stacks-lifo-1d0n</guid>
      <description>&lt;p&gt;¿Alguna vez te has preguntado qué pasa cuando presionas el botón "atrás" en tu navegador? ¿O cómo &lt;code&gt;Ctrl + Z&lt;/code&gt; sabe exactamente qué acción deshacer? Detrás de esas funciones hay una estructura de datos que llevas años usando sin darte cuenta: el stack.&lt;/p&gt;

&lt;p&gt;En los artículos anteriores vimos los &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;arrays&lt;/a&gt; y los &lt;a href="https://dev.to/aws/strings-en-programacion-mas-que-un-simple-array-de-caracteres-2lgn"&gt;strings&lt;/a&gt;. Hoy toca hablar de la siguiente pieza: los stacks. Si los arrays son el almacén general, el stack es una pila de platos. Ya lo vas a ver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo44qgfbopv1qjuo5c1pe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo44qgfbopv1qjuo5c1pe.png" alt="Todo esto que ya usas es un stack: botón atrás, Ctrl+Z y stack traces" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lo que encontrarás en este artículo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qué es un stack y qué significa LIFO&lt;/li&gt;
&lt;li&gt;Las operaciones básicas: push, pop, peek, size, isEmpty&lt;/li&gt;
&lt;li&gt;Cómo implementar tu propio stack en JavaScript&lt;/li&gt;
&lt;li&gt;La complejidad Big O de cada operación&lt;/li&gt;
&lt;li&gt;Dónde se usan los stacks en la vida real&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ¿Qué es un stack?
&lt;/h2&gt;

&lt;p&gt;Un stack (o pila) es una estructura de datos que sigue el principio &lt;strong&gt;LIFO: Last In, First Out&lt;/strong&gt;. En español: el último que entra es el primero que sale.&lt;/p&gt;

&lt;p&gt;Imagina una pila de libros sobre tu escritorio. Vas apilándolos uno sobre otro. Cuando quieres leer uno, ¿por cuál empiezas? Por el de arriba, no por el de abajo. El último libro que pusiste es el primero que vas a tomar.&lt;/p&gt;

&lt;p&gt;Esa es la esencia de un stack. No puedes sacar un elemento del medio o del fondo. Solo trabajas con el que está hasta arriba.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcku5pmn7qj6isjnc8amj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcku5pmn7qj6isjnc8amj.png" alt="LIFO: Last In, First Out" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle interesante: aunque suene restrictivo, esta limitación es justo lo que hace al stack útil. Cuando solo te importa el último elemento agregado, un stack es la herramienta perfecta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operaciones básicas de un stack
&lt;/h2&gt;

&lt;p&gt;Un stack tiene cinco operaciones fundamentales. Estas son las que aparecen en el ADT (Abstract Data Type) de un stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;push(item)&lt;/code&gt;: agrega un elemento a la parte superior&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pop()&lt;/code&gt;: elimina el elemento de arriba y lo devuelve&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;peek()&lt;/code&gt;: mira el elemento de arriba sin eliminarlo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;size()&lt;/code&gt;: devuelve cuántos elementos hay en el stack&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isEmpty()&lt;/code&gt;: dice si el stack está vacío o no&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Las dos estrellas son &lt;code&gt;push&lt;/code&gt; y &lt;code&gt;pop&lt;/code&gt;. Con ellas agregas y quitas elementos, siempre desde la misma puerta: la de arriba.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9gqqyr24femkwdeopc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9gqqyr24femkwdeopc6.png" alt="push y pop paso a paso" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fíjate en cómo &lt;code&gt;pop()&lt;/code&gt; siempre saca el último que entró. En el paso 3 agregamos 🐱, y en el paso 4 &lt;code&gt;pop()&lt;/code&gt; nos devuelve 🐱. Si hubiéramos hecho &lt;code&gt;pop()&lt;/code&gt; otra vez, nos devolvería 🐶.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo implementar un stack en JavaScript
&lt;/h2&gt;

&lt;p&gt;Dato curioso antes de empezar: los arrays en JavaScript ya se comportan como un stack. Si haces &lt;code&gt;miArray.push(x)&lt;/code&gt; y &lt;code&gt;miArray.pop()&lt;/code&gt;, estás trabajando como si fuera un stack..&lt;/p&gt;

&lt;p&gt;Pero un array te deja hacer cosas que un stack no debería permitir: acceder por cualquier índice, &lt;code&gt;unshift&lt;/code&gt;, &lt;code&gt;splice&lt;/code&gt;, lo que quieras. Y esa libertad de más es justo lo que queremos esconder.&lt;/p&gt;

&lt;p&gt;Así que vamos a implementarlo desde cero. Sin usar &lt;code&gt;.push()&lt;/code&gt; ni &lt;code&gt;.pop()&lt;/code&gt; del array. Solo lo vamos a usar como almacenamiento indexado y el control lo lleva nosotros. Así se ve qué pasa por debajo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// posición donde iría el próximo elemento&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El stack está vacío&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// recortamos el array&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El stack está vacío&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probemos cómo se usa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;miStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐱&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "👻" (solo mira, no elimina)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "👻" (lo elimina y devuelve)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así se ve el stack en cada paso:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifm64jmuvcn9tj2aqnzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifm64jmuvcn9tj2aqnzt.png" alt="Paso a paso de push, peek y pop sobre miStack" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Puedes probar este código en &lt;a href="https://runjs.app/play" rel="noopener noreferrer"&gt;RunJS&lt;/a&gt; o verlo paso a paso en &lt;a href="https://pythontutor.com/visualize.html#mode=edit" rel="noopener noreferrer"&gt;PythonTutor&lt;/a&gt;, que también soporta JavaScript.&lt;/p&gt;

&lt;p&gt;Vamos a desarmar lo que está pasando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; lleva la cuenta de cuántos elementos hay. También indica la siguiente posición libre del array. Recuerda que los arrays empiezan en el índice 0, así que cuando el stack está vacío &lt;code&gt;count&lt;/code&gt; vale 0 y ese es justo el lugar donde va a caer el primer elemento.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;push()&lt;/code&gt; coloca el nuevo elemento en la posición &lt;code&gt;count&lt;/code&gt; y luego incrementa el contador.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pop()&lt;/code&gt; hace lo contrario: decrementa &lt;code&gt;count&lt;/code&gt; primero (ahora apunta al último elemento), lee ese valor y recorta el array.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;peek()&lt;/code&gt; lee la posición &lt;code&gt;count - 1&lt;/code&gt; (el último elemento) sin mover nada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por ejemplo, si hacemos &lt;code&gt;push("🐶")&lt;/code&gt;, &lt;code&gt;push("🐱")&lt;/code&gt;, &lt;code&gt;push("👻")&lt;/code&gt;, el array queda así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl2g84clcfs1afg5taz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl2g84clcfs1afg5taz6.png" alt="Estado interno del stack" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando hacemos &lt;code&gt;pop()&lt;/code&gt;, el contador baja de 3 a 2 y leemos &lt;code&gt;items[2]&lt;/code&gt; que es 👻. Luego hacemos &lt;code&gt;this.items.length = 2&lt;/code&gt; para recortar el array, y listo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Un truco de los arrays en JavaScript
&lt;/h3&gt;

&lt;p&gt;Fíjate en esta línea: &lt;code&gt;this.items.length = this.count&lt;/code&gt;. Podría parecer que solo estamos "cambiando un número", pero en realidad estamos &lt;strong&gt;modificando el array&lt;/strong&gt;. En JavaScript, asignarle un valor menor a &lt;code&gt;.length&lt;/code&gt; recorta el array y elimina los elementos que sobran.&lt;/p&gt;

&lt;p&gt;Míralo por fuera de la clase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 5&lt;/span&gt;

&lt;span class="c1"&gt;// Definir la longitud&lt;/span&gt;
&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2, 3]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// undefined (los elementos extra se eliminan)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este es un detalle que muchos desarrolladores desconocen y te abre posibilidades interesantes. En nuestra clase lo usamos para asegurarnos de que el array y el contador &lt;code&gt;count&lt;/code&gt; siempre estén sincronizados.&lt;/p&gt;

&lt;p&gt;Si te fijas, no usamos los métodos &lt;code&gt;push&lt;/code&gt; y &lt;code&gt;pop&lt;/code&gt; del array nativo de JavaScript. Solo lo usamos como almacenamiento indexado. Todo el control lo lleva nuestra variable &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complejidad Big O de las operaciones
&lt;/h2&gt;

&lt;p&gt;Ya vimos qué hace cada operación. Ahora, ¿cuánto cuestan? Aquí es donde entra &lt;a href="https://www.freecodecamp.org/espanol/news/explicacion-de-la-notacion-big-o-con-ejemplo/" rel="noopener noreferrer"&gt;Big O&lt;/a&gt;, la notación que nos dice cómo crece el tiempo de una operación conforme crece el stack.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operación&lt;/th&gt;
&lt;th&gt;Complejidad en tiempo&lt;/th&gt;
&lt;th&gt;Complejidad en espacio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;push()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O(1)*&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pop()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;peek()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isEmpty()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Amortizado. Ocasionalmente O(n) cuando el array dinámico necesita crecer por debajo.&lt;/p&gt;

&lt;p&gt;Todas las operaciones de un stack son O(1). ¿Por qué? Porque siempre trabajamos con un solo elemento: el de arriba. No importa si el stack tiene 10 o 10 millones de elementos, &lt;code&gt;push&lt;/code&gt; y &lt;code&gt;pop&lt;/code&gt; tardan lo mismo.&lt;/p&gt;

&lt;p&gt;Compara esto con un array, donde insertar al inicio es O(n) porque hay que mover todos los elementos. En un stack no tenemos ese problema porque solo tocamos la punta.&lt;/p&gt;

&lt;p&gt;Esta es la razón principal por la que los stacks se usan tanto: son rápidos y predecibles. Si tu problema solo necesita trabajar con el último elemento agregado, un stack te da esa operación en tiempo constante.&lt;/p&gt;

&lt;p&gt;Eso sí, rápido no quiere decir infinito. Un stack vive en memoria, así que si crece demasiado va a depender por completo de los recursos del dispositivo donde corra. En celulares, tablets y computadoras con poca RAM esto importa más de lo que crees: un stack que crece sin control puede tronar la app. Los lenguajes hasta tienen un límite específico para el call stack, y si lo rebasas te topas con el famoso &lt;em&gt;stack overflow&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Dónde se usan los stacks en la vida real?
&lt;/h2&gt;

&lt;p&gt;Antes de ver ejemplos, quédate con esto:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Regla de oro:&lt;/strong&gt; cuando lo único que te importa es el último elemento, un stack es la respuesta.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Todo lo que viene a continuación es una variante del mismo patrón. Una vez que lo ves, empiezas a reconocer stacks en todos lados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navegador web: botón de "atrás"
&lt;/h3&gt;

&lt;p&gt;Cada vez que visitas una página nueva, el navegador hace &lt;code&gt;push()&lt;/code&gt; con la URL. Cuando presionas "atrás", hace &lt;code&gt;pop()&lt;/code&gt; y te lleva a la página anterior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3uc6zt7do2joho3d27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3uc6zt7do2joho3d27.png" alt="Historial del navegador como stack" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Funciona perfecto porque siempre quieres volver a la última página que visitaste, no a una del medio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ctrl + Z: deshacer acciones
&lt;/h3&gt;

&lt;p&gt;Cuando escribes en un editor de texto, cada acción (escribir una letra, borrar, pegar) se agrega a un stack. Cuando presionas &lt;code&gt;Ctrl + Z&lt;/code&gt;, la última acción se hace &lt;code&gt;pop()&lt;/code&gt; y se deshace. Presionas &lt;code&gt;Ctrl + Z&lt;/code&gt; otra vez y la penúltima se deshace.&lt;/p&gt;

&lt;p&gt;Mismo patrón: siempre deshaces la acción más reciente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Call stack de tu programa
&lt;/h3&gt;

&lt;p&gt;Cuando una función llama a otra, que a su vez llama a otra, tu programa va apilando cada llamada en un "call stack". Cuando una función termina, se hace &lt;code&gt;pop()&lt;/code&gt; y el control vuelve a la función anterior.&lt;/p&gt;

&lt;p&gt;Por eso cuando ves un error con "stack trace" en la consola, estás viendo exactamente eso: el estado del stack de llamadas en el momento del error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validación de paréntesis balanceados
&lt;/h3&gt;

&lt;p&gt;Un problema clásico de entrevistas. ¿Cómo verificas que en &lt;code&gt;((a + b) * (c - d))&lt;/code&gt; todos los paréntesis estén correctamente balanceados? Con un stack. Cada &lt;code&gt;(&lt;/code&gt; hace push, cada &lt;code&gt;)&lt;/code&gt; hace pop. Si al final el stack está vacío, los paréntesis están balanceados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cierre
&lt;/h2&gt;

&lt;p&gt;Los stacks son simples: cinco métodos, todos O(1), un solo principio (LIFO). Y justo por eso los encuentras en tantos lugares, desde el botón de atrás hasta el call stack de tu lenguaje de programación.&lt;/p&gt;

&lt;p&gt;Si te sirvió el artículo, dale ❤️ y sígueme para no perderte el siguiente. Nos leemos pronto. 🙌🏻&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>beginners</category>
      <category>computerscience</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Two Pointers en entrevistas técnicas: 3 problemas resueltos</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Wed, 22 Apr 2026 20:31:27 +0000</pubDate>
      <link>https://forem.com/aws/two-pointers-en-entrevistas-tecnicas-3-problemas-resueltos-324n</link>
      <guid>https://forem.com/aws/two-pointers-en-entrevistas-tecnicas-3-problemas-resueltos-324n</guid>
      <description>&lt;p&gt;Si estás preparándote para entrevistas técnicas, tarde o temprano vas a encontrarte con problemas de arrays y strings. Y varios se resuelven con una misma familia de técnicas: two pointers.&lt;/p&gt;

&lt;p&gt;En los artículos anteriores vimos &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;cómo funcionan los arrays&lt;/a&gt; y &lt;a href="https://dev.to/aws/strings-en-programacion-mas-que-un-simple-array-de-caracteres-1knd"&gt;los strings&lt;/a&gt; por debajo: memoria contigua, acceso por índice, operaciones y sus costos. Hoy toca usar todo eso para resolver problemas reales.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lo que vas a encontrar en este artículo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qué son las entrevistas técnicas y por qué te piden resolver problemas&lt;/li&gt;
&lt;li&gt;Qué es two pointers y qué técnicas incluye&lt;/li&gt;
&lt;li&gt;Cómo identificar cuál técnica usar&lt;/li&gt;
&lt;li&gt;Un problema resuelto paso a paso por cada técnica&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ¿Qué son los problemas de entrevistas técnicas?
&lt;/h2&gt;

&lt;p&gt;Son ejercicios de programación que te ponen en entrevistas para puestos de desarrollo de software. Ojo, las entrevistas técnicas existen para muchos roles (arquitectura, DevOps, SRE, developer) y no todas se ven igual. Este artículo se enfoca en las entrevistas para roles de developer.&lt;/p&gt;

&lt;p&gt;El objetivo no es que te sepas la respuesta de memoria. Lo que evalúan es cómo piensas: cómo descompones un problema, qué estructura de datos eliges y si tu solución es eficiente.&lt;/p&gt;

&lt;p&gt;Y aquí viene lo interesante: existen técnicas que se crearon específicamente para resolver estos problemas de forma óptima. No es magia, es práctica y reconocimiento de patrones.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Two Pointers?
&lt;/h2&gt;

&lt;p&gt;Two pointers es un paradigma general para resolver problemas con arrays y strings. La idea es simple: usas dos variables (los "punteros") que recorren la estructura de datos de formas específicas.&lt;/p&gt;

&lt;p&gt;Ojo, cuando digo "punteros" no me refiero a punteros de memoria como en C. Aquí son simplemente variables que guardan índices para acceder a posiciones del array o string.&lt;/p&gt;

&lt;p&gt;¿Por qué funciona? Porque con dos punteros moviéndose de forma inteligente, puedes evitar soluciones de fuerza bruta O(n²) y resolverlo en O(n). Eso es exactamente lo que buscan en una entrevista.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué técnicas incluye?
&lt;/h3&gt;

&lt;p&gt;Two pointers incluye tres variantes principales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast and slow pointers&lt;/strong&gt; (lento y rápido): un puntero explora y otro se queda marcando una posición.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opposite direction pointers&lt;/strong&gt; (punteros convergentes): empiezan en los extremos y se acercan al centro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel pointers&lt;/strong&gt; (punteros paralelos): cada puntero recorre un array diferente al mismo tiempo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo que todas tienen en común: usan al menos 2 variables para recorrer un arreglo o string, y nos ayudan a pasar de O(n²) a O(n).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Vamos a usar los nombres en inglés porque así los encuentras en la mayoría de recursos, LeetCode y entrevistas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ¿Cómo saber cuál técnica usar?
&lt;/h3&gt;

&lt;p&gt;Antes de entrar a los problemas, una guía rápida. Si en el enunciado ves algo de esto, probablemente necesitas two pointers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Te dan uno o dos arreglos/strings.&lt;/li&gt;
&lt;li&gt;Te piden espacio O(1) o modificar el array en su lugar.&lt;/li&gt;
&lt;li&gt;La solución obvia sería O(n²) pero necesitas algo mejor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora, ¿cuál variante? Aquí va un resumen:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Técnica&lt;/th&gt;
&lt;th&gt;Úsala cuando...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fast and slow&lt;/td&gt;
&lt;td&gt;Necesitas comparar o modificar elementos dentro del mismo array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opposite direction&lt;/td&gt;
&lt;td&gt;Necesitas verificar propiedades simétricas, encontrar pares, o trabajar desde los extremos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel pointers&lt;/td&gt;
&lt;td&gt;Tienes dos arrays y necesitas compararlos o fusionarlos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sé que puede parecer mucho, pero conforme resolvamos los problemas vas a ver que es más intuitivo de lo que parece. Vamos a eso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opposite direction: Verificar un palíndromo
&lt;/h2&gt;

&lt;p&gt;Empecemos con opposite direction porque es la más visual.&lt;/p&gt;

&lt;p&gt;Tomemos el problema &lt;a href="https://leetcode.com/problems/valid-palindrome/description/" rel="noopener noreferrer"&gt;"Valid Palindrome" de LeetCode&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problema:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Una frase es un palíndromo si, tras convertir todas las letras a minúsculas y eliminar los caracteres no alfanuméricos, se lee igual de izquierda a derecha que de derecha a izquierda.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dada una cadena &lt;code&gt;s&lt;/code&gt;, devuelve &lt;code&gt;true&lt;/code&gt; si es un palíndromo, o &lt;code&gt;false&lt;/code&gt; en caso contrario.&lt;/p&gt;

&lt;p&gt;
  Ejemplos
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input:  s = "A man, a plan, a canal: Panama"
Output: true
// Porque "amanaplanacanalpanama" se lee igual en ambas direcciones

Input:  s = "race a car"
Output: false
// Porque "raceacar" no es palíndromo

Input:  s = " "
Output: true
// Un string vacío se lee igual al derecho y al revés
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo lo pensamos?
&lt;/h3&gt;

&lt;p&gt;La solución de fuerza bruta sería limpiar el string, invertirlo y comparar. Funciona, pero crea strings nuevos en memoria (recuerda que los strings son inmutables, así que cada operación crea uno nuevo).&lt;/p&gt;

&lt;p&gt;Con opposite direction pointers hacemos algo más elegante: ponemos un puntero al inicio y otro al final. Los vamos acercando al centro comparando los caracteres. Si en algún momento no coinciden, no es palíndromo. Si los punteros se cruzan sin encontrar diferencias, sí lo es.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solución paso a paso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @param {string} s
 * @return {boolean}
 */&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isPalindrome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isAlphanumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isAlphanumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// función auxiliar: ¿es letra o número?&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isAlphanumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="c1"&gt;// 0-9&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="c1"&gt;// A-Z&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// a-z&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos línea por línea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;l&lt;/code&gt; arranca en &lt;code&gt;0&lt;/code&gt; (inicio del string) y &lt;code&gt;r&lt;/code&gt; en &lt;code&gt;s.length - 1&lt;/code&gt; (final). Son nuestros dos punteros que se van a acercar al centro.&lt;/li&gt;
&lt;li&gt;El &lt;code&gt;while (l &amp;lt; r)&lt;/code&gt; se ejecuta mientras los punteros no se hayan cruzado.&lt;/li&gt;
&lt;li&gt;Dentro del loop hay cuatro casos:

&lt;ul&gt;
&lt;li&gt;Si &lt;code&gt;s[l]&lt;/code&gt; no es alfanumérico (un espacio, coma, dos puntos...), lo saltamos moviendo &lt;code&gt;l&lt;/code&gt; a la derecha.&lt;/li&gt;
&lt;li&gt;Si &lt;code&gt;s[r]&lt;/code&gt; no es alfanumérico, lo saltamos moviendo &lt;code&gt;r&lt;/code&gt; a la izquierda.&lt;/li&gt;
&lt;li&gt;Si ambos son alfanuméricos pero no coinciden (comparando en minúsculas), no es palíndromo. Retornamos &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si coinciden, avanzamos ambos punteros hacia el centro (&lt;code&gt;l++&lt;/code&gt;, &lt;code&gt;r--&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Si el loop termina sin retornar &lt;code&gt;false&lt;/code&gt;, los punteros se cruzaron sin encontrar diferencias. Es palíndromo, retornamos &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La función auxiliar &lt;code&gt;isAlphanumeric&lt;/code&gt; &lt;a href="https://dev.to/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5"&gt;revisa el código ASCII del carácter&lt;/a&gt;: &lt;code&gt;48-57&lt;/code&gt; son dígitos, &lt;code&gt;65-90&lt;/code&gt; letras mayúsculas, &lt;code&gt;97-122&lt;/code&gt; letras minúsculas. Todo lo demás (espacios, puntuación, etc.) retorna &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Complejidad: O(n) en tiempo, O(1) en espacio. Un solo recorrido del string, sin crear copias ni estructuras extra.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Veamos cómo se ve con &lt;code&gt;s = "A man, a plan, a canal: Panama"&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e5tzx2idnwpgti20buy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e5tzx2idnwpgti20buy.png" alt="Paso a paso de opposite direction pointers para validar un palíndromo" width="800" height="957"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast and slow: Remove Duplicates
&lt;/h2&gt;

&lt;p&gt;Ahora veamos fast and slow con el clásico &lt;a href="https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/" rel="noopener noreferrer"&gt;"Remove Duplicates from Sorted Array" de LeetCode&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problema:&lt;/strong&gt;&lt;br&gt;
Te dan una lista de números &lt;code&gt;nums&lt;/code&gt; ya ordenada de menor a mayor, pero con algunos repetidos. Tienes que dejar cada número una sola vez, moviendo los únicos al inicio de la misma lista (sin crear otra lista nueva).&lt;br&gt;
Por ejemplo, si te dan &lt;code&gt;[1, 1, 2, 3, 3]&lt;/code&gt;, la lista debe quedar así: &lt;code&gt;[1, 2, 3, ?, ?]&lt;/code&gt;. Los primeros tres espacios tienen los números únicos en orden, y los últimos dos espacios no importan (pueden quedar con cualquier valor, por eso los marcamos con &lt;code&gt;?&lt;/code&gt;).&lt;br&gt;
Además, tu función debe devolver cuántos números únicos quedaron al inicio. En el ejemplo anterior, devolverías &lt;code&gt;3&lt;/code&gt; porque hay tres números únicos (&lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;). A ese número lo llaman &lt;code&gt;k&lt;/code&gt; en el enunciado.&lt;/p&gt;

&lt;p&gt;
  Ejemplos
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ejemplo 1

Entrada: nums = [1,1,2]
Salida: 2, nums = [1,2,_]

Explicación: Tu función debe devolver k = 2, y los primeros dos elementos de nums deben ser 1 y 2 respectivamente. No importa qué quede después de los primeros k espacios (por eso aparecen como guiones bajos).

Ejemplo 2

Entrada: nums = [0,0,1,1,1,2,2,3,3,4]
Salida: 5, nums = [0,1,2,3,4,_,_,_,_,_]

Explicación: Tu función debe devolver k = 5, y los primeros cinco elementos de nums deben ser 0, 1, 2, 3 y 4 respectivamente. No importa qué quede después de los primeros k espacios (por eso aparecen como guiones bajos).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo lo pensamos?
&lt;/h3&gt;

&lt;p&gt;La fuerza bruta sería crear un nuevo array y copiar solo los valores que no se repiten. Pero el problema dice explícitamente que lo hagas "in-place", o sea, modificando el mismo array sin crear otro. Ahí es donde entra fast and slow.&lt;/p&gt;

&lt;p&gt;La idea es esta: usamos dos punteros que arrancan casi juntos. &lt;code&gt;slow&lt;/code&gt; marca la posición donde va el siguiente número único. &lt;code&gt;fast&lt;/code&gt; se adelanta recorriendo todo el array buscando valores nuevos.&lt;/p&gt;

&lt;p&gt;Como el array ya está ordenado, los duplicados siempre están juntos. Entonces &lt;code&gt;fast&lt;/code&gt; solo necesita comparar su valor con el de &lt;code&gt;slow&lt;/code&gt;. Si son diferentes, encontramos un número nuevo: avanzamos &lt;code&gt;slow&lt;/code&gt; una posición y copiamos ahí el valor de &lt;code&gt;fast&lt;/code&gt;. Si son iguales, &lt;code&gt;fast&lt;/code&gt; simplemente sigue avanzando.&lt;/p&gt;

&lt;p&gt;Piénsalo así: &lt;code&gt;slow&lt;/code&gt; es el que construye la respuesta, y &lt;code&gt;fast&lt;/code&gt; es el explorador que le dice "oye, encontré uno nuevo".&lt;/p&gt;

&lt;h3&gt;
  
  
  Solución paso a paso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @param {number[]} nums
 * @return {number}
 */&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;removeDuplicates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;slow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;fast&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;slow&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;slow&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos línea por línea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;slow&lt;/code&gt; arranca en &lt;code&gt;0&lt;/code&gt;, apuntando al primer elemento. Ese siempre es único porque no hay nada antes con qué comparar.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fast&lt;/code&gt; arranca en &lt;code&gt;1&lt;/code&gt; y recorre el array completo con el &lt;code&gt;for&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;En cada paso, comparamos &lt;code&gt;nums[fast]&lt;/code&gt; con &lt;code&gt;nums[slow]&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Si son &lt;strong&gt;iguales&lt;/strong&gt;, es un duplicado. &lt;code&gt;fast&lt;/code&gt; avanza y &lt;code&gt;slow&lt;/code&gt; se queda donde está. No hacemos nada.&lt;/li&gt;
&lt;li&gt;Si son &lt;strong&gt;diferentes&lt;/strong&gt;, encontramos un valor nuevo. Avanzamos &lt;code&gt;slow&lt;/code&gt; una posición (&lt;code&gt;slow++&lt;/code&gt;) y copiamos el valor de &lt;code&gt;fast&lt;/code&gt; ahí (&lt;code&gt;nums[slow] = nums[fast]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Al final, &lt;code&gt;slow&lt;/code&gt; queda apuntando al último elemento único. Como los índices empiezan en &lt;code&gt;0&lt;/code&gt;, el total de únicos es &lt;code&gt;slow + 1&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Veamos cómo se ve con &lt;code&gt;nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc29qo1ge8gmobk34f4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc29qo1ge8gmobk34f4g.png" alt="Ejemplo visual de fast and slow pointers eliminando duplicados en un array ordenado" width="800" height="1560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los primeros 5 elementos son &lt;code&gt;[0, 1, 2, 3, 4]&lt;/code&gt;, exactamente los valores únicos en orden. Lo que queda después del índice 4 no importa.&lt;/p&gt;

&lt;p&gt;¿Ves el patrón? &lt;code&gt;fast&lt;/code&gt; recorre todo el array una sola vez, y &lt;code&gt;slow&lt;/code&gt; solo avanza cuando encuentra algo nuevo. Eso nos da O(n) en tiempo y O(1) en espacio, porque no creamos ninguna estructura extra.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Complejidad: O(n) en tiempo, O(1) en espacio. Un solo recorrido, sin estructuras extra.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Parallel pointers: Intersección de dos arrays
&lt;/h2&gt;

&lt;p&gt;Por último, parallel pointers con &lt;a href="https://leetcode.com/problems/intersection-of-two-arrays/description/" rel="noopener noreferrer"&gt;"Intersection of Two Arrays" de LeetCode&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problema:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Dados dos arreglos de enteros, devuelve un arreglo con su intersección. Cada elemento del resultado debe ser único y puede estar en cualquier orden.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
  Ejemplos
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input:  nums1 = [1, 2, 2, 1], nums2 = [2, 2]
Output: [2]

Input:  nums1 = [4, 9, 5], nums2 = [9, 4, 9, 8, 4]
Output: [9, 4]  // el orden no importa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo lo pensamos?
&lt;/h3&gt;

&lt;p&gt;La fuerza bruta sería usar dos loops anidados: por cada elemento de &lt;code&gt;nums1&lt;/code&gt;, recorrer todo &lt;code&gt;nums2&lt;/code&gt; buscando coincidencias.&lt;/p&gt;

&lt;p&gt;Con parallel pointers hacemos algo más inteligente: primero ordenamos ambos arrays y después los recorremos una sola vez con dos punteros. Como están ordenados, podemos comparar los valores y decidir cuál puntero mover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si los valores son iguales, encontramos una intersección. Avanzamos ambos.&lt;/li&gt;
&lt;li&gt;Si el valor de &lt;code&gt;p1&lt;/code&gt; es menor, lo avanzamos porque no puede haber coincidencia más atrás en &lt;code&gt;nums2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si el valor de &lt;code&gt;p2&lt;/code&gt; es menor, lo avanzamos por la misma razón.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es como hacer merge de dos listas ordenadas, pero solo nos quedamos con los valores que aparecen en ambas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solución paso a paso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;intersection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// ordenar arreglos&lt;/span&gt;
  &lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intersection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Evita duplicados en el resultado&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos línea por línea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ordenamos ambos arrays con &lt;code&gt;.sort()&lt;/code&gt;. Esto es clave: sin el orden, no podríamos saber hacia dónde mover los punteros.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p1&lt;/code&gt; y &lt;code&gt;p2&lt;/code&gt; arrancan en &lt;code&gt;0&lt;/code&gt;, cada uno apuntando al inicio de su array.&lt;/li&gt;
&lt;li&gt;El &lt;code&gt;while&lt;/code&gt; se ejecuta mientras ambos punteros estén dentro de sus arrays.&lt;/li&gt;
&lt;li&gt;Dentro del loop hay tres casos:

&lt;ul&gt;
&lt;li&gt;Si &lt;code&gt;nums1[p1] === nums2[p2]&lt;/code&gt;, encontramos un valor en común. Antes de agregarlo, verificamos que no sea un duplicado (comparando con el último elemento del resultado). Avanzamos ambos punteros.&lt;/li&gt;
&lt;li&gt;Si &lt;code&gt;nums1[p1] &amp;lt; nums2[p2]&lt;/code&gt;, el valor de &lt;code&gt;p1&lt;/code&gt; es más chico. Como ambos arrays están ordenados, ese valor no puede existir más adelante en &lt;code&gt;nums2&lt;/code&gt;. Avanzamos &lt;code&gt;p1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si &lt;code&gt;nums1[p1] &amp;gt; nums2[p2]&lt;/code&gt;, misma lógica pero al revés. Avanzamos &lt;code&gt;p2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cuando alguno de los dos punteros llega al final de su array, el loop termina. Ya no puede haber más intersecciones.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Veamos con &lt;code&gt;nums1 = [4, 9, 5]&lt;/code&gt;, &lt;code&gt;nums2 = [9, 4, 9, 8, 4]&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbm7ndbv01ljj53pjttd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbm7ndbv01ljj53pjttd.png" alt="Ejemplo de parallel pointers encontrando la intersección de dos arrays" width="800" height="1362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Ves cómo cada puntero solo avanza hacia adelante? Nunca retroceden. El recorrido en sí es O(n + m), pero el ordenamiento inicial domina: O(n log n + m log m) en total.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Complejidad: O(n log n + m log m) en tiempo por el ordenamiento. O(n) en espacio para el resultado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Resumen
&lt;/h2&gt;

&lt;p&gt;Estas tres técnicas son variantes de un mismo concepto: usar dos punteros para recorrer arrays o strings de forma eficiente.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Técnica&lt;/th&gt;
&lt;th&gt;Movimiento de punteros&lt;/th&gt;
&lt;th&gt;Problema resuelto&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Opposite direction&lt;/td&gt;
&lt;td&gt;De los extremos al centro&lt;/td&gt;
&lt;td&gt;Valid Palindrome&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast and slow&lt;/td&gt;
&lt;td&gt;Uno explora, otro referencia&lt;/td&gt;
&lt;td&gt;Remove Duplicates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel pointers&lt;/td&gt;
&lt;td&gt;Cada uno en su array&lt;/td&gt;
&lt;td&gt;Intersection of Two Arrays&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzino3kb155ixt357afde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzino3kb155ixt357afde.png" alt="Árbol de decisión para elegir la variante de two pointers" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La clave no es memorizar las soluciones. Es reconocer el patrón en el enunciado y saber qué técnica aplicar. Con práctica, vas a leer un problema y saber qué variante de two pointers usar antes de escribir una línea de código.&lt;/p&gt;

&lt;p&gt;Si quieres seguir practicando, aquí te dejo más problemas de LeetCode:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/valid-anagram/description/" rel="noopener noreferrer"&gt;Valid Anagram&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/explore/learn/card/fun-with-arrays/527/searching-for-items-in-an-array/3250/" rel="noopener noreferrer"&gt;Check If N and Its Double Exist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/explore/learn/card/fun-with-arrays/511/searching-for-items-in-an-array/3157/" rel="noopener noreferrer"&gt;Move Zeroes&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¿Cuál técnica te costó más entender? ¿Hay algún problema que quieras que resolvamos juntos? Déjamelo en los comentarios. 🙌🏻&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>algorithms</category>
      <category>beginners</category>
      <category>spanish</category>
    </item>
    <item>
      <title>No olvides revisar estos consejos para disminuir la probabilidad de infectar tu computadora con un troyano al instalar un paquete de npm.</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Thu, 16 Apr 2026 18:03:35 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/no-olvides-revisar-estos-consejos-para-disminuir-la-probabilidad-de-infectar-tu-computadora-con-un-2k6h</link>
      <guid>https://forem.com/fromchiapasdev/no-olvides-revisar-estos-consejos-para-disminuir-la-probabilidad-de-infectar-tu-computadora-con-un-2k6h</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea" class="crayons-story__hidden-navigation-link"&gt;npm install puede infectar tu máquina: cómo protegerte&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/fromchiapasdev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186583%2F9cef57b1-206b-4316-9880-0fe5907f987f.jpeg" alt="fromchiapasdev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/fromchiapasdev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Axel Espinosa
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Axel Espinosa
                
              
              &lt;div id="story-author-preview-content-3452405" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/fromchiapasdev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186583%2F9cef57b1-206b-4316-9880-0fe5907f987f.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Axel Espinosa&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 4&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea" id="article-link-3452405"&gt;
          npm install puede infectar tu máquina: cómo protegerte
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/security"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;security&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/npm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;npm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>🙌🏻</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Wed, 15 Apr 2026 16:25:01 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/-2ai7</link>
      <guid>https://forem.com/fromchiapasdev/-2ai7</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/aws/como-crear-un-agente-de-ia-desde-cero-open-source-local-y-gratis-k6d" class="crayons-story__hidden-navigation-link"&gt;Cómo crear un agente de IA desde cero. Open source, local y gratis.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/aws"&gt;
            &lt;img alt="AWS logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1726%2F2a73f1e6-7995-4348-ae37-44b064274c59.png" class="crayons-logo__image" width="320" height="320"&gt;
          &lt;/a&gt;

          &lt;a href="/hsaenzg" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F852908%2Fa3a10986-307b-4a35-8adf-eeb9a583e6a9.jpg" alt="hsaenzg profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hsaenzg" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Hazel Saenz
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Hazel Saenz
                
              
              &lt;div id="story-author-preview-content-3506071" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/hsaenzg" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F852908%2Fa3a10986-307b-4a35-8adf-eeb9a583e6a9.jpg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Hazel Saenz&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/aws" class="crayons-story__secondary fw-medium"&gt;AWS&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/aws/como-crear-un-agente-de-ia-desde-cero-open-source-local-y-gratis-k6d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 15&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/aws/como-crear-un-agente-de-ia-desde-cero-open-source-local-y-gratis-k6d" id="article-link-3506071"&gt;
          Cómo crear un agente de IA desde cero. Open source, local y gratis.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/aws/como-crear-un-agente-de-ia-desde-cero-open-source-local-y-gratis-k6d" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/aws/como-crear-un-agente-de-ia-desde-cero-open-source-local-y-gratis-k6d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            14 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>¿Qué es un String y para qué sirven?</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Mon, 13 Apr 2026 21:19:53 +0000</pubDate>
      <link>https://forem.com/aws/strings-en-programacion-mas-que-un-simple-array-de-caracteres-1knd</link>
      <guid>https://forem.com/aws/strings-en-programacion-mas-que-un-simple-array-de-caracteres-1knd</guid>
      <description>&lt;p&gt;Los strings son probablemente la estructura de datos que más usas sin pensar. Pero, ¿sabes cómo se almacenan en memoria? ¿Por qué no puedes modificarlos directamente? ¿Cuánto cuesta concatenarlos en un loop?&lt;/p&gt;

&lt;p&gt;En el &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;artículo anterior&lt;/a&gt; vimos cómo funcionan los arrays por debajo: memoria contigua, acceso por índice, operaciones y sus costos. Si aún no lo has leído, te recomiendo empezar por ahí. Hoy toca hablar de sus primos: los strings.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En estos ejemplos usaremos JavaScript como lenguaje principal. Si usas otro lenguaje, te invito a buscar los métodos equivalentes. Los conceptos son los mismos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que encontrarás en este artículo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qué es un string y cómo se almacena en memoria&lt;/li&gt;
&lt;li&gt;Qué significa que sean inmutables&lt;/li&gt;
&lt;li&gt;En qué se parecen y en qué se diferencian de los arrays&lt;/li&gt;
&lt;li&gt;Operaciones comunes con strings y cuánto cuestan (Big O)&lt;/li&gt;
&lt;li&gt;Una tabla de complejidad para que la tengas de referencia&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. ¿Qué es un string?
&lt;/h2&gt;

&lt;p&gt;Un string (o cadena de caracteres) es una secuencia de caracteres almacenados de forma contigua en memoria. Suena familiar, ¿verdad? Es básicamente lo que vimos con los &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;arrays&lt;/a&gt;, pero en lugar de números o emojis, almacenamos caracteres.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Índice:    0   1   2   3   4
         ┌───┬───┬───┬───┬───┐
String:  │ H │ o │ l │ a │ ! │
         └───┴───┴───┴───┴───┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para empezar, puedes pensar en un string como un array de caracteres — es un buen modelo mental. Más adelante verás que los motores modernos implementan strings con estructuras más sofisticadas, pero conceptualmente esta idea te va a servir para entender cómo se comportan.&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle: ¿qué es realmente un "carácter" para la computadora? No es una letra. Es un número. La "H" es el 72, la "o" es el 111. Cada carácter tiene un código numérico asignado por un estándar (como ASCII o Unicode), y un encoding (como UTF-8) convierte ese código a bits. Así que cuando digo "array de caracteres", por debajo es un array de números.&lt;/p&gt;

&lt;p&gt;Si quieres entender a fondo cómo funciona eso, lo cubrimos en el &lt;a href="https://dev.to/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5"&gt;artículo de encodings&lt;/a&gt;. Ahí explicamos por qué un emoji ocupa 4 bytes y una letra solo 1. 😉&lt;/p&gt;

&lt;p&gt;Cada carácter ocupa una posición y tiene un índice, exactamente como en un array. Y al igual que con los &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;arrays&lt;/a&gt;, acceder a un carácter por su índice es instantáneo: O(1).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saludo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saludo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "H"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saludo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Una advertencia importante:&lt;/strong&gt; este modelo funciona perfectamente con caracteres del alfabeto latino básico, pero se complica con emojis y algunos caracteres especiales. En JavaScript, un emoji como 😀 ocupa &lt;strong&gt;dos posiciones&lt;/strong&gt; en el string, no una:&lt;/p&gt;


&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;😀&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2, no 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Esto es por cómo JavaScript representa internamente el texto (UTF-16). Lo vemos a detalle en el &lt;a href="https://dev.to/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5"&gt;artículo de encodings&lt;/a&gt;. Por ahora, si trabajas con caracteres simples, el modelo de "array de caracteres" te sirve bien.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. ¿Por qué los strings son inmutables?
&lt;/h2&gt;

&lt;p&gt;Porque una vez que creas un string, su contenido no puede cambiar. Si necesitas una versión diferente, se crea uno nuevo en memoria. Esto aplica en JavaScript, Python y la mayoría de lenguajes modernos. Aquí es donde los strings empiezan a diferenciarse de los arrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué significa inmutable?
&lt;/h3&gt;

&lt;p&gt;Inmutable quiere decir que algo no puede cambiar después de creado. En programación, cuando decimos que un valor es inmutable, significa que no puedes modificar su contenido directamente. Si necesitas una versión diferente, tienes que crear una nueva.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué pasa cuando modificas un string?
&lt;/h3&gt;

&lt;p&gt;En lenguajes como JavaScript y Python, los strings son inmutables. Esto quiere decir que cuando "modificas" un string, en realidad se está creando uno nuevo en memoria. El original no se toca.&lt;/p&gt;

&lt;p&gt;Veamos un ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;palabra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;palabra&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;J&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Intentamos cambiar la "H" por "J"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;palabra&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hola" — no cambió nada&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Ves? JavaScript simplemente ignora el intento. No lanza un error, pero tampoco hace el cambio.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si tu código está en strict mode (lo cual pasa automáticamente dentro de módulos ES y clases), este intento sí lanza un &lt;code&gt;TypeError&lt;/code&gt;. Es el comportamiento más común en código moderno.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En Python es más explícito:&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="n"&gt;palabra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hola&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;palabra&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;J&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# TypeError: 'str' object does not support item assignment
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python directamente te dice: "no puedes hacer eso".&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuánto cuesta concatenar strings?
&lt;/h3&gt;

&lt;p&gt;Cuando concatenas strings con &lt;code&gt;+=&lt;/code&gt;, no estás "agregando" al final como harías con &lt;code&gt;push()&lt;/code&gt; en un array. Conceptualmente, se crea un string nuevo que contiene todo el contenido anterior más lo que agregaste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Se crea un nuevo string "Hola"&lt;/span&gt;
&lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Se crea un nuevo string "Hola "&lt;/span&gt;
&lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mundo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Se crea un nuevo string "Hola Mundo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Construir un string de tamaño N con concatenaciones repetidas tiene un costo total de O(N) — el tamaño del resultado final.&lt;/p&gt;

&lt;p&gt;Los motores de JavaScript modernos optimizan este caso con estructuras internas que evitan copiar el string completo en cada paso, así que en la práctica &lt;code&gt;+=&lt;/code&gt; en un loop es bastante eficiente. Pero la regla general sigue siendo útil: si vas a construir texto pieza por pieza, piensa en el tamaño del resultado final, no solo en cuántas piezas tienes.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. ¿Cuál es la diferencia entre strings y arrays?
&lt;/h2&gt;

&lt;p&gt;Ambos son secuencias contiguas con acceso por índice O(1), pero los arrays son mutables y los strings no. Esa diferencia cambia todo: los arrays tienen &lt;code&gt;push&lt;/code&gt; y &lt;code&gt;pop&lt;/code&gt;, los strings tienen métodos de texto como &lt;code&gt;slice&lt;/code&gt;, &lt;code&gt;split&lt;/code&gt; y &lt;code&gt;replace&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Primos, no gemelos. Los arrays te permiten modificar su contenido directamente: cambiar un elemento por índice, agregar al final, quitar del inicio. Los strings no. Son inmutables, así que no puedes hacer &lt;code&gt;push&lt;/code&gt; o &lt;code&gt;pop&lt;/code&gt; sobre un string.&lt;/p&gt;

&lt;p&gt;Lo que sí tienen los strings son métodos especializados para operaciones comunes con texto: buscar, acortar, dividir, reemplazar. Implementar estos métodos de strings manualmente sería tedioso (y propenso a errores). Por eso los lenguajes nos dan estos métodos listos para usar.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Array (dinámico)&lt;/th&gt;
&lt;th&gt;String&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Secuencia contigua&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acceso por índice&lt;/td&gt;
&lt;td&gt;✅ O(1)&lt;/td&gt;
&lt;td&gt;✅ O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutable&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push / pop&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Métodos de texto&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (search, slice, split, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redimensionable&lt;/td&gt;
&lt;td&gt;✅ (crece automáticamente)&lt;/td&gt;
&lt;td&gt;❌ (se crea uno nuevo)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  4. Operaciones comunes con strings y su complejidad
&lt;/h2&gt;

&lt;p&gt;Vamos a las operaciones que más vas a usar con strings. Cada una con un ejemplo en JavaScript y su complejidad.&lt;/p&gt;

&lt;h3&gt;
  
  
  Obtener longitud
&lt;/h3&gt;

&lt;p&gt;Igual que con los arrays, podemos saber cuántos caracteres tiene un string con &lt;code&gt;.length&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;texto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola Mundo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(1)&lt;/strong&gt; — el acceso es inmediato&lt;/p&gt;

&lt;h3&gt;
  
  
  Acceso por índice
&lt;/h3&gt;

&lt;p&gt;Ya lo vimos, pero vale la pena repetirlo: puedes acceder a cualquier carácter directamente por su posición.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;texto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "J"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "S"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(1)&lt;/strong&gt; — acceso directo, como el elevador del artículo de arrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  Buscar dentro de un string
&lt;/h3&gt;

&lt;p&gt;Podemos verificar si un string contiene cierto texto con &lt;code&gt;includes()&lt;/code&gt;, o encontrar la posición exacta con &lt;code&gt;indexOf()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Los arrays son geniales&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrays&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrays&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// -1 (no lo encontró)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(n·m) en el peor caso&lt;/strong&gt; — donde &lt;code&gt;n&lt;/code&gt; es la longitud del string y &lt;code&gt;m&lt;/code&gt; la longitud del texto que buscas. En la práctica, los motores modernos usan algoritmos de búsqueda optimizados que son mucho más rápidos en la mayoría de los casos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extraer una porción (slice / substring)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;slice()&lt;/code&gt; te permite extraer una parte del string sin modificar el original (recuerda: inmutabilidad).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;texto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "Java"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "Script"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// string original&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(n) en el peor caso&lt;/strong&gt; — donde &lt;code&gt;n&lt;/code&gt; es el tamaño de la porción extraída. Algunos motores optimizan esta operación para evitar copiar cuando es posible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dividir un string (split)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;split()&lt;/code&gt; divide un string en un array de substrings usando un separador.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nombre,edad,ciudad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;campos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;campos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ["nombre", "edad", "ciudad"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(n)&lt;/strong&gt; — recorre todo el string para encontrar los separadores y crear los substrings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concatenar strings
&lt;/h3&gt;

&lt;p&gt;Ya hablamos de esto, pero aquí va el resumen con código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saludo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; Mundo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saludo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hola Mundo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complejidad: O(n)&lt;/strong&gt; — donde &lt;code&gt;n&lt;/code&gt; es el tamaño del resultado final. Recuerda que los motores modernos optimizan esta operación por debajo.&lt;/p&gt;

&lt;p&gt;Si quieres explorar todos los métodos de strings disponibles en JavaScript, la &lt;a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String" rel="noopener noreferrer"&gt;referencia de String en MDN&lt;/a&gt; es un excelente recurso.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. ¿Cuál es la complejidad Big O de las operaciones con strings?
&lt;/h2&gt;

&lt;p&gt;Aquí te dejo la tabla de complejidad, en el mismo formato que usamos en el artículo de arrays para que puedas compararlas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operación&lt;/th&gt;
&lt;th&gt;Complejidad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Acceso por índice&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Obtener longitud&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buscar un substring&lt;/td&gt;
&lt;td&gt;O(n·m)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concatenar (resultado total)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slice / Substring&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Split&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; las complejidades de búsqueda y concatenación representan el &lt;strong&gt;peor caso&lt;/strong&gt;. Los motores modernos de JavaScript implementan optimizaciones que hacen que en la práctica sean más rápidas de lo que sugiere la teoría.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compara esta tabla con la del &lt;a href="https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf"&gt;artículo de arrays&lt;/a&gt;. Vas a notar que el acceso por índice es igual de rápido en ambos. La diferencia está en que los strings no tienen operaciones como &lt;code&gt;push&lt;/code&gt; o &lt;code&gt;pop&lt;/code&gt; porque son inmutables. Cada vez que necesitas un string "modificado", estás pagando el costo de crear uno nuevo.&lt;/p&gt;

&lt;p&gt;Algo importante: en esta tabla y a lo largo del artículo usamos Big O para describir el costo de las operaciones. Big O es una notación que nos dice cómo crece el tiempo de una operación conforme crece el tamaño de la entrada. O(1) significa tiempo constante (siempre tarda lo mismo sin importar el tamaño), y O(n) significa tiempo lineal (entre más grande la entrada, más tarda, proporcionalmente).&lt;/p&gt;

&lt;p&gt;No es el foco de este artículo, pero es importante que tengas el contexto. Si quieres que hagamos un artículo dedicado a Big O, dime en los comentarios.&lt;/p&gt;

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

&lt;p&gt;Los strings son como los primos de los arrays: comparten la misma base (secuencia contigua, acceso por índice) pero juegan con reglas diferentes gracias a la inmutabilidad. Eso los hace predecibles y seguros, pero también significa que operaciones que parecen simples, como concatenar en un loop, pueden ser más costosas de lo que esperabas.&lt;/p&gt;

&lt;p&gt;Si leíste con atención, quizá notaste que dije varias veces "en el peor caso". Eso es porque los motores de JavaScript modernos hacen optimizaciones que a veces rompen el modelo mental simple que vimos aquí.&lt;/p&gt;

&lt;p&gt;En el siguiente artículo de la serie vamos a poner en práctica todo lo que hemos visto de arrays y strings con problemas y patrones comunes de entrevistas técnicas. Ahí es donde todo se conecta. 💪&lt;/p&gt;

&lt;p&gt;Si quieres avanzar con el siguiente tema intenta resolver esto: &lt;em&gt;dado un string, ¿cómo lo invertirías sin usar &lt;code&gt;.reverse()&lt;/code&gt;? Piensa en lo que vimos de inmutabilidad&lt;/em&gt;. En el siguiente artículo vamos a resolver este tipo de problemas.&lt;/p&gt;

&lt;p&gt;Gracias por llegar hasta el final. Estaré pendiente de tus comentarios 🙌🏻&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>algorithms</category>
      <category>beginners</category>
      <category>español</category>
    </item>
    <item>
      <title>npm install puede infectar tu máquina: cómo protegerte</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Sat, 04 Apr 2026 05:57:09 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea</link>
      <guid>https://forem.com/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea</guid>
      <description>&lt;p&gt;Haces &lt;code&gt;npm install&lt;/code&gt;, confías en que todo está bien, y sin saberlo un script malicioso ya se ejecutó en tu máquina. Así funcionan los ataques de supply chain en npm: infectan paquetes populares (o sus dependencias) y usan los lifecycle scripts para correr código antes de que te des cuenta.&lt;/p&gt;

&lt;p&gt;Este tipo de ataque se viene hablando desde el 2022 pero los atacantes lo han utilizado con mayor frecuencia debido al alcance que logran tener en el ecosistema de npm. Un ejemplo reciente: &lt;a href="https://www.microsoft.com/en-us/security/blog/2025/12/09/shai-hulud-2-0-guidance-for-detecting-investigating-and-defending-against-the-supply-chain-attack/" rel="noopener noreferrer"&gt;Shai Hulud&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En este post te explico cómo funcionan estos ataques y qué configuraciones puedes aplicar hoy para proteger tus proyectos.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un "supply chain attack" o ataque a la cadena de suministro?
&lt;/h2&gt;

&lt;p&gt;Este tipo de ataque se caracteriza por infectar alguna parte del ciclo de entrega del software.&lt;br&gt;
Muchos proyectos tienen este ciclo de vida:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Escribir el código&lt;/li&gt;
&lt;li&gt;Instalar paquetes&lt;/li&gt;
&lt;li&gt;Mandar a un ambiente de CI/CD&lt;/li&gt;
&lt;li&gt;Enviar proyecto a producción&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Los ataques de supply chain se insertan en uno de estos pasos comprometiendo toda la cadena de pasos siguientes.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo se infecta una librería?
&lt;/h2&gt;

&lt;p&gt;Los atacantes no siempre comprometen el paquete popular directamente. Muchas veces infectan una dependencia interna de ese paquete.&lt;/p&gt;

&lt;p&gt;Tu al instalar el paquete popular, sin saberlo estás instalando también el código de la dependencia infectada.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo funcionan los lifecycle scripts en npm?
&lt;/h2&gt;

&lt;p&gt;Los ataques recientes han utilizado una funcionalidad del gestor de paquetes de npm: la capacidad de ejecutar scripts antes o después de la instalación de un paquete.&lt;/p&gt;

&lt;p&gt;A esto se le llaman "lifecycle scripts". Muchos paquetes los usan de manera legítima para preparar pasos previos a la instalación, como la compilación de paquetes nativos. Aunque la documentación de npm recomienda evitarlos, algunos paquetes los necesitan, y es precisamente esa característica la que los paquetes infectados utilizan.&lt;/p&gt;

&lt;p&gt;Como esto es un proceso que sucede antes de que se instale el paquete, nosotros no nos percatamos de lo que se ejecuta. Los paquetes con malware ejecutan todos los pasos que necesitan para infectar tu equipo, robar información y después dejar todo limpio como si nada hubiera pasado. Eso es lo más crítico.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo proteger tu proyecto de paquetes maliciosos en npm?
&lt;/h2&gt;

&lt;p&gt;Hay varias medidas que podemos tomar. Vamos una por una.&lt;/p&gt;
&lt;h3&gt;
  
  
  No actualices versiones a lo loco
&lt;/h3&gt;

&lt;p&gt;Es muy común utilizar herramientas como &lt;a href="https://www.npmjs.com/package/npm-check-updates" rel="noopener noreferrer"&gt;npm-check-updates&lt;/a&gt; para actualizar dependencias automáticamente. Siempre queremos tener lo último y pensamos que eso es lo correcto, pero realmente introducimos un vector de ataque.&lt;/p&gt;

&lt;p&gt;La última versión puede traer malware. Mejor revisa qué se publicó, qué cambió en el changelog y si hay reportes antes de actualizar.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bloquea los lifecycle scripts
&lt;/h3&gt;

&lt;p&gt;Como vimos, es por estos scripts que muchos de los ataques suceden. Podemos desactivarlos al instalar una dependencia.&lt;/p&gt;

&lt;p&gt;De manera individual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt; &amp;lt;pkg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De manera global:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ignore-scripts &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O por proyecto con el archivo &lt;code&gt;.npmrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto se agregó en la versión v11 de npm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloquea instalaciones desde Git
&lt;/h3&gt;

&lt;p&gt;Adicional a esto necesitas configurar el flag de &lt;code&gt;allow-git&lt;/code&gt; para evitar que se instalen paquetes desde algún repositorio de Git en vez del registro de npm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt; &lt;span class="nt"&gt;--allow-git&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# global&lt;/span&gt;
npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; allow-git none

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;allow-git&lt;span class="o"&gt;=&lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fija la versión de tus dependencias
&lt;/h3&gt;

&lt;p&gt;Algo que yo particularmente no sabía es que fijar las versiones es una buena práctica. Estamos acostumbrados a instalar con &lt;code&gt;npm install&lt;/code&gt; y asumir que el símbolo &lt;code&gt;^&lt;/code&gt; al inicio de la versión en &lt;code&gt;package.json&lt;/code&gt; está bien.&lt;/p&gt;

&lt;p&gt;Pero ese &lt;code&gt;^&lt;/code&gt; significa que al actualizar puedes descargar cualquier versión del paquete que no haga un salto de major version (el primer número). Es decir, si tienes la versión &lt;code&gt;1.x.x&lt;/code&gt;, npm puede instalar cualquier &lt;code&gt;1.y.z&lt;/code&gt; sin preguntarte.&lt;/p&gt;

&lt;p&gt;Para fijar la versión exacta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# global&lt;/span&gt;
npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; save-exact &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
save-exact&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  No instales la versión más reciente
&lt;/h3&gt;

&lt;p&gt;Otra precaución: evita instalar el paquete más reciente que existe. Esto puede pasar cuando haces un &lt;code&gt;npm update&lt;/code&gt; o instalas el paquete por primera vez.&lt;/p&gt;

&lt;p&gt;Muchos de los infectados en los ataques fue porque se publicó una versión nueva y muchas personas la instalaron de inmediato. Al paso de unas horas los contribuidores del paquete se dieron cuenta de que el paquete había sido comprometido.&lt;/p&gt;

&lt;p&gt;Para evitar esto existe &lt;code&gt;min-release-age&lt;/code&gt;: configuras cuánto tiempo debe haber pasado desde que se publicó un paquete para que npm lo instale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--min-release-age&lt;/span&gt; 3 &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
min-release-age&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="c"&gt;# 3 dias (npm usa días)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta configuración está disponible a partir de la versión v11 de npm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tu &lt;code&gt;.npmrc&lt;/code&gt; defensivo mínimo
&lt;/h3&gt;

&lt;p&gt;Así queda el &lt;code&gt;.npmrc&lt;/code&gt; mínimo para tus proyectos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;save-exact&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;min-release-age&lt;span class="o"&gt;=&lt;/span&gt;3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y en CI, siempre &lt;code&gt;npm ci --ignore-scripts&lt;/code&gt;, nunca &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerar pnpm
&lt;/h2&gt;

&lt;p&gt;pnpm es una alternativa a npm que bloquea los lifecycle scripts por defecto. Personalmente lo estoy usando para mis proyectos porque reduce el consumo de espacio (optimiza los &lt;code&gt;node_modules&lt;/code&gt;) y porque trae estas protecciones incluidas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloqueo de dependencias y builds
&lt;/h3&gt;

&lt;p&gt;Por defecto, pnpm bloquea los scripts de pre/post instalación. Si algún paquete legítimo los necesita (como &lt;code&gt;esbuild&lt;/code&gt; o &lt;code&gt;next&lt;/code&gt;), puedes permitirlo explícitamente en el &lt;code&gt;pnpm-workspace.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Permitir dependencias que sí pueden usar los lifecycle scripts (pnpm 10+)&lt;/span&gt;
&lt;span class="na"&gt;allowBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;esbuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;strictDepBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Muestra error si alguna dependencia no listada hace uso de lifecycle scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tiempo de antigüedad
&lt;/h3&gt;

&lt;p&gt;Como en npm, puedes configurar el tiempo mínimo que debe haber pasado para instalar un paquete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;allowBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;esbuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;strictDepBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;minimumReleaseAge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1440&lt;/span&gt; &lt;span class="c1"&gt;# mínimo 24 hrs (pnpm usa minutos)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Snyk recomienda que usemos al menos 21 días como periodo para instalar una nueva dependencia.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo funciona &lt;code&gt;trustPolicy&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;pnpm asigna un &lt;strong&gt;nivel de confianza&lt;/strong&gt; a cada versión publicada de un paquete, basado en cómo fue publicada. Los niveles de mayor a menor son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trusted Publisher&lt;/strong&gt;: publicado vía GitHub Actions con OIDC (el CI firma criptográficamente que el paquete viene de un workflow específico en un repo específico)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance&lt;/strong&gt;: tiene una prueba verificable de npm que confirma dónde y cómo se construyó el paquete&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signatures&lt;/strong&gt;: tiene firma del registry de npm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sin evidencia&lt;/strong&gt;: publicado sin ninguna señal de confianza&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si configuras &lt;code&gt;trustPolicy: no-downgrade&lt;/code&gt;, pnpm compara el nivel de confianza de la versión que vas a instalar con el de versiones anteriores del mismo paquete. Si la confianza baja (por ejemplo, un paquete que siempre se publicó desde CI de repente aparece publicado sin ninguna evidencia), pnpm aborta la instalación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Revisar antes de instalar
&lt;/h2&gt;

&lt;p&gt;No instales paquetes de manera ciega. Existen herramientas que te ayudan a revisarlos antes.&lt;/p&gt;

&lt;h3&gt;
  
  
  npq
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/lirantal/npq" rel="noopener noreferrer"&gt;npq&lt;/a&gt; te ayuda a revisar lo que piensas instalar antes de siquiera instalarlo. Te advierte de posibles vulnerabilidades.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx npq &lt;span class="nb"&gt;install &lt;/span&gt;express &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir de lo que veas puedes decidir si instalas la última versión o te esperas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Socket Firewall
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://socket.dev/blog/introducing-socket-firewall" rel="noopener noreferrer"&gt;Socket Firewall&lt;/a&gt; es similar a npq pero además te permite usarlo con el manejador de paquetes de Python (uv). Personalmente no lo he utilizado, pero lo mencionan en las buenas prácticas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Medidas adicionales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evitar el uso de .env con información sensible
&lt;/h3&gt;

&lt;p&gt;No tengas tus claves de producción, tokens o lo que sea importante en tu &lt;code&gt;.env&lt;/code&gt; de manera plana como solíamos hacerlo. Si bien no subimos esta información a GitHub, en los ataques de supply chain los paquetes maliciosos tienen acceso al entorno donde se ejecutan. Esto quiere decir: tus accesos están expuestos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nodejs-security.com/blog/do-not-use-secrets-in-environment-variables-and-here-is-how-to-do-it-better" rel="noopener noreferrer"&gt;Una alternativa es usar secretos. En su blog, Liran te explica cómo hacerlo.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usa devcontainers
&lt;/h3&gt;

&lt;p&gt;Personalmente ya sabía que existían pero no suelo trabajar con ellos. En las &lt;a href="https://github.com/lirantal/npm-security-best-practices?tab=readme-ov-file#8-work-in-dev-containers" rel="noopener noreferrer"&gt;buenas prácticas de seguridad de Node.js mencionan&lt;/a&gt; la opción de usarlos para aislar los ataques y reducir el área de ataque a únicamente ese contenedor.&lt;/p&gt;

&lt;p&gt;Si te gustaría un tutorial, déjame un comentario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifica tu ambiente
&lt;/h3&gt;

&lt;p&gt;Para verificar si tu ambiente ya bloquea los pre/post scripts puedes probar &lt;a href="https://www.npmjs.com/package/@lavamoat/preinstall-always-fail" rel="noopener noreferrer"&gt;este paquete creado específicamente para eso&lt;/a&gt;. Si la instalación falla, significa que tus protecciones están funcionando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm &lt;span class="nb"&gt;install&lt;/span&gt; @lavamoat/preinstall-always-fail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  No estamos 100% seguros
&lt;/h2&gt;

&lt;p&gt;Con estas prácticas reducimos el área de ataque, pero lo importante es mantenernos atentos a las noticias de seguridad y reducir el número de paquetes instalados si es posible.&lt;/p&gt;

&lt;p&gt;Entre menos paquetes tengas, menos área de ataque y menos dependencias que vigilar. JavaScript ha evolucionado tanto que muchas cosas que antes necesitaban una librería hoy son triviales de hacer de forma nativa, o la librería estándar de Node.js ya las incluye.&lt;/p&gt;

&lt;p&gt;Con un &lt;code&gt;.npmrc&lt;/code&gt; bien configurado ya reduces la mayoría de los vectores de ataque. Recuerda revisar tus paquetes con npq o algún otra herramienta antes de instalarlos.&lt;/p&gt;

&lt;p&gt;¿Ya tenías alguna de estas configuraciones? ¿Usas alguna otra medida? ¿Hay algo que no sea correcto? Deja tus comentarios.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: no soy experto en seguridad. Esto es información recopilada para mi propio uso y para ayudar a los demás.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>security</category>
      <category>npm</category>
      <category>node</category>
    </item>
    <item>
      <title>npm install tips para la seguridad</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 31 Mar 2026 19:10:23 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/npm-install-tips-para-la-seguridad-3lm9</link>
      <guid>https://forem.com/fromchiapasdev/npm-install-tips-para-la-seguridad-3lm9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Actualización: Escribí un &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea"&gt;artículo&lt;/a&gt; sobre lo minimo que debes hacer para protegerte&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwcvjhlyzj5i6k9tj5rj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwcvjhlyzj5i6k9tj5rj.gif" alt="Gif espantado por el ataque de NPM hoy" width="334" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Hay un nuevo ataque en el ecosistema de npm y con esto crece la duda de cómo prevenir infectarse.&lt;/p&gt;

&lt;p&gt;Compartamos los mejores consejos para evitar infectarse en los comentarios para mantenernos seguros.&lt;/p&gt;

&lt;p&gt;Empiezo ⬇️&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>npm</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>¿Qué son los arrays y para qué sirven? Explicación sencilla</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Fri, 20 Mar 2026 18:40:05 +0000</pubDate>
      <link>https://forem.com/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf</link>
      <guid>https://forem.com/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf</guid>
      <description>&lt;p&gt;Bienvenido a esta serie de artículos donde cubrimos temas fundamentales de computación. Hoy platicaremos sobre arrays, una de las estructuras de datos más utilizadas en cualquier lenguaje de programación.&lt;/p&gt;

&lt;p&gt;Pero antes de entrar de lleno, necesitamos hablar sobre la memoria. Específicamente, la memoria RAM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En estos ejemplos usaremos JavaScript como lenguaje principal y algunos ejemplos básicos de C. No necesitas ser experto en ninguno de los dos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cómo funciona la RAM
&lt;/h2&gt;

&lt;p&gt;Todas las computadoras utilizan memoria para funcionar. En particular, hablamos de la memoria RAM, la cual almacena información temporal sobre los programas que estás ejecutando. Cuando digo temporal es porque, cuando la computadora se apaga, toda esa información se pierde y, al encender, la memoria vuelve a estar limpia. Es como si la RAM tuviera mala memoria.&lt;/p&gt;

&lt;p&gt;Al hablar de memoria RAM, es inevitable hablar de direcciones y sé lo que estás pensando. ¿Cómo que direcciones?&lt;/p&gt;

&lt;p&gt;Déjame darte un ejemplo que me ayudó a entender este concepto:&lt;/p&gt;

&lt;p&gt;Imagina un elevador en un edificio. Cada piso tiene un número: 0, 1, 2, 3... y en cada piso hay exactamente una oficina con información. Cuando presionas el botón del piso 42, el elevador no necesita detenerse en cada piso antes. No importa si es el piso 1 o el 99, el tiempo de llegada es prácticamente el mismo. Así funciona la RAM: cada posición de memoria tiene una dirección numérica y tu computadora accede a cualquiera de forma instantánea, sin recorrer las anteriores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finhnrgftlyqrubqx45lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finhnrgftlyqrubqx45lw.png" alt="Edificio analogía" width="800" height="1509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un array?
&lt;/h2&gt;

&lt;p&gt;Ahora imagina que una empresa renta 5 pisos consecutivos para sus 5 departamentos, todos del mismo tamaño. Eso es un array: una secuencia de datos del mismo tipo, almacenados en posiciones contiguas de memoria. Si sabes en qué piso empieza la empresa y cuánto ocupa cada departamento, puedes llegar a cualquiera de ellos con el elevador sin recorrer los demás.&lt;/p&gt;

&lt;p&gt;La contigüidad importa porque, como vimos en la analogía, podemos acceder de manera directa a cualquier elemento sin necesidad de recorrer los anteriores. Tu computadora calcula la dirección exacta del elemento que necesitas y va directo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8qvvxor1v4szs4tgc5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8qvvxor1v4szs4tgc5q.png" alt="Ejemplo de memoria" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En un momento vamos a ver cómo lucen los arrays en código. Por ahora, quédate conmigo para hablar de los tipos de arrays que existen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrays estáticos
&lt;/h2&gt;

&lt;p&gt;Los arrays en su forma original son un bloque de memoria contigua con un tamaño fijo. No pueden crecer ni reducirse después de creados. Este tipo de arrays lo vemos en lenguajes como C, donde tú tienes que decirle explícitamente al lenguaje cuántos espacios debe reservarte en la memoria.&lt;/p&gt;

&lt;p&gt;Volviendo a la analogía: la empresa rentó exactamente 5 pisos. Si después necesita un sexto, no hay forma de crecer en el mismo lugar.&lt;/p&gt;

&lt;p&gt;Ventajas: predecible en memoria, sin costo adicional de redimensionamiento.&lt;br&gt;
Limitaciones: Si necesitas más espacio, no puedes agregarlo.&lt;/p&gt;

&lt;p&gt;Este es un ejemplo de cómo se ve un array estático en C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;my_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí le estamos diciendo a C: "Reserva espacio para exactamente 10 números enteros". Ni más ni menos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrays dinámicos
&lt;/h2&gt;

&lt;p&gt;Los arrays dinámicos resuelven la limitación principal de los estáticos: no necesitas saber de antemano cuántos elementos vas a almacenar. Crecen conforme vas insertando elementos.&lt;/p&gt;

&lt;p&gt;¿Cómo funciona esto por debajo? Cuando el array se llena, el lenguaje crea uno nuevo más grande en otra parte de la memoria y copia todos los elementos. Siguiendo la analogía: cuando la empresa necesita más pisos, se muda a un edificio más grande y lleva todo consigo.&lt;/p&gt;

&lt;p&gt;Ventajas: flexibilidad, no necesitas definir un tamaño desde el inicio.&lt;br&gt;
Desventajas: la cantidad de memoria no es predecible y la "mudanza" tiene un costo.&lt;/p&gt;

&lt;p&gt;En lenguajes como JavaScript y Python, los arrays dinámicos vienen integrados por defecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En JavaScript no necesitas preocuparte por declarar el tamaño. El lenguaje se encarga de todo por debajo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbhcu93gm6188ddy0ov7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbhcu93gm6188ddy0ov7.png" alt="Arrays dinámicos" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Estáticos vs. Dinámicos
&lt;/h2&gt;

&lt;p&gt;Ahora que conoces ambos tipos, aquí va una comparación directa:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Array estático&lt;/th&gt;
&lt;th&gt;Array dinámico&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño&lt;/td&gt;
&lt;td&gt;Fijo, definido al crear&lt;/td&gt;
&lt;td&gt;Crece automáticamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibilidad&lt;/td&gt;
&lt;td&gt;Baja&lt;/td&gt;
&lt;td&gt;Alta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uso de memoria&lt;/td&gt;
&lt;td&gt;Predecible&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Costo de inserción&lt;/td&gt;
&lt;td&gt;No aplica (tamaño fijo)&lt;/td&gt;
&lt;td&gt;O(1) amortizado, O(n) al crecer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lenguajes comunes&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;JavaScript, Python, Java (ArrayList)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;En la práctica, la mayoría de lenguajes modernos usan arrays dinámicos por defecto. Pero entender los estáticos te da una mejor perspectiva de lo que sucede por debajo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operaciones comunes
&lt;/h2&gt;

&lt;p&gt;Vamos a platicar sobre lo que puedes hacer con los arrays. Todos los ejemplos están en JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Acceso por índice
&lt;/h3&gt;

&lt;p&gt;El acceso por índice nos permite seleccionar un elemento a partir de su posición. Como en el elevador: tú sabes directamente a qué piso vas.&lt;/p&gt;

&lt;p&gt;Los arrays tienen una forma particular de numerar sus elementos. Se empieza a contar a partir del 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "🥸"&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "☺️"&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "🐶"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Insertar al final
&lt;/h3&gt;

&lt;p&gt;Podemos insertar elementos al final del array utilizando el método &lt;code&gt;push()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👏🏻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆", "👾", "🐶", "👏🏻"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Eliminar el último elemento
&lt;/h3&gt;

&lt;p&gt;Podemos eliminar el último elemento del array con &lt;code&gt;pop()&lt;/code&gt;. Este método además te devuelve el elemento que eliminó.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eliminado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eliminado&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "🐶"&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆", "👾"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Obtener longitud
&lt;/h3&gt;

&lt;p&gt;Podemos obtener la longitud de nuestro array con la propiedad &lt;code&gt;length&lt;/code&gt;. Esto nos dice cuántos elementos contiene.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recorrer los elementos
&lt;/h3&gt;

&lt;p&gt;Algo muy utilizado en los programas es recorrer un array, ya sea para mostrar qué elementos hay dentro o para buscar algún elemento. En JavaScript puedes hacer este recorrido con &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;forEach&lt;/code&gt; o &lt;code&gt;map&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si te das cuenta, aquí acabamos de utilizar lo que aprendimos en los conceptos anteriores. Usamos el acceso por índice con &lt;code&gt;array[i]&lt;/code&gt;. El &lt;code&gt;for&lt;/code&gt; nos ayuda a repetir algo muchas veces y en nuestro ejemplo, vamos aumentando el valor del índice para ir de izquierda a derecha. Y también usamos &lt;code&gt;.length&lt;/code&gt; para saber cuántos elementos tiene el array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modificar el inicio del array
&lt;/h3&gt;

&lt;p&gt;Podemos hacer modificaciones al inicio del array o en el medio. El detalle es que estas operaciones requieren pasos adicionales. Déjame explicarte.&lt;/p&gt;

&lt;p&gt;Cuando tienes un array, hablamos de posiciones contiguas en memoria.&lt;/p&gt;

&lt;p&gt;Si insertamos un elemento al inicio, necesitamos desplazar todos los elementos una posición a la derecha para hacer espacio. Primero se mueven los elementos y luego se inserta el nuevo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5r5appthk1yty38jfph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5r5appthk1yty38jfph.png" alt="Insertar al inicio" width="800" height="939"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y al contrario, si eliminamos un elemento del inicio, tenemos que mover todos los elementos que le seguían una posición hacia la izquierda para llenar el hueco.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwttf6mp0perdjoq4q8ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwttf6mp0perdjoq4q8ni.png" alt="Eliminar al inicio" width="800" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto hace que sea más costoso que insertar o eliminar al final. En JavaScript podemos hacer estas operaciones con &lt;code&gt;unshift()&lt;/code&gt; para insertar al inicio y &lt;code&gt;shift()&lt;/code&gt; para eliminar del inicio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Insertar al inicio&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆"]&lt;/span&gt;

&lt;span class="c1"&gt;// Eliminar del inicio&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["☺️", "👻", "🐆"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Costo de las operaciones
&lt;/h2&gt;

&lt;p&gt;Pero no todo es miel sobre hojuelas. Como vimos, es muy fácil trabajar con los arrays pero las operaciones tienen un costo. El costo de las operaciones nos lo indica Big O, una notación matemática que nos ayuda a conocer cuánto tarda una operación a medida que el array crece. Nos ayuda a identificar la mejor estructura de datos para lo que necesitamos.&lt;/p&gt;

&lt;p&gt;En esta tabla te dejo el costo de las operaciones que vimos:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operación&lt;/th&gt;
&lt;th&gt;Complejidad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Acceso por índice&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buscar un elemento&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insertar al final&lt;/td&gt;
&lt;td&gt;O(1)*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insertar al inicio&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eliminar al final&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eliminar al inicio&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Amortizado. Ocasionalmente O(n) cuando el array dinámico necesita crecer.&lt;/p&gt;

&lt;p&gt;Las operaciones &lt;code&gt;O(1)&lt;/code&gt; indican que toman tiempo constante. No importa cuántos elementos haya en el array, el tiempo va a ser el mismo. Por eso acceder por índice es tan rápido: tu computadora calcula la dirección exacta y va directo, como el elevador.&lt;/p&gt;

&lt;p&gt;Las operaciones &lt;code&gt;O(n)&lt;/code&gt; quieren decir que toman un tiempo lineal: entre más elementos haya, más tiempo tarda. Por eso insertar al inicio es costoso: hay que mover todos los elementos una posición.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si quieres saber más sobre Big O y complejidad algorítmica, dime en los comentarios y preparo un artículo dedicado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Construye tu propia implementación de un array
&lt;/h2&gt;

&lt;p&gt;Vamos a construir tu propia implementación de un array. Para este ejercicio debemos asumir que no tenemos los métodos especiales que vimos anteriormente. Vamos a utilizar el acceso por índices para todo.&lt;/p&gt;

&lt;p&gt;Implementaremos los métodos: &lt;code&gt;get(index)&lt;/code&gt;, &lt;code&gt;push(item)&lt;/code&gt;, &lt;code&gt;pop()&lt;/code&gt; y &lt;code&gt;delete(index)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El objetivo es que entiendas qué pasa por debajo cuando usas un array y los métodos que los lenguajes de alto nivel nos proporcionan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Índice inválido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El array está vacío&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lastItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Índice inválido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_shiftItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;_shiftItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probemos nuestra implementación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;miArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "🥸"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "👻"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "🐆"&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "👻"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código puedes probarlo en &lt;a href="https://runjs.app/play" rel="noopener noreferrer"&gt;RunJS&lt;/a&gt; o de una forma visual en &lt;a href="https://pythontutor.com/visualize.html#mode=edit" rel="noopener noreferrer"&gt;PythonTutor&lt;/a&gt; que tiene soporte para JavaScript y te muestra el paso a paso.&lt;/p&gt;

&lt;p&gt;Fíjate en el método &lt;code&gt;_shiftItems&lt;/code&gt;: ahí puedes ver exactamente por qué eliminar un elemento del inicio o del medio es O(n). Tenemos que recorrer todos los elementos que están después del índice eliminado y moverlos una posición.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Te reto a que implementes el método &lt;code&gt;unshift(item)&lt;/code&gt; para agregar elementos al inicio. Comparte tu solución en los comentarios&lt;/em&gt;. 💪&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Entender los arrays al principio puede ser intimidante. Recuerdo que yo no entendía cómo recorrer un array con &lt;code&gt;for&lt;/code&gt;, pero con la práctica puedes dominarlo.&lt;/p&gt;

&lt;p&gt;Vimos cómo funciona la memoria RAM con la analogía del elevador, los arrays estáticos y los arrays dinámicos. Recuerda que los arrays dinámicos vienen en los lenguajes de alto nivel como Python o JavaScript, así que no debes preocuparte por declarar los elementos que necesitas de antemano. Pero aun así es bueno tener el entendimiento de lo que sucede por debajo. Eso nos da un mayor panorama.&lt;/p&gt;

&lt;p&gt;En el siguiente artículo vamos a cubrir strings como estructura de datos. Y después de eso, vamos a ver patrones de entrevista con arrays y strings.&lt;/p&gt;

&lt;p&gt;Espero que el artículo te sirva. Coméntame si te gustaría que aborde algún tema con mayor profundidad. Gracias por leer. 🙌🏻&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>algorithms</category>
      <category>beginners</category>
      <category>coding</category>
    </item>
    <item>
      <title>Cómo construir un videojuego usando Kiro</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Sat, 14 Mar 2026 02:00:17 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/cavernicolas-dinosaurios-y-codigo-como-construi-un-videojuego-usando-kiro-3ifo</link>
      <guid>https://forem.com/fromchiapasdev/cavernicolas-dinosaurios-y-codigo-como-construi-un-videojuego-usando-kiro-3ifo</guid>
      <description>&lt;p&gt;Quería hacer un videojuego, pero no sabía por dónde empezar. No tenía experiencia en desarrollo de juegos y tampoco estaba familiarizado con los conceptos necesarios. Usé &lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; y terminé construyendo un clon del dinosaurio de Chrome con un cavernícola huyendo de un T-Rex.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En este artículo te cuento cómo lo hice: los problemas que aparecieron, cómo los resolví y los prompts que usé por si quieres replicarlo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Vibecoding
&lt;/h2&gt;

&lt;p&gt;¿Cómo construyes un juego sin saber hacer juegos? Con vibecoding.&lt;/p&gt;

&lt;p&gt;El vibecoding es una forma de prototipar y darle vida a tus ideas sin seguir una metodología formal. Tú describes lo que quieres y la IA lo construye. No es para producción, pero funciona perfecto para algo que quieres probar rápido.&lt;/p&gt;

&lt;p&gt;El juego lo creé con Kiro, un editor que convierte tus ideas en código. Mi rol fue simple: supervisar que los resultados me gustaran. Yo dirigía; Kiro ejecutaba.&lt;/p&gt;

&lt;h2&gt;
  
  
  La idea
&lt;/h2&gt;

&lt;p&gt;Quería construir una versión del clásico dinosaurio de Chrome. Pero en vez de un dinosaurio saltando cactus, quería un cavernícola huyendo de un T-Rex. Algo con personalidad propia.&lt;/p&gt;

&lt;p&gt;La mecánica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un cavernícola corre de izquierda a derecha&lt;/li&gt;
&lt;li&gt;Un T-Rex lo persigue desde atrás&lt;/li&gt;
&lt;li&gt;Aparecen obstáculos: cactus que hay que saltar, pterodáctilos que hay que esquivar agachándose&lt;/li&gt;
&lt;li&gt;Cada colisión atrasa al cavernícola y el dinosaurio se acerca&lt;/li&gt;
&lt;li&gt;Si el dinosaurio te alcanza, game over 💀&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conceptos rápidos
&lt;/h2&gt;

&lt;p&gt;Antes de contarte el proceso, quiero repasar tres conceptos para que tengas contexto de lo que hace el código por debajo. Si ya los conoces, salta directo a "El proceso".&lt;/p&gt;

&lt;h3&gt;
  
  
  POO (Programación Orientada a Objetos)
&lt;/h3&gt;

&lt;p&gt;¿Recuerdas esa clase donde veías diagramas UML y hablaban de herencia (lamentablemente no monetaria)? Pues ese paradigma finalmente se usa en algo divertido.&lt;/p&gt;

&lt;p&gt;En los videojuegos, la POO es clave porque cada elemento del juego (el cavernícola, el dinosaurio, los obstáculos) es un objeto con su propio estado y comportamiento. Eso facilita mucho el modelo mental cuando tienes decenas de cosas moviéndose en pantalla. Si quieres un &lt;a href="https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos" rel="noopener noreferrer"&gt;repaso completo, aquí tienes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Por si no recuerdas, una clase se ve así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dino-chase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FPS (Frames Per Second)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2kqsj3iyfh9fu1jcl4y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2kqsj3iyfh9fu1jcl4y.jpeg" alt="FPS ejemplo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concepto sencillo pero poco entendido. Los FPS son el número de imágenes que tu computadora logra mostrar en un segundo.&lt;/p&gt;

&lt;p&gt;Imagina un cuaderno donde dibujas en cada hoja una secuencia de una persona moviéndose. Cuando pasas las hojas rápido, el dibujo parece cobrar vida. Eso son los FPS.&lt;/p&gt;

&lt;p&gt;Lo más común es 30, 60 y 120 FPS. Cuantos más FPS, más fluidos se sienten los movimientos. Y eso depende mucho del hardware donde se ejecuta el juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Loop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwnl9be0jz4t6i392vo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwnl9be0jz4t6i392vo9.png" alt="Gameloop diagrama"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El game loop es el corazón de cualquier videojuego. Es un bucle que se repite continuamente y hace tres cosas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recibe los eventos del usuario (presionar una tecla, mover el mouse)&lt;/li&gt;
&lt;li&gt;Actualiza el estado interno de los personajes y el mapa (por eso necesitamos POO)&lt;/li&gt;
&lt;li&gt;Redibuja la pantalla con las nuevas posiciones, vidas, puntajes, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Este ciclo se repite hasta que el juego termina.&lt;/p&gt;

&lt;h2&gt;
  
  
  El proceso
&lt;/h2&gt;

&lt;p&gt;Aquí es donde se pone interesante. El juego no salió bien a la primera. Ni a la segunda. Fueron varias iteraciones, cada una resolviendo algo que solo descubrí jugando.&lt;/p&gt;

&lt;p&gt;Si quieres replicar lo que hice, puedes usar Kiro. &lt;a href="https://builder.aws.com/content/34X2JujaGkTJed5N2KeMYt1Mz9m/como-comenzar-con-kiro-tu-guia-de-primeros-pasos" rel="noopener noreferrer"&gt;En este tutorial&lt;/a&gt; aprendes a instalar Kiro y, si te registras, obtienes créditos gratis para poder replicar lo que hice. No te vas a gastar ni la mitad de créditos haciendo este juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  0. Preparar el proyecto
&lt;/h3&gt;

&lt;p&gt;Antes del primer prompt necesitas un proyecto de Vite y unos sonidos. Abre tu terminal y corre esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm create vite@latest game-with-kiro &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; vanilla
&lt;span class="nb"&gt;cd &lt;/span&gt;game-with-kiro
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Después crea la carpeta &lt;code&gt;public/game-assets/audio/&lt;/code&gt; y agrega 3 archivos &lt;code&gt;.wav&lt;/code&gt;. El juego los va a usar para reproducir efectos de sonido cuando el cavernícola salte, choque con un obstáculo o agarre un power-up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jump.wav&lt;/code&gt; para el sonido de salto&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hitHurt.wav&lt;/code&gt; para cuando te golpeas con algo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;powerUp.wav&lt;/code&gt; para futuros power-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Los sonidos los puedes encontrar en mi &lt;a href="https://github.com/AxelDavid45/building-games-with-kiro" rel="noopener noreferrer"&gt;repositorio&lt;/a&gt;. O puedes generar los tuyos en &lt;a href="https://sfxr.me/" rel="noopener noreferrer"&gt;sfxr.me&lt;/a&gt; en 2 minutos. Es importante que los tengas listos antes de empezar porque en el primer prompt le vamos a decir a Kiro que los use.&lt;/p&gt;

&lt;p&gt;Con eso listo, ya puedes empezar con los prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. El prompt inicial
&lt;/h3&gt;

&lt;p&gt;Este fue el prompt más importante. Le expliqué a Kiro exactamente qué quería construir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quiero crear un videojuego en el navegador. El juego se trata de un clon del juego que tiene Chrome cuando te quedas sin internet.

Quiero hacer mi versión inspirada en ese juego. Quiero que el dinosaurio persiga a un cavernícola y que con cada obstáculo que no logre esquivar, el cavernícola se retrase por milisegundos para que al dinosaurio le dé tiempo de atraparlo.

Conforme vayas avanzando los obstáculos deben acercarse a ti más rápido pero siempre permitiéndole al jugador esquivarlos.

El diseño del juego es pixel art minimalista, usando solo tonos de gris. El juego usa la tecla espaciadora o las flechas del teclado.
Los obstáculos son infinitos: cactus en el suelo y pterodáctilos volando donde el cavernícola tenga que agacharse o saltarlos.

Consideraciones:
- Utiliza los sonidos que tengo en la carpeta public/game-assets/audio/
- Todo el trabajo debe ser hecho en la carpeta src/
- Utilizamos Vite
- Utilizamos pnpm
- Los sprites deben ser dibujados con canvas no usar imágenes externas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro creó todo el proyecto. Corrí &lt;code&gt;pnpm dev&lt;/code&gt;, abrí &lt;code&gt;http://localhost:5173&lt;/code&gt; y ya había algo funcionando.&lt;/p&gt;

&lt;p&gt;¿Pero fue suficiente? No del todo.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Simplificar el fondo
&lt;/h3&gt;

&lt;p&gt;El primer problema que encontré: el fondo tenía demasiados elementos. Volcanes, gradientes, parallax. Se veía laggeado y no se sentía como el juego original.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;El fondo se ve laggeado con cada actualización. Mantenlo minimalista como el juego original de Chrome: fondo gris claro sólido, nubes simples, una línea de suelo. Sin volcanes ni parallax complejo.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Los obstáculos tardaban mucho en aparecer
&lt;/h3&gt;

&lt;p&gt;El juego se sentía aburrido. Pasaban segundos sin que apareciera nada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Necesito que los obstáculos no tarden tanto en aparecer. Que a veces haya que saltar obstáculos seguidos o agacharse para que sea un poco más difícil.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con eso ya se sentía como un juego de verdad.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Obstáculos imposibles de esquivar
&lt;/h3&gt;

&lt;p&gt;A veces aparecían dos obstáculos encimados, o uno aparecía justo cuando estaba cayendo de un salto. Imposible esquivarlos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tenemos un bug: cuando el cavernícola salta, a veces aparece un obstáculo tan cerca que ya no me permite saltar de nuevo y me cuenta como un golpe. Además dos obstáculos aparecen al mismo tiempo. Necesito que eso se arregle.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro cambió el sistema de spawn para usar distancia mínima entre obstáculos en vez de tiempo. Mucho mejor.&lt;/p&gt;

&lt;p&gt;Pero algo seguía sintiéndose raro. 🤔&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Mejorar la respuesta de los controles
&lt;/h3&gt;

&lt;p&gt;Este fue un momento clave. Presionaba saltar en el momento correcto, pero el juego no respondía porque el cavernícola todavía estaba en el aire del salto anterior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implementa un input buffer porque cuando aparecen combos parece que no logra saltar los obstáculos aunque yo le aplaste la tecla en el tiempo adecuado.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro implementó dos técnicas clásicas de platformers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input Buffer (150ms): Si presionas saltar mientras estás en el aire, el juego recuerda ese input y salta automáticamente cuando aterrices.&lt;/li&gt;
&lt;li&gt;Coyote Time (80ms): Tienes una ventana pequeña para saltar incluso después de empezar a caer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto hizo que el juego se sintiera responsivo. Los combos de obstáculos ahora sí se podían esquivar.&lt;/p&gt;

&lt;p&gt;Perfecto. La mecánica básica ya funcionaba. Pero faltaba algo para competir con amigos.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. El contador y high score
&lt;/h3&gt;

&lt;p&gt;Sin puntaje no hay competencia.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implementa el counter del juego con high score guardado en localStorage. El formato debe ser de 5 dígitos como el juego original de Chrome.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora sí podía retar a mis amigos.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. El efecto dominó
&lt;/h3&gt;

&lt;p&gt;Este fue el bug más difícil. Me tomó varias iteraciones resolverlo.&lt;/p&gt;

&lt;p&gt;El problema era un ciclo vicioso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chocas con un obstáculo → el cavernícola se atrasa&lt;/li&gt;
&lt;li&gt;Al atrasarte, el siguiente obstáculo ya está encima tuyo&lt;/li&gt;
&lt;li&gt;Chocas de nuevo → te atrasas más&lt;/li&gt;
&lt;li&gt;Se repite hasta game over&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Era injugable. Le pedí esto a Kiro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Si choco varias veces es imposible sortear los objetos siguientes porque queda muy cerca de ellos. Necesito que al colisionar se limpien los obstáculos cercanos y haya un periodo de inmunidad para recuperarse.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La solución combinó varias técnicas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inmunidad de 500ms después de cada colisión&lt;/li&gt;
&lt;li&gt;Limpieza de obstáculos en un radio de 250px al colisionar&lt;/li&gt;
&lt;li&gt;Recuperación de posición más rápida, proporcional a la velocidad del juego&lt;/li&gt;
&lt;li&gt;Spawn basado en la posición del jugador, no del borde del canvas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora tocaba preocuparme del dinosaurio.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Balancear al dinosaurio
&lt;/h3&gt;

&lt;p&gt;El T-Rex alcanzaba al cavernícola demasiado rápido, incluso sin colisiones. La presión tenía que venir de mis errores, no del paso del tiempo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;El dinosaurio alcanza al cavernícola muy rápido. Haz que empiece más atrás y avance más lento. La presión debe venir de las colisiones, no del avance natural del dinosaurio.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro redujo la velocidad de avance del dinosaurio de &lt;code&gt;0.2&lt;/code&gt; a &lt;code&gt;0.08&lt;/code&gt;. Ahora la tensión viene de tus errores, no del reloj.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Pterodáctilos a dos alturas
&lt;/h3&gt;

&lt;p&gt;Para darle más variedad, agregué pterodáctilos a diferentes alturas. Unos que hay que saltar y otros donde hay que agacharse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quiero que haya pterodáctilos a dos alturas: altos donde hay que agacharse y bajos donde hay que saltar. Asegúrate de que las figuras estén bien calibradas para que ambas acciones funcionen a cualquier velocidad del juego.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Estructura final del proyecto
&lt;/h2&gt;

&lt;p&gt;Después de todas las iteraciones, la estructura quedó así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;├── src/&lt;/span&gt;
&lt;span class="s"&gt;│   ├── main.js&lt;/span&gt;          &lt;span class="c1"&gt;# Entry point, pantallas inicio/game over&lt;/span&gt;
&lt;span class="s"&gt;│   ├── game.js&lt;/span&gt;          &lt;span class="c1"&gt;# Game loop, colisiones, score, renderizado&lt;/span&gt;
&lt;span class="s"&gt;│   ├── caveman.js&lt;/span&gt;       &lt;span class="c1"&gt;# Jugador: salto, agacharse, input buffer, inmunidad&lt;/span&gt;
&lt;span class="s"&gt;│   ├── dinosaur.js&lt;/span&gt;      &lt;span class="c1"&gt;# Enemigo perseguidor&lt;/span&gt;
&lt;span class="s"&gt;│   ├── obstacles.js&lt;/span&gt;     &lt;span class="c1"&gt;# Manager + CactusSmall, CactusBig, Pterodactyl&lt;/span&gt;
&lt;span class="s"&gt;│   ├── background.js&lt;/span&gt;    &lt;span class="c1"&gt;# Nubes y decoraciones del suelo&lt;/span&gt;
&lt;span class="s"&gt;│   ├── audio.js&lt;/span&gt;         &lt;span class="c1"&gt;# Gestión de sonidos&lt;/span&gt;
&lt;span class="s"&gt;│   └── style.css&lt;/span&gt;        &lt;span class="c1"&gt;# Estilos de UI&lt;/span&gt;
&lt;span class="s"&gt;├── public/game-assets/&lt;/span&gt;
&lt;span class="s"&gt;│   └── audio/&lt;/span&gt;           &lt;span class="c1"&gt;# Archivos .wav&lt;/span&gt;
&lt;span class="s"&gt;├── index.html&lt;/span&gt;
&lt;span class="s"&gt;└── package.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lo que aprendí
&lt;/h2&gt;

&lt;p&gt;No sabía hacer un videojuego. No sabía qué conceptos necesitaba ni por dónde empezar. Con ayuda de la IA logré construir algo que de otra forma me hubiera tomado semanas de investigación, y probablemente lo hubiera abandonado por frustración.&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle: la IA no lo hizo sola. Fueron 9 iteraciones. Cada una requirió que yo jugara, identificara problemas y supiera explicar qué estaba mal. La IA ejecuta, pero tú diriges.&lt;/p&gt;

&lt;p&gt;Si estás estudiando programación y sientes que la IA viene a dejarte sin oportunidades, no pienses eso. Aprende a usarla. Empodérate con ella. Ahora puedes crear ideas más rápido y dedicarle tiempo a lo que realmente importa: entender los fundamentos.&lt;/p&gt;

&lt;p&gt;Ojo, es importante que, aunque la IA escriba el código, tú seas capaz de leerlo y modificarlo cuando algo salga mal. Porque todavía no es perfecta.&lt;/p&gt;

&lt;p&gt;Sigue aprendiendo y no le tengas miedo a la IA. Úsala como lo que es: una herramienta que amplifica lo que ya sabes y una aliada para aprender construyendo.&lt;/p&gt;




&lt;p&gt;Si te animas a hacer tu propia versión, déjame el link a tu repositorio en los comentarios o puedes escribirme en &lt;a href="https://www.linkedin.com/in/axelespinosa/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; si tienes alguna duda.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;También te dejo el link al repositorio de mi juego 👉 &lt;a href="https://github.com/AxelDavid45/building-games-with-kiro" rel="noopener noreferrer"&gt;Repositorio con juego&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kiro</category>
      <category>ai</category>
      <category>programming</category>
      <category>español</category>
    </item>
    <item>
      <title>¿Qué es un encoding? Explicación sencilla: ASCII, UTF-8 y Unicode</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Thu, 19 Feb 2026 20:58:11 +0000</pubDate>
      <link>https://forem.com/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5</link>
      <guid>https://forem.com/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5</guid>
      <description>&lt;p&gt;La forma en que nos comunicamos digitalmente ha cambiado muchísimo. Hoy nos comunicamos hasta con stickers, pero ¿alguna vez te has preguntado cómo llegamos hasta aquí?&lt;/p&gt;

&lt;p&gt;Seguramente navegando por internet te has encontrado con textos que muestran caracteres extraños como este: &lt;code&gt;M�xico&lt;/code&gt;&lt;br&gt;
Eso tiene un nombre: &lt;a href="https://en.wikipedia.org/wiki/Mojibake" rel="noopener noreferrer"&gt;Mojibake&lt;/a&gt;. Así se le llama al fenómeno de ver caracteres raros cuando hay un error en la codificación del texto. &lt;/p&gt;

&lt;p&gt;En este artículo te explico a detalle qué es la codificación, con ejemplos claros y sencillos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Encodings
&lt;/h2&gt;

&lt;p&gt;El encoding (o en español, codificación) es el proceso de transformar la información de una representación a otra siguiendo reglas específicas. En este contexto, nos enfocaremos en la codificación de caracteres: cómo se representan letras, números y símbolos en formato digital.&lt;/p&gt;

&lt;p&gt;Me imagino que has escuchado que las computadoras solamente entienden &lt;a href="https://es.wikipedia.org/wiki/Sistema_binario" rel="noopener noreferrer"&gt;números binarios: 0 y 1&lt;/a&gt;. Esto es cierto, pero imagina si tuviéramos que usar únicamente esos números para comunicarnos con ellas todos los días. Por eso, los investigadores desarrollaron sistemas que nos facilitan esta comunicación. &lt;/p&gt;

&lt;p&gt;Te muestro un ejemplo con mi nombre. Sería impráctico tener que escribirlo usando solo ceros y unos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhwj04xoc2z6qmojd26x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhwj04xoc2z6qmojd26x.jpg" alt="Mi nombre en binario" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Son demasiados números, ¿cierto? ¿Cómo pasamos de letras a un montón de números?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preguntas muy buenas, ser, joven Padawan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrocedamos un paso. Entendamos primero de dónde salieron esos números. Te presento a ASCII.&lt;/p&gt;
&lt;h2&gt;
  
  
  ASCII
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ASCII" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt; son las siglas de &lt;strong&gt;American Standard Code for Information Interchange&lt;/strong&gt;. Es un estándar que nos dice cómo deben representarse las letras como números para que las computadoras lo entiendan y nosotros también podamos entenderlo. &lt;/p&gt;

&lt;p&gt;La primera versión de este estándar fue creada en 1963 y hasta hoy en día sigue siendo importante conocer que existe, porque es fácil de usar y los fabricantes de computadoras se encargan de que todas las PCs entiendan este formato.&lt;/p&gt;

&lt;p&gt;Podemos encontrar la tabla ASCII que muestra cada letra del idioma inglés con un valor en decimal, hexadecimal y binario. Es por eso que pude transformar mi nombre a números binarios: porque cada letra cuenta con un valor que las computadoras pueden entender. &lt;/p&gt;

&lt;p&gt;Te dejo los caracteres que usé:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvduapin1dhvgno8uuxn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvduapin1dhvgno8uuxn.jpg" alt="ASCII Códigos" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La codificación ASCII solo nos provee de 127 caracteres, lo que equivale a 7 bits (2^7). &lt;strong&gt;Esto es importante porque la computadora utiliza 1 byte (8 bits) para poder almacenar un carácter, es decir, que se está desperdiciando un bit.&lt;/strong&gt; &lt;strong&gt;Y precisamente de eso se dieron cuenta los investigadores, así que después decidieron extender esta tabla de caracteres a 256. Ahora un carácter podía utilizar hasta 8 bits, o lo que es igual a 1 byte completo.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Esta expansión fue clave para que otros países con idiomas y alfabetos diferentes al inglés pudieran usar la codificación sin problemas de compatibilidad.&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle: 256 caracteres no son suficientes cuando tienes que representar chino, árabe, cirílico y todos los demás alfabetos del mundo. Cada fabricante empezó a inventar su propia solución, y ahí es donde empezó el problema de &lt;code&gt;M├®xico&lt;/code&gt; que viste arriba. La solución a este caos fue Unicode. &lt;/p&gt;
&lt;h2&gt;
  
  
  Unicode
&lt;/h2&gt;

&lt;p&gt;Unicode se creó en los años 80 y se convirtió en un estándar hoy en día que define más de 1.1 millones de caracteres. Este estándar asigna a cada carácter un código que después, con ayuda de un encoding, se transforma a bits (lo que realmente la computadora entiende). Y no solamente se trata de letras: los emojis también están dentro de Unicode y por eso podemos utilizarlos en cualquier idioma. &lt;/p&gt;

&lt;p&gt;La idea principal de Unicode es evitar que cada fabricante de hardware cree su propio encoding incompatible con los demás. Así, un fabricante en Europa que usa caracteres distintos al inglés puede compartir información con alguien en Asia o en América, evitando el caos de &lt;code&gt;M├®xico&lt;/code&gt; que vimos antes.&lt;/p&gt;

&lt;p&gt;Los códigos Unicode están definidos con un formato hexadecimal y se ven así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxsxg7v84x8dquyv7b4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxsxg7v84x8dquyv7b4.jpg" alt="Unicode codes" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si ves esto y no sabes qué es hexadecimal, te dejo un link a un artículo: &lt;a href="https://en.wikipedia.org/wiki/Hexadecimal" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Hexadecimal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Listo. Ya conocemos Unicode y por qué es importante, pero esto solo nos da una pequeña porción del panorama completo. Recuerda que la computadora solo entiende bits, entonces, ¿cómo pasamos de estos códigos hexadecimales a bits? Aquí es donde entra UTF-8 🙌🏻&lt;/p&gt;
&lt;h2&gt;
  
  
  UTF-8 👾
&lt;/h2&gt;

&lt;p&gt;UTF-8 es un encoding creado por el consorcio Unicode (los mismos que crearon el estándar Unicode) y se encarga de transformar los códigos hexadecimales a bits que la computadora pueda entender. &lt;/p&gt;

&lt;p&gt;Algo muy inteligente de UTF-8 es que fue diseñado desde el inicio para ser compatible con ASCII. Los primeros 128 códigos tienen una traducción idéntica, es decir, se conservan los códigos ASCII. Por ejemplo, la letra &lt;code&gt;A&lt;/code&gt; en ASCII es 65 (en decimal) y en UTF-8 también es 65. &lt;/p&gt;

&lt;p&gt;Esto permitió que programas que ya usaban ASCII funcionaran automáticamente con UTF-8, lo que mejoró la adopción y ahora UTF-8 sea el encoding más popular en la web. &lt;/p&gt;

&lt;p&gt;UTF-8 utiliza una transformación dinámica a bits: caracteres simples ocupan solo 1 byte, mientras que caracteres más complejos —con múltiples formas, diacríticos, etc.— pueden ocupar hasta 4 bytes.&lt;/p&gt;

&lt;p&gt;Por ejemplo, este emoji 👾 ocupa 4 bytes completos, mientras que la letra &lt;code&gt;A&lt;/code&gt; solo necesita 1 byte:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbcmli0y3t37j6abk7s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbcmli0y3t37j6abk7s.jpg" alt="Tamaño de emoji" width="554" height="182"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Charset y Encoding
&lt;/h2&gt;

&lt;p&gt;Perfecto. Ya sabes cómo funcionan ASCII, Unicode y UTF-8. Pero hay una distinción importante que te ayudará a entender todo el panorama: &lt;strong&gt;charset vs encoding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando trabajas con bases de datos o creas un documento HTML, seguro has visto una etiqueta o configuración llamada &lt;strong&gt;charset&lt;/strong&gt;. Esto se refiere al &lt;strong&gt;catálogo de caracteres&lt;/strong&gt; que puedes usar en ese documento y que se mostrarán correctamente en pantalla. Es decir, qué caracteres están “permitidos” o “disponibles”. &lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;encoding,&lt;/strong&gt; por otro lado, es la forma en que esos caracteres se transforman a bits para ser almacenados o transmitidos. &lt;/p&gt;
&lt;h3&gt;
  
  
  ¿Por qué importa?
&lt;/h3&gt;

&lt;p&gt;Si no trabajas con el mismo charset en documentos compartidos, terminas con el problema que vimos antes: caracteres rotos, símbolos raros y texto ilegible. &lt;/p&gt;
&lt;h2&gt;
  
  
  Ejemplo práctico
&lt;/h2&gt;

&lt;p&gt;Imagina que creas un archivo de texto con este contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;México
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creamos el archivo en nuestra computadora y verificamos su encoding con el comando &lt;a href="https://man7.org/linux/man-pages/man1/file.1.html" rel="noopener noreferrer"&gt;file&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"México"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test.txt
~ file &lt;span class="nt"&gt;-I&lt;/span&gt; test.txt
test.txt: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfecto, está en UTF-8. Ahora intentemos convertirlo a un encoding que no soporte acentos, como &lt;code&gt;ISO-8859-10&lt;/code&gt; (diseñado para idiomas nórdicos: sueco, noruego, danés).&lt;/p&gt;

&lt;p&gt;Usamos la herramienta &lt;a href="https://man7.org/linux/man-pages/man1/iconv.1.html" rel="noopener noreferrer"&gt;&lt;code&gt;iconv&lt;/code&gt;&lt;/a&gt; para transformar el encoding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ iconv &lt;span class="nt"&gt;-f&lt;/span&gt; UTF-8 &lt;span class="nt"&gt;-t&lt;/span&gt; ISO-8859-10 test.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; converted.txt

~ &lt;span class="nb"&gt;cat &lt;/span&gt;converted.txt
M�xico
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Qué pasó? 😳 El archivo ahora contiene caracteres raros donde debería estar la “é”. La terminal no puede mostrarlo bien, pero un editor de texto sí revela el problema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pc3zjet3e62i3fsj4ad.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pc3zjet3e62i3fsj4ad.jpg" alt="Transformación erronea" width="568" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nuestro archivo original estaba en UTF-8, donde la “é” tiene un código específico. Al convertirlo en ISO-8859-10, &lt;code&gt;iconv&lt;/code&gt; intentó encontrar un equivalente... pero no es lo mismo, por eso se ve raro.&lt;/p&gt;

&lt;p&gt;Ahora, si intentamos convertirlo a ASCII (que en teoría es compatible con UTF-8), vemos que directamente no puede manejar el acento porque en el charset ASCII no existen letras con acento como sí existen en Unicode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ iconv &lt;span class="nt"&gt;-f&lt;/span&gt; UTF-8 &lt;span class="nt"&gt;-t&lt;/span&gt; ASCII &lt;span class="nt"&gt;-c&lt;/span&gt;  test.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; converted.txt
iconv: warning: invalid characters: 1
~ &lt;span class="nb"&gt;cat &lt;/span&gt;converted.txt
Mxico
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incluso si abres el editor, verás que no se logró transformar la segunda letra:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54vvk8tmwe55iswg4msi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54vvk8tmwe55iswg4msi.jpg" alt="Transformación: elimina una letra" width="516" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La letra “é” simplemente desapareció. Para verificar que el nuevo archivo tiene otro encoding, ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ file &lt;span class="nt"&gt;-I&lt;/span&gt; converted.txt
converted.txt: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-ascii
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahí está: ahora es &lt;code&gt;us-ascii&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo en programación
&lt;/h2&gt;

&lt;p&gt;Listo. Ya entendemos la diferencia entre charset y encoding. ¿Pero cómo nos ayuda esto al programar?&lt;br&gt;
Imagina este problema:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Valida si una cadena de texto contiene únicamente caracteres A-Z y dígitos 0-9"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para resolverlo, vamos a asumir que la cadena de texto es pequeña y trabajaremos con los códigos ASCII:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Evaluating s[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]= &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; charcode=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AUDID3222&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// TRUE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D444E##RUURUJ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// FALSE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asbueu3$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// FALSE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asbueu3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// TRUE&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código puedes probarlo con herramientas como &lt;a href="https://runjs.app/play" rel="noopener noreferrer"&gt;RunJS&lt;/a&gt; o de una forma visual con un editor que te muestra el paso a paso que tiene soporte para Javascript: &lt;a href="https://pythontutor.com/visualize.html#mode=edit" rel="noopener noreferrer"&gt;PythonTutor&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Y así llegamos al final. En este artículo vimos cómo funcionan los encodings, por qué un emoji puede ocupar 4 bytes y ejemplos prácticos de transformaciones entre charsets.&lt;/p&gt;

&lt;p&gt;Reacciona:&lt;br&gt;
❤️ Sí, ya lo conocías&lt;br&gt;
🔥 Si te sorprendió algo&lt;br&gt;
💬 Y cuéntame qué fue lo que más te llamó la atención&lt;/p&gt;

&lt;p&gt;Si crees que me faltó algo importante, déjamelo en los comentarios. Te estaré leyendo. 👇&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
