Torres de Hanói

Avanzado

Este es unEngineering, Multimodal AIflujo de automatización del dominio deautomatización que contiene 21 nodos.Utiliza principalmente nodos como If, Set, Code, ManualTrigger, ExecuteWorkflow. Implementación de algoritmos recursivos usando sub-flujos de trabajo: Demostración de la Torre de Hanoi

Requisitos previos
  • No hay requisitos previos especiales, puede importar y usarlo directamente
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "VPnclcR3gHg85eOV",
  "meta": {
    "instanceId": "1ee7910f98ee64be6f03d5c49b072eda83992583a161149dc94314ed0b0a2fe0"
  },
  "name": "Towers of Hanoi",
  "tags": [],
  "nodes": [
    {
      "id": "d0112e92-b3e0-4d97-b06d-382470864364",
      "name": "Establecer número de discos",
      "type": "n8n-nodes-base.set",
      "position": [
        912,
        1664
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c775d359-9599-494b-918c-3e46aae9274c",
              "name": "numberOfDiscs",
              "type": "number",
              "value": 4
            }
          ]
        }
      },
      "notesInFlow": true,
      "typeVersion": 3.4
    },
    {
      "id": "b76775a3-9cf4-4cb5-9945-4cb7d2df7436",
      "name": "Máximo 1 disco",
      "type": "n8n-nodes-base.if",
      "position": [
        752,
        1984
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "26c868df-4677-4ded-9ba5-7a69fc3cfd06",
              "operator": {
                "type": "number",
                "operation": "lte"
              },
              "leftValue": "={{ $json.numberOfDiscs }}",
              "rightValue": 1
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a4ce4e6c-cc21-43f3-b1ae-04768a1abee3",
      "name": "A B C",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        1328,
        1664
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": true
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "VPnclcR3gHg85eOV",
          "cachedResultName": "Towers of Hanoi"
        },
        "workflowInputs": {
          "value": {
            "logs": "={{ $json.logs }}",
            "stackX": "={{ $json.stackA }}",
            "stackY": "={{ $json.stackB }}",
            "stackZ": "={{ $json.stackC }}",
            "numberOfDiscs": "={{ $json.numberOfDiscs }}"
          },
          "schema": [
            {
              "id": "numberOfDiscs",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "numberOfDiscs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackX",
              "type": "object",
              "display": true,
              "required": false,
              "displayName": "stackX",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackY",
              "type": "object",
              "display": true,
              "required": false,
              "displayName": "stackY",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackZ",
              "type": "object",
              "display": true,
              "required": false,
              "displayName": "stackZ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "logs",
              "type": "array",
              "display": true,
              "required": false,
              "displayName": "logs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "notesInFlow": true,
      "typeVersion": 1.2
    },
    {
      "id": "5ef7690f-7554-47f5-8124-562edbba5a86",
      "name": "X Y Z",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        640,
        1984
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "numberOfDiscs",
              "type": "number"
            },
            {
              "name": "stackX",
              "type": "object"
            },
            {
              "name": "stackY",
              "type": "object"
            },
            {
              "name": "stackZ",
              "type": "object"
            },
            {
              "name": "logs",
              "type": "array"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "be89d88c-9814-440b-8d49-99fe49e65a4b",
      "name": "X a Z",
      "type": "n8n-nodes-base.code",
      "position": [
        1232,
        1968
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Move disc\nconst disc = $json.stackX.items.pop();\n$json.stackZ.items.push(disc);\n\n// Log\n$json.logs.push($json.stackX.name + \" \" + $json.stackZ.name + \" \" + disc);\n\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "81ad6f90-0689-43e9-b67b-911c91dade6a",
      "name": "X a Z",
      "type": "n8n-nodes-base.code",
      "position": [
        1232,
        2112
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Move disc\nconst disc = $json.stackX.items.pop();\n$json.stackZ.items.push(disc);\n\n// Log\n$json.logs.push($json.stackX.name + \" \" + $json.stackZ.name + \" \" + disc);\n\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "e9430884-2810-475f-90d2-9cffcfbaf9c8",
      "name": "Actualizar",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        2112
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Reset number of discs\n$json.numberOfDiscs += 1;\n\n// Reset stacks (XZY to XYZ)\nconst stack = $json.stackY;\n$json.stackY = $json.stackZ;\n$json.stackZ = stack;\n\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "ef117924-272e-4eb6-b098-f1a909ae0334",
      "name": "Actualizar",
      "type": "n8n-nodes-base.code",
      "position": [
        1520,
        2112
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Reset number of discs\n$json.numberOfDiscs += 1;\n\n// Reset stacks (YXZ to XYZ)\nconst stack = $json.stackY;\n$json.stackY = $json.stackX;\n$json.stackX = stack;\n\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "a3f48f91-44f9-41c2-963d-51c4d2f4e21d",
      "name": "Crear pilas",
      "type": "n8n-nodes-base.code",
      "position": [
        1120,
        1664
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Really check, if you want to waste computing energy. Recursion errors are hard enough. Best regards, Adrian\nconst min = 1;\nconst max = 5;\nif ($json.numberOfDiscs < min) {\n  $json.numberOfDiscs = min;\n}\nif ($json.numberOfDiscs > max) {\n  $json.numberOfDiscs = max;\n}\n\n// Create stack items\nlet items = [];\nfor (let i=$json.numberOfDiscs; i>0; i--) {\n  items.push(i);\n}\n\n// Set data\n$json.stackA = {};\n$json.stackA.name = \"A\";\n$json.stackA.items = items;\n$json.stackB = {};\n$json.stackB.name = \"B\";\n$json.stackB.items = [];\n$json.stackC = {};\n$json.stackC.name = \"C\";\n$json.stackC.items = [];\n$json.logs = [];\n\n// Return this n8n item\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "ade72738-15aa-4bcf-b98c-d4804eeb949e",
      "name": "X Z Y",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        944,
        2112
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "VPnclcR3gHg85eOV",
          "cachedResultName": "Towers of Hanoi"
        },
        "workflowInputs": {
          "value": {
            "logs": "={{ $json.logs }}",
            "stackX": "={{ $json.stackX }}",
            "stackY": "={{ $json.stackZ }}",
            "stackZ": "={{ $json.stackY }}",
            "numberOfDiscs": "={{ $json.numberOfDiscs - 1 }}"
          },
          "schema": [
            {
              "id": "numberOfDiscs",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "numberOfDiscs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackX",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackX",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackY",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackY",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackZ",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackZ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "logs",
              "type": "array",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "logs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "notesInFlow": true,
      "typeVersion": 1.2
    },
    {
      "id": "69fe66b5-2244-4ba8-a22f-507613f53f0b",
      "name": "Y X Z",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        1392,
        2112
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": true
        },
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "VPnclcR3gHg85eOV",
          "cachedResultName": "Towers of Hanoi"
        },
        "workflowInputs": {
          "value": {
            "logs": "={{ $json.logs }}",
            "stackX": "={{ $json.stackY }}",
            "stackY": "={{ $json.stackX }}",
            "stackZ": "={{ $json.stackZ }}",
            "numberOfDiscs": "={{ $json.numberOfDiscs - 1 }}"
          },
          "schema": [
            {
              "id": "numberOfDiscs",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "numberOfDiscs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackX",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackX",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackY",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackY",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stackZ",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "stackZ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "logs",
              "type": "array",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "logs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "notesInFlow": true,
      "typeVersion": 1.2
    },
    {
      "id": "01a8c211-6e7f-4ef2-a651-84ed77de8390",
      "name": "Solución",
      "type": "n8n-nodes-base.code",
      "position": [
        1536,
        1664
      ],
      "parameters": {
        "jsCode": "function logsToSentence(logs) {\n  return logs.map((entry, index) => {\n    const [from, to, disc] = entry.split(\" \");\n    let text;\n\n    if (index === 0) {\n      text = `Move disc ${disc} from ${from} to ${to}`;\n    } else if (index === 1) {\n      text = `then ${from} ${disc}→ ${to}`;\n    } else {\n      text = `${from} ${disc}→ ${to}`;\n    }\n\n    text += \",\";\n\n    if (index === 0 || index % 2 === 1) {\n      text += \"\\n\";\n    } else {\n      text += \" \";\n    }\n\n    return text;\n  }).join(\"\").slice(0, -2) + \".\";\n}\n\nreturn { \"solution\" : logsToSentence($input.first().json.logs) };"
      },
      "typeVersion": 2
    },
    {
      "id": "4f5aeb9a-37e0-4a02-9c0d-35dfe57cf70b",
      "name": "Entrada del usuario",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 448,
        "content": "### Input\n- **numberOfDiscs:** 4 "
      },
      "typeVersion": 1
    },
    {
      "id": "1633c56d-628c-4976-b00a-f2322bffc46f",
      "name": "Configuración",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1072,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 448,
        "content": "### Setup\n- **numberOfDiscs:** 4  \n- **stackA**\n  - **name:** A  \n  - **items:** 4, 3, 2, 1  \n- **stackB**\n  - **name:** B  \n  - **items:** -  \n- **stackC**\n  - **name:** C  \n  - **items:** -  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "187388ec-ec1c-4ee9-acf2-cad916f301b6",
      "name": "Resultado",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 448,
        "content": "### Result\n- **numberOfDiscs:** 4  \n- **stackX**\n  - **name:** A  \n  - **items:** -  \n- **stackY**\n  - **name:** B  \n  - **items:** -  \n- **stackZ**\n  - **name:** C  \n  - **items:** 4, 3, 2, 1"
      },
      "typeVersion": 1
    },
    {
      "id": "3a038abe-5ee2-4875-898a-d92910fc343a",
      "name": "Solución",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 448,
        "content": "### Solution\nMove disc 1 from A to B,\nthen A 2→ C,\nB 1→ C, A 3→ B,\nC 1→ A, C 2→ B,\nA 1→ B, A 4→ C,\nB 1→ C, B 2→ A,\nC 1→ A, B 3→ C,\nA 1→ B, A 2→ C,\nB 1→ C."
      },
      "typeVersion": 1
    },
    {
      "id": "2cdfe45e-3284-46b9-933c-c399ed0abfdc",
      "name": "Intercambiar",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        1840
      ],
      "parameters": {
        "color": 7,
        "width": 198,
        "height": 416,
        "content": "### Node input\n- **numberOfDiscs** -1 \n- stackX = **stackX** \n- stackY = **stackZ** \n- stackZ = **stackY** "
      },
      "typeVersion": 1
    },
    {
      "id": "f4cef2e4-e803-4b61-b197-56b8ef90685a",
      "name": "Mover",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        1840
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 416,
        "content": "### Node steps\n- disc = **stackX**.pop()\n- **stackZ**.push(disc)"
      },
      "typeVersion": 1
    },
    {
      "id": "b4ad8c17-ff19-4cd6-a848-207ec67918e1",
      "name": "Actualizar",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        1840
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 416,
        "content": "### Node steps\n- **numberOfDiscs** += 1\n- YXZ to XYZ\n  - stack = **stackY**\n  - **stackY** = **stackX**\n  - **stackX** = stack"
      },
      "typeVersion": 1
    },
    {
      "id": "89a9c41f-42c4-48c1-a187-a90a795f7bdd",
      "name": "Inicio",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        640,
        1664
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9baa2d1d-6d3b-4d8f-9d95-db479479a4e2",
      "name": "Torres de Hanói",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        1360
      ],
      "parameters": {
        "color": 5,
        "width": 576,
        "height": 1024,
        "content": "## Towers of Hanoi\nThis is an **example of using sub-workflow nodes** and a proof of concept showing that it’s possible to **solve and explain recursive problems with n8n**.\n\n### Task\nMove a stack of n disks from rod A to rod C, using rod B as auxiliary. Only one disk can be moved at a time, and no disk may be placed on a smaller disk.\n\n### Example\n```\nn=4\n     |          |          |\n     =          |          |\n    ===         |          |\n   =====        |          |\n  =======       |          |\n ---------  ---------  ---------\n     A          B          C\n```\n### Algorithm\n```\nprocedure Hanoi(n, X, Y, Z):\n  if n == 1:\n    move disk from X to Z\n  else:\n    Hanoi(n-1, X, Z, Y)\n    move disk from X to Z\n    Hanoi(n-1, Y, X, Z)\n```\nAnother variant, with better readability and no redundant code, but it includes empty n8n executions (when n is 0):\n```\nprocedure Hanoi(n, X, Y, Z):\n    if n > 0:\n        Hanoi(n-1, X, Z, Y)\n        move disk from X to Z\n        Hanoi(n-1, Y, X, Z)\n```\n### Notes\n- This is a learning example. In a real scenario, you would probably use an iterative approach with only a single code node.\n- The workflow variables X, Y, and Z represent the positions of the rods. E.g., if rods A and B are swapped, A is at position Y and B is at position X.\n- As the modified number of discs and positions are returned when a sub-workflow finishes, the \"Update\" nodes reset these values.\n- When experimenting with recursion, make sure to define a termination condition first. Also, be aware of the \"Restart workspace\" link in the [n8n Dashboard](https://app.n8n.cloud/manage).\n- Check Towers of Hanoi on [GitHub](https://github.com/adibaba/n8n.workflows)\n- Learn more about [Recursion on Wikipedia](https://en.wikipedia.org/w/index.php?title=Recursion_(computer_science)&oldid=1301600240#Towers_of_Hanoi)."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "50e00ac4-9c41-4e49-9390-4f196d97ad1a",
  "connections": {
    "a4ce4e6c-cc21-43f3-b1ae-04768a1abee3": {
      "main": [
        [
          {
            "node": "3a038abe-5ee2-4875-898a-d92910fc343a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "89a9c41f-42c4-48c1-a187-a90a795f7bdd": {
      "main": [
        [
          {
            "node": "d0112e92-b3e0-4d97-b06d-382470864364",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5ef7690f-7554-47f5-8124-562edbba5a86": {
      "main": [
        [
          {
            "node": "b76775a3-9cf4-4cb5-9945-4cb7d2df7436",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ade72738-15aa-4bcf-b98c-d4804eeb949e": {
      "main": [
        [
          {
            "node": "b4ad8c17-ff19-4cd6-a848-207ec67918e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "69fe66b5-2244-4ba8-a22f-507613f53f0b": {
      "main": [
        [
          {
            "node": "b4ad8c17-ff19-4cd6-a848-207ec67918e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b4ad8c17-ff19-4cd6-a848-207ec67918e1": {
      "main": [
        [
          {
            "node": "81ad6f90-0689-43e9-b67b-911c91dade6a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "81ad6f90-0689-43e9-b67b-911c91dade6a": {
      "main": [
        [
          {
            "node": "69fe66b5-2244-4ba8-a22f-507613f53f0b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b76775a3-9cf4-4cb5-9945-4cb7d2df7436": {
      "main": [
        [
          {
            "node": "81ad6f90-0689-43e9-b67b-911c91dade6a",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ade72738-15aa-4bcf-b98c-d4804eeb949e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a3f48f91-44f9-41c2-963d-51c4d2f4e21d": {
      "main": [
        [
          {
            "node": "a4ce4e6c-cc21-43f3-b1ae-04768a1abee3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d0112e92-b3e0-4d97-b06d-382470864364": {
      "main": [
        [
          {
            "node": "a3f48f91-44f9-41c2-963d-51c4d2f4e21d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Ingeniería, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos21
Categoría2
Tipos de nodos7
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Adrian

Adrian

@adrian

AI Software & Platform Engineer. Senior Technical Consultant, Associate Researcher (Data Science & Computer Science Education), Project Engineer, Master of Computer Science (M.Sc.)

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34