> For the complete documentation index, see [llms.txt](https://educacion.gitbook.io/programacion/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://educacion.gitbook.io/programacion/pila.md).

# pila

## HTML

### HTML Preprocessor

#### About HTML Preprocessors

HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.

[Learn more](https://blog.codepen.io/documentation/editor/using-html-preprocessors/) · [Versions](https://codepen.io/versions/)

* None
* Haml
* Markdown
* Slim
* Pug

### Add Class(es) to `<html>`

#### Adding Classes

In CodePen, whatever you write in the HTML editor is what goes within the `<body>` tags in [a basic HTML5 template](https://blog.codepen.io/documentation/features/preview-template/). So you don't have access to higher-up elements like the `<html>` tag. If you want to add classes there that can affect the whole document, this is the place to do it.

### Stuff for `<head>`

#### About the `<head>`

In CodePen, whatever you write in the HTML editor is what goes within the `<body>` tags in [a basic HTML5 template](https://blog.codepen.io/documentation/features/preview-template/). If you need things in the `<head>` of the document, put that code here.

**Insecure Resource**

The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.

↑ Insert the most common viewport meta tag

## CSS

### CSS Preprocessor

#### About CSS Preprocessors

CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.

[Learn more](https://blog.codepen.io/documentation/editor/using-css-preprocessors/) · [Versions](https://codepen.io/versions/)

* None
* Less
* SCSS
* Sass
* Stylus
* PostCSS

[Need an add-on?](#0)

#### About CSS Base

It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: [normalize.css](http://necolas.github.io/normalize.css/) and a [reset](http://meyerweb.com/eric/tools/css/reset/). Or, choose **Neither** and nothing will be applied.

* Normalize
* Reset
* Neither

### Vendor Prefixing

#### About Vendor Prefixing

To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance `-webkit-` or `-moz-`.

We offer two popular choices: [Autoprefixer](https://github.com/postcss/autoprefixer) (which processes your CSS server-side) and [-prefix-free](http://leaverou.github.io/prefixfree/) (which applies prefixes via a script, client-side).

* Autoprefixer
* Prefixfree
* Neither

### Add External Stylesheets/Pens

Any URLs added here will be added as `<link>`s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper [URL extension](https://blog.codepen.io/documentation/url-extensions/).

#### About External Resources

You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.

You can also link to another Pen here (use the `.css` [URL Extension](https://blog.codepen.io/documentation/url-extensions/)) and we'll pull the CSS from that Pen and include it. If it's using a *matching* preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.

[Learn more](https://blog.codepen.io/documentation/editor/adding-external-resources/)

**Insecure Resource**

You are linking to a resource using the non-secure http\:// protocol, which may not work when the browser is using https\:// like CodePen enforces.

**URL Extension Required**

When linking another Pen as a resource, make sure you use a [URL Extension](https://blog.codepen.io/documentation/url-extensions/) of the type of code you want to link to. Either `.css`, `.js`, or the extension of a matching code processor.

\+ add another resource

## JavaScript

### JavaScript Preprocessor

#### About JavaScript Preprocessors

JavaScript preprocessors can help make authoring JavaScript easier and more convenient.

[Learn more](https://blog.codepen.io/documentation/editor/using-js-preprocessors/) · [Versions](https://codepen.io/versions/)

* None
* Babel
* TypeScript
* CoffeeScript
* LiveScript

Babel includes JSX processing.

### Add External Scripts/Pens

Any URL's added here will be added as `<script>`s in order, and run *before* the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

#### About External Resources

You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.

If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.

You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.

[Learn more](https://blog.codepen.io/documentation/adding-external-resources/)

**Insecure Resource**

You are linking to a resource using the non-secure http\:// protocol, which may not work when the browser is using https\:// like CodePen enforces.

**URL Extension Required**

When linking another Pen as a resource, make sure you use a [URL Extension](https://blog.codepen.io/documentation/url-extensions/) of the type of code you want to link to. Either `.css`, `.js`, or the extension of a matching code processor.

\+ add another resource

## Packages

### Add Packages

Search for and use JavaScript packages from [npm](https://www.npmjs.com/) here. By selecting a package, an `import` statement will be added to the top of the JavaScript editor for this package.

#### About Packages

Using packages here is powered by [esm.sh](https://esm.sh/), which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.

All packages are different, so refer to their docs for how they work.

If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.

## Behavior

### Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

### Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

### Format on Save

If enabled, your code will be formatted when you actively save your Pen. **Note: your code becomes un-folded during formatting.**

## Editor Settings

### Code Indentation

* Spaces
* Tabs

### Code Indent width

123456

### Want to change your Syntax Highlighting theme, Fonts and more?

Visit your [global Editor Settings](https://codepen.io/settings/editor).

## HTML

```html
<!DOCTYPE html>
<html lang="gl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pila (Stack) - Metáfora do Editor de Texto | TAD</title>
    <style>
        * {
            box-sizing: border-box;
            user-select: none; /* Evita selección accidental na demo, pero non impide escribir */
        }

        body {
            font-family: system-ui, 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif;
            background: linear-gradient(145deg, #f1f4fa 0%, #e9eef4 100%);
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            padding: 20px;
        }

        /* TARXETA PRINCIPAL */
        .card {
            max-width: 1100px;
            width: 100%;
            background: rgba(255,255,255,0.9);
            backdrop-filter: blur(2px);
            border-radius: 2.5rem;
            box-shadow: 0 25px 45px -12px rgba(0,0,0,0.3), 0 2px 5px rgba(0,0,0,0.05);
            overflow: hidden;
            transition: all 0.2s;
        }

        .header {
            background: #1e293b;
            color: white;
            padding: 1.2rem 2rem;
        }

        .header h1 {
            margin: 0;
            font-size: 1.8rem;
            font-weight: 600;
            letter-spacing: -0.3px;
        }

        .header h1 span {
            background: #facc15;
            color: #0f172a;
            font-size: 0.9rem;
            font-weight: bold;
            padding: 0.2rem 0.7rem;
            border-radius: 40px;
            margin-left: 12px;
            vertical-align: middle;
        }

        .header p {
            margin: 0.5rem 0 0;
            opacity: 0.85;
            font-size: 1rem;
        }

        /* DÚAS COLUMNAS: SIMULADOR + PILA GRÁFICA */
        .demo-area {
            display: flex;
            flex-wrap: wrap;
            gap: 1.5rem;
            padding: 2rem;
        }

        /* COLUMNA ESQUERDA: EDITOR DE TEXTO SIMULADO */
        .editor-section {
            flex: 2;
            min-width: 240px;
            background: #ffffff;
            border-radius: 1.5rem;
            box-shadow: 0 8px 20px rgba(0,0,0,0.08);
            padding: 1.2rem;
            transition: 0.1s;
        }

        .editor-label {
            font-weight: 700;
            color: #0f172a;
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 12px;
            border-left: 4px solid #3b82f6;
            padding-left: 12px;
        }

        .editor-label i {
            font-size: 1.3rem;
        }

        textarea {
            width: 100%;
            height: 180px;
            padding: 12px;
            font-family: 'SF Mono', 'Fira Code', monospace;
            font-size: 1rem;
            border: 2px solid #e2e8f0;
            border-radius: 1rem;
            resize: vertical;
            background: #fefce8;
            transition: 0.1s;
            line-height: 1.4;
        }

        textarea:focus {
            outline: none;
            border-color: #3b82f6;
            box-shadow: 0 0 0 3px rgba(59,130,246,0.2);
        }

        .buttons-editor {
            display: flex;
            gap: 12px;
            margin-top: 16px;
            flex-wrap: wrap;
        }

        button {
            background: #f1f5f9;
            border: none;
            padding: 8px 16px;
            border-radius: 60px;
            font-weight: 600;
            font-size: 0.85rem;
            cursor: pointer;
            transition: all 0.2s ease;
            display: inline-flex;
            align-items: center;
            gap: 8px;
            font-family: inherit;
            color: #0f172a;
            box-shadow: 0 1px 2px rgba(0,0,0,0.05);
        }

        button i {
            font-style: normal;
            font-weight: bold;
            font-size: 1.1rem;
        }

        .btn-undo {
            background: #3b82f6;
            color: white;
            box-shadow: 0 2px 6px rgba(59,130,246,0.3);
        }

        .btn-undo:hover {
            background: #2563eb;
            transform: scale(0.97);
        }

        .btn-reset {
            background: #f1f5f9;
            border: 1px solid #cbd5e1;
        }

        .btn-reset:hover {
            background: #e2e8f0;
        }

        /* COLUMNA DEREITA: REPRESENTACIÓN DA PILA (STACK) */
        .stack-section {
            flex: 1.2;
            min-width: 220px;
            background: #0f172a;
            border-radius: 1.5rem;
            padding: 1rem;
            color: #e2e8f0;
            box-shadow: 0 20px 30px -12px rgba(0,0,0,0.3);
        }

        .stack-title {
            font-weight: 700;
            text-align: center;
            margin-bottom: 16px;
            font-size: 1.2rem;
            background: #1e293b;
            display: inline-block;
            width: 100%;
            padding: 6px 0;
            border-radius: 60px;
            letter-spacing: 1px;
        }

        .stack-container {
            background: #020617;
            border-radius: 1rem;
            padding: 12px;
            min-height: 300px;
            display: flex;
            flex-direction: column-reverse; /* Para que o "top" apareza enriba visualmente */
            gap: 8px;
            border: 1px solid #334155;
        }

        .stack-element {
            background: linear-gradient(135deg, #facc15, #f59e0b);
            color: #0f172a;
            font-weight: bold;
            padding: 10px;
            text-align: center;
            border-radius: 14px;
            font-family: monospace;
            font-size: 0.9rem;
            word-break: break-word;
            box-shadow: 0 2px 6px rgba(0,0,0,0.3);
            transition: 0.1s;
            border-left: 3px solid #fffbeb;
        }

        .empty-stack {
            text-align: center;
            color: #94a3b8;
            padding: 24px 0;
            font-style: italic;
            font-size: 0.9rem;
        }

        .stack-info {
            margin-top: 12px;
            font-size: 0.8rem;
            background: #1e293b;
            padding: 6px 12px;
            border-radius: 20px;
            text-align: center;
        }

        .stack-info strong {
            color: #facc15;
        }

        .legend {
            background: #f8fafc;
            padding: 0.8rem 2rem;
            border-top: 1px solid #cbd5e1;
            font-size: 0.8rem;
            color: #334155;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: center;
        }

        .badge {
            background: #e2e8f0;
            padding: 4px 8px;
            border-radius: 20px;
            font-family: monospace;
            font-weight: bold;
        }

        footer {
            text-align: center;
            font-size: 0.7rem;
            padding: 12px;
            color: #475569;
            background: #f1f5f9;
        }

        @media (max-width: 700px) {
            .demo-area {
                flex-direction: column;
            }
            .stack-container {
                min-height: 200px;
            }
        }
    </style>
</head>
<body>

<div class="card">
    <div class="header">
        <h1>📚 Pila (Stack) · TAD <span>LIFO</span></h1>
        <p>📝 Metáfora do editor de texto: <strong>Desfacer (Ctrl+Z)</strong> → a última acción é a primeira en desfacerse</p>
    </div>

    <div class="demo-area">
        <!-- SIMULADOR DE EDITOR DE TEXTO -->
        <div class="editor-section">
            <div class="editor-label">
                <i>✍️</i> Editor de texto (demo)
            </div>
            <textarea id="textArea" placeholder="Escribe aquí... cada cambio importante pódese desfacer como nun editor real"></textarea>
            <div class="buttons-editor">
                <button id="undoBtn" class="btn-undo">
                    <i>↩️</i> DESFACER (Ctrl+Z)
                </button>
                <button id="resetStackBtn" class="btn-reset">
                    <i>🗑️</i> Reiniciar historial
                </button>
                <button id="clearTextBtn" class="btn-reset">
                    <i>🧹</i> Limpar texto
                </button>
            </div>
            <p style="font-size: 0.7rem; margin-top: 12px; color:#475569;">
                ⚡ Cada vez que <strong>escribas ou pegues</strong> (cambie o texto) apilamos o estado anterior.<br>
                🔼 O botón <strong>DESFACER</strong> saca da pila a última acción e restaura o texto previo.
            </p>
        </div>

        <!-- REPRESENTACIÓN VISUAL DA PILA -->
        <div class="stack-section">
            <div class="stack-title">
                🗂️ PILA de estados "Desfacer"
            </div>
            <div class="stack-container" id="stackVisual">
                <!-- Aquí renderizaremos os elementos dinamicamente -->
                <div class="empty-stack">⚡ Pila baleira</div>
            </div>
            <div class="stack-info">
                📌 <strong>TOP</strong> ⬆️ (último en apilar) <br>
                Comportamento <strong>LIFO</strong>: o último en gardarse é o primeiro en saír co Desfacer
            </div>
        </div>
    </div>

    <div class="legend">
        <div>🧠 <strong>TAD Pila:</strong> operacións <span class="badge">push()</span> (apilar) e <span class="badge">pop()</span> (desapilar)</div>
        <div>🎯 <strong>Exemplo:</strong> "Escribir 'ola'" → push → "Escribir 'mundo'" → push → Desfacer → pop() → volves a 'ola'</div>
    </div>
    <footer>
        💡 A pila non coñece o contido do editor, só garda instantáneas do texto anterior. Cada DESFACER é un pop().
    </footer>
</div>

<script>
    // ---------- LÓXICA DA PILA (TAD) ----------
    class Stack {
        constructor() {
            this.items = [];   // array interno, pero o usuario do TAD só ve push/pop/isEmpty/peek
        }

        // Apilar (push) - engade un elemento arriba
        push(element) {
            this.items.push(element);
        }

        // Desapilar (pop) - elimina e devolve o elemento do cume
        pop() {
            if (this.isEmpty()) return null;
            return this.items.pop();
        }

        // Ollar o cume sen eliminar (peek)
        peek() {
            if (this.isEmpty()) return null;
            return this.items[this.items.length - 1];
        }

        isEmpty() {
            return this.items.length === 0;
        }

        size() {
            return this.items.length;
        }

        // Para amosar a pila de abaixo a arriba (visualmente usamos orde orixinal)
        getAll() {
            return [...this.items];
        }

        // Limpar a pila
        clear() {
            this.items = [];
        }
    }

    // ---------- ESTADO DA DEMO ----------
    // 1. Referencias ao DOM
    const textarea = document.getElementById('textArea');
    const undoButton = document.getElementById('undoBtn');
    const resetStackBtn = document.getElementById('resetStackBtn');
    const clearTextBtn = document.getElementById('clearTextBtn');
    const stackContainer = document.getElementById('stackVisual');

    // 2. Instancia da nosa Pila (TAD)
    const undoStack = new Stack();

    // 3. Gardamos o estado INICIAL do editor (texto baleiro ou o que poida haber por defecto)
    let currentText = textarea.value;   // "" por defecto
    // Non apilamos o estado inicial (para que desfacer non borre todo sen historial, opcional)
    // Pero nun editor real, o primeiro desfacer non fai nada. Imos gardar un flag? Mellor:
    // Cada vez que o texto CAMBIA por ACCIÓN DO USUARIO (input) apilamos o estado PREVIO.
    // Así o primeiro cambio apila o baleiro, e desfacer volve a baleiro.

    // Función para actualizar a visualización da pila no HTML
    function renderStack() {
        const elements = undoStack.getAll();
        stackContainer.innerHTML = '';
        if (elements.length === 0) {
            stackContainer.innerHTML = '<div class="empty-stack">📭 Pila baleira<br>Sen historial para desfacer</div>';
            return;
        }
        // Amosar de ARRIBA (último) abaixo? visualmente usamos column reverse no CSS, pero mostramos todos.
        // Para que sexa claro: queremos que o "top" estea enriba visualmente.
        // Como .stack-container ten flex-direction: column-reverse, imos engadir os elementos
        // en orde normal (primeiro o máis antigo, último o máis recente) e o CSS invirte.
        // Así o último en apilar aparece arriba.
        for (let i = 0; i < elements.length; i++) {
            const itemDiv = document.createElement('div');
            itemDiv.className = 'stack-element';
            // Mostrar unha previsualización do texto gardado (cortamos se é longo)
            let displayText = elements[i];
            if (displayText.length > 28) {
                displayText = displayText.substring(0, 25) + '…';
            }
            // Escape para comiñas etc
            itemDiv.textContent = `📄 "${displayText}"`;
            if (i === elements.length - 1) {
                // Marcamos o elemento do top cun indicador
                itemDiv.style.border = "2px solid #facc15";
                itemDiv.style.background = "linear-gradient(135deg, #ffd966, #f59e0b)";
                itemDiv.style.fontWeight = "bold";
                // engadir un pequeno selo "TOP"
                const topBadge = document.createElement('span');
                topBadge.textContent = " 🔝";
                topBadge.style.fontSize = "0.7rem";
                topBadge.style.marginLeft = "6px";
                itemDiv.appendChild(topBadge);
            }
            stackContainer.appendChild(itemDiv);
        }
    }

    // Función para apilar o estado actual (chamada antes de modificar o texto)
    function saveCurrentStateToStack() {
        // Apilamos o texto actual (o que estaba antes do cambio)
        undoStack.push(currentText);
        renderStack();
    }

    // Función para desfacer: recuperar o último estado apilado
    function performUndo() {
        if (undoStack.isEmpty()) {
            // Non hai nada que desfacer
            // feedback visual breve (pode ser un chisco de animación, pero así está ben)
            undoButton.style.transform = "scale(0.96)";
            setTimeout(() => { undoButton.style.transform = ""; }, 120);
            return false;
        }
        // pop() devolve o estado anterior
        const previousState = undoStack.pop();
        if (previousState !== null) {
            // Actualizar o editor e o currentText
            textarea.value = previousState;
            currentText = previousState;
            renderStack();
            // feedback visual correcto
            undoButton.style.background = "#22c55e";
            setTimeout(() => { undoButton.style.background = "#3b82f6"; }, 200);
        }
        return true;
    }

    // Reseteo completo do historial (pila baleira) e opcionalmente texto a baleiro?
    function resetHistoryOnly() {
        undoStack.clear();
        renderStack();
        // non modificamos o texto actual, só limpamos historial
        // Pero para unha boa experiencia, avisamos visual
        resetStackBtn.style.transform = "scale(0.96)";
        setTimeout(() => { resetStackBtn.style.transform = ""; }, 120);
    }

    function resetFullEditor() {
        // Limpa texto, limpa historial
        textarea.value = "";
        currentText = "";
        undoStack.clear();
        renderStack();
        clearTextBtn.style.transform = "scale(0.96)";
        setTimeout(() => { clearTextBtn.style.transform = ""; }, 100);
    }

    // ---------- MANEXO DO EVENTO INPUT (cando o usuario modifica o texto) ----------
    // Necesitamos saber se o cambio vén do usuario ou programático (como desfacer ou limpar)
    // para non apilar estados duplicados nin infinitos.
    let isProgrammaticChange = false;

    function onUserTextChange() {
        if (isProgrammaticChange) {
            // Se o cambio foi causado por desfacer/limpar, non queremos apilar outro estado extra
            return;
        }
        // O usuario escribiu, pegou, cortou... Antes de actualizar currentText, apilamos o estado anterior.
        const oldText = currentText;
        const newText = textarea.value;
        if (oldText !== newText) {
            // Gardamos o estado previo (oldText) na pila
            saveCurrentStateToStack();   // apila currentText (o vello)
            currentText = newText;
        }
        // Se o texto é igual, non facemos nada (non debería ocorrer en input normal)
    }

    // Atopar o evento de entrada do usuario
    textarea.addEventListener('input', function() {
        if (!isProgrammaticChange) {
            onUserTextChange();
        }
    });

    // Desfacer (Ctrl+Z simulado e botón)
    undoButton.addEventListener('click', () => {
        isProgrammaticChange = true;
        performUndo();
        isProgrammaticChange = false;
    });

    // Reset do historial (non toca o texto)
    resetStackBtn.addEventListener('click', () => {
        isProgrammaticChange = true;
        resetHistoryOnly();
        isProgrammaticChange = false;
    });

    // Limpar texto + borrar historial
    clearTextBtn.addEventListener('click', () => {
        isProgrammaticChange = true;
        resetFullEditor();
        isProgrammaticChange = false;
    });

    // Tecla Ctrl+Z (ou Cmd+Z) para desfacer
    document.addEventListener('keydown', (e) => {
        if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
            e.preventDefault();
            isProgrammaticChange = true;
            performUndo();
            isProgrammaticChange = false;
        }
    });

    // Inicialización: non apilamos nada baleiro a non ser que o usuario empece a escribir.
    // Pero para que se vexa que a pila comeza baleira.
    renderStack();
    currentText = textarea.value;   // baleiro ao inicio

    // Pequeno detalle: se o usuario pulsa "Limpar texto" o texto queda baleiro,
    // e o historial tamén. Perfecto.
    // Se queremos que desfacer despois de limpar funcione, pero ao limpar reseteouse a pila.
    // Está ben para entender que o historial pérdese se o reiniciamos.
</script>
</body>
</html>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://educacion.gitbook.io/programacion/pila.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
