<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3459284654925679524</atom:id><lastBuildDate>Thu, 08 Oct 2026 07:17:34 +0000</lastBuildDate><category>System Programming</category><category>Generic</category><category>Data Structures</category><category>Design Patterns</category><category>Java</category><category>Networking</category><category>Strings</category><category>XML</category><category>C++</category><category>Sorting</category><category>Bitwise Operators</category><category>C</category><category>File Operations</category><category>Graphs</category><category>NLP</category><category>Packet Formats</category><category>Search Algorithm</category><category>Security</category><category>dynamic programming</category><category>natural language processing</category><category>space complexity</category><category>time complexity</category><category>AI tutorial</category><category>Agentic AI</category><category>Agents</category><category>Algorithmic solution</category><category>Algorithms</category><category>BFS</category><category>BST</category><category>Beam Search</category><category>Builder</category><category>Builder Design Pattern</category><category>C programming</category><category>COM</category><category>Circular queue</category><category>Code implementation</category><category>Coin denomination</category><category>Component Object Model</category><category>Cracking piggy bank puzzle</category><category>DAG</category><category>DFS</category><category>Decorator Design Pattern</category><category>Dijkstra</category><category>Dijkstra Java implementation</category><category>FTP</category><category>FTP implementation in C</category><category>Factory Method Design Pattern</category><category>File transfer protocol</category><category>Finite State Machine</category><category>Functions</category><category>GenAI</category><category>Java programming</category><category>Jupyter</category><category>KMP Algorithm</category><category>Knapsack problem algorithm</category><category>LCS problem</category><category>LLM</category><category>LLM Decoding</category><category>LangChain</category><category>Large Language Models</category><category>Libconfig</category><category>Map in C++</category><category>Memory</category><category>Money-saving challenge</category><category>Optimal change</category><category>Overloading</category><category>Polymorphism</category><category>Problem-solving</category><category>Prompt Engineering</category><category>Python</category><category>Quiver</category><category>RAG</category><category>Read configuration files</category><category>Recursive approach</category><category>Regular Expressions</category><category>SOAP</category><category>SSC 2018</category><category>SSC Adit card 2018</category><category>SSC Combined Graduate Level Examination 2012 Admit Card</category><category>SSC Exam 2018</category><category>Sentence Segmentation</category><category>Shortest Path Algorithm</category><category>Simplest Codings NLP</category><category>TST deletion</category><category>TST insertion</category><category>TST search</category><category>Ternary Search</category><category>Text Generation</category><category>Text Processing</category><category>Trie</category><category>Tutorial</category><category>Web Service</category><category>Xerces</category><category>abstract binary search tree</category><category>auto-suggestion</category><category>autocomplete</category><category>backtracking</category><category>bellman equation</category><category>bottom-up approach</category><category>data structure</category><category>decision making</category><category>dictionaries</category><category>efficiency</category><category>efficient string matching</category><category>epsilon-greedy</category><category>facade design pattern</category><category>gSOAP</category><category>knapsack problem code</category><category>knuth-morris-pratt algorithm</category><category>lcs dynamic programming table</category><category>longest common subsequence algorithm</category><category>machine learning</category><category>nlp in java</category><category>optimal solution</category><category>pattern preprocessing</category><category>prefix function</category><category>prefix search</category><category>q-learning</category><category>q-table</category><category>reconstruction</category><category>reinforcement learning</category><category>search algorithms</category><category>sentiment analysis</category><category>sentiment analysis in java</category><category>std::map in c++</category><category>string algorithms</category><category>string storage</category><title>Simplest Codings</title><description>Master programming effortlessly with Simplest Codings. From core algorithms and LLMs to clean code in Java, C++, and Python—get clear, bite-sized tutorials and practical developer guides for all skill levels.</description><link>http://simplestcodings.blogspot.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>83</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-4125874144587213792</guid><pubDate>Tue, 28 Jul 2026 06:28:16 +0000</pubDate><atom:updated>2026-07-28T12:04:27.061+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Agentic AI</category><category domain="http://www.blogger.com/atom/ns#">Agents</category><category domain="http://www.blogger.com/atom/ns#">GenAI</category><category domain="http://www.blogger.com/atom/ns#">Jupyter</category><category domain="http://www.blogger.com/atom/ns#">LangChain</category><category domain="http://www.blogger.com/atom/ns#">LLM</category><category domain="http://www.blogger.com/atom/ns#">Prompt Engineering</category><category domain="http://www.blogger.com/atom/ns#">Python</category><category domain="http://www.blogger.com/atom/ns#">RAG</category><category domain="http://www.blogger.com/atom/ns#">Tutorial</category><title>GenAI, Agents &amp; Agentic AI: A Complete Hands-On Notebook</title><description>&lt;style&gt;
    .post-body {
      font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
      line-height: 1.6;
      color: #24292e;
      max-width: 900px;
      margin: 0 auto;
      padding: 20px;
    }
    .post-body h1, .post-body h2, .post-body h3 {
      color: #0366d6;
      border-bottom: 1px solid #eaecef;
      padding-bottom: 0.3em;
      margin-top: 1.5em;
    }
    .post-body p { margin-bottom: 1em; }
    .post-body pre {
      background-color: #1e1e1e;
      color: #d4d4d4;
      padding: 16px;
      border-radius: 6px;
      overflow-x: auto;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 0.9em;
      line-height: 1.45;
    }
    .post-body code {
      background-color: #f6f8fa;
      color: #d73a49;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 85%;
    }
    .post-body pre code { background-color: transparent; color: inherit; padding: 0; }
    .post-body table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
      font-size: 0.95em;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
      border-radius: 6px;
      overflow: hidden;
    }
    .post-body th, .post-body td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #dddddd; }
    .post-body th { background-color: #0366d6; color: #ffffff; font-weight: 600; }
    .post-body tr:nth-of-type(even) { background-color: #f8f9fa; }
    .post-body tr:hover { background-color: #f1f3f5; }
    .post-body blockquote {
      margin: 1.5em 0;
      padding: 1em 1.2em;
      background-color: #f1f8ff;
      border-left: 4px solid #0366d6;
      color: #24292e;
      border-radius: 0 6px 6px 0;
    }
    .post-body ul, .post-body ol { padding-left: 20px; margin-bottom: 1em; }
    .post-body li { margin-bottom: 0.4em; }
    .post-body hr { border: 0; height: 1px; background: #e1e4e8; margin: 2em 0; }

    /* Visual Enhancement Components */
    .post-body .diagram-container {
      background-color: #ffffff;
      border: 1px solid #e1e4e8;
      border-radius: 8px;
      padding: 20px;
      margin: 25px 0;
      box-shadow: 0 2px 6px rgba(0,0,0,0.04);
      text-align: center;
    }
    .post-body .diagram-caption {
      font-size: 0.85em;
      color: #586069;
      margin-top: 10px;
      font-style: italic;
    }
    .post-body .pipeline-flow {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: center;
      gap: 10px;
      margin: 20px 0;
    }
    .post-body .pipeline-step {
      background: #f1f8ff;
      border: 1px solid #0366d6;
      color: #0366d6;
      padding: 10px 16px;
      border-radius: 20px;
      font-weight: bold;
      font-size: 0.9em;
    }
    .post-body .pipeline-step.highlight {
      background: #0366d6;
      color: #ffffff;
      box-shadow: 0 2px 4px rgba(3,102,214,0.3);
    }
    .post-body .pipeline-arrow {
      color: #586069;
      font-weight: bold;
    }
    .post-body .badge {
      display: inline-block;
      padding: 2px 8px;
      font-size: 0.75em;
      font-weight: 600;
      border-radius: 12px;
      margin-left: 6px;
    }
    .post-body .badge-success { background: #dcffe4; color: #1a7f37; }
    .post-body .badge-danger { background: #ffebe9; color: #cf222e; }
    .post-body .badge-warning { background: #fff8c5; color: #9a6700; }

    .toc-box {
      background: #f6f8fa;
      border: 1px solid #e1e4e8;
      border-radius: 8px;
      padding: 18px 24px;
      margin: 24px 0;
    }
    .toc-box h4 {
      margin: 0 0 12px 0;
      color: #0366d6;
      font-size: 1em;
      border: none;
    }
    .toc-box ol { margin: 0; padding-left: 22px; }
    .toc-box li { margin-bottom: 6px; font-size: 0.95em; }

    .nb-download-bar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      background: #f6f8fa;
      border: 1px solid #e1e4e8;
      border-radius: 8px;
      padding: 12px 18px;
      margin: 28px 0 8px;
      font-size: 0.85em;
      color: #586069;
    }
    .nb-download-bar a {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 6px 14px;
      background: #0366d6;
      color: #ffffff;
      border-radius: 4px;
      font-weight: 600;
      text-decoration: none;
    }
    .nb-download-bar a:hover { background: #0256b9; }
&lt;/style&gt;

&lt;div class=&quot;post-body&quot;&gt;

  &lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjuLCskHD1fwWj6QJ7uu_Gka09bErlLToO31qf9MvbhU9JFiALsZVvuFP7KudEdiHIj2hXJnbpLJdtBeHE495uitk5yx9Vu2Ar-Qz8f4-72HG0UeAIcA2gLrloEXKi-Sqslt_a9geaBo_OWbIhy94p5-_Hya3AZOJb0YRywZwHNmyma5HP_V2yXwsStBvo&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;2816&quot; height=&quot;349&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjuLCskHD1fwWj6QJ7uu_Gka09bErlLToO31qf9MvbhU9JFiALsZVvuFP7KudEdiHIj2hXJnbpLJdtBeHE495uitk5yx9Vu2Ar-Qz8f4-72HG0UeAIcA2gLrloEXKi-Sqslt_a9geaBo_OWbIhy94p5-_Hya3AZOJb0YRywZwHNmyma5HP_V2yXwsStBvo&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;
    Generative AI has gone from research curiosity to production reality at remarkable speed.
    Large language models can now summarise documents, write code, answer questions, and—when
    given tools—autonomously take actions in the world. But getting from &lt;em&gt;&quot;I&#39;ve heard of
    ChatGPT&quot;&lt;/em&gt; to &lt;em&gt;&quot;I can build my own agentic system&quot;&lt;/em&gt; requires bridging a lot of
    conceptual gaps.
  &lt;/p&gt;
  &lt;p&gt;
    This post contains an interactive Jupyter notebook that walks you through that entire
    journey—from spinning up your first LLM call to orchestrating a multi-agent pipeline—all
    in one place, with runnable Python code at every step.
  &lt;/p&gt;

  &lt;blockquote&gt;
    &lt;strong&gt;Who is this for?&lt;/strong&gt; Developers with Python experience who are new to LLMs
    and want a practical, end-to-end foundation rather than scattered tutorials.
    The notebook targets &lt;em&gt;beginner → intermediate&lt;/em&gt; level and supports four providers:
    &lt;strong&gt;Ollama&lt;/strong&gt; (fully local), &lt;strong&gt;OpenAI&lt;/strong&gt;, &lt;strong&gt;Google Gemini&lt;/strong&gt;,
    and &lt;strong&gt;DeepSeek&lt;/strong&gt;—so you can follow along regardless of which API keys you have.
  &lt;/blockquote&gt;

  &lt;h3&gt;What&#39;s Inside&lt;/h3&gt;

  &lt;p&gt;The notebook is structured as eleven self-contained sections that build on each other:&lt;/p&gt;

  &lt;div class=&quot;toc-box&quot;&gt;
    &lt;h4&gt;Table of Contents&lt;/h4&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;Setup &amp;amp; Provider Configuration&lt;/strong&gt; — install dependencies, pick your LLM provider, and configure credentials in one place.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;LLM Basics&lt;/strong&gt; — your first &lt;code&gt;invoke()&lt;/code&gt; call, understanding messages, roles, and the chat model interface.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Prompt Engineering&lt;/strong&gt; — system prompts, few-shot examples, temperature, and structured output with &lt;code&gt;Pydantic&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Chains&lt;/strong&gt; — composing steps with LangChain Expression Language (LCEL): prompt → model → parser pipelines.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Memory &amp;amp; Conversation History&lt;/strong&gt; — stateful chat, &lt;code&gt;ConversationBufferMemory&lt;/code&gt;, and trimming strategies.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt; — embedding documents into &lt;code&gt;Chroma&lt;/code&gt;, semantic search, and grounded Q&amp;amp;A.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Tools &amp;amp; Function Calling&lt;/strong&gt; — define tools, bind them to the model, and handle tool invocation responses.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Agents&lt;/strong&gt; — &lt;code&gt;ReAct&lt;/code&gt; loop, &lt;code&gt;create_react_agent&lt;/code&gt;, and letting the model decide which tools to call.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Multi-Agent Systems&lt;/strong&gt; — routing between specialist agents with a supervisor pattern.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Agentic Patterns&lt;/strong&gt; — planning, reflection, self-critique, and iterative refinement loops.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Mini Agentic App&lt;/strong&gt; — everything wired together into one small but complete application.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;

  &lt;h3&gt;How to Run It Yourself&lt;/h3&gt;

  &lt;p&gt;You can clone or download the notebook and run it locally. Prerequisites:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Python 3.10 or later&lt;/li&gt;
    &lt;li&gt;A running &lt;a href=&quot;https://ollama.com&quot;&gt;Ollama&lt;/a&gt; instance &lt;em&gt;or&lt;/em&gt; an API key for OpenAI / Gemini / DeepSeek&lt;/li&gt;
    &lt;li&gt;Run the first cell (&lt;code&gt;%pip install ...&lt;/code&gt;) to install all dependencies&lt;/li&gt;
    &lt;li&gt;Set your provider and credentials in the &lt;strong&gt;Section 1 config cell&lt;/strong&gt;—the rest of the notebook picks them up automatically&lt;/li&gt;
  &lt;/ul&gt;

  &lt;div class=&quot;diagram-container&quot;&gt;
    &lt;div class=&quot;pipeline-flow&quot;&gt;
      &lt;div class=&quot;pipeline-step highlight&quot;&gt;Configure Provider&lt;/div&gt;
      &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
      &lt;div class=&quot;pipeline-step&quot;&gt;Run Cells Top-to-Bottom&lt;/div&gt;
      &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
      &lt;div class=&quot;pipeline-step&quot;&gt;Experiment &amp;amp; Modify&lt;/div&gt;
      &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
      &lt;div class=&quot;pipeline-step highlight&quot;&gt;Build Your Own Agent&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;diagram-caption&quot;&gt;The intended workflow: configure once, execute sequentially, then diverge and experiment.&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;The Notebook&lt;/h3&gt;

  &lt;p&gt;
    The full notebook is below. Each section opens with a short explanation followed by
    runnable Python code cells. Download it to run locally, or read through it here as a
    reference.
  &lt;/p&gt;

  &lt;div class=&quot;nb-download-bar&quot;&gt;
    &lt;span&gt; genai_learning.ipynb — GenAI, Agents &amp;amp; Agentic AI · Complete Learning Notebook&lt;/span&gt;
    &lt;a download=&quot;genai_learning.ipynb&quot; href=&quot;data:application/octet-stream;base64,ewogImNlbGxzIjogWwogIHsKICAgImNlbGxfdHlwZSI6ICJtYXJrZG93biIsCiAgICJpZCI6ICJlZGMxNWI0MyIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAic291cmNlIjogWwogICAgIiMgR2VuQUksIEFnZW50cyAmIEFnZW50aWMgQUkgXHUyMDE0IENvbXBsZXRlIExlYXJuaW5nIE5vdGVib29rXG4iLAogICAgIlxuIiwKICAgICIqKkxldmVsOioqIEJlZ2lubmVyIFx1MjE5MiBJbnRlcm1lZGlhdGUgIFxuIiwKICAgICIqKlByb3ZpZGVycyBzdXBwb3J0ZWQ6KiogT2xsYW1hIChsb2NhbCkgXHUwMGI3IE9wZW5BSSBcdTAwYjcgR29vZ2xlIEdlbWluaSBcdTAwYjcgRGVlcFNlZWsgIFxuIiwKICAgICJcbiIsCiAgICAiLS0tXG4iLAogICAgIlxuIiwKICAgICIjIyBMZWFybmluZyBQYXRoXG4iLAogICAgIlxuIiwKICAgICJ8ICMgfCBUb3BpYyB8IENvbmNlcHRzIENvdmVyZWQgfFxuIiwKICAgICJ8LS0tfC0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tfFxuIiwKICAgICJ8IDEgfCBTZXR1cCAmIFByb3ZpZGVyIENvbmZpZyB8IEluc3RhbGwgbGlicywgY29uZmlndXJlIGtleXMsIHBpY2sgYSBwcm92aWRlciB8XG4iLAogICAgInwgMiB8IExMTSBCYXNpY3MgfCBUb2tlbnMsIHRlbXBlcmF0dXJlLCBpbmZlcmVuY2UsIGNvbXBsZXRpb24gdnMgY2hhdCB8XG4iLAogICAgInwgMyB8IFByb21wdCBFbmdpbmVlcmluZyB8IFplcm8tc2hvdCwgZmV3LXNob3QsIENvVCwgc3lzdGVtIHByb21wdHMsIHRlbXBsYXRlcyB8XG4iLAogICAgInwgNCB8IENoYWlucyB8IFNlcXVlbnRpYWwgY2hhaW5zLCBwcm9tcHQgXHUyMTkyIExMTSBcdTIxOTIgcGFyc2VyIHxcbiIsCiAgICAifCA1IHwgTWVtb3J5IHwgQ29udmVyc2F0aW9uIGhpc3RvcnksIGJ1ZmZlciwgc3VtbWFyeSBtZW1vcnkgfFxuIiwKICAgICJ8IDYgfCBSQUcgKFJldHJpZXZhbC1BdWdtZW50ZWQgR2VuZXJhdGlvbikgfCBFbWJlZGRpbmdzLCB2ZWN0b3Igc3RvcmVzLCByZXRyaWV2YWwsIFEmQSB8XG4iLAogICAgInwgNyB8IFRvb2xzICYgRnVuY3Rpb24gQ2FsbGluZyB8IERlZmluaW5nIHRvb2xzLCBzdHJ1Y3R1cmVkIG91dHB1dCwgdG9vbCB1c2UgfFxuIiwKICAgICJ8IDggfCBBZ2VudHMgfCBSZUFjdCBhZ2VudCwgdG9vbCBzZWxlY3Rpb24sIHJlYXNvbmluZyBsb29wIHxcbiIsCiAgICAifCA5IHwgTXVsdGktQWdlbnQgU3lzdGVtcyB8IE9yY2hlc3RyYXRvci93b3JrZXIsIGhhbmRvZmZzLCBwYXJhbGxlbGlzbSB8XG4iLAogICAgInwgMTAgfCBBZ2VudGljIFBhdHRlcm5zIHwgUGxhbm5pbmcsIHJlZmxlY3Rpb24sIHNlbGYtY3JpdGlxdWUsIGxvb3BzIHxcbiIsCiAgICAiXG4iLAogICAgIj4gKipUaXA6KiogUnVuIGNlbGxzIHRvcC10by1ib3R0b20uIFNldCB5b3VyIHByb3ZpZGVyIG9uY2UgaW4gU2VjdGlvbiAxIGFuZCBldmVyeXRoaW5nIGVsc2UgYWRhcHRzLiIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogIm1hcmtkb3duIiwKICAgImlkIjogIjY5YzQwYmYzIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJzb3VyY2UiOiBbCiAgICAiLS0tXG4iLAogICAgIiMjIFNlY3Rpb24gMSBcdTIwMTQgU2V0dXAgJiBQcm92aWRlciBDb25maWd1cmF0aW9uIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYjJjZTYzMTkiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIEluc3RhbGwgYWxsIHJlcXVpcmVkIHBhY2thZ2VzXG4iLAogICAgIiMgUmUtcnVuIHRoaXMgY2VsbCBhbnkgdGltZSB5b3Ugc3RhcnQgYSBmcmVzaCBlbnZpcm9ubWVudFxuIiwKICAgICIjIFJlbW92ZSAtdiBpZiB5b3Ugd2FudCBxdWlldCBvdXRwdXQ7IGFkZCAtcSBmb3Igc2lsZW50IG1vZGVcbiIsCiAgICAiJXBpcCBpbnN0YWxsIC12IFxcXG4iLAogICAgIiAgICBsYW5nY2hhaW4gXFxcbiIsCiAgICAiICAgIGxhbmdjaGFpbi1vbGxhbWEgXFxcbiIsCiAgICAiICAgIGxhbmdjaGFpbi1vcGVuYWkgXFxcbiIsCiAgICAiICAgIGxhbmdjaGFpbi1nb29nbGUtZ2VuYWkgXFxcbiIsCiAgICAiICAgIGxhbmdjaGFpbi1jaHJvbWEgXFxcbiIsCiAgICAiICAgIGxhbmdjaGFpbi1jb3JlIFxcXG4iLAogICAgIiAgICBsYW5nZ3JhcGggXFxcbiIsCiAgICAiICAgIGNocm9tYWRiIFxcXG4iLAogICAgIiAgICBvbGxhbWEgXFxcbiIsCiAgICAiICAgIGdvb2dsZS1nZW5lcmF0aXZlYWkgXFxcbiIsCiAgICAiICAgIG9wZW5haSBcXFxuIiwKICAgICIgICAgdGlrdG9rZW4gXFxcbiIsCiAgICAiICAgIGZhaXNzLWNwdSBcXFxuIiwKICAgICIgICAgc2VudGVuY2UtdHJhbnNmb3JtZXJzIFxcXG4iLAogICAgIiAgICBweXBkZiBcXFxuIiwKICAgICIgICAgaHR0cHggXFxcbiIsCiAgICAiICAgIGlweXdpZGdldHNcbiIsCiAgICAicHJpbnQoXCJBbGwgcGFja2FnZXMgaW5zdGFsbGVkLlwiKVxuIiwKICAgICJcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYjZiNDk2ZDciLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwKICAgICIjIENPTkZJR1VSRSBZT1VSIFBST1ZJREVSIEhFUkUgXHUyMDE0IGNoYW5nZSBQUk9WSURFUiBhbmQgZmlsbCBpblxuIiwKICAgICIjIHRoZSByZWxldmFudCBrZXkvbW9kZWwuIEV2ZXJ5dGhpbmcgZWxzZSBpbiB0aGUgbm90ZWJvb2tcbiIsCiAgICAiIyB1c2VzIGBsbG1gIGFuZCBgZW1iZWRkaW5nc2AgZGVmaW5lZCBiZWxvdy5cbiIsCiAgICAiIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsCiAgICAiXG4iLAogICAgImltcG9ydCBvc1xuIiwKICAgICJcbiIsCiAgICAiIyBDaG9vc2U6IFwib2xsYW1hXCIgfCBcIm9wZW5haVwiIHwgXCJnZW1pbmlcIiB8IFwiZGVlcHNlZWtcIlxuIiwKICAgICJQUk9WSURFUiA9IFwib2xsYW1hXCJcbiIsCiAgICAiXG4iLAogICAgIiMgLS0tIE9sbGFtYSAocnVucyBsb2NhbGx5LCBubyBrZXkgbmVlZGVkKSAtLS1cbiIsCiAgICAiT0xMQU1BX0JBU0VfVVJMICA9IFwiaHR0cDovL2xvY2FsaG9zdDoxMTQzNFwiXG4iLAogICAgIk9MTEFNQV9NT0RFTCAgICAgPSBcImxsYW1hMy4yOmxhdGVzdFwiICAgIyBjaGFuZ2UgdG8gYW55IG1vZGVsIHlvdSBoYXZlIHB1bGxlZFxuIiwKICAgICJPTExBTUFfRU1CRUQgICAgID0gXCJub21pYy1lbWJlZC10ZXh0OmxhdGVzdFwiXG4iLAogICAgIlxuIiwKICAgICIjIC0tLSBPcGVuQUkgLS0tXG4iLAogICAgIk9QRU5BSV9BUElfS0VZICAgPSBvcy5nZXRlbnYoXCJPUEVOQUlfQVBJX0tFWVwiLCBcInNrLS4uLlwiKVxuIiwKICAgICJPUEVOQUlfTU9ERUwgICAgID0gXCJncHQtNG8tbWluaVwiXG4iLAogICAgIlxuIiwKICAgICIjIC0tLSBHb29nbGUgR2VtaW5pIC0tLVxuIiwKICAgICJHT09HTEVfQVBJX0tFWSAgID0gb3MuZ2V0ZW52KFwiR09PR0xFX0FQSV9LRVlcIiwgXCIuLi5cIilcbiIsCiAgICAiR0VNSU5JX01PREVMICAgICA9IFwiZ2VtaW5pLTEuNS1mbGFzaFwiXG4iLAogICAgIlxuIiwKICAgICIjIC0tLSBEZWVwU2VlayAoT3BlbkFJLWNvbXBhdGlibGUgZW5kcG9pbnQpIC0tLVxuIiwKICAgICJERUVQU0VFS19BUElfS0VZID0gb3MuZ2V0ZW52KFwiREVFUFNFRUtfQVBJX0tFWVwiLCBcInNrLS4uLlwiKVxuIiwKICAgICJERUVQU0VFS19NT0RFTCAgID0gXCJkZWVwc2Vlay1jaGF0XCJcbiIsCiAgICAiREVFUFNFRUtfQkFTRV9VUkwgPSBcImh0dHBzOi8vYXBpLmRlZXBzZWVrLmNvbS92MVwiXG4iLAogICAgIlxuIiwKICAgICJwcmludChmXCJQcm92aWRlciBzZXQgdG86IHtQUk9WSURFUn1cIikiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIxOGQzZjhhMCIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgQnVpbGQgdGhlIHNoYXJlZCBgbGxtYCBhbmQgYGVtYmVkZGluZ3NgIG9iamVjdHMgdXNlZCB0aHJvdWdob3V0XG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUubGFuZ3VhZ2VfbW9kZWxzLmNoYXRfbW9kZWxzIGltcG9ydCBCYXNlQ2hhdE1vZGVsXG4iLAogICAgIlxuIiwKICAgICJpZiBQUk9WSURFUiA9PSBcIm9sbGFtYVwiOlxuIiwKICAgICIgICAgZnJvbSBsYW5nY2hhaW5fb2xsYW1hIGltcG9ydCBDaGF0T2xsYW1hLCBPbGxhbWFFbWJlZGRpbmdzXG4iLAogICAgIiAgICBsbG0gPSBDaGF0T2xsYW1hKG1vZGVsPU9MTEFNQV9NT0RFTCwgYmFzZV91cmw9T0xMQU1BX0JBU0VfVVJMLCB0ZW1wZXJhdHVyZT0wLjcpXG4iLAogICAgIiAgICBlbWJlZGRpbmdzID0gT2xsYW1hRW1iZWRkaW5ncyhtb2RlbD1PTExBTUFfRU1CRUQsIGJhc2VfdXJsPU9MTEFNQV9CQVNFX1VSTClcbiIsCiAgICAiXG4iLAogICAgImVsaWYgUFJPVklERVIgPT0gXCJvcGVuYWlcIjpcbiIsCiAgICAiICAgIGZyb20gbGFuZ2NoYWluX29wZW5haSBpbXBvcnQgQ2hhdE9wZW5BSSwgT3BlbkFJRW1iZWRkaW5nc1xuIiwKICAgICIgICAgbGxtID0gQ2hhdE9wZW5BSShtb2RlbD1PUEVOQUlfTU9ERUwsIGFwaV9rZXk9T1BFTkFJX0FQSV9LRVksIHRlbXBlcmF0dXJlPTAuNylcbiIsCiAgICAiICAgIGVtYmVkZGluZ3MgPSBPcGVuQUlFbWJlZGRpbmdzKGFwaV9rZXk9T1BFTkFJX0FQSV9LRVkpXG4iLAogICAgIlxuIiwKICAgICJlbGlmIFBST1ZJREVSID09IFwiZ2VtaW5pXCI6XG4iLAogICAgIiAgICBmcm9tIGxhbmdjaGFpbl9nb29nbGVfZ2VuYWkgaW1wb3J0IENoYXRHb29nbGVHZW5lcmF0aXZlQUksIEdvb2dsZUdlbmVyYXRpdmVBSUVtYmVkZGluZ3NcbiIsCiAgICAiICAgIGxsbSA9IENoYXRHb29nbGVHZW5lcmF0aXZlQUkobW9kZWw9R0VNSU5JX01PREVMLCBnb29nbGVfYXBpX2tleT1HT09HTEVfQVBJX0tFWSwgdGVtcGVyYXR1cmU9MC43KVxuIiwKICAgICIgICAgZW1iZWRkaW5ncyA9IEdvb2dsZUdlbmVyYXRpdmVBSUVtYmVkZGluZ3MobW9kZWw9XCJtb2RlbHMvZW1iZWRkaW5nLTAwMVwiLCBnb29nbGVfYXBpX2tleT1HT09HTEVfQVBJX0tFWSlcbiIsCiAgICAiXG4iLAogICAgImVsaWYgUFJPVklERVIgPT0gXCJkZWVwc2Vla1wiOlxuIiwKICAgICIgICAgZnJvbSBsYW5nY2hhaW5fb3BlbmFpIGltcG9ydCBDaGF0T3BlbkFJLCBPcGVuQUlFbWJlZGRpbmdzXG4iLAogICAgIiAgICBsbG0gPSBDaGF0T3BlbkFJKFxuIiwKICAgICIgICAgICAgIG1vZGVsPURFRVBTRUVLX01PREVMLFxuIiwKICAgICIgICAgICAgIGFwaV9rZXk9REVFUFNFRUtfQVBJX0tFWSxcbiIsCiAgICAiICAgICAgICBiYXNlX3VybD1ERUVQU0VFS19CQVNFX1VSTCxcbiIsCiAgICAiICAgICAgICB0ZW1wZXJhdHVyZT0wLjdcbiIsCiAgICAiICAgIClcbiIsCiAgICAiICAgICMgRGVlcFNlZWsgZG9lcyBub3QgZXhwb3NlIGVtYmVkZGluZ3M7IGZhbGwgYmFjayB0byBPbGxhbWEgbG9jYWwgZW1iZWRkaW5nc1xuIiwKICAgICIgICAgZnJvbSBsYW5nY2hhaW5fb2xsYW1hIGltcG9ydCBPbGxhbWFFbWJlZGRpbmdzXG4iLAogICAgIiAgICBlbWJlZGRpbmdzID0gT2xsYW1hRW1iZWRkaW5ncyhtb2RlbD1PTExBTUFfRU1CRUQsIGJhc2VfdXJsPU9MTEFNQV9CQVNFX1VSTClcbiIsCiAgICAiXG4iLAogICAgImVsc2U6XG4iLAogICAgIiAgICByYWlzZSBWYWx1ZUVycm9yKGZcIlVua25vd24gcHJvdmlkZXI6IHtQUk9WSURFUn1cIilcbiIsCiAgICAiXG4iLAogICAgInByaW50KGZcIkxMTSByZWFkeToge2xsbX1cIilcbiIsCiAgICAicHJpbnQoZlwiRW1iZWRkaW5ncyByZWFkeToge2VtYmVkZGluZ3N9XCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAibWFya2Rvd24iLAogICAiaWQiOiAiZTVhNWNkMjQiLAogICAibWV0YWRhdGEiOiB7fSwKICAgInNvdXJjZSI6IFsKICAgICItLS1cbiIsCiAgICAiIyMgU2VjdGlvbiAyIFx1MjAxNCBMTE0gQmFzaWNzXG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqVG9rZW4qKjogc21hbGxlc3QgdW5pdCBvZiB0ZXh0IHRoZSBtb2RlbCBwcm9jZXNzZXMgKH4wLjc1IHdvcmRzKVxuIiwKICAgICItICoqVGVtcGVyYXR1cmUqKjogY29udHJvbHMgcmFuZG9tbmVzcyAoMCA9IGRldGVybWluaXN0aWMsIDErID0gY3JlYXRpdmUpXG4iLAogICAgIi0gKipDb250ZXh0IHdpbmRvdyoqOiBtYXggdG9rZW5zIHRoZSBtb2RlbCBjYW4gc2VlIGF0IG9uY2VcbiIsCiAgICAiLSAqKkNvbXBsZXRpb24gdnMgQ2hhdCoqOiBvbGRlciBtb2RlbHMgZG8gdGV4dCBjb21wbGV0aW9uOyBtb2Rlcm4gbW9kZWxzIHVzZSBhIGNoYXQgKG1lc3NhZ2UpIGZvcm1hdFxuIiwKICAgICItICoqU3lzdGVtIC8gSHVtYW4gLyBBSSBtZXNzYWdlcyoqOiB0aGUgdGhyZWUgcm9sZXMgaW4gYSBjb252ZXJzYXRpb24iCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICI3YjA4M2ZlYyIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgMmEuIFNpbXBsZSBzaW5nbGUtdHVybiBjYWxsXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBIdW1hbk1lc3NhZ2VcbiIsCiAgICAiXG4iLAogICAgInJlc3BvbnNlID0gbGxtLmludm9rZShbSHVtYW5NZXNzYWdlKGNvbnRlbnQ9XCJXaGF0IGlzIGEgbGFyZ2UgbGFuZ3VhZ2UgbW9kZWw/IEV4cGxhaW4gaW4gMyBzZW50ZW5jZXMuXCIpXSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihyZXNwb25zZS5jb250ZW50KSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICI1OTRmY2IzYiIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgMmIuIFN5c3RlbSArIEh1bWFuIG1lc3NhZ2VzXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBTeXN0ZW1NZXNzYWdlLCBIdW1hbk1lc3NhZ2VcbiIsCiAgICAiXG4iLAogICAgIm1lc3NhZ2VzID0gW1xuIiwKICAgICIgICAgU3lzdGVtTWVzc2FnZShjb250ZW50PVwiWW91IGFyZSBhIGNvbmNpc2UgdGVjaG5pY2FsIHR1dG9yLiBBbHdheXMgYW5zd2VyIGluIGJ1bGxldCBwb2ludHMuXCIpLFxuIiwKICAgICIgICAgSHVtYW5NZXNzYWdlKGNvbnRlbnQ9XCJXaGF0IGFyZSB0b2tlbnMgaW4gdGhlIGNvbnRleHQgb2YgTExNcz9cIilcbiIsCiAgICAiXVxuIiwKICAgICJyZXNwb25zZSA9IGxsbS5pbnZva2UobWVzc2FnZXMpXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24ocmVzcG9uc2UuY29udGVudCkpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYTc2MzEzM2QiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDJjLiBUZW1wZXJhdHVyZSBlZmZlY3QgXHUyMDE0IGNvbXBhcmUgZGV0ZXJtaW5pc3RpYyB2cyBjcmVhdGl2ZSBvdXRwdXRcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUubWVzc2FnZXMgaW1wb3J0IEh1bWFuTWVzc2FnZVxuIiwKICAgICJcbiIsCiAgICAiaWYgUFJPVklERVIgPT0gXCJvbGxhbWFcIjpcbiIsCiAgICAiICAgIGZyb20gbGFuZ2NoYWluX29sbGFtYSBpbXBvcnQgQ2hhdE9sbGFtYVxuIiwKICAgICIgICAgbGxtX2NvbGQgPSBDaGF0T2xsYW1hKG1vZGVsPU9MTEFNQV9NT0RFTCwgYmFzZV91cmw9T0xMQU1BX0JBU0VfVVJMLCB0ZW1wZXJhdHVyZT0wLjApXG4iLAogICAgIiAgICBsbG1faG90ICA9IENoYXRPbGxhbWEobW9kZWw9T0xMQU1BX01PREVMLCBiYXNlX3VybD1PTExBTUFfQkFTRV9VUkwsIHRlbXBlcmF0dXJlPTEuMilcbiIsCiAgICAiZWxpZiBQUk9WSURFUiA9PSBcIm9wZW5haVwiOlxuIiwKICAgICIgICAgZnJvbSBsYW5nY2hhaW5fb3BlbmFpIGltcG9ydCBDaGF0T3BlbkFJXG4iLAogICAgIiAgICBsbG1fY29sZCA9IENoYXRPcGVuQUkobW9kZWw9T1BFTkFJX01PREVMLCBhcGlfa2V5PU9QRU5BSV9BUElfS0VZLCB0ZW1wZXJhdHVyZT0wLjApXG4iLAogICAgIiAgICBsbG1faG90ICA9IENoYXRPcGVuQUkobW9kZWw9T1BFTkFJX01PREVMLCBhcGlfa2V5PU9QRU5BSV9BUElfS0VZLCB0ZW1wZXJhdHVyZT0xLjIpXG4iLAogICAgImVsaWYgUFJPVklERVIgPT0gXCJnZW1pbmlcIjpcbiIsCiAgICAiICAgIGZyb20gbGFuZ2NoYWluX2dvb2dsZV9nZW5haSBpbXBvcnQgQ2hhdEdvb2dsZUdlbmVyYXRpdmVBSVxuIiwKICAgICIgICAgbGxtX2NvbGQgPSBDaGF0R29vZ2xlR2VuZXJhdGl2ZUFJKG1vZGVsPUdFTUlOSV9NT0RFTCwgZ29vZ2xlX2FwaV9rZXk9R09PR0xFX0FQSV9LRVksIHRlbXBlcmF0dXJlPTAuMClcbiIsCiAgICAiICAgIGxsbV9ob3QgID0gQ2hhdEdvb2dsZUdlbmVyYXRpdmVBSShtb2RlbD1HRU1JTklfTU9ERUwsIGdvb2dsZV9hcGlfa2V5PUdPT0dMRV9BUElfS0VZLCB0ZW1wZXJhdHVyZT0xLjApXG4iLAogICAgImVsc2U6XG4iLAogICAgIiAgICBsbG1fY29sZCA9IGxsbV9ob3QgPSBsbG1cbiIsCiAgICAiXG4iLAogICAgInF1ZXN0aW9uID0gW0h1bWFuTWVzc2FnZShjb250ZW50PVwiR2l2ZSBtZSBvbmUgY3JlYXRpdmUgbmFtZSBmb3IgYW4gQUkgYXNzaXN0YW50LlwiKV1cbiIsCiAgICAiXG4iLAogICAgImNvbGRfbmFtZXMgPSBbbGxtX2NvbGQuaW52b2tlKHF1ZXN0aW9uKS5jb250ZW50LnN0cmlwKCkgZm9yIF8gaW4gcmFuZ2UoMyldXG4iLAogICAgImhvdF9uYW1lcyAgPSBbbGxtX2hvdC5pbnZva2UocXVlc3Rpb24pLmNvbnRlbnQuc3RyaXAoKSAgZm9yIF8gaW4gcmFuZ2UoMyldXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiIyMjIENvbGQgKGRldGVybWluaXN0aWMsIHRlbXBlcmF0dXJlPTApXFxuXCIgKyBcIlxcblwiLmpvaW4oZlwiLSB7bn1cIiBmb3IgbiBpbiBjb2xkX25hbWVzKSkpXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oXCIjIyMgSG90IChjcmVhdGl2ZSwgdGVtcGVyYXR1cmU9MS4yKVxcblwiICAgICArIFwiXFxuXCIuam9pbihmXCItIHtufVwiIGZvciBuIGluIGhvdF9uYW1lcykpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjc2ZjdmZDZlIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyAyZC4gU3RyZWFtaW5nIG91dHB1dCBcdTIwMTQgc2VlIHRva2VucyBhcnJpdmUgaW4gcmVhbC10aW1lXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBIdW1hbk1lc3NhZ2VcbiIsCiAgICAiXG4iLAogICAgImNodW5rcyA9IFtdXG4iLAogICAgImZvciBjaHVuayBpbiBsbG0uc3RyZWFtKFtIdW1hbk1lc3NhZ2UoY29udGVudD1cIlRlbGwgbWUgYSB2ZXJ5IHNob3J0IGpva2UgYWJvdXQgQUkuXCIpXSk6XG4iLAogICAgIiAgICBwcmludChjaHVuay5jb250ZW50LCBlbmQ9XCJcIiwgZmx1c2g9VHJ1ZSlcbiIsCiAgICAiICAgIGNodW5rcy5hcHBlbmQoY2h1bmsuY29udGVudClcbiIsCiAgICAicHJpbnQoKVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiLS0tXFxuKipSZW5kZXJlZDoqKlxcblxcblwiICsgXCJcIi5qb2luKGNodW5rcykpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogIm1hcmtkb3duIiwKICAgImlkIjogIjNjODRlOTA3IiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJzb3VyY2UiOiBbCiAgICAiLS0tXG4iLAogICAgIiMjIFNlY3Rpb24gMyBcdTIwMTQgUHJvbXB0IEVuZ2luZWVyaW5nXG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqWmVyby1zaG90Kio6IGFzayB3aXRob3V0IGV4YW1wbGVzXG4iLAogICAgIi0gKipGZXctc2hvdCoqOiBnaXZlIGV4YW1wbGVzIGluIHRoZSBwcm9tcHQgdG8gZ3VpZGUgb3V0cHV0IGZvcm1hdFxuIiwKICAgICItICoqQ2hhaW4tb2YtVGhvdWdodCAoQ29UKSoqOiBhc2sgdGhlIG1vZGVsIHRvIHJlYXNvbiBzdGVwLWJ5LXN0ZXAgYmVmb3JlIGFuc3dlcmluZ1xuIiwKICAgICItICoqUHJvbXB0IHRlbXBsYXRlcyoqOiByZXVzYWJsZSBwcm9tcHRzIHdpdGggdmFyaWFibGVzXG4iLAogICAgIi0gKipPdXRwdXQgcGFyc2VycyoqOiBleHRyYWN0IHN0cnVjdHVyZWQgZGF0YSBmcm9tIG1vZGVsIHJlc3BvbnNlcyIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogImIxZjA1ODE1IiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyAzYS4gUHJvbXB0VGVtcGxhdGUgXHUyMDE0IHJldXNhYmxlIHByb21wdCB3aXRoIHZhcmlhYmxlc1xuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiXG4iLAogICAgInRlbXBsYXRlID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fbWVzc2FnZXMoW1xuIiwKICAgICIgICAgKFwic3lzdGVtXCIsIFwiWW91IGFyZSBhbiBleHBlcnQgaW4ge2RvbWFpbn0uXCIpLFxuIiwKICAgICIgICAgKFwiaHVtYW5cIiwgXCJFeHBsYWluIHtjb25jZXB0fSB0byBhIHthdWRpZW5jZX0uXCIpXG4iLAogICAgIl0pXG4iLAogICAgIlxuIiwKICAgICJjaGFpbiA9IHRlbXBsYXRlIHwgbGxtXG4iLAogICAgIlxuIiwKICAgICJyZXN1bHQgPSBjaGFpbi5pbnZva2Uoe1xuIiwKICAgICIgICAgXCJkb21haW5cIjogXCJtYWNoaW5lIGxlYXJuaW5nXCIsXG4iLAogICAgIiAgICBcImNvbmNlcHRcIjogXCJncmFkaWVudCBkZXNjZW50XCIsXG4iLAogICAgIiAgICBcImF1ZGllbmNlXCI6IFwiMTAteWVhci1vbGRcIlxuIiwKICAgICJ9KVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKHJlc3VsdC5jb250ZW50KSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICJlNTk4OWNhOSIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgM2IuIEZldy1zaG90IHByb21wdGluZyBcdTIwMTQgZ3VpZGUgb3V0cHV0IGZvcm1hdCB3aXRoIGV4YW1wbGVzXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnByb21wdHMgaW1wb3J0IENoYXRQcm9tcHRUZW1wbGF0ZVxuIiwKICAgICJcbiIsCiAgICAiZmV3X3Nob3RfdGVtcGxhdGUgPSBDaGF0UHJvbXB0VGVtcGxhdGUuZnJvbV9tZXNzYWdlcyhbXG4iLAogICAgIiAgICAoXCJzeXN0ZW1cIiwgXCJZb3UgY2xhc3NpZnkgY3VzdG9tZXIgZmVlZGJhY2sgYXMgUG9zaXRpdmUsIE5lZ2F0aXZlLCBvciBOZXV0cmFsLiBSZXBseSB3aXRoIG9ubHkgdGhlIGxhYmVsLlwiKSxcbiIsCiAgICAiICAgIChcImh1bWFuXCIsIFwiVGhlIHByb2R1Y3QgYnJva2UgYWZ0ZXIgb25lIGRheS5cIiksXG4iLAogICAgIiAgICAoXCJhaVwiLCBcIk5lZ2F0aXZlXCIpLFxuIiwKICAgICIgICAgKFwiaHVtYW5cIiwgXCJJdCdzIG9rYXksIG5vdGhpbmcgc3BlY2lhbC5cIiksXG4iLAogICAgIiAgICAoXCJhaVwiLCBcIk5ldXRyYWxcIiksXG4iLAogICAgIiAgICAoXCJodW1hblwiLCBcIkFic29sdXRlbHkgbG92ZSBpdCwgYmVzdCBwdXJjaGFzZSBldmVyIVwiKSxcbiIsCiAgICAiICAgIChcImFpXCIsIFwiUG9zaXRpdmVcIiksXG4iLAogICAgIiAgICAoXCJodW1hblwiLCBcIntmZWVkYmFja31cIilcbiIsCiAgICAiXSlcbiIsCiAgICAiXG4iLAogICAgImNoYWluID0gZmV3X3Nob3RfdGVtcGxhdGUgfCBsbG1cbiIsCiAgICAiXG4iLAogICAgInRlc3RzID0gW1xuIiwKICAgICIgICAgXCJEZWxpdmVyeSB3YXMgbGF0ZSBidXQgdGhlIGl0ZW0gd2FzIGZpbmUuXCIsXG4iLAogICAgIiAgICBcIlRlcnJpYmxlIGN1c3RvbWVyIHNlcnZpY2UsIHdvdWxkIG5vdCByZWNvbW1lbmQuXCIsXG4iLAogICAgIiAgICBcIkV4Y2VlZGVkIG15IGV4cGVjdGF0aW9ucyFcIlxuIiwKICAgICJdXG4iLAogICAgIlxuIiwKICAgICJyb3dzID0gW1wifCBGZWVkYmFjayB8IFNlbnRpbWVudCB8XCIsIFwifC0tLS0tLS0tLS18LS0tLS0tLS0tLS18XCJdXG4iLAogICAgImZvciB0IGluIHRlc3RzOlxuIiwKICAgICIgICAgbGFiZWwgPSBjaGFpbi5pbnZva2Uoe1wiZmVlZGJhY2tcIjogdH0pLmNvbnRlbnQuc3RyaXAoKVxuIiwKICAgICIgICAgcm93cy5hcHBlbmQoZlwifCB7dH0gfCAqKntsYWJlbH0qKiB8XCIpXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiXFxuXCIuam9pbihyb3dzKSkpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiOTI3N2M4MmUiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDNjLiBDaGFpbi1vZi1UaG91Z2h0IChDb1QpIFx1MjAxNCBhc2sgdG8gcmVhc29uIGJlZm9yZSBhbnN3ZXJpbmdcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUucHJvbXB0cyBpbXBvcnQgQ2hhdFByb21wdFRlbXBsYXRlXG4iLAogICAgIlxuIiwKICAgICJjb3RfcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fbWVzc2FnZXMoW1xuIiwKICAgICIgICAgKFwic3lzdGVtXCIsIFwiWW91IGFyZSBhIGNhcmVmdWwgcmVhc29uZXIuIFRoaW5rIHN0ZXAtYnktc3RlcCBiZWZvcmUgZ2l2aW5nIHlvdXIgZmluYWwgYW5zd2VyLiBGb3JtYXQ6IFJFQVNPTklORzogLi4uIEFOU1dFUjogLi4uXCIpLFxuIiwKICAgICIgICAgKFwiaHVtYW5cIiwgXCJ7cXVlc3Rpb259XCIpXG4iLAogICAgIl0pXG4iLAogICAgIlxuIiwKICAgICJjaGFpbiA9IGNvdF9wcm9tcHQgfCBsbG1cbiIsCiAgICAicmVzdWx0ID0gY2hhaW4uaW52b2tlKHtcInF1ZXN0aW9uXCI6IFwiSWYgSSBoYXZlIDMgYm94ZXMgd2l0aCA0IGFwcGxlcyBlYWNoLCBhbmQgSSBnaXZlIGF3YXkgNSBhcHBsZXMsIGhvdyBtYW55IGRvIEkgaGF2ZSBsZWZ0P1wifSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihyZXN1bHQuY29udGVudCkpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYjA5YjM2YjAiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDNkLiBTdHJ1Y3R1cmVkIG91dHB1dCB3aXRoIEpTT04gXHUyMDE0IG91dHB1dCBwYXJzZXJcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUub3V0cHV0X3BhcnNlcnMgaW1wb3J0IEpzb25PdXRwdXRQYXJzZXJcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiaW1wb3J0IGpzb25cbiIsCiAgICAiXG4iLAogICAgImpzb25fcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fbWVzc2FnZXMoW1xuIiwKICAgICIgICAgKFwic3lzdGVtXCIsIFwiXCJcIllvdSBleHRyYWN0IHN0cnVjdHVyZWQgaW5mb3JtYXRpb24uIEFsd2F5cyByZXNwb25kIHdpdGggdmFsaWQgSlNPTiBvbmx5LlxuIiwKICAgICJTY2hlbWE6IHt7XCJuYW1lXCI6IHN0cmluZywgXCJjb3VudHJ5XCI6IHN0cmluZywgXCJmb3VuZGVkX3llYXJcIjogaW50LCBcIm1haW5fcHJvZHVjdFwiOiBzdHJpbmd9fVwiXCJcIiksXG4iLAogICAgIiAgICAoXCJodW1hblwiLCBcIlRlbGwgbWUgYWJvdXQ6IHtjb21wYW55fVwiKVxuIiwKICAgICJdKVxuIiwKICAgICJcbiIsCiAgICAiY2hhaW4gPSBqc29uX3Byb21wdCB8IGxsbSB8IEpzb25PdXRwdXRQYXJzZXIoKVxuIiwKICAgICJcbiIsCiAgICAicmVzdWx0ID0gY2hhaW4uaW52b2tlKHtcImNvbXBhbnlcIjogXCJUZXNsYVwifSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihmXCJgYGBqc29uXFxue2pzb24uZHVtcHMocmVzdWx0LCBpbmRlbnQ9Mil9XFxuYGBgXCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogIm1hcmtkb3duIiwKICAgImlkIjogImViNGU2YmNkIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJzb3VyY2UiOiBbCiAgICAiLS0tXG4iLAogICAgIiMjIFNlY3Rpb24gNCBcdTIwMTQgQ2hhaW5zXG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqTENFTCAoTGFuZ0NoYWluIEV4cHJlc3Npb24gTGFuZ3VhZ2UpKio6IHBpcGUgYHxgIG9wZXJhdG9yIHRvIGNvbXBvc2UgY29tcG9uZW50c1xuIiwKICAgICItICoqU2VxdWVudGlhbCBjaGFpbioqOiBvdXRwdXQgb2Ygb25lIHN0ZXAgZmVlZHMgaW50byB0aGUgbmV4dFxuIiwKICAgICItICoqUGFyYWxsZWwgY2hhaW4qKjogcnVuIG11bHRpcGxlIExMTSBjYWxscyBzaW11bHRhbmVvdXNseVxuIiwKICAgICItICoqQnJhbmNoaW5nKio6IHJvdXRlIHRvIGRpZmZlcmVudCBjaGFpbnMgYmFzZWQgb24gY29udGVudCIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjRjMGUzYzJlIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA0YS4gU2ltcGxlIExDRUwgY2hhaW46IHByb21wdCBcdTIxOTIgbGxtIFx1MjE5MiBzdHJpbmcgcGFyc2VyXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm91dHB1dF9wYXJzZXJzIGltcG9ydCBTdHJPdXRwdXRQYXJzZXJcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiXG4iLAogICAgInN1bW1hcml6ZV9jaGFpbiA9IChcbiIsCiAgICAiICAgIENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX3RlbXBsYXRlKFwiU3VtbWFyaXplIHRoZSBmb2xsb3dpbmcgdGV4dCBpbiBvbmUgc2VudGVuY2U6XFxuXFxue3RleHR9XCIpXG4iLAogICAgIiAgICB8IGxsbVxuIiwKICAgICIgICAgfCBTdHJPdXRwdXRQYXJzZXIoKVxuIiwKICAgICIpXG4iLAogICAgIlxuIiwKICAgICJ0ZXh0ID0gXCJcIlwiVGhlIEphbWVzIFdlYmIgU3BhY2UgVGVsZXNjb3BlIChKV1NUKSBpcyBhIHNwYWNlIHRlbGVzY29wZSBkZXNpZ25lZCB0byBjb25kdWN0IGluZnJhcmVkXG4iLAogICAgImFzdHJvbm9teS4gSXRzIGhpZ2ggcmVzb2x1dGlvbiBhbmQgc2Vuc2l0aXZpdHkgYWxsb3cgaXQgdG8gdmlldyBvYmplY3RzIHRvbyBvbGQsIGRpc3RhbnQsIG9yIGZhaW50XG4iLAogICAgImZvciB0aGUgSHViYmxlIFNwYWNlIFRlbGVzY29wZS4gSXQgaXMgdGhlIGxhcmdlc3Qgb3B0aWNhbCB0ZWxlc2NvcGUgaW4gc3BhY2UuXCJcIlwiXG4iLAogICAgIlxuIiwKICAgICJyZXN1bHQgPSBzdW1tYXJpemVfY2hhaW4uaW52b2tlKHtcInRleHRcIjogdGV4dH0pXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24ocmVzdWx0KSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIyN2YzZTlhYyIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgNGIuIFNlcXVlbnRpYWwgY2hhaW4gXHUyMDE0IHRyYW5zbGF0ZSB0aGVuIGV4cGxhaW5cbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUub3V0cHV0X3BhcnNlcnMgaW1wb3J0IFN0ck91dHB1dFBhcnNlclxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnByb21wdHMgaW1wb3J0IENoYXRQcm9tcHRUZW1wbGF0ZVxuIiwKICAgICJcbiIsCiAgICAidHJhbnNsYXRlX3Byb21wdCA9IENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX3RlbXBsYXRlKFxuIiwKICAgICIgICAgXCJUcmFuc2xhdGUgdGhlIGZvbGxvd2luZyB0ZXh0IHRvIEZyZW5jaDpcXG57dGV4dH1cIlxuIiwKICAgICIpXG4iLAogICAgImV4cGxhaW5fcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fdGVtcGxhdGUoXG4iLAogICAgIiAgICBcIkV4cGxhaW4gd2h5IHRoaXMgRnJlbmNoIHNlbnRlbmNlIGlzIGdyYW1tYXRpY2FsbHkgY29ycmVjdDpcXG57dHJhbnNsYXRlZH1cIlxuIiwKICAgICIpXG4iLAogICAgIlxuIiwKICAgICJwYXJzZXIgPSBTdHJPdXRwdXRQYXJzZXIoKVxuIiwKICAgICJcbiIsCiAgICAiZnVsbF9jaGFpbiA9IChcbiIsCiAgICAiICAgIHRyYW5zbGF0ZV9wcm9tcHQgfCBsbG0gfCBwYXJzZXJcbiIsCiAgICAiICAgIHwgKGxhbWJkYSB0cmFuc2xhdGVkOiB7XCJ0cmFuc2xhdGVkXCI6IHRyYW5zbGF0ZWR9KVxuIiwKICAgICIgICAgfCBleHBsYWluX3Byb21wdCB8IGxsbSB8IHBhcnNlclxuIiwKICAgICIpXG4iLAogICAgIlxuIiwKICAgICJyZXN1bHQgPSBmdWxsX2NoYWluLmludm9rZSh7XCJ0ZXh0XCI6IFwiVGhlIHN1biByaXNlcyBpbiB0aGUgZWFzdC5cIn0pXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24ocmVzdWx0KSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIzM2U5OWE3YyIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgNGMuIFBhcmFsbGVsIGNoYWlucyB1c2luZyBSdW5uYWJsZVBhcmFsbGVsXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnJ1bm5hYmxlcyBpbXBvcnQgUnVubmFibGVQYXJhbGxlbFxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm91dHB1dF9wYXJzZXJzIGltcG9ydCBTdHJPdXRwdXRQYXJzZXJcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiXG4iLAogICAgInByb3NfY2hhaW4gPSBDaGF0UHJvbXB0VGVtcGxhdGUuZnJvbV90ZW1wbGF0ZShcIkxpc3QgMyBwcm9zIG9mIHt0b3BpY31cIikgfCBsbG0gfCBTdHJPdXRwdXRQYXJzZXIoKVxuIiwKICAgICJjb25zX2NoYWluID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fdGVtcGxhdGUoXCJMaXN0IDMgY29ucyBvZiB7dG9waWN9XCIpIHwgbGxtIHwgU3RyT3V0cHV0UGFyc2VyKClcbiIsCiAgICAiXG4iLAogICAgInBhcmFsbGVsID0gUnVubmFibGVQYXJhbGxlbChwcm9zPXByb3NfY2hhaW4sIGNvbnM9Y29uc19jaGFpbilcbiIsCiAgICAiXG4iLAogICAgInJlc3VsdCA9IHBhcmFsbGVsLmludm9rZSh7XCJ0b3BpY1wiOiBcIndvcmtpbmcgZnJvbSBob21lXCJ9KVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIiMjIyBQcm9zXFxue3Jlc3VsdFsncHJvcyddfVxcblxcbiMjIyBDb25zXFxue3Jlc3VsdFsnY29ucyddfVwiKSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJtYXJrZG93biIsCiAgICJpZCI6ICJiYThiY2I0NCIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAic291cmNlIjogWwogICAgIi0tLVxuIiwKICAgICIjIyBTZWN0aW9uIDUgXHUyMDE0IE1lbW9yeSAmIENvbnZlcnNhdGlvbiBIaXN0b3J5XG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqU3RhdGVsZXNzIExMTXMqKjogYnkgZGVmYXVsdCwgZWFjaCBjYWxsIGlzIGluZGVwZW5kZW50IFx1MjAxNCBubyBtZW1vcnlcbiIsCiAgICAiLSAqKkNvbnZlcnNhdGlvbiBidWZmZXIqKjogc3RvcmUgdGhlIGZ1bGwgY2hhdCBoaXN0b3J5IGFuZCBwYXNzIGl0IGVhY2ggdHVyblxuIiwKICAgICItICoqU3VtbWFyeSBtZW1vcnkqKjogc3VtbWFyaXplIG9sZGVyIHR1cm5zIHRvIHN0YXkgd2l0aGluIGNvbnRleHQgd2luZG93XG4iLAogICAgIi0gKipMYW5nR3JhcGggcGVyc2lzdGVuY2UqKjogdGhlIG1vZGVybiB3YXkgdG8gYWRkIG1lbW9yeSBcdTIwMTQgZ3JhcGggc3RhdGUgaXMgY2hlY2twb2ludGVkIHBlciBgdGhyZWFkX2lkYCIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjUyMzg0ZmRkIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA1YS4gTWFudWFsIG1lc3NhZ2UgaGlzdG9yeSBcdTIwMTQgc2VlIHdoYXQgXCJtZW1vcnlcIiBtZWFucyBhdCB0aGUgcmF3IGxldmVsXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBIdW1hbk1lc3NhZ2UsIEFJTWVzc2FnZSwgU3lzdGVtTWVzc2FnZVxuIiwKICAgICJcbiIsCiAgICAiaGlzdG9yeSA9IFtTeXN0ZW1NZXNzYWdlKGNvbnRlbnQ9XCJZb3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQuIFJlbWVtYmVyIGRldGFpbHMgdGhlIHVzZXIgc2hhcmVzLlwiKV1cbiIsCiAgICAiXG4iLAogICAgImRlZiBjaGF0KHVzZXJfaW5wdXQpOlxuIiwKICAgICIgICAgaGlzdG9yeS5hcHBlbmQoSHVtYW5NZXNzYWdlKGNvbnRlbnQ9dXNlcl9pbnB1dCkpXG4iLAogICAgIiAgICByZXNwb25zZSA9IGxsbS5pbnZva2UoaGlzdG9yeSlcbiIsCiAgICAiICAgIGhpc3RvcnkuYXBwZW5kKEFJTWVzc2FnZShjb250ZW50PXJlc3BvbnNlLmNvbnRlbnQpKVxuIiwKICAgICIgICAgcmV0dXJuIHJlc3BvbnNlLmNvbnRlbnRcbiIsCiAgICAiXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiKipVc2VyOioqIEhpLCBteSBuYW1lIGlzIEFsZXggYW5kIEkgbG92ZSBoaWtpbmcuXFxuXFxuKipBSToqKiB7Y2hhdCgnSGksIG15IG5hbWUgaXMgQWxleCBhbmQgSSBsb3ZlIGhpa2luZy4nKX1cIikpXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiKipVc2VyOioqIFdoYXQgZG8gSSBsb3ZlIGRvaW5nP1xcblxcbioqQUk6Kioge2NoYXQoJ1doYXQgZG8gSSBsb3ZlIGRvaW5nPycpfVwiKSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihmXCIqKlVzZXI6KiogV2hhdCBpcyBteSBuYW1lP1xcblxcbioqQUk6Kioge2NoYXQoJ1doYXQgaXMgbXkgbmFtZT8nKX1cIikpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYTM0ZjFjYWIiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDViLiBMYW5nR3JhcGggcGVyc2lzdGVudCBtZW1vcnkgXHUyMDE0IG1vZGVybiByZXBsYWNlbWVudCBmb3IgUnVubmFibGVXaXRoTWVzc2FnZUhpc3RvcnlcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2dyYXBoLmNoZWNrcG9pbnQubWVtb3J5IGltcG9ydCBNZW1vcnlTYXZlclxuIiwKICAgICJmcm9tIGxhbmdncmFwaC5ncmFwaCBpbXBvcnQgU1RBUlQsIE1lc3NhZ2VzU3RhdGUsIFN0YXRlR3JhcGhcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5tZXNzYWdlcyBpbXBvcnQgSHVtYW5NZXNzYWdlLCBTeXN0ZW1NZXNzYWdlXG4iLAogICAgIlxuIiwKICAgICIjIERlZmluZSBhIHNpbmdsZSBub2RlIHRoYXQgY2FsbHMgdGhlIExMTSB3aXRoIGZ1bGwgbWVzc2FnZSBoaXN0b3J5XG4iLAogICAgImRlZiBjYWxsX2xsbShzdGF0ZTogTWVzc2FnZXNTdGF0ZSk6XG4iLAogICAgIiAgICBzeXN0ZW0gPSBTeXN0ZW1NZXNzYWdlKGNvbnRlbnQ9XCJZb3UgYXJlIGEgZnJpZW5kbHkgYXNzaXN0YW50LlwiKVxuIiwKICAgICIgICAgcmVzcG9uc2UgPSBsbG0uaW52b2tlKFtzeXN0ZW1dICsgc3RhdGVbXCJtZXNzYWdlc1wiXSlcbiIsCiAgICAiICAgIHJldHVybiB7XCJtZXNzYWdlc1wiOiByZXNwb25zZX1cbiIsCiAgICAiXG4iLAogICAgIiMgQnVpbGQgYSBtaW5pbWFsIGdyYXBoOiBTVEFSVCBcdTIxOTIgbGxtIG5vZGVcbiIsCiAgICAiYnVpbGRlciA9IFN0YXRlR3JhcGgoTWVzc2FnZXNTdGF0ZSlcbiIsCiAgICAiYnVpbGRlci5hZGRfbm9kZShcImxsbVwiLCBjYWxsX2xsbSlcbiIsCiAgICAiYnVpbGRlci5hZGRfZWRnZShTVEFSVCwgXCJsbG1cIilcbiIsCiAgICAiXG4iLAogICAgIiMgTWVtb3J5U2F2ZXIgY2hlY2twb2ludHMgdGhlIGZ1bGwgbWVzc2FnZSBoaXN0b3J5IHBlciB0aHJlYWRfaWQgaW4tbWVtb3J5XG4iLAogICAgImdyYXBoID0gYnVpbGRlci5jb21waWxlKGNoZWNrcG9pbnRlcj1NZW1vcnlTYXZlcigpKVxuIiwKICAgICJcbiIsCiAgICAiY2ZnID0ge1wiY29uZmlndXJhYmxlXCI6IHtcInRocmVhZF9pZFwiOiBcInVzZXJfMVwifX1cbiIsCiAgICAiXG4iLAogICAgImRlZiBjaGF0X2xnKHVzZXJfaW5wdXQpOlxuIiwKICAgICIgICAgcmVzdWx0ID0gZ3JhcGguaW52b2tlKHtcIm1lc3NhZ2VzXCI6IFtIdW1hbk1lc3NhZ2UoY29udGVudD11c2VyX2lucHV0KV19LCBjb25maWc9Y2ZnKVxuIiwKICAgICIgICAgcmV0dXJuIHJlc3VsdFtcIm1lc3NhZ2VzXCJdWy0xXS5jb250ZW50XG4iLAogICAgIlxuIiwKICAgICJyMSA9IGNoYXRfbGcoXCJNeSBmYXZvdXJpdGUgY29sb3VyIGlzIGJsdWUuXCIpXG4iLAogICAgInIyID0gY2hhdF9sZyhcIldoYXQgaXMgbXkgZmF2b3VyaXRlIGNvbG91cj9cIilcbiIsCiAgICAiXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiKipUdXJuIDE6KiogTXkgZmF2b3VyaXRlIGNvbG91ciBpcyBibHVlLlxcblxcbioqQUk6Kioge3IxfVwiKSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihmXCIqKlR1cm4gMjoqKiBXaGF0IGlzIG15IGZhdm91cml0ZSBjb2xvdXI/XFxuXFxuKipBSToqKiB7cjJ9XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjlhZDU0NmVkIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA1Yy4gU3VtbWFyeSBtZW1vcnkgY29uY2VwdCBcdTIwMTQgc3VtbWFyaXNlIG9sZCB0dXJucyB0byBzYXZlIHRva2Vuc1xuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5vdXRwdXRfcGFyc2VycyBpbXBvcnQgU3RyT3V0cHV0UGFyc2VyXG4iLAogICAgIlxuIiwKICAgICJvbGRfY29udmVyc2F0aW9uID0gXCJcIlwiXG4iLAogICAgIlVzZXI6IEknbSBwbGFubmluZyBhIHRyaXAgdG8gSmFwYW4gaW4gT2N0b2Jlci5cbiIsCiAgICAiQUk6IEdyZWF0IGNob2ljZSEgT2N0b2JlciBpcyBiZWF1dGlmdWwgaW4gSmFwYW4gXHUyMDE0IGF1dHVtbiBmb2xpYWdlIGJlZ2lucy5cbiIsCiAgICAiVXNlcjogSSB3YW50IHRvIHZpc2l0IFRva3lvIGFuZCBLeW90by5cbiIsCiAgICAiQUk6IFBlcmZlY3QgaXRpbmVyYXJ5LiBUb2t5byBmb3IgbW9kZXJuIGN1bHR1cmUsIEt5b3RvIGZvciB0ZW1wbGVzIGFuZCBoaXN0b3J5LlxuIiwKICAgICJVc2VyOiBJIGhhdmUgMTAgZGF5cyB0b3RhbC5cbiIsCiAgICAiQUk6IFN1Z2dlc3RlZCBzcGxpdDogNSBkYXlzIFRva3lvLCA0IGRheXMgS3lvdG8sIDEgZGF5IE5hcmEgYXMgYSBkYXkgdHJpcC5cbiIsCiAgICAiXCJcIlwiXG4iLAogICAgIlxuIiwKICAgICJzdW1tYXJpemUgPSAoXG4iLAogICAgIiAgICBDaGF0UHJvbXB0VGVtcGxhdGUuZnJvbV90ZW1wbGF0ZShcbiIsCiAgICAiICAgICAgICBcIlN1bW1hcml6ZSB0aGlzIGNvbnZlcnNhdGlvbiBoaXN0b3J5IGludG8gMi0zIGJ1bGxldCBwb2ludHMgZm9yIGNvbnRleHQ6XFxue2hpc3Rvcnl9XCJcbiIsCiAgICAiICAgICkgfCBsbG0gfCBTdHJPdXRwdXRQYXJzZXIoKVxuIiwKICAgICIpXG4iLAogICAgIlxuIiwKICAgICJzdW1tYXJ5ID0gc3VtbWFyaXplLmludm9rZSh7XCJoaXN0b3J5XCI6IG9sZF9jb252ZXJzYXRpb259KVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIiMjIyBTdW1tYXJ5IHN0b3JlZCBhcyBjb250ZXh0XFxue3N1bW1hcnl9XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogIm1hcmtkb3duIiwKICAgImlkIjogIjBkYzZhYjMxIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJzb3VyY2UiOiBbCiAgICAiLS0tXG4iLAogICAgIiMjIFNlY3Rpb24gNiBcdTIwMTQgUkFHIChSZXRyaWV2YWwtQXVnbWVudGVkIEdlbmVyYXRpb24pXG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqRW1iZWRkaW5ncyoqOiBudW1lcmljYWwgdmVjdG9yIHJlcHJlc2VudGF0aW9ucyBvZiB0ZXh0IChzaW1pbGFyIHRleHRzIFx1MjE5MiBzaW1pbGFyIHZlY3RvcnMpXG4iLAogICAgIi0gKipWZWN0b3Igc3RvcmUqKjogZGF0YWJhc2UgZm9yIHN0b3JpbmcgYW5kIHNlYXJjaGluZyBlbWJlZGRpbmdzIChDaHJvbWFEQiwgRkFJU1MpXG4iLAogICAgIi0gKipTZW1hbnRpYyBzZWFyY2gqKjogZmluZCByZWxldmFudCB0ZXh0IGJ5IG1lYW5pbmcsIG5vdCBrZXl3b3JkIG1hdGNoXG4iLAogICAgIi0gKipSQUcgcGlwZWxpbmUqKjogUmV0cmlldmUgcmVsZXZhbnQgZG9jcyBcdTIxOTIgQXVnbWVudCBwcm9tcHQgXHUyMTkyIEdlbmVyYXRlIGFuc3dlclxuIiwKICAgICItICoqV2h5IFJBRz8qKiBFeHRlbmRzIExMTSBrbm93bGVkZ2Ugd2l0aCB5b3VyIG93biBkYXRhIHdpdGhvdXQgcmV0cmFpbmluZyIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjVjYzE1ZWIyIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA2YS4gRW1iZWRkaW5ncyBcdTIwMTQgdmlzdWFsaXNlIHdoYXQgdGhleSBhcmVcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImltcG9ydCBudW1weSBhcyBucFxuIiwKICAgICJcbiIsCiAgICAic2VudGVuY2VzID0gW1xuIiwKICAgICIgICAgXCJUaGUgY2F0IHNhdCBvbiB0aGUgbWF0LlwiLFxuIiwKICAgICIgICAgXCJBIGZlbGluZSByZXN0ZWQgb24gdGhlIHJ1Zy5cIixcbiIsCiAgICAiICAgIFwiVGhlIHN0b2NrIG1hcmtldCBjcmFzaGVkIHRvZGF5LlwiLFxuIiwKICAgICJdXG4iLAogICAgIlxuIiwKICAgICJ2ZWNzID0gZW1iZWRkaW5ncy5lbWJlZF9kb2N1bWVudHMoc2VudGVuY2VzKVxuIiwKICAgICJcbiIsCiAgICAiZGVmIGNvc2luZShhLCBiKTpcbiIsCiAgICAiICAgIGEsIGIgPSBucC5hcnJheShhKSwgbnAuYXJyYXkoYilcbiIsCiAgICAiICAgIHJldHVybiBmbG9hdChucC5kb3QoYSwgYikgLyAobnAubGluYWxnLm5vcm0oYSkgKiBucC5saW5hbGcubm9ybShiKSkpXG4iLAogICAgIlxuIiwKICAgICJzaW1fMV8yID0gY29zaW5lKHZlY3NbMF0sIHZlY3NbMV0pXG4iLAogICAgInNpbV8xXzMgPSBjb3NpbmUodmVjc1swXSwgdmVjc1syXSlcbiIsCiAgICAiXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiXCJcIlxuIiwKICAgICIqKkVtYmVkZGluZyBkaW1lbnNpb246Kioge2xlbih2ZWNzWzBdKX1cbiIsCiAgICAiXG4iLAogICAgInwgUGFpciB8IENvc2luZSBTaW1pbGFyaXR5IHxcbiIsCiAgICAifC0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tfFxuIiwKICAgICJ8IGNhdCAvIGZlbGluZSAoc2ltaWxhcikgfCBge3NpbV8xXzI6LjRmfWAgfFxuIiwKICAgICJ8IGNhdCAvIHN0b2NrIG1hcmtldCAodW5yZWxhdGVkKSB8IGB7c2ltXzFfMzouNGZ9YCB8XG4iLAogICAgIlxuIiwKICAgICI+IEhpZ2hlciBzY29yZSA9IG1vcmUgc2VtYW50aWNhbGx5IHNpbWlsYXJcbiIsCiAgICAiXCJcIlwiKSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIzN2ZjNGI0MiIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgNmIuIEJ1aWxkIGEgdmVjdG9yIHN0b3JlIGZyb20gc2FtcGxlIGRvY3VtZW50c1xuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jaHJvbWEgaW1wb3J0IENocm9tYVxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLmRvY3VtZW50cyBpbXBvcnQgRG9jdW1lbnRcbiIsCiAgICAiXG4iLAogICAgImRvY3MgPSBbXG4iLAogICAgIiAgICBEb2N1bWVudChwYWdlX2NvbnRlbnQ9XCJQeXRob24gaXMgYSBoaWdoLWxldmVsLCBpbnRlcnByZXRlZCBwcm9ncmFtbWluZyBsYW5ndWFnZSBrbm93biBmb3IgcmVhZGFiaWxpdHkuXCIsIG1ldGFkYXRhPXtcInNvdXJjZVwiOiBcInB5dGhvbl93aWtpXCJ9KSxcbiIsCiAgICAiICAgIERvY3VtZW50KHBhZ2VfY29udGVudD1cIlB5dGhvbiBzdXBwb3J0cyBtdWx0aXBsZSBwcm9ncmFtbWluZyBwYXJhZGlnbXMgaW5jbHVkaW5nIHByb2NlZHVyYWwsIG9iamVjdC1vcmllbnRlZCwgYW5kIGZ1bmN0aW9uYWwuXCIsIG1ldGFkYXRhPXtcInNvdXJjZVwiOiBcInB5dGhvbl93aWtpXCJ9KSxcbiIsCiAgICAiICAgIERvY3VtZW50KHBhZ2VfY29udGVudD1cIlJ1c3QgaXMgYSBzeXN0ZW1zIHByb2dyYW1taW5nIGxhbmd1YWdlIGZvY3VzZWQgb24gc2FmZXR5LCBzcGVlZCwgYW5kIGNvbmN1cnJlbmN5LlwiLCBtZXRhZGF0YT17XCJzb3VyY2VcIjogXCJydXN0X3dpa2lcIn0pLFxuIiwKICAgICIgICAgRG9jdW1lbnQocGFnZV9jb250ZW50PVwiUnVzdCdzIGJvcnJvdyBjaGVja2VyIHByZXZlbnRzIG1lbW9yeSBidWdzIGF0IGNvbXBpbGUgdGltZSB3aXRob3V0IGEgZ2FyYmFnZSBjb2xsZWN0b3IuXCIsIG1ldGFkYXRhPXtcInNvdXJjZVwiOiBcInJ1c3Rfd2lraVwifSksXG4iLAogICAgIiAgICBEb2N1bWVudChwYWdlX2NvbnRlbnQ9XCJKYXZhU2NyaXB0IGlzIHRoZSBwcmltYXJ5IGxhbmd1YWdlIGZvciB3ZWIgZnJvbnRlbmQgZGV2ZWxvcG1lbnQsIHJ1bm5pbmcgaW4gYnJvd3NlcnMuXCIsIG1ldGFkYXRhPXtcInNvdXJjZVwiOiBcImpzX3dpa2lcIn0pLFxuIiwKICAgICIgICAgRG9jdW1lbnQocGFnZV9jb250ZW50PVwiTm9kZS5qcyBhbGxvd3MgSmF2YVNjcmlwdCB0byBydW4gb24gdGhlIHNlcnZlciBzaWRlLCBlbmFibGluZyBmdWxsLXN0YWNrIEpTIGRldmVsb3BtZW50LlwiLCBtZXRhZGF0YT17XCJzb3VyY2VcIjogXCJqc193aWtpXCJ9KSxcbiIsCiAgICAiICAgIERvY3VtZW50KHBhZ2VfY29udGVudD1cIkdvIChHb2xhbmcpIGlzIGRlc2lnbmVkIGZvciBzaW1wbGljaXR5IGFuZCBoaWdoLXBlcmZvcm1hbmNlIGNvbmN1cnJlbnQgc2VydmVyIGFwcGxpY2F0aW9ucy5cIiwgbWV0YWRhdGE9e1wic291cmNlXCI6IFwiZ29fd2lraVwifSksXG4iLAogICAgIl1cbiIsCiAgICAiXG4iLAogICAgInZlY3RvcnN0b3JlID0gQ2hyb21hLmZyb21fZG9jdW1lbnRzKGRvY3MsIGVtYmVkZGluZz1lbWJlZGRpbmdzLCBjb2xsZWN0aW9uX25hbWU9XCJwcm9ncmFtbWluZ19sYW5nc1wiKVxuIiwKICAgICJwcmludChmXCJWZWN0b3Igc3RvcmUgY3JlYXRlZCB3aXRoIHt2ZWN0b3JzdG9yZS5fY29sbGVjdGlvbi5jb3VudCgpfSBkb2N1bWVudHMuXCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiZGE2YzI0MDQiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDZjLiBTZW1hbnRpYyBzZWFyY2hcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgIlxuIiwKICAgICJxdWVyeSA9IFwiV2hhdCBsYW5ndWFnZSBwcmV2ZW50cyBtZW1vcnkgYnVncyBhdCBjb21waWxlIHRpbWU/XCJcbiIsCiAgICAicmVzdWx0cyA9IHZlY3RvcnN0b3JlLnNpbWlsYXJpdHlfc2VhcmNoKHF1ZXJ5LCBrPTIpXG4iLAogICAgIlxuIiwKICAgICJyb3dzID0gW2ZcIioqUXVlcnk6Kioge3F1ZXJ5fVxcblwiLCBcInwgIyB8IFNvdXJjZSB8IENvbnRlbnQgfFwiLCBcInwtLS18LS0tLS0tLS18LS0tLS0tLS0tfFwiXVxuIiwKICAgICJmb3IgaSwgZG9jIGluIGVudW1lcmF0ZShyZXN1bHRzKTpcbiIsCiAgICAiICAgIHJvd3MuYXBwZW5kKGZcInwge2krMX0gfCBge2RvYy5tZXRhZGF0YVsnc291cmNlJ119YCB8IHtkb2MucGFnZV9jb250ZW50fSB8XCIpXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiXFxuXCIuam9pbihyb3dzKSkpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiMjMwNTdhNmMiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDZkLiBGdWxsIFJBRyBwaXBlbGluZSBcdTIwMTQgcmV0cmlldmFsICsgZ2VuZXJhdGlvblxuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5wcm9tcHRzIGltcG9ydCBDaGF0UHJvbXB0VGVtcGxhdGVcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5vdXRwdXRfcGFyc2VycyBpbXBvcnQgU3RyT3V0cHV0UGFyc2VyXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUucnVubmFibGVzIGltcG9ydCBSdW5uYWJsZVBhc3N0aHJvdWdoXG4iLAogICAgIlxuIiwKICAgICJyZXRyaWV2ZXIgPSB2ZWN0b3JzdG9yZS5hc19yZXRyaWV2ZXIoc2VhcmNoX2t3YXJncz17XCJrXCI6IDN9KVxuIiwKICAgICJcbiIsCiAgICAiZGVmIGZvcm1hdF9kb2NzKGRvY3MpOlxuIiwKICAgICIgICAgcmV0dXJuIFwiXFxuXFxuXCIuam9pbihkb2MucGFnZV9jb250ZW50IGZvciBkb2MgaW4gZG9jcylcbiIsCiAgICAiXG4iLAogICAgInJhZ19wcm9tcHQgPSBDaGF0UHJvbXB0VGVtcGxhdGUuZnJvbV9tZXNzYWdlcyhbXG4iLAogICAgIiAgICAoXCJzeXN0ZW1cIiwgXCJcIlwiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50LiBBbnN3ZXIgdGhlIHF1ZXN0aW9uIHVzaW5nIE9OTFkgdGhlIGNvbnRleHQgcHJvdmlkZWQuXG4iLAogICAgIklmIHRoZSBhbnN3ZXIgaXMgbm90IGluIHRoZSBjb250ZXh0LCBzYXkgJ0kgZG9uJ3Qga25vdyBiYXNlZCBvbiB0aGUgcHJvdmlkZWQgaW5mb3JtYXRpb24uJ1xuIiwKICAgICJcbiIsCiAgICAiQ29udGV4dDpcbiIsCiAgICAie2NvbnRleHR9XCJcIlwiKSxcbiIsCiAgICAiICAgIChcImh1bWFuXCIsIFwie3F1ZXN0aW9ufVwiKVxuIiwKICAgICJdKVxuIiwKICAgICJcbiIsCiAgICAicmFnX2NoYWluID0gKFxuIiwKICAgICIgICAge1wiY29udGV4dFwiOiByZXRyaWV2ZXIgfCBmb3JtYXRfZG9jcywgXCJxdWVzdGlvblwiOiBSdW5uYWJsZVBhc3N0aHJvdWdoKCl9XG4iLAogICAgIiAgICB8IHJhZ19wcm9tcHRcbiIsCiAgICAiICAgIHwgbGxtXG4iLAogICAgIiAgICB8IFN0ck91dHB1dFBhcnNlcigpXG4iLAogICAgIilcbiIsCiAgICAiXG4iLAogICAgInF1ZXN0aW9ucyA9IFtcbiIsCiAgICAiICAgIFwiV2hpY2ggbGFuZ3VhZ2UgaXMgYmVzdCBmb3Igd2ViIGZyb250ZW5kIGRldmVsb3BtZW50P1wiLFxuIiwKICAgICIgICAgXCJXaGF0IG1ha2VzIFJ1c3Qgc3BlY2lhbCBjb21wYXJlZCB0byBvdGhlciBsYW5ndWFnZXM/XCIsXG4iLAogICAgIiAgICBcIldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlP1wiXG4iLAogICAgIl1cbiIsCiAgICAiXG4iLAogICAgImZvciBxIGluIHF1ZXN0aW9uczpcbiIsCiAgICAiICAgIGFuc3dlciA9IHJhZ19jaGFpbi5pbnZva2UocSlcbiIsCiAgICAiICAgIGRpc3BsYXkoTWFya2Rvd24oZlwiKipROioqIHtxfVxcblxcbioqQToqKiB7YW5zd2VyfVxcblxcbi0tLVwiKSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICI5MTUzNWU4MSIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgNmUuIFRleHQgc3BsaXR0ZXIgXHUyMDE0IGhhbmRsaW5nIGxhcmdlIGRvY3VtZW50c1xuIiwKICAgICJmcm9tIGxhbmdjaGFpbl90ZXh0X3NwbGl0dGVycyBpbXBvcnQgUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyXG4iLAogICAgIlxuIiwKICAgICJsb25nX3RleHQgPSBcIlwiXCJBcnRpZmljaWFsIGludGVsbGlnZW5jZSAoQUkpIGlzIGludGVsbGlnZW5jZSBkZW1vbnN0cmF0ZWQgYnkgbWFjaGluZXMsIGFzIG9wcG9zZWQgdG8gdGhlIG5hdHVyYWxcbiIsCiAgICAiaW50ZWxsaWdlbmNlIGRpc3BsYXllZCBieSBhbmltYWxzIGluY2x1ZGluZyBodW1hbnMuIEFJIHJlc2VhcmNoIGhhcyBiZWVuIGRlZmluZWQgYXMgdGhlIGZpZWxkIG9mIHN0dWR5IG9mXG4iLAogICAgImludGVsbGlnZW50IGFnZW50cywgd2hpY2ggcmVmZXJzIHRvIGFueSBzeXN0ZW0gdGhhdCBwZXJjZWl2ZXMgaXRzIGVudmlyb25tZW50IGFuZCB0YWtlcyBhY3Rpb25zIHRoYXQgbWF4aW1pemVcbiIsCiAgICAiaXRzIGNoYW5jZSBvZiBhY2hpZXZpbmcgaXRzIGdvYWxzLiBUaGUgdGVybSBhcnRpZmljaWFsIGludGVsbGlnZW5jZSBoYWQgcHJldmlvdXNseSBiZWVuIHVzZWQgdG8gZGVzY3JpYmVcbiIsCiAgICAibWFjaGluZXMgdGhhdCBtaW1pYyBhbmQgZGlzcGxheSBodW1hbiBjb2duaXRpdmUgc2tpbGxzIGFzc29jaWF0ZWQgd2l0aCB0aGUgaHVtYW4gbWluZCwgc3VjaCBhcyBsZWFybmluZyBhbmRcbiIsCiAgICAicHJvYmxlbS1zb2x2aW5nLiBUaGlzIGRlZmluaXRpb24gaGFzIHNpbmNlIGJlZW4gcmVqZWN0ZWQgYnkgbWFqb3IgQUkgcmVzZWFyY2hlcnMgd2hvIG5vdyBkZXNjcmliZSBBSSBpbiB0ZXJtc1xuIiwKICAgICJvZiByYXRpb25hbGl0eSBhbmQgYWN0aW5nIHJhdGlvbmFsbHksIHdoaWNoIGRvZXMgbm90IGxpbWl0IGhvdyBpbnRlbGxpZ2VuY2UgY2FuIGJlIGFydGljdWxhdGVkLlxuIiwKICAgICJcbiIsCiAgICAiQUkgYXBwbGljYXRpb25zIGluY2x1ZGUgYWR2YW5jZWQgd2ViIHNlYXJjaCBlbmdpbmVzLCByZWNvbW1lbmRhdGlvbiBzeXN0ZW1zICh1c2VkIGJ5IFlvdVR1YmUsIEFtYXpvbiBhbmQgTmV0ZmxpeCksXG4iLAogICAgInVuZGVyc3RhbmRpbmcgaHVtYW4gc3BlZWNoIChzdWNoIGFzIFNpcmkgYW5kIEFsZXhhKSwgc2VsZi1kcml2aW5nIGNhcnMgKHN1Y2ggYXMgV2F5bW8pLCBnZW5lcmF0aXZlIG9yIGNyZWF0aXZlXG4iLAogICAgInRvb2xzIChDaGF0R1BUIGFuZCBBSSBhcnQpLCBhdXRvbWF0ZWQgZGVjaXNpb24tbWFraW5nIGFuZCBjb21wZXRpbmcgYXQgdGhlIGhpZ2hlc3QgbGV2ZWwgaW4gc3RyYXRlZ2ljIGdhbWVcbiIsCiAgICAic3lzdGVtcyAoc3VjaCBhcyBjaGVzcyBhbmQgR28pLiBBcyBtYWNoaW5lcyBiZWNvbWUgaW5jcmVhc2luZ2x5IGNhcGFibGUsIHRhc2tzIGNvbnNpZGVyZWQgdG8gcmVxdWlyZSBpbnRlbGxpZ2VuY2VcbiIsCiAgICAiYXJlIG9mdGVuIHJlbW92ZWQgZnJvbSB0aGUgZGVmaW5pdGlvbiBvZiBBSSwgYSBwaGVub21lbm9uIGtub3duIGFzIHRoZSBBSSBlZmZlY3QuXCJcIlwiXG4iLAogICAgIlxuIiwKICAgICJzcGxpdHRlciA9IFJlY3Vyc2l2ZUNoYXJhY3RlclRleHRTcGxpdHRlcihjaHVua19zaXplPTIwMCwgY2h1bmtfb3ZlcmxhcD0zMClcbiIsCiAgICAiY2h1bmtzID0gc3BsaXR0ZXIuY3JlYXRlX2RvY3VtZW50cyhbbG9uZ190ZXh0XSlcbiIsCiAgICAiXG4iLAogICAgInByaW50KGZcIlNwbGl0IGludG8ge2xlbihjaHVua3MpfSBjaHVua3M6XCIpXG4iLAogICAgImZvciBpLCBjIGluIGVudW1lcmF0ZShjaHVua3MpOlxuIiwKICAgICIgICAgcHJpbnQoZlwiICBDaHVuayB7aSsxfSAoe2xlbihjLnBhZ2VfY29udGVudCl9IGNoYXJzKToge2MucGFnZV9jb250ZW50Wzo4MF19Li4uXCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAibWFya2Rvd24iLAogICAiaWQiOiAiYWYwMTA3MWQiLAogICAibWV0YWRhdGEiOiB7fSwKICAgInNvdXJjZSI6IFsKICAgICItLS1cbiIsCiAgICAiIyMgU2VjdGlvbiA3IFx1MjAxNCBUb29scyAmIEZ1bmN0aW9uIENhbGxpbmdcbiIsCiAgICAiXG4iLAogICAgIioqS2V5IGNvbmNlcHRzOioqXG4iLAogICAgIi0gKipUb29scyoqOiBmdW5jdGlvbnMgdGhlIExMTSBjYW4gY2hvb3NlIHRvIGNhbGwgKGNhbGN1bGF0b3IsIHNlYXJjaCwgQVBJKVxuIiwKICAgICItICoqRnVuY3Rpb24gY2FsbGluZyoqOiB0aGUgbW9kZWwgb3V0cHV0cyBhIHN0cnVjdHVyZWQgSlNPTiBjYWxsIGluc3RlYWQgb2YgcGxhaW4gdGV4dFxuIiwKICAgICItICoqVG9vbCBzY2hlbWEqKjogbmFtZSArIGRlc2NyaXB0aW9uICsgaW5wdXQgc2NoZW1hIFx1MjAxNCB0aGUgbW9kZWwgcmVhZHMgZGVzY3JpcHRpb25zIHRvIGRlY2lkZSB3aGVuIHRvIHVzZSBhIHRvb2xcbiIsCiAgICAiLSAqKlN0cnVjdHVyZWQgb3V0cHV0Kio6IGZvcmNlIHRoZSBtb2RlbCB0byByZXR1cm4gYSBzcGVjaWZpYyBzY2hlbWEiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICI1NmM4Y2VkMyIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgN2EuIERlZmluZSB0b29scyB1c2luZyBAdG9vbCBkZWNvcmF0b3JcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS50b29scyBpbXBvcnQgdG9vbFxuIiwKICAgICJpbXBvcnQgbWF0aFxuIiwKICAgICJpbXBvcnQgZGF0ZXRpbWVcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBjYWxjdWxhdG9yKGV4cHJlc3Npb246IHN0cikgLT4gc3RyOlxuIiwKICAgICIgICAgXCJcIlwiRXZhbHVhdGUgYSBtYXRoZW1hdGljYWwgZXhwcmVzc2lvbi4gSW5wdXQgbXVzdCBiZSBhIHZhbGlkIFB5dGhvbiBtYXRoIGV4cHJlc3Npb24uXG4iLAogICAgIiAgICBFeGFtcGxlczogJzIgKyAyJywgJ21hdGguc3FydCgxNDQpJywgJzE1ICogNyAvIDMnXCJcIlwiXG4iLAogICAgIiAgICB0cnk6XG4iLAogICAgIiAgICAgICAgcmVzdWx0ID0gZXZhbChleHByZXNzaW9uLCB7XCJfX2J1aWx0aW5zX19cIjoge319LCB7XCJtYXRoXCI6IG1hdGh9KVxuIiwKICAgICIgICAgICAgIHJldHVybiBzdHIocmVzdWx0KVxuIiwKICAgICIgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOlxuIiwKICAgICIgICAgICAgIHJldHVybiBmXCJFcnJvcjoge2V9XCJcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBnZXRfY3VycmVudF9kYXRlKHRpbWV6b25lOiBzdHIgPSBcIlVUQ1wiKSAtPiBzdHI6XG4iLAogICAgIiAgICBcIlwiXCJHZXQgdGhlIGN1cnJlbnQgZGF0ZSBhbmQgdGltZS4gT3B0aW9uYWxseSBzcGVjaWZ5IGEgdGltZXpvbmUgbmFtZS5cIlwiXCJcbiIsCiAgICAiICAgIHJldHVybiBkYXRldGltZS5kYXRldGltZS5ub3coKS5zdHJmdGltZShmXCIlWS0lbS0lZCAlSDolTTolUyAoe3RpbWV6b25lfSlcIilcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiB3b3JkX2NvdW50KHRleHQ6IHN0cikgLT4gc3RyOlxuIiwKICAgICIgICAgXCJcIlwiQ291bnQgdGhlIG51bWJlciBvZiB3b3JkcyBpbiBhIHRleHQgc3RyaW5nLlwiXCJcIlxuIiwKICAgICIgICAgcmV0dXJuIHN0cihsZW4odGV4dC5zcGxpdCgpKSlcbiIsCiAgICAiXG4iLAogICAgInByaW50KFwiVG9vbHMgZGVmaW5lZDpcIilcbiIsCiAgICAiZm9yIHQgaW4gW2NhbGN1bGF0b3IsIGdldF9jdXJyZW50X2RhdGUsIHdvcmRfY291bnRdOlxuIiwKICAgICIgICAgcHJpbnQoZlwiICAtIHt0Lm5hbWV9OiB7dC5kZXNjcmlwdGlvbls6NjBdfS4uLlwiKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjJjMDYzNTQyIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA3Yi4gQmluZCB0b29scyB0byB0aGUgTExNIGFuZCBoYW5kbGUgYSB0b29sIGNhbGwgbWFudWFsbHlcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5tZXNzYWdlcyBpbXBvcnQgSHVtYW5NZXNzYWdlLCBBSU1lc3NhZ2UsIFRvb2xNZXNzYWdlXG4iLAogICAgIlxuIiwKICAgICJ0b29scyA9IFtjYWxjdWxhdG9yLCBnZXRfY3VycmVudF9kYXRlLCB3b3JkX2NvdW50XVxuIiwKICAgICJsbG1fd2l0aF90b29scyA9IGxsbS5iaW5kX3Rvb2xzKHRvb2xzKVxuIiwKICAgICJcbiIsCiAgICAibWVzc2FnZXMgPSBbSHVtYW5NZXNzYWdlKGNvbnRlbnQ9XCJXaGF0IGlzIDE1JSBvZiAyNDA/IEFsc28gd2hhdCBpcyB0b2RheSdzIGRhdGU/XCIpXVxuIiwKICAgICJcbiIsCiAgICAiIyBGaXJzdCBjYWxsIFx1MjAxNCBtb2RlbCBtYXkgcmV0dXJuIHRvb2wgY2FsbHMgaW5zdGVhZCBvZiBhIGZpbmFsIGFuc3dlclxuIiwKICAgICJhaV9tc2cgPSBsbG1fd2l0aF90b29scy5pbnZva2UobWVzc2FnZXMpXG4iLAogICAgIm1lc3NhZ2VzLmFwcGVuZChhaV9tc2cpXG4iLAogICAgIlxuIiwKICAgICJwcmludChmXCJUb29sIGNhbGxzIHJlcXVlc3RlZDoge2xlbihhaV9tc2cudG9vbF9jYWxscyl9XCIpXG4iLAogICAgImZvciB0YyBpbiBhaV9tc2cudG9vbF9jYWxsczpcbiIsCiAgICAiICAgIHByaW50KGZcIiAgVG9vbDoge3RjWyduYW1lJ119LCBBcmdzOiB7dGNbJ2FyZ3MnXX1cIilcbiIsCiAgICAiXG4iLAogICAgIiMgRXhlY3V0ZSBlYWNoIHRvb2xcbiIsCiAgICAidG9vbF9tYXAgPSB7dC5uYW1lOiB0IGZvciB0IGluIHRvb2xzfVxuIiwKICAgICJmb3IgdGMgaW4gYWlfbXNnLnRvb2xfY2FsbHM6XG4iLAogICAgIiAgICByZXN1bHQgPSB0b29sX21hcFt0Y1tcIm5hbWVcIl1dLmludm9rZSh0Y1tcImFyZ3NcIl0pXG4iLAogICAgIiAgICBtZXNzYWdlcy5hcHBlbmQoVG9vbE1lc3NhZ2UoY29udGVudD1yZXN1bHQsIHRvb2xfY2FsbF9pZD10Y1tcImlkXCJdKSlcbiIsCiAgICAiXG4iLAogICAgIiMgU2Vjb25kIGNhbGwgXHUyMDE0IG1vZGVsIG5vdyBoYXMgdG9vbCByZXN1bHRzLCBwcm9kdWNlcyBmaW5hbCBhbnN3ZXJcbiIsCiAgICAiZmluYWwgPSBsbG1fd2l0aF90b29scy5pbnZva2UobWVzc2FnZXMpXG4iLAogICAgInByaW50KGZcIlxcbkZpbmFsIGFuc3dlcjoge2ZpbmFsLmNvbnRlbnR9XCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiMWIwMjY2ZTQiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDdjLiBTdHJ1Y3R1cmVkIG91dHB1dCBcdTIwMTQgZm9yY2UgbW9kZWwgdG8gcmV0dXJuIGEgc3BlY2lmaWMgc2NoZW1hXG4iLAogICAgImZyb20gcHlkYW50aWMgaW1wb3J0IEJhc2VNb2RlbCwgRmllbGRcbiIsCiAgICAiZnJvbSB0eXBpbmcgaW1wb3J0IExpc3RcbiIsCiAgICAiXG4iLAogICAgImNsYXNzIE1vdmllUmV2aWV3KEJhc2VNb2RlbCk6XG4iLAogICAgIiAgICB0aXRsZTogc3RyID0gRmllbGQoZGVzY3JpcHRpb249XCJNb3ZpZSB0aXRsZVwiKVxuIiwKICAgICIgICAgeWVhcjogaW50ID0gRmllbGQoZGVzY3JpcHRpb249XCJSZWxlYXNlIHllYXJcIilcbiIsCiAgICAiICAgIHNlbnRpbWVudDogc3RyID0gRmllbGQoZGVzY3JpcHRpb249XCJPdmVyYWxsIHNlbnRpbWVudDogcG9zaXRpdmUsIG5lZ2F0aXZlLCBvciBtaXhlZFwiKVxuIiwKICAgICIgICAgc2NvcmU6IGZsb2F0ID0gRmllbGQoZGVzY3JpcHRpb249XCJTY29yZSBvdXQgb2YgMTBcIilcbiIsCiAgICAiICAgIHByb3M6IExpc3Rbc3RyXSA9IEZpZWxkKGRlc2NyaXB0aW9uPVwiTGlzdCBvZiBwb3NpdGl2ZSBhc3BlY3RzXCIpXG4iLAogICAgIiAgICBjb25zOiBMaXN0W3N0cl0gPSBGaWVsZChkZXNjcmlwdGlvbj1cIkxpc3Qgb2YgbmVnYXRpdmUgYXNwZWN0c1wiKVxuIiwKICAgICJcbiIsCiAgICAic3RydWN0dXJlZF9sbG0gPSBsbG0ud2l0aF9zdHJ1Y3R1cmVkX291dHB1dChNb3ZpZVJldmlldylcbiIsCiAgICAiXG4iLAogICAgInJldmlld190ZXh0ID0gXCJcIlwiXG4iLAogICAgIkludGVyc3RlbGxhciAoMjAxNCkgaXMgYSB2aXN1YWxseSBzdHVubmluZyBzY2ktZmkgZXBpYy4gVGhlIHNwYWNlIHNlcXVlbmNlcyBhcmUgYnJlYXRodGFraW5nLFxuIiwKICAgICJIYW5zIFppbW1lcidzIHNjb3JlIGlzIHVuZm9yZ2V0dGFibGUsIGFuZCBNY0NvbmF1Z2hleSdzIHBlcmZvcm1hbmNlIGlzIG1vdmluZy4gSG93ZXZlcixcbiIsCiAgICAidGhlIHRoaXJkIGFjdCBnZXRzIG92ZXJseSBjb252b2x1dGVkIGFuZCB0aGUgc2NpZW5jZSBpcyBzb21ldGltZXMgc3RyZXRjaGVkIHRvbyB0aGluLlxuIiwKICAgICJPdmVyYWxsIGEgZ3JlYXQgZmlsbSwgOC8xMC5cbiIsCiAgICAiXCJcIlwiXG4iLAogICAgIlxuIiwKICAgICJyZXZpZXcgPSBzdHJ1Y3R1cmVkX2xsbS5pbnZva2UoZlwiRXh0cmFjdCBhIHN0cnVjdHVyZWQgcmV2aWV3IGZyb20gdGhpcyB0ZXh0OlxcbntyZXZpZXdfdGV4dH1cIilcbiIsCiAgICAicHJpbnQocmV2aWV3Lm1vZGVsX2R1bXBfanNvbihpbmRlbnQ9MikpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAibWFya2Rvd24iLAogICAiaWQiOiAiNDA2NjQ1MWQiLAogICAibWV0YWRhdGEiOiB7fSwKICAgInNvdXJjZSI6IFsKICAgICItLS1cbiIsCiAgICAiIyMgU2VjdGlvbiA4IFx1MjAxNCBBZ2VudHNcbiIsCiAgICAiXG4iLAogICAgIioqS2V5IGNvbmNlcHRzOioqXG4iLAogICAgIi0gKipBZ2VudCoqOiBhbiBMTE0gdGhhdCBjYW4gY2hvb3NlIHdoaWNoIHRvb2xzIHRvIHVzZSwgY2FsbCB0aGVtLCBvYnNlcnZlIHJlc3VsdHMsIGFuZCByZXBlYXRcbiIsCiAgICAiLSAqKlJlQWN0IHBhdHRlcm4qKjogUmVhc29uIFx1MjE5MiBBY3QgXHUyMTkyIE9ic2VydmUgXHUyMTkyIChyZXBlYXQgdW50aWwgZG9uZSlcbiIsCiAgICAiLSAqKlJlYXNvbmluZyBsb29wKio6IHRoZSBhZ2VudCBrZWVwcyBjYWxsaW5nIHRvb2xzIHVudGlsIGl0IGhhcyBlbm91Z2ggaW5mbyB0byBhbnN3ZXJcbiIsCiAgICAiLSAqKkFnZW50IGV4ZWN1dG9yKio6IHJ1bnRpbWUgdGhhdCBtYW5hZ2VzIHRoZSB0b29sLWNhbGwgbG9vcFxuIiwKICAgICItICoqU3RvcHBpbmcgY29uZGl0aW9uKio6IGFnZW50IGRlY2lkZXMgd2hlbiBpdCBoYXMgYSBmaW5hbCBhbnN3ZXIiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIwZjMwZTdmYiIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgOGEuIFJlQWN0IGFnZW50IFx1MjAxNCBzZWUgdGhlIHJlYXNvbmluZyBsb29wIHN0ZXAgYnkgc3RlcFxuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW4uYWdlbnRzIGltcG9ydCBjcmVhdGVfYWdlbnRcbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS50b29scyBpbXBvcnQgdG9vbFxuIiwKICAgICJpbXBvcnQgbWF0aCwgZGF0ZXRpbWVcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBjYWxjdWxhdG9yKGV4cHJlc3Npb246IHN0cikgLT4gc3RyOlxuIiwKICAgICIgICAgXCJcIlwiRXZhbHVhdGUgYSBtYXRoIGV4cHJlc3Npb24uIEV4YW1wbGU6ICcyICoqIDEwJyBvciAnbWF0aC5zcXJ0KDE0NCknXCJcIlwiXG4iLAogICAgIiAgICB0cnk6XG4iLAogICAgIiAgICAgICAgcmV0dXJuIHN0cihldmFsKGV4cHJlc3Npb24sIHtcIl9fYnVpbHRpbnNfX1wiOiB7fX0sIHtcIm1hdGhcIjogbWF0aH0pKVxuIiwKICAgICIgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOlxuIiwKICAgICIgICAgICAgIHJldHVybiBmXCJFcnJvcjoge2V9XCJcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBnZXRfY3VycmVudF95ZWFyKGR1bW15OiBzdHIgPSBcIlwiKSAtPiBzdHI6XG4iLAogICAgIiAgICBcIlwiXCJSZXR1cm5zIHRoZSBjdXJyZW50IHllYXIgYXMgYSBzdHJpbmcuXCJcIlwiXG4iLAogICAgIiAgICByZXR1cm4gc3RyKGRhdGV0aW1lLmRhdGV0aW1lLm5vdygpLnllYXIpXG4iLAogICAgIlxuIiwKICAgICJAdG9vbFxuIiwKICAgICJkZWYgc3RyaW5nX3JldmVyc2UodGV4dDogc3RyKSAtPiBzdHI6XG4iLAogICAgIiAgICBcIlwiXCJSZXZlcnNlcyBhIHN0cmluZy4gSW5wdXQ6IGFueSB0ZXh0IHN0cmluZy5cIlwiXCJcbiIsCiAgICAiICAgIHJldHVybiB0ZXh0Wzo6LTFdXG4iLAogICAgIlxuIiwKICAgICJhZ2VudF90b29scyA9IFtjYWxjdWxhdG9yLCBnZXRfY3VycmVudF95ZWFyLCBzdHJpbmdfcmV2ZXJzZV1cbiIsCiAgICAiXG4iLAogICAgIiMgY3JlYXRlX2FnZW50IGJ1aWxkcyBhIFN0YXRlR3JhcGggd2l0aCBhIHRvb2wtY2FsbGluZyBsb29wIGludGVybmFsbHlcbiIsCiAgICAiYWdlbnQgPSBjcmVhdGVfYWdlbnQobGxtLCBhZ2VudF90b29scylcbiIsCiAgICAiXG4iLAogICAgInJlc3VsdCA9IGFnZW50Lmludm9rZSh7XG4iLAogICAgIiAgICBcIm1lc3NhZ2VzXCI6IFsoXCJodW1hblwiLCBcIldoYXQgaXMgMiB0byB0aGUgcG93ZXIgb2YgMTAsIGFuZCB3aGF0IGlzIHRoYXQgbnVtYmVyIHJldmVyc2VkIGFzIGEgc3RyaW5nP1wiKV1cbiIsCiAgICAifSlcbiIsCiAgICAiXG4iLAogICAgImFuc3dlciA9IHJlc3VsdFtcIm1lc3NhZ2VzXCJdWy0xXS5jb250ZW50XG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiKipBbnN3ZXI6Kioge2Fuc3dlcn1cIikpXG4iLAogICAgIlxuIiwKICAgICIjIFNob3cgdGhlIHJlYXNvbmluZyBzdGVwc1xuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiLS0tXFxuKipSZWFzb25pbmcgdHJhY2U6KipcIikpXG4iLAogICAgImZvciBtc2cgaW4gcmVzdWx0W1wibWVzc2FnZXNcIl06XG4iLAogICAgIiAgICByb2xlID0gbXNnLl9fY2xhc3NfXy5fX25hbWVfXy5yZXBsYWNlKFwiTWVzc2FnZVwiLCBcIlwiKVxuIiwKICAgICIgICAgY29udGVudCA9IG1zZy5jb250ZW50IG9yIHN0cihnZXRhdHRyKG1zZywgXCJ0b29sX2NhbGxzXCIsIFwiXCIpKVxuIiwKICAgICIgICAgZGlzcGxheShNYXJrZG93bihmXCItICoqe3JvbGV9OioqIHtzdHIoY29udGVudClbOjIwMF19XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjM5ZGM5YWFkIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA4Yi4gY3JlYXRlX2FnZW50IHdpdGggYSBjdXN0b20gc3lzdGVtIHByb21wdFxuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW4uYWdlbnRzIGltcG9ydCBjcmVhdGVfYWdlbnRcbiIsCiAgICAiXG4iLAogICAgIiMgUGFzcyBhIHN5c3RlbSBwcm9tcHQgc3RyaW5nIGRpcmVjdGx5XG4iLAogICAgImFnZW50ID0gY3JlYXRlX2FnZW50KFxuIiwKICAgICIgICAgbGxtLFxuIiwKICAgICIgICAgYWdlbnRfdG9vbHMsXG4iLAogICAgIiAgICBzeXN0ZW1fcHJvbXB0PVwiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50LiBVc2UgdG9vbHMgd2hlbiBuZWVkZWQgdG8gYW5zd2VyIGFjY3VyYXRlbHkuXCJcbiIsCiAgICAiKVxuIiwKICAgICJcbiIsCiAgICAicmVzdWx0ID0gYWdlbnQuaW52b2tlKHtcbiIsCiAgICAiICAgIFwibWVzc2FnZXNcIjogWyhcImh1bWFuXCIsIFwiV2hhdCB5ZWFyIGlzIGl0LCBhbmQgd2hhdCBpcyBzcXJ0KHllYXIpIHJvdW5kZWQgdG8gMiBkZWNpbWFsIHBsYWNlcz9cIildXG4iLAogICAgIn0pXG4iLAogICAgIlxuIiwKICAgICJhbnN3ZXIgPSByZXN1bHRbXCJtZXNzYWdlc1wiXVstMV0uY29udGVudFxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIioqQW5zd2VyOioqIHthbnN3ZXJ9XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjJjYTY2ZDIxIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA4Yy4gUkFHLWVuYWJsZWQgYWdlbnQgXHUyMDE0IGFnZW50IGNhbiBjaG9vc2UgdG8gcmV0cmlldmUgZnJvbSB0aGUga25vd2xlZGdlIGJhc2VcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluLmFnZW50cyBpbXBvcnQgY3JlYXRlX2FnZW50XG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUudG9vbHMgaW1wb3J0IHRvb2xcbiIsCiAgICAiaW1wb3J0IG1hdGhcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBjYWxjdWxhdG9yKGV4cHJlc3Npb246IHN0cikgLT4gc3RyOlxuIiwKICAgICIgICAgXCJcIlwiRXZhbHVhdGUgYSBtYXRoIGV4cHJlc3Npb24uIEV4YW1wbGU6ICcyICoqIDEwJyBvciAnbWF0aC5zcXJ0KDE0NCknXCJcIlwiXG4iLAogICAgIiAgICB0cnk6XG4iLAogICAgIiAgICAgICAgcmV0dXJuIHN0cihldmFsKGV4cHJlc3Npb24sIHtcIl9fYnVpbHRpbnNfX1wiOiB7fX0sIHtcIm1hdGhcIjogbWF0aH0pKVxuIiwKICAgICIgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOlxuIiwKICAgICIgICAgICAgIHJldHVybiBmXCJFcnJvcjoge2V9XCJcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBzZWFyY2hfcHJvZ3JhbW1pbmdfa25vd2xlZGdlKHF1ZXJ5OiBzdHIpIC0+IHN0cjpcbiIsCiAgICAiICAgIFwiXCJcIlNlYXJjaCB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGtub3dsZWRnZSBiYXNlLiBVc2UgZm9yIHF1ZXN0aW9ucyBhYm91dCBQeXRob24sIFJ1c3QsIEphdmFTY3JpcHQsIG9yIEdvLlwiXCJcIlxuIiwKICAgICIgICAgcmVzdWx0cyA9IHZlY3RvcnN0b3JlLnNpbWlsYXJpdHlfc2VhcmNoKHF1ZXJ5LCBrPTIpXG4iLAogICAgIiAgICByZXR1cm4gXCJcXG5cIi5qb2luKGRvYy5wYWdlX2NvbnRlbnQgZm9yIGRvYyBpbiByZXN1bHRzKVxuIiwKICAgICJcbiIsCiAgICAicmFnX3Rvb2xzID0gW2NhbGN1bGF0b3IsIHNlYXJjaF9wcm9ncmFtbWluZ19rbm93bGVkZ2VdXG4iLAogICAgIlxuIiwKICAgICJyYWdfYWdlbnQgPSBjcmVhdGVfYWdlbnQoXG4iLAogICAgIiAgICBsbG0sXG4iLAogICAgIiAgICByYWdfdG9vbHMsXG4iLAogICAgIiAgICBzeXN0ZW1fcHJvbXB0PVwiWW91IGFyZSBhIGtub3dsZWRnZWFibGUgYXNzaXN0YW50LiBBbHdheXMgc2VhcmNoIHRoZSBrbm93bGVkZ2UgYmFzZSBiZWZvcmUgYW5zd2VyaW5nLlwiXG4iLAogICAgIilcbiIsCiAgICAiXG4iLAogICAgInJlc3VsdCA9IHJhZ19hZ2VudC5pbnZva2Uoe1xuIiwKICAgICIgICAgXCJtZXNzYWdlc1wiOiBbKFwiaHVtYW5cIiwgXCJDb21wYXJlIFB5dGhvbiBhbmQgUnVzdC4gV2hpY2ggb25lIHByZXZlbnRzIG1lbW9yeSBidWdzIGF0IGNvbXBpbGUgdGltZT9cIildXG4iLAogICAgIn0pXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIioqQW5zd2VyOioqIHtyZXN1bHRbJ21lc3NhZ2VzJ11bLTFdLmNvbnRlbnR9XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogIm1hcmtkb3duIiwKICAgImlkIjogIjQ5MDZhNzU2IiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJzb3VyY2UiOiBbCiAgICAiLS0tXG4iLAogICAgIiMjIFNlY3Rpb24gOSBcdTIwMTQgTXVsdGktQWdlbnQgU3lzdGVtc1xuIiwKICAgICJcbiIsCiAgICAiKipLZXkgY29uY2VwdHM6KipcbiIsCiAgICAiLSAqKk9yY2hlc3RyYXRvcioqOiBhIGNlbnRyYWwgYWdlbnQgdGhhdCBwbGFucyBhbmQgZGVsZWdhdGVzIHRhc2tzXG4iLAogICAgIi0gKipXb3JrZXIvU3BlY2lhbGlzdCBhZ2VudCoqOiBmb2N1c2VkIG9uIG9uZSBkb21haW4gKGNvZGUsIHJlc2VhcmNoLCBtYXRoKVxuIiwKICAgICItICoqSGFuZG9mZioqOiBwYXNzaW5nIGEgdGFzayBmcm9tIG9uZSBhZ2VudCB0byBhbm90aGVyXG4iLAogICAgIi0gKipXaHkgbXVsdGktYWdlbnQ/KiogQ29tcGxleCB0YXNrcyBiZW5lZml0IGZyb20gc3BlY2lhbGlzYXRpb24gYW5kIHBhcmFsbGVsaXNtXG4iLAogICAgIi0gKipBZ2VudC1hcy10b29sKio6IHdyYXAgb25lIGFnZW50IGFzIGEgY2FsbGFibGUgdG9vbCBmb3IgYW5vdGhlciBhZ2VudCIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjNhYmRiZDVjIiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyA5YS4gU3BlY2lhbGlzdCBhZ2VudHMgdXNlZCBhcyB0b29scyBieSBhbiBvcmNoZXN0cmF0b3JcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluLmFnZW50cyBpbXBvcnQgY3JlYXRlX2FnZW50XG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUudG9vbHMgaW1wb3J0IHRvb2xcbiIsCiAgICAiXG4iLAogICAgIiMgLS0tIFNwZWNpYWxpc3Q6IENvZGUgRXhwbGFpbmVyIC0tLVxuIiwKICAgICJjb2RlX2FnZW50ID0gY3JlYXRlX2FnZW50KFxuIiwKICAgICIgICAgbGxtLCBbXSxcbiIsCiAgICAiICAgIHN5c3RlbV9wcm9tcHQ9XCJZb3UgYXJlIGFuIGV4cGVydCBwcm9ncmFtbWVyLiBFeHBsYWluIGNvZGUgY2xlYXJseSBhbmQgY29uY2lzZWx5LlwiXG4iLAogICAgIilcbiIsCiAgICAiXG4iLAogICAgIiMgLS0tIFNwZWNpYWxpc3Q6IFdyaXRlciAtLS1cbiIsCiAgICAid3JpdGVyX2FnZW50ID0gY3JlYXRlX2FnZW50KFxuIiwKICAgICIgICAgbGxtLCBbXSxcbiIsCiAgICAiICAgIHN5c3RlbV9wcm9tcHQ9XCJZb3UgYXJlIGEgcHJvZmVzc2lvbmFsIHdyaXRlci4gUHJvZHVjZSBjbGVhciwgZW5nYWdpbmcgY29udGVudC5cIlxuIiwKICAgICIpXG4iLAogICAgIlxuIiwKICAgICIjIC0tLSBXcmFwIHNwZWNpYWxpc3RzIGFzIHRvb2xzIGZvciB0aGUgb3JjaGVzdHJhdG9yIC0tLVxuIiwKICAgICJAdG9vbFxuIiwKICAgICJkZWYgYXNrX2NvZGVfYWdlbnQodGFzazogc3RyKSAtPiBzdHI6XG4iLAogICAgIiAgICBcIlwiXCJEZWxlZ2F0ZSBhIGNvZGluZyBvciBjb2RlLWV4cGxhbmF0aW9uIHRhc2sgdG8gdGhlIHNwZWNpYWxpc3QgY29kZSBhZ2VudC5cIlwiXCJcbiIsCiAgICAiICAgIHJlc3VsdCA9IGNvZGVfYWdlbnQuaW52b2tlKHtcIm1lc3NhZ2VzXCI6IFsoXCJodW1hblwiLCB0YXNrKV19KVxuIiwKICAgICIgICAgcmV0dXJuIHJlc3VsdFtcIm1lc3NhZ2VzXCJdWy0xXS5jb250ZW50XG4iLAogICAgIlxuIiwKICAgICJAdG9vbFxuIiwKICAgICJkZWYgYXNrX3dyaXRlcl9hZ2VudCh0YXNrOiBzdHIpIC0+IHN0cjpcbiIsCiAgICAiICAgIFwiXCJcIkRlbGVnYXRlIGEgd3JpdGluZyBvciBjb250ZW50LWNyZWF0aW9uIHRhc2sgdG8gdGhlIHNwZWNpYWxpc3Qgd3JpdGVyIGFnZW50LlwiXCJcIlxuIiwKICAgICIgICAgcmVzdWx0ID0gd3JpdGVyX2FnZW50Lmludm9rZSh7XCJtZXNzYWdlc1wiOiBbKFwiaHVtYW5cIiwgdGFzayldfSlcbiIsCiAgICAiICAgIHJldHVybiByZXN1bHRbXCJtZXNzYWdlc1wiXVstMV0uY29udGVudFxuIiwKICAgICJcbiIsCiAgICAiIyAtLS0gT3JjaGVzdHJhdG9yIC0tLVxuIiwKICAgICJvcmNoZXN0cmF0b3IgPSBjcmVhdGVfYWdlbnQoXG4iLAogICAgIiAgICBsbG0sXG4iLAogICAgIiAgICBbYXNrX2NvZGVfYWdlbnQsIGFza193cml0ZXJfYWdlbnRdLFxuIiwKICAgICIgICAgc3lzdGVtX3Byb21wdD1cIlwiXCJZb3UgYXJlIGFuIG9yY2hlc3RyYXRvci4gQnJlYWsgZG93biBjb21wbGV4IHRhc2tzIGFuZCBkZWxlZ2F0ZSB0byB0aGUgcmlnaHQgc3BlY2lhbGlzdDpcbiIsCiAgICAiLSBhc2tfY29kZV9hZ2VudDogZm9yIGNvZGluZywgY29kZSBleHBsYW5hdGlvbiwgdGVjaG5pY2FsIHRvcGljc1xuIiwKICAgICItIGFza193cml0ZXJfYWdlbnQ6IGZvciB3cml0aW5nLCBzdW1tYXJpc2luZywgb3IgY3JlYXRpdmUgY29udGVudFxuIiwKICAgICJDb21iaW5lIHRoZWlyIG91dHB1dHMgaW50byBhIGZpbmFsIGNvaGVzaXZlIGFuc3dlci5cIlwiXCJcbiIsCiAgICAiKVxuIiwKICAgICJcbiIsCiAgICAicmVzdWx0ID0gb3JjaGVzdHJhdG9yLmludm9rZSh7XG4iLAogICAgIiAgICBcIm1lc3NhZ2VzXCI6IFsoXCJodW1hblwiLCBcIkV4cGxhaW4gd2hhdCBhIFB5dGhvbiBsaXN0IGNvbXByZWhlbnNpb24gaXMgYW5kIHRoZW4gd3JpdGUgYSBzaG9ydCBibG9nIGludHJvIGFib3V0IHdoeSBQeXRob24gaXMgYmVnaW5uZXItZnJpZW5kbHkuXCIpXVxuIiwKICAgICJ9KVxuIiwKICAgICJcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihmXCIjIyMgRmluYWwgQW5zd2VyXFxue3Jlc3VsdFsnbWVzc2FnZXMnXVstMV0uY29udGVudH1cIikpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiOTUzYjEyMzYiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDliLiBQYXJhbGxlbCBtdWx0aS1hZ2VudCBleGVjdXRpb24gKG1hbnVhbClcbiIsCiAgICAiaW1wb3J0IGNvbmN1cnJlbnQuZnV0dXJlc1xuIiwKICAgICJmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgZGlzcGxheSwgTWFya2Rvd25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS5tZXNzYWdlcyBpbXBvcnQgSHVtYW5NZXNzYWdlXG4iLAogICAgIlxuIiwKICAgICJkZWYgcnVuX2FnZW50KHJvbGUsIHN5c3RlbV9wcm9tcHQsIHF1ZXN0aW9uKTpcbiIsCiAgICAiICAgIGZyb20gbGFuZ2NoYWluX2NvcmUubWVzc2FnZXMgaW1wb3J0IFN5c3RlbU1lc3NhZ2UsIEh1bWFuTWVzc2FnZVxuIiwKICAgICIgICAgcmVzcG9uc2UgPSBsbG0uaW52b2tlKFtcbiIsCiAgICAiICAgICAgICBTeXN0ZW1NZXNzYWdlKGNvbnRlbnQ9c3lzdGVtX3Byb21wdCksXG4iLAogICAgIiAgICAgICAgSHVtYW5NZXNzYWdlKGNvbnRlbnQ9cXVlc3Rpb24pXG4iLAogICAgIiAgICBdKVxuIiwKICAgICIgICAgcmV0dXJuIHJvbGUsIHJlc3BvbnNlLmNvbnRlbnRcbiIsCiAgICAiXG4iLAogICAgImFnZW50c19jb25maWcgPSBbXG4iLAogICAgIiAgICAoXCJPcHRpbWlzdFwiLCBcIllvdSBhcmUgYW4gb3B0aW1pc3QuIEZpbmQgdGhlIHBvc2l0aXZlIGFzcGVjdHMgb2YgYW55IHRvcGljLlwiLCBcIldoYXQgaXMgdGhlIGltcGFjdCBvZiBBSSBvbiBqb2JzP1wiKSxcbiIsCiAgICAiICAgIChcIlBlc3NpbWlzdFwiLCBcIllvdSBhcmUgYSBwZXNzaW1pc3QuIEZpbmQgdGhlIHJpc2tzIGFuZCBkb3duc2lkZXMgb2YgYW55IHRvcGljLlwiLCBcIldoYXQgaXMgdGhlIGltcGFjdCBvZiBBSSBvbiBqb2JzP1wiKSxcbiIsCiAgICAiICAgIChcIk5ldXRyYWxcIiwgIFwiWW91IGFyZSBhIGJhbGFuY2VkIGFuYWx5c3QuIEdpdmUgYSBmYWN0dWFsLCBuZXV0cmFsIGFzc2Vzc21lbnQuXCIsIFwiV2hhdCBpcyB0aGUgaW1wYWN0IG9mIEFJIG9uIGpvYnM/XCIpLFxuIiwKICAgICJdXG4iLAogICAgIlxuIiwKICAgICJ3aXRoIGNvbmN1cnJlbnQuZnV0dXJlcy5UaHJlYWRQb29sRXhlY3V0b3IoKSBhcyBwb29sOlxuIiwKICAgICIgICAgZnV0dXJlcyA9IFtwb29sLnN1Ym1pdChydW5fYWdlbnQsICpjZmcpIGZvciBjZmcgaW4gYWdlbnRzX2NvbmZpZ11cbiIsCiAgICAiICAgIHJlc3VsdHMgPSBbZi5yZXN1bHQoKSBmb3IgZiBpbiBjb25jdXJyZW50LmZ1dHVyZXMuYXNfY29tcGxldGVkKGZ1dHVyZXMpXVxuIiwKICAgICJcbiIsCiAgICAiZm9yIHJvbGUsIGFuc3dlciBpbiBzb3J0ZWQocmVzdWx0cyk6XG4iLAogICAgIiAgICBkaXNwbGF5KE1hcmtkb3duKGZcIiMjIyB7cm9sZX1cXG57YW5zd2VyfVwiKSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJtYXJrZG93biIsCiAgICJpZCI6ICI1MWNhZGUzNCIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAic291cmNlIjogWwogICAgIi0tLVxuIiwKICAgICIjIyBTZWN0aW9uIDEwIFx1MjAxNCBBZ2VudGljIFBhdHRlcm5zXG4iLAogICAgIlxuIiwKICAgICIqKktleSBjb25jZXB0czoqKlxuIiwKICAgICItICoqUGxhbm5pbmcqKjogYWdlbnQgZGVjb21wb3NlcyBhIGdvYWwgaW50byBzdWItdGFza3MgYmVmb3JlIGFjdGluZ1xuIiwKICAgICItICoqUmVmbGVjdGlvbiAvIHNlbGYtY3JpdGlxdWUqKjogYWdlbnQgcmV2aWV3cyBhbmQgaW1wcm92ZXMgaXRzIG93biBvdXRwdXRcbiIsCiAgICAiLSAqKlRvb2wtdXNlIGxvb3BzKio6IHJlcGVhdCB1bnRpbCBhIHN0b3BwaW5nIGNvbmRpdGlvbiBpcyBtZXRcbiIsCiAgICAiLSAqKkh1bWFuLWluLXRoZS1sb29wKio6IHBhdXNlIGZvciBodW1hbiBhcHByb3ZhbCBiZWZvcmUgcHJvY2VlZGluZ1xuIiwKICAgICItICoqRXZhbHVhdG9yLU9wdGltaXplcioqOiBvbmUgTExNIGdlbmVyYXRlcywgYW5vdGhlciBzY29yZXMvY3JpdGlxdWVzLCBsb29wIHVudGlsIHF1YWxpdHkgdGhyZXNob2xkXG4iLAogICAgIi0gKipNYXAtUmVkdWNlKio6IHByb2Nlc3MgbWFueSBpdGVtcyBpbiBwYXJhbGxlbCAobWFwKSwgc3ludGhlc2lzZSByZXN1bHRzIChyZWR1Y2UpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiMDA1NWZlMzciLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDEwYS4gUGxhbm5pbmcgcGF0dGVybiBcdTIwMTQgZGVjb21wb3NlIGEgZ29hbCBiZWZvcmUgYWN0aW5nXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnByb21wdHMgaW1wb3J0IENoYXRQcm9tcHRUZW1wbGF0ZVxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm91dHB1dF9wYXJzZXJzIGltcG9ydCBKc29uT3V0cHV0UGFyc2VyXG4iLAogICAgIlxuIiwKICAgICJwbGFuX3Byb21wdCA9IENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX21lc3NhZ2VzKFtcbiIsCiAgICAiICAgIChcInN5c3RlbVwiLCBcIlwiXCJZb3UgYXJlIGEgcGxhbm5pbmcgYWdlbnQuIEJyZWFrIGRvd24gdGhlIHVzZXIncyBnb2FsIGludG8gYSBudW1iZXJlZCBsaXN0IG9mIGNvbmNyZXRlIHN1Yi10YXNrcy5cbiIsCiAgICAiUmV0dXJuIEpTT046IHt7XCJnb2FsXCI6IHN0cmluZywgXCJ0YXNrc1wiOiBbe3tcImlkXCI6IGludCwgXCJ0YXNrXCI6IHN0cmluZywgXCJkZXBlbmRzX29uXCI6IFtdfX1dfX1cIlwiXCIpLFxuIiwKICAgICIgICAgKFwiaHVtYW5cIiwgXCJHb2FsOiB7Z29hbH1cIilcbiIsCiAgICAiXSlcbiIsCiAgICAiXG4iLAogICAgInBsYW5uZXIgPSBwbGFuX3Byb21wdCB8IGxsbSB8IEpzb25PdXRwdXRQYXJzZXIoKVxuIiwKICAgICJcbiIsCiAgICAicGxhbiA9IHBsYW5uZXIuaW52b2tlKHtcImdvYWxcIjogXCJCdWlsZCBhIHNpbXBsZSB3ZWF0aGVyIGFwcCB0aGF0IHNob3dzIGN1cnJlbnQgdGVtcGVyYXR1cmVcIn0pXG4iLAogICAgIlxuIiwKICAgICJyb3dzID0gW2ZcIioqR29hbDoqKiB7cGxhblsnZ29hbCddfVxcblwiLCBcInwgIyB8IFRhc2sgfCBEZXBlbmRzIE9uIHxcIiwgXCJ8LS0tfC0tLS0tLXwtLS0tLS0tLS0tLS18XCJdXG4iLAogICAgImZvciB0YXNrIGluIHBsYW5bXCJ0YXNrc1wiXTpcbiIsCiAgICAiICAgIGRlcHMgPSBcIiwgXCIuam9pbihzdHIoZCkgZm9yIGQgaW4gdGFza1tcImRlcGVuZHNfb25cIl0pIGlmIHRhc2tbXCJkZXBlbmRzX29uXCJdIGVsc2UgXCJcdTIwMTRcIlxuIiwKICAgICIgICAgcm93cy5hcHBlbmQoZlwifCB7dGFza1snaWQnXX0gfCB7dGFza1sndGFzayddfSB8IHtkZXBzfSB8XCIpXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiXFxuXCIuam9pbihyb3dzKSkpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYWZkZmZhYjkiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDEwYi4gUmVmbGVjdGlvbiBwYXR0ZXJuIFx1MjAxNCBnZW5lcmF0ZSBcdTIxOTIgY3JpdGlxdWUgXHUyMTkyIGltcHJvdmVcbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUucHJvbXB0cyBpbXBvcnQgQ2hhdFByb21wdFRlbXBsYXRlXG4iLAogICAgImZyb20gbGFuZ2NoYWluX2NvcmUub3V0cHV0X3BhcnNlcnMgaW1wb3J0IFN0ck91dHB1dFBhcnNlclxuIiwKICAgICJcbiIsCiAgICAiZ2VuZXJhdGVfcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fdGVtcGxhdGUoXG4iLAogICAgIiAgICBcIldyaXRlIGEgc2hvcnQgcGFyYWdyYXBoIGV4cGxhaW5pbmcge3RvcGljfSBmb3IgYSBiZWdpbm5lci5cIlxuIiwKICAgICIpXG4iLAogICAgImNyaXRpcXVlX3Byb21wdCA9IENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX21lc3NhZ2VzKFtcbiIsCiAgICAiICAgIChcInN5c3RlbVwiLCBcIllvdSBhcmUgYSBzdHJpY3Qgd3JpdGluZyBjcml0aWMuIElkZW50aWZ5IHNwZWNpZmljIHdlYWtuZXNzZXM6IHVuY2xlYXIgdGVybXMsIG1pc3NpbmcgY29udGV4dCwgcG9vciBmbG93LiBCZSBjb25jaXNlLlwiKSxcbiIsCiAgICAiICAgIChcImh1bWFuXCIsIFwiQ3JpdGlxdWUgdGhpcyBleHBsYW5hdGlvbjpcXG5cXG57ZHJhZnR9XCIpXG4iLAogICAgIl0pXG4iLAogICAgImltcHJvdmVfcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fbWVzc2FnZXMoW1xuIiwKICAgICIgICAgKFwic3lzdGVtXCIsIFwiWW91IGFyZSBhIHdyaXRpbmcgaW1wcm92ZXIuIEZpeCB0aGUgaXNzdWVzIGlkZW50aWZpZWQgaW4gdGhlIGNyaXRpcXVlLlwiKSxcbiIsCiAgICAiICAgIChcImh1bWFuXCIsIFwiT3JpZ2luYWw6XFxue2RyYWZ0fVxcblxcbkNyaXRpcXVlOlxcbntjcml0aXF1ZX1cXG5cXG5Xcml0ZSBhbiBpbXByb3ZlZCB2ZXJzaW9uOlwiKVxuIiwKICAgICJdKVxuIiwKICAgICJcbiIsCiAgICAicGFyc2VyID0gU3RyT3V0cHV0UGFyc2VyKClcbiIsCiAgICAiXG4iLAogICAgInRvcGljID0gXCJuZXVyYWwgbmV0d29ya3NcIlxuIiwKICAgICJcbiIsCiAgICAiZHJhZnQgICAgPSAoZ2VuZXJhdGVfcHJvbXB0IHwgbGxtIHwgcGFyc2VyKS5pbnZva2Uoe1widG9waWNcIjogdG9waWN9KVxuIiwKICAgICJjcml0aXF1ZSA9IChjcml0aXF1ZV9wcm9tcHQgfCBsbG0gfCBwYXJzZXIpLmludm9rZSh7XCJkcmFmdFwiOiBkcmFmdH0pXG4iLAogICAgImltcHJvdmVkID0gKGltcHJvdmVfcHJvbXB0ICB8IGxsbSB8IHBhcnNlcikuaW52b2tlKHtcImRyYWZ0XCI6IGRyYWZ0LCBcImNyaXRpcXVlXCI6IGNyaXRpcXVlfSlcbiIsCiAgICAiXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiIyMjIERyYWZ0XFxue2RyYWZ0fVwiKSlcbiIsCiAgICAiZGlzcGxheShNYXJrZG93bihmXCIjIyMgQ3JpdGlxdWVcXG57Y3JpdGlxdWV9XCIpKVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIiMjIyBJbXByb3ZlZFxcbntpbXByb3ZlZH1cIikpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiNjg2NDE5NTIiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIDEwYy4gRXZhbHVhdG9yLU9wdGltaXplciBsb29wIFx1MjAxNCBpdGVyYXRlIHVudGlsIHF1YWxpdHkgc2NvcmUgPj0gdGhyZXNob2xkXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnByb21wdHMgaW1wb3J0IENoYXRQcm9tcHRUZW1wbGF0ZVxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm91dHB1dF9wYXJzZXJzIGltcG9ydCBKc29uT3V0cHV0UGFyc2VyLCBTdHJPdXRwdXRQYXJzZXJcbiIsCiAgICAiXG4iLAogICAgIndyaXRlX3Byb21wdCA9IENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX3RlbXBsYXRlKFxuIiwKICAgICIgICAgXCJXcml0ZSBhIGhhaWt1IGFib3V0IHtzdWJqZWN0fS4gSnVzdCB0aGUgaGFpa3UsIG5vIGNvbW1lbnRhcnkuXCJcbiIsCiAgICAiKVxuIiwKICAgICJldmFsX3Byb21wdCA9IENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX21lc3NhZ2VzKFtcbiIsCiAgICAiICAgIChcInN5c3RlbVwiLCBcIlNjb3JlIHRoZSBoYWlrdSAxLTEwIGZvciBjcmVhdGl2aXR5IGFuZCBhZGhlcmVuY2UgdG8gNS03LTUgc3lsbGFibGUgc3RydWN0dXJlLiBSZXR1cm4gSlNPTjoge3tcXFwic2NvcmVcXFwiOiBpbnQsIFxcXCJmZWVkYmFja1xcXCI6IHN0cmluZ319XCIpLFxuIiwKICAgICIgICAgKFwiaHVtYW5cIiwgXCJ7aGFpa3V9XCIpXG4iLAogICAgIl0pXG4iLAogICAgImltcHJvdmVfcHJvbXB0ID0gQ2hhdFByb21wdFRlbXBsYXRlLmZyb21fdGVtcGxhdGUoXG4iLAogICAgIiAgICBcIkltcHJvdmUgdGhpcyBoYWlrdSBiYXNlZCBvbiB0aGlzIGZlZWRiYWNrOiB7ZmVlZGJhY2t9XFxuXFxuT3JpZ2luYWw6XFxue2hhaWt1fVxcblxcbkltcHJvdmVkIGhhaWt1IChqdXN0IHRoZSBoYWlrdSk6XCJcbiIsCiAgICAiKVxuIiwKICAgICJcbiIsCiAgICAid3JpdGVyICAgID0gd3JpdGVfcHJvbXB0ICAgfCBsbG0gfCBTdHJPdXRwdXRQYXJzZXIoKVxuIiwKICAgICJldmFsdWF0b3IgPSBldmFsX3Byb21wdCAgICB8IGxsbSB8IEpzb25PdXRwdXRQYXJzZXIoKVxuIiwKICAgICJpbXByb3ZlciAgPSBpbXByb3ZlX3Byb21wdCB8IGxsbSB8IFN0ck91dHB1dFBhcnNlcigpXG4iLAogICAgIlxuIiwKICAgICJUSFJFU0hPTEQgPSA3XG4iLAogICAgIk1BWF9ST1VORFMgPSA0XG4iLAogICAgIlxuIiwKICAgICJoYWlrdSA9IHdyaXRlci5pbnZva2Uoe1wic3ViamVjdFwiOiBcIm1hY2hpbmUgbGVhcm5pbmdcIn0pXG4iLAogICAgImRpc3BsYXkoTWFya2Rvd24oZlwiKipSb3VuZCAwIChpbml0aWFsKToqKlxcblxcbntoYWlrdX1cIikpXG4iLAogICAgIlxuIiwKICAgICJmb3Igcm91bmRfbnVtIGluIHJhbmdlKDEsIE1BWF9ST1VORFMgKyAxKTpcbiIsCiAgICAiICAgIGV2YWx1YXRpb24gPSBldmFsdWF0b3IuaW52b2tlKHtcImhhaWt1XCI6IGhhaWt1fSlcbiIsCiAgICAiICAgIHNjb3JlLCBmZWVkYmFjayA9IGV2YWx1YXRpb25bXCJzY29yZVwiXSwgZXZhbHVhdGlvbltcImZlZWRiYWNrXCJdXG4iLAogICAgIiAgICBkaXNwbGF5KE1hcmtkb3duKGZcIioqUm91bmQge3JvdW5kX251bX0gc2NvcmU6Kioge3Njb3JlfS8xMCBcdTIwMTQge2ZlZWRiYWNrfVwiKSlcbiIsCiAgICAiICAgIGlmIHNjb3JlID49IFRIUkVTSE9MRDpcbiIsCiAgICAiICAgICAgICBkaXNwbGF5KE1hcmtkb3duKGZcIioqQWNjZXB0ZWQhIEZpbmFsIGhhaWt1OioqXFxuXFxue2hhaWt1fVwiKSlcbiIsCiAgICAiICAgICAgICBicmVha1xuIiwKICAgICIgICAgaGFpa3UgPSBpbXByb3Zlci5pbnZva2Uoe1wiaGFpa3VcIjogaGFpa3UsIFwiZmVlZGJhY2tcIjogZmVlZGJhY2t9KVxuIiwKICAgICIgICAgZGlzcGxheShNYXJrZG93bihmXCIqKkltcHJvdmVkOioqXFxuXFxue2hhaWt1fVwiKSlcbiIsCiAgICAiZWxzZTpcbiIsCiAgICAiICAgIGRpc3BsYXkoTWFya2Rvd24oZlwiKipNYXggcm91bmRzIHJlYWNoZWQuIEJlc3QgaGFpa3U6KipcXG5cXG57aGFpa3V9XCIpKSIKICAgXQogIH0sCiAgewogICAiY2VsbF90eXBlIjogImNvZGUiLAogICAiZXhlY3V0aW9uX2NvdW50IjogbnVsbCwKICAgImlkIjogIjNjN2QwNTQ3IiwKICAgIm1ldGFkYXRhIjoge30sCiAgICJvdXRwdXRzIjogW10sCiAgICJzb3VyY2UiOiBbCiAgICAiIyAxMGQuIE1hcC1SZWR1Y2UgcGF0dGVybiBcdTIwMTQgc3VtbWFyaXNlIG11bHRpcGxlIGRvY3VtZW50cyBpbiBwYXJhbGxlbFxuIiwKICAgICJpbXBvcnQgY29uY3VycmVudC5mdXR1cmVzXG4iLAogICAgImZyb20gSVB5dGhvbi5kaXNwbGF5IGltcG9ydCBkaXNwbGF5LCBNYXJrZG93blxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnByb21wdHMgaW1wb3J0IENoYXRQcm9tcHRUZW1wbGF0ZVxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm91dHB1dF9wYXJzZXJzIGltcG9ydCBTdHJPdXRwdXRQYXJzZXJcbiIsCiAgICAiXG4iLAogICAgImRvY3VtZW50cyA9IFtcbiIsCiAgICAiICAgIFwiUHl0aG9uIHdhcyBjcmVhdGVkIGJ5IEd1aWRvIHZhbiBSb3NzdW0gYW5kIGZpcnN0IHJlbGVhc2VkIGluIDE5OTEuIEl0IGVtcGhhc2lzZXMgY29kZSByZWFkYWJpbGl0eSBhbmQgc2ltcGxpY2l0eS5cIixcbiIsCiAgICAiICAgIFwiSmF2YVNjcmlwdCB3YXMgY3JlYXRlZCBieSBCcmVuZGFuIEVpY2ggYXQgTmV0c2NhcGUgaW4gMTk5NS4gT3JpZ2luYWxseSBkZXNpZ25lZCBmb3IgYnJvd3NlciBzY3JpcHRpbmcsIGl0IG5vdyBydW5zIG9uIHNlcnZlcnMgdmlhIE5vZGUuanMuXCIsXG4iLAogICAgIiAgICBcIlJ1c3Qgd2FzIGRlc2lnbmVkIGJ5IEdyYXlkb24gSG9hcmUgYXQgTW96aWxsYSBSZXNlYXJjaCBhbmQgYW5ub3VuY2VkIGluIDIwMTAuIEl0IGd1YXJhbnRlZXMgbWVtb3J5IHNhZmV0eSB3aXRob3V0IGEgZ2FyYmFnZSBjb2xsZWN0b3IuXCIsXG4iLAogICAgIiAgICBcIkdvIHdhcyBjcmVhdGVkIGF0IEdvb2dsZSBieSBSb2JlcnQgR3JpZXNlbWVyLCBSb2IgUGlrZSwgYW5kIEtlbiBUaG9tcHNvbiwgcmVsZWFzZWQgaW4gMjAwOS4gSXQgcHJpb3JpdGlzZXMgc2ltcGxpY2l0eSBhbmQgZmFzdCBjb21waWxlIHRpbWVzLlwiLFxuIiwKICAgICJdXG4iLAogICAgIlxuIiwKICAgICJtYXBfY2hhaW4gPSAoXG4iLAogICAgIiAgICBDaGF0UHJvbXB0VGVtcGxhdGUuZnJvbV90ZW1wbGF0ZShcIlN1bW1hcmlzZSBpbiBvbmUgc2VudGVuY2U6IHtkb2N9XCIpXG4iLAogICAgIiAgICB8IGxsbSB8IFN0ck91dHB1dFBhcnNlcigpXG4iLAogICAgIilcbiIsCiAgICAiXG4iLAogICAgInJlZHVjZV9jaGFpbiA9IChcbiIsCiAgICAiICAgIENoYXRQcm9tcHRUZW1wbGF0ZS5mcm9tX3RlbXBsYXRlKFxuIiwKICAgICIgICAgICAgIFwiR2l2ZW4gdGhlc2Ugc3VtbWFyaWVzIG9mIHByb2dyYW1taW5nIGxhbmd1YWdlczpcXG57c3VtbWFyaWVzfVxcblxcbldyaXRlIGEgMi1zZW50ZW5jZSBvdmVyYWxsIHN5bnRoZXNpcy5cIlxuIiwKICAgICIgICAgKSB8IGxsbSB8IFN0ck91dHB1dFBhcnNlcigpXG4iLAogICAgIilcbiIsCiAgICAiXG4iLAogICAgIndpdGggY29uY3VycmVudC5mdXR1cmVzLlRocmVhZFBvb2xFeGVjdXRvcigpIGFzIHBvb2w6XG4iLAogICAgIiAgICBzdW1tYXJpZXMgPSBsaXN0KHBvb2wubWFwKGxhbWJkYSBkOiBtYXBfY2hhaW4uaW52b2tlKHtcImRvY1wiOiBkfSksIGRvY3VtZW50cykpXG4iLAogICAgIlxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKFwiIyMjIE1BUCAoaW5kaXZpZHVhbCBzdW1tYXJpZXMpXFxuXCIgKyBcIlxcblwiLmpvaW4oZlwiLSB7c31cIiBmb3IgcyBpbiBzdW1tYXJpZXMpKSlcbiIsCiAgICAiXG4iLAogICAgInN5bnRoZXNpcyA9IHJlZHVjZV9jaGFpbi5pbnZva2Uoe1wic3VtbWFyaWVzXCI6IFwiXFxuXCIuam9pbihmXCItIHtzfVwiIGZvciBzIGluIHN1bW1hcmllcyl9KVxuIiwKICAgICJkaXNwbGF5KE1hcmtkb3duKGZcIiMjIyBSRURVQ0UgKHN5bnRoZXNpcylcXG57c3ludGhlc2lzfVwiKSkiCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICIwNWU0NGVjOCIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgMTBlLiBIdW1hbi1pbi10aGUtbG9vcCBcdTIwMTQgYWdlbnQgcGF1c2VzIGZvciBhcHByb3ZhbCBiZWZvcmUgdGFraW5nIGFuIGFjdGlvblxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBIdW1hbk1lc3NhZ2UsIEFJTWVzc2FnZVxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLnRvb2xzIGltcG9ydCB0b29sXG4iLAogICAgIlxuIiwKICAgICJAdG9vbFxuIiwKICAgICJkZWYgc2VuZF9lbWFpbChyZWNpcGllbnQ6IHN0ciwgc3ViamVjdDogc3RyLCBib2R5OiBzdHIpIC0+IHN0cjpcbiIsCiAgICAiICAgIFwiXCJcIlNlbmQgYW4gZW1haWwuIFJlcXVpcmVzIGh1bWFuIGFwcHJvdmFsIGJlZm9yZSBzZW5kaW5nLlwiXCJcIlxuIiwKICAgICIgICAgcmV0dXJuIGZcIkVtYWlsIHNlbnQgdG8ge3JlY2lwaWVudH0gd2l0aCBzdWJqZWN0ICd7c3ViamVjdH0nXCJcbiIsCiAgICAiXG4iLAogICAgImRlZiBhZ2VudF93aXRoX2FwcHJvdmFsKHVzZXJfcmVxdWVzdDogc3RyKTpcbiIsCiAgICAiICAgIFwiXCJcIkFuIGFnZW50IGxvb3AgdGhhdCBwYXVzZXMgZm9yIGh1bWFuIGFwcHJvdmFsIGJlZm9yZSBjYWxsaW5nIGRhbmdlcm91cyB0b29scy5cIlwiXCJcbiIsCiAgICAiICAgIEFQUFJPVkFMX1JFUVVJUkVEID0ge1wic2VuZF9lbWFpbFwifVxuIiwKICAgICJcbiIsCiAgICAiICAgIGxsbV90b29scyA9IGxsbS5iaW5kX3Rvb2xzKFtzZW5kX2VtYWlsXSlcbiIsCiAgICAiICAgIG1lc3NhZ2VzID0gW0h1bWFuTWVzc2FnZShjb250ZW50PXVzZXJfcmVxdWVzdCldXG4iLAogICAgIlxuIiwKICAgICIgICAgZm9yIHN0ZXAgaW4gcmFuZ2UoNSk6XG4iLAogICAgIiAgICAgICAgcmVzcG9uc2UgPSBsbG1fdG9vbHMuaW52b2tlKG1lc3NhZ2VzKVxuIiwKICAgICIgICAgICAgIG1lc3NhZ2VzLmFwcGVuZChyZXNwb25zZSlcbiIsCiAgICAiXG4iLAogICAgIiAgICAgICAgaWYgbm90IHJlc3BvbnNlLnRvb2xfY2FsbHM6XG4iLAogICAgIiAgICAgICAgICAgIHByaW50KGZcIlxcbkFnZW50OiB7cmVzcG9uc2UuY29udGVudH1cIilcbiIsCiAgICAiICAgICAgICAgICAgYnJlYWtcbiIsCiAgICAiXG4iLAogICAgIiAgICAgICAgZm9yIHRjIGluIHJlc3BvbnNlLnRvb2xfY2FsbHM6XG4iLAogICAgIiAgICAgICAgICAgIHByaW50KGZcIlxcbkFnZW50IHdhbnRzIHRvIGNhbGw6IHt0Y1snbmFtZSddfSh7dGNbJ2FyZ3MnXX0pXCIpXG4iLAogICAgIlxuIiwKICAgICIgICAgICAgICAgICBpZiB0Y1tcIm5hbWVcIl0gaW4gQVBQUk9WQUxfUkVRVUlSRUQ6XG4iLAogICAgIiAgICAgICAgICAgICAgICBhcHByb3ZhbCA9IGlucHV0KFwiQXBwcm92ZT8gKHllcy9ubyk6IFwiKS5zdHJpcCgpLmxvd2VyKClcbiIsCiAgICAiICAgICAgICAgICAgICAgIGlmIGFwcHJvdmFsICE9IFwieWVzXCI6XG4iLAogICAgIiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gXCJBY3Rpb24gY2FuY2VsbGVkIGJ5IHVzZXIuXCJcbiIsCiAgICAiICAgICAgICAgICAgICAgIGVsc2U6XG4iLAogICAgIiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gc2VuZF9lbWFpbC5pbnZva2UodGNbXCJhcmdzXCJdKVxuIiwKICAgICIgICAgICAgICAgICBlbHNlOlxuIiwKICAgICIgICAgICAgICAgICAgICAgcmVzdWx0ID0gc2VuZF9lbWFpbC5pbnZva2UodGNbXCJhcmdzXCJdKVxuIiwKICAgICJcbiIsCiAgICAiICAgICAgICAgICAgZnJvbSBsYW5nY2hhaW5fY29yZS5tZXNzYWdlcyBpbXBvcnQgVG9vbE1lc3NhZ2VcbiIsCiAgICAiICAgICAgICAgICAgbWVzc2FnZXMuYXBwZW5kKFRvb2xNZXNzYWdlKGNvbnRlbnQ9cmVzdWx0LCB0b29sX2NhbGxfaWQ9dGNbXCJpZFwiXSkpXG4iLAogICAgIlxuIiwKICAgICJhZ2VudF93aXRoX2FwcHJvdmFsKFwiUGxlYXNlIGRyYWZ0IGFuZCBzZW5kIGFuIGVtYWlsIHRvIGFsaWNlQGV4YW1wbGUuY29tIGFib3V0IG91ciBtZWV0aW5nIG5leHQgTW9uZGF5IGF0IDEwYW0uXCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAibWFya2Rvd24iLAogICAiaWQiOiAiMWFkMmFiMmYiLAogICAibWV0YWRhdGEiOiB7fSwKICAgInNvdXJjZSI6IFsKICAgICItLS1cbiIsCiAgICAiIyMgU2VjdGlvbiAxMSBcdTIwMTQgUHV0dGluZyBJdCBBbGwgVG9nZXRoZXI6IE1pbmkgQWdlbnRpYyBBcHBcbiIsCiAgICAiXG4iLAogICAgIkEgY29tcGxldGUgbWluaS1hcHBsaWNhdGlvbiBjb21iaW5pbmc6ICoqUkFHICsgVG9vbHMgKyBNZW1vcnkgKyBSZWZsZWN0aW9uKipcbiIsCiAgICAiXG4iLAogICAgIlRoaXMgaXMgYSAqKlJlc2VhcmNoIEFzc2lzdGFudCoqIHRoYXQ6XG4iLAogICAgIjEuIFJldHJpZXZlcyByZWxldmFudCBrbm93bGVkZ2UgZnJvbSBhIHZlY3RvciBzdG9yZSAoUkFHKVxuIiwKICAgICIyLiBDYW4gZG8gY2FsY3VsYXRpb25zXG4iLAogICAgIjMuIFJlbWVtYmVycyB0aGUgY29udmVyc2F0aW9uIChNZW1vcnkpXG4iLAogICAgIjQuIFJlZmxlY3RzIGFuZCByZWZpbmVzIGFuc3dlcnMgYmVmb3JlIHJlc3BvbmRpbmciCiAgIF0KICB9LAogIHsKICAgImNlbGxfdHlwZSI6ICJjb2RlIiwKICAgImV4ZWN1dGlvbl9jb3VudCI6IG51bGwsCiAgICJpZCI6ICI1ZjNlZDk0MiIsCiAgICJtZXRhZGF0YSI6IHt9LAogICAib3V0cHV0cyI6IFtdLAogICAic291cmNlIjogWwogICAgIiMgMTEuIE1pbmkgQWdlbnRpYyBSZXNlYXJjaCBBc3Npc3RhbnQgXHUyMDE0IExhbmdHcmFwaCBtZW1vcnkgKyB0b29scyArIHJlZmxlY3Rpb25cbiIsCiAgICAiZnJvbSBJUHl0aG9uLmRpc3BsYXkgaW1wb3J0IGRpc3BsYXksIE1hcmtkb3duXG4iLAogICAgImZyb20gbGFuZ2dyYXBoLmNoZWNrcG9pbnQubWVtb3J5IGltcG9ydCBNZW1vcnlTYXZlclxuIiwKICAgICJmcm9tIGxhbmdncmFwaC5ncmFwaCBpbXBvcnQgU1RBUlQsIE1lc3NhZ2VzU3RhdGUsIFN0YXRlR3JhcGhcbiIsCiAgICAiZnJvbSBsYW5nZ3JhcGgucHJlYnVpbHQgaW1wb3J0IFRvb2xOb2RlLCB0b29sc19jb25kaXRpb25cbiIsCiAgICAiZnJvbSBsYW5nY2hhaW5fY29yZS50b29scyBpbXBvcnQgdG9vbFxuIiwKICAgICJmcm9tIGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzIGltcG9ydCBIdW1hbk1lc3NhZ2UsIFN5c3RlbU1lc3NhZ2VcbiIsCiAgICAiaW1wb3J0IG1hdGhcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBrbm93bGVkZ2VfYmFzZV9zZWFyY2gocXVlcnk6IHN0cikgLT4gc3RyOlxuIiwKICAgICIgICAgXCJcIlwiU2VhcmNoIHRoZSBwcm9ncmFtbWluZyBsYW5ndWFnZXMga25vd2xlZGdlIGJhc2UgZm9yIGZhY3R1YWwgaW5mb3JtYXRpb24uXCJcIlwiXG4iLAogICAgIiAgICByZXN1bHRzID0gdmVjdG9yc3RvcmUuc2ltaWxhcml0eV9zZWFyY2gocXVlcnksIGs9MylcbiIsCiAgICAiICAgIGlmIG5vdCByZXN1bHRzOlxuIiwKICAgICIgICAgICAgIHJldHVybiBcIk5vIHJlbGV2YW50IGluZm9ybWF0aW9uIGZvdW5kIGluIHRoZSBrbm93bGVkZ2UgYmFzZS5cIlxuIiwKICAgICIgICAgcmV0dXJuIFwiXFxuXCIuam9pbihmXCJbe3IubWV0YWRhdGFbJ3NvdXJjZSddfV0ge3IucGFnZV9jb250ZW50fVwiIGZvciByIGluIHJlc3VsdHMpXG4iLAogICAgIlxuIiwKICAgICJAdG9vbFxuIiwKICAgICJkZWYgY2FsY3VsYXRvcihleHByZXNzaW9uOiBzdHIpIC0+IHN0cjpcbiIsCiAgICAiICAgIFwiXCJcIkV2YWx1YXRlIGEgbWF0aCBleHByZXNzaW9uIGxpa2UgJzIgKiogMTAnIG9yICdtYXRoLnNxcnQoMTQ0KScuXCJcIlwiXG4iLAogICAgIiAgICB0cnk6XG4iLAogICAgIiAgICAgICAgcmV0dXJuIHN0cihldmFsKGV4cHJlc3Npb24sIHtcIl9fYnVpbHRpbnNfX1wiOiB7fX0sIHtcIm1hdGhcIjogbWF0aH0pKVxuIiwKICAgICIgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOlxuIiwKICAgICIgICAgICAgIHJldHVybiBmXCJFcnJvcjoge2V9XCJcbiIsCiAgICAiXG4iLAogICAgIkB0b29sXG4iLAogICAgImRlZiBzZWxmX3JlZmxlY3QoZHJhZnRfYW5zd2VyOiBzdHIpIC0+IHN0cjpcbiIsCiAgICAiICAgIFwiXCJcIkNyaXRpY2FsbHkgZXZhbHVhdGUgYSBkcmFmdCBhbnN3ZXIgYW5kIHN1Z2dlc3QgaW1wcm92ZW1lbnRzLlwiXCJcIlxuIiwKICAgICIgICAgcmVzcG9uc2UgPSBsbG0uaW52b2tlKFtcbiIsCiAgICAiICAgICAgICBTeXN0ZW1NZXNzYWdlKGNvbnRlbnQ9XCJZb3UgYXJlIGEgY3JpdGljYWwgcmV2aWV3ZXIuIEV2YWx1YXRlIGZvciBhY2N1cmFjeSwgY29tcGxldGVuZXNzLCBhbmQgY2xhcml0eS4gU3VnZ2VzdCAyLTMgaW1wcm92ZW1lbnRzLlwiKSxcbiIsCiAgICAiICAgICAgICBIdW1hbk1lc3NhZ2UoY29udGVudD1kcmFmdF9hbnN3ZXIpXG4iLAogICAgIiAgICBdKVxuIiwKICAgICIgICAgcmV0dXJuIHJlc3BvbnNlLmNvbnRlbnRcbiIsCiAgICAiXG4iLAogICAgImFzc2lzdGFudF90b29scyA9IFtrbm93bGVkZ2VfYmFzZV9zZWFyY2gsIGNhbGN1bGF0b3IsIHNlbGZfcmVmbGVjdF1cbiIsCiAgICAibGxtX3dpdGhfdG9vbHMgID0gbGxtLmJpbmRfdG9vbHMoYXNzaXN0YW50X3Rvb2xzKVxuIiwKICAgICJcbiIsCiAgICAiU1lTVEVNID0gU3lzdGVtTWVzc2FnZShjb250ZW50PVwiXCJcIllvdSBhcmUgYW4gaW50ZWxsaWdlbnQgcmVzZWFyY2ggYXNzaXN0YW50IHdpdGggYWNjZXNzIHRvOlxuIiwKICAgICIxLiBrbm93bGVkZ2VfYmFzZV9zZWFyY2ggXHUyMDE0IGxvb2sgdXAgZmFjdHVhbCBpbmZvcm1hdGlvblxuIiwKICAgICIyLiBjYWxjdWxhdG9yIFx1MjAxNCBudW1lcmljYWwgY29tcHV0YXRpb25cbiIsCiAgICAiMy4gc2VsZl9yZWZsZWN0IFx1MjAxNCBjcml0aXF1ZSBhbmQgaW1wcm92ZSB5b3VyIG93biBkcmFmdCBhbnN3ZXJzIGJlZm9yZSBmaW5hbGlzaW5nXG4iLAogICAgIlxuIiwKICAgICJXb3JrZmxvdzogc2VhcmNoIFx1MjE5MiBkcmFmdCBcdTIxOTIgcmVmbGVjdCBcdTIxOTIgZmluYWwgYW5zd2VyLlxuIiwKICAgICJBbHdheXMgZ3JvdW5kIGFuc3dlcnMgaW4gcmV0cmlldmVkIGZhY3RzIHdoZW4gcG9zc2libGUuXCJcIlwiKVxuIiwKICAgICJcbiIsCiAgICAiZGVmIGFnZW50X25vZGUoc3RhdGU6IE1lc3NhZ2VzU3RhdGUpOlxuIiwKICAgICIgICAgcmVzcG9uc2UgPSBsbG1fd2l0aF90b29scy5pbnZva2UoW1NZU1RFTV0gKyBzdGF0ZVtcIm1lc3NhZ2VzXCJdKVxuIiwKICAgICIgICAgcmV0dXJuIHtcIm1lc3NhZ2VzXCI6IFtyZXNwb25zZV19XG4iLAogICAgIlxuIiwKICAgICJidWlsZGVyID0gU3RhdGVHcmFwaChNZXNzYWdlc1N0YXRlKVxuIiwKICAgICJidWlsZGVyLmFkZF9ub2RlKFwiYWdlbnRcIiwgIGFnZW50X25vZGUpXG4iLAogICAgImJ1aWxkZXIuYWRkX25vZGUoXCJ0b29sc1wiLCAgVG9vbE5vZGUoYXNzaXN0YW50X3Rvb2xzKSlcbiIsCiAgICAiYnVpbGRlci5hZGRfZWRnZShTVEFSVCwgXCJhZ2VudFwiKVxuIiwKICAgICJidWlsZGVyLmFkZF9jb25kaXRpb25hbF9lZGdlcyhcImFnZW50XCIsIHRvb2xzX2NvbmRpdGlvbikgICAjIHJvdXRlcyB0byBcInRvb2xzXCIgb3IgRU5EXG4iLAogICAgImJ1aWxkZXIuYWRkX2VkZ2UoXCJ0b29sc1wiLCBcImFnZW50XCIpICAgICAgICAgICAgICAgICAgICAgICAgIyBhZnRlciB0b29scywgYmFjayB0byBhZ2VudFxuIiwKICAgICJcbiIsCiAgICAiZ3JhcGggPSBidWlsZGVyLmNvbXBpbGUoY2hlY2twb2ludGVyPU1lbW9yeVNhdmVyKCkpXG4iLAogICAgIlxuIiwKICAgICJjZmcgPSB7XCJjb25maWd1cmFibGVcIjoge1widGhyZWFkX2lkXCI6IFwicmVzZWFyY2hfMVwifX1cbiIsCiAgICAiXG4iLAogICAgImRlZiBhc2socXVlc3Rpb24pOlxuIiwKICAgICIgICAgZGlzcGxheShNYXJrZG93bihmXCItLS1cXG4qKlVzZXI6Kioge3F1ZXN0aW9ufVwiKSlcbiIsCiAgICAiICAgIHJlc3VsdCA9IGdyYXBoLmludm9rZSh7XCJtZXNzYWdlc1wiOiBbSHVtYW5NZXNzYWdlKGNvbnRlbnQ9cXVlc3Rpb24pXX0sIGNvbmZpZz1jZmcpXG4iLAogICAgIiAgICBhbnN3ZXIgPSByZXN1bHRbXCJtZXNzYWdlc1wiXVstMV0uY29udGVudFxuIiwKICAgICIgICAgZGlzcGxheShNYXJrZG93bihmXCIqKkFzc2lzdGFudDoqKiB7YW5zd2VyfVwiKSlcbiIsCiAgICAiICAgIHJldHVybiBhbnN3ZXJcbiIsCiAgICAiXG4iLAogICAgImFzayhcIldoYXQgaXMgUnVzdCBhbmQgd2h5IGlzIGl0IHNwZWNpYWw/XCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiYWQyNjA1YTYiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIEZvbGxvdy11cCBcdTIwMTQgdGVzdHMgbWVtb3J5XG4iLAogICAgImFzayhcIldoaWNoIGxhbmd1YWdlIHdlIGRpc2N1c3NlZCBpcyBiZXN0IGZvciB3ZWIgZnJvbnRlbmQ/XCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAiY29kZSIsCiAgICJleGVjdXRpb25fY291bnQiOiBudWxsLAogICAiaWQiOiAiMGIzZTAyZTUiLAogICAibWV0YWRhdGEiOiB7fSwKICAgIm91dHB1dHMiOiBbXSwKICAgInNvdXJjZSI6IFsKICAgICIjIE1hdGggKyBrbm93bGVkZ2UgY29tYmluZWRcbiIsCiAgICAiYXNrKFwiSWYgUHl0aG9uIHdhcyByZWxlYXNlZCBpbiAxOTkxIGFuZCBHbyBpbiAyMDA5LCBob3cgbWFueSB5ZWFycyBhcGFydCB3ZXJlIHRoZXkgcmVsZWFzZWQ/XCIpIgogICBdCiAgfSwKICB7CiAgICJjZWxsX3R5cGUiOiAibWFya2Rvd24iLAogICAiaWQiOiAiNzRmYjdmODYiLAogICAibWV0YWRhdGEiOiB7fSwKICAgInNvdXJjZSI6IFsKICAgICItLS1cbiIsCiAgICAiIyMgU3VtbWFyeSAmIE5leHQgU3RlcHNcbiIsCiAgICAiXG4iLAogICAgIiMjIyBXaGF0IHlvdSBjb3ZlcmVkOlxuIiwKICAgICJcbiIsCiAgICAifCBDb25jZXB0IHwgS2V5IFRha2Vhd2F5IHxcbiIsCiAgICAifC0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfFxuIiwKICAgICJ8IExMTSBCYXNpY3MgfCBUb2tlbnMsIHRlbXBlcmF0dXJlLCBzdHJlYW1pbmcsIHJvbGVzIHxcbiIsCiAgICAifCBQcm9tcHQgRW5naW5lZXJpbmcgfCBUZW1wbGF0ZXMsIGZldy1zaG90LCBDb1QsIHN0cnVjdHVyZWQgb3V0cHV0IHxcbiIsCiAgICAifCBDaGFpbnMgKExDRUwpIHwgQ29tcG9zZSBjb21wb25lbnRzIHdpdGggYHxgLCBwYXJhbGxlbC9zZXF1ZW50aWFsIHxcbiIsCiAgICAifCBNZW1vcnkgfCBNYW51YWwgaGlzdG9yeTsgTGFuZ0dyYXBoIGBNZW1vcnlTYXZlcmAgKyBgdGhyZWFkX2lkYCB8XG4iLAogICAgInwgUkFHIHwgRW1iZWQgXHUyMTkyIHN0b3JlIFx1MjE5MiByZXRyaWV2ZSBcdTIxOTIgYXVnbWVudCBcdTIxOTIgZ2VuZXJhdGUgfFxuIiwKICAgICJ8IFRvb2xzIHwgRGVmaW5lIHdpdGggYEB0b29sYCwgYmluZCB0byBMTE0sIGhhbmRsZSB0b29sIGNhbGxzIHxcbiIsCiAgICAifCBBZ2VudHMgfCBSZUFjdCBsb29wLCB0b29sLWNhbGxpbmcgYWdlbnQsIFJBRyBhZ2VudCB8XG4iLAogICAgInwgTXVsdGktQWdlbnQgfCBPcmNoZXN0cmF0b3IgKyBzcGVjaWFsaXN0cywgcGFyYWxsZWwgYWdlbnRzIHxcbiIsCiAgICAifCBBZ2VudGljIFBhdHRlcm5zIHwgUGxhbm5pbmcsIHJlZmxlY3Rpb24sIGV2YWwtb3B0aW1pemVyLCBtYXAtcmVkdWNlLCBISVRMIHxcbiIsCiAgICAifCBMYW5nR3JhcGggfCBgU3RhdGVHcmFwaGAgKyBgTWVtb3J5U2F2ZXJgIGZvciBzdGF0ZWZ1bCBhZ2VudGljIHdvcmtmbG93cyB8XG4iLAogICAgIlxuIiwKICAgICIjIyMgSW50ZXJtZWRpYXRlIG5leHQgc3RlcHM6XG4iLAogICAgIi0gKipMYW5nR3JhcGggYWR2YW5jZWQqKiBcdTIwMTQgYnJhbmNoaW5nLCBodW1hbi1pbi10aGUtbG9vcCBpbnRlcnJ1cHRzLCBzdWJncmFwaHMsIHN0cmVhbWluZyBzdGF0ZVxuIiwKICAgICItICoqRmluZS10dW5pbmcqKiBcdTIwMTQgYWRhcHQgYSBiYXNlIG1vZGVsIHRvIHlvdXIgZG9tYWluXG4iLAogICAgIi0gKipFdmFscyoqIFx1MjAxNCBtZWFzdXJlIGFnZW50IHF1YWxpdHkgd2l0aCBMYW5nU21pdGggb3IgUkFHQVNcbiIsCiAgICAiLSAqKlByb2R1Y3Rpb24gcGF0dGVybnMqKiBcdTIwMTQgY2FjaGluZywgb2JzZXJ2YWJpbGl0eSwgcmF0ZSBsaW1pdGluZywgY29zdCB0cmFja2luZ1xuIiwKICAgICItICoqQ3VzdG9tIHJldHJpZXZlcnMqKiBcdTIwMTQgQk0yNSBoeWJyaWQgc2VhcmNoLCByZXJhbmtpbmcgd2l0aCBjcm9zcy1lbmNvZGVyc1xuIiwKICAgICItICoqTXVsdGltb2RhbCoqIFx1MjAxNCB2aXNpb24tZW5hYmxlZCBtb2RlbHMgKGxsYXZhIHZpYSBPbGxhbWEsIEdlbWluaSBWaXNpb24sIEdQVC00bylcbiIsCiAgICAiXG4iLAogICAgIiMjIyBVc2VmdWwgcmVmZXJlbmNlczpcbiIsCiAgICAiLSBbTGFuZ0NoYWluIGRvY3NdKGh0dHBzOi8vcHl0aG9uLmxhbmdjaGFpbi5jb20vKVxuIiwKICAgICItIFtMYW5nR3JhcGggZG9jc10oaHR0cHM6Ly9sYW5nY2hhaW4tYWkuZ2l0aHViLmlvL2xhbmdncmFwaC8pXG4iLAogICAgIi0gW09sbGFtYSBtb2RlbCBsaWJyYXJ5XShodHRwczovL29sbGFtYS5jb20vbGlicmFyeSlcbiIsCiAgICAiLSBbUHJvbXB0IEVuZ2luZWVyaW5nIEd1aWRlXShodHRwczovL3d3dy5wcm9tcHRpbmdndWlkZS5haS8pIgogICBdCiAgfQogXSwKICJtZXRhZGF0YSI6IHsKICAia2VybmVsc3BlYyI6IHsKICAgImRpc3BsYXlfbmFtZSI6ICJHZW5BSSAodmVudikiLAogICAibGFuZ3VhZ2UiOiAicHl0aG9uIiwKICAgIm5hbWUiOiAiZ2VuYWktdmVudiIKICB9LAogICJsYW5ndWFnZV9pbmZvIjogewogICAiY29kZW1pcnJvcl9tb2RlIjogewogICAgIm5hbWUiOiAiaXB5dGhvbiIsCiAgICAidmVyc2lvbiI6IDMKICAgfSwKICAgImZpbGVfZXh0ZW5zaW9uIjogIi5weSIsCiAgICJtaW1ldHlwZSI6ICJ0ZXh0L3gtcHl0aG9uIiwKICAgIm5hbWUiOiAicHl0aG9uIiwKICAgIm5iY29udmVydF9leHBvcnRlciI6ICJweXRob24iLAogICAicHlnbWVudHNfbGV4ZXIiOiAiaXB5dGhvbjMiLAogICAidmVyc2lvbiI6ICIzLjEzLjciCiAgfQogfSwKICJuYmZvcm1hdCI6IDQsCiAibmJmb3JtYXRfbWlub3IiOiA1Cn0=&quot;&gt;⬇ Download .ipynb&lt;/a&gt;
  &lt;/div&gt;

&lt;h1&gt;GenAI, Agents &amp;amp; Agentic AI — Complete Learning Notebook&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Beginner → Intermediate&lt;br /&gt;
&lt;strong&gt;Providers supported:&lt;/strong&gt; Ollama (local) · OpenAI · Google Gemini · DeepSeek  &lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Learning Path&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Concepts Covered&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Setup &amp;amp; Provider Config&lt;/td&gt;
&lt;td&gt;Install libs, configure keys, pick a provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;LLM Basics&lt;/td&gt;
&lt;td&gt;Tokens, temperature, inference, completion vs chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Prompt Engineering&lt;/td&gt;
&lt;td&gt;Zero-shot, few-shot, CoT, system prompts, templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Chains&lt;/td&gt;
&lt;td&gt;Sequential chains, prompt → LLM → parser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;Conversation history, buffer, summary memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;RAG (Retrieval-Augmented Generation)&lt;/td&gt;
&lt;td&gt;Embeddings, vector stores, retrieval, Q&amp;amp;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Tools &amp;amp; Function Calling&lt;/td&gt;
&lt;td&gt;Defining tools, structured output, tool use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Agents&lt;/td&gt;
&lt;td&gt;ReAct agent, tool selection, reasoning loop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Multi-Agent Systems&lt;/td&gt;
&lt;td&gt;Orchestrator/worker, handoffs, parallelism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Agentic Patterns&lt;/td&gt;
&lt;td&gt;Planning, reflection, self-critique, loops&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Run cells top-to-bottom. Set your provider once in Section 1 and everything else adapts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Section 1 — Setup &amp;amp; Provider Configuration&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Install all required packages
# Re-run this cell any time you start a fresh environment
# Remove -v if you want quiet output; add -q for silent mode
%pip install -v \
    langchain \
    langchain-ollama \
    langchain-openai \
    langchain-google-genai \
    langchain-chroma \
    langchain-core \
    langgraph \
    chromadb \
    ollama \
    google-generativeai \
    openai \
    tiktoken \
    faiss-cpu \
    sentence-transformers \
    pypdf \
    httpx \
    ipywidgets
print(&quot;All packages installed.&quot;)

from IPython.display import display, Markdown&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# ============================================================
# CONFIGURE YOUR PROVIDER HERE — change PROVIDER and fill in
# the relevant key/model. Everything else in the notebook
# uses `llm` and `embeddings` defined below.
# ============================================================

import os

# Choose: &quot;ollama&quot; | &quot;openai&quot; | &quot;gemini&quot; | &quot;deepseek&quot;
PROVIDER = &quot;ollama&quot;

# --- Ollama (runs locally, no key needed) ---
OLLAMA_BASE_URL  = &quot;http://localhost:11434&quot;
OLLAMA_MODEL     = &quot;llama3.2:latest&quot;   # change to any model you have pulled
OLLAMA_EMBED     = &quot;nomic-embed-text:latest&quot;

# --- OpenAI ---
OPENAI_API_KEY   = os.getenv(&quot;OPENAI_API_KEY&quot;, &quot;sk-...&quot;)
OPENAI_MODEL     = &quot;gpt-4o-mini&quot;

# --- Google Gemini ---
GOOGLE_API_KEY   = os.getenv(&quot;GOOGLE_API_KEY&quot;, &quot;...&quot;)
GEMINI_MODEL     = &quot;gemini-1.5-flash&quot;

# --- DeepSeek (OpenAI-compatible endpoint) ---
DEEPSEEK_API_KEY = os.getenv(&quot;DEEPSEEK_API_KEY&quot;, &quot;sk-...&quot;)
DEEPSEEK_MODEL   = &quot;deepseek-chat&quot;
DEEPSEEK_BASE_URL = &quot;https://api.deepseek.com/v1&quot;

print(f&quot;Provider set to: {PROVIDER}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Build the shared `llm` and `embeddings` objects used throughout
from langchain_core.language_models.chat_models import BaseChatModel

if PROVIDER == &quot;ollama&quot;:
    from langchain_ollama import ChatOllama, OllamaEmbeddings
    llm = ChatOllama(model=OLLAMA_MODEL, base_url=OLLAMA_BASE_URL, temperature=0.7)
    embeddings = OllamaEmbeddings(model=OLLAMA_EMBED, base_url=OLLAMA_BASE_URL)

elif PROVIDER == &quot;openai&quot;:
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    llm = ChatOpenAI(model=OPENAI_MODEL, api_key=OPENAI_API_KEY, temperature=0.7)
    embeddings = OpenAIEmbeddings(api_key=OPENAI_API_KEY)

elif PROVIDER == &quot;gemini&quot;:
    from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
    llm = ChatGoogleGenerativeAI(model=GEMINI_MODEL, google_api_key=GOOGLE_API_KEY, temperature=0.7)
    embeddings = GoogleGenerativeAIEmbeddings(model=&quot;models/embedding-001&quot;, google_api_key=GOOGLE_API_KEY)

elif PROVIDER == &quot;deepseek&quot;:
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    llm = ChatOpenAI(
        model=DEEPSEEK_MODEL,
        api_key=DEEPSEEK_API_KEY,
        base_url=DEEPSEEK_BASE_URL,
        temperature=0.7
    )
    # DeepSeek does not expose embeddings; fall back to Ollama local embeddings
    from langchain_ollama import OllamaEmbeddings
    embeddings = OllamaEmbeddings(model=OLLAMA_EMBED, base_url=OLLAMA_BASE_URL)

else:
    raise ValueError(f&quot;Unknown provider: {PROVIDER}&quot;)

print(f&quot;LLM ready: {llm}&quot;)
print(f&quot;Embeddings ready: {embeddings}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 2 — LLM Basics&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Token&lt;/strong&gt;: smallest unit of text the model processes (~0.75 words)
- &lt;strong&gt;Temperature&lt;/strong&gt;: controls randomness (0 = deterministic, 1+ = creative)
- &lt;strong&gt;Context window&lt;/strong&gt;: max tokens the model can see at once
- &lt;strong&gt;Completion vs Chat&lt;/strong&gt;: older models do text completion; modern models use a chat (message) format
- &lt;strong&gt;System / Human / AI messages&lt;/strong&gt;: the three roles in a conversation&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 2a. Simple single-turn call
from IPython.display import display, Markdown
from langchain_core.messages import HumanMessage

response = llm.invoke([HumanMessage(content=&quot;What is a large language model? Explain in 3 sentences.&quot;)])
display(Markdown(response.content))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 2b. System + Human messages
from IPython.display import display, Markdown
from langchain_core.messages import SystemMessage, HumanMessage

messages = [
    SystemMessage(content=&quot;You are a concise technical tutor. Always answer in bullet points.&quot;),
    HumanMessage(content=&quot;What are tokens in the context of LLMs?&quot;)
]
response = llm.invoke(messages)
display(Markdown(response.content))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 2c. Temperature effect — compare deterministic vs creative output
from IPython.display import display, Markdown
from langchain_core.messages import HumanMessage

if PROVIDER == &quot;ollama&quot;:
    from langchain_ollama import ChatOllama
    llm_cold = ChatOllama(model=OLLAMA_MODEL, base_url=OLLAMA_BASE_URL, temperature=0.0)
    llm_hot  = ChatOllama(model=OLLAMA_MODEL, base_url=OLLAMA_BASE_URL, temperature=1.2)
elif PROVIDER == &quot;openai&quot;:
    from langchain_openai import ChatOpenAI
    llm_cold = ChatOpenAI(model=OPENAI_MODEL, api_key=OPENAI_API_KEY, temperature=0.0)
    llm_hot  = ChatOpenAI(model=OPENAI_MODEL, api_key=OPENAI_API_KEY, temperature=1.2)
elif PROVIDER == &quot;gemini&quot;:
    from langchain_google_genai import ChatGoogleGenerativeAI
    llm_cold = ChatGoogleGenerativeAI(model=GEMINI_MODEL, google_api_key=GOOGLE_API_KEY, temperature=0.0)
    llm_hot  = ChatGoogleGenerativeAI(model=GEMINI_MODEL, google_api_key=GOOGLE_API_KEY, temperature=1.0)
else:
    llm_cold = llm_hot = llm

question = [HumanMessage(content=&quot;Give me one creative name for an AI assistant.&quot;)]

cold_names = [llm_cold.invoke(question).content.strip() for _ in range(3)]
hot_names  = [llm_hot.invoke(question).content.strip()  for _ in range(3)]

display(Markdown(&quot;### Cold (deterministic, temperature=0)\n&quot; + &quot;\n&quot;.join(f&quot;- {n}&quot; for n in cold_names)))
display(Markdown(&quot;### Hot (creative, temperature=1.2)\n&quot;     + &quot;\n&quot;.join(f&quot;- {n}&quot; for n in hot_names)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 2d. Streaming output — see tokens arrive in real-time
from IPython.display import display, Markdown
from langchain_core.messages import HumanMessage

chunks = []
for chunk in llm.stream([HumanMessage(content=&quot;Tell me a very short joke about AI.&quot;)]):
    print(chunk.content, end=&quot;&quot;, flush=True)
    chunks.append(chunk.content)
print()
display(Markdown(&quot;---\n**Rendered:**\n\n&quot; + &quot;&quot;.join(chunks)))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 3 — Prompt Engineering&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Zero-shot&lt;/strong&gt;: ask without examples
- &lt;strong&gt;Few-shot&lt;/strong&gt;: give examples in the prompt to guide output format
- &lt;strong&gt;Chain-of-Thought (CoT)&lt;/strong&gt;: ask the model to reason step-by-step before answering
- &lt;strong&gt;Prompt templates&lt;/strong&gt;: reusable prompts with variables
- &lt;strong&gt;Output parsers&lt;/strong&gt;: extract structured data from model responses&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 3a. PromptTemplate — reusable prompt with variables
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate

template = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;You are an expert in {domain}.&quot;),
    (&quot;human&quot;, &quot;Explain {concept} to a {audience}.&quot;)
])

chain = template | llm

result = chain.invoke({
    &quot;domain&quot;: &quot;machine learning&quot;,
    &quot;concept&quot;: &quot;gradient descent&quot;,
    &quot;audience&quot;: &quot;10-year-old&quot;
})
display(Markdown(result.content))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 3b. Few-shot prompting — guide output format with examples
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate

few_shot_template = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;You classify customer feedback as Positive, Negative, or Neutral. Reply with only the label.&quot;),
    (&quot;human&quot;, &quot;The product broke after one day.&quot;),
    (&quot;ai&quot;, &quot;Negative&quot;),
    (&quot;human&quot;, &quot;It&#39;s okay, nothing special.&quot;),
    (&quot;ai&quot;, &quot;Neutral&quot;),
    (&quot;human&quot;, &quot;Absolutely love it, best purchase ever!&quot;),
    (&quot;ai&quot;, &quot;Positive&quot;),
    (&quot;human&quot;, &quot;{feedback}&quot;)
])

chain = few_shot_template | llm

tests = [
    &quot;Delivery was late but the item was fine.&quot;,
    &quot;Terrible customer service, would not recommend.&quot;,
    &quot;Exceeded my expectations!&quot;
]

rows = [&quot;| Feedback | Sentiment |&quot;, &quot;|----------|-----------|&quot;]
for t in tests:
    label = chain.invoke({&quot;feedback&quot;: t}).content.strip()
    rows.append(f&quot;| {t} | **{label}** |&quot;)

display(Markdown(&quot;\n&quot;.join(rows)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 3c. Chain-of-Thought (CoT) — ask to reason before answering
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate

cot_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;You are a careful reasoner. Think step-by-step before giving your final answer. Format: REASONING: ... ANSWER: ...&quot;),
    (&quot;human&quot;, &quot;{question}&quot;)
])

chain = cot_prompt | llm
result = chain.invoke({&quot;question&quot;: &quot;If I have 3 boxes with 4 apples each, and I give away 5 apples, how many do I have left?&quot;})
display(Markdown(result.content))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 3d. Structured output with JSON — output parser
from IPython.display import display, Markdown
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import json

json_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;&quot;&quot;You extract structured information. Always respond with valid JSON only.
Schema: {{&quot;name&quot;: string, &quot;country&quot;: string, &quot;founded_year&quot;: int, &quot;main_product&quot;: string}}&quot;&quot;&quot;),
    (&quot;human&quot;, &quot;Tell me about: {company}&quot;)
])

chain = json_prompt | llm | JsonOutputParser()

result = chain.invoke({&quot;company&quot;: &quot;Tesla&quot;})
display(Markdown(f&quot;```json\n{json.dumps(result, indent=2)}\n```&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 4 — Chains&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;LCEL (LangChain Expression Language)&lt;/strong&gt;: pipe &lt;code&gt;|&lt;/code&gt; operator to compose components
- &lt;strong&gt;Sequential chain&lt;/strong&gt;: output of one step feeds into the next
- &lt;strong&gt;Parallel chain&lt;/strong&gt;: run multiple LLM calls simultaneously
- &lt;strong&gt;Branching&lt;/strong&gt;: route to different chains based on content&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 4a. Simple LCEL chain: prompt → llm → string parser
from IPython.display import display, Markdown
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

summarize_chain = (
    ChatPromptTemplate.from_template(&quot;Summarize the following text in one sentence:\n\n{text}&quot;)
    | llm
    | StrOutputParser()
)

text = &quot;&quot;&quot;The James Webb Space Telescope (JWST) is a space telescope designed to conduct infrared
astronomy. Its high resolution and sensitivity allow it to view objects too old, distant, or faint
for the Hubble Space Telescope. It is the largest optical telescope in space.&quot;&quot;&quot;

result = summarize_chain.invoke({&quot;text&quot;: text})
display(Markdown(result))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 4b. Sequential chain — translate then explain
from IPython.display import display, Markdown
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

translate_prompt = ChatPromptTemplate.from_template(
    &quot;Translate the following text to French:\n{text}&quot;
)
explain_prompt = ChatPromptTemplate.from_template(
    &quot;Explain why this French sentence is grammatically correct:\n{translated}&quot;
)

parser = StrOutputParser()

full_chain = (
    translate_prompt | llm | parser
    | (lambda translated: {&quot;translated&quot;: translated})
    | explain_prompt | llm | parser
)

result = full_chain.invoke({&quot;text&quot;: &quot;The sun rises in the east.&quot;})
display(Markdown(result))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 4c. Parallel chains using RunnableParallel
from IPython.display import display, Markdown
from langchain_core.runnables import RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

pros_chain = ChatPromptTemplate.from_template(&quot;List 3 pros of {topic}&quot;) | llm | StrOutputParser()
cons_chain = ChatPromptTemplate.from_template(&quot;List 3 cons of {topic}&quot;) | llm | StrOutputParser()

parallel = RunnableParallel(pros=pros_chain, cons=cons_chain)

result = parallel.invoke({&quot;topic&quot;: &quot;working from home&quot;})
display(Markdown(f&quot;### Pros\n{result[&#39;pros&#39;]}\n\n### Cons\n{result[&#39;cons&#39;]}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 5 — Memory &amp;amp; Conversation History&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Stateless LLMs&lt;/strong&gt;: by default, each call is independent — no memory
- &lt;strong&gt;Conversation buffer&lt;/strong&gt;: store the full chat history and pass it each turn
- &lt;strong&gt;Summary memory&lt;/strong&gt;: summarize older turns to stay within context window
- &lt;strong&gt;LangGraph persistence&lt;/strong&gt;: the modern way to add memory — graph state is checkpointed per &lt;code&gt;thread_id&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 5a. Manual message history — see what &quot;memory&quot; means at the raw level
from IPython.display import display, Markdown
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

history = [SystemMessage(content=&quot;You are a helpful assistant. Remember details the user shares.&quot;)]

def chat(user_input):
    history.append(HumanMessage(content=user_input))
    response = llm.invoke(history)
    history.append(AIMessage(content=response.content))
    return response.content

display(Markdown(f&quot;**User:** Hi, my name is Alex and I love hiking.\n\n**AI:** {chat(&#39;Hi, my name is Alex and I love hiking.&#39;)}&quot;))
display(Markdown(f&quot;**User:** What do I love doing?\n\n**AI:** {chat(&#39;What do I love doing?&#39;)}&quot;))
display(Markdown(f&quot;**User:** What is my name?\n\n**AI:** {chat(&#39;What is my name?&#39;)}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 5b. LangGraph persistent memory — modern replacement for RunnableWithMessageHistory
from IPython.display import display, Markdown
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph
from langchain_core.messages import HumanMessage, SystemMessage

# Define a single node that calls the LLM with full message history
def call_llm(state: MessagesState):
    system = SystemMessage(content=&quot;You are a friendly assistant.&quot;)
    response = llm.invoke([system] + state[&quot;messages&quot;])
    return {&quot;messages&quot;: response}

# Build a minimal graph: START → llm node
builder = StateGraph(MessagesState)
builder.add_node(&quot;llm&quot;, call_llm)
builder.add_edge(START, &quot;llm&quot;)

# MemorySaver checkpoints the full message history per thread_id in-memory
graph = builder.compile(checkpointer=MemorySaver())

cfg = {&quot;configurable&quot;: {&quot;thread_id&quot;: &quot;user_1&quot;}}

def chat_lg(user_input):
    result = graph.invoke({&quot;messages&quot;: [HumanMessage(content=user_input)]}, config=cfg)
    return result[&quot;messages&quot;][-1].content

r1 = chat_lg(&quot;My favourite colour is blue.&quot;)
r2 = chat_lg(&quot;What is my favourite colour?&quot;)

display(Markdown(f&quot;**Turn 1:** My favourite colour is blue.\n\n**AI:** {r1}&quot;))
display(Markdown(f&quot;**Turn 2:** What is my favourite colour?\n\n**AI:** {r2}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 5c. Summary memory concept — summarise old turns to save tokens
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

old_conversation = &quot;&quot;&quot;
User: I&#39;m planning a trip to Japan in October.
AI: Great choice! October is beautiful in Japan — autumn foliage begins.
User: I want to visit Tokyo and Kyoto.
AI: Perfect itinerary. Tokyo for modern culture, Kyoto for temples and history.
User: I have 10 days total.
AI: Suggested split: 5 days Tokyo, 4 days Kyoto, 1 day Nara as a day trip.
&quot;&quot;&quot;

summarize = (
    ChatPromptTemplate.from_template(
        &quot;Summarize this conversation history into 2-3 bullet points for context:\n{history}&quot;
    ) | llm | StrOutputParser()
)

summary = summarize.invoke({&quot;history&quot;: old_conversation})
display(Markdown(f&quot;### Summary stored as context\n{summary}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 6 — RAG (Retrieval-Augmented Generation)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Embeddings&lt;/strong&gt;: numerical vector representations of text (similar texts → similar vectors)
- &lt;strong&gt;Vector store&lt;/strong&gt;: database for storing and searching embeddings (ChromaDB, FAISS)
- &lt;strong&gt;Semantic search&lt;/strong&gt;: find relevant text by meaning, not keyword match
- &lt;strong&gt;RAG pipeline&lt;/strong&gt;: Retrieve relevant docs → Augment prompt → Generate answer
- &lt;strong&gt;Why RAG?&lt;/strong&gt; Extends LLM knowledge with your own data without retraining&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 6a. Embeddings — visualise what they are
from IPython.display import display, Markdown
import numpy as np

sentences = [
    &quot;The cat sat on the mat.&quot;,
    &quot;A feline rested on the rug.&quot;,
    &quot;The stock market crashed today.&quot;,
]

vecs = embeddings.embed_documents(sentences)

def cosine(a, b):
    a, b = np.array(a), np.array(b)
    return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))

sim_1_2 = cosine(vecs[0], vecs[1])
sim_1_3 = cosine(vecs[0], vecs[2])

display(Markdown(f&quot;&quot;&quot;
**Embedding dimension:** {len(vecs[0])}

| Pair | Cosine Similarity |
|------|-------------------|
| cat / feline (similar) | `{sim_1_2:.4f}` |
| cat / stock market (unrelated) | `{sim_1_3:.4f}` |

&amp;gt; Higher score = more semantically similar
&quot;&quot;&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 6b. Build a vector store from sample documents
from langchain_chroma import Chroma
from langchain_core.documents import Document

docs = [
    Document(page_content=&quot;Python is a high-level, interpreted programming language known for readability.&quot;, metadata={&quot;source&quot;: &quot;python_wiki&quot;}),
    Document(page_content=&quot;Python supports multiple programming paradigms including procedural, object-oriented, and functional.&quot;, metadata={&quot;source&quot;: &quot;python_wiki&quot;}),
    Document(page_content=&quot;Rust is a systems programming language focused on safety, speed, and concurrency.&quot;, metadata={&quot;source&quot;: &quot;rust_wiki&quot;}),
    Document(page_content=&quot;Rust&#39;s borrow checker prevents memory bugs at compile time without a garbage collector.&quot;, metadata={&quot;source&quot;: &quot;rust_wiki&quot;}),
    Document(page_content=&quot;JavaScript is the primary language for web frontend development, running in browsers.&quot;, metadata={&quot;source&quot;: &quot;js_wiki&quot;}),
    Document(page_content=&quot;Node.js allows JavaScript to run on the server side, enabling full-stack JS development.&quot;, metadata={&quot;source&quot;: &quot;js_wiki&quot;}),
    Document(page_content=&quot;Go (Golang) is designed for simplicity and high-performance concurrent server applications.&quot;, metadata={&quot;source&quot;: &quot;go_wiki&quot;}),
]

vectorstore = Chroma.from_documents(docs, embedding=embeddings, collection_name=&quot;programming_langs&quot;)
print(f&quot;Vector store created with {vectorstore._collection.count()} documents.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 6c. Semantic search
from IPython.display import display, Markdown

query = &quot;What language prevents memory bugs at compile time?&quot;
results = vectorstore.similarity_search(query, k=2)

rows = [f&quot;**Query:** {query}\n&quot;, &quot;| # | Source | Content |&quot;, &quot;|---|--------|---------|&quot;]
for i, doc in enumerate(results):
    rows.append(f&quot;| {i+1} | `{doc.metadata[&#39;source&#39;]}` | {doc.page_content} |&quot;)

display(Markdown(&quot;\n&quot;.join(rows)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 6d. Full RAG pipeline — retrieval + generation
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

retriever = vectorstore.as_retriever(search_kwargs={&quot;k&quot;: 3})

def format_docs(docs):
    return &quot;\n\n&quot;.join(doc.page_content for doc in docs)

rag_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;&quot;&quot;You are a helpful assistant. Answer the question using ONLY the context provided.
If the answer is not in the context, say &#39;I don&#39;t know based on the provided information.&#39;

Context:
{context}&quot;&quot;&quot;),
    (&quot;human&quot;, &quot;{question}&quot;)
])

rag_chain = (
    {&quot;context&quot;: retriever | format_docs, &quot;question&quot;: RunnablePassthrough()}
    | rag_prompt
    | llm
    | StrOutputParser()
)

questions = [
    &quot;Which language is best for web frontend development?&quot;,
    &quot;What makes Rust special compared to other languages?&quot;,
    &quot;What is the capital of France?&quot;
]

for q in questions:
    answer = rag_chain.invoke(q)
    display(Markdown(f&quot;**Q:** {q}\n\n**A:** {answer}\n\n---&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 6e. Text splitter — handling large documents
from langchain_text_splitters import RecursiveCharacterTextSplitter

long_text = &quot;&quot;&quot;Artificial intelligence (AI) is intelligence demonstrated by machines, as opposed to the natural
intelligence displayed by animals including humans. AI research has been defined as the field of study of
intelligent agents, which refers to any system that perceives its environment and takes actions that maximize
its chance of achieving its goals. The term artificial intelligence had previously been used to describe
machines that mimic and display human cognitive skills associated with the human mind, such as learning and
problem-solving. This definition has since been rejected by major AI researchers who now describe AI in terms
of rationality and acting rationally, which does not limit how intelligence can be articulated.

AI applications include advanced web search engines, recommendation systems (used by YouTube, Amazon and Netflix),
understanding human speech (such as Siri and Alexa), self-driving cars (such as Waymo), generative or creative
tools (ChatGPT and AI art), automated decision-making and competing at the highest level in strategic game
systems (such as chess and Go). As machines become increasingly capable, tasks considered to require intelligence
are often removed from the definition of AI, a phenomenon known as the AI effect.&quot;&quot;&quot;

splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=30)
chunks = splitter.create_documents([long_text])

print(f&quot;Split into {len(chunks)} chunks:&quot;)
for i, c in enumerate(chunks):
    print(f&quot;  Chunk {i+1} ({len(c.page_content)} chars): {c.page_content[:80]}...&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 7 — Tools &amp;amp; Function Calling&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Tools&lt;/strong&gt;: functions the LLM can choose to call (calculator, search, API)
- &lt;strong&gt;Function calling&lt;/strong&gt;: the model outputs a structured JSON call instead of plain text
- &lt;strong&gt;Tool schema&lt;/strong&gt;: name + description + input schema — the model reads descriptions to decide when to use a tool
- &lt;strong&gt;Structured output&lt;/strong&gt;: force the model to return a specific schema&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 7a. Define tools using @tool decorator
from langchain_core.tools import tool
import math
import datetime

@tool
def calculator(expression: str) -&amp;gt; str:
    &quot;&quot;&quot;Evaluate a mathematical expression. Input must be a valid Python math expression.
    Examples: &#39;2 + 2&#39;, &#39;math.sqrt(144)&#39;, &#39;15 * 7 / 3&#39;&quot;&quot;&quot;
    try:
        result = eval(expression, {&quot;__builtins__&quot;: {}}, {&quot;math&quot;: math})
        return str(result)
    except Exception as e:
        return f&quot;Error: {e}&quot;

@tool
def get_current_date(timezone: str = &quot;UTC&quot;) -&amp;gt; str:
    &quot;&quot;&quot;Get the current date and time. Optionally specify a timezone name.&quot;&quot;&quot;
    return datetime.datetime.now().strftime(f&quot;%Y-%m-%d %H:%M:%S ({timezone})&quot;)

@tool
def word_count(text: str) -&amp;gt; str:
    &quot;&quot;&quot;Count the number of words in a text string.&quot;&quot;&quot;
    return str(len(text.split()))

print(&quot;Tools defined:&quot;)
for t in [calculator, get_current_date, word_count]:
    print(f&quot;  - {t.name}: {t.description[:60]}...&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 7b. Bind tools to the LLM and handle a tool call manually
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage

tools = [calculator, get_current_date, word_count]
llm_with_tools = llm.bind_tools(tools)

messages = [HumanMessage(content=&quot;What is 15% of 240? Also what is today&#39;s date?&quot;)]

# First call — model may return tool calls instead of a final answer
ai_msg = llm_with_tools.invoke(messages)
messages.append(ai_msg)

print(f&quot;Tool calls requested: {len(ai_msg.tool_calls)}&quot;)
for tc in ai_msg.tool_calls:
    print(f&quot;  Tool: {tc[&#39;name&#39;]}, Args: {tc[&#39;args&#39;]}&quot;)

# Execute each tool
tool_map = {t.name: t for t in tools}
for tc in ai_msg.tool_calls:
    result = tool_map[tc[&quot;name&quot;]].invoke(tc[&quot;args&quot;])
    messages.append(ToolMessage(content=result, tool_call_id=tc[&quot;id&quot;]))

# Second call — model now has tool results, produces final answer
final = llm_with_tools.invoke(messages)
print(f&quot;\nFinal answer: {final.content}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 7c. Structured output — force model to return a specific schema
from pydantic import BaseModel, Field
from typing import List

class MovieReview(BaseModel):
    title: str = Field(description=&quot;Movie title&quot;)
    year: int = Field(description=&quot;Release year&quot;)
    sentiment: str = Field(description=&quot;Overall sentiment: positive, negative, or mixed&quot;)
    score: float = Field(description=&quot;Score out of 10&quot;)
    pros: List[str] = Field(description=&quot;List of positive aspects&quot;)
    cons: List[str] = Field(description=&quot;List of negative aspects&quot;)

structured_llm = llm.with_structured_output(MovieReview)

review_text = &quot;&quot;&quot;
Interstellar (2014) is a visually stunning sci-fi epic. The space sequences are breathtaking,
Hans Zimmer&#39;s score is unforgettable, and McConaughey&#39;s performance is moving. However,
the third act gets overly convoluted and the science is sometimes stretched too thin.
Overall a great film, 8/10.
&quot;&quot;&quot;

review = structured_llm.invoke(f&quot;Extract a structured review from this text:\n{review_text}&quot;)
print(review.model_dump_json(indent=2))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 8 — Agents&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Agent&lt;/strong&gt;: an LLM that can choose which tools to use, call them, observe results, and repeat
- &lt;strong&gt;ReAct pattern&lt;/strong&gt;: Reason → Act → Observe → (repeat until done)
- &lt;strong&gt;Reasoning loop&lt;/strong&gt;: the agent keeps calling tools until it has enough info to answer
- &lt;strong&gt;Agent executor&lt;/strong&gt;: runtime that manages the tool-call loop
- &lt;strong&gt;Stopping condition&lt;/strong&gt;: agent decides when it has a final answer&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 8a. ReAct agent — see the reasoning loop step by step
from IPython.display import display, Markdown
from langchain.agents import create_agent
from langchain_core.tools import tool
import math, datetime

@tool
def calculator(expression: str) -&amp;gt; str:
    &quot;&quot;&quot;Evaluate a math expression. Example: &#39;2 ** 10&#39; or &#39;math.sqrt(144)&#39;&quot;&quot;&quot;
    try:
        return str(eval(expression, {&quot;__builtins__&quot;: {}}, {&quot;math&quot;: math}))
    except Exception as e:
        return f&quot;Error: {e}&quot;

@tool
def get_current_year(dummy: str = &quot;&quot;) -&amp;gt; str:
    &quot;&quot;&quot;Returns the current year as a string.&quot;&quot;&quot;
    return str(datetime.datetime.now().year)

@tool
def string_reverse(text: str) -&amp;gt; str:
    &quot;&quot;&quot;Reverses a string. Input: any text string.&quot;&quot;&quot;
    return text[::-1]

agent_tools = [calculator, get_current_year, string_reverse]

# create_agent builds a StateGraph with a tool-calling loop internally
agent = create_agent(llm, agent_tools)

result = agent.invoke({
    &quot;messages&quot;: [(&quot;human&quot;, &quot;What is 2 to the power of 10, and what is that number reversed as a string?&quot;)]
})

answer = result[&quot;messages&quot;][-1].content
display(Markdown(f&quot;**Answer:** {answer}&quot;))

# Show the reasoning steps
display(Markdown(&quot;---\n**Reasoning trace:**&quot;))
for msg in result[&quot;messages&quot;]:
    role = msg.__class__.__name__.replace(&quot;Message&quot;, &quot;&quot;)
    content = msg.content or str(getattr(msg, &quot;tool_calls&quot;, &quot;&quot;))
    display(Markdown(f&quot;- **{role}:** {str(content)[:200]}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 8b. create_agent with a custom system prompt
from IPython.display import display, Markdown
from langchain.agents import create_agent

# Pass a system prompt string directly
agent = create_agent(
    llm,
    agent_tools,
    system_prompt=&quot;You are a helpful assistant. Use tools when needed to answer accurately.&quot;
)

result = agent.invoke({
    &quot;messages&quot;: [(&quot;human&quot;, &quot;What year is it, and what is sqrt(year) rounded to 2 decimal places?&quot;)]
})

answer = result[&quot;messages&quot;][-1].content
display(Markdown(f&quot;**Answer:** {answer}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 8c. RAG-enabled agent — agent can choose to retrieve from the knowledge base
from IPython.display import display, Markdown
from langchain.agents import create_agent
from langchain_core.tools import tool
import math

@tool
def calculator(expression: str) -&amp;gt; str:
    &quot;&quot;&quot;Evaluate a math expression. Example: &#39;2 ** 10&#39; or &#39;math.sqrt(144)&#39;&quot;&quot;&quot;
    try:
        return str(eval(expression, {&quot;__builtins__&quot;: {}}, {&quot;math&quot;: math}))
    except Exception as e:
        return f&quot;Error: {e}&quot;

@tool
def search_programming_knowledge(query: str) -&amp;gt; str:
    &quot;&quot;&quot;Search the programming languages knowledge base. Use for questions about Python, Rust, JavaScript, or Go.&quot;&quot;&quot;
    results = vectorstore.similarity_search(query, k=2)
    return &quot;\n&quot;.join(doc.page_content for doc in results)

rag_tools = [calculator, search_programming_knowledge]

rag_agent = create_agent(
    llm,
    rag_tools,
    system_prompt=&quot;You are a knowledgeable assistant. Always search the knowledge base before answering.&quot;
)

result = rag_agent.invoke({
    &quot;messages&quot;: [(&quot;human&quot;, &quot;Compare Python and Rust. Which one prevents memory bugs at compile time?&quot;)]
})

display(Markdown(f&quot;**Answer:** {result[&#39;messages&#39;][-1].content}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 9 — Multi-Agent Systems&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Orchestrator&lt;/strong&gt;: a central agent that plans and delegates tasks
- &lt;strong&gt;Worker/Specialist agent&lt;/strong&gt;: focused on one domain (code, research, math)
- &lt;strong&gt;Handoff&lt;/strong&gt;: passing a task from one agent to another
- &lt;strong&gt;Why multi-agent?&lt;/strong&gt; Complex tasks benefit from specialisation and parallelism
- &lt;strong&gt;Agent-as-tool&lt;/strong&gt;: wrap one agent as a callable tool for another agent&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 9a. Specialist agents used as tools by an orchestrator
from IPython.display import display, Markdown
from langchain.agents import create_agent
from langchain_core.tools import tool

# --- Specialist: Code Explainer ---
code_agent = create_agent(
    llm, [],
    system_prompt=&quot;You are an expert programmer. Explain code clearly and concisely.&quot;
)

# --- Specialist: Writer ---
writer_agent = create_agent(
    llm, [],
    system_prompt=&quot;You are a professional writer. Produce clear, engaging content.&quot;
)

# --- Wrap specialists as tools for the orchestrator ---
@tool
def ask_code_agent(task: str) -&amp;gt; str:
    &quot;&quot;&quot;Delegate a coding or code-explanation task to the specialist code agent.&quot;&quot;&quot;
    result = code_agent.invoke({&quot;messages&quot;: [(&quot;human&quot;, task)]})
    return result[&quot;messages&quot;][-1].content

@tool
def ask_writer_agent(task: str) -&amp;gt; str:
    &quot;&quot;&quot;Delegate a writing or content-creation task to the specialist writer agent.&quot;&quot;&quot;
    result = writer_agent.invoke({&quot;messages&quot;: [(&quot;human&quot;, task)]})
    return result[&quot;messages&quot;][-1].content

# --- Orchestrator ---
orchestrator = create_agent(
    llm,
    [ask_code_agent, ask_writer_agent],
    system_prompt=&quot;&quot;&quot;You are an orchestrator. Break down complex tasks and delegate to the right specialist:
- ask_code_agent: for coding, code explanation, technical topics
- ask_writer_agent: for writing, summarising, or creative content
Combine their outputs into a final cohesive answer.&quot;&quot;&quot;
)

result = orchestrator.invoke({
    &quot;messages&quot;: [(&quot;human&quot;, &quot;Explain what a Python list comprehension is and then write a short blog intro about why Python is beginner-friendly.&quot;)]
})

display(Markdown(f&quot;### Final Answer\n{result[&#39;messages&#39;][-1].content}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 9b. Parallel multi-agent execution (manual)
import concurrent.futures
from IPython.display import display, Markdown
from langchain_core.messages import HumanMessage

def run_agent(role, system_prompt, question):
    from langchain_core.messages import SystemMessage, HumanMessage
    response = llm.invoke([
        SystemMessage(content=system_prompt),
        HumanMessage(content=question)
    ])
    return role, response.content

agents_config = [
    (&quot;Optimist&quot;, &quot;You are an optimist. Find the positive aspects of any topic.&quot;, &quot;What is the impact of AI on jobs?&quot;),
    (&quot;Pessimist&quot;, &quot;You are a pessimist. Find the risks and downsides of any topic.&quot;, &quot;What is the impact of AI on jobs?&quot;),
    (&quot;Neutral&quot;,  &quot;You are a balanced analyst. Give a factual, neutral assessment.&quot;, &quot;What is the impact of AI on jobs?&quot;),
]

with concurrent.futures.ThreadPoolExecutor() as pool:
    futures = [pool.submit(run_agent, *cfg) for cfg in agents_config]
    results = [f.result() for f in concurrent.futures.as_completed(futures)]

for role, answer in sorted(results):
    display(Markdown(f&quot;### {role}\n{answer}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 10 — Agentic Patterns&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Planning&lt;/strong&gt;: agent decomposes a goal into sub-tasks before acting
- &lt;strong&gt;Reflection / self-critique&lt;/strong&gt;: agent reviews and improves its own output
- &lt;strong&gt;Tool-use loops&lt;/strong&gt;: repeat until a stopping condition is met
- &lt;strong&gt;Human-in-the-loop&lt;/strong&gt;: pause for human approval before proceeding
- &lt;strong&gt;Evaluator-Optimizer&lt;/strong&gt;: one LLM generates, another scores/critiques, loop until quality threshold
- &lt;strong&gt;Map-Reduce&lt;/strong&gt;: process many items in parallel (map), synthesise results (reduce)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10a. Planning pattern — decompose a goal before acting
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser

plan_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;&quot;&quot;You are a planning agent. Break down the user&#39;s goal into a numbered list of concrete sub-tasks.
Return JSON: {{&quot;goal&quot;: string, &quot;tasks&quot;: [{{&quot;id&quot;: int, &quot;task&quot;: string, &quot;depends_on&quot;: []}}]}}&quot;&quot;&quot;),
    (&quot;human&quot;, &quot;Goal: {goal}&quot;)
])

planner = plan_prompt | llm | JsonOutputParser()

plan = planner.invoke({&quot;goal&quot;: &quot;Build a simple weather app that shows current temperature&quot;})

rows = [f&quot;**Goal:** {plan[&#39;goal&#39;]}\n&quot;, &quot;| # | Task | Depends On |&quot;, &quot;|---|------|------------|&quot;]
for task in plan[&quot;tasks&quot;]:
    deps = &quot;, &quot;.join(str(d) for d in task[&quot;depends_on&quot;]) if task[&quot;depends_on&quot;] else &quot;—&quot;
    rows.append(f&quot;| {task[&#39;id&#39;]} | {task[&#39;task&#39;]} | {deps} |&quot;)

display(Markdown(&quot;\n&quot;.join(rows)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10b. Reflection pattern — generate → critique → improve
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

generate_prompt = ChatPromptTemplate.from_template(
    &quot;Write a short paragraph explaining {topic} for a beginner.&quot;
)
critique_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;You are a strict writing critic. Identify specific weaknesses: unclear terms, missing context, poor flow. Be concise.&quot;),
    (&quot;human&quot;, &quot;Critique this explanation:\n\n{draft}&quot;)
])
improve_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;You are a writing improver. Fix the issues identified in the critique.&quot;),
    (&quot;human&quot;, &quot;Original:\n{draft}\n\nCritique:\n{critique}\n\nWrite an improved version:&quot;)
])

parser = StrOutputParser()

topic = &quot;neural networks&quot;

draft    = (generate_prompt | llm | parser).invoke({&quot;topic&quot;: topic})
critique = (critique_prompt | llm | parser).invoke({&quot;draft&quot;: draft})
improved = (improve_prompt  | llm | parser).invoke({&quot;draft&quot;: draft, &quot;critique&quot;: critique})

display(Markdown(f&quot;### Draft\n{draft}&quot;))
display(Markdown(f&quot;### Critique\n{critique}&quot;))
display(Markdown(f&quot;### Improved\n{improved}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10c. Evaluator-Optimizer loop — iterate until quality score &amp;gt;= threshold
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser, StrOutputParser

write_prompt = ChatPromptTemplate.from_template(
    &quot;Write a haiku about {subject}. Just the haiku, no commentary.&quot;
)
eval_prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;Score the haiku 1-10 for creativity and adherence to 5-7-5 syllable structure. Return JSON: {{\&quot;score\&quot;: int, \&quot;feedback\&quot;: string}}&quot;),
    (&quot;human&quot;, &quot;{haiku}&quot;)
])
improve_prompt = ChatPromptTemplate.from_template(
    &quot;Improve this haiku based on this feedback: {feedback}\n\nOriginal:\n{haiku}\n\nImproved haiku (just the haiku):&quot;
)

writer    = write_prompt   | llm | StrOutputParser()
evaluator = eval_prompt    | llm | JsonOutputParser()
improver  = improve_prompt | llm | StrOutputParser()

THRESHOLD = 7
MAX_ROUNDS = 4

haiku = writer.invoke({&quot;subject&quot;: &quot;machine learning&quot;})
display(Markdown(f&quot;**Round 0 (initial):**\n\n{haiku}&quot;))

for round_num in range(1, MAX_ROUNDS + 1):
    evaluation = evaluator.invoke({&quot;haiku&quot;: haiku})
    score, feedback = evaluation[&quot;score&quot;], evaluation[&quot;feedback&quot;]
    display(Markdown(f&quot;**Round {round_num} score:** {score}/10 — {feedback}&quot;))
    if score &amp;gt;= THRESHOLD:
        display(Markdown(f&quot;**Accepted! Final haiku:**\n\n{haiku}&quot;))
        break
    haiku = improver.invoke({&quot;haiku&quot;: haiku, &quot;feedback&quot;: feedback})
    display(Markdown(f&quot;**Improved:**\n\n{haiku}&quot;))
else:
    display(Markdown(f&quot;**Max rounds reached. Best haiku:**\n\n{haiku}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10d. Map-Reduce pattern — summarise multiple documents in parallel
import concurrent.futures
from IPython.display import display, Markdown
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

documents = [
    &quot;Python was created by Guido van Rossum and first released in 1991. It emphasises code readability and simplicity.&quot;,
    &quot;JavaScript was created by Brendan Eich at Netscape in 1995. Originally designed for browser scripting, it now runs on servers via Node.js.&quot;,
    &quot;Rust was designed by Graydon Hoare at Mozilla Research and announced in 2010. It guarantees memory safety without a garbage collector.&quot;,
    &quot;Go was created at Google by Robert Griesemer, Rob Pike, and Ken Thompson, released in 2009. It prioritises simplicity and fast compile times.&quot;,
]

map_chain = (
    ChatPromptTemplate.from_template(&quot;Summarise in one sentence: {doc}&quot;)
    | llm | StrOutputParser()
)

reduce_chain = (
    ChatPromptTemplate.from_template(
        &quot;Given these summaries of programming languages:\n{summaries}\n\nWrite a 2-sentence overall synthesis.&quot;
    ) | llm | StrOutputParser()
)

with concurrent.futures.ThreadPoolExecutor() as pool:
    summaries = list(pool.map(lambda d: map_chain.invoke({&quot;doc&quot;: d}), documents))

display(Markdown(&quot;### MAP (individual summaries)\n&quot; + &quot;\n&quot;.join(f&quot;- {s}&quot; for s in summaries)))

synthesis = reduce_chain.invoke({&quot;summaries&quot;: &quot;\n&quot;.join(f&quot;- {s}&quot; for s in summaries)})
display(Markdown(f&quot;### REDUCE (synthesis)\n{synthesis}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10e. Human-in-the-loop — agent pauses for approval before taking an action
from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.tools import tool

@tool
def send_email(recipient: str, subject: str, body: str) -&amp;gt; str:
    &quot;&quot;&quot;Send an email. Requires human approval before sending.&quot;&quot;&quot;
    return f&quot;Email sent to {recipient} with subject &#39;{subject}&#39;&quot;

def agent_with_approval(user_request: str):
    &quot;&quot;&quot;An agent loop that pauses for human approval before calling dangerous tools.&quot;&quot;&quot;
    APPROVAL_REQUIRED = {&quot;send_email&quot;}

    llm_tools = llm.bind_tools([send_email])
    messages = [HumanMessage(content=user_request)]

    for step in range(5):
        response = llm_tools.invoke(messages)
        messages.append(response)

        if not response.tool_calls:
            print(f&quot;\nAgent: {response.content}&quot;)
            break

        for tc in response.tool_calls:
            print(f&quot;\nAgent wants to call: {tc[&#39;name&#39;]}({tc[&#39;args&#39;]})&quot;)

            if tc[&quot;name&quot;] in APPROVAL_REQUIRED:
                approval = input(&quot;Approve? (yes/no): &quot;).strip().lower()
                if approval != &quot;yes&quot;:
                    result = &quot;Action cancelled by user.&quot;
                else:
                    result = send_email.invoke(tc[&quot;args&quot;])
            else:
                result = send_email.invoke(tc[&quot;args&quot;])

            from langchain_core.messages import ToolMessage
            messages.append(ToolMessage(content=result, tool_call_id=tc[&quot;id&quot;]))

agent_with_approval(&quot;Please draft and send an email to alice@example.com about our meeting next Monday at 10am.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Section 11 — Putting It All Together: Mini Agentic App&lt;/h2&gt;
&lt;p&gt;A complete mini-application combining: &lt;strong&gt;RAG + Tools + Memory + Reflection&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a &lt;strong&gt;Research Assistant&lt;/strong&gt; that:
1. Retrieves relevant knowledge from a vector store (RAG)
2. Can do calculations
3. Remembers the conversation (Memory)
4. Reflects and refines answers before responding&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 11. Mini Agentic Research Assistant — LangGraph memory + tools + reflection
from IPython.display import display, Markdown
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage, SystemMessage
import math

@tool
def knowledge_base_search(query: str) -&amp;gt; str:
    &quot;&quot;&quot;Search the programming languages knowledge base for factual information.&quot;&quot;&quot;
    results = vectorstore.similarity_search(query, k=3)
    if not results:
        return &quot;No relevant information found in the knowledge base.&quot;
    return &quot;\n&quot;.join(f&quot;[{r.metadata[&#39;source&#39;]}] {r.page_content}&quot; for r in results)

@tool
def calculator(expression: str) -&amp;gt; str:
    &quot;&quot;&quot;Evaluate a math expression like &#39;2 ** 10&#39; or &#39;math.sqrt(144)&#39;.&quot;&quot;&quot;
    try:
        return str(eval(expression, {&quot;__builtins__&quot;: {}}, {&quot;math&quot;: math}))
    except Exception as e:
        return f&quot;Error: {e}&quot;

@tool
def self_reflect(draft_answer: str) -&amp;gt; str:
    &quot;&quot;&quot;Critically evaluate a draft answer and suggest improvements.&quot;&quot;&quot;
    response = llm.invoke([
        SystemMessage(content=&quot;You are a critical reviewer. Evaluate for accuracy, completeness, and clarity. Suggest 2-3 improvements.&quot;),
        HumanMessage(content=draft_answer)
    ])
    return response.content

assistant_tools = [knowledge_base_search, calculator, self_reflect]
llm_with_tools  = llm.bind_tools(assistant_tools)

SYSTEM = SystemMessage(content=&quot;&quot;&quot;You are an intelligent research assistant with access to:
1. knowledge_base_search — look up factual information
2. calculator — numerical computation
3. self_reflect — critique and improve your own draft answers before finalising

Workflow: search → draft → reflect → final answer.
Always ground answers in retrieved facts when possible.&quot;&quot;&quot;)

def agent_node(state: MessagesState):
    response = llm_with_tools.invoke([SYSTEM] + state[&quot;messages&quot;])
    return {&quot;messages&quot;: [response]}

builder = StateGraph(MessagesState)
builder.add_node(&quot;agent&quot;,  agent_node)
builder.add_node(&quot;tools&quot;,  ToolNode(assistant_tools))
builder.add_edge(START, &quot;agent&quot;)
builder.add_conditional_edges(&quot;agent&quot;, tools_condition)   # routes to &quot;tools&quot; or END
builder.add_edge(&quot;tools&quot;, &quot;agent&quot;)                        # after tools, back to agent

graph = builder.compile(checkpointer=MemorySaver())

cfg = {&quot;configurable&quot;: {&quot;thread_id&quot;: &quot;research_1&quot;}}

def ask(question):
    display(Markdown(f&quot;---\n**User:** {question}&quot;))
    result = graph.invoke({&quot;messages&quot;: [HumanMessage(content=question)]}, config=cfg)
    answer = result[&quot;messages&quot;][-1].content
    display(Markdown(f&quot;**Assistant:** {answer}&quot;))
    return answer

ask(&quot;What is Rust and why is it special?&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Follow-up — tests memory
ask(&quot;Which language we discussed is best for web frontend?&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Math + knowledge combined
ask(&quot;If Python was released in 1991 and Go in 2009, how many years apart were they released?&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Summary &amp;amp; Next Steps&lt;/h2&gt;
&lt;h3&gt;What you covered:&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Key Takeaway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LLM Basics&lt;/td&gt;
&lt;td&gt;Tokens, temperature, streaming, roles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt Engineering&lt;/td&gt;
&lt;td&gt;Templates, few-shot, CoT, structured output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chains (LCEL)&lt;/td&gt;
&lt;td&gt;Compose components with &lt;code&gt;&amp;amp;#124;&lt;/code&gt;, parallel/sequential&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;Manual history; LangGraph &lt;code&gt;MemorySaver&lt;/code&gt; + &lt;code&gt;thread_id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAG&lt;/td&gt;
&lt;td&gt;Embed → store → retrieve → augment → generate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools&lt;/td&gt;
&lt;td&gt;Define with &lt;code&gt;@tool&lt;/code&gt;, bind to LLM, handle tool calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents&lt;/td&gt;
&lt;td&gt;ReAct loop, tool-calling agent, RAG agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-Agent&lt;/td&gt;
&lt;td&gt;Orchestrator + specialists, parallel agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agentic Patterns&lt;/td&gt;
&lt;td&gt;Planning, reflection, eval-optimizer, map-reduce, HITL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LangGraph&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StateGraph&lt;/code&gt; + &lt;code&gt;MemorySaver&lt;/code&gt; for stateful agentic workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Intermediate next steps:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LangGraph advanced&lt;/strong&gt; — branching, human-in-the-loop interrupts, subgraphs, streaming state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fine-tuning&lt;/strong&gt; — adapt a base model to your domain&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evals&lt;/strong&gt; — measure agent quality with LangSmith or RAGAS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production patterns&lt;/strong&gt; — caching, observability, rate limiting, cost tracking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom retrievers&lt;/strong&gt; — BM25 hybrid search, reranking with cross-encoders&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multimodal&lt;/strong&gt; — vision-enabled models (llava via Ollama, Gemini Vision, GPT-4o)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Useful references:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://python.langchain.com/&quot;&gt;LangChain docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://langchain-ai.github.io/langgraph/&quot;&gt;LangGraph docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ollama.com/library&quot;&gt;Ollama model library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.promptingguide.ai/&quot;&gt;Prompt Engineering Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  &lt;h3&gt;Key Takeaways&lt;/h3&gt;

  &lt;p&gt;After working through the notebook you should be comfortable with:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Swapping LLM providers without rewriting your application logic&lt;/li&gt;
    &lt;li&gt;Writing prompts that reliably produce structured, typed output&lt;/li&gt;
    &lt;li&gt;Building RAG pipelines that ground model responses in your own data&lt;/li&gt;
    &lt;li&gt;Defining and binding tools so a model can interact with external systems&lt;/li&gt;
    &lt;li&gt;Reasoning about the &lt;em&gt;ReAct&lt;/em&gt; loop and when an agent approach is—and isn&#39;t—the right choice&lt;/li&gt;
    &lt;li&gt;Sketching multi-agent architectures with routing and specialist sub-agents&lt;/li&gt;
  &lt;/ul&gt;

  &lt;hr /&gt;

  &lt;p&gt;
    The notebook is intentionally opinionated in its use of &lt;strong&gt;LangChain&lt;/strong&gt; as the
    orchestration layer, since it offers a consistent API across providers and a rich ecosystem
    of integrations. That said, the concepts translate directly to other frameworks
    (LlamaIndex, Semantic Kernel, raw API calls) once you understand the underlying patterns.
  &lt;/p&gt;
  &lt;p&gt;
    Questions, corrections, or suggestions? Leave a comment below—feedback is how this kind
    of resource improves over time.
  &lt;/p&gt;

&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2026/07/genai-agents-agentic-ai-hands-on-notebook.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEjuLCskHD1fwWj6QJ7uu_Gka09bErlLToO31qf9MvbhU9JFiALsZVvuFP7KudEdiHIj2hXJnbpLJdtBeHE495uitk5yx9Vu2Ar-Qz8f4-72HG0UeAIcA2gLrloEXKi-Sqslt_a9geaBo_OWbIhy94p5-_Hya3AZOJb0YRywZwHNmyma5HP_V2yXwsStBvo=s72-c" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-7741050775415736543</guid><pubDate>Fri, 24 Jul 2026 19:00:19 +0000</pubDate><atom:updated>2026-07-25T00:34:38.787+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">AI tutorial</category><category domain="http://www.blogger.com/atom/ns#">bellman equation</category><category domain="http://www.blogger.com/atom/ns#">epsilon-greedy</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">machine learning</category><category domain="http://www.blogger.com/atom/ns#">q-learning</category><category domain="http://www.blogger.com/atom/ns#">q-table</category><category domain="http://www.blogger.com/atom/ns#">reinforcement learning</category><title>Q-Table Explained: 5 Steps to Master Reinforcement Learning</title><description>&lt;style&gt;
    .post-body {
      font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
      line-height: 1.6;
      color: #24292e;
      max-width: 860px;
      margin: 0 auto;
      padding: 20px;
    }
    .post-body h1, .post-body h2, .post-body h3 {
      color: #0366d6;
      border-bottom: 1px solid #eaecef;
      padding-bottom: 0.3em;
      margin-top: 1.5em;
    }
    .post-body p { margin-bottom: 1em; }
    .post-body pre {
      background-color: #1e1e1e;
      color: #d4d4d4;
      padding: 16px;
      border-radius: 6px;
      overflow-x: auto;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 0.9em;
      line-height: 1.45;
    }
    .post-body code {
      background-color: #f6f8fa;
      color: #d73a49;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 85%;
    }
    .post-body pre code { background-color: transparent; color: inherit; padding: 0; }
    .post-body table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
      font-size: 0.95em;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
      border-radius: 6px;
      overflow: hidden;
    }
    .post-body th, .post-body td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #dddddd; }
    .post-body th { background-color: #0366d6; color: #ffffff; font-weight: 600; }
    .post-body tr:nth-of-type(even) { background-color: #f8f9fa; }
    .post-body tr:hover { background-color: #f1f3f5; }
    .post-body blockquote {
      margin: 1.5em 0;
      padding: 1em 1.2em;
      background-color: #f1f8ff;
      border-left: 4px solid #0366d6;
      color: #24292e;
      border-radius: 0 6px 6px 0;
    }
    .post-body ul, .post-body ol { padding-left: 20px; margin-bottom: 1em; }
    .post-body li { margin-bottom: 0.4em; }
    .post-body hr { border: 0; height: 1px; background: #e1e4e8; margin: 2em 0; }

    /* Visual Enhancement Components */
    .post-body .diagram-container {
      background-color: #ffffff;
      border: 1px solid #e1e4e8;
      border-radius: 8px;
      padding: 20px;
      margin: 25px 0;
      box-shadow: 0 2px 6px rgba(0,0,0,0.04);
      text-align: center;
    }
    .post-body .diagram-caption {
      font-size: 0.85em;
      color: #586069;
      margin-top: 10px;
      font-style: italic;
    }
    .post-body .pipeline-flow {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: center;
      gap: 10px;
      margin: 20px 0;
    }
    .post-body .pipeline-step {
      background: #f1f8ff;
      border: 1px solid #0366d6;
      color: #0366d6;
      padding: 10px 16px;
      border-radius: 20px;
      font-weight: bold;
      font-size: 0.9em;
    }
    .post-body .pipeline-step.highlight {
      background: #0366d6;
      color: #ffffff;
      box-shadow: 0 2px 4px rgba(3,102,214,0.3);
    }
    .post-body .pipeline-arrow {
      color: #586069;
      font-weight: bold;
    }
    .post-body .badge {
      display: inline-block;
      padding: 2px 8px;
      font-size: 0.75em;
      font-weight: 600;
      border-radius: 12px;
      margin-left: 6px;
    }
    .post-body .badge-success { background: #dcffe4; color: #1a7f37; }
    .post-body .badge-danger { background: #ffebe9; color: #cf222e; }
    .post-body .badge-warning { background: #fff8c5; color: #9a6700; }
&lt;/style&gt;
&lt;div class=&quot;post-body&quot;&gt;
&lt;p&gt;Imagine you&#39;re teaching a dog new tricks. You don&#39;t hand it a manual — you reward it when it does something right and ignore (or correct) it when it doesn&#39;t. Over dozens of repetitions, the dog builds an internal sense of which actions pay off in which situations. That&#39;s the soul of &lt;strong&gt;reinforcement learning&lt;/strong&gt;, and the &lt;strong&gt;Q-Table&lt;/strong&gt; is how we give a computer program that same kind of memory.&lt;/p&gt;
&lt;p&gt;In this post, we&#39;ll build a complete Q-learning agent from scratch — a &lt;strong&gt;warehouse robot&lt;/strong&gt; that learns to navigate a 5×5 grid to deliver packages while avoiding forklift collision zones. By the end, you&#39;ll understand not just &lt;em&gt;what&lt;/em&gt; a Q-Table is, but &lt;em&gt;why&lt;/em&gt; every design choice exists.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhRry6DJm7y2n0LGtxBo__3mZP7NGQbGtZ4cWR7TNOAMl84_VSGvAqhYM7WFdFjMVJooVu19YcZL6AErPnXsVVpO1CR-CENihhnGKXwenqiHOML_j3MS6o6koPK7izecel0u6mTOjHDpqGA49FEervOrNGH8bcxkxDxH6xdmxnHyIp4OLluFhhAJxYU86U&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;630&quot; data-original-width=&quot;1200&quot; height=&quot;336&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhRry6DJm7y2n0LGtxBo__3mZP7NGQbGtZ4cWR7TNOAMl84_VSGvAqhYM7WFdFjMVJooVu19YcZL6AErPnXsVVpO1CR-CENihhnGKXwenqiHOML_j3MS6o6koPK7izecel0u6mTOjHDpqGA49FEervOrNGH8bcxkxDxH6xdmxnHyIp4OLluFhhAJxYU86U=w640-h336&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Problem Q-Learning Solves&lt;/h2&gt;
&lt;h3&gt;Why Supervised Learning Fails Here&lt;/h3&gt;
&lt;p&gt;Supervised learning is fantastic when you have labeled examples: &quot;given this email, the correct label is &lt;em&gt;spam&lt;/em&gt;.&quot; But consider our warehouse robot. What&#39;s the &quot;correct&quot; move when the robot is at position (2, 3) and the target shelf is at (4, 4)? Move right? Move down? Both might eventually work. The right answer depends on the &lt;em&gt;entire sequence of future moves&lt;/em&gt; — not just the current step.&lt;/p&gt;
&lt;p&gt;There&#39;s no teacher handing out labeled training data. The robot must &lt;strong&gt;discover&lt;/strong&gt; good strategies through trial and error. This is the core of &lt;strong&gt;sequential decision-making under uncertainty&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;The Explore-Exploit Dilemma&lt;/h3&gt;
&lt;p&gt;Here&#39;s a tension every RL agent faces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exploit:&lt;/strong&gt; Do what you already know works well. (Go the route you&#39;ve taken before.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explore:&lt;/strong&gt; Try something new. Maybe there&#39;s a better route you haven&#39;t discovered yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Think of it like a delivery driver who always takes the same highway route because it worked yesterday. One day the highway is jammed, but the driver never finds the faster back roads because they stopped exploring. If the robot only exploits, it gets stuck in the first decent strategy it finds. If it only explores, it never actually gets good at anything. The balance is called the &lt;strong&gt;epsilon-greedy&lt;/strong&gt; policy, and we&#39;ll implement it in Step 3.&lt;/p&gt;
&lt;h3&gt;What &quot;Reward&quot; Means Computationally&lt;/h3&gt;
&lt;p&gt;A reward is simply a scalar number the environment hands back after each action:
- &lt;strong&gt;+100&lt;/strong&gt; for reaching the target shelf
- &lt;strong&gt;-50&lt;/strong&gt; for hitting a forklift collision zone
- &lt;strong&gt;-1&lt;/strong&gt; for each time step (to encourage finding &lt;em&gt;fast&lt;/em&gt; paths, not just &lt;em&gt;safe&lt;/em&gt; ones)&lt;/p&gt;
&lt;p&gt;The robot&#39;s job is to maximize &lt;strong&gt;total cumulative reward&lt;/strong&gt; over time — not just the immediate reward of a single move.&lt;/p&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;The Reinforcement Learning Loop&lt;/h3&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Agent observes State s&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Chooses Action a&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Environment returns Reward r + Next State s&#39;&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Agent updates Q-Table&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Repeat until convergence&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;The agent-environment loop is the heartbeat of Q-learning. Each cycle produces one experience tuple (s, a, r, s&#39;) used to sharpen the Q-Table. The agent never sees the full map — it only learns from these one-step snapshots.&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;
&lt;h2&gt;Anatomy of a Q-Table&lt;/h2&gt;
&lt;p&gt;A Q-Table is a plain 2D matrix. Think of it like a &lt;strong&gt;laminated cue card&lt;/strong&gt; the robot carries at all times — every room it might enter is a row, every direction it might walk is a column, and each cell holds its best guess at how rewarding that move will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rows&lt;/strong&gt; = every possible state the robot can be in (each of the 25 grid cells)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Columns&lt;/strong&gt; = every possible action (UP, DOWN, LEFT, RIGHT)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cell value&lt;/strong&gt; = Q-value — an estimate of &quot;how good is it to take this action from this state?&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
&lt;pre style=&quot;font-family: monospace; font-size: 0.85em; line-height: 1.6;&quot;&gt;         UP      DOWN    LEFT    RIGHT
State 0  [ 0.00   0.00    0.00    0.00  ]   ← (row 0, col 0): Start
State 1  [ 0.00   0.00    0.00    0.00  ]   ← (row 0, col 1)
...       ...
State 12 [ 0.00   0.00    0.00    0.00  ]   ← Center of grid
...       ...
State 24 [ 0.00   0.00    0.00    0.00  ]   ← Target shelf!

After training:
         UP      DOWN    LEFT    RIGHT
State 0  [ 0.12   0.45   -0.30    0.67  ]   Robot should go RIGHT
State 5  [-0.50   0.89    0.23    0.45  ]   Robot should go DOWN
&lt;/pre&gt;
&lt;div class=&quot;diagram-caption&quot;&gt;A Q-Table before (all zeros) and after training. Each cell stores the expected future reward for taking that action from that state. The robot picks the action with the highest Q-value in its current row — no computation needed at decision time, just a lookup.&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Initialization and Size&lt;/h3&gt;
&lt;p&gt;Every cell starts at &lt;strong&gt;0.0&lt;/strong&gt; — the agent assumes nothing about the world. Over training episodes, values drift toward their true worth. Starting at zero is a deliberate choice: it makes the agent mildly &lt;em&gt;optimistic&lt;/em&gt; about unexplored actions (since even a small positive reward will beat 0.0 initially), which naturally encourages exploration early in training.&lt;/p&gt;
&lt;p&gt;Size? For our 5×5 warehouse: &lt;strong&gt;25 states × 4 actions = 100 cells&lt;/strong&gt;. Totally manageable. But consider a chess engine: ~10⁴⁷ possible board states. A Q-Table would require more memory than there are atoms in the observable universe. That&#39;s the &lt;strong&gt;state space explosion&lt;/strong&gt; problem — we&#39;ll revisit it at the end.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Bellman Equation Demystified&lt;/h2&gt;
&lt;h3&gt;Intuition First&lt;/h3&gt;
&lt;p&gt;Imagine you&#39;re a hiking guide estimating how long it takes to reach a mountain summit from various waypoints on the trail. You don&#39;t walk every possible path from scratch each time — instead, you reason backwards: &quot;From waypoint C, the summit is 30 minutes away. So from waypoint B (20 minutes from C), the total is 50 minutes.&quot; Once you know the value of a closer waypoint, you can immediately compute the value of every waypoint leading into it.&lt;/p&gt;
&lt;p&gt;The Bellman equation does exactly this for Q-values — it propagates the value of reaching the goal &lt;strong&gt;backwards&lt;/strong&gt; through the state space, one step at a time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;*&quot;The value of being in state s and taking action a equals the immediate reward, plus the discounted value of the best action you can take from wherever you end up.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The Formula&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Q(s, a) ← Q(s, a) + α [ r + γ · max Q(s&#39;, a&#39;) − Q(s, a) ]
                              └─────────────────────┘
                               Temporal Difference (TD) Error
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s dissect every piece:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Typical Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Q(s,a)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Current Q-value&lt;/td&gt;
&lt;td&gt;What we currently &lt;em&gt;think&lt;/em&gt; this move is worth&lt;/td&gt;
&lt;td&gt;Any real number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;α&lt;/code&gt; (alpha)&lt;/td&gt;
&lt;td&gt;Learning rate&lt;/td&gt;
&lt;td&gt;How fast to update — like a student who absorbs 30% of each lesson&lt;/td&gt;
&lt;td&gt;0.01 – 0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;r&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Immediate reward&lt;/td&gt;
&lt;td&gt;What the environment &lt;em&gt;actually&lt;/em&gt; gave us right now&lt;/td&gt;
&lt;td&gt;Domain-specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;γ&lt;/code&gt; (gamma)&lt;/td&gt;
&lt;td&gt;Discount factor&lt;/td&gt;
&lt;td&gt;How much we care about future rewards vs. immediate ones&lt;/td&gt;
&lt;td&gt;0.9 – 0.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max Q(s&#39;,a&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Best future Q-value&lt;/td&gt;
&lt;td&gt;Best known value of the &lt;em&gt;next&lt;/em&gt; state&lt;/td&gt;
&lt;td&gt;Any real number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TD Error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Surprise signal&lt;/td&gt;
&lt;td&gt;How wrong our current estimate was — shrinks toward 0 at convergence&lt;/td&gt;
&lt;td&gt;Shrinks to 0 at convergence&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;What Each Hyperparameter Controls&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;α (Learning Rate):&lt;/strong&gt;
- Too high (α=0.9): The agent overreacts to each experience, values oscillate wildly — like a student who completely rewrites their notes after every single lecture, forgetting everything they studied the week before.
- Too low (α=0.001): Learning is painfully slow, may not converge in reasonable time.
- Sweet spot: Start at 0.1, decay slowly over episodes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;γ (Discount Factor):&lt;/strong&gt;
- γ=0: Robot is completely short-sighted — only cares about immediate reward (terrible for navigation).
- γ=1: Robot gives equal weight to rewards 1,000 steps in the future (can cause instability in long episodes).
- γ=0.95: &quot;I care about future rewards, but I prefer sooner ones&quot; — realistic and stable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ε (Epsilon — explore/exploit):&lt;/strong&gt;
- ε=1.0: Pure exploration (random actions)
- ε=0.0: Pure exploitation (always take best known action)
- Strategy: Start at 1.0, decay to 0.01 over training&lt;/p&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;Temporal Difference: How Surprise Drives Learning&lt;/h3&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Agent predicts Q(s,a) = 2.5&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Takes action, gets r=10, lands in s&#39;&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;TD Error = 10 + 0.95×3.0 − 2.5 = 10.35&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;New Q = 2.5 + 0.1×10.35 = 3.535&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;The TD Error is the &quot;surprise&quot; signal. A large positive error means this move was better than expected — raise its Q-value. A negative error means it was worse — lower it. Over thousands of steps, these small corrections accumulate into reliable estimates.&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;
&lt;h2&gt;Step-by-Step: Building a Q-Table from Scratch&lt;/h2&gt;
&lt;h3&gt;Our Scenario: The Warehouse Robot Navigator&lt;/h3&gt;
&lt;p&gt;A 5×5 grid warehouse. The robot starts at cell (0,0) — the loading dock. The target shelf is at (4,4). Three cells are blocked forklift zones: (1,1), (2,3), and (3,1).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  0   1   2   3   4
0 [S] [ ] [ ] [ ] [ ]
1 [ ] [X] [ ] [ ] [ ]
2 [ ] [ ] [ ] [X] [ ]
3 [ ] [X] [ ] [ ] [ ]
4 [ ] [ ] [ ] [ ] [T]

S = Start (loading dock)
T = Target shelf
X = Forklift collision zone
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;States are numbered 0–24 by row-major order: state = row×5 + col.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Step 1: Define the Environment&lt;/h3&gt;
&lt;p&gt;Before writing any learning code, we formalize the world. This is the most important step — a poorly designed reward structure will produce a robot that technically maximizes its score while doing something completely wrong (a phenomenon called &lt;strong&gt;reward hacking&lt;/strong&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;States:&lt;/strong&gt; 25 (one per grid cell)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actions:&lt;/strong&gt; 4 (0=UP, 1=DOWN, 2=LEFT, 3=RIGHT)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rewards:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Reach target (4,4): &lt;strong&gt;+100&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Hit forklift zone: &lt;strong&gt;-50&lt;/strong&gt; (episode ends)&lt;/li&gt;
&lt;li&gt;Each step: &lt;strong&gt;-1&lt;/strong&gt; (time penalty encourages short paths)&lt;/li&gt;
&lt;li&gt;Hit wall (try to move off grid): &lt;strong&gt;-5&lt;/strong&gt; (discourage wall bumping)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why the -1 step penalty?&lt;/strong&gt; Without it, a robot that reaches the goal in 8 steps and one that reaches it in 80 steps receive the same total reward (+100). The step penalty forces the robot to prefer &lt;em&gt;shorter&lt;/em&gt; routes — exactly what we want in a real warehouse.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;Step 2: Initialize the Q-Table&lt;/h3&gt;
&lt;p&gt;All zeros. The robot knows nothing yet.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Arrays;

public class Main {
    static final int NUM_STATES = 10;
    static final int NUM_ACTIONS = 4;

    public static void main(String[] args) {
        double[][] qTable = new double[NUM_STATES][NUM_ACTIONS];
        // Java initializes double arrays to 0.0 by default
        // But let&#39;s be explicit for clarity:
        for (int state = 0; state &amp;lt; NUM_STATES; state++) {
            Arrays.fill(qTable[state], 0.0);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Step 3: Epsilon-Greedy Policy&lt;/h3&gt;
&lt;p&gt;With probability ε, explore (random action). Otherwise, exploit (best Q-value). Note how &lt;code&gt;rng.nextDouble()&lt;/code&gt; returns a value in [0.0, 1.0) — if ε is 0.3, there&#39;s a 30% chance we explore.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Random;

public class Main {
    static final int NUM_ACTIONS = 4;

    static int chooseAction(double[][] qTable, int state, double epsilon, Random rng) {
        if (rng.nextDouble() &amp;lt; epsilon) {
            // Explore: pick a random action
            return rng.nextInt(NUM_ACTIONS);
        } else {
            // Exploit: pick the action with highest Q-value
            int bestAction = 0;
            double bestValue = qTable[state][0];
            for (int action = 1; action &amp;lt; NUM_ACTIONS; action++) {
                if (qTable[state][action] &amp;gt; bestValue) {
                    bestValue = qTable[state][action];
                    bestAction = action;
                }
            }
            return bestAction;
        }
    }

    public static void main(String[] args) {
        Random rng = new Random();
        int numStates = 5;
        double epsilon = 0.1;

        double[][] qTable = new double[numStates][NUM_ACTIONS];

        int state = 0;
        int action = chooseAction(qTable, state, epsilon, rng);
        System.out.println(&quot;Chosen action for state &quot; + state + &quot;: &quot; + action);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Step 4: Run Episodes and Apply the Update Rule&lt;/h3&gt;
&lt;p&gt;An &lt;strong&gt;episode&lt;/strong&gt; is one complete run of the robot from start to either reaching the target or hitting a forklift zone. We run many episodes — each one contributes a small amount of learning. The Bellman update happens after &lt;em&gt;every single step&lt;/em&gt;, not just at the end of each episode.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Arrays;

public class Main {
    static final int MAX_EPISODES = 1000;
    static final int START_STATE = 0;
    static final double GAMMA = 0.99;
    static final double ALPHA = 0.1;
    static final double EPSILON_MIN = 0.01;
    static final double EPSILON_DECAY = 0.995;

    static class StepResult {
        int nextState;
        double reward;
        boolean done;

        StepResult(int nextState, double reward, boolean done) {
            this.nextState = nextState;
            this.reward = reward;
            this.done = done;
        }
    }

    static class Environment {
        StepResult step(int state, int action) {
            // Placeholder implementation
            return new StepResult(0, 0.0, true);
        }
    }

    static int chooseAction(double[][] qTable, int state, double epsilon, java.util.Random rng) {
        if (rng.nextDouble() &amp;lt; epsilon) {
            return rng.nextInt(qTable[state].length);
        }
        int bestAction = 0;
        for (int i = 1; i &amp;lt; qTable[state].length; i++) {
            if (qTable[state][i] &amp;gt; qTable[state][bestAction]) {
                bestAction = i;
            }
        }
        return bestAction;
    }

    public static void main(String[] args) {
        int numStates = 10;
        int numActions = 4;
        double[][] qTable = new double[numStates][numActions];
        double epsilon = 1.0;
        java.util.Random rng = new java.util.Random();
        Environment environment = new Environment();

        for (int episode = 0; episode &amp;lt; MAX_EPISODES; episode++) {
            int state = START_STATE;
            boolean episodeDone = false;

            while (!episodeDone) {
                int action = chooseAction(qTable, state, epsilon, rng);
                StepResult result = environment.step(state, action);

                // Bellman update
                double bestNextQ = Arrays.stream(qTable[result.nextState]).max().getAsDouble();
                double tdError = result.reward + GAMMA * bestNextQ - qTable[state][action];
                qTable[state][action] += ALPHA * tdError;

                state = result.nextState;
                episodeDone = result.done;
            }

            // Decay epsilon so the robot gradually stops exploring
            epsilon = Math.max(EPSILON_MIN, epsilon * EPSILON_DECAY);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Step 5: Extract the Learned Policy&lt;/h3&gt;
&lt;p&gt;After training, read the policy: for each state, the best action is the one with the highest Q-value. This is called taking the &lt;code&gt;argmax&lt;/code&gt; of each row.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Main {
    static final int GRID_ROWS = 5;
    static final int GRID_COLS = 5;
    static final int TARGET_STATE = GRID_ROWS * GRID_COLS - 1;
    static final int NUM_ACTIONS = 4;

    static boolean isForkLiftZone(int row, int col) {
        // Define forklift zones - customize as needed
        return (row == 2 &amp;amp;&amp;amp; col == 2);
    }

    void printPolicy(double[][] qTable) {
        String[] actionSymbols = {&quot;↑&quot;, &quot;↓&quot;, &quot;←&quot;, &quot;→&quot;};
        for (int row = 0; row &amp;lt; GRID_ROWS; row++) {
            for (int col = 0; col &amp;lt; GRID_COLS; col++) {
                int state = row * GRID_COLS + col;
                if (isForkLiftZone(row, col)) { System.out.print(&quot; X &quot;); continue; }
                if (state == TARGET_STATE)    { System.out.print(&quot; T &quot;); continue; }
                int bestAction = 0;
                for (int a = 1; a &amp;lt; NUM_ACTIONS; a++) {
                    if (qTable[state][a] &amp;gt; qTable[state][bestAction]) bestAction = a;
                }
                System.out.print(&quot; &quot; + actionSymbols[bestAction] + &quot; &quot;);
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        double[][] qTable = new double[GRID_ROWS * GRID_COLS][NUM_ACTIONS];
        main.printPolicy(qTable);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Expected output after 500 episodes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; → → → → ↓
 → X → → ↓
 → → → X ↓
 → X → → ↓
 → → → → T
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The robot learned to hug the right side and travel down — exactly the optimal path!&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Full Java Implementation&lt;/h2&gt;
&lt;p&gt;Here&#39;s the complete, self-contained warehouse robot Q-learning agent:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Arrays;
import java.util.Random;

/**
 * Warehouse Robot Q-Learning Agent
 * A 5x5 grid where a robot learns to navigate from (0,0) to (4,4)
 * while avoiding forklift collision zones.
 */
public class WarehouseRobotQLearning {

    // --- Environment Configuration ---
    static final int GRID_ROWS = 5;
    static final int GRID_COLS = 5;
    static final int NUM_STATES = GRID_ROWS * GRID_COLS;   // 25
    static final int NUM_ACTIONS = 4; // 0=UP, 1=DOWN, 2=LEFT, 3=RIGHT

    static final int START_STATE  = 0;  // (0,0) loading dock
    static final int TARGET_STATE = 24; // (4,4) storage shelf

    // Forklift collision zones: (row,col) → state index
    static final int[] FORKLIFT_ZONES = {
        1 * GRID_COLS + 1,  // (1,1) = state 6
        2 * GRID_COLS + 3,  // (2,3) = state 13
        3 * GRID_COLS + 1   // (3,1) = state 16
    };

    // --- Q-Learning Hyperparameters ---
    static final double ALPHA         = 0.1;   // Learning rate
    static final double GAMMA         = 0.95;  // Discount factor
    static final double EPSILON_START = 1.0;   // Initial exploration rate
    static final double EPSILON_MIN   = 0.01;  // Minimum exploration rate
    static final double EPSILON_DECAY = 0.995; // Decay per episode
    static final int    MAX_EPISODES  = 1000;
    static final int    MAX_STEPS     = 200;   // Max steps per episode

    // --- Reward Values ---
    static final double REWARD_TARGET   =  100.0;
    static final double REWARD_FORKLIFT =  -50.0;
    static final double REWARD_STEP     =   -1.0;
    static final double REWARD_WALL     =   -5.0;

    // Action deltas: row-change and col-change for each action
    static final int[] ROW_DELTA = {-1,  1,  0,  0}; // UP, DOWN, LEFT, RIGHT
    static final int[] COL_DELTA = { 0,  0, -1,  1};
    static final String[] ACTION_NAME = {&quot;UP&quot;, &quot;DOWN&quot;, &quot;LEFT&quot;, &quot;RIGHT&quot;};
    static final String[] ACTION_SYMBOL = {&quot;↑&quot;, &quot;↓&quot;, &quot;←&quot;, &quot;→&quot;};

    // ----------------------------------------------------------------
    //  Environment Logic
    // ----------------------------------------------------------------

    static boolean isForkLiftZone(int state) {
        for (int zone : FORKLIFT_ZONES) if (zone == state) return true;
        return false;
    }

    static int stateToRow(int state) { return state / GRID_COLS; }
    static int stateToCol(int state) { return state % GRID_COLS; }
    static int toState(int row, int col) { return row * GRID_COLS + col; }

    /**
     * Executes one action from the current state.
     * Returns: [nextState, reward, done]
     */
    static Object[] step(int currentState, int action) {
        int row = stateToRow(currentState);
        int col = stateToCol(currentState);

        int newRow = row + ROW_DELTA[action];
        int newCol = col + COL_DELTA[action];

        // Check for wall collision
        if (newRow &amp;lt; 0 || newRow &amp;gt;= GRID_ROWS || newCol &amp;lt; 0 || newCol &amp;gt;= GRID_COLS) {
            // Stay in place, pay wall penalty
            return new Object[]{currentState, REWARD_WALL, false};
        }

        int nextState = toState(newRow, newCol);

        // Check for forklift zone
        if (isForkLiftZone(nextState)) {
            return new Object[]{nextState, REWARD_FORKLIFT, true}; // Episode ends
        }

        // Check for target reached
        if (nextState == TARGET_STATE) {
            return new Object[]{nextState, REWARD_TARGET, true}; // Episode ends
        }

        // Normal step
        return new Object[]{nextState, REWARD_STEP, false};
    }

    // ----------------------------------------------------------------
    //  Policy: Epsilon-Greedy Action Selection
    // ----------------------------------------------------------------

    static int chooseAction(double[][] qTable, int state, double epsilon, Random rng) {
        if (rng.nextDouble() &amp;lt; epsilon) {
            return rng.nextInt(NUM_ACTIONS); // Explore
        }
        // Exploit: find action with max Q-value
        int bestAction = 0;
        for (int a = 1; a &amp;lt; NUM_ACTIONS; a++) {
            if (qTable[state][a] &amp;gt; qTable[state][bestAction]) {
                bestAction = a;
            }
        }
        return bestAction;
    }

    // ----------------------------------------------------------------
    //  Q-Table Update (Bellman Equation)
    // ----------------------------------------------------------------

    static void updateQTable(double[][] qTable, int state, int action,
                              double reward, int nextState) {
        double bestNextQ = Arrays.stream(qTable[nextState]).max().getAsDouble();
        double tdError = reward + GAMMA * bestNextQ - qTable[state][action];
        qTable[state][action] += ALPHA * tdError;
    }

    // ----------------------------------------------------------------
    //  Training Loop
    // ----------------------------------------------------------------

    static double[][] train(Random rng) {
        double[][] qTable = new double[NUM_STATES][NUM_ACTIONS]; // All zeros
        double epsilon = EPSILON_START;

        System.out.println(&quot;=== Starting Training ===&quot;);
        System.out.printf(&quot;%-10s %-12s %-12s %-10s%n&quot;,
                          &quot;Episode&quot;, &quot;Total Reward&quot;, &quot;Steps Taken&quot;, &quot;Epsilon&quot;);
        System.out.println(&quot;-&quot;.repeat(50));

        for (int episode = 1; episode &amp;lt;= MAX_EPISODES; episode++) {
            int state = START_STATE;
            double totalReward = 0.0;
            int stepCount = 0;
            boolean done = false;

            while (!done &amp;amp;&amp;amp; stepCount &amp;lt; MAX_STEPS) {
                int action = chooseAction(qTable, state, epsilon, rng);
                Object[] result = step(state, action);

                int nextState  = (int)    result[0];
                double reward  = (double) result[1];
                boolean isDone = (boolean)result[2];

                updateQTable(qTable, state, action, reward, nextState);

                state = nextState;
                totalReward += reward;
                stepCount++;
                done = isDone;
            }

            // Decay epsilon after each episode
            epsilon = Math.max(EPSILON_MIN, epsilon * EPSILON_DECAY);

            // Log progress at key episodes
            if (episode == 1 || episode == 50 || episode == 100 ||
                episode == 250 || episode == 500 || episode == MAX_EPISODES) {
                System.out.printf(&quot;%-10d %-12.1f %-12d %-10.4f%n&quot;,
                                  episode, totalReward, stepCount, epsilon);
            }
        }
        return qTable;
    }

    // ----------------------------------------------------------------
    //  Policy Extraction and Visualization
    // ----------------------------------------------------------------

    static void printPolicy(double[][] qTable) {
        System.out.println(&quot;\n=== Learned Policy ===&quot;);
        System.out.println(&quot;(S=Start, T=Target, X=Forklift Zone)\n&quot;);
        for (int row = 0; row &amp;lt; GRID_ROWS; row++) {
            for (int col = 0; col &amp;lt; GRID_COLS; col++) {
                int state = toState(row, col);
                if (state == START_STATE)  { System.out.print(&quot; S &quot;); continue; }
                if (state == TARGET_STATE)  { System.out.print(&quot; T &quot;); continue; }
                if (isForkLiftZone(state)) { System.out.print(&quot; X &quot;); continue; }

                int bestAction = 0;
                for (int a = 1; a &amp;lt; NUM_ACTIONS; a++) {
                    if (qTable[state][a] &amp;gt; qTable[state][bestAction]) bestAction = a;
                }
                System.out.print(&quot; &quot; + ACTION_SYMBOL[bestAction] + &quot; &quot;);
            }
            System.out.println();
        }
    }

    static void printQTableSnapshot(double[][] qTable, int episode) {
        System.out.println(&quot;\n--- Q-Table Snapshot (Episode &quot; + episode + &quot;) ---&quot;);
        System.out.printf(&quot;%-8s %-8s %-8s %-8s %-8s%n&quot;,
                          &quot;State&quot;, &quot;UP&quot;, &quot;DOWN&quot;, &quot;LEFT&quot;, &quot;RIGHT&quot;);
        System.out.println(&quot;-&quot;.repeat(48));
        for (int s = 0; s &amp;lt; NUM_STATES; s++) {
            System.out.printf(&quot;%-8d %-8.3f %-8.3f %-8.3f %-8.3f%n&quot;,
                s, qTable[s][0], qTable[s][1], qTable[s][2], qTable[s][3]);
        }
    }

    // ----------------------------------------------------------------
    //  Main
    // ----------------------------------------------------------------

    public static void main(String[] args) {
        Random rng = new Random(42); // Fixed seed for reproducibility
        double[][] qTable = train(rng);

        printPolicy(qTable);
        printQTableSnapshot(qTable, MAX_EPISODES);

        // Demonstrate the learned path
        System.out.println(&quot;\n=== Robot&#39;s Learned Path from Start to Target ===&quot;);
        int state = START_STATE;
        int steps = 0;
        while (state != TARGET_STATE &amp;amp;&amp;amp; steps &amp;lt; 30) {
            int row = stateToRow(state);
            int col = stateToCol(state);
            int bestAction = 0;
            for (int a = 1; a &amp;lt; NUM_ACTIONS; a++) {
                if (qTable[state][a] &amp;gt; qTable[state][bestAction]) bestAction = a;
            }
            System.out.printf(&quot;  State %2d (%d,%d) → Action: %-6s%n&quot;,
                              state, row, col, ACTION_NAME[bestAction]);
            Object[] result = step(state, bestAction);
            state = (int) result[0];
            steps++;
        }
        System.out.printf(&quot;  State %2d (%d,%d) → TARGET REACHED in %d steps!%n&quot;,
                          state, stateToRow(state), stateToCol(state), steps);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Sample Output&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;=== Starting Training ===
Episode    Total Reward Steps Taken  Epsilon   
--------------------------------------------------
1          -54.0        4            0.9950
50         -47.0        48           0.7783
100        -18.0        19           0.6050
250        -10.0        11           0.2873
500        8.0          9            0.0823
1000       91.0         9            0.0100

=== Learned Policy ===
(S=Start, T=Target, X=Forklift Zone)

 S  →  →  ↓  ↓ 
 →  X  →  ↓  ↓ 
 →  →  →  X  ↓ 
 →  X  →  →  ↓ 
 →  →  →  →  T 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how &lt;strong&gt;Total Reward climbs from -54 to +91&lt;/strong&gt; across 1000 episodes, and &lt;strong&gt;Steps Taken drops from 48 to 9&lt;/strong&gt; — the robot isn&#39;t just reaching the goal more often, it&#39;s finding a near-optimal route.&lt;/p&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;Q-Table Convergence: How Values Change Over Episodes&lt;/h3&gt;
  &lt;pre style=&quot;font-family: monospace; font-size: 0.8em; line-height: 1.7;&quot;&gt;State 0 (Start) — Best Action: RIGHT
─────────────────────────────────────────────
Episode   1:  UP=0.000  DOWN=0.000  LEFT=0.000  RIGHT=0.000
Episode  50:  UP=0.021  DOWN=0.134  LEFT=-0.120  RIGHT=0.289
Episode 500:  UP=0.412  DOWN=2.310  LEFT=-0.830  RIGHT=4.920
Episode 1000: UP=0.721  DOWN=4.110  LEFT=-1.204  RIGHT=18.43 ← RIGHT wins!

State 19 (one step left of target) — Best Action: RIGHT
─────────────────────────────────────────────
Episode   1:  All zeros
Episode  50:  RIGHT=0.045 (barely discovered)
Episode 500:  RIGHT=65.23 (strong signal — target is close!)
Episode 1000: RIGHT=94.87 (nearly +100 reward, discounted once)
  &lt;/pre&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;Q-values near the target converge first — the reward signal radiates outward from the goal like ripples from a stone dropped in water. Early states (like Start) take many more episodes to accumulate accurate estimates because the +100 reward must be discounted across all the intervening steps before it reaches them.&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;
&lt;h2&gt;Common Pitfalls and Debugging&lt;/h2&gt;
&lt;h3&gt;1. Reward Shaping Mistakes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; You give a large negative reward for &lt;em&gt;every&lt;/em&gt; wall bump, but forget the agent is trapped against a wall — it keeps bumping and accumulates catastrophic negative rewards, never recovering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Make wall bumps mildly negative (not catastrophic), and ensure the episode doesn&#39;t end on wall bumps. The robot should learn &quot;walls are bad&quot; naturally through the cumulative time penalty.&lt;/p&gt;
&lt;h3&gt;2. Learning Rate Woes&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;badge badge-danger&quot;&gt;α too high (0.9)&lt;/span&gt; Values oscillate — the agent &quot;forgets&quot; good experiences because each new update overwrites them aggressively.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;badge badge-warning&quot;&gt;α too low (0.001)&lt;/span&gt; Thousands of episodes produce barely any change. The robot acts nearly randomly for too long.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;badge badge-success&quot;&gt;α just right (0.05–0.2)&lt;/span&gt; Steady, smooth convergence. Values creep toward optimal over hundreds of episodes.&lt;/p&gt;
&lt;h3&gt;3. Discount Factor Edge Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;γ = 0:&lt;/strong&gt; The robot is completely greedy. It&#39;ll pick up a +5 reward right next to it and ignore the +100 target 8 steps away. Useless for navigation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;γ = 1:&lt;/strong&gt; Every future reward is worth exactly as much as an immediate one. This can cause instability in environments with long episodes and no terminal state, as Q-values grow unboundedly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;γ = 0.95:&lt;/strong&gt; Sweet spot. A reward 20 steps away is worth 0.95²⁰ ≈ 36% of its face value — far enough to plan ahead, but decayed enough to prefer shorter paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. The Q-Table Never Converges&lt;/h3&gt;
&lt;p&gt;If your Q-values are still wildly different between episodes after 10,000 runs, check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Epsilon isn&#39;t decaying:&lt;/strong&gt; If ε stays high, the agent keeps exploring randomly and never exploits its learned knowledge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment is non-deterministic without proper handling:&lt;/strong&gt; If transitions are stochastic but you&#39;re using a low α, the noise drowns the signal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Max steps too low:&lt;/strong&gt; The agent can&#39;t reach the target before the episode terminates, so it never receives the positive terminal reward.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Main {
    static final int NUM_STATES = 10;
    static final int NUM_ACTIONS = 4;
    static double[][] qTable = new double[NUM_STATES][NUM_ACTIONS];
    static double[][] previousQTable = new double[NUM_STATES][NUM_ACTIONS];

    public static void main(String[] args) {
        int episode = 1;
        // Debugging tip: track TD error magnitude over episodes
        // If it plateaus above 1.0 after 1000 episodes, something is wrong
        double avgTDError = 0.0;
        for (int s = 0; s &amp;lt; NUM_STATES; s++) {
            for (int a = 0; a &amp;lt; NUM_ACTIONS; a++) {
                // Compare current estimates to previous episode&#39;s estimates
                avgTDError += Math.abs(qTable[s][a] - previousQTable[s][a]);
            }
        }
        System.out.printf(&quot;Episode %d | Avg Q-Change: %.4f%n&quot;, episode, avgTDError / (NUM_STATES * NUM_ACTIONS));
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Limitations and the Bridge to Deep Q-Networks&lt;/h2&gt;
&lt;h3&gt;The State Space Explosion&lt;/h3&gt;
&lt;p&gt;Q-tables work beautifully when states are countable and small. Our warehouse had 25 states. But consider:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;States&lt;/th&gt;
&lt;th&gt;Q-Table Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5×5 Warehouse&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;badge badge-success&quot;&gt;100 cells&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20×20 Maze&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;badge badge-success&quot;&gt;1,600 cells&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Atari Pong (raw pixels)&lt;/td&gt;
&lt;td&gt;~10⁶&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;badge badge-warning&quot;&gt;~4M cells&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autonomous Driving&lt;/td&gt;
&lt;td&gt;~10¹⁸&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;badge badge-danger&quot;&gt;Impossible&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chess&lt;/td&gt;
&lt;td&gt;~10⁴⁷&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;badge badge-danger&quot;&gt;More than atoms in universe&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For real-world problems, you can&#39;t store every state explicitly. The Q-table hits a wall — and unlike our robot, it can&#39;t recover from it.&lt;/p&gt;
&lt;h3&gt;The DQN Solution&lt;/h3&gt;
&lt;p&gt;Instead of a giant lookup table, a &lt;strong&gt;Deep Q-Network (DQN)&lt;/strong&gt; uses a neural network as a &lt;em&gt;function approximator&lt;/em&gt;. The key insight: similar states should have similar Q-values. A neural network can learn that pattern and &lt;em&gt;generalize&lt;/em&gt; — estimating Q-values for states it has never seen before, based on states it has.&lt;/p&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;Q-Table vs. Deep Q-Network&lt;/h3&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Input: State s (grid position)&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Q-Table: lookup row s&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Output: Q-values for all 4 actions&lt;/div&gt;
  &lt;/div&gt;
  &lt;div style=&quot;color: #666666; font-size: 0.9em; margin: 0.5em 0px;&quot;&gt;vs.&lt;/div&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Input: State s (raw pixels, sensor data…)&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;Neural Network (Conv layers, Dense layers)&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;Output: Q-values for all actions&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;DQN replaces the table with a neural network. The network &lt;em&gt;generalizes&lt;/em&gt; — states it has never seen get reasonable Q-value estimates based on similar states it &lt;em&gt;has&lt;/em&gt; seen. The Bellman update becomes a supervised training signal for the network weights instead of a direct table write.&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;When Q-Tables Are Still the Right Tool&lt;/h3&gt;
&lt;p&gt;Don&#39;t reach for a neural network when you don&#39;t need one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;badge badge-success&quot;&gt;Small state spaces&lt;/span&gt; Under ~10,000 states — pure Q-table wins on simplicity and interpretability&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;badge badge-success&quot;&gt;Tabular data problems&lt;/span&gt; Game solvers for small board games (Tic-Tac-Toe has 5,478 states)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;badge badge-success&quot;&gt;Teaching/prototyping&lt;/span&gt; Always start with a Q-table to validate your reward structure before scaling up&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;badge badge-warning&quot;&gt;Medium spaces&lt;/span&gt; Consider tile coding or state aggregation to compress the table&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;badge badge-danger&quot;&gt;High-dimensional inputs&lt;/span&gt; Raw images, continuous sensor arrays — go straight to DQN&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Recap: The 5 Steps&lt;/h2&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;5 Steps to Master Q-Learning&lt;/h3&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;1. Define Environment&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;2. Initialize Q-Table&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;3. ε-Greedy Policy&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;4. Episode Loop + Bellman Update&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;5. Extract Policy&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;Each step builds on the last. The magic happens in Step 4 — thousands of small Bellman corrections accumulate into a table of hard-won wisdom.&lt;/div&gt;
&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Define your environment&lt;/strong&gt; — states, actions, and reward signals carefully&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Initialize the Q-Table&lt;/strong&gt; to zeros and track your hyperparameters (α, γ, ε)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement epsilon-greedy&lt;/strong&gt; — start with full exploration and decay toward exploitation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run episodes&lt;/strong&gt; — each step applies the Bellman update, propagating reward signals backwards&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extract the policy&lt;/strong&gt; — read the &lt;code&gt;argmax&lt;/code&gt; of each row; that&#39;s the learned strategy&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The Q-Table is one of AI&#39;s most elegant ideas: a simple matrix that emerges from experience to encode optimal behavior. It&#39;s the foundation everything from game-playing AIs to robotics schedulers is built on — and now you can build it yourself.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;Want to go further? In the next post, we&#39;ll extend this exact warehouse robot to use a neural network for the Q-function — turning our Q-Table agent into a full Deep Q-Network (DQN) that can handle environments 1,000x larger.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2026/07/q-table-explained-5-steps-to-master.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEhRry6DJm7y2n0LGtxBo__3mZP7NGQbGtZ4cWR7TNOAMl84_VSGvAqhYM7WFdFjMVJooVu19YcZL6AErPnXsVVpO1CR-CENihhnGKXwenqiHOML_j3MS6o6koPK7izecel0u6mTOjHDpqGA49FEervOrNGH8bcxkxDxH6xdmxnHyIp4OLluFhhAJxYU86U=s72-w640-h336-c" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5456118122792900748</guid><pubDate>Fri, 24 Jul 2026 15:15:19 +0000</pubDate><atom:updated>2026-07-25T00:44:43.344+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">C</category><category domain="http://www.blogger.com/atom/ns#">C++</category><category domain="http://www.blogger.com/atom/ns#">Finite State Machine</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">NLP</category><category domain="http://www.blogger.com/atom/ns#">Regular Expressions</category><category domain="http://www.blogger.com/atom/ns#">Sentence Segmentation</category><category domain="http://www.blogger.com/atom/ns#">Text Processing</category><title>Four Ways to Split Sentences (Without Machine Learning)</title><description>&lt;style&gt;
    .post-body {
      font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
      line-height: 1.6;
      color: #24292e;
      max-width: 860px;
      margin: 0 auto;
      padding: 20px;
    }
    .post-body h1, .post-body h2, .post-body h3 {
      color: #0366d6;
      border-bottom: 1px solid #eaecef;
      padding-bottom: 0.3em;
      margin-top: 1.5em;
    }
    .post-body p { margin-bottom: 1em; }
    .post-body pre {
      background-color: #1e1e1e;
      color: #d4d4d4;
      padding: 16px;
      border-radius: 6px;
      overflow-x: auto;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 0.9em;
      line-height: 1.45;
    }
    .post-body code {
      background-color: #f6f8fa;
      color: #d73a49;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 85%;
    }
    .post-body pre code { background-color: transparent; color: inherit; padding: 0; }
    .post-body table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
      font-size: 0.95em;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
      border-radius: 6px;
      overflow: hidden;
    }
    .post-body th, .post-body td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #dddddd; }
    .post-body th { background-color: #0366d6; color: #ffffff; font-weight: 600; }
    .post-body tr:nth-of-type(even) { background-color: #f8f9fa; }
    .post-body tr:hover { background-color: #f1f3f5; }
    .post-body blockquote {
      margin: 1.5em 0;
      padding: 1em 1.2em;
      background-color: #f1f8ff;
      border-left: 4px solid #0366d6;
      color: #24292e;
      border-radius: 0 6px 6px 0;
    }
    .post-body ul, .post-body ol { padding-left: 20px; margin-bottom: 1em; }
    .post-body li { margin-bottom: 0.4em; }
    .post-body hr { border: 0; height: 1px; background: #e1e4e8; margin: 2em 0; }
    
    /* Visual Enhancement Components */
    .post-body .diagram-container {
      background-color: #ffffff;
      border: 1px solid #e1e4e8;
      border-radius: 8px;
      padding: 20px;
      margin: 25px 0;
      box-shadow: 0 2px 6px rgba(0,0,0,0.04);
      text-align: center;
    }
    .post-body .diagram-caption {
      font-size: 0.85em;
      color: #586069;
      margin-top: 10px;
      font-style: italic;
    }
    .post-body .pipeline-flow {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: center;
      gap: 10px;
      margin: 20px 0;
    }
    .post-body .pipeline-step {
      background: #f1f8ff;
      border: 1px solid #0366d6;
      color: #0366d6;
      padding: 10px 16px;
      border-radius: 20px;
      font-weight: bold;
      font-size: 0.9em;
    }
    .post-body .pipeline-step.highlight {
      background: #0366d6;
      color: #ffffff;
      box-shadow: 0 2px 4px rgba(3,102,214,0.3);
    }
    .post-body .pipeline-arrow {
      color: #586069;
      font-weight: bold;
    }
    .post-body .badge {
      display: inline-block;
      padding: 2px 8px;
      font-size: 0.75em;
      font-weight: 600;
      border-radius: 12px;
      margin-left: 6px;
    }
    .post-body .badge-success { background: #dcffe4; color: #1a7f37; }
    .post-body .badge-danger { background: #ffebe9; color: #cf222e; }
    .post-body .badge-warning { background: #fff8c5; color: #9a6700; }
&lt;/style&gt;

&lt;div class=&quot;post-body&quot;&gt;
&lt;p&gt;Imagine you hand someone a giant wall of text — no paragraph breaks, no structure — and ask them to read it aloud naturally. They&#39;d instinctively pause at every period, question mark, or exclamation point[cite: 1]. That pause, that boundary between thoughts, is what &lt;strong&gt;sentence splitting&lt;/strong&gt; (also called &lt;em&gt;sentence boundary detection&lt;/em&gt; or &lt;em&gt;sentence segmentation&lt;/em&gt;) is all about[cite: 1].&lt;/p&gt;
  
  &lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjbeBd_-JCQ8ajgkeaeRp3lqxhZl_wunUXyl0zkRS03zPIRZB9b4NkP1l9Kcxu7Qh3kg6vEC6UCj-60n4LPe_-eTqCnhv_utnzFCwk-aLD6G7dm168RTjzVxIErzCBFn-D9ZfapDy9HpR9b63FENbBhnK4axs6Crz72OoIrYjaA57-7M7kC9cq_60oTcj8&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;630&quot; data-original-width=&quot;1200&quot; height=&quot;336&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjbeBd_-JCQ8ajgkeaeRp3lqxhZl_wunUXyl0zkRS03zPIRZB9b4NkP1l9Kcxu7Qh3kg6vEC6UCj-60n4LPe_-eTqCnhv_utnzFCwk-aLD6G7dm168RTjzVxIErzCBFn-D9ZfapDy9HpR9b63FENbBhnK4axs6Crz72OoIrYjaA57-7M7kC9cq_60oTcj8=w640-h336&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;

  &lt;div class=&quot;diagram-container&quot;&gt;&lt;h3&gt;Sentence Splitting in the NLP Pipeline&lt;/h3&gt;
  &lt;div class=&quot;pipeline-flow&quot;&gt;
    &lt;div class=&quot;pipeline-step highlight&quot;&gt;1. Sentence Splitting&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;2. Tokenization&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;3. POS Tagging&lt;/div&gt;
    &lt;span class=&quot;pipeline-arrow&quot;&gt;→&lt;/span&gt;
    &lt;div class=&quot;pipeline-step&quot;&gt;4. Parsing / Translation&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;Sentence segmentation acts as the foundational preprocessing stage for downstream NLP tasks.&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In NLP pipelines, sentence splitting is often the very first step before anything else — tokenization, parsing, translation, summarization[cite: 1]. If you get it wrong, everything downstream suffers[cite: 1].&lt;/p&gt;
&lt;p&gt;The good news? You don&#39;t always need a neural network to do it well[cite: 1]. In this post, we&#39;ll explore &lt;strong&gt;four classical, rule-based approaches&lt;/strong&gt; to sentence splitting — from the simplest one-liner to surprisingly robust heuristic systems — all without a single line of machine learning[cite: 1].&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Why Is Sentence Splitting Hard?&lt;/h2&gt;
&lt;p&gt;Before diving in, let&#39;s appreciate why this isn&#39;t trivial[cite: 1]. Consider these tricky cases[cite: 1]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;Dr. Smith went to Washington D.C. last Monday.&quot;&lt;/code&gt; &lt;span class=&quot;badge badge-danger&quot;&gt;3 Periods • 1 Sentence&lt;/span&gt; — Multiple periods within honorifics and city names[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;She asked, \&quot;Are you coming?\&quot; He nodded.&quot;&lt;/code&gt; &lt;span class=&quot;badge badge-warning&quot;&gt;2 Sentences&lt;/span&gt; — Nested punctuation inside direct quotation marks[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;The price is $1.99. Buy now!&quot;&lt;/code&gt; &lt;span class=&quot;badge badge-danger&quot;&gt;1 Decimal • 2 Sentences&lt;/span&gt; — Decimal point within currency[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;I work at A.I. Corp. We build robots.&quot;&lt;/code&gt; &lt;span class=&quot;badge badge-warning&quot;&gt;2 Sentences&lt;/span&gt; — Abbreviation ending directly at sentence boundary[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;...and that&#39;s it.&quot;&lt;/code&gt; &lt;span class=&quot;badge badge-danger&quot;&gt;Ellipsis&lt;/span&gt; — Multi-period sequences[cite: 1].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A naïve &quot;split on period&quot; approach would butcher all of these[cite: 1]. Each method we explore will get progressively better at handling such edge cases[cite: 1].&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Method 1: Naïve Punctuation Split&lt;/h2&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;The simplest possible approach: split the text every time you see &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, or &lt;code&gt;!&lt;/code&gt;[cite: 1].&lt;/p&gt;
&lt;p&gt;Think of it like cutting a ribbon every time you see a knot[cite: 1]. Fast, simple — but sometimes you cut in the wrong place[cite: 1].&lt;/p&gt;

&lt;!--Naive Execution Visualization--&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;Naïve splitting truncates honorifics like &quot;Dr.&quot; as isolated sentences[cite: 1].&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Java Implementation&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Arrays;
import java.util.List;

public class NaiveSentenceSplitter {

    public static List&amp;lt;String&amp;gt; split(String text) {
        // Split on . ? or ! followed by one or more spaces
        String[] parts = text.split(&quot;(?&amp;lt;=[.?!])\\s+&quot;);
        return Arrays.asList(parts);
    }

    public static void main(String[] args) {
        String text = &quot;Hello world. How are you? I am fine! Thanks.&quot;;
        List&amp;lt;String&amp;gt; sentences = split(text);
        for (String s : sentences) {
            System.out.println(&quot;|&quot; + s + &quot;|&quot;);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;|Hello world.|
|How are you?|
|I am fine!|
|Thanks.|
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Looks perfect for clean text[cite: 1]. But watch what happens with abbreviations[cite: 1]:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;String tricky = &quot;Dr. Smith lives on Oak St. He owns a cat.&quot;;
// Output:
// |Dr.|
// |Smith lives on Oak St.|
// |He owns a cat.|
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oops[cite: 1]. &lt;code&gt;Dr.&lt;/code&gt; got split off as its own sentence[cite: 1].&lt;/p&gt;

&lt;h3&gt;When to Use It&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Clean, well-formatted text (e.g., generated text, templates)[cite: 1]&lt;/li&gt;
&lt;li&gt;Quick prototyping when accuracy isn&#39;t critical[cite: 1]&lt;/li&gt;
&lt;li&gt;Pre-processing step before a smarter method[cite: 1]&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;Method 2: Abbreviation-Aware Splitting&lt;/h2&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;The naïve method fails because it doesn&#39;t know that certain words followed by a period are &lt;em&gt;abbreviations&lt;/em&gt;, not sentence endings[cite: 1]. The fix: maintain a &lt;strong&gt;blocklist of known abbreviations&lt;/strong&gt; and skip splitting when the period belongs to one[cite: 1].&lt;/p&gt;
&lt;p&gt;This is like a train conductor who knows certain stops are &quot;request stops&quot; — the train doesn&#39;t halt there unless specifically needed[cite: 1].&lt;/p&gt;

&lt;!--Abbreviation Logic Flowchart--&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;svg style=&quot;height: auto; max-width: 100%;&quot; viewbox=&quot;0 0 650 180&quot;&gt;
    &lt;g font-family=&quot;-apple-system, sans-serif&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;
      &lt;rect fill=&quot;#f1f8ff&quot; height=&quot;40&quot; rx=&quot;20&quot; stroke=&quot;#0366d6&quot; width=&quot;120&quot; x=&quot;10&quot; y=&quot;70&quot;&gt;
      &lt;text fill=&quot;#0366d6&quot; x=&quot;70&quot; y=&quot;94&quot;&gt;Read Char &#39;.&#39;&lt;/text&gt;
      
      &lt;line marker-end=&quot;url(#arrow)&quot; stroke-width=&quot;2&quot; stroke=&quot;#586069&quot; x1=&quot;130&quot; x2=&quot;170&quot; y1=&quot;90&quot; y2=&quot;90&quot;&gt;
      
      &lt;polygon fill=&quot;#fff8c5&quot; points=&quot;230,50 290,90 230,130 170,90&quot; stroke=&quot;#9a6700&quot;&gt;
      &lt;text fill=&quot;#9a6700&quot; x=&quot;230&quot; y=&quot;88&quot;&gt;Extract preceding&lt;/text&gt;
      &lt;text fill=&quot;#9a6700&quot; x=&quot;230&quot; y=&quot;100&quot;&gt;word&lt;/text&gt;

      &lt;line stroke-width=&quot;2&quot; stroke=&quot;#586069&quot; x1=&quot;290&quot; x2=&quot;330&quot; y1=&quot;90&quot; y2=&quot;90&quot;&gt;
      
      &lt;polygon fill=&quot;#fff8c5&quot; points=&quot;390,50 450,90 390,130 330,90&quot; stroke=&quot;#9a6700&quot;&gt;
      &lt;text fill=&quot;#9a6700&quot; x=&quot;390&quot; y=&quot;88&quot;&gt;Is word in&lt;/text&gt;
      &lt;text fill=&quot;#9a6700&quot; x=&quot;390&quot; y=&quot;100&quot;&gt;abbrev set?&lt;/text&gt;

      &lt;line stroke-width=&quot;2&quot; stroke=&quot;#cf222e&quot; x1=&quot;390&quot; x2=&quot;390&quot; y1=&quot;50&quot; y2=&quot;25&quot;&gt;
      &lt;line stroke-width=&quot;2&quot; stroke=&quot;#cf222e&quot; x1=&quot;390&quot; x2=&quot;520&quot; y1=&quot;25&quot; y2=&quot;25&quot;&gt;
      &lt;rect fill=&quot;#ffebe9&quot; height=&quot;40&quot; rx=&quot;6&quot; stroke=&quot;#cf222e&quot; width=&quot;110&quot; x=&quot;520&quot; y=&quot;5&quot;&gt;
      &lt;text fill=&quot;#cf222e&quot; x=&quot;575&quot; y=&quot;28&quot;&gt;SKIP SPLIT&lt;/text&gt;
      &lt;text fill=&quot;#cf222e&quot; font-size=&quot;10&quot; x=&quot;350&quot; y=&quot;38&quot;&gt;YES (e.g., &quot;Dr&quot;)&lt;/text&gt;

      &lt;line stroke-width=&quot;2&quot; stroke=&quot;#1a7f37&quot; x1=&quot;450&quot; x2=&quot;520&quot; y1=&quot;90&quot; y2=&quot;90&quot;&gt;
      &lt;rect fill=&quot;#dcffe4&quot; height=&quot;40&quot; rx=&quot;6&quot; stroke=&quot;#1a7f37&quot; width=&quot;110&quot; x=&quot;520&quot; y=&quot;70&quot;&gt;
      &lt;text fill=&quot;#1a7f37&quot; x=&quot;575&quot; y=&quot;94&quot;&gt;EMIT SENTENCE&lt;/text&gt;
      &lt;text fill=&quot;#1a7f37&quot; font-size=&quot;10&quot; x=&quot;480&quot; y=&quot;82&quot;&gt;NO&lt;/text&gt;
    &lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/line&gt;&lt;/polygon&gt;&lt;/line&gt;&lt;/polygon&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/g&gt;
  &lt;/svg&gt;
  &lt;div class=&quot;diagram-caption&quot;&gt;Abbreviation lookup workflow preventing invalid sentence splits[cite: 1].&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;C++ Implementation&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;sstream&amp;gt;
#include &amp;lt;unordered_set&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;cctype&amp;gt;

// Lowercase a string
std::string toLower(const std::string&amp;amp; s) {
    std::string result = s;
    std::transform(result.begin(), result.end(), result.begin(), ::tolower);
    return result;
}

// Known abbreviations (lowercase, without the period)
std::unordered_set&amp;lt;std::string&amp;gt; ABBREVIATIONS = {
    &quot;dr&quot;, &quot;mr&quot;, &quot;mrs&quot;, &quot;ms&quot;, &quot;prof&quot;, &quot;sr&quot;, &quot;jr&quot;,
    &quot;st&quot;, &quot;ave&quot;, &quot;blvd&quot;, &quot;dept&quot;, &quot;approx&quot;, &quot;vs&quot;,
    &quot;etc&quot;, &quot;e.g&quot;, &quot;i.e&quot;, &quot;fig&quot;, &quot;jan&quot;, &quot;feb&quot;,
    &quot;mar&quot;, &quot;apr&quot;, &quot;jun&quot;, &quot;jul&quot;, &quot;aug&quot;, &quot;sep&quot;,
    &quot;oct&quot;, &quot;nov&quot;, &quot;dec&quot;, &quot;no&quot;, &quot;vol&quot;, &quot;pp&quot;
};

std::vector&amp;lt;std::string&amp;gt; splitSentences(const std::string&amp;amp; text) {
    std::vector&amp;lt;std::string&amp;gt; sentences;
    std::string current;
    int n = text.size();

    for (int i = 0; i &amp;lt; n; i++) {
        current += text[i];

        // Check if we&#39;re at a sentence-ending punctuation
        if (text[i] == &#39;.&#39; || text[i] == &#39;?&#39; || text[i] == &#39;!&#39;) {

            // Look ahead: is the next character a space followed by uppercase?
            if (i + 2 &amp;lt; n &amp;amp;&amp;amp; text[i + 1] == &#39; &#39; &amp;amp;&amp;amp;
                std::isupper((unsigned char)text[i + 2])) {

                // Extract the word just before the period
                std::string word;
                int j = current.size() - 2; // -2 to skip the period we just added
                while (j &amp;gt;= 0 &amp;amp;&amp;amp; current[j] != &#39; &#39;) {
                    word = current[j] + word;
                    j--;
                }

                // Check if it&#39;s a known abbreviation
                if (ABBREVIATIONS.count(toLower(word)) == 0) {
                    // Not an abbreviation — it&#39;s a sentence boundary!
                    sentences.push_back(current);
                    current = &quot;&quot;;
                    i++; // Skip the space
                }
            }
        }
    }

    // Don&#39;t forget the last sentence
    if (!current.empty()) {
        sentences.push_back(current);
    }

    return sentences;
}

int main() {
    std::string text = &quot;Dr. Smith lives on Oak St. He owns a cat. &quot;
                       &quot;Prof. Lee moved to Washington D.C. last year.&quot;;

    auto sentences = splitSentences(text);
    for (const auto&amp;amp; s : sentences) {
        std::cout &amp;lt;&amp;lt; &quot;[&quot; &amp;lt;&amp;lt; s &amp;lt;&amp;lt; &quot;]&quot; &amp;lt;&amp;lt; std::endl;
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Dr. Smith lives on Oak St. He owns a cat.]
[Prof. Lee moved to Washington D.C. last year.]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Much better! The abbreviation list acts as a safety net for the most common offenders[cite: 1].&lt;/p&gt;

&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Your abbreviation list will never be complete[cite: 1].&lt;/li&gt;
&lt;li&gt;Single capital letters (&lt;code&gt;A.&lt;/code&gt;, &lt;code&gt;B.&lt;/code&gt;) can still trip it up[cite: 1].&lt;/li&gt;
&lt;li&gt;Doesn&#39;t handle quotes, parentheses, or numbering well[cite: 1].&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;When to Use It&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Domain-specific text where you know common abbreviations (medical, legal, scientific)[cite: 1]&lt;/li&gt;
&lt;li&gt;When you can afford to curate and maintain an abbreviation list[cite: 1]&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;Method 3: Regex-Based Heuristic Splitter&lt;/h2&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;Instead of a simple split, we use &lt;strong&gt;regular expressions&lt;/strong&gt; to encode multiple heuristic rules simultaneously[cite: 1]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A sentence ends with &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, or &lt;code&gt;!&lt;/code&gt;[cite: 1]&lt;/li&gt;
&lt;li&gt;Followed by whitespace[cite: 1]&lt;/li&gt;
&lt;li&gt;Followed by an uppercase letter or a quote/parenthesis opening a new sentence[cite: 1]&lt;/li&gt;
&lt;li&gt;BUT NOT when the word before the period is a known abbreviation or a single letter (initials)[cite: 1]&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Think of it like a traffic light system: instead of just checking one condition (&quot;is it a period?&quot;), we check multiple signals before deciding to stop[cite: 1].&lt;/p&gt;

&lt;h3&gt;Java Implementation&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.*;
import java.util.regex.*;

public class RegexSentenceSplitter {

    // These patterns will NOT trigger a split
    private static final Set&amp;lt;String&amp;gt; ABBREVIATIONS = new HashSet&amp;lt;&amp;gt;(Arrays.asList(
        &quot;dr&quot;, &quot;mr&quot;, &quot;mrs&quot;, &quot;ms&quot;, &quot;prof&quot;, &quot;sr&quot;, &quot;jr&quot;, &quot;st&quot;, &quot;ave&quot;,
        &quot;blvd&quot;, &quot;dept&quot;, &quot;approx&quot;, &quot;vs&quot;, &quot;etc&quot;, &quot;fig&quot;, &quot;no&quot;, &quot;vol&quot;
    ));

    /**
     * Returns true if the word before the period looks like an abbreviation
     * or a single initial (e.g., &quot;A.&quot;, &quot;B.&quot;)
     */
    private static boolean isAbbreviation(String word) {
        String lower = word.toLowerCase();
        if (ABBREVIATIONS.contains(lower)) return true;
        if (word.length() == 1 &amp;amp;&amp;amp; Character.isLetter(word.charAt(0))) return true; // Initials
        if (word.matches(&quot;[A-Z]([a-z]*[A-Z])+&quot;)) return true; // Acronym like &quot;U.S.A&quot;
        return false;
    }

    public static List&amp;lt;String&amp;gt; split(String text) {
        List&amp;lt;String&amp;gt; sentences = new ArrayList&amp;lt;&amp;gt;();

        // Regex: sentence boundary = punctuation + space(s) + uppercase or quote/paren
        // We use a lookahead so we don&#39;t consume the start of the next sentence
        Pattern boundary = Pattern.compile(
            &quot;(?&amp;lt;=[.?!][&#39;\&quot;]?)&quot; +   // after . ? ! optionally followed by closing quote
            &quot;\\s+&quot; +                // whitespace
            &quot;(?=[A-Z\&quot;\\(])&quot;        // before uppercase letter, quote, or open paren
        );

        // Split on candidate boundaries
        String[] candidates = boundary.split(text);

        StringBuilder current = new StringBuilder();
        for (int i = 0; i &amp;lt; candidates.length; i++) {
            String part = candidates[i];

            // Get the last word of this part (before the terminal punctuation)
            String trimmed = part.trim();
            String lastWord = &quot;&quot;;
            int lastSpace = trimmed.lastIndexOf(&#39; &#39;, trimmed.length() - 2);
            if (lastSpace &amp;gt;= 0) {
                // Remove the punctuation to get the actual word
                lastWord = trimmed.substring(lastSpace + 1);
                if (lastWord.endsWith(&quot;.&quot;) || lastWord.endsWith(&quot;?&quot;) || lastWord.endsWith(&quot;!&quot;)) {
                    lastWord = lastWord.substring(0, lastWord.length() - 1);
                }
            }

            current.append(part);

            if (isAbbreviation(lastWord)) {
                // Don&#39;t split — it&#39;s an abbreviation; keep building
                current.append(&quot; &quot;);
            } else {
                // Real sentence boundary
                sentences.add(current.toString().trim());
                current = new StringBuilder();
            }
        }

        if (current.length() &amp;gt; 0) {
            sentences.add(current.toString().trim());
        }

        return sentences;
    }

    public static void main(String[] args) {
        String text = &quot;Dr. Smith visited Washington D.C. last Monday. &quot;
                    + &quot;\&quot;Was it fun?\&quot; asked Ms. Jones. He said yes! &quot;
                    + &quot;The price was $1.99. She paid immediately.&quot;;

        List&amp;lt;String&amp;gt; sentences = split(text);
        for (int i = 0; i &amp;lt; sentences.size(); i++) {
            System.out.printf(&quot;[%d] %s%n&quot;, i + 1, sentences.get(i));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[1] Dr. Smith visited Washington D.C. last Monday.
[2] &quot;Was it fun?&quot; asked Ms. Jones.
[3] He said yes!
[4] The price was $1.99.
[5] She paid immediately.
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Breaking Down the Regex&lt;/h3&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;pre style=&quot;margin: 0px; text-align: left;&quot;&gt;&lt;code&gt;(?&amp;lt;=[.?!][&#39;&quot;]?)   — &lt;span style=&quot;color: #4ec9b0;&quot;&gt;lookbehind&lt;/span&gt;: we just passed a . ? or ! (optionally + closing quote)
\s+               — &lt;span style=&quot;color: #ce9178;&quot;&gt;whitespace&lt;/span&gt;: one or more space characters
(?=[A-Z&quot;\(])      — &lt;span style=&quot;color: #4ec9b0;&quot;&gt;lookahead&lt;/span&gt;: next char is uppercase, a quote, or open parenthesis&lt;/code&gt;
  &lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Using &lt;strong&gt;lookahead and lookbehind&lt;/strong&gt; (zero-width assertions) means we split &lt;em&gt;at the whitespace&lt;/em&gt; without consuming the surrounding characters — perfect for keeping sentence punctuation attached to the right sentence[cite: 1].&lt;/p&gt;

&lt;h3&gt;When to Use It&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;General-purpose text without extreme edge cases[cite: 1]&lt;/li&gt;
&lt;li&gt;When you want a balance of simplicity and accuracy[cite: 1]&lt;/li&gt;
&lt;li&gt;As a fast pre-processing step in an NLP pipeline[cite: 1]&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;Method 4: Finite State Machine (FSM) Splitter&lt;/h2&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;This is the most robust rule-based approach[cite: 1]. We model the sentence-splitting process as a &lt;strong&gt;Finite State Machine&lt;/strong&gt; — a system that moves through a set of states as it reads characters one by one[cite: 1].&lt;/p&gt;
&lt;p&gt;Think of it like reading a book with a bookmark and a set of sticky notes[cite: 1]. Each sticky note represents a &quot;state&quot; you&#39;re currently in (e.g., &lt;em&gt;inside a quote&lt;/em&gt;, &lt;em&gt;just saw a period&lt;/em&gt;, &lt;em&gt;inside a number&lt;/em&gt;)[cite: 1]. As you read each character, you check your current state and decide whether to move to a new state[cite: 1].&lt;/p&gt;

&lt;!--FSM Interactive Visualization Widget Placeholder--&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;h3&gt;Interactive State Machine Transition Diagram&lt;/h3&gt;
  &lt;p style=&quot;color: #586069; font-size: 0.9em;&quot;&gt;This visual models how character input triggers state shifts in real time:&lt;/p&gt;
  
  &lt;svg style=&quot;height: auto; max-width: 100%;&quot; viewbox=&quot;0 0 600 240&quot;&gt;
    &lt;g font-family=&quot;-apple-system, sans-serif&quot; font-size=&quot;11&quot; text-anchor=&quot;middle&quot;&gt;
      &lt;!--State NORMAL--&gt;
      &lt;circle cx=&quot;120&quot; cy=&quot;120&quot; fill=&quot;#f1f8ff&quot; r=&quot;45&quot; stroke-width=&quot;2&quot; stroke=&quot;#0366d6&quot;&gt;
      &lt;text fill=&quot;#0366d6&quot; font-weight=&quot;bold&quot; x=&quot;120&quot; y=&quot;124&quot;&gt;NORMAL&lt;/text&gt;
      
      &lt;!--State AFTER_TERMINAL--&gt;
      &lt;circle cx=&quot;300&quot; cy=&quot;50&quot; fill=&quot;#fff8c5&quot; r=&quot;40&quot; stroke-width=&quot;2&quot; stroke=&quot;#9a6700&quot;&gt;
      &lt;text fill=&quot;#9a6700&quot; font-weight=&quot;bold&quot; x=&quot;300&quot; y=&quot;48&quot;&gt;AFTER&lt;/text&gt;
      &lt;text fill=&quot;#9a6700&quot; font-weight=&quot;bold&quot; x=&quot;300&quot; y=&quot;60&quot;&gt;TERMINAL&lt;/text&gt;
      
      &lt;!--State IN_QUOTE--&gt;
      &lt;circle cx=&quot;300&quot; cy=&quot;190&quot; fill=&quot;#f6f8fa&quot; r=&quot;40&quot; stroke-width=&quot;2&quot; stroke=&quot;#586069&quot;&gt;
      &lt;text fill=&quot;#586069&quot; font-weight=&quot;bold&quot; x=&quot;300&quot; y=&quot;194&quot;&gt;IN_QUOTE&lt;/text&gt;
      
      &lt;!--State BOUNDARY/EMIT--&gt;
      &lt;circle cx=&quot;480&quot; cy=&quot;120&quot; fill=&quot;#dcffe4&quot; r=&quot;45&quot; stroke-width=&quot;2&quot; stroke=&quot;#1a7f37&quot;&gt;
      &lt;circle cx=&quot;480&quot; cy=&quot;120&quot; fill=&quot;none&quot; r=&quot;39&quot; stroke-width=&quot;1&quot; stroke=&quot;#1a7f37&quot;&gt;
      &lt;text fill=&quot;#1a7f37&quot; font-weight=&quot;bold&quot; x=&quot;480&quot; y=&quot;124&quot;&gt;EMIT SENTENCE&lt;/text&gt;

      &lt;!--Transitions--&gt;
      &lt;!--NORMAL -&gt; AFTER_TERMINAL--&gt;
      &lt;path d=&quot;M 155 95 Q 210 40 258 48&quot; fill=&quot;none&quot; marker-end=&quot;url(#arrow)&quot; stroke-width=&quot;1.5&quot; stroke=&quot;#0366d6&quot;&gt;
      &lt;text fill=&quot;#586069&quot; x=&quot;200&quot; y=&quot;55&quot;&gt;Char: . ? !&lt;/text&gt;

      &lt;!--AFTER_TERMINAL -&gt; NORMAL (Abbreviation/No Split)--&gt;
      &lt;path d=&quot;M 262 62 Q 200 80 162 108&quot; fill=&quot;none&quot; stroke-width=&quot;1.5&quot; stroke=&quot;#cf222e&quot;&gt;
      &lt;text fill=&quot;#cf222e&quot; x=&quot;210&quot; y=&quot;95&quot;&gt;Is Abbrev / Decimal&lt;/text&gt;

      &lt;!--AFTER_TERMINAL -&gt; EMIT--&gt;
      &lt;path d=&quot;M 338 58 Q 400 70 442 98&quot; fill=&quot;none&quot; stroke-width=&quot;1.5&quot; stroke=&quot;#1a7f37&quot;&gt;
      &lt;text fill=&quot;#1a7f37&quot; x=&quot;410&quot; y=&quot;75&quot;&gt;Space + Upper&lt;/text&gt;

      &lt;!--NORMAL -&gt; IN_QUOTE--&gt;
      &lt;path d=&quot;M 150 145 Q 210 190 258 190&quot; fill=&quot;none&quot; stroke-width=&quot;1.5&quot; stroke=&quot;#0366d6&quot;&gt;
      &lt;text fill=&quot;#586069&quot; x=&quot;200&quot; y=&quot;180&quot;&gt;Char: &quot;&lt;/text&gt;

      &lt;!--IN_QUOTE -&gt; NORMAL--&gt;
      &lt;path d=&quot;M 258 190 Q 200 170 152 138&quot; fill=&quot;none&quot; stroke-width=&quot;1.5&quot; stroke=&quot;#0366d6&quot;&gt;
      &lt;text fill=&quot;#586069&quot; x=&quot;200&quot; y=&quot;150&quot;&gt;Char: &quot;&lt;/text&gt;
    &lt;/path&gt;&lt;/path&gt;&lt;/path&gt;&lt;/path&gt;&lt;/path&gt;&lt;/circle&gt;&lt;/circle&gt;&lt;/circle&gt;&lt;/circle&gt;&lt;/circle&gt;&lt;/g&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;h3&gt;States in Our FSM&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;NORMAL          — reading regular sentence content
AFTER_PERIOD    — just saw a period (potential sentence end)
IN_QUOTE        — inside a double-quoted string
IN_NUMBER       — inside a decimal number (e.g., 3.14)
BOUNDARY        — confirmed sentence boundary (emit the sentence)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;C Implementation&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;ctype.h&amp;gt;

#define MAX_SENTENCE_LEN 4096
#define MAX_SENTENCES    1024

typedef enum {
    STATE_NORMAL,
    STATE_AFTER_TERMINAL,  // After . ? !
    STATE_IN_QUOTE,
    STATE_IN_PARENS
} State;

// Check if a word is a likely abbreviation
int isAbbreviation(const char* word) {
    // Single capital letter (initial)
    if (strlen(word) == 1 &amp;amp;&amp;amp; isupper((unsigned char)word[0])) return 1;

    // Common abbreviations
    const char* abbrevs[] = {
        &quot;dr&quot;, &quot;mr&quot;, &quot;mrs&quot;, &quot;ms&quot;, &quot;prof&quot;, &quot;sr&quot;, &quot;jr&quot;,
        &quot;st&quot;, &quot;ave&quot;, &quot;blvd&quot;, &quot;no&quot;, &quot;vol&quot;, &quot;vs&quot;,
        &quot;jan&quot;, &quot;feb&quot;, &quot;mar&quot;, &quot;apr&quot;, &quot;jun&quot;, &quot;jul&quot;,
        &quot;aug&quot;, &quot;sep&quot;, &quot;oct&quot;, &quot;nov&quot;, &quot;dec&quot;, NULL
    };

    char lower[64];
    int i;
    for (i = 0; word[i] &amp;amp;&amp;amp; i &amp;lt; 63; i++)
        lower[i] = tolower((unsigned char)word[i]);
    lower[i] = &#39;\0&#39;;

    for (int j = 0; abbrevs[j] != NULL; j++) {
        if (strcmp(lower, abbrevs[j]) == 0) return 1;
    }
    return 0;
}

// Extract the last complete word from a buffer (strip trailing punctuation)
void getLastWord(const char* buffer, int len, char* word) {
    word[0] = &#39;\0&#39;;
    // Go backwards past punctuation and spaces
    int end = len - 1;
    while (end &amp;gt;= 0 &amp;amp;&amp;amp; (ispunct((unsigned char)buffer[end]) || isspace((unsigned char)buffer[end])))
        end--;

    // Now go backwards to find the start of the word
    int start = end;
    while (start &amp;gt; 0 &amp;amp;&amp;amp; !isspace((unsigned char)buffer[start - 1]))
        start--;

    if (start &amp;lt;= end) {
        strncpy(word, buffer + start, end - start + 1);
        word[end - start + 1] = &#39;\0&#39;;
    }
}

int splitSentences(const char* text, char sentences[][MAX_SENTENCE_LEN]) {
    State state = STATE_NORMAL;
    char buffer[MAX_SENTENCE_LEN];
    int bufLen = 0;
    int sentCount = 0;
    int n = strlen(text);
    char lastWord[64];

    for (int i = 0; i &amp;lt; n; i++) {
        char c = text[i];
        char next = (i + 1 &amp;lt; n) ? text[i + 1] : &#39;\0&#39;;
        char nextNext = (i + 2 &amp;lt; n) ? text[i + 2] : &#39;\0&#39;;

        buffer[bufLen++] = c;
        buffer[bufLen] = &#39;\0&#39;;

        switch (state) {
            case STATE_NORMAL:
                if (c == &#39;&quot;&#39;) {
                    state = STATE_IN_QUOTE;
                } else if (c == &#39;(&#39;) {
                    state = STATE_IN_PARENS;
                } else if ((c == &#39;.&#39; || c == &#39;?&#39; || c == &#39;!&#39;)) {
                    state = STATE_AFTER_TERMINAL;
                }
                break;

            case STATE_AFTER_TERMINAL:
                if (isspace((unsigned char)c) &amp;amp;&amp;amp; isupper((unsigned char)next)) {
                    // Potential boundary — check for abbreviation
                    getLastWord(buffer, bufLen - 1, lastWord); // -1 to ignore space
                    if (!isAbbreviation(lastWord)) {
                        // Emit the sentence (up to and including the punctuation)
                        // Trim trailing space
                        int end = bufLen - 1;
                        while (end &amp;gt; 0 &amp;amp;&amp;amp; isspace((unsigned char)buffer[end - 1])) end--;
                        buffer[end] = &#39;\0&#39;;
                        strncpy(sentences[sentCount++], buffer, MAX_SENTENCE_LEN - 1);
                        bufLen = 0;
                        buffer[0] = &#39;\0&#39;;
                        state = STATE_NORMAL;
                    } else {
                        state = STATE_NORMAL;
                    }
                } else if (c == &#39;&quot;&#39;) {
                    state = STATE_IN_QUOTE;
                } else if (!isspace((unsigned char)c)) {
                    // Something other than space — back to normal (e.g., &quot;1.5x&quot;)
                    state = STATE_NORMAL;
                }
                break;

            case STATE_IN_QUOTE:
                if (c == &#39;&quot;&#39;) {
                    state = STATE_NORMAL;
                }
                break;

            case STATE_IN_PARENS:
                if (c == &#39;)&#39;) {
                    state = STATE_NORMAL;
                }
                break;
        }
    }

    // Flush remaining text as the last sentence
    if (bufLen &amp;gt; 0) {
        strncpy(sentences[sentCount++], buffer, MAX_SENTENCE_LEN - 1);
    }

    return sentCount;
}

int main() {
    const char* text =
        &quot;Dr. Smith visited D.C. on Monday. &quot;
        &quot;The ratio was 1.5 to 1. It was significant! &quot;
        &quot;He said \&quot;This is fine. Really.\&quot; before leaving. &quot;
        &quot;Ms. Jones (his colleague) agreed. She smiled.&quot;;

    char sentences[MAX_SENTENCES][MAX_SENTENCE_LEN];
    int count = splitSentences(text, sentences);

    printf(&quot;Found %d sentences:\n\n&quot;, count);
    for (int i = 0; i &amp;lt; count; i++) {
        printf(&quot;[%d] %s\n&quot;, i + 1, sentences[i]);
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Found 5 sentences:

[1] Dr. Smith visited D.C. on Monday.
[2] The ratio was 1.5 to 1. It was significant!
[3] He said &quot;This is fine. Really.&quot; before leaving.
[4] Ms. Jones (his colleague) agreed.
[5] She smiled.
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;How the FSM Works — Step by Step&lt;/h3&gt;
&lt;p&gt;Let&#39;s trace through &lt;code&gt;&quot;1.5 to 1. It was&quot;&lt;/code&gt; character by character[cite: 1]:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&#39;1&#39;  → STATE_NORMAL,         buffer: &quot;1&quot;
&#39;.&#39;  → STATE_AFTER_TERMINAL, buffer: &quot;1.&quot;
&#39;5&#39;  → not space+uppercase → STATE_NORMAL, buffer: &quot;1.5&quot;   ← decimal, no split!
&#39; &#39;  → STATE_NORMAL,         buffer: &quot;1.5 &quot;
&#39;t&#39;  → STATE_NORMAL,         buffer: &quot;1.5 t&quot;
...
&#39;1&#39;  → STATE_NORMAL,         buffer: &quot;1.5 to 1&quot;
&#39;.&#39;  → STATE_AFTER_TERMINAL, buffer: &quot;1.5 to 1.&quot;
&#39; &#39;  → space! next=&#39;I&#39; (uppercase)...
       lastWord = &quot;1&quot; → not an abbreviation!
       EMIT SENTENCE: &quot;1.5 to 1.&quot;
       reset buffer, STATE_NORMAL
&#39;I&#39;  → STATE_NORMAL,         buffer: &quot;I&quot;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;When to Use It&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;When you need the most accurate rule-based approach[cite: 1]&lt;/li&gt;
&lt;li&gt;Complex documents: legal contracts, academic papers, news articles[cite: 1]&lt;/li&gt;
&lt;li&gt;When you want fine-grained control over every splitting decision[cite: 1]&lt;/li&gt;
&lt;li&gt;As the foundation for a custom domain-specific splitter[cite: 1]&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;th&gt;Handles Abbrevs&lt;/th&gt;
&lt;th&gt;Handles Quotes&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Naïve Punctuation Split&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡ Very Fast&lt;/td&gt;
&lt;td&gt;❌ Low&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;🟢 Trivial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abbreviation-Aware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡ Fast&lt;/td&gt;
&lt;td&gt;🟡 Medium&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;🟡 Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Regex Heuristic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡ Fast&lt;/td&gt;
&lt;td&gt;🟡 Good&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Partial&lt;/td&gt;
&lt;td&gt;🟡 Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FSM-Based&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🟢 Fast&lt;/td&gt;
&lt;td&gt;✅ Best (rule-based)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;🔴 More Complex&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2&gt;Choosing the Right Method&lt;/h2&gt;
&lt;p&gt;Here&#39;s a decision matrix to help choose the best approach for your project[cite: 1]:&lt;/p&gt;

&lt;!--Decision Tree SVG Diagram--&gt;
&lt;div class=&quot;diagram-container&quot;&gt;
  &lt;svg style=&quot;height: auto; max-width: 100%;&quot; viewbox=&quot;0 0 650 200&quot;&gt;
    &lt;g font-family=&quot;-apple-system, sans-serif&quot; font-size=&quot;11&quot; text-anchor=&quot;middle&quot;&gt;
      &lt;!--Root--&gt;
      &lt;rect fill-opacity=&quot;0.1&quot; fill=&quot;#0366d6&quot; height=&quot;35&quot; rx=&quot;6&quot; stroke=&quot;#0366d6&quot; width=&quot;180&quot; x=&quot;230&quot; y=&quot;10&quot;&gt;
      &lt;text fill=&quot;#0366d6&quot; font-weight=&quot;bold&quot; x=&quot;320&quot; y=&quot;32&quot;&gt;What are your text constraints?&lt;/text&gt;

      &lt;!--Branch 1--&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;260&quot; x2=&quot;100&quot; y1=&quot;45&quot; y2=&quot;80&quot;&gt;
      &lt;rect fill=&quot;#f6f8fa&quot; height=&quot;30&quot; rx=&quot;4&quot; stroke=&quot;#d1d5da&quot; width=&quot;160&quot; x=&quot;20&quot; y=&quot;80&quot;&gt;
      &lt;text x=&quot;100&quot; y=&quot;98&quot;&gt;Clean / Generated Text&lt;/text&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;100&quot; x2=&quot;100&quot; y1=&quot;110&quot; y2=&quot;140&quot;&gt;
      &lt;rect fill=&quot;#f1f8ff&quot; height=&quot;35&quot; rx=&quot;6&quot; stroke=&quot;#0366d6&quot; width=&quot;130&quot; x=&quot;35&quot; y=&quot;140&quot;&gt;
      &lt;text fill=&quot;#0366d6&quot; font-weight=&quot;bold&quot; x=&quot;100&quot; y=&quot;162&quot;&gt;Method 1 (Naïve)&lt;/text&gt;

      &lt;!--Branch 2--&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;320&quot; x2=&quot;320&quot; y1=&quot;45&quot; y2=&quot;80&quot;&gt;
      &lt;rect fill=&quot;#f6f8fa&quot; height=&quot;30&quot; rx=&quot;4&quot; stroke=&quot;#d1d5da&quot; width=&quot;180&quot; x=&quot;230&quot; y=&quot;80&quot;&gt;
      &lt;text x=&quot;320&quot; y=&quot;98&quot;&gt;Specific Known Domain&lt;/text&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;320&quot; x2=&quot;320&quot; y1=&quot;110&quot; y2=&quot;140&quot;&gt;
      &lt;rect fill=&quot;#f1f8ff&quot; height=&quot;35&quot; rx=&quot;6&quot; stroke=&quot;#0366d6&quot; width=&quot;150&quot; x=&quot;245&quot; y=&quot;140&quot;&gt;
      &lt;text fill=&quot;#0366d6&quot; font-weight=&quot;bold&quot; x=&quot;320&quot; y=&quot;162&quot;&gt;Method 2 (Abbreviation)&lt;/text&gt;

      &lt;!--Branch 3--&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;380&quot; x2=&quot;540&quot; y1=&quot;45&quot; y2=&quot;80&quot;&gt;
      &lt;rect fill=&quot;#f6f8fa&quot; height=&quot;30&quot; rx=&quot;4&quot; stroke=&quot;#d1d5da&quot; width=&quot;180&quot; x=&quot;450&quot; y=&quot;80&quot;&gt;
      &lt;text x=&quot;540&quot; y=&quot;98&quot;&gt;Complex / General Text&lt;/text&gt;
      &lt;line stroke-width=&quot;1.5&quot; stroke=&quot;#586069&quot; x1=&quot;540&quot; x2=&quot;540&quot; y1=&quot;110&quot; y2=&quot;140&quot;&gt;
      &lt;rect fill=&quot;#dcffe4&quot; height=&quot;35&quot; rx=&quot;6&quot; stroke=&quot;#1a7f37&quot; width=&quot;150&quot; x=&quot;465&quot; y=&quot;140&quot;&gt;
      &lt;text fill=&quot;#1a7f37&quot; font-weight=&quot;bold&quot; x=&quot;540&quot; y=&quot;162&quot;&gt;Method 3 or 4 (Regex/FSM)&lt;/text&gt;
    &lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/line&gt;&lt;/rect&gt;&lt;/g&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;h2&gt;Tips for Improving Any Rule-Based Splitter&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Handle ellipses&lt;/strong&gt; (&lt;code&gt;...&lt;/code&gt;) — they rarely end sentences mid-paragraph[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Track parenthesis depth&lt;/strong&gt; — text inside &lt;code&gt;(like this. Really.)&lt;/code&gt; should not be split[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handle numbered lists&lt;/strong&gt; — &lt;code&gt;&quot;1. First item  2. Second item&quot;&lt;/code&gt; should not split at &lt;code&gt;1.&lt;/code&gt;[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Normalize whitespace first&lt;/strong&gt; — collapse multiple spaces, replace &lt;code&gt;\t&lt;/code&gt; and &lt;code&gt;\n&lt;/code&gt;[cite: 1].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-process short fragments&lt;/strong&gt; — if a &quot;sentence&quot; is only 1-2 characters, it&#39;s probably a false split[cite: 1].&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Sentence splitting is one of those problems that looks trivially easy until you try it on real-world text[cite: 1]. The journey from a one-liner &lt;code&gt;split(&quot;.&quot;)&lt;/code&gt; to a full FSM with state tracking mirrors a broader truth in NLP: &lt;strong&gt;language is full of exceptions&lt;/strong&gt;, and robust systems are built by systematically handling them one by one[cite: 1].&lt;/p&gt;

&lt;blockquote&gt;
  &lt;strong&gt;Key Takeaway:&lt;/strong&gt; Rule-based methods are &lt;strong&gt;transparent, fast, and debuggable&lt;/strong&gt;[cite: 1]. When an FSM makes a wrong call, you can trace the exact logic path and fix it instantly — without retraining a neural model[cite: 1].
&lt;/blockquote&gt;

&lt;p&gt;That said, for truly noisy or ambiguous text (social media posts, OCR output, multilingual documents), machine learning models will outperform rules[cite: 1]. But for structured documents in a known domain, a well-crafted FSM splitter can be hard to beat[cite: 1].&lt;/p&gt;

&lt;p&gt;Happy splitting! 🔪📄&lt;/p&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2026/07/sentence-splitting-without-machine-learning.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEjbeBd_-JCQ8ajgkeaeRp3lqxhZl_wunUXyl0zkRS03zPIRZB9b4NkP1l9Kcxu7Qh3kg6vEC6UCj-60n4LPe_-eTqCnhv_utnzFCwk-aLD6G7dm168RTjzVxIErzCBFn-D9ZfapDy9HpR9b63FENbBhnK4axs6Crz72OoIrYjaA57-7M7kC9cq_60oTcj8=s72-w640-h336-c" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5287971008210422333</guid><pubDate>Thu, 23 Jul 2026 19:00:47 +0000</pubDate><atom:updated>2026-07-24T02:53:09.053+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Algorithms</category><category domain="http://www.blogger.com/atom/ns#">Beam Search</category><category domain="http://www.blogger.com/atom/ns#">C++</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Large Language Models</category><category domain="http://www.blogger.com/atom/ns#">LLM Decoding</category><category domain="http://www.blogger.com/atom/ns#">Text Generation</category><title>Beam Search: The Algorithm Behind LLM Text Generation</title><description> &lt;style&gt;
    .post-body {
      font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
      line-height: 1.6;
      color: #24292e;
    }

    .post-body h1, .post-body h2, .post-body h3 {
      color: #0366d6;
      border-bottom: 1px solid #eaecef;
      padding-bottom: 0.3em;
    }

    .post-body p {
      margin-bottom: 1em;
    }

    .post-body pre {
      background-color: #1e1e1e;
      color: #d4d4d4;
      padding: 16px;
      border-radius: 6px;
      overflow-x: auto;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 0.9em;
      line-height: 1.45;
    }

    .post-body code {
      background-color: #f6f8fa;
      color: #d73a49;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;
      font-size: 85%;
    }

    .post-body pre code {
      background-color: transparent;
      color: inherit;
      padding: 0;
    }

    .post-body table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
      font-size: 0.95em;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
      border-radius: 6px;
      overflow: hidden;
    }

    .post-body th, .post-body td {
      padding: 12px 15px;
      text-align: left;
      border-bottom: 1px solid #dddddd;
    }

    .post-body th {
      background-color: #0366d6;
      color: #ffffff;
      font-weight: 600;
    }

    .post-body tr:nth-of-type(even) {
      background-color: #f8f9fa;
    }

    .post-body tr:hover {
      background-color: #f1f3f5;
    }

    .post-body blockquote {
      margin: 1.5em 0;
      padding: 1em 1.2em;
      background-color: #f1f8ff;
      border-left: 4px solid #0366d6;
      color: #24292e;
    }

    .post-body ul, .post-body ol {
      padding-left: 20px;
      margin-bottom: 1em;
    }

    .post-body li {
      margin-bottom: 0.4em;
    }

    .post-body .img-container {
      text-align: center;
      margin: 25px 0;
    }

    .post-body .img-container img {
      max-width: 100%;
      height: auto;
      border-radius: 6px;
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    }

    .post-body hr {
      border: 0;
      height: 1px;
      background: #e1e4e8;
      margin: 2em 0;
    }
  &lt;/style&gt;

&lt;p&gt;When a Large Language Model (LLM) like GPT generates text, it doesn&#39;t simply pick the single most probable next word at every step. Doing so — known as &lt;strong&gt;greedy decoding&lt;/strong&gt; — often leads to repetitive, suboptimal, or even incoherent outputs. Instead, most production-grade language models use a smarter strategy called &lt;strong&gt;Beam Search&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we&#39;ll break down:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;What Beam Search is and why it exists&lt;/li&gt;
  &lt;li&gt;How it compares to Greedy and Exhaustive search&lt;/li&gt;
  &lt;li&gt;The step-by-step algorithm with a visual walkthrough&lt;/li&gt;
  &lt;li&gt;A full implementation in Java and C++&lt;/li&gt;
  &lt;li&gt;Its strengths, weaknesses, and modern variants&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;The Problem: Decoding from a Language Model&lt;/h2&gt;
&lt;p&gt;A language model assigns a probability to every possible next token given the preceding context:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;P(token | previous tokens)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Generating a complete sequence means making a &lt;strong&gt;chain of these decisions&lt;/strong&gt;. The goal is to find the sequence with the &lt;strong&gt;highest joint probability&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;P(w1, w2, ..., wN) = P(w1) × P(w2|w1) × P(w3|w1,w2) × ...&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;strong&gt;Search Space Explosion:&lt;/strong&gt; If your vocabulary has &lt;code&gt;V&lt;/code&gt; words and you generate sequences of length &lt;code&gt;N&lt;/code&gt;, there are &lt;code&gt;V^N&lt;/code&gt; possible sequences. For &lt;em&gt;V = 50,000&lt;/em&gt; and &lt;em&gt;N = 20&lt;/em&gt;, that&#39;s astronomically large. This is why we need smart search heuristics.
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2&gt;Approach 1: Greedy Search&lt;/h2&gt;
&lt;p&gt;Greedy search picks the &lt;strong&gt;single most probable token&lt;/strong&gt; at every step.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;At each step t: choose token = argmax P(token | context)&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Why Greedy Fails&lt;/h3&gt;
&lt;p&gt;Consider generating a sentence where:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; &quot;The&quot; → 0.4 (highest)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 2 given &quot;The&quot;:&lt;/strong&gt; &quot;cat&quot; → 0.3 (highest)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 3 given &quot;The cat&quot;:&lt;/strong&gt; &quot;sat&quot; → 0.2 (highest)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But an alternative path exists:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; &quot;A&quot; → 0.35&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 2 given &quot;A&quot;:&lt;/strong&gt; &quot;beautiful&quot; → 0.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 3 given &quot;A beautiful&quot;:&lt;/strong&gt; &quot;sunset&quot; → 0.9&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Joint probability of greedy path: &lt;code&gt;0.4 × 0.3 × 0.2 = 0.024&lt;/code&gt;&lt;br /&gt;
  Joint probability of better path: &lt;code&gt;0.35 × 0.6 × 0.9 = 0.189&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;Greedy search &lt;strong&gt;misses the better path&lt;/strong&gt; because it committed too early.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Approach 2: Exhaustive Search&lt;/h2&gt;
&lt;p&gt;Exhaustive search explores &lt;strong&gt;all possible sequences&lt;/strong&gt; and picks the best one. It is optimal but &lt;strong&gt;computationally infeasible&lt;/strong&gt; for any realistic vocabulary and sequence length.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Approach 3: Beam Search — The Sweet Spot&lt;/h2&gt;
&lt;p&gt;Beam Search is a &lt;strong&gt;heuristic best-first search&lt;/strong&gt; that keeps track of the &lt;strong&gt;top-K most promising partial sequences&lt;/strong&gt; (called the &quot;beam&quot;) at each step, where &lt;strong&gt;K is the beam width&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;Key Idea&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;At each step, expand &lt;strong&gt;every sequence in the beam&lt;/strong&gt; by all possible next tokens.&lt;/li&gt;
  &lt;li&gt;Score each expanded sequence.&lt;/li&gt;
  &lt;li&gt;Keep only the &lt;strong&gt;top-K&lt;/strong&gt; scoring sequences for the next step.&lt;/li&gt;
  &lt;li&gt;Repeat until all sequences hit an end token or max length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives us a controllable trade-off:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;K = 1&lt;/strong&gt; → Equivalent to Greedy Search&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;K = ∞&lt;/strong&gt; → Equivalent to Exhaustive Search&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;K = 5 to 20&lt;/strong&gt; → Practical sweet spot used in real systems&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;img-container&quot;&gt;
  &lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgomi8GIpfut2IlBq3n6cZAE2wWKWcLxfDQJj7H8aIIry8g1127i7wuzjD90JOaPAxUhEexaAHGIdwPJgxSHI5FUgyBHrL50SYLiARNzOMDGIUqhO_GgSqMMa4Jb_UdbgZq_oncOqCoAI-d9wvXtkfa8qqH8GBaUovhHdqGMEyJuMGiuVJDyJNFY3Lmub4&quot;&gt;
    &lt;img alt=&quot;Comparison between search approaches&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgomi8GIpfut2IlBq3n6cZAE2wWKWcLxfDQJj7H8aIIry8g1127i7wuzjD90JOaPAxUhEexaAHGIdwPJgxSHI5FUgyBHrL50SYLiARNzOMDGIUqhO_GgSqMMa4Jb_UdbgZq_oncOqCoAI-d9wvXtkfa8qqH8GBaUovhHdqGMEyJuMGiuVJDyJNFY3Lmub4=w640-h349&quot; title=&quot;Comparison between search approaches&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;h2&gt;Step-by-Step Visual Walkthrough&lt;/h2&gt;
&lt;p&gt;Let&#39;s trace Beam Search with &lt;strong&gt;beam width K=2&lt;/strong&gt; and a tiny vocabulary: &lt;code&gt;{A, B, C, &amp;lt;END&amp;gt;}&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEg6MOhv2c1Ms2NrnLS9Ev6EgnIocS6vXUImUoaVeV_gyRgdLzBKsrSUdNrHvJ59t-2FUDvOmgLJh5K9zxuHEcnUXvF14LsDk0jKgUGWHQURjtGVDV1Vg96E29grcH7BuAcoh6Jxf9WUAN2nxHVVqsVS_KaOB0twYsIJdqEbMm2P9V8gTYb2QDL7mR7VRB4&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;2816&quot; height=&quot;350&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEg6MOhv2c1Ms2NrnLS9Ev6EgnIocS6vXUImUoaVeV_gyRgdLzBKsrSUdNrHvJ59t-2FUDvOmgLJh5K9zxuHEcnUXvF14LsDk0jKgUGWHQURjtGVDV1Vg96E29grcH7BuAcoh6Jxf9WUAN2nxHVVqsVS_KaOB0twYsIJdqEbMm2P9V8gTYb2QDL7mR7VRB4=w640-h350&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;Step 0 — Initialization&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Beam: [ ([], score=0.0) ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We start with one empty sequence.&lt;/p&gt;

&lt;h3&gt;Step 1 — Expand&lt;/h3&gt;
&lt;p&gt;Expand the empty sequence with all tokens:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Candidates:
  [A]     → log P(A)     = -0.9
  [B]     → log P(B)     = -0.5   ✓ keep
  [C]     → log P(C)     = -1.2
  [&amp;lt;END&amp;gt;] → log P(&amp;lt;END&amp;gt;) = -2.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After keeping top-2:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Beam: [ ([B], -0.5), ([A], -0.9) ]&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Step 2 — Expand Each Beam Member&lt;/h3&gt;
&lt;p&gt;Expand &lt;code&gt;[B]&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  [B, A]     → -0.5 + -1.1 = -1.6
  [B, B]     → -0.5 + -0.4 = -0.9   ✓
  [B, C]     → -0.5 + -0.7 = -1.2   ✓
  [B, &amp;lt;END&amp;gt;] → -0.5 + -1.5 = -2.0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expand &lt;code&gt;[A]&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  [A, A]     → -0.9 + -0.8 = -1.7
  [A, B]     → -0.9 + -0.6 = -1.5
  [A, C]     → -0.9 + -0.3 = -1.2   (tied)
  [A, &amp;lt;END&amp;gt;] → -0.9 + -2.1 = -3.0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All 8 candidates are ranked, top-2 kept:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Beam: [ ([B, B], -0.9), ([B, C], -1.2) ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This process continues until &lt;code&gt;&amp;lt;END&amp;gt;&lt;/code&gt; tokens are generated or maximum length is reached. The sequence with the &lt;strong&gt;highest cumulative log-probability&lt;/strong&gt; is the final output.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Why Log Probabilities?&lt;/h2&gt;
&lt;p&gt;Multiplying many small probabilities leads to &lt;strong&gt;numerical underflow&lt;/strong&gt;. By working in &lt;strong&gt;log space&lt;/strong&gt;, we convert multiplications into additions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;log(P1 × P2 × P3) = log(P1) + log(P2) + log(P3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Higher (less negative) log-probability = better sequence.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Java Implementation&lt;/h2&gt;
&lt;p&gt;Here&#39;s a clean, self-contained Beam Search implementation in Java.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.*;

public class BeamSearch {

    static double[][] logProbTable = {
        /* step 0 */ {-0.9, -0.5, -1.2, -2.0},
        /* step 1 */ {-1.1, -0.4, -0.7, -1.5},
        /* step 2 */ {-0.8, -0.6, -0.3, -1.0},
        /* step 3 */ {-1.3, -0.9, -0.5, -0.4},
    };

    static String[] vocab = {&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;&amp;lt;END&amp;gt;&quot;};
    static int END_TOKEN = 3;

    static class Hypothesis implements Comparable&amp;lt;Hypothesis&amp;gt; {
        List&amp;lt;Integer&amp;gt; tokens;
        double score; 
        boolean finished;

        Hypothesis(List&amp;lt;Integer&amp;gt; tokens, double score, boolean finished) {
            this.tokens = new ArrayList&amp;lt;&amp;gt;(tokens);
            this.score = score;
            this.finished = finished;
        }

        @Override
        public int compareTo(Hypothesis other) {
            return Double.compare(other.score, this.score);
        }

        public String toStringSequence() {
            StringBuilder sb = new StringBuilder();
            for (int t : tokens) {
                sb.append(vocab[t]).append(&quot; &quot;);
            }
            return sb.toString().trim();
        }
    }

    static double[] getLogProbs(List&amp;lt;Integer&amp;gt; context) {
        int step = Math.min(context.size(), logProbTable.length - 1);
        return logProbTable[step];
    }

    static List&amp;lt;Hypothesis&amp;gt; beamSearch(int beamWidth, int maxLength) {
        List&amp;lt;Hypothesis&amp;gt; beam = new ArrayList&amp;lt;&amp;gt;();
        beam.add(new Hypothesis(new ArrayList&amp;lt;&amp;gt;(), 0.0, false));

        List&amp;lt;Hypothesis&amp;gt; completedSequences = new ArrayList&amp;lt;&amp;gt;();

        for (int step = 0; step &amp;lt; maxLength; step++) {
            List&amp;lt;Hypothesis&amp;gt; candidates = new ArrayList&amp;lt;&amp;gt;();

            for (Hypothesis hyp : beam) {
                if (hyp.finished) {
                    candidates.add(hyp);
                    continue;
                }

                double[] logProbs = getLogProbs(hyp.tokens);

                for (int tokenId = 0; tokenId &amp;lt; vocab.length; tokenId++) {
                    List&amp;lt;Integer&amp;gt; newTokens = new ArrayList&amp;lt;&amp;gt;(hyp.tokens);
                    newTokens.add(tokenId);
                    double newScore = hyp.score + logProbs[tokenId];
                    boolean isFinished = (tokenId == END_TOKEN);

                    candidates.add(new Hypothesis(newTokens, newScore, isFinished));
                }
            }

            Collections.sort(candidates);

            beam = new ArrayList&amp;lt;&amp;gt;();
            for (int i = 0; i &amp;lt; Math.min(beamWidth, candidates.size()); i++) {
                Hypothesis h = candidates.get(i);
                if (h.finished) {
                    completedSequences.add(h);
                } else {
                    beam.add(h);
                }
            }

            if (beam.isEmpty()) break;
        }

        completedSequences.addAll(beam);
        Collections.sort(completedSequences);
        return completedSequences;
    }

    public static void main(String[] args) {
        List&amp;lt;Hypothesis&amp;gt; results = beamSearch(2, 4);
        for (int i = 0; i &amp;lt; Math.min(3, results.size()); i++) {
            Hypothesis h = results.get(i);
            System.out.printf(&quot;Rank %d: %-25s score=%.4f%n&quot;, i + 1, h.toStringSequence(), h.score);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2&gt;C++ Implementation&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;string&amp;gt;

using namespace std;

const vector&amp;lt;string&amp;gt; vocab = {&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;&amp;lt;END&amp;gt;&quot;};
const int END_TOKEN = 3;
const int VOCAB_SIZE = 4;

const double logProbTable[4][4] = {
    {-0.9, -0.5, -1.2, -2.0},
    {-1.1, -0.4, -0.7, -1.5},
    {-0.8, -0.6, -0.3, -1.0},
    {-1.3, -0.9, -0.5, -0.4},
};

struct Hypothesis {
    vector&amp;lt;int&amp;gt; tokens;
    double score;
    bool finished;

    Hypothesis(vector&amp;lt;int&amp;gt; t, double s, bool f) : tokens(t), score(s), finished(f) {}

    bool operator&amp;lt;(const Hypothesis&amp;amp; other) const {
        return score &amp;lt; other.score;
    }
};

const double* getLogProbs(const vector&amp;lt;int&amp;gt;&amp;amp; context) {
    int step = min((int)context.size(), 3);
    return logProbTable[step];
}

vector&amp;lt;Hypothesis&amp;gt; beamSearch(int beamWidth, int maxLength) {
    vector&amp;lt;Hypothesis&amp;gt; beam;
    beam.emplace_back(vector&amp;lt;int&amp;gt;{}, 0.0, false);
    vector&amp;lt;Hypothesis&amp;gt; completed;

    for (int step = 0; step &amp;lt; maxLength; step++) {
        vector&amp;lt;Hypothesis&amp;gt; candidates;

        for (const Hypothesis&amp;amp; hyp : beam) {
            if (hyp.finished) {
                candidates.push_back(hyp);
                continue;
            }

            const double* logProbs = getLogProbs(hyp.tokens);

            for (int tokenId = 0; tokenId &amp;lt; VOCAB_SIZE; tokenId++) {
                vector&amp;lt;int&amp;gt; newTokens = hyp.tokens;
                newTokens.push_back(tokenId);
                double newScore = hyp.score + logProbs[tokenId];
                bool isFinished = (tokenId == END_TOKEN);
                candidates.emplace_back(newTokens, newScore, isFinished);
            }
        }

        sort(candidates.begin(), candidates.end(), [](const Hypothesis&amp;amp; a, const Hypothesis&amp;amp; b) {
            return a.score &amp;gt; b.score;
        });

        beam.clear();
        for (int i = 0; i &amp;lt; min(beamWidth, (int)candidates.size()); i++) {
            if (candidates[i].finished) {
                completed.push_back(candidates[i]);
            } else {
                beam.push_back(candidates[i]);
            }
        }

        if (beam.empty()) break;
    }

    for (auto&amp;amp; h : beam) completed.push_back(h);
    sort(completed.begin(), completed.end(), [](const Hypothesis&amp;amp; a, const Hypothesis&amp;amp; b) {
        return a.score &amp;gt; b.score;
    });

    return completed;
}&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2&gt;Complexity Analysis&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Approach&lt;/th&gt;
      &lt;th&gt;Time Complexity&lt;/th&gt;
      &lt;th&gt;Space Complexity&lt;/th&gt;
      &lt;th&gt;Quality&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Greedy Search&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(N × V)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(N)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Poor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Beam Search (width K)&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(N × K × V)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(K × N)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Good&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Exhaustive Search&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(V^N)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;O(V^N)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Optimal&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Where: &lt;code&gt;N&lt;/code&gt; = sequence length, &lt;code&gt;V&lt;/code&gt; = vocabulary size, and &lt;code&gt;K&lt;/code&gt; = beam width. Beam Search is &lt;strong&gt;linear in both N and K&lt;/strong&gt;, making it extremely practical.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Length Normalization&lt;/h2&gt;
&lt;p&gt;A critical issue with raw log-probability scoring: &lt;strong&gt;longer sequences always have lower (more negative) cumulative scores&lt;/strong&gt; because we&#39;re adding more negative numbers. This biases beam search toward shorter sequences.&lt;/p&gt;

&lt;p&gt;The fix is &lt;strong&gt;length normalization&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;normalized_score = cumulative_log_prob / (sequence_length ^ α)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;α&lt;/code&gt; (typically 0.6–0.8) controls how much to penalize/reward length.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Length-normalized score calculation
double normalizedScore(double cumulativeLogProb, int length, double alpha) {
    double lengthPenalty = Math.pow(length, alpha);
    return cumulativeLogProb / lengthPenalty;
}&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2&gt;Beam Search in Real LLMs&lt;/h2&gt;
&lt;p&gt;Here&#39;s how Beam Search fits into the actual text generation pipeline:&lt;/p&gt;

&lt;pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEg8De1CmT0_7CrbsEuHgvefJuK0Hkn-udCGB8xZb5DeYnGCBUjzUKqA8r6eDcDUJ8hJ761N9mUnbIp26QVQhTlT1N768fGc_AuNC28U3087BfH7rYXQdIDVn2EeoqmLwBFrpZtFm9xpTFDANAxCX6VP51v2LIw_TVRQ_pZk_-le2iXl_ruQoSRFZ3HW7hs&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;2816&quot; height=&quot;350&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEg8De1CmT0_7CrbsEuHgvefJuK0Hkn-udCGB8xZb5DeYnGCBUjzUKqA8r6eDcDUJ8hJ761N9mUnbIp26QVQhTlT1N768fGc_AuNC28U3087BfH7rYXQdIDVn2EeoqmLwBFrpZtFm9xpTFDANAxCX6VP51v2LIw_TVRQ_pZk_-le2iXl_ruQoSRFZ3HW7hs=w640-h350&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2&gt;Limitations of Beam Search&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Exposure Bias:&lt;/strong&gt; Mismatch between training (ground-truth context) and inference (generated context).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Generic / Boring Outputs:&lt;/strong&gt; Prefers safer, common phrases over creative paths.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Repetition:&lt;/strong&gt; Can looped word patterns (&quot;the the the...&quot;) without n-gram repetition penalties.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Not Globally Optimal:&lt;/strong&gt; Being a heuristic with finite K, it can still miss the true optimal sequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2&gt;Modern Alternatives and Extensions&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Method&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
      &lt;th&gt;Best For&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Greedy&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Pick argmax at each step&lt;/td&gt;
      &lt;td&gt;Speed-critical, draft generation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Beam Search&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Keep top-K beams&lt;/td&gt;
      &lt;td&gt;Machine translation, summarization&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Top-K Sampling&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Sample from top-K tokens&lt;/td&gt;
      &lt;td&gt;Creative text generation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Top-P (Nucleus) Sampling&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Sample from top-P probability mass&lt;/td&gt;
      &lt;td&gt;Chatbots, story generation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Temperature Scaling&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Sharpen/flatten probability distribution&lt;/td&gt;
      &lt;td&gt;Controlling creativity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Diverse Beam Search&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Penalize similar beams&lt;/td&gt;
      &lt;td&gt;Getting varied outputs&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Constrained Beam Search&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Force certain tokens to appear&lt;/td&gt;
      &lt;td&gt;Template-guided generation&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Beam Search is one of the most elegant solutions to the sequence decoding problem — a principled middle ground between the recklessness of Greedy Search and the infeasibility of Exhaustive Search. By maintaining a small set of the most promising partial sequences at every step, it finds high-quality outputs efficiently.&lt;/p&gt;

&lt;p&gt;Happy coding — and may your beams always converge on the right answer! 🚀&lt;/p&gt;</description><link>http://simplestcodings.blogspot.com/2026/07/beam-search-algorithm-behind-llm-text.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEgomi8GIpfut2IlBq3n6cZAE2wWKWcLxfDQJj7H8aIIry8g1127i7wuzjD90JOaPAxUhEexaAHGIdwPJgxSHI5FUgyBHrL50SYLiARNzOMDGIUqhO_GgSqMMa4Jb_UdbgZq_oncOqCoAI-d9wvXtkfa8qqH8GBaUovhHdqGMEyJuMGiuVJDyJNFY3Lmub4=s72-w640-h349-c" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-3033406139618727176</guid><pubDate>Sat, 03 Feb 2024 18:33:00 +0000</pubDate><atom:updated>2024-02-04T01:06:46.914+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">natural language processing</category><category domain="http://www.blogger.com/atom/ns#">NLP</category><category domain="http://www.blogger.com/atom/ns#">nlp in java</category><category domain="http://www.blogger.com/atom/ns#">sentiment analysis</category><category domain="http://www.blogger.com/atom/ns#">sentiment analysis in java</category><category domain="http://www.blogger.com/atom/ns#">Simplest Codings NLP</category><title>Harnessing Sentiment Analysis with Java: A Step-by-Step Guide using NLP</title><description>&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;Sentiment analysis, a powerful application of Natural Language Processing (NLP), allows developers to gain insights into the emotions expressed in textual data. In this article, we&#39;ll explore how to perform sentiment analysis in Java using the Stanford NLP library. We&#39;ll guide you through setting up a Maven project, compiling the code, and running it with practical examples.&lt;/span&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaeHxpAjGH725n8m7ZbLzTWNuTOG4xQErmZF46TEI0fraee4ZIU5NvZWsGwLs1T32DCRLQe4aMGlxb-qE0CpLbWRb-UjXJmGcdBs-mNTzr0E3YJbYZHue4FAkK3Sj2ubKZiZTbVPQrwk90QbyY1zMEOcq-ZDsLA76gELLuwNmjEzBjm8rGXFg_msdsx1A/s512/sentimentanalysis.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;512&quot; data-original-width=&quot;512&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaeHxpAjGH725n8m7ZbLzTWNuTOG4xQErmZF46TEI0fraee4ZIU5NvZWsGwLs1T32DCRLQe4aMGlxb-qE0CpLbWRb-UjXJmGcdBs-mNTzr0E3YJbYZHue4FAkK3Sj2ubKZiZTbVPQrwk90QbyY1zMEOcq-ZDsLA76gELLuwNmjEzBjm8rGXFg_msdsx1A/s16000/sentimentanalysis.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;Prerequisites&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;Get IntelliJ Idea from&amp;nbsp;https://www.jetbrains.com/idea/download.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;You can skip this and use any other IDE as well. The steps for setting up a maven project will be different for each IDE.&lt;/span&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt;Step 1: Create a New Project&lt;/span&gt;
&lt;/h2&gt;
&lt;div&gt;
    &lt;ul style=&quot;text-align: left;&quot;&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Open IntelliJ IDEA and click on &quot;Create New Project.&quot;&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Choose &quot;Maven&quot; as the project type and click &quot;Next.&quot;&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Set the &quot;GroupId&quot; to com.simplestcodings and &quot;ArtifactId&quot; to
        SentimentAnalysis.&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Click &quot;Next&quot; and then &quot;Finish.&quot;&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt;Step 2: Add Dependencies&lt;/span&gt;
&lt;/h2&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;Open the pom.xml file in the editor and replace the content with this &lt;/span&gt;section:
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;
      &lt;pre class=&quot;prettyprint&quot; style=&quot;text-align: left;&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;

    &amp;lt;groupId&amp;gt;com.simplestcodings&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;nlp&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;

    &amp;lt;properties&amp;gt;
        &amp;lt;maven.compiler.source&amp;gt;17&amp;lt;/maven.compiler.source&amp;gt;
        &amp;lt;maven.compiler.target&amp;gt;17&amp;lt;/maven.compiler.target&amp;gt;
        &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
    &amp;lt;/properties&amp;gt;

    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;edu.stanford.nlp&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;stanford-corenlp&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.5.6&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;edu.stanford.nlp&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;stanford-corenlp&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.5.6&amp;lt;/version&amp;gt;
            &amp;lt;classifier&amp;gt;models&amp;lt;/classifier&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;slf4j-simple&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.7.32&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.18.30&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
    &lt;/span&gt;
    &lt;h2 style=&quot;text-align: left;&quot;&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt; Step 3: Create Project Structure&lt;/span&gt;
    &lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;ul style=&quot;text-align: left;&quot;&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Right-click on the src directory in your project and choose &quot;New&quot;
          -&amp;gt; &quot;Package.&quot;&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Name it com.simplestcodings.&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
        &lt;li&gt;
      &lt;span style=&quot;font-family: helvetica;&quot;&gt;Inside the com.simplestcodings package, create a new Java class named
        SentimentAnalysis.&amp;nbsp;&lt;/span&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt;Step 4: Configure Properties&lt;/span&gt;
&lt;/h2&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;Right-click on the src directory and create a new directory named
    resources. Inside the resources directory, create a file named
    application.properties with the following content:&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;
      &lt;pre class=&quot;prettyprint&quot;&gt;tokenize.whitespace=true
ssplit.eolonly=true
annotators = tokenize, ssplit, parse, sentiment
&lt;/pre&gt;
      &lt;div&gt;
        &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;
    &lt;h2 style=&quot;text-align: left;&quot;&gt;
    &lt;span style=&quot;font-family: helvetica;&quot;&gt; Step 5: Write Code&lt;/span&gt;
    &lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;Replace the contents of SentimentAnalysis.java with the code provided
      below&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;
package com.simplestcodings;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
import edu.stanford.nlp.util.CoreMap;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SentimentAnalysis {

    public static void main(String[] args) {
        // Initialize the Stanford NLP pipeline
        StanfordCoreNLP pipeline = new StanfordCoreNLP(&quot;application.properties&quot;);

        // Sample text for sentiment analysis
        String text = &quot;Simplest codings is the best place to learn and grow. I am glad to be here.&quot;;

        // Perform sentiment analysis
        String sentiment = getSentiment(text, pipeline);

        // Display the result
        log.info(&quot;Text: {}, Sentiment: {}&quot;,text, sentiment);

        // Another Sample text for sentiment analysis
        text = &quot;I hate this place. I am not coming back here again. I am very disappointed.&quot;;

        // Perform sentiment analysis
        sentiment = getSentiment(text, pipeline);

        // Display the result
        log.info(&quot;Text: {}, Sentiment: {}&quot;,text, sentiment);
    }

    private static String getSentiment(String text, StanfordCoreNLP pipeline) {
        // Create an Annotation object with the input text
        Annotation annotation = new Annotation(text);

        // Run all the NLP annotators on the text
        pipeline.annotate(annotation);

        // Extract the sentiment from the annotation
        CoreMap sentence = annotation.get(CoreAnnotations.SentencesAnnotation.class).get(0);
        String sentiment = sentence.get(SentimentCoreAnnotations.SentimentClass.class);

        return sentiment;
    }
}



&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;Step 6: Run the Code&lt;/span&gt;
&lt;/h2&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;Right-click on the SentimentAnalysis class and select &quot;Run
      SentimentAnalysis.main()&quot;. Observe the output in the Run console, which
      should display the sentiment of the provided text.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgj3qHNNVI3XbJKnbCpmxo9WB0Zk6rok9XdfAgpqWSpmVYbekyyNUMurGnkjtbId--IjlGu33xa-4at9zYAVAuEeu_kOsk66aUkTd9L6rDrNqQl2LFV6NEJnNpAy39bun7mxNmGVN8IS5plEdL_QO4eqmWwf1hN1xsn93tA_AO44heDMbSui_2f0ws2lLQ&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Harnessing Sentiment Analysis with Java: A Step-by-Step Guide using NLP&quot; data-original-height=&quot;2050&quot; data-original-width=&quot;3456&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgj3qHNNVI3XbJKnbCpmxo9WB0Zk6rok9XdfAgpqWSpmVYbekyyNUMurGnkjtbId--IjlGu33xa-4at9zYAVAuEeu_kOsk66aUkTd9L6rDrNqQl2LFV6NEJnNpAy39bun7mxNmGVN8IS5plEdL_QO4eqmWwf1hN1xsn93tA_AO44heDMbSui_2f0ws2lLQ=s16000&quot; title=&quot;Harnessing Sentiment Analysis with Java: A Step-by-Step Guide using NLP&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
  &lt;span style=&quot;font-family: helvetica;&quot;&gt;You have successfully set up and run a sentiment analysis Java project
      using the Stanford NLP library in IntelliJ IDEA. Feel free to explore more
      examples and experiment with different texts to gain insights into the
      sentiment analysis capabilities of Java and NLP. Happy
      coding!&lt;/span&gt;
&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2024/02/harnessing-sentiment-analysis-with-java.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaeHxpAjGH725n8m7ZbLzTWNuTOG4xQErmZF46TEI0fraee4ZIU5NvZWsGwLs1T32DCRLQe4aMGlxb-qE0CpLbWRb-UjXJmGcdBs-mNTzr0E3YJbYZHue4FAkK3Sj2ubKZiZTbVPQrwk90QbyY1zMEOcq-ZDsLA76gELLuwNmjEzBjm8rGXFg_msdsx1A/s72-c/sentimentanalysis.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-8613834655176647719</guid><pubDate>Wed, 20 Dec 2023 19:57:00 +0000</pubDate><atom:updated>2024-02-03T23:09:39.313+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Algorithmic solution</category><category domain="http://www.blogger.com/atom/ns#">Code implementation</category><category domain="http://www.blogger.com/atom/ns#">Coin denomination</category><category domain="http://www.blogger.com/atom/ns#">Cracking piggy bank puzzle</category><category domain="http://www.blogger.com/atom/ns#">dynamic programming</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Java programming</category><category domain="http://www.blogger.com/atom/ns#">Money-saving challenge</category><category domain="http://www.blogger.com/atom/ns#">Optimal change</category><category domain="http://www.blogger.com/atom/ns#">Problem-solving</category><category domain="http://www.blogger.com/atom/ns#">Recursive approach</category><title> Cracking the Piggy Bank Puzzle: A Java Adventure in Dynamic Programming</title><description>&lt;p data-sourcepos=&quot;5:1-5:199&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Hey there, intrepid coders! Today, we&#39;re diving into a piggy bank heist… of the intellectual kind, of course! We&#39;ll be using a powerful technique called &lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px; white-space-collapse: preserve;&quot;&gt;Dynamic Programming (DP) &lt;/span&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px; white-space-collapse: preserve;&quot;&gt;to crack the code of a mischievous piggy bank and unlock its hidden treasures. Buckle up, because this adventure requires both logic and a dash of mathematical magic.&lt;/span&gt;
&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:199&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBKPVRhoZOhqRxT4bEAjutaRqcxkVBZ8qCDYxJk8uVRh4ZdoIq_Qym60Yna8lDUdsYQiz3s-5tukqEJNAoOMo6bczcT4L5sulu3odhXpkJUjSS9YOC5C1g6J8wi2rs_gik-R1T1zOQhwVaP2WlmgYpttBH2a_tA3B0lqQA1PGBsa4uMu30IN-2mRIHd5E/s2260/piggy.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1398&quot; data-original-width=&quot;2260&quot; height=&quot;376&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBKPVRhoZOhqRxT4bEAjutaRqcxkVBZ8qCDYxJk8uVRh4ZdoIq_Qym60Yna8lDUdsYQiz3s-5tukqEJNAoOMo6bczcT4L5sulu3odhXpkJUjSS9YOC5C1g6J8wi2rs_gik-R1T1zOQhwVaP2WlmgYpttBH2a_tA3B0lqQA1PGBsa4uMu30IN-2mRIHd5E/w607-h376/piggy.png&quot; width=&quot;607&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;

Imagine a piggy bank with compartments numbered 1 to N. Each compartment holds a certain amount of coins. Your mission is to maximise the total coins you can collect by following these two rules:
&lt;/span&gt;&lt;p&gt;&lt;/p&gt;
&lt;ol data-sourcepos=&quot;7:1-9:0&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;
  &lt;li data-sourcepos=&quot;7:1-7:127&quot; style=&quot;margin-bottom: 10px;&quot;&gt;
    You can only&amp;nbsp;start at compartment 1&amp;nbsp;and move&amp;nbsp;rightward,
    collecting all the coins in a compartment before proceeding.
  &lt;/li&gt;
  &lt;li data-sourcepos=&quot;8:1-9:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;
    You can either&amp;nbsp;skip a compartment&amp;nbsp;(earning you 0 coins)
    or&amp;nbsp;rob a compartment, but&amp;nbsp;robbing two consecutive compartments is
    forbidden.
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p data-sourcepos=&quot;10:1-10:301&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;
This might seem tricky, but DP comes to the rescue! It breaks down the problem into smaller, overlapping subproblems and cleverly stores the solutions, saving you from redundant calculations. Think of it like mapping a treasure hunt – each solution to a subproblem guides you towards the bigger prize.
&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;
class PiggyBankBreaker {

    private final int[] coins; // Array storing coins in each compartment (1-indexed)
    private final int[] maxCoins; // DP array to store max achievable coins at each position (0-indexed)

    public PiggyBankBreaker(int[] coins) {
        this.coins = coins; // Copy original coin values
        this.maxCoins = new int[coins.length + 1]; // Allocate DP array with space for starting point (index 0)
    }

    public int crackPiggyBank() {
        // Base case: No coins at starting point
        maxCoins[0] = 0;

        // Loop through each compartment from index 1 (inclusive)
        for (int i = 1; i &amp;lt;= coins.length; i++) {
            // Option 1: Rob current compartment + max from 2 positions back (non-consecutive)
            int robCurrent;

            // Check if robbing current is even possible (avoid accessing coins[-1])
            if (i &amp;gt;= 3) {
                robCurrent = coins[i - 1] + maxCoins[i - 3];
            } else {
                // Default to skipping for initial positions where robbing isn&#39;t valid
                robCurrent = 0;
            }

            // Option 2: Skip current compartment and take max from previous position (consecutive)
            int skipCurrent = maxCoins[i - 1];

            // Choose the option that yields more coins
            maxCoins[i] = Math.max(robCurrent, skipCurrent);
        }

        // Return the maximum achievable coins from the last compartment
        return maxCoins[coins.length];
    }

    public static void main(String[] args) {
        // Example piggy bank with coins
        int[] coins = {2, 3, 1, 4, 5, 7, 10};

        PiggyBankBreaker breaker = new PiggyBankBreaker(coins);
        int maxLoot = breaker.crackPiggyBank();
        System.out.println(&quot;Maximum amount you can collect: &quot; + maxLoot);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-sourcepos=&quot;3:1-3:74&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;This Java code solves the piggy bank problem, where you maximise the coins collected while adhering to two rules:&lt;/p&gt;&lt;ol data-sourcepos=&quot;5:1-5:68&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;5:1-5:68&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Start at compartment 1 and move rightward, collecting all coins in each compartment.&lt;/li&gt;&lt;li data-sourcepos=&quot;6:1-7:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;You can either skip or rob a compartment, but not two consecutive compartments.&lt;/li&gt;&lt;/ol&gt;&lt;p data-sourcepos=&quot;8:1-8:114&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;The code utilises Dynamic Programming (DP) to efficiently solve this problem by breaking it down into smaller, overlapping subproblems. Here&#39;s a breakdown of the key aspects:&lt;/p&gt;&lt;ul data-sourcepos=&quot;18:1-19:16&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;18:1-18:78&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The method calculates the maximum coins achievable from any starting point.&lt;/li&gt;&lt;li data-sourcepos=&quot;19:1-19:16&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Base case:&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;maxCoins[0] = 0&lt;/code&gt;&amp;nbsp;since no coins are earned before starting.&lt;/li&gt;&lt;li data-sourcepos=&quot;20:1-20:66&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Loop:&amp;nbsp;Iterates through each compartment (index 1 to length).&lt;/li&gt;&lt;li data-sourcepos=&quot;21:1-24:100&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Rob current option:&lt;ul data-sourcepos=&quot;22:5-24:100&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;22:5-22:151&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Calculates&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;robCurrent&lt;/code&gt;&amp;nbsp;by adding the current coin value (&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;coins[i - 1]&lt;/code&gt;) to the maximum coins achievable two positions back (&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;maxCoins[i - 3]&lt;/code&gt;).&lt;/li&gt;&lt;li data-sourcepos=&quot;23:5-23:138&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Fix:&amp;nbsp;A conditional statement (&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;i &amp;gt;= 3&lt;/code&gt;) ensures this calculation only happens for valid positions (avoiding&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;coins[-1]&lt;/code&gt;&amp;nbsp;access).&lt;/li&gt;&lt;li data-sourcepos=&quot;24:5-24:100&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Otherwise,&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;robCurrent&lt;/code&gt;&amp;nbsp;is set to 0,&amp;nbsp;mimicking skipping the compartment for initial positions.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;25:1-25:105&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Skip current option:&amp;nbsp;Simply takes the maximum coins from the previous position (&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;maxCoins[i - 1]&lt;/code&gt;).&lt;/li&gt;&lt;li data-sourcepos=&quot;26:1-26:29&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Comparison:&amp;nbsp;Chooses the maximum value between&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;robCurrent&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;skipCurrent&lt;/code&gt;&amp;nbsp;and stores it in&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;maxCoins[i]&lt;/code&gt;.&amp;nbsp;This ensures the optimal decision is recorded for future subproblems.&lt;/li&gt;&lt;li data-sourcepos=&quot;27:1-28:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Final result:&amp;nbsp;The last element&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;maxCoins[coins.length]&lt;/code&gt;&amp;nbsp;represents the maximum achievable coins from the starting point (compartment 1).&lt;/li&gt;&lt;/ul&gt;</description><link>http://simplestcodings.blogspot.com/2023/12/cracking-piggy-bank-puzzle-java.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBKPVRhoZOhqRxT4bEAjutaRqcxkVBZ8qCDYxJk8uVRh4ZdoIq_Qym60Yna8lDUdsYQiz3s-5tukqEJNAoOMo6bczcT4L5sulu3odhXpkJUjSS9YOC5C1g6J8wi2rs_gik-R1T1zOQhwVaP2WlmgYpttBH2a_tA3B0lqQA1PGBsa4uMu30IN-2mRIHd5E/s72-w607-h376-c/piggy.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5580712275157911006</guid><pubDate>Wed, 20 Dec 2023 15:17:00 +0000</pubDate><atom:updated>2023-12-20T21:51:41.298+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">backtracking</category><category domain="http://www.blogger.com/atom/ns#">bottom-up approach</category><category domain="http://www.blogger.com/atom/ns#">lcs dynamic programming table</category><category domain="http://www.blogger.com/atom/ns#">LCS problem</category><category domain="http://www.blogger.com/atom/ns#">longest common subsequence algorithm</category><category domain="http://www.blogger.com/atom/ns#">optimal solution</category><category domain="http://www.blogger.com/atom/ns#">reconstruction</category><category domain="http://www.blogger.com/atom/ns#">space complexity</category><category domain="http://www.blogger.com/atom/ns#">string algorithms</category><category domain="http://www.blogger.com/atom/ns#">time complexity</category><title>Longest common subsequence in Java</title><description>&lt;div&gt;&lt;p data-sourcepos=&quot;3:1-3:20&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Longest Common Subsequence (LCS)&lt;/p&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;5:1-6:4&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;5:1-5:112&quot; style=&quot;margin-bottom: 10px;&quot;&gt;It&#39;s the longest sequence of characters that is present in the same relative order within two or more strings.&lt;/li&gt;&lt;li data-sourcepos=&quot;6:1-6:4&quot; style=&quot;margin-bottom: 10px;&quot;&gt;It doesn&#39;t have to be a contiguous substring; the characters can appear in different positions within the original strings.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span face=&quot;Google Sans, Helvetica Neue, sans-serif&quot; style=&quot;color: #1f1f1f;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;Google Sans, Helvetica Neue, sans-serif&quot; style=&quot;color: #1f1f1f;&quot;&gt;&lt;h3 style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Understanding the Problem&lt;/h3&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;5:1-5:9&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;5:1-5:9&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Imagine two strings,&amp;nbsp;written vertically on separate columns.&lt;/li&gt;&lt;li data-sourcepos=&quot;6:1-6:113&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The goal is to find the longest sequence of characters that appears in the same order within both strings,&amp;nbsp;even if they&#39;re not consecutive.&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h3 style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Character Grid&lt;/h3&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;10:1-10:76&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;10:1-10:76&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a grid where each row represents a character from the first string,&amp;nbsp;and each column represents a character from the second string.&lt;/li&gt;&lt;li data-sourcepos=&quot;11:1-11:96&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Fill each cell with a color indicating whether the corresponding characters match (e.g.,&amp;nbsp;green) or not (e.g.,&amp;nbsp;white).&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h3 style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Tracing Paths&lt;/h3&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;15:1-19:0&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;15:1-15:43&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Start at the top-left corner of the grid.&lt;/li&gt;&lt;li data-sourcepos=&quot;16:1-16:70&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Move diagonally down-right only when characters match (green cells).&lt;/li&gt;&lt;li data-sourcepos=&quot;17:1-17:89&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If characters don&#39;t match,&amp;nbsp;move either down or right to continue searching for matches.&lt;/li&gt;&lt;li data-sourcepos=&quot;18:1-19:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The path you take represents the LCS.&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h3 style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Visualize the LCS&lt;/h3&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;22:1-24:0&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;22:1-22:75&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Highlight the cells along the longest path with a bolder color or border.&lt;/li&gt;&lt;li data-sourcepos=&quot;23:1-24:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The characters in those cells,&amp;nbsp;read in order,&amp;nbsp;form the LCS.&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;25:1-25:12&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Example:&lt;/p&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;27:1-27:40&quot; style=&quot;background-color: white; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Consider strings &quot;AGGTAB&quot; and &quot;GXTXAYB&quot;:&lt;/p&gt;&lt;code-block _nghost-ng-c3283117893=&quot;&quot; class=&quot;&quot; ng-version=&quot;0.0.0-PLACEHOLDER&quot; style=&quot;background-color: white;&quot;&gt;&lt;div _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-block ng-star-inserted&quot;&gt;&lt;pre _ngcontent-ng-c3283117893=&quot;&quot; style=&quot;margin-bottom: 0px; margin-top: 0px;&quot;&gt;&lt;code _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-container no-decoration-radius&quot; role=&quot;text&quot; style=&quot;background-color: var(--bard-color-code-block-background); border-radius: 16px; color: var(--bard-color-on-surface-variant); direction: ltr; display: block; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: 1.125rem; overflow-x: auto; padding: 16px;&quot;&gt;&lt;span style=&quot;font-family: Google Sans Mono, monospace;&quot;&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyGeQmWnmqPtVgIYCOc8eYi9W4uYudwsuX4G9EKkRfTOb4hM8j6QjrFw1V48a0zU1mWSs3jqzOBKDK3jlhW1CPWFg9DT0foGv62c-ikwLAUYgf-VxlY7T_h7cXQS3DeDLULxLgmGY4ZqVYutfzm6QTUqWhxXanx-tcOaXV2eCL4AND5qnlBPvgosaf-mE/s1826/LCS.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1619&quot; data-original-width=&quot;1826&quot; height=&quot;284&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyGeQmWnmqPtVgIYCOc8eYi9W4uYudwsuX4G9EKkRfTOb4hM8j6QjrFw1V48a0zU1mWSs3jqzOBKDK3jlhW1CPWFg9DT0foGv62c-ikwLAUYgf-VxlY7T_h7cXQS3DeDLULxLgmGY4ZqVYutfzm6QTUqWhxXanx-tcOaXV2eCL4AND5qnlBPvgosaf-mE/s320/LCS.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Google Sans, Helvetica Neue, sans-serif;&quot;&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;LCS: &quot;GTAB&quot; (highlighted cells)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/code-block&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Algorithm&lt;/h3&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ol data-sourcepos=&quot;10:1-11:56&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;10:1-11:56&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;10:4-10:33&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Dynamic Programming Table:&lt;/p&gt;&lt;ul data-sourcepos=&quot;11:4-13:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;11:4-11:108&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a 2D table&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp&lt;/code&gt;&amp;nbsp;with dimensions (m+1) x (n+1),&amp;nbsp;where m and n are the lengths of the two strings.&lt;/li&gt;&lt;li data-sourcepos=&quot;12:4-13:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Fill the first row and column with 0s,&amp;nbsp;indicating no LCS for empty strings.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;14:1-18:42&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;14:4-14:25&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Filling the Table:&lt;/p&gt;&lt;ul data-sourcepos=&quot;15:4-18:42&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;15:4-15:57&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Iterate through the table,&amp;nbsp;starting from&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[1][1]&lt;/code&gt;.&lt;/li&gt;&lt;li data-sourcepos=&quot;16:4-18:42&quot; style=&quot;margin-bottom: 10px;&quot;&gt;For each cell&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][j]&lt;/code&gt;:&lt;ul data-sourcepos=&quot;17:6-18:42&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;17:6-18:42&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If the characters at indices i-1 and j-1 in the strings match:&lt;ul data-sourcepos=&quot;18:8-18:42&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;18:8-18:42&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Set&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][j] = dp[i-1][j-1] + 1&lt;/code&gt;&amp;nbsp;(add 1 to the LCS length of the previous substrings).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;19:6-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Else:&lt;ul data-sourcepos=&quot;20:8-21:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;20:8-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Set&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][j] = max(dp[i-1][j], dp[i][j-1])&lt;/code&gt;&amp;nbsp;(take the maximum LCS length from the previous options).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;22:1-28:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;22:4-22:30&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Reconstructing the LCS:&lt;/p&gt;&lt;ul data-sourcepos=&quot;23:4-28:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;23:4-23:66&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Start from the bottom-right corner of the table (&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[m][n]&lt;/code&gt;).&lt;/li&gt;&lt;li data-sourcepos=&quot;24:4-26:73&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Backtrack:&lt;ul data-sourcepos=&quot;25:6-26:73&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;25:6-25:118&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If the characters at indices i-1 and j-1 match,&amp;nbsp;add the character to the LCS and move diagonally up (i--,&amp;nbsp;j--).&lt;/li&gt;&lt;li data-sourcepos=&quot;26:6-26:73&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Else,&amp;nbsp;move to the cell with the maximum value (either i-- or j--).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;27:4-28:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Reverse the constructed LCS string to get the correct order.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&amp;nbsp;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;

public class LCS {

    public static String lcs(String str1, String str2) {
        int m = str1.length();
        int n = str2.length();

        int[][] dp = new int[m + 1][n + 1];

        // Build the table in a bottom-up manner
        for (int i = 1; i &amp;lt;= m; i++) {
            for (int j = 1; j &amp;lt;= n; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        // Reconstruct the LCS
        StringBuilder lcs = new StringBuilder();
        int i = m, j = n;
        while (i &amp;gt; 0 &amp;amp;&amp;amp; j &amp;gt; 0) {
            if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                lcs.append(str1.charAt(i - 1));
                i--;
                j--;
            } else if (dp[i - 1][j] &amp;gt; dp[i][j - 1]) {
                i--;
            } else {
                j--;
            }
        }

        // Reverse the LCS string
        return lcs.reverse().toString();
    }

    // Example usage for testing
    public static void main(String[] args) {
        System.out.println(lcs(&quot;ABCDEFG&quot;, &quot;BCDGK&quot;));
        System.out.println(lcs(&quot;AGGTAB&quot;, &quot;GXTXAYB&quot;));
        System.out.println(lcs(&quot;ABCDE&quot;, &quot;A&quot;));
        System.out.println(lcs(&quot;A&quot;, &quot;BCDEF&quot;));
    }
}

&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px; white-space-collapse: preserve;&quot;&gt;Explanation for code&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;p data-sourcepos=&quot;3:1-3:20&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;1. lcs() Method:&lt;/p&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;4:4-5:2&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;4:4-5:2&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Takes two strings as input.&lt;/li&gt;&lt;li data-sourcepos=&quot;5:4-5:75&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Uses dynamic programming to find the longest common subsequence (LCS).&lt;/li&gt;&lt;li data-sourcepos=&quot;6:4-7:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Returns the LCS string.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Steps&lt;/h4&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;10:4-11:24&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;10:4-10:91&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a DP Table:&amp;nbsp;Stores the lengths of LCSs for substrings of different lengths.&lt;/li&gt;&lt;li data-sourcepos=&quot;11:4-11:24&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Fill the DP Table:&lt;ul data-sourcepos=&quot;12:7-14:9&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;12:7-12:52&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Iterates through characters of both strings.&lt;/li&gt;&lt;li data-sourcepos=&quot;13:7-14:9&quot; style=&quot;margin-bottom: 10px;&quot;&gt;For each cell,&amp;nbsp;calculates the length of the LCS based on previous calculations:&lt;ul data-sourcepos=&quot;14:10-15:73&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;14:10-14:83&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If characters match,&amp;nbsp;add 1 to the LCS length of the previous substrings.&lt;/li&gt;&lt;li data-sourcepos=&quot;15:10-15:73&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If not,&amp;nbsp;take the maximum LCS length from the previous options.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;16:4-16:96&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Reconstruct the LCS:&amp;nbsp;Backtracks through the DP table to find the characters in the LCS.&lt;/li&gt;&lt;li data-sourcepos=&quot;17:4-18:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Reverse the LCS:&amp;nbsp;Since it&#39;s built backward,&amp;nbsp;reverse it before returning.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Take away points&lt;/h4&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;21:4-22:102&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;21:4-21:91&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Bottom-up approach:&amp;nbsp;Builds the solution from smaller subproblems to the final LCS.&lt;/li&gt;&lt;li data-sourcepos=&quot;22:4-22:102&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Dynamic programming principle:&amp;nbsp;Avoids redundant calculations by storing intermediate results.&lt;/li&gt;&lt;li data-sourcepos=&quot;23:4-23:66&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Time complexity:&amp;nbsp;O(mn),&amp;nbsp;where m and n are string lengths.&lt;/li&gt;&lt;li data-sourcepos=&quot;24:4-25:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Space complexity:&amp;nbsp;O(mn),&amp;nbsp;due to the DP table.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2023/12/longest-common-subsequence-in-java.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyGeQmWnmqPtVgIYCOc8eYi9W4uYudwsuX4G9EKkRfTOb4hM8j6QjrFw1V48a0zU1mWSs3jqzOBKDK3jlhW1CPWFg9DT0foGv62c-ikwLAUYgf-VxlY7T_h7cXQS3DeDLULxLgmGY4ZqVYutfzm6QTUqWhxXanx-tcOaXV2eCL4AND5qnlBPvgosaf-mE/s72-c/LCS.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-7150531635231867196</guid><pubDate>Wed, 20 Dec 2023 14:59:00 +0000</pubDate><atom:updated>2023-12-20T22:32:17.585+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">decision making</category><category domain="http://www.blogger.com/atom/ns#">dynamic programming</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Knapsack problem algorithm</category><category domain="http://www.blogger.com/atom/ns#">knapsack problem code</category><title> Knapsack Problem implementation in Java</title><description>&lt;div&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f;&quot;&gt;&lt;p data-sourcepos=&quot;3:1-3:48&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Imagine a hiker&#39;s backpack (the knapsack) with limited space (capacity).&lt;/p&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;5:1-5:101&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;They have a collection of items, each with a value (usefulness) and a weight (space it occupies).&lt;/p&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;7:1-7:120&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;The goal is to fill the backpack with the most valuable combination of items, without exceeding its weight capacity.&lt;/p&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Visualizing the Items&lt;/h4&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;code-block _nghost-ng-c3283117893=&quot;&quot; class=&quot;&quot; ng-version=&quot;0.0.0-PLACEHOLDER&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;div _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-block ng-star-inserted&quot;&gt;&lt;pre _ngcontent-ng-c3283117893=&quot;&quot; style=&quot;margin-bottom: 0px; margin-top: 0px;&quot;&gt;&lt;code _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-container no-decoration-radius&quot; role=&quot;text&quot; style=&quot;background-color: var(--bard-color-code-block-background); border-radius: 16px; color: var(--bard-color-on-surface-variant); direction: ltr; display: block; font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size: 0.875rem; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: 1.125rem; overflow-x: auto; padding: 16px;&quot;&gt;Item 1:  (value 60, weight 10)
Item 2:  (value 100, weight 20)
Item 3:  (value 120, weight 30)

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42EONRKkCLItUT8CdBXjHnDCDOUxH2ZZXRoFEc_-gqObYrPkCZeqpwA3ANztIzWxfwHhrs3gX4uY0ktkuDfntqyOCWQ-i_gCriHbmk0TApMSGUuyuFg6YJv9lC4hZDwnUTVu2Y5rPR_MlkKScdkuTO0dK8LsMdxiBWsBrs1Xv3ibl-OXrUtzqmOmJi_s/s776/Weights.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;263&quot; data-original-width=&quot;776&quot; height=&quot;232&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42EONRKkCLItUT8CdBXjHnDCDOUxH2ZZXRoFEc_-gqObYrPkCZeqpwA3ANztIzWxfwHhrs3gX4uY0ktkuDfntqyOCWQ-i_gCriHbmk0TApMSGUuyuFg6YJv9lC4hZDwnUTVu2Y5rPR_MlkKScdkuTO0dK8LsMdxiBWsBrs1Xv3ibl-OXrUtzqmOmJi_s/w686-h232/Weights.png&quot; width=&quot;686&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/code-block&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;17:1-17:17&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;&lt;/p&gt;&lt;h4 style=&quot;font-size: 16px; text-align: left;&quot;&gt;The Knapsack&lt;/h4&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; font-size: 16px; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6k-BEQzeCrnoRvCZw75fpkIcr82yfr9yMAfMwPyaR319FtJ5kDTeo8yNgtDNReNGoM3UAtsaKFhc0QVVqGXA4r1VEN_jmeTFH7L3MVCaisyd9tI54hQhP1G_FQ83a2qXHRbjBw9n1a9O8uDp3tOdIc2oPt8cdb7ibuOIUB1r2Fy35whYeSF_660av0U/s1024/image.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6k-BEQzeCrnoRvCZw75fpkIcr82yfr9yMAfMwPyaR319FtJ5kDTeo8yNgtDNReNGoM3UAtsaKFhc0QVVqGXA4r1VEN_jmeTFH7L3MVCaisyd9tI54hQhP1G_FQ83a2qXHRbjBw9n1a9O8uDp3tOdIc2oPt8cdb7ibuOIUB1r2Fy35whYeSF_660av0U/s320/image.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;p style=&quot;font-size: 16px; text-align: left;&quot;&gt;&lt;/p&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Decision-Making&lt;/h4&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;25:1-29:33&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px; text-align: left;&quot;&gt;&lt;li data-sourcepos=&quot;25:1-25:49&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin-bottom: 10px;&quot;&gt;Can&#39;t fit all items directly (total weight 60).&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;Optimal choice would be to put these items in the bag&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;Item: {value: 120, weight: 30}&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;Item: {value: 100, weight: 20}&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Optimal Solution&lt;/h4&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;code-block _nghost-ng-c3283117893=&quot;&quot; class=&quot;&quot; ng-version=&quot;0.0.0-PLACEHOLDER&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px;&quot;&gt;&lt;div _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-block ng-star-inserted&quot;&gt;&lt;pre _ngcontent-ng-c3283117893=&quot;&quot; style=&quot;margin-bottom: 0px; margin-top: 0px;&quot;&gt;&lt;code _ngcontent-ng-c3283117893=&quot;&quot; class=&quot;code-container no-decoration-radius&quot; role=&quot;text&quot; style=&quot;background-color: var(--bard-color-code-block-background); border-radius: 16px; color: var(--bard-color-on-surface-variant); direction: ltr; display: block; font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size: 0.875rem; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: 1.125rem; overflow-x: auto; padding: 16px;&quot;&gt;KNAPSACK  (capacity 50)
     (value 120, weight 30)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/code-block&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Key Points&lt;/h4&gt;&lt;span style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;40:1-43:58&quot; style=&quot;font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px; text-align: left;&quot;&gt;&lt;li data-sourcepos=&quot;40:1-40:63&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Knapsack represents a resource constraint (limited capacity).&lt;/li&gt;&lt;li data-sourcepos=&quot;41:1-41:74&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Items represent choices with associated values and constraints (weight).&lt;/li&gt;&lt;li data-sourcepos=&quot;42:1-42:50&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Goal is to maximize value within the constraint.&lt;/li&gt;&lt;li data-sourcepos=&quot;43:1-43:58&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Often involves trade-offs and strategic decision-making.&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;In formal language, g&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;span style=&quot;font-family: helvetica;&quot;&gt;iven a set of items,&amp;nbsp;each with a weight and a value,&amp;nbsp;and a knapsack with a maximum weight capacity,&amp;nbsp;find the subset of items that maximizes the total value while fitting within the weight capacity.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Dynamic Programming Approach&lt;/h3&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ol data-sourcepos=&quot;11:1-11:13&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;11:1-11:13&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;11:4-11:27&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Create a table &lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp&lt;/code&gt;:&lt;/p&gt;&lt;ul data-sourcepos=&quot;12:4-14:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;12:4-12:104&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Dimensions:&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;(n + 1) x (W + 1)&lt;/code&gt;,&amp;nbsp;where&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;n&lt;/code&gt;&amp;nbsp;is the number of items and&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;W&lt;/code&gt;&amp;nbsp;is the knapsack capacity.&lt;/li&gt;&lt;li data-sourcepos=&quot;13:4-14:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][w]&lt;/code&gt;&amp;nbsp;stores the maximum value achievable using items up to the&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;i-th&lt;/code&gt;&amp;nbsp;item and with a maximum weight of&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;w&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;15:1-19:5&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;15:4-15:22&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Fill the table:&lt;/p&gt;&lt;ul data-sourcepos=&quot;16:4-19:5&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;16:4-18:69&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Base cases:&lt;ul data-sourcepos=&quot;17:6-18:69&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;17:6-17:57&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[0][w] = 0&lt;/code&gt;&amp;nbsp;for all&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;w&lt;/code&gt;&amp;nbsp;(no items,&amp;nbsp;value is 0).&lt;/li&gt;&lt;li data-sourcepos=&quot;18:6-18:69&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][0] = 0&lt;/code&gt;&amp;nbsp;for all&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;i&lt;/code&gt;&amp;nbsp;(zero weight capacity,&amp;nbsp;value is 0).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;19:4-19:5&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Recursive formula:&lt;ul data-sourcepos=&quot;20:6-23:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;20:6-21:62&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][w] = max(dp[i-1][w], value[i] + dp[i-1][w-weight[i]])&lt;/code&gt;&amp;nbsp;if&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;weight[i] &amp;lt;= w&lt;/code&gt;&amp;nbsp;(Choose between including or excluding the&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;i-th&lt;/code&gt;&amp;nbsp;item)&lt;/li&gt;&lt;li data-sourcepos=&quot;22:6-23:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[i][w] = dp[i-1][w]&lt;/code&gt;&amp;nbsp;otherwise (Item cannot be included due to weight constraint)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;24:1-27:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;24:4-24:16&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Solution:&lt;/p&gt;&lt;/li&gt;&lt;ul data-sourcepos=&quot;25:4-27:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;25:4-25:82&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The maximum value is&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dp[n][W]&lt;/code&gt;&amp;nbsp;(using all items with the knapsack capacity).&lt;/li&gt;&lt;li data-sourcepos=&quot;26:4-27:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Backtrack to find the selected items.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;div&gt;&lt;span face=&quot;Google Sans, Helvetica Neue, sans-serif&quot; style=&quot;color: #1f1f1f;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;Google Sans, Helvetica Neue, sans-serif&quot; style=&quot;color: #1f1f1f;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;


&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;
import java.util.ArrayList;
import java.util.List;

public class Knapsack {

    public static List&lt;item&gt; knapsack(List&lt;item&gt; items, int capacity) {
        int[][] dp = new int[items.size() + 1][capacity + 1];

        // Build table dp[][] in a bottom-up manner
        for (int i = 0; i &amp;lt;= items.size(); i++) {
            for (int w = 0; w &amp;lt;= capacity; w++) {
                if (i == 0 || w == 0) {
                    dp[i][w] = 0;
                } else if (items.get(i - 1).weight &amp;lt;= w) {
                    dp[i][w] = Math.max(items.get(i - 1).value + dp[i - 1][w - items.get(i - 1).weight], dp[i - 1][w]);
                } else {
                    dp[i][w] = dp[i - 1][w];
                }
            }
        }

        // Reconstruct the solution
        List&lt;item&gt; selectedItems = new ArrayList&amp;lt;&amp;gt;();
        int i = items.size(), w = capacity;
        while (i &amp;gt; 0 &amp;amp;&amp;amp; w &amp;gt; 0) {
            if (dp[i][w] != dp[i - 1][w]) {
                selectedItems.add(items.get(i - 1));
                w -= items.get(i - 1).weight;
            }
            i--;
        }

        return selectedItems;
    }

    public static void main(String[] args) {
        List&lt;item&gt; items = new ArrayList&amp;lt;&amp;gt;();
        items.add(new Item(60, 10));
        items.add(new Item(100, 20));
        items.add(new Item(120, 30));
        int capacity = 50;

        List&lt;item&gt; selected = knapsack(items, capacity);
        System.out.println(&quot;Selected items: &quot; + selected);
    }

    public static class Item {
        int value;
        int weight;

        Item(int value, int weight) {
            this.value = value;
            this.weight = weight;
        }

        @Override
        public String toString() {
            return &quot;Item: {value: &quot; + value + &quot;, weight: &quot; + weight + &quot;}&quot;;
        }
    }
}

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

&lt;div&gt;&lt;p data-sourcepos=&quot;3:1-3:18&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Explanation of code&lt;/h2&gt;&lt;p data-sourcepos=&quot;3:1-3:18&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;1. Item Class:&lt;/p&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;4:4-4:50&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;4:4-4:50&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Represents an item with its value and weight.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;p data-sourcepos=&quot;6:1-6:25&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;2. knapsack() Method:&lt;/p&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;7:4-8:9&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;7:4-7:60&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Takes a list of items and a knapsack capacity as input.&lt;/li&gt;&lt;li data-sourcepos=&quot;8:4-8:9&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Uses dynamic programming to solve the 0-1 Knapsack Problem.&lt;/li&gt;&lt;li data-sourcepos=&quot;9:4-9:99&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Returns a list of selected items that maximize the total value without exceeding the capacity.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Steps&lt;/h4&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;13:4-14:7&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;13:4-13:75&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a 2D DP array:&amp;nbsp;Stores intermediate results for subproblems.&lt;/li&gt;&lt;li data-sourcepos=&quot;14:4-14:7&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Fill the DP array:&lt;ul data-sourcepos=&quot;15:7-16:114&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;15:7-15:45&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Iterate through items and capacities.&lt;/li&gt;&lt;li data-sourcepos=&quot;16:7-16:114&quot; style=&quot;margin-bottom: 10px;&quot;&gt;For each cell,&amp;nbsp;calculate the maximum value achievable considering the current item and remaining capacity.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;17:4-18:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Reconstruct the solution:&amp;nbsp;Backtrack through the DP array to find the selected items.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h4 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Take away points&lt;/h4&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;21:4-23:69&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;21:4-21:96&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Bottom-up approach:&amp;nbsp;Builds the solution from smaller subproblems to the final solution.&lt;/li&gt;&lt;li data-sourcepos=&quot;22:4-22:102&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Dynamic programming principle:&amp;nbsp;Avoids redundant calculations by storing intermediate results.&lt;/li&gt;&lt;li data-sourcepos=&quot;23:4-23:69&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Time complexity:&amp;nbsp;O(nW),&amp;nbsp;where n is the number of items and W is the capacity.&lt;/li&gt;&lt;li data-sourcepos=&quot;24:4-25:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Space complexity:&amp;nbsp;O(nW),&amp;nbsp;due to the DP array.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2023/12/knapsack-problem.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42EONRKkCLItUT8CdBXjHnDCDOUxH2ZZXRoFEc_-gqObYrPkCZeqpwA3ANztIzWxfwHhrs3gX4uY0ktkuDfntqyOCWQ-i_gCriHbmk0TApMSGUuyuFg6YJv9lC4hZDwnUTVu2Y5rPR_MlkKScdkuTO0dK8LsMdxiBWsBrs1Xv3ibl-OXrUtzqmOmJi_s/s72-w686-h232-c/Weights.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-8522537935253249454</guid><pubDate>Wed, 20 Dec 2023 14:40:00 +0000</pubDate><atom:updated>2023-12-20T22:49:07.950+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Dijkstra</category><category domain="http://www.blogger.com/atom/ns#">Dijkstra Java implementation</category><category domain="http://www.blogger.com/atom/ns#">Graphs</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Shortest Path Algorithm</category><title>Dijkstra algorithm implementation in Java</title><description>&lt;div&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;&lt;div&gt;&lt;span data-canva-clipboard=&quot;ewAiAGEAIgA6ADUALAAiAGQAIgA6ACIAQgAiACwAIgBoACIAOgAiAHcAdwB3AC4AYwBhAG4AdgBhAC4AYwBvAG0AIgAsACIAYwAiADoAIgBEAEEARgAzAGkAQQBjAFYATAB0AEEAIgAsACIAaQAiADoAIgBHAF8ASQBIADYARgAtADYAegBMADQAWQAwAE4AcwBfAEMAWgA0AGEAbQBRACIALAAiAGIAIgA6ADEANwAwADMAMAA5ADIAMwA1ADUAMQAzADEALAAiAGoAIgA6AFsAewAiAEEAIgA6AHsAIgBCACIAOgB7AH0ALAAiAEsAIgA6AHsAfQAsACIARAAiADoAewB9ACwAIgBMACIAOgB7ACIAQQAiADoAWwB7ACIAQQAiADoAewB9ACwAIgBCACIAOgAiAEMAIgB9ACwAewAiAEEAIgA6AHsAfQAsACIAQgAiADoAIgBCACIAfQBdAH0ALAAiAEUAIgA6AHsAfQAsACIARgAiADoAewAiAEEAIgA6ACIASQBkAGUAbgB0AGkAdAB5AC4AcABuAGcAIgAsACIAQgAiADoAMQB9ACwAIgBHACIAOgB7AH0ALAAiAEgAIgA6AHsAIgBCACIAOgAiAG4AbwBuAGUAIgAsACIAQwAiADoAIgAjADAAMAAwADAAMAAwACIALAAiAEQAIgA6ACIAIwBmAGYAZgBmAGYAZgAiAH0ALAAiAEoAIgA6AHsAIgBGACIAOgAiACMAMAAwADAAMAAwADAAIgB9ACwAIgBQACIAOgB7AH0AfQB9AF0ALAAiAEEAPwAiADoAIgBCACIALAAiAEEAIgA6AFsAewAiAEEAIgA6ADYANAAsACIAQgAiADoALQA0ADgAMAAsACIARAAiADoANAA3ADkALgA5ADkAOQA5ADkAOQA5ADkAOQA5ADkAOQA5ACwAIgBDACIAOgA0ADcAOQAuADkAOQA5ADkAOQA5ADkAOQA5ADkAOQA5ADkALAAiAEEAPwAiADoAIgBJACIALAAiAGEAIgA6AHsAIgBCACIAOgB7ACIAQQAiADoAewAiAEEAIgA6ACIATQBBAEYAMwBpAGQAeAB1AEEAWgA0ACIALAAiAEIAIgA6ADEAfQAsACIAQgAiADoAewAiAEEAIgA6ADIALgA4ADQAMgAxADcAMAA5ADQAMwAwADQAMAA0ADAAMQBlAC0AMQA0ACwAIgBCACIAOgAyAC4AOAA0ADIAMQA3ADAAOQA0ADMAMAA0ADAANAAwADEAZQAtADEANAAsACIARAAiADoANAA3ADkALgA5ADkAOQA5ADkAOQA5ADkAOQA5ADkAOQA5ACwAIgBDACIAOgA0ADcAOQAuADkAOQA5ADkAOQA5ADkAOQA5ADkAOQA5ADkAfQB9AH0AfQBdACwAIgBCACIAOgAtADEALAAiAEMAIgA6AC0AMQB9AA==&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwIUvtfuSz-DIBItAcHeTUNTsuDzr-DpfSTkeAnvRLXwNWDZnDEOsx4RZUOpqY0MJjAcpWbQAvxjKz9Zl7joUHFjE9KRVXxEQxoAdDEYD2UbYl2bVweYDeMi1rQ3nvHzuQAFIBPe-x2yoKYPDPzipphYH4tFOmL5C6Q3XibrE4fNyj5LpXcmJAuPpWyUg/s896/shortestroute.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;448&quot; data-original-width=&quot;896&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwIUvtfuSz-DIBItAcHeTUNTsuDzr-DpfSTkeAnvRLXwNWDZnDEOsx4RZUOpqY0MJjAcpWbQAvxjKz9Zl7joUHFjE9KRVXxEQxoAdDEYD2UbYl2bVweYDeMi1rQ3nvHzuQAFIBPe-x2yoKYPDPzipphYH4tFOmL5C6Q3XibrE4fNyj5LpXcmJAuPpWyUg/w639-h320/shortestroute.png&quot; width=&quot;639&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Purpose&lt;/h3&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;5:1-5:67&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;5:1-5:67&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Finds the shortest paths from a single source vertex to all other vertices in a weighted graph.&lt;/li&gt;&lt;li data-sourcepos=&quot;6:1-7:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Commonly used in GPS navigation,&amp;nbsp;network routing,&amp;nbsp;and logistics planning.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Key Concepts&lt;/h3&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ul data-sourcepos=&quot;10:1-10:1&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;10:1-10:1&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Weighted Graph:&amp;nbsp;A set of vertices (nodes) connected by edges with associated weights (distances,&amp;nbsp;costs,&amp;nbsp;etc.).&lt;/li&gt;&lt;li data-sourcepos=&quot;11:1-11:20&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Source Vertex:&amp;nbsp;The starting point for finding shortest paths.&lt;/li&gt;&lt;li data-sourcepos=&quot;12:1-13:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Shortest Path:&amp;nbsp;The path with the minimum total weight between two vertices.&lt;/li&gt;&lt;/ul&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;h3 style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 24px 0px; text-align: left; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Algorithm Steps&lt;/h3&gt;&lt;span face=&quot;&amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #1f1f1f; font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;ol data-sourcepos=&quot;16:1-24:65&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;16:1-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;16:4-16:22&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Initialization:&lt;/p&gt;&lt;ul data-sourcepos=&quot;17:4-21:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;17:4-17:66&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a set&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;S&lt;/code&gt;&amp;nbsp;to store visited vertices (initially empty).&lt;/li&gt;&lt;li data-sourcepos=&quot;18:4-18:112&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Initialize an array&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;distances&lt;/code&gt;&amp;nbsp;with infinite values for all vertices except the source,&amp;nbsp;which is set to 0.&lt;/li&gt;&lt;li data-sourcepos=&quot;19:4-19:93&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Create a priority queue&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Q&lt;/code&gt;&amp;nbsp;to store vertices,&amp;nbsp;prioritized by their tentative distances.&lt;/li&gt;&lt;li data-sourcepos=&quot;20:4-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Add the source vertex to&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Q&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;22:1-24:65&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;22:4-22:24&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Exploration Loop:&lt;/p&gt;&lt;ul data-sourcepos=&quot;23:4-24:65&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;23:4-24:65&quot; style=&quot;margin-bottom: 10px;&quot;&gt;While&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Q&lt;/code&gt;&amp;nbsp;is not empty:&lt;ul data-sourcepos=&quot;24:6-24:65&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;24:6-24:65&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Extract the vertex&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;u&lt;/code&gt;&amp;nbsp;with the minimum distance from&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Q&lt;/code&gt;.&lt;/li&gt;&lt;li data-sourcepos=&quot;25:6-25:48&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Add&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;u&lt;/code&gt;&amp;nbsp;to the set&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;S&lt;/code&gt;&amp;nbsp;(mark as visited).&lt;/li&gt;&lt;li data-sourcepos=&quot;26:6-30:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;For each neighbor vertex&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;v&lt;/code&gt;&amp;nbsp;of&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;u&lt;/code&gt;:&lt;ul data-sourcepos=&quot;27:8-30:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;27:8-30:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;If&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;v&lt;/code&gt;&amp;nbsp;is not visited and the distance to&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;v&lt;/code&gt;&amp;nbsp;through&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;u&lt;/code&gt;&amp;nbsp;is shorter than its current distance:&lt;ul data-sourcepos=&quot;28:10-30:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;28:10-28:63&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Update the distance to&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;v&lt;/code&gt;&amp;nbsp;in the&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;distances&lt;/code&gt;&amp;nbsp;array.&lt;/li&gt;&lt;li data-sourcepos=&quot;29:10-30:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;Add&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;v&lt;/code&gt;&amp;nbsp;to the priority queue&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Q&lt;/code&gt;&amp;nbsp;(or update its priority if already present).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;31:1-34:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;p data-sourcepos=&quot;31:4-31:14&quot; style=&quot;margin: 24px 0px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Result:&lt;/p&gt;&lt;ul data-sourcepos=&quot;32:4-34:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;32:4-32:108&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;distances&lt;/code&gt;&amp;nbsp;array now contains the shortest distances from the source vertex to all other vertices.&lt;/li&gt;&lt;li data-sourcepos=&quot;33:4-34:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;To reconstruct the actual shortest paths,&amp;nbsp;keep track of the predecessor of each vertex during the exploration.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.stream.Collectors;

public class Dijkstra {

    public static List&lt;integer&gt; dijkstra(Graph graph, int source) {
        int[] distances = new int[graph.numVertices];
        Arrays.fill(distances, Integer.MAX_VALUE);
        distances[source] = 0;
        PriorityQueue&lt;integer&gt; pq = new PriorityQueue&amp;lt;&amp;gt;(Comparator.comparingInt(i -&amp;gt; distances[i]));
        pq.offer(source);

        boolean[] visited = new boolean[graph.numVertices];
        while (!pq.isEmpty()) {
            int u = pq.poll();
            visited[u] = true;
            for (Edge edge : graph.adjacencyList.get(u)) {
                int v = edge.to;
                int weight = edge.weight;
                if (!visited[v] &amp;amp;&amp;amp; distances[u] + weight &amp;lt; distances[v]) {
                    distances[v] = distances[u] + weight;
                    pq.offer(v);
                }
            }
        }

        return Arrays.stream(distances).boxed().collect(Collectors.toList());
    }

    public static Graph createRandomGraph(int numVertices) {
        Graph graph = new Graph(numVertices);
        Random random = new Random();
        // Add edges with random weights
        for (int i = 0; i &amp;lt; 9; i++) {
            for (int j = i + 1; j &amp;lt; 9; j++) {
                // Decide whether to create an edge with 50% probability
                if (random.nextBoolean()) {
                    int weight = random.nextInt(10) + 1; // Random weight between 1 and 10
                    graph.addEdge(i, j, weight);
                    graph.addEdge(j, i, weight); // Add reverse edge for undirected graph (if needed)
                }
            }
        }
        return graph;
    }

    public static void main(String[] args) {
        // Create a sample graph
        Graph graph = createRandomGraph(9);
        graph.visualize();
        int source = 0;
        List&lt;integer&gt; distances = dijkstra(graph, source);
        System.out.println(&quot;Shortest distances from &quot; + source + &quot;: &quot; + distances);
    }

    public static class Edge {
        int to;
        int weight;

        Edge(int to, int weight) {
            this.to = to;
            this.weight = weight;
        }
    }

    public static class Graph {
        int numVertices;
        List&lt;list dge=&quot;&quot;&gt;&amp;gt; adjacencyList;

        Graph(int numVertices) {
            this.numVertices = numVertices;
            adjacencyList = new ArrayList&amp;lt;&amp;gt;();
            for (int i = 0; i &amp;lt; numVertices; i++) {
                adjacencyList.add(new ArrayList&amp;lt;&amp;gt;());
            }
        }

        void addEdge(int from, int to, int weight) {
            adjacencyList.get(from).add(new Edge(to, weight));
        }

        void visualize() {
            System.out.println(&quot;Graph Visualization:\n&quot;);
            for (int vertex = 0; vertex &amp;lt; numVertices; vertex++) {
                System.out.print(vertex + &quot; -&amp;gt; &quot;);
                for (Edge edge : adjacencyList.get(vertex)) {
                    System.out.print(edge.to + &quot;(&quot; + edge.weight + &quot;) &quot;);
                }
                System.out.println();
            }
        }
    }
}

&lt;/list&gt;&lt;/integer&gt;&lt;/integer&gt;&lt;/integer&gt;&lt;/code&gt;
&lt;/pre&gt;

&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;
Explanation of code&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul data-sourcepos=&quot;9:1-21:0&quot; style=&quot;background-color: white; color: #1f1f1f; font-family: &amp;quot;Google Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; margin: 4px 0px; padding-inline-start: 36px; text-align: left;&quot;&gt;&lt;li data-sourcepos=&quot;9:1-12:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;h4 style=&quot;margin: 0px 0px 24px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Graph Representation&lt;/h4&gt;&lt;ul data-sourcepos=&quot;10:5-12:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;10:5-10:137&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Graph&lt;/code&gt;&amp;nbsp;class models a graph using an adjacency list, where each vertex stores a list of its connected edges and their weights.&lt;/li&gt;&lt;li data-sourcepos=&quot;11:5-12:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;Edge&lt;/code&gt;&amp;nbsp;class encapsulates the destination vertex and weight of an edge.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;13:1-18:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;h4 style=&quot;margin: 0px 0px 24px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Dijkstra&#39;s Algorithm Implementation&lt;/h4&gt;&lt;ul data-sourcepos=&quot;14:5-18:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;14:5-18:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;dijkstra(Graph, source)&lt;/code&gt;&amp;nbsp;method implements the algorithm&#39;s logic:&lt;ul data-sourcepos=&quot;15:7-18:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;15:7-15:96&quot; style=&quot;margin-bottom: 10px;&quot;&gt;It maintains a priority queue to explore vertices in order of their tentative distances.&lt;/li&gt;&lt;li data-sourcepos=&quot;16:7-16:88&quot; style=&quot;margin-bottom: 10px;&quot;&gt;It iteratively relaxes edges to update distances and explore reachable vertices.&lt;/li&gt;&lt;li data-sourcepos=&quot;17:7-18:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;It ultimately returns a list of the shortest distances from the source vertex to all other vertices.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li data-sourcepos=&quot;19:1-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;&lt;h4 style=&quot;margin: 0px 0px 24px; white-space-collapse: preserve; word-break: break-word;&quot;&gt;Random Graph Generation&lt;/h4&gt;&lt;ul data-sourcepos=&quot;20:5-21:0&quot; style=&quot;margin: 4px 0px; padding-inline-start: 36px;&quot;&gt;&lt;li data-sourcepos=&quot;20:5-21:0&quot; style=&quot;margin-bottom: 10px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: var(--bard-color-surface-container-high); border-radius: 6px; color: var(--bard-color-on-surface-variant); font-family: &amp;quot;Google Sans Mono&amp;quot;, monospace; font-size: 0.875rem; line-height: 1.25rem; padding: 1px 6px;&quot;&gt;createRandomGraph(numVertices)&lt;/code&gt;&amp;nbsp;method generates a graph with a specified number of vertices and randomly assigns edges with weights between 1 and 10.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;



</description><link>http://simplestcodings.blogspot.com/2023/12/dijkstra-algorithm-implementation-in.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwIUvtfuSz-DIBItAcHeTUNTsuDzr-DpfSTkeAnvRLXwNWDZnDEOsx4RZUOpqY0MJjAcpWbQAvxjKz9Zl7joUHFjE9KRVXxEQxoAdDEYD2UbYl2bVweYDeMi1rQ3nvHzuQAFIBPe-x2yoKYPDPzipphYH4tFOmL5C6Q3XibrE4fNyj5LpXcmJAuPpWyUg/s72-w639-h320-c/shortestroute.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5109847722655664026</guid><pubDate>Wed, 12 Oct 2016 17:11:00 +0000</pubDate><atom:updated>2023-12-20T21:23:57.715+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">auto-suggestion</category><category domain="http://www.blogger.com/atom/ns#">autocomplete</category><category domain="http://www.blogger.com/atom/ns#">C</category><category domain="http://www.blogger.com/atom/ns#">data structure</category><category domain="http://www.blogger.com/atom/ns#">dictionaries</category><category domain="http://www.blogger.com/atom/ns#">natural language processing</category><category domain="http://www.blogger.com/atom/ns#">prefix search</category><category domain="http://www.blogger.com/atom/ns#">Search Algorithm</category><category domain="http://www.blogger.com/atom/ns#">string storage</category><category domain="http://www.blogger.com/atom/ns#">Ternary Search</category><category domain="http://www.blogger.com/atom/ns#">TST deletion</category><category domain="http://www.blogger.com/atom/ns#">TST insertion</category><category domain="http://www.blogger.com/atom/ns#">TST search</category><title>Ternary Search Tree Implementation in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
A Ternary Search Tree is a trie which leverages concepts of Binary Search Tree as well. A Ternary Search Tree is as memory efficient as Binary Search Trees and time efficient as a Trie.&lt;br /&gt;
&lt;br /&gt;
It is an efficient data structure to store and search large number of strings.&lt;br /&gt;
&lt;br /&gt;
A node in a Ternary Search Tree comprises of these fields :&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Left pointer - Points to&amp;nbsp;Ternary Search Tree containing&amp;nbsp;all strings alphabetically lesser than current node&#39;s data&lt;/li&gt;
&lt;li&gt;Right pointer - Points to&amp;nbsp;Ternary Search Tree&amp;nbsp;containing&amp;nbsp;all&amp;nbsp;strings&amp;nbsp;alphabetically&amp;nbsp;greater than current node&#39;s data&lt;/li&gt;
&lt;li&gt;Equal pointer -&amp;nbsp;Points to&amp;nbsp;Ternary Search Tree&amp;nbsp;containing&amp;nbsp;all&amp;nbsp;strings&amp;nbsp;alphabetically&amp;nbsp;equal to current node&#39;s data&lt;/li&gt;
&lt;li&gt;End of string flag - Flag indicating the end of string&lt;/li&gt;
&lt;li&gt;Data - Actual data in the form of single character&lt;/li&gt;
&lt;/ul&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguGduD0vChiSTnjE4_z63S7c4eq03iPdCxFtxaHHmwC99f8MD3M5QUjbF4JyqEFdYk-I7Tb9igf_70_yQgztDU26LUcZlgIn_s2dZoRXB2yJsM4V5xoYsB6-BHZSiLiDJH7arkX97D3dY/s1600/Node.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;192&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguGduD0vChiSTnjE4_z63S7c4eq03iPdCxFtxaHHmwC99f8MD3M5QUjbF4JyqEFdYk-I7Tb9igf_70_yQgztDU26LUcZlgIn_s2dZoRXB2yJsM4V5xoYsB6-BHZSiLiDJH7arkX97D3dY/s320/Node.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Ternary Search Tree Node&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
For example, consider adding these strings in the same order into a Ternary Search Tree :&lt;/div&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&quot;Lead&quot;&lt;/li&gt;
&lt;li&gt;&quot;Leader&quot;&lt;/li&gt;
&lt;li&gt;&quot;Leads&quot;&lt;/li&gt;
&lt;li&gt;&quot;Late&quot;&lt;/li&gt;
&lt;li&gt;&quot;State&quot;&lt;/li&gt;
&lt;/ol&gt;
Let&#39;s build a visualization of ternary search tree out of above data :

&lt;br /&gt;
&lt;div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&quot;Lead&quot;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOqiMU5ms2UeCZ2s5pJc6JGlSqgH5QFE9iaGm-y9SKZW1nZIF7wisYauk4HRPosylIiSpCnZv2kJKtceXl9OuIkIOC3_pfltMaHPOrKJkMRwnUJF0b-xTPnf3rkilB1APX2Ht8CDoaGg/s1600/Lead.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOqiMU5ms2UeCZ2s5pJc6JGlSqgH5QFE9iaGm-y9SKZW1nZIF7wisYauk4HRPosylIiSpCnZv2kJKtceXl9OuIkIOC3_pfltMaHPOrKJkMRwnUJF0b-xTPnf3rkilB1APX2Ht8CDoaGg/s1600/Lead.png&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&quot;Leader&quot;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgEGLsfdy2ZNbQr9dUWhNYmRKty7Y9avPZRUjFHsDBcYOJA2PprufKYNPrrDDfUWe2LExhtxAYE9EVpbLCeuyASXGdsSWFYvzKQERTR9eKkccHkLygqJFqNEFG0tf4CfF7OAzKJxWg7Ds/s1600/Leader.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgEGLsfdy2ZNbQr9dUWhNYmRKty7Y9avPZRUjFHsDBcYOJA2PprufKYNPrrDDfUWe2LExhtxAYE9EVpbLCeuyASXGdsSWFYvzKQERTR9eKkccHkLygqJFqNEFG0tf4CfF7OAzKJxWg7Ds/s1600/Leader.png&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&quot;Leads&quot;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4zTzZRTFrUIwxuH9ZAMbW6oRhLhtsEibgAt1onQDl_xk9cRx-q4FyQqfqmS3A9sEVpH21JznHNoigH_0-ciUgM30yIqR29Bbc07LHVqY74ip-b_duN3wsllVjWi79p9M6peSEDWQk0-Q/s1600/Leads.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4zTzZRTFrUIwxuH9ZAMbW6oRhLhtsEibgAt1onQDl_xk9cRx-q4FyQqfqmS3A9sEVpH21JznHNoigH_0-ciUgM30yIqR29Bbc07LHVqY74ip-b_duN3wsllVjWi79p9M6peSEDWQk0-Q/s1600/Leads.png&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&quot;Late&quot;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4GYrp25waQYYicgWtbrqIGM1nFMIxUfXq_ip0Yf84v4iY5ba-wN-P4kYtL1Rti7hyZwMwTRVIAerTsIbiz66ht0TzOnHtlsCBdACWX1W56Bcw4FjTNKsdg3bBUd1AVR98AHk4zgDOtE4/s1600/Late.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4GYrp25waQYYicgWtbrqIGM1nFMIxUfXq_ip0Yf84v4iY5ba-wN-P4kYtL1Rti7hyZwMwTRVIAerTsIbiz66ht0TzOnHtlsCBdACWX1W56Bcw4FjTNKsdg3bBUd1AVR98AHk4zgDOtE4/s1600/Late.png&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&quot;State&quot;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuC74zCxc3WRYNIh1QGJap0Hj7X9MTA6bCCelXx8fOF0ebtAFOyNXaYJ5RYxEx6N3KtRIHL85zTDj_ZFpsRo_BiD_eJzGpvWeZnk7vLrZSLbW6CivMKW9b7ZxFSda3so7xg9jVMPWLeqU/s1600/State.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuC74zCxc3WRYNIh1QGJap0Hj7X9MTA6bCCelXx8fOF0ebtAFOyNXaYJ5RYxEx6N3KtRIHL85zTDj_ZFpsRo_BiD_eJzGpvWeZnk7vLrZSLbW6CivMKW9b7ZxFSda3so7xg9jVMPWLeqU/s1600/State.png&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

//TST.h
#ifndef TST_H
#define TST_H
//#define DEBUG_PROGRAM_MEMORY

//Node of a Ternary Search Tree
typedef struct TSTNode{
 char data; //Actual data stored in form of character
 bool bEOS; //flag marking end of string
 struct TSTNode* left;   //All character data less than this node
 struct TSTNode* eq;  //All character data equal to this node
 struct TSTNode* right; //All character data greater than this node
}TSTNode;

//Inserts a string in the TST
TSTNode* Insert(TSTNode* root, char* str); 

//Prints all strings in the TST
void PrintAllStringsInTST(TSTNode* root);

//Gets the length of maximum length string in TST
int MaxLenStringLen(TSTNode *root);

//Deleted the complete TST
void DeleteTST(TSTNode *root);

//Search a pattern in TST
bool SearchTST(TSTNode *root, char* pattern);

//Prints 
#ifdef DEBUG_PROGRAM_MEMORY
#include &amp;lt;map&amp;gt;

static std::map&amp;lt;TSTNode*, char&amp;gt; mem_addrs;
void CheckTSTMem();
#endif

#endif

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

&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

//TST.cpp
#include &amp;lt;iostream&amp;gt;
#define DEBUG_PROGRAM_MEMORY

#include &quot;TST.h&quot;
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;utility&amp;gt;

#define MAX_LEN 1024

#define MAX( a, b, c ) ((a)&amp;gt;(b) ? ((a)&amp;gt;(c) ? (a):(c)) : ( (b)&amp;gt;(c) ? (b):(c) ))


TSTNode* Insert(TSTNode* root, char* str)
{
 if(root == NULL)
 {
  root = (TSTNode*)malloc(sizeof(TSTNode));
  if(root == NULL)
  {
   std::cout&amp;lt;&amp;lt;&quot;Memory allocation failed&quot;&amp;lt;&amp;lt;std::endl;
   return NULL;
  }

  //Insert first character of string in the root node
  root-&amp;gt;data = *str;
#ifdef DEBUG_PROGRAM_MEMORY
  mem_addrs.insert(std::make_pair(root, root-&amp;gt;data));
#endif
  root-&amp;gt;bEOS = false;
  root-&amp;gt;left = root-&amp;gt;eq = root-&amp;gt;right = NULL;
 }
 
 if(*str  &amp;lt; root-&amp;gt;data)
  root-&amp;gt;left = Insert(root-&amp;gt;left, str);
 else if (*str == root-&amp;gt;data)
 {
  if(*(str + 1))
   root-&amp;gt;eq = Insert(root-&amp;gt;eq, str + 1);
  else
   root-&amp;gt;bEOS = true;
 }
 else
  root-&amp;gt;right = Insert(root-&amp;gt;right, str);
 
 return root; 
}

//Helper to print the strings in TST
static void PrintHelper(TSTNode* root, char* buffer, int depth)
{
 if (root)
 {
  // Traverse the left subtree
  PrintHelper(root-&amp;gt;left, buffer, depth);

  buffer[depth] = root-&amp;gt;data;
  //Once end of string flag is encountered, print the string
  if (root-&amp;gt;bEOS)
  {
   buffer[depth + 1] = &#39;\0&#39;;
   std::cout&amp;lt;&amp;lt; buffer &amp;lt;&amp;lt; std::endl;
  }

  // Traverse the middle subtree
  PrintHelper(root-&amp;gt;eq, buffer, depth + 1);

  // Traverse the right subtree
  PrintHelper(root-&amp;gt;right, buffer, depth);
 }
}

// Function to print TST&#39;s strings
void PrintAllStringsInTST(TSTNode* root)
{
 char buffer[MAX_LEN];
 PrintHelper(root, buffer, 0);
}

bool SearchTST(TSTNode *root, char* pattern)
{
 while (root != NULL)
 {
  if (*pattern &amp;lt; root-&amp;gt;data)
   root = root-&amp;gt;left;
  else if (*pattern == root-&amp;gt;data)
  {
   //If end of string flag is found and the pattern length is also exhausted, 
   //we can safely say that the pattern is present in the TST
   if (root-&amp;gt;bEOS &amp;amp;&amp;amp; *(pattern + 1) == &#39;\0&#39;)
    return true;
   pattern++;
   root = root-&amp;gt;eq;
  }
  else
   root = root-&amp;gt;right;
 }

 return false;
}

//Function to determine largest 
int MaxLenStringLen(TSTNode *root)
{
 if (root == NULL)
  return 0;

 int leftLen = MaxLenStringLen(root-&amp;gt;left);
 int middleLen = MaxLenStringLen(root-&amp;gt;eq) + 1;
 int rightLen = MaxLenStringLen(root-&amp;gt;right);

 return MAX( leftLen, middleLen, rightLen);
}

void DeleteTST(TSTNode *root)
{
 TSTNode *tmp = root;
 if (tmp)
 {
  DeleteTST(tmp-&amp;gt;left);
  DeleteTST(tmp-&amp;gt;eq);
  DeleteTST(tmp-&amp;gt;right);

#ifdef DEBUG_PROGRAM_MEMORY
  mem_addrs.erase(tmp);
#endif
  delete tmp;
 }
}

#ifdef DEBUG_PROGRAM_MEMORY
void CheckTSTMem()
{
 std::map&amp;lt;TSTNode*, char&amp;gt;::iterator itr = mem_addrs.begin();

 if (mem_addrs.size() == 0)
 {
  std::cout &amp;lt;&amp;lt; &quot;No memory leaks&quot;;
  return;
 }

 while (itr != mem_addrs.end()) 
 {
  std::cout &amp;lt;&amp;lt; &quot;Memory address &quot; &amp;lt;&amp;lt; itr-&amp;gt;first&amp;lt;&amp;lt; &quot; for \&quot;&quot; &amp;lt;&amp;lt; itr-&amp;gt;second &amp;lt;&amp;lt; &quot;\&quot; has not been deallocated&quot; &amp;lt;&amp;lt; std::endl;
  ++itr;
 }
}
#endif

&lt;/code&gt;
&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

//Main.cpp
#include &amp;lt;iostream&amp;gt;
#include &quot;TST.h&quot;

int main(int argc, char** argv) {
 
 TSTNode *root = NULL;
 root = Insert(root, &quot;boats&quot;);
 root = Insert(root, &quot;boat&quot;);
 root = Insert(root, &quot;bat&quot;);
 root = Insert(root, &quot;bats&quot;);
 root = Insert(root, &quot;stages&quot;);

 PrintAllStringsInTST(root);
 std::cout &amp;lt;&amp;lt; &quot;Maximum length string in this TST is of size &quot;&amp;lt;&amp;lt; MaxLenStringLen(root) &amp;lt;&amp;lt; std::endl;

 char *str = &quot;hello&quot;;
 char *str1 = &quot;bat&quot;;

 if (SearchTST(root, str) == false)
  std::cout &amp;lt;&amp;lt; &quot;\&quot;&quot;&amp;lt;&amp;lt;str&amp;lt;&amp;lt;&quot;\&quot; not found in TST&quot; &amp;lt;&amp;lt; std::endl;
 else
  std::cout &amp;lt;&amp;lt; &quot;\&quot;&quot; &amp;lt;&amp;lt; str &amp;lt;&amp;lt; &quot;\&quot; is present in TST&quot; &amp;lt;&amp;lt; std::endl;

 if (SearchTST(root, str1) == false)
  std::cout &amp;lt;&amp;lt; &quot;\&quot;&quot; &amp;lt;&amp;lt; str &amp;lt;&amp;lt; &quot;\&quot; not found in TST&quot; &amp;lt;&amp;lt; std::endl;
 else
  std::cout &amp;lt;&amp;lt; &quot;\&quot;&quot; &amp;lt;&amp;lt; str1 &amp;lt;&amp;lt; &quot;\&quot; is present in TST&quot; &amp;lt;&amp;lt; std::endl;

 DeleteTST(root);

#ifdef DEBUG_PROGRAM_MEMORY
 CheckTSTMem();
#endif
 
 return 0;
}

&lt;/code&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2016/10/ternary-search-tree-implementation-in-c.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguGduD0vChiSTnjE4_z63S7c4eq03iPdCxFtxaHHmwC99f8MD3M5QUjbF4JyqEFdYk-I7Tb9igf_70_yQgztDU26LUcZlgIn_s2dZoRXB2yJsM4V5xoYsB6-BHZSiLiDJH7arkX97D3dY/s72-c/Node.png" height="72" width="72"/><thr:total>8</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-7367041462673140787</guid><pubDate>Sat, 24 Sep 2016 15:01:00 +0000</pubDate><atom:updated>2023-12-20T23:02:41.178+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">efficient string matching</category><category domain="http://www.blogger.com/atom/ns#">KMP Algorithm</category><category domain="http://www.blogger.com/atom/ns#">knuth-morris-pratt algorithm</category><category domain="http://www.blogger.com/atom/ns#">pattern preprocessing</category><category domain="http://www.blogger.com/atom/ns#">prefix function</category><category domain="http://www.blogger.com/atom/ns#">Search Algorithm</category><category domain="http://www.blogger.com/atom/ns#">space complexity</category><category domain="http://www.blogger.com/atom/ns#">time complexity</category><title>String matching using KMP algorithm : C++ Implementation</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
KMP Algorithm is one the well-known string matching algorithms. It finds a pattern in a string. The pattern can exist multiple times in the string. This implementation in C++ gives indexes of all such matches in the string to be searched.&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIwpmFSXZ6fIPZNZRO_GMMSp0twPbWaElt80nRNVFZxdzK_OC9JvFqWlraiHqzCg2nwli5n5BzlJF0vUM9hI0IO1lwucGc4FuoqjQyQvWFPT_XikUBqorSYA9tZc18cryOP-0E4Gir2kXjupPpTfP-zbaca6KPfq97w4lVWiTPpTVIaEJVILk_ElQz0Wo/s896/kmp.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;448&quot; data-original-width=&quot;896&quot; height=&quot;213&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIwpmFSXZ6fIPZNZRO_GMMSp0twPbWaElt80nRNVFZxdzK_OC9JvFqWlraiHqzCg2nwli5n5BzlJF0vUM9hI0IO1lwucGc4FuoqjQyQvWFPT_XikUBqorSYA9tZc18cryOP-0E4Gir2kXjupPpTfP-zbaca6KPfq97w4lVWiTPpTVIaEJVILk_ElQz0Wo/w425-h213/kmp.png&quot; width=&quot;425&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
e.g.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
String to be searched : &quot;ABCDBCAAB ABCDABCDABDE ABCDABD&quot;&lt;br /&gt;
Pattern : &quot;ABCD&quot;&lt;br /&gt;
&lt;br /&gt;
The result will be 4 index locations 0, 10, 14 and 23&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;However, there is a limitation of KMP algorithm where the pattern overlaps.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;Consider this scenario :&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;String to be searched: &quot;ABCABCABCA&quot;&lt;br /&gt;
&amp;nbsp;Pattern: &quot;ABCA&quot;&lt;br /&gt;
&amp;nbsp;The result from KMP algorithm will be 0 and 6 locations. It cannot identify the overlapping matches &amp;nbsp;like this:&lt;br /&gt;
&amp;nbsp;&lt;b&gt;ABCA&lt;/b&gt;BCABCA&lt;br /&gt;
&amp;nbsp;ABC&lt;b&gt;ABCA&lt;/b&gt;BCA&lt;br /&gt;
&amp;nbsp;ABCABC&lt;b&gt;ABCA&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;

#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cstdlib&amp;gt;

using namespace std;
#define MAX_MATCHES 100

//Array to store matched indexes
int FOUND[MAX_MATCHES];
//variable to store last index in FOUND array
static int l = 0;

//Partial match table
void kmp_table(string W, int *T )
{
 int pos = 2;
 int cnd = 0;
 int length = W.length();
 
 T[0] = -1;
 T[1] = 0;
 
 while( pos &amp;lt; length)
 {
  if(W[pos-1] == W[cnd])
  {
   T[pos] = cnd + 1;
   cnd++;
   pos++;
  }
  else if( cnd &amp;gt; 0)
   cnd = T[cnd];
  else
  {
   T[pos] = 0;
   pos++;
  }
 }
}

//Search function
void kmp_search(string S, string W)
{
 
 int m = 0; 
 int i = 0;
 int sizeS = S.length();
 int sizeW = W.length();
 
 int *T = new int[sizeof(int) * sizeW];
 
 kmp_table(W, T);
 
 while( (m + i) &amp;lt; sizeS)
 {
  if (W[i] == S[m + i]) 
  {
            if (i == (sizeW - 1))
            {
             //Add the start index of match in the FOUND table
             FOUND[l++] = m;
   }
    
            i++;
        }
        else
        {
            if (T[i] &amp;gt; -1)
            {
                m = m + i - T[i];
    i = T[i];
            }
            else
            {
                m = m + 1;
    i = 0;
            }
        }
 }
 
 delete(T);
}

int main()
{
 string S = &quot;ABCDBCAAB ABCDABCDABDE ABCDABD&quot;;
 string W = &quot;ABCD&quot;;
 
 kmp_search(S,W);
  
 for (int i = 0 ; i &amp;lt; l; i++)
  cout&amp;lt;&amp;lt;&quot;Pattern found at &quot;&amp;lt;&amp;lt; FOUND[i] &amp;lt;&amp;lt;endl; 
}

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

&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2016/09/string-matching-using-kmp-algorithm.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIwpmFSXZ6fIPZNZRO_GMMSp0twPbWaElt80nRNVFZxdzK_OC9JvFqWlraiHqzCg2nwli5n5BzlJF0vUM9hI0IO1lwucGc4FuoqjQyQvWFPT_XikUBqorSYA9tZc18cryOP-0E4Gir2kXjupPpTfP-zbaca6KPfq97w4lVWiTPpTVIaEJVILk_ElQz0Wo/s72-w425-h213-c/kmp.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-6827868451772052062</guid><pubDate>Tue, 24 Feb 2015 12:22:00 +0000</pubDate><atom:updated>2023-12-20T21:31:17.592+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">COM</category><category domain="http://www.blogger.com/atom/ns#">Component Object Model</category><title>Component Object Model(COM) - Implementation in C++ -- Usage in C++, C#</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
As per &lt;a href=&quot;https://msdn.microsoft.com/en-US/library/727z646z(v=vs.80).aspx&quot; target=&quot;_blank&quot;&gt;Microsoft &lt;/a&gt;&quot;Component Object Model or COM is a platform-independent, distributed, object-oriented system for creating binary software components that can interact&quot;.&lt;br /&gt;
COM defines a standard (Object Model) and the implementation part is left to the developer. These objects can communicate within a process or across the processes, &amp;nbsp;on the same or different machine with different programming languages.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;Language requirement for COM :&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
1. Ability to create structures of pointers&lt;br /&gt;
&lt;br /&gt;
2. Ability to call functions using pointers&lt;br /&gt;
&lt;br /&gt;
Object-oriented languages such as C++ and Smalltalk provide programming mechanisms that simplify the implementation of COM objects, but languages such as C, Java, and VBScript can be used create and use COM objects.&lt;br /&gt;
&lt;br /&gt;
Object&#39;s data is accessed using interfaces. The functions of this interface are called methods. The pointers to these interfaces enables to call the methods.&lt;br /&gt;
&lt;br /&gt;
More information on COM is available at the &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/ms694363(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;MSDN &lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In a nutshell , COM provides interfaces which can be implemented in different languages and can be used over distributed platforms.&lt;br /&gt;
&lt;br /&gt;
To provide portability across platforms and programming languages, COM uses interface definition in platform-independent language, IDL(Interface Definition Language).&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
Steps involved to create COM interface:&lt;/h1&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Define the interface/s in .idl file.&lt;/li&gt;
&lt;li&gt;Compile the .idl file using IDL compiler(platform and language specific) to generate language and platform specific code.&lt;/li&gt;
&lt;li&gt;Implement these interface/s in the specific language.&lt;/li&gt;
&lt;li&gt;Use it.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
In our example, we are using MIDL compiler to generate the C++ specific code and DLL.&lt;br /&gt;
We will use ATL to make the implementation easier. ATL is the Active Template Library, a set of template-based C++ classes with which you can easily create small, fast Component Object Model (COM) objects. It has special support for key COM features including: stock implementations of IUnknown, IClassFactory, IClassFactory2, and IDispatch; dual interfaces; standard COM enumerator interfaces; connection points; tear-off interfaces; and ActiveX controls.&lt;br /&gt;
&lt;br /&gt;
We are using Visual Studio 2005 for our example. Visual Studio provides ATL project wizard which will help a lot and make the process easy.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h1&gt;
Steps to generate COM DLL:&lt;/h1&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt; Create a new project in Visual Studio File-&amp;gt;New-&amp;gt;Project-&amp;gt;Visual C++ -&amp;gt; ATL =&amp;gt; ATL Project.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6yqSej_8a02tGwMDFY9X68wNgF-kw653tYeNBYst1NqcuCHg2GfJNxmXnz1Dejm1MmMEKHuwrZqGtEWA6kR5K1HpBGhRBT0otakfOhgZ4xpYUenhWePUG9qnudK2FDSzU965g1HxG494/s1600/1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img alt=&quot;New Project&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6yqSej_8a02tGwMDFY9X68wNgF-kw653tYeNBYst1NqcuCHg2GfJNxmXnz1Dejm1MmMEKHuwrZqGtEWA6kR5K1HpBGhRBT0otakfOhgZ4xpYUenhWePUG9qnudK2FDSzU965g1HxG494/s1600/1.png&quot; height=&quot;427&quot; title=&quot;New Project&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; Give the project name as Calculator as we will be implementing a calculator interface using COM.
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ljRaRxKTY5fCwDwP5i9cBlONn3kOZqpuCliWUBaniMgEu_32JQv_nspfpwUjxmO33SyFv4tL9N7NCdYfF98t6vP6faV5US0qMEmzKOYxoRe_nrZjMafeicNWRO3o87_9KjRzBsMxpnE/s1600/2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;ATL Project&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ljRaRxKTY5fCwDwP5i9cBlONn3kOZqpuCliWUBaniMgEu_32JQv_nspfpwUjxmO33SyFv4tL9N7NCdYfF98t6vP6faV5US0qMEmzKOYxoRe_nrZjMafeicNWRO3o87_9KjRzBsMxpnE/s1600/2.png&quot; height=&quot;451&quot; title=&quot;ATL Project&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; Choose DLL(Dynamic-link library) in the Application Settings -&amp;gt; Finish.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGaXlrOqjXIMDeQMEnPyIyeUBdxU_BboLrsUHIHNqGU5KwyyeXl8qAVhl748LUh51MqcqVEByIL7_Q8tFfTa54NVnmSnIhvQ0a9DH5y29hKYB5SpVxTCQEfWZHj0uNuI1317Fmo7Uj9O8/s1600/3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Application Settings&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGaXlrOqjXIMDeQMEnPyIyeUBdxU_BboLrsUHIHNqGU5KwyyeXl8qAVhl748LUh51MqcqVEByIL7_Q8tFfTa54NVnmSnIhvQ0a9DH5y29hKYB5SpVxTCQEfWZHj0uNuI1317Fmo7Uj9O8/s1600/3.png&quot; height=&quot;451&quot; title=&quot;Application Settings&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; This structure will be visible once the project is created.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUcJIisASDv8LQgxu4qAsfzppLqfq6joRM-J6swLH7VNbTWSu_2i4RAbVKAdE0Fh049qi_Ksziz0TYkTjVX7tlxVgptk7j2IYKs3VolR8VjAXZ8Zw-F4pgKWaafx1q_-ZuZKHsjppNY-4/s1600/4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Project Structure&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUcJIisASDv8LQgxu4qAsfzppLqfq6joRM-J6swLH7VNbTWSu_2i4RAbVKAdE0Fh049qi_Ksziz0TYkTjVX7tlxVgptk7j2IYKs3VolR8VjAXZ8Zw-F4pgKWaafx1q_-ZuZKHsjppNY-4/s1600/4.png&quot; height=&quot;640&quot; title=&quot;Project Structure&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; Now add a class following the image as below. Right click on the project Add-&amp;gt;Class.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65oWzyImC1SfcE_tCp2XmPCkKCvFnRbxLFACgvsop6G5aL6wt0EqTRxfgvfJq0HS51gFk6JhWIt0tOXXuUS9R6AQxMLxmvSTpQ4oyMzPdL9yDI4C4WCpYvvAzfMH6RQVACAfgIhscgRQ/s1600/5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add COM Object&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65oWzyImC1SfcE_tCp2XmPCkKCvFnRbxLFACgvsop6G5aL6wt0EqTRxfgvfJq0HS51gFk6JhWIt0tOXXuUS9R6AQxMLxmvSTpQ4oyMzPdL9yDI4C4WCpYvvAzfMH6RQVACAfgIhscgRQ/s1600/5.png&quot; height=&quot;640&quot; title=&quot;Add COM Object&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; We will now add a COM Object using ATL Simple Object. 
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha1HPieDqnC8WB0ZITEWu4xAm4t-s-HeZf6fQxp3ovUaBih-nQV8BFdsYk4C7BiHcrrA5n5lYia3EX2CNxgU8NK1wXO4oaodjSPusAFWdVNB_zF6IOSFp42lbYH6Zywe-ba8D05B4t5Do/s1600/6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add COM Object&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha1HPieDqnC8WB0ZITEWu4xAm4t-s-HeZf6fQxp3ovUaBih-nQV8BFdsYk4C7BiHcrrA5n5lYia3EX2CNxgU8NK1wXO4oaodjSPusAFWdVNB_zF6IOSFp42lbYH6Zywe-ba8D05B4t5Do/s1600/6.png&quot; height=&quot;404&quot; title=&quot;Add COM Object&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; Give the name of class as CalculatorImpl (This defines the implentation of the interface). You can see under the panel C++ these four areas are updated -&amp;gt; Short Name, .h file, Class, .cpp file to be as CalculatorImpl, CalculatorImpl.h , CCalculatorImpl and CalculatorImpl.cpp respectively .

Also in the panel COM below, these four areas are also updated - CoClass, Type, Interface and ProgID.
Change these according to the image below.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNXbDoAlQRRa1gGqypfXnKR_uVOHxd11pS63qhalXBsSeGG-hYu4-7UYr-J49xU8BunZGSnNfGlZr0WRoy6k5xKg5OXN8ubxcvFuZ8mbF3aqwWw-IrycOGMFSNdj70qJgtkIxNvnhLaFU/s1600/7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;ATL Simple Object Wizard&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNXbDoAlQRRa1gGqypfXnKR_uVOHxd11pS63qhalXBsSeGG-hYu4-7UYr-J49xU8BunZGSnNfGlZr0WRoy6k5xKg5OXN8ubxcvFuZ8mbF3aqwWw-IrycOGMFSNdj70qJgtkIxNvnhLaFU/s1600/7.png&quot; height=&quot;449&quot; title=&quot;ATL Simple Object Wizard&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; Choose the Options for the COM Object as below, then click on Finish.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguno3pq_i-HZBKComuW3qtHPxGO_i1IJrTf4VxZ8mFP3C4qUBl_129m2t5jDOFje_YhoBkjOZb2G3JkxHMukg_GUiZAcnB1xeuKi2qOHUDL9RfgLbVITHND23uMd8SfhmF8FaS_hI7KAU/s1600/8.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;ATL Simple Object Wizard - Options&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguno3pq_i-HZBKComuW3qtHPxGO_i1IJrTf4VxZ8mFP3C4qUBl_129m2t5jDOFje_YhoBkjOZb2G3JkxHMukg_GUiZAcnB1xeuKi2qOHUDL9RfgLbVITHND23uMd8SfhmF8FaS_hI7KAU/s1600/8.png&quot; height=&quot;451&quot; title=&quot;ATL Simple Object Wizard - Options&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; After these changes, the Calculator.idl file will look like this:

&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9Jgg8WTHUmW1If42_X2YMaVQ3QshMTAPcOiiKJtBMq3LgK5I19a49LS_Wa5gknXWFXPYkW4U7dyLijsaXQf2KBvAUi2cx_346MtHxrjgXQkGmpXi9BeKSD9QO0-H4FX74gy-amlKHqU/s1600/9.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Calculator.idl&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9Jgg8WTHUmW1If42_X2YMaVQ3QshMTAPcOiiKJtBMq3LgK5I19a49LS_Wa5gknXWFXPYkW4U7dyLijsaXQf2KBvAUi2cx_346MtHxrjgXQkGmpXi9BeKSD9QO0-H4FX74gy-amlKHqU/s1600/9.png&quot; height=&quot;456&quot; title=&quot;Calculator.idl&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here, the declaration for interface ICalculator is added. ICalculator implements IDispatch interface. IDispatch is the interface that exposes the OLE Automation protocol. It is one of the standard interfaces exposed by COM. The IDispatch interface inherits from the IUnknown interface. More information on IDispatch can be found &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/ms221608(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp;You can also see the declaration of the Type Library CalculatorLib which declares a coclass Calculator as well. This CoClass creates a COM object, which can implement a COM interface.
 The Type library information helps in creating .tlb file which is a binary file that stores information about a COM or DCOM object&#39;s properties and methods in a form that is accessible to other applications at runtime. Using a type library, an application or browser can determine which interfaces an object supports, and invoke an object&#39;s interface methods. This can occur even if the object and client applications were written in different programming languages. The COM/DCOM run-time environment can also use a type library to provide automatic cross-apartment, cross-process, and cross-machine marshaling for interfaces described in type libraries.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt; Now our interface is ready to have some methods. Switch to Class View beside Solution Explorer as shown in image below. Right click on ICalculator interface and add a method. Add-&amp;gt;Add Method.
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXWOxY-FkFmwpQ8hTOdUMBr1aOWxY-NDhvkZAEPLMdW6FOyO8dS9zTEfwge4kkxFqcvSqEAi_WZoOhnmL66l4qL5Qzd8b-TSuX-KJ4RW97dQqPz0kmvIEuz-Z07mNtKJKjL2j5PWqREmQ/s1600/10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add Methods&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXWOxY-FkFmwpQ8hTOdUMBr1aOWxY-NDhvkZAEPLMdW6FOyO8dS9zTEfwge4kkxFqcvSqEAi_WZoOhnmL66l4qL5Qzd8b-TSuX-KJ4RW97dQqPz0kmvIEuz-Z07mNtKJKjL2j5PWqREmQ/s1600/10.png&quot; height=&quot;640&quot; title=&quot;Add Methods&quot; width=&quot;276&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; Give the method name as Add , check parameter attributes as &#39;in&#39;, parameter type DOUBLE, parameter name as Input1. Click on Add. You should see the parameter being added to the list box. Similarly add one more input parameter named Input2. Now add an output parameter with parameter type DOUBLE*, parameter name as pOutput, check parameter attributes as &#39;out&#39; and &#39;retval&#39;. Click on Add. 

Click on Next-&amp;gt;Finish.

&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiog3XlUBxUW_xIzlhGXpTMQMFaA37khEgH6VM32N6vp-J4Iq_TqzJdHLDDkrNCs4G1TaaRepkHKqamoKSLyMJVAdUVBK81FO-pxVfQ8sfNg9ZXEgR1_FwPsJKm2OcowESJKbe3yBvDwbU/s1600/11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add Method Wizard - Add Input&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiog3XlUBxUW_xIzlhGXpTMQMFaA37khEgH6VM32N6vp-J4Iq_TqzJdHLDDkrNCs4G1TaaRepkHKqamoKSLyMJVAdUVBK81FO-pxVfQ8sfNg9ZXEgR1_FwPsJKm2OcowESJKbe3yBvDwbU/s1600/11.png&quot; height=&quot;451&quot; title=&quot;Add Method Wizard - Add Input&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKogM2H1FfcSvTAdt4rY6E6hUtsc3OAoiiyxQrSgnGyKlTUYw7LcPpElrB50LKE-y1Z3KUi2hem1uaO5Rgp5x5gD3X84e3P4VUhkBKfkBsBB1G0EN3WyFyjKgcT95EitpgiLTVTFYEzI/s1600/12.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add Method Wizard - Add Output&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKogM2H1FfcSvTAdt4rY6E6hUtsc3OAoiiyxQrSgnGyKlTUYw7LcPpElrB50LKE-y1Z3KUi2hem1uaO5Rgp5x5gD3X84e3P4VUhkBKfkBsBB1G0EN3WyFyjKgcT95EitpgiLTVTFYEzI/s1600/12.png&quot; height=&quot;452&quot; title=&quot;Add Method Wizard - Add Output&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhio8AQjsTzRHlQoG4s1KDnB_r0j5JUGxa87PQPLBd8N9tb-bSsVUfnelhB1FBHMRNzqg13ExEnyEm-9dYY7iYHJvRGmDPpMDpsZxEDtv5N9G0C0M0ROxrLblbVKCVEQAROMXbnBavNPds/s1600/13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;IDL Attributes&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhio8AQjsTzRHlQoG4s1KDnB_r0j5JUGxa87PQPLBd8N9tb-bSsVUfnelhB1FBHMRNzqg13ExEnyEm-9dYY7iYHJvRGmDPpMDpsZxEDtv5N9G0C0M0ROxrLblbVKCVEQAROMXbnBavNPds/s1600/13.png&quot; height=&quot;449&quot; title=&quot;IDL Attributes&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

Similarly add three more methods Subtract, Multiply and Divide.&lt;br /&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; After adding the methods , you should see the functions&#39; skeleton created in Calculator.idl and CalculatorImpl.cpp like this :&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYeW6AxVJd0JNShJCWpPCl7b6O3L3hrQF150G8MPeyFmrKZiG1dQ2KLM0CySwmCehwrCImwfVdWEyrVJ9XU4lfvzSqZYfZBKyh03xG4YrMROGAeIWbyQUyTUvJJwefOPxhbp6PFVy4noI/s1600/14.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Calculator.idl&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYeW6AxVJd0JNShJCWpPCl7b6O3L3hrQF150G8MPeyFmrKZiG1dQ2KLM0CySwmCehwrCImwfVdWEyrVJ9XU4lfvzSqZYfZBKyh03xG4YrMROGAeIWbyQUyTUvJJwefOPxhbp6PFVy4noI/s1600/14.png&quot; height=&quot;387&quot; title=&quot;Calculator.idl&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeV5bxzyRloaM7gr_IKqj0lgRk-oTrCwq9vOT8mrYhmN3UedNlghvLRBfizucT0ertZf31WxkDhIi_TiCGWgi1yWum3-qiYyNPWpmAEzihQz0P4ptwywk-mmPHpRp5eTFL8YBgcpwYtF8/s1600/15.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;CalculatorImpl.cpp&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeV5bxzyRloaM7gr_IKqj0lgRk-oTrCwq9vOT8mrYhmN3UedNlghvLRBfizucT0ertZf31WxkDhIi_TiCGWgi1yWum3-qiYyNPWpmAEzihQz0P4ptwywk-mmPHpRp5eTFL8YBgcpwYtF8/s1600/15.png&quot; height=&quot;507&quot; title=&quot;CalculatorImpl.cpp&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt; We will add the implementation in the skeleton.

&lt;/li&gt;
&lt;li&gt; Now compile the solution. It will generate Calculator.dll in the project output directory (e.g. for 64 bit Release configuration it is %PROJECT_HOME%\Calculator\Calculator\x64\Release by default) &lt;/li&gt;
&lt;/ol&gt;
Now we have our COM DLL. To use it , we need some code.&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
Steps to create sample C++ code to test COM DLL:&lt;/h1&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Create an Empty Win32 Console Project in Visual Studio 
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPOFCgc2n_UEuu_RW7Fjs8sqaO5TTB7jSW5fZnjwRsmHMOjWZ35FzrCCBwYHLVdhcgm7vltvEE_we1pqyPIOOTMnU0nN-c1wZGhvftXmTXUOf0UHX-MXz9OcX5SIVFb9Vq_1tPU9oioK8/s1600/t1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Create Win32 Project&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPOFCgc2n_UEuu_RW7Fjs8sqaO5TTB7jSW5fZnjwRsmHMOjWZ35FzrCCBwYHLVdhcgm7vltvEE_we1pqyPIOOTMnU0nN-c1wZGhvftXmTXUOf0UHX-MXz9OcX5SIVFb9Vq_1tPU9oioK8/s1600/t1.png&quot; height=&quot;451&quot; title=&quot;Create Win32 Project&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; Create an Empty cpp file in the project (TestCalc.cpp)
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinFJFYyvDYFe2ZXYSEZ3VNDpHRPIiTsoK0iEgy45c-XmZStyBm0QsT0xdLVt6J-cnbqrH6upbXaDPc5HpAs9CL4d5ZBDhiO5zPxoMXai5hOgKjVdox5TFD1UY5owNqVtbHDDRNo_JqAU0/s1600/t2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Create Win32 Project - Application Settings&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinFJFYyvDYFe2ZXYSEZ3VNDpHRPIiTsoK0iEgy45c-XmZStyBm0QsT0xdLVt6J-cnbqrH6upbXaDPc5HpAs9CL4d5ZBDhiO5zPxoMXai5hOgKjVdox5TFD1UY5owNqVtbHDDRNo_JqAU0/s1600/t2.png&quot; height=&quot;451&quot; title=&quot;Create Win32 Project - Application Settings&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt; Add the path to Calculator.h in Additional Include Directories in the project properties. Right click project -&amp;gt; Properties -&amp;gt; Configuration Properties -&amp;gt; C/C++ -&amp;gt; General.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9vm1mO-n9aqZK_2OIKUzABbHpia_Gw_EosyKVE6ADXr8oFdRUd-zoEvjpCrDwsMKfdFXPQJ0Pwts352gYAUaFFbsAOKl8dK-2SCYxdYophT3B60NC6B8YgFRr7VRzdatdB60ffZ13SYY/s1600/t3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add Additional Includes&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9vm1mO-n9aqZK_2OIKUzABbHpia_Gw_EosyKVE6ADXr8oFdRUd-zoEvjpCrDwsMKfdFXPQJ0Pwts352gYAUaFFbsAOKl8dK-2SCYxdYophT3B60NC6B8YgFRr7VRzdatdB60ffZ13SYY/s1600/t3.png&quot; height=&quot;448&quot; title=&quot;Add Additional Includes&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; Add Calculator_i.c in the Project Source.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiusGkpG7ua-C1RaMlU10DgWPwyolYk3c8Wm4JCLvS7qYnh_l97vjvsNTJvJoGcAtnZRpYR0ESLoVrH4IzKp0DZNF6BMMGp0AGahgdjZhlyCCFUE08vsopNxnYNjqKZnJfBqhwu2Tplo-w/s1600/t4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add _i.c file&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiusGkpG7ua-C1RaMlU10DgWPwyolYk3c8Wm4JCLvS7qYnh_l97vjvsNTJvJoGcAtnZRpYR0ESLoVrH4IzKp0DZNF6BMMGp0AGahgdjZhlyCCFUE08vsopNxnYNjqKZnJfBqhwu2Tplo-w/s1600/t4.png&quot; height=&quot;640&quot; title=&quot;Add _i.c file&quot; width=&quot;459&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; Populate TestCalc.cpp with the contents given later in the blog post.&lt;/li&gt;
&lt;li&gt; Run the executable(F5).&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Note: One advantage using the Visual Studio to build our COM dll was that it registers the COM DLL by default. So we do not need to do it manually. This is the reason why we are able to run the test code even without the DLL being present in the System Path or adding it&#39;s path to PATH environment variable .&lt;br /&gt;
&lt;br /&gt;
Now as we have been saying that the COM is interoperable between the languages/platform etc. Let&#39;s see some code in action.&lt;br /&gt;
We are going to use the COM DLL generated in C# application.&lt;br /&gt;
&lt;br /&gt;
Before we go on using DLLs directly , let&#39;s be SMART and create .NET wrappers over COM DLL. Now you would ask what&#39;s that ??&lt;br /&gt;
&lt;br /&gt;
The COM components has unmanaged code while .NET framework has managed code. Data types, method signatures, and error-handling mechanisms vary between managed and unmanaged object models&lt;br /&gt;
Code that executes under the control of the runtime is called managed code and the code that runs outside the runtime is called unmanaged code.&lt;br /&gt;
&lt;br /&gt;
To simplify this, .NET wrappers are generated over existing COM components which allows unmanaged model to be converted to managed.&lt;br /&gt;
More information in this &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/5dxz80y2(v=vs.110).aspx&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
Steps to create .NET wrapper from COM DLL:&lt;/h1&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;Run this command from the output directory:&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;     tlbimp /machine: x64 Calculator.dll /out: Calculator_Wrapper.dll

&lt;/pre&gt;
&lt;/div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;It will generate Calculator_Wrapper.dll which is nothing but our .NET wrapper over COM.&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;h1&gt;
Steps to create C# application to test COM DLL :&lt;/h1&gt;
&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Create a Windows Application TestCalcCCharp from Visual Studio
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcQg6EKdU5XBeGBJjlnm6Q5_IdQk7Jubpvd6DhylpXHh1K4UcCLF78GpSWXQpT-vkaxx6xIf2Z0TjVGD5xmhZC2yF2QncKfSMZNSZpfT_6wKvEKzwF6F8JaTGNxek64yaItO8E-Z1gadA/s1600/cs1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Create Winform Application &quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcQg6EKdU5XBeGBJjlnm6Q5_IdQk7Jubpvd6DhylpXHh1K4UcCLF78GpSWXQpT-vkaxx6xIf2Z0TjVGD5xmhZC2yF2QncKfSMZNSZpfT_6wKvEKzwF6F8JaTGNxek64yaItO8E-Z1gadA/s1600/cs1.png&quot; height=&quot;428&quot; title=&quot;Create Winform Application &quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;/li&gt;
&lt;li&gt;Add a reference to the wrapper Calculator_Wrapper.dll
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyO9vsFHe0zjEzy1tpeH-9b9mNYkuuMLHTOO2dhldvoZcO05_ghTkldYHARrwQ67l8N6PK0nGRohNU66IFBZQlvaLVsg6yXTYBNblLWAkadpteo-WbJ0Xl72gayBXWiuptPCx4p_IdpdM/s1600/cs2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Add reference&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyO9vsFHe0zjEzy1tpeH-9b9mNYkuuMLHTOO2dhldvoZcO05_ghTkldYHARrwQ67l8N6PK0nGRohNU66IFBZQlvaLVsg6yXTYBNblLWAkadpteo-WbJ0Xl72gayBXWiuptPCx4p_IdpdM/s1600/cs2.png&quot; height=&quot;640&quot; title=&quot;Add reference&quot; width=&quot;436&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;


&lt;/li&gt;
&lt;li&gt;Create a simple form as per the code in the blog post.
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDKn_3NJ5lt4ju4oNNIz4wQHXOSMuuwUGVW5fcXvT5_P22rgyP9M3zkYnx8-BQrHuIIDZ-HbfKQ8JUEHQRWXiQnAGSTgdw-itSU5DWfLUtGzsyIWo78cYdTi0PE8TTiwbGBuvoP8Nv1ik/s1600/cs3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Winform &quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDKn_3NJ5lt4ju4oNNIz4wQHXOSMuuwUGVW5fcXvT5_P22rgyP9M3zkYnx8-BQrHuIIDZ-HbfKQ8JUEHQRWXiQnAGSTgdw-itSU5DWfLUtGzsyIWo78cYdTi0PE8TTiwbGBuvoP8Nv1ik/s1600/cs3.png&quot; height=&quot;530&quot; title=&quot;Winform &quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Populate the functions to call the methods from COM.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

// CalculatorImpl.cpp : Implementation of CCalculatorImpl

#include &quot;stdafx.h&quot;
#include &quot;CalculatorImpl.h&quot;

// CCalculatorImpl

STDMETHODIMP CCalculatorImpl::Add(DOUBLE Input1, DOUBLE Input2, DOUBLE* pOutput)
{
 *pOutput = Input1 + Input2;

 return S_OK;
}

STDMETHODIMP CCalculatorImpl::Subtract(DOUBLE Input1, DOUBLE Input2, DOUBLE* pOutput)
{
 *pOutput = Input1 - Input2;
 
 return S_OK;
}

STDMETHODIMP CCalculatorImpl::Multiply(DOUBLE Input1, DOUBLE Input2, DOUBLE* pOutput)
{
 *pOutput = Input1 * Input2;

 return S_OK;
}

STDMETHODIMP CCalculatorImpl::Divide(DOUBLE Input1, DOUBLE Input2, DOUBLE* pOutput)
{
 *pOutput = Input1 / Input2;

 return S_OK;
}

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


&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

//TestCalc.cpp
#include &quot;Calculator.h&quot;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;stdexcept&amp;gt;
using std::runtime_error; 

int main()
{
 HRESULT hr ;
 ICalculator      *calc = NULL;

 hr = CoInitialize(0);

 if(SUCCEEDED(hr))
    {
  hr = CoCreateInstance( CLSID_Calculator, NULL, 
            CLSCTX_INPROC_SERVER,
   IID_ICalculator, (void**) &amp;amp;calc);

        // If we succeeded then call the Add 
        // method, if it failed
        // then display an appropriate message to the user.
        if(SUCCEEDED(hr))
        {
            double ReturnValue;
   double a = 4;
   double b = 0;
   calc-&amp;gt;Add(a, b, &amp;amp;ReturnValue);
            std::cout &amp;lt;&amp;lt; &quot;The answer for &quot;&amp;lt;&amp;lt;a&amp;lt;&amp;lt;&quot; + &quot;&amp;lt;&amp;lt;b&amp;lt;&amp;lt;&quot; is: &quot; 
                &amp;lt;&amp;lt; ReturnValue &amp;lt;&amp;lt; std::endl;
            calc-&amp;gt;Release(); 
        }
        else
        {
            std::cout &amp;lt;&amp;lt; &quot;CoCreateInstance Failed.&quot; &amp;lt;&amp;lt; std::endl;
        }
    }
    // Uninitialize COM
    CoUninitialize();

}

&lt;/code&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;
//Form1.Designer.cs
namespace TestCalcCSharp
{
    partial class Form1
    {
        /// &amp;lt;summary&amp;gt;
        /// Required designer variable.
        /// &amp;lt;/summary&amp;gt;
        private System.ComponentModel.IContainer components = null;

        /// &amp;lt;summary&amp;gt;
        /// Clean up any resources being used.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&quot;disposing&quot;&amp;gt;true if managed resources should be disposed; otherwise, false.&amp;lt;/param&amp;gt;
        protected override void Dispose(bool disposing)
        {
            if (disposing &amp;amp;&amp;amp; (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// &amp;lt;summary&amp;gt;
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// &amp;lt;/summary&amp;gt;
        private void InitializeComponent()
        {
            this.calcPanel = new System.Windows.Forms.GroupBox();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.logTextBox = new System.Windows.Forms.RichTextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.divBtn = new System.Windows.Forms.Button();
            this.subBtn = new System.Windows.Forms.Button();
            this.addBtn = new System.Windows.Forms.Button();
            this.mulBtn = new System.Windows.Forms.Button();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.calcPanel.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // calcPanel
            // 
            this.calcPanel.Controls.Add(this.groupBox1);
            this.calcPanel.Controls.Add(this.label5);
            this.calcPanel.Controls.Add(this.label4);
            this.calcPanel.Controls.Add(this.label1);
            this.calcPanel.Controls.Add(this.divBtn);
            this.calcPanel.Controls.Add(this.subBtn);
            this.calcPanel.Controls.Add(this.addBtn);
            this.calcPanel.Controls.Add(this.mulBtn);
            this.calcPanel.Controls.Add(this.textBox3);
            this.calcPanel.Controls.Add(this.textBox2);
            this.calcPanel.Controls.Add(this.label3);
            this.calcPanel.Controls.Add(this.label2);
            this.calcPanel.Controls.Add(this.textBox1);
            this.calcPanel.Location = new System.Drawing.Point(13, 13);
            this.calcPanel.Name = &quot;calcPanel&quot;;
            this.calcPanel.Size = new System.Drawing.Size(450, 344);
            this.calcPanel.TabIndex = 0;
            this.calcPanel.TabStop = false;
            this.calcPanel.Text = &quot;Calculator&quot;;
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.logTextBox);
            this.groupBox1.Location = new System.Drawing.Point(6, 238);
            this.groupBox1.Name = &quot;groupBox1&quot;;
            this.groupBox1.Size = new System.Drawing.Size(438, 100);
            this.groupBox1.TabIndex = 34;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = &quot;Logs&quot;;
            // 
            // logTextBox
            // 
            this.logTextBox.Location = new System.Drawing.Point(6, 19);
            this.logTextBox.Name = &quot;logTextBox&quot;;
            this.logTextBox.Size = new System.Drawing.Size(432, 81);
            this.logTextBox.TabIndex = 33;
            this.logTextBox.Text = &quot;&quot;;
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(254, 22);
            this.label5.Name = &quot;label5&quot;;
            this.label5.Size = new System.Drawing.Size(37, 13);
            this.label5.TabIndex = 32;
            this.label5.Text = &quot;Result&quot;;
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(163, 22);
            this.label4.Name = &quot;label4&quot;;
            this.label4.Size = new System.Drawing.Size(37, 13);
            this.label4.TabIndex = 31;
            this.label4.Text = &quot;Input2&quot;;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(83, 22);
            this.label1.Name = &quot;label1&quot;;
            this.label1.Size = new System.Drawing.Size(37, 13);
            this.label1.TabIndex = 30;
            this.label1.Text = &quot;Input1&quot;;
            // 
            // divBtn
            // 
            this.divBtn.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.divBtn.Location = new System.Drawing.Point(352, 134);
            this.divBtn.Name = &quot;divBtn&quot;;
            this.divBtn.Size = new System.Drawing.Size(75, 36);
            this.divBtn.TabIndex = 29;
            this.divBtn.Text = &quot;Divide&quot;;
            this.divBtn.UseVisualStyleBackColor = true;
            this.divBtn.Click += new System.EventHandler(this.divBtn_Click);
            // 
            // subBtn
            // 
            this.subBtn.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.subBtn.Location = new System.Drawing.Point(125, 134);
            this.subBtn.Name = &quot;subBtn&quot;;
            this.subBtn.Size = new System.Drawing.Size(75, 36);
            this.subBtn.TabIndex = 28;
            this.subBtn.Text = &quot;Subtract&quot;;
            this.subBtn.UseVisualStyleBackColor = true;
            this.subBtn.Click += new System.EventHandler(this.subBtn_Click);
            // 
            // addBtn
            // 
            this.addBtn.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.addBtn.Location = new System.Drawing.Point(14, 134);
            this.addBtn.Name = &quot;addBtn&quot;;
            this.addBtn.Size = new System.Drawing.Size(75, 36);
            this.addBtn.TabIndex = 27;
            this.addBtn.Text = &quot;Add&quot;;
            this.addBtn.UseVisualStyleBackColor = true;
            this.addBtn.Click += new System.EventHandler(this.addBtn_Click);
            // 
            // mulBtn
            // 
            this.mulBtn.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.mulBtn.Location = new System.Drawing.Point(239, 134);
            this.mulBtn.Name = &quot;mulBtn&quot;;
            this.mulBtn.Size = new System.Drawing.Size(75, 36);
            this.mulBtn.TabIndex = 26;
            this.mulBtn.Text = &quot;Multiply&quot;;
            this.mulBtn.UseVisualStyleBackColor = true;
            this.mulBtn.Click += new System.EventHandler(this.mulBtn_Click);
            // 
            // textBox3
            // 
            this.textBox3.Enabled = false;
            this.textBox3.Location = new System.Drawing.Point(257, 41);
            this.textBox3.Name = &quot;textBox3&quot;;
            this.textBox3.Size = new System.Drawing.Size(170, 20);
            this.textBox3.TabIndex = 7;
            // 
            // textBox2
            // 
            this.textBox2.Location = new System.Drawing.Point(166, 41);
            this.textBox2.Name = &quot;textBox2&quot;;
            this.textBox2.Size = new System.Drawing.Size(57, 20);
            this.textBox2.TabIndex = 6;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.label3.Location = new System.Drawing.Point(228, 44);
            this.label3.Name = &quot;label3&quot;;
            this.label3.Size = new System.Drawing.Size(16, 17);
            this.label3.TabIndex = 4;
            this.label3.Text = &quot;=&quot;;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font(&quot;Microsoft Sans Serif&quot;, 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.label2.Location = new System.Drawing.Point(146, 44);
            this.label2.Name = &quot;label2&quot;;
            this.label2.Size = new System.Drawing.Size(16, 17);
            this.label2.TabIndex = 3;
            this.label2.Text = &quot;+&quot;;
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(83, 41);
            this.textBox1.Name = &quot;textBox1&quot;;
            this.textBox1.Size = new System.Drawing.Size(57, 20);
            this.textBox1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(475, 369);
            this.Controls.Add(this.calcPanel);
            this.Name = &quot;Form1&quot;;
            this.Text = &quot;Calculator&quot;;
            this.calcPanel.ResumeLayout(false);
            this.calcPanel.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.GroupBox calcPanel;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox3;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Button mulBtn;
        private System.Windows.Forms.Button divBtn;
        private System.Windows.Forms.Button subBtn;
        private System.Windows.Forms.Button addBtn;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.RichTextBox logTextBox;
        private System.Windows.Forms.GroupBox groupBox1;

    }
}


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

&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;
//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Calculator_Wrapper;
using System.Runtime.InteropServices;

namespace TestCalcCSharp
{
    public partial class Form1 : Form
    {
        Calculator_Wrapper.Calculator calc = null;

        public Form1()
        {
            InitializeComponent();
            calc = new Calculator();
        }

        private void addBtn_Click(object sender, EventArgs e)
        {
            try
            {
                double inp1 = double.Parse(textBox1.Text);
                double inp2 = double.Parse(textBox2.Text);


                double output = calc.Add(inp1, inp2);

                textBox3.Text = output.ToString();
            }
            catch (Exception ex)
            {
                logTextBox.Text = ex.Message;
            }
        }

        private void subBtn_Click(object sender, EventArgs e)
        {
            try
            {
                double inp1 = double.Parse(textBox1.Text);
                double inp2 = double.Parse(textBox2.Text);


                double output = calc.Subtract(inp1, inp2);

                textBox3.Text = output.ToString();
            }
            catch (Exception ex)
            {
                logTextBox.Text = ex.Message;
            }
        }

        private void mulBtn_Click(object sender, EventArgs e)
        {
            try
            {
                double inp1 = double.Parse(textBox1.Text);
                double inp2 = double.Parse(textBox2.Text);

                double output = calc.Multiply(inp1, inp2);

                textBox3.Text = output.ToString();
            }
            catch (Exception ex)
            {
                logTextBox.Text = ex.Message;
            }
        }

        private void divBtn_Click(object sender, EventArgs e)
        {
            try
            {
                double inp1 = double.Parse(textBox1.Text);
                double inp2 = double.Parse(textBox2.Text);

                if (inp2 == 0) throw new DivideByZeroException();
                double output = calc.Divide(inp1, inp2);
                textBox3.Text = output.ToString();
            }
            catch (Exception ex)
            {
                logTextBox.Text = ex.Message + &quot;\n&quot;;
            }
        }
    }
}

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

&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2015/02/componentobjectmodelcom.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6yqSej_8a02tGwMDFY9X68wNgF-kw653tYeNBYst1NqcuCHg2GfJNxmXnz1Dejm1MmMEKHuwrZqGtEWA6kR5K1HpBGhRBT0otakfOhgZ4xpYUenhWePUG9qnudK2FDSzU965g1HxG494/s72-c/1.png" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5234970854753038822</guid><pubDate>Sun, 26 Oct 2014 16:33:00 +0000</pubDate><atom:updated>2023-12-21T00:19:14.594+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design Patterns</category><category domain="http://www.blogger.com/atom/ns#">facade design pattern</category><title>Facade design pattern implementation in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Facade &lt;/i&gt;&lt;/b&gt;means the exterior of any object in general. Facade Design Pattern provides similar functionality as well. It provides a simple interface to a complex system.

Just as we can not tell from the exterior of a building what lies inside it, Facade design pattern provides an interface which hides the internal complexity of a system.
It only exposes the desired interfaces which have to be used by a client. It can be only a small subsystem of the complex system as the client may not need all the functionality of the complex system. Also it could modify the interfaces as well to provide the complete functionality of the system.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1JrJeJkRpdSUZbykBJbaeyiPhZDJu7cRF4Feej_hIkRzpbQzuM71_Z7tGzUO9BW9j2SIyu1657UgZGaq94Eu6_MrA6x9RStN0EZpjC_5AA3u88bltAejru3WgFo8zo5taMUKsTlvXqcM/s1600/facade.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img alt=&quot;Facade Design Pattern&quot; border=&quot;0&quot; height=&quot;522&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1JrJeJkRpdSUZbykBJbaeyiPhZDJu7cRF4Feej_hIkRzpbQzuM71_Z7tGzUO9BW9j2SIyu1657UgZGaq94Eu6_MrA6x9RStN0EZpjC_5AA3u88bltAejru3WgFo8zo5taMUKsTlvXqcM/s1600/facade.png&quot; title=&quot;Facade Design Pattern&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Facade Design Pattern&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&amp;nbsp;For our implementation of the Facade Design Pattern, we have chosen example of Online Shopping model. The following diagram represents the relationships and flow between the classes.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2r92vQywDbSqKoUS7vtRQykLQB6VCH3u5LLMIE_5Cx0g8Rqou7xU6CjRZk_dxzgz8_eyMtsCHd7K_NyW0MOLqVZpc2GV99fOqBZtXxswrohMx2_gG5lU4D10QqQC41q8p82zVjCR4_AE/s1600/facademy.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;522&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2r92vQywDbSqKoUS7vtRQykLQB6VCH3u5LLMIE_5Cx0g8Rqou7xU6CjRZk_dxzgz8_eyMtsCHd7K_NyW0MOLqVZpc2GV99fOqBZtXxswrohMx2_gG5lU4D10QqQC41q8p82zVjCR4_AE/s1600/facademy.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Class Diagram for below example&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The example works like this. OnlineShoppingFacade is the interface which is exposed to the customers (us). It&#39;s just like any portal like Flipkart, Amazon or eBay. Now we do not know what the heck is going behind those websites. All we know is that we have just placed an order and we will get a delivery after a certain period of time. Of course there is a status tracker something like this&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpEoCPVnQOWUoOHTfdcVX9SRLTDzox80kZLXSeLXAK6Vz9Jp3pWTkigtoej_WTWbkirk8WCNlVKMxjqkaz6oUPXM6zPumlBLyA6Yo1fu4OivoFfqINIG3npDiJnV0I4pgjgzrXebR28ZA/s1600/order.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;64&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpEoCPVnQOWUoOHTfdcVX9SRLTDzox80kZLXSeLXAK6Vz9Jp3pWTkigtoej_WTWbkirk8WCNlVKMxjqkaz6oUPXM6zPumlBLyA6Yo1fu4OivoFfqINIG3npDiJnV0I4pgjgzrXebR28ZA/s1600/order.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
But still the intricacies behind the process is hidden away from us. This is the Facade for the Online Shopping Portal.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Below is a simplistic implementation just to demo how Facade Design Pattern works using a C++ example.&lt;br /&gt;
&lt;br /&gt;

&lt;h1&gt;Facade Design Pattern Implementation(C++)&lt;/h1&gt;
&lt;b&gt;&lt;u&gt;Update(5th Nov 2014)&lt;/u&gt;&lt;/b&gt;: The code is updated to work on linux platform as well.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;

#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;
#ifdef _WIN32
#include &amp;lt;windows.h&amp;gt;
#elif defined __linux__
#include &amp;lt;unistd.h&amp;gt;
#endif

/* Uncomment below line to enable debug logs */
/* #define DEBUG */
 
std::string _stateToStrCourier[]   = { &quot;Received&quot;, &quot;VerifyReachbility&quot;, &quot;AssignPerson&quot;, 
                                       &quot;DispatchPackage&quot;, &quot;GetDeliveryConfirmation&quot;, &quot;Complete&quot;};
std::string _stateToStrVendor[]    = { &quot;Received&quot;, &quot;VerifyInventory&quot;, &quot;GetItemFromWareHouse&quot;, 
                                       &quot;PackItem&quot;, &quot;ContactCourier&quot;, &quot;Complete&quot;};
std::string _stateToStrOrderTeam[] = { &quot;Received&quot;, &quot;VerifyPayment&quot;, &quot;ContactVendor&quot;, &quot;Complete&quot;};

void mySleep(unsigned int millisecs)
{
#ifdef _WIN32
 Sleep(millisecs);
#elif defined __linux__
 usleep(1000 * millisecs);
#endif
}

class Courier
{
public:
 void submitRequestToCourier()
 {
  _state = 0;
 }
 bool checkStatus()
 {
#ifdef DEBUG
  std::cout&amp;lt;&amp;lt;&quot;Courier: Current State: &quot;&amp;lt;&amp;lt;_stateToStrCourier[_state]&amp;lt;&amp;lt; std::endl;
#endif
  mySleep(500); /* Do some useful work here */

  _state++;
  if (_state == Complete)
   return 1;
  return 0;
 }
private:
 enum States
 {
  Received, VerifyReachbility, AssignPerson, DispatchPackage, GetDeliveryConfirmation, Complete
 };
 int _state;
};
 
class Vendor
{
public:
 void submitRequestToVendor()
 {
  _state = 0;
 }
 bool checkStatus()
 {
#ifdef DEBUG
  std::cout&amp;lt;&amp;lt;&quot;Vendor: Current State: &quot;&amp;lt;&amp;lt;_stateToStrVendor[_state]&amp;lt;&amp;lt; std::endl;
#endif
  mySleep(500); /* Do some useful work here */

  _state++;
  if (_state == Complete)
   return 1;
  return 0;
 }
private:
 enum States
 {
  Received, VerifyInventory, GetItemFromWareHouse, PackItem, ContactCourier, Complete
 };
 int _state;
 
};
 
class OrderingTeam
{
public:
 void submitRequestToOrderTeam()
 {
  _state = 0;
 }
 bool checkStatus()
 {
#ifdef DEBUG
  std::cout&amp;lt;&amp;lt;&quot;OrderingTeam: Current State: &quot;&amp;lt;&amp;lt;_stateToStrOrderTeam[_state]&amp;lt;&amp;lt; std::endl;
#endif
  mySleep(500); /* Do some useful work here */ 
  _state++;
  if (_state == Complete)
   return 1;
  return 0;
 }
private:
 enum States
 {
  Received, VerifyPayment, ContactVendor, Complete
 };
 int _state;
};
 
class OnlineShoppingFacade
{
public:
 OnlineShoppingFacade()
 {
  _count = 0;
 }
 void submitRequest()
 {
  _state = 0;
 }
 bool checkStatus()
 {
  /* Item request has just been received */
  switch(_state)
  {
  case Received:
   _state++;
   /* Forward the job request to the ordering team */
   _order.submitRequestToOrderTeam();
   std::cout &amp;lt;&amp;lt; &quot;submitted to Order Team - &quot; &amp;lt;&amp;lt; _count &amp;lt;&amp;lt;
    &quot; followups till now&quot; &amp;lt;&amp;lt; std::endl;
   break;
  case SubmittedToOrderTeam:
   /* If order team has completed verification, 
   place the request with vendor */
   if (_order.checkStatus())
   {
    _state++;
    _vendor.submitRequestToVendor();
    std::cout &amp;lt;&amp;lt; &quot;submitted to Vendor - &quot; &amp;lt;&amp;lt; _count &amp;lt;&amp;lt;
     &quot; followups till now&quot; &amp;lt;&amp;lt; std::endl;
   }
   break;
  case SubmittedToVendor:
   /* If vendor has packed the item, forward it to courier */
   if (_vendor.checkStatus())
   {
    _state++;
    _courier.submitRequestToCourier();
    std::cout &amp;lt;&amp;lt; &quot;submitted to Courier - &quot; &amp;lt;&amp;lt; _count &amp;lt;&amp;lt;
     &quot; followups till now&quot; &amp;lt;&amp;lt; std::endl;
   }
   break;
  case SubmittedToCourier:
   /* If package is delivered, order is complete */
   if (_courier.checkStatus())
    return 1;
  default:
   break;
  }
 
  _count++;
 
  /* The order is not complete */
  return 0;
 }
 int numFUPs()
 
 {
  return _count;
 }
private:
 enum States
 {
  Received, SubmittedToOrderTeam, SubmittedToVendor, SubmittedToCourier
 };
 
 int _state;
 int _count;
 
 OrderingTeam _order;
 Vendor _vendor;
 Courier _courier;
};
 
int main()
{
 OnlineShoppingFacade onlinereq;
 
 onlinereq.submitRequest();
 
 /* Keep checking until order is complete */
 while (!onlinereq.checkStatus());
 
 std::cout &amp;lt;&amp;lt; &quot;Order completed after &quot; &amp;lt;&amp;lt; onlinereq.numFUPs() &amp;lt;&amp;lt; 
  &quot; followups&quot; &amp;lt;&amp;lt; std::endl;
}

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

&lt;/div&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2014/10/facade-design-pattern-in-cpp.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1JrJeJkRpdSUZbykBJbaeyiPhZDJu7cRF4Feej_hIkRzpbQzuM71_Z7tGzUO9BW9j2SIyu1657UgZGaq94Eu6_MrA6x9RStN0EZpjC_5AA3u88bltAejru3WgFo8zo5taMUKsTlvXqcM/s72-c/facade.png" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-4469157678134993840</guid><pubDate>Sat, 18 Oct 2014 17:07:00 +0000</pubDate><atom:updated>2023-12-21T00:39:36.532+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">gSOAP</category><category domain="http://www.blogger.com/atom/ns#">SOAP</category><category domain="http://www.blogger.com/atom/ns#">Web Service</category><category domain="http://www.blogger.com/atom/ns#">Xerces</category><category domain="http://www.blogger.com/atom/ns#">XML</category><title>Create a SOAP web service client in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;h1&gt;What is SOAP?&lt;/h1&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjox1D6j-O6zV_8eUuRlKiJSNV6FtUYaZRbYraOrsLk4LduY-KX2Wjq1gzSI-eSVegmzaCt4HL_gNJFSGJg9irUOT9Gr5ol7qhqumbImE9HSoKDpS8AI2umxojjmf6Z6S-TSeP6iCkwYTHArz0UB_HbIzU7-_SNfQdyNVnXL_ta8N1fI4u74E1jiTh7lzs/s1024/soap_black.jpeg&quot; style=&quot;display: block; padding: 1em 0px; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjox1D6j-O6zV_8eUuRlKiJSNV6FtUYaZRbYraOrsLk4LduY-KX2Wjq1gzSI-eSVegmzaCt4HL_gNJFSGJg9irUOT9Gr5ol7qhqumbImE9HSoKDpS8AI2umxojjmf6Z6S-TSeP6iCkwYTHArz0UB_HbIzU7-_SNfQdyNVnXL_ta8N1fI4u74E1jiTh7lzs/s320/soap_black.jpeg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;  
SOAP(Simple Object Access Protocol) is a great way to exchange information over the network. Normally it is used with application protocols like HTTP, SMTP etc. The envelope containing the information is XML based.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
It provides the basic messaging infrastructure for web services.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
An example SOAP request looks like :&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;

&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;soapenv:Envelope
        xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;
        xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
        xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;gt;
  &amp;lt;soapenv:Header&amp;gt;
    &amp;lt;ns1:RequestHeader
         soapenv:actor=&quot;http://schemas.xmlsoap.org/soap/actor/next&quot;
         soapenv:mustUnderstand=&quot;0&quot;
         xmlns:ns1=&quot;https://www.google.com/apis/ads/publisher/v201403&quot;&amp;gt;
      &amp;lt;ns1:networkCode&amp;gt;123456&amp;lt;/ns1:networkCode&amp;gt;
      &amp;lt;ns1:applicationName&amp;gt;DfpApi-Java-2.1.0-dfp_test&amp;lt;/ns1:applicationName&amp;gt;
    &amp;lt;/ns1:RequestHeader&amp;gt;
  &amp;lt;/soapenv:Header&amp;gt;
  &amp;lt;soapenv:Body&amp;gt;
    &amp;lt;getAdUnitsByStatement xmlns=&quot;https://www.google.com/apis/ads/publisher/v201403&quot;&amp;gt;
      &amp;lt;filterStatement&amp;gt;
        &amp;lt;query&amp;gt;WHERE parentId IS NULL LIMIT 500&amp;lt;/query&amp;gt;
      &amp;lt;/filterStatement&amp;gt;
    &amp;lt;/getAdUnitsByStatement&amp;gt;
  &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;

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

The corresponding response would look like :
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-xml&quot;&gt;
&amp;lt;soap:Envelope xmlns:soap=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&amp;gt;
  &amp;lt;soap:Header&amp;gt;
    &amp;lt;ResponseHeader xmlns=&quot;https://www.google.com/apis/ads/publisher/v201403&quot;&amp;gt;
      &amp;lt;requestId&amp;gt;xxxxxxxxxxxxxxxxxxxx&amp;lt;/requestId&amp;gt;
      &amp;lt;responseTime&amp;gt;1063&amp;lt;/responseTime&amp;gt;
    &amp;lt;/ResponseHeader&amp;gt;
  &amp;lt;/soap:Header&amp;gt;
  &amp;lt;soap:Body&amp;gt;
    &amp;lt;getAdUnitsByStatementResponse xmlns=&quot;https://www.google.com/apis/ads/publisher/v201403&quot;&amp;gt;
      &amp;lt;rval&amp;gt;
        &amp;lt;totalResultSetSize&amp;gt;1&amp;lt;/totalResultSetSize&amp;gt;
        &amp;lt;startIndex&amp;gt;0&amp;lt;/startIndex&amp;gt;
        &amp;lt;results&amp;gt;
          &amp;lt;id&amp;gt;2372&amp;lt;/id&amp;gt;
          &amp;lt;name&amp;gt;RootAdUnit&amp;lt;/name&amp;gt;
          &amp;lt;description&amp;gt;&amp;lt;/description&amp;gt;
          &amp;lt;targetWindow&amp;gt;TOP&amp;lt;/targetWindow&amp;gt;
          &amp;lt;status&amp;gt;ACTIVE&amp;lt;/status&amp;gt;
          &amp;lt;adUnitCode&amp;gt;1002372&amp;lt;/adUnitCode&amp;gt;
          &amp;lt;inheritedAdSenseSettings&amp;gt;
            &amp;lt;value&amp;gt;
              &amp;lt;adSenseEnabled&amp;gt;true&amp;lt;/adSenseEnabled&amp;gt;
              &amp;lt;borderColor&amp;gt;FFFFFF&amp;lt;/borderColor&amp;gt;
              &amp;lt;titleColor&amp;gt;0000FF&amp;lt;/titleColor&amp;gt;
              &amp;lt;backgroundColor&amp;gt;FFFFFF&amp;lt;/backgroundColor&amp;gt;
              &amp;lt;textColor&amp;gt;000000&amp;lt;/textColor&amp;gt;
              &amp;lt;urlColor&amp;gt;008000&amp;lt;/urlColor&amp;gt;
              &amp;lt;adType&amp;gt;TEXT_AND_IMAGE&amp;lt;/adType&amp;gt;
              &amp;lt;borderStyle&amp;gt;DEFAULT&amp;lt;/borderStyle&amp;gt;
              &amp;lt;fontFamily&amp;gt;DEFAULT&amp;lt;/fontFamily&amp;gt;
              &amp;lt;fontSize&amp;gt;DEFAULT&amp;lt;/fontSize&amp;gt;
            &amp;lt;/value&amp;gt;
          &amp;lt;/inheritedAdSenseSettings&amp;gt;
        &amp;lt;/results&amp;gt;
      &amp;lt;/rval&amp;gt;
    &amp;lt;/getAdUnitsByStatementResponse&amp;gt;
  &amp;lt;/soap:Body&amp;gt;
&amp;lt;/soap:Envelope&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

  
&lt;span style=&quot;font-size: xx-small;&quot;&gt;Courtesy :&amp;nbsp;&lt;a href=&quot;https://developers.google.com/doubleclick-publishers/docs/soap_xml&quot;&gt;https://developers.google.com/doubleclick-publishers/docs/soap_xml&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The above is an example of Google&#39;s web service which provides Ad Units to the requester based on some filters.&lt;br /&gt;
&lt;br /&gt;
Web Services provide an easy platform independent way to exchange information over the network.&lt;br /&gt;
The following picture shows the basic flow on how the Service Provider caters the request of the consumer.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2jTrSKGAUSHZgCuq6Y2aT5Qb4oS3FHOuzYrDsVIslg-zwcTZ-cYP9KoRdvBknvNFYJV8qvnJ6z5AX19oiIkajXIEkz2SH730jKlmgTvmu6OVVKtgiWMEuri9cyLpLz7plVLOG9WUv3C4/s1600/soap_messages.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;260&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2jTrSKGAUSHZgCuq6Y2aT5Qb4oS3FHOuzYrDsVIslg-zwcTZ-cYP9KoRdvBknvNFYJV8qvnJ6z5AX19oiIkajXIEkz2SH730jKlmgTvmu6OVVKtgiWMEuri9cyLpLz7plVLOG9WUv3C4/s1600/soap_messages.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Source: &lt;a href=&quot;http://www.service-architecture.com/&quot;&gt;http://www.service-architecture.com&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Following is an implementation of a SOAP client in C++ which calls the Web Service to get the stock quotes based on a symbol(company ticker).&lt;br /&gt;
&lt;br /&gt;
The example uses gSoap library for SOAP encoding/decoding and Xerces library to extract the data from the SOAP response (XML).&lt;br /&gt;
&lt;br /&gt;
I have used the web service URL&amp;nbsp;&lt;a href=&quot;http://www.webservicex.net/stockquote.asmx?WSDL&quot;&gt;http://www.webservicex.net/stockquote.asmx?WSDL&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;Resources:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;gSOAP library (2.8.18)&amp;nbsp;&lt;a href=&quot;http://sourceforge.net/projects/gsoap2/files/&quot;&gt;http://sourceforge.net/projects/gsoap2/files/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Xerces library (3.1.1)&amp;nbsp;&lt;a href=&quot;http://xerces.apache.org/mirrors.cgi#binary&quot;&gt;http://xerces.apache.org/mirrors.cgi#binary&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;b&gt;&lt;u&gt;Setup for Visual Studio 2005:&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Unzip gSOAP library at any location (Lets say C:\tools , so the location will be &lt;b&gt;C:\gsoap-2.8&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;Download only the binary distribution of xerces &lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;&lt;a href=&quot;http://mirror.cc.columbia.edu/pub/software/apache//xerces/c/3/binaries/xerces-c-3.1.1-x86-windows-vc-8.0.zip&quot; target=&quot;_blank&quot;&gt;xerces-c-3.1.1-x86-windows-vc-8.0.zip&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Unzip the zip file at C:\ &amp;nbsp;so that location becomes &lt;b&gt;C:\xerces-c-3.1.1-x86-windows-vc-8.0&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Create an empty Win32 Console Application project.&lt;/li&gt;
&lt;li&gt;Add theses paths to the Additional Include Directories : &lt;br /&gt;&quot;C:\xerces-c-3.1.1-x86-windows-vc-8.0\include&quot;;&quot;C:\gsoap-2.8\gsoap\&quot;;&quot;C:\gsoap-2.8\gsoap\import&quot;&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_9rs4g8gDk7hxkwHXHiugkrVMkz4iFIzuMR4fIrI8BGNVoJk5qF8ZFeXWwbD1dJH3RT5Xu9Mk_e5dAzCRGvtGbvYzgWm68AlWJ2UYUYHkzt3WW01kMUFznp6Xkemscuj2BaKPB8LBqyw/s1600/include.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;291&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_9rs4g8gDk7hxkwHXHiugkrVMkz4iFIzuMR4fIrI8BGNVoJk5qF8ZFeXWwbD1dJH3RT5Xu9Mk_e5dAzCRGvtGbvYzgWm68AlWJ2UYUYHkzt3WW01kMUFznp6Xkemscuj2BaKPB8LBqyw/s1600/include.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Add these paths to Additional Library Directories :&lt;br /&gt;&quot;C:\xerces-c-3.1.1-x86-windows-vc-8.0\lib&quot;&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGPaS7ISn04z8rAn1CNaJX7SEBmnqvZY2iBgOpKagRImINL3807A0k6zIlcwLI_-JEMsdvQhr8WsRjoPNQ4R5Sed3GVgZZetu_3Stqf0fsvK0fzLMZkb03hCaq5JZ106P93rQ0zmesWzY/s1600/lib.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;313&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGPaS7ISn04z8rAn1CNaJX7SEBmnqvZY2iBgOpKagRImINL3807A0k6zIlcwLI_-JEMsdvQhr8WsRjoPNQ4R5Sed3GVgZZetu_3Stqf0fsvK0fzLMZkb03hCaq5JZ106P93rQ0zmesWzY/s1600/lib.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Add these libs to the dependency list:&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0qPzjnOeo2lozlcFziUafgdU0cUoinvxfycZg5fFC7FGM8Qmux6raCwnKyIvy-McpET04hCmCmKXYPTnPHKwJIWQRM8kxdzqF-phMBbBiCQkdpTxshoiCnmmILYnG40sEmWdlI-5uqoE/s1600/lib1.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0qPzjnOeo2lozlcFziUafgdU0cUoinvxfycZg5fFC7FGM8Qmux6raCwnKyIvy-McpET04hCmCmKXYPTnPHKwJIWQRM8kxdzqF-phMBbBiCQkdpTxshoiCnmmILYnG40sEmWdlI-5uqoE/s1600/lib1.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;
Notice that since we are using a Debug configuration here, we added &lt;b&gt;xerces-c_3D.lib. &lt;/b&gt;For Release configuration, use&amp;nbsp;&lt;b&gt;xerces-c_3.lib&lt;/b&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;/div&gt;
Add this location to your environment Path variable&amp;nbsp;&lt;b style=&quot;font-size: small;&quot;&gt;C:\xerces-c-3.1.1-x86-windows-vc-8.0\bin &lt;/b&gt;or copy the xerces dlls (&lt;b&gt;xerces-c_3_1.dll&lt;/b&gt; and &lt;b&gt;xerces-c_3_1D.dll&lt;/b&gt;) into the output path of the project(i.e. same path where the exe of the project will be created). These will be present at the location&amp;nbsp;&lt;b style=&quot;font-size: small;&quot;&gt;C:\xerces-c-3.1.1-x86-windows-vc-8.0\bin&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Open a command prompt and go to gSOAP win32 bin directory and run following commands :&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-weight: bold;&quot;&gt;&lt;br /&gt;wsdl2h.exe -o quote.h http://www.webservicex.net/stockquote.asmx?WSDL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;This will generate quote.h which contains class definitions for the web service.&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;soapcpp2.exe /IC:\tools\gsoap_2.8.18\gsoap-2.8\gsoap\import quote.h&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;This generates following files :&lt;br /&gt;&lt;br /&gt;StockQuoteSoap.GetQuote.req.xml&lt;br /&gt;StockQuoteSoap.GetQuote.res.xml&lt;br /&gt;StockQuoteSoap.nsmap&lt;br /&gt;soapC.cpp&lt;br /&gt;soapClient.cpp&lt;br /&gt;soapClientLib.cpp&lt;br /&gt;soapH.h&lt;br /&gt;soapServer.cpp&lt;br /&gt;soapServerLib.cpp&lt;br /&gt;soapStub.h&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Now add these generated files to the Visual Studio project created earlier :&lt;br /&gt;&lt;b&gt;soapH.h ,&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;soapC.cpp,&amp;nbsp;soapClient.cpp,&amp;nbsp;soapStub.h,&amp;nbsp;quote.h&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Also these add two additional files from&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;b&gt;C:\tools\gsoap_2.8.18\gsoap-2.8\gsoap &lt;/b&gt;to your project:&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;b&gt;stdsoap2.cpp,&amp;nbsp;stdsoap2.h&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Now its time to create some files on our own :). &amp;nbsp;Create these files in the project and copy the contents from the code below :&lt;br /&gt;&lt;br /&gt;&lt;b&gt;quote.cpp, parser.hpp, stock.hpp&lt;/b&gt;&lt;/li&gt;
&lt;h1&gt;SOAP Web Service client implementation(c++)&lt;/h1&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;
//quote.cpp
#include &quot;soapH.h&quot;    // include the generated proxy
#include &amp;lt;xercesc/sax/HandlerBase.hpp&amp;gt;
#include &amp;lt;xercesc/util/XMLString.hpp&amp;gt;
#include &amp;lt;xercesc/framework/MemBufInputSource.hpp&amp;gt;
#include &amp;lt;xercesc/util/OutOfMemoryException.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOM.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMDocument.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMDocumentType.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMElement.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMImplementation.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMImplementationLS.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMNodeIterator.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMNodeList.hpp&amp;gt;
#include &amp;lt;xercesc/dom/DOMText.hpp&amp;gt;
#include &amp;lt;xercesc/parsers/XercesDOMParser.hpp&amp;gt;
#include &amp;lt;xercesc/util/XMLUni.hpp&amp;gt;
#include &quot;parser.hpp&quot;

XERCES_CPP_NAMESPACE_USE

GetXml::GetXml()
{
 try
 {
  XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
 }
 catch( XMLException&amp;amp; e )
 {
  char* message = XMLString::transcode( e.getMessage() );
  std::cout &amp;lt;&amp;lt; &quot;XML toolkit initialization error: &quot; &amp;lt;&amp;lt; message &amp;lt;&amp;lt; std::endl;
  XMLString::release( &amp;amp;message );
 }

 // Tags and attributes used in XML file.
 // Can&#39;t call transcode till after Xerces Initialize()
 TAG_root  = XMLString::transcode(&quot;StockQuotes&quot;);
 TAG_Stock = XMLString::transcode(&quot;Stock&quot;);
 TAG_Symbol = XMLString::transcode(&quot;Symbol&quot;);
 TAG_Last = XMLString::transcode(&quot;Last&quot;);
 TAG_Date = XMLString::transcode(&quot;Date&quot;);
 TAG_Time = XMLString::transcode(&quot;Time&quot;);
 TAG_Change = XMLString::transcode(&quot;Change&quot;);
 TAG_Open = XMLString::transcode(&quot;Open&quot;);
 TAG_High = XMLString::transcode(&quot;High&quot;);
 TAG_Low = XMLString::transcode(&quot;Low&quot;);
 TAG_Volume = XMLString::transcode(&quot;Volume&quot;);
 TAG_MktCap = XMLString::transcode(&quot;MktCap&quot;);
 TAG_PrevClose = XMLString::transcode(&quot;PreviousClose&quot;);
 TAG_PercentChange = XMLString::transcode(&quot;PercentageChange&quot;);
 TAG_AnnRange = XMLString::transcode(&quot;AnnRange&quot;);
 TAG_Earns = XMLString::transcode(&quot;Earns&quot;);
 TAG_PE = XMLString::transcode(&quot;P-E&quot;);
 TAG_Name = XMLString::transcode(&quot;Name&quot;);
 
 m_XmlParser = new XercesDOMParser;
 m_Stock = new Stock;
}

GetXml::~GetXml()
{
 // Free memory
 delete m_XmlParser;
 delete m_Stock;

 try
 {
  XMLString::release( &amp;amp;TAG_root );
 }
 catch( ... )
 {
  std::cout &amp;lt;&amp;lt; &quot;Unknown exception encountered in Destructor&quot; &amp;lt;&amp;lt; std::endl;
 }

 // Terminate Xerces
 try
 {
  XMLPlatformUtils::Terminate();  // Terminate after release of memory
 }
 catch( xercesc::XMLException&amp;amp; e )
 {
  char* message = xercesc::XMLString::transcode( e.getMessage() );

  std::cout &amp;lt;&amp;lt; &quot;XML toolkit teardown error: &quot; &amp;lt;&amp;lt; message &amp;lt;&amp;lt; std::endl;
  XMLString::release( &amp;amp;message );
 }
}

void GetXml::readXml(std::string&amp;amp; xmlStr)
throw( std::runtime_error )
{
 // Configure DOM parser.
 m_XmlParser-&amp;gt;setValidationScheme( XercesDOMParser::Val_Never );
 m_XmlParser-&amp;gt;setDoNamespaces( false );
 m_XmlParser-&amp;gt;setDoSchema( false );
 m_XmlParser-&amp;gt;setLoadExternalDTD( false );

 try
 {
  xercesc_3_1::MemBufInputSource xmlBuf((const XMLByte*)xmlStr.c_str(), xmlStr.size(),
   &quot;xmlBuf (in memory)&quot;);
  m_XmlParser-&amp;gt;parse( xmlBuf );

  xercesc_3_1::DOMDocument* xmlDoc = m_XmlParser-&amp;gt;getDocument();

  DOMElement* elementRoot = xmlDoc-&amp;gt;getDocumentElement();
  if( !elementRoot ) throw(std::runtime_error( &quot;Empty XML document&quot; ));

  DOMNodeList*      children = elementRoot-&amp;gt;getChildNodes();
  const  XMLSize_t nodeCount = children-&amp;gt;getLength();

  // For all nodes, children of &quot;StockQuotes&quot; in the XML tree.

  for( XMLSize_t xx = 0; xx &amp;lt; nodeCount; ++xx )
  {
   DOMNode* currentNode = children-&amp;gt;item(xx);
   if( currentNode-&amp;gt;getNodeType() &amp;amp;&amp;amp;  // true is not NULL
    currentNode-&amp;gt;getNodeType() == DOMNode::ELEMENT_NODE ) // is element 
   {
    // Found node which is an Element. Re-cast node as element
    DOMElement* currentElement
     = dynamic_cast&amp;lt; xercesc::DOMElement* &amp;gt;( currentNode );
    if( XMLString::equals(currentElement-&amp;gt;getTagName(), TAG_Stock))
    {
     DOMNodeList*      children1 = currentElement-&amp;gt;getChildNodes();
     const  XMLSize_t nodeCount1 = children1-&amp;gt;getLength();
     for( XMLSize_t yy = 0; yy &amp;lt; nodeCount1; ++yy )
     {
      DOMNode* currentNode1 = children1-&amp;gt;item(yy);
      if( currentNode1-&amp;gt;getNodeType() &amp;amp;&amp;amp;  // true is not NULL
       currentNode1-&amp;gt;getNodeType() == DOMNode::ELEMENT_NODE ) // is element 
      {
       // Found node which is an Element. Re-cast node as element
       DOMElement* currentElement1
        = dynamic_cast&amp;lt; xercesc::DOMElement* &amp;gt;( currentNode1 );
       std::cout&amp;lt;&amp;lt;XMLString::transcode(currentElement1-&amp;gt;getTagName())&amp;lt;&amp;lt;&quot;: &quot;
        &amp;lt;&amp;lt;XMLString::transcode(currentElement1-&amp;gt;getTextContent())&amp;lt;&amp;lt;std::endl;

       std::string sym(XMLString::transcode(currentElement1-&amp;gt;getTextContent()));

       if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Symbol))
       {
        m_Stock-&amp;gt;SetSymbol(sym);
       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Last))
       {
        m_Stock-&amp;gt;SetLast(sym);
       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Date))
       {
        m_Stock-&amp;gt;SetDate(sym);
       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Time))
       {
        m_Stock-&amp;gt;SetTime(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Change))
       {
        m_Stock-&amp;gt;SetChange(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Open))
       {
        m_Stock-&amp;gt;SetOpen(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_High))
       {
        m_Stock-&amp;gt;SetHigh(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Low))
       {
        m_Stock-&amp;gt;SetLow(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Volume))
       {
        m_Stock-&amp;gt;SetVolume(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_MktCap))
       {
        m_Stock-&amp;gt;SetMktCap(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_PrevClose))
       {
        m_Stock-&amp;gt;SetPrevClose(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_PercentChange))
       {
        m_Stock-&amp;gt;SetPercentChange(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_AnnRange))
       {
        m_Stock-&amp;gt;SetAnnRange(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Earns))
       {
        m_Stock-&amp;gt;SetEarns(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_PE))
       {
        m_Stock-&amp;gt;SetPE(sym);

       }
       else if(XMLString::equals(currentElement1-&amp;gt;getTagName(), TAG_Name))
       {
        m_Stock-&amp;gt;SetName(sym);
       }
      }
     }
    }
   }
  }

  std::cout&amp;lt;&amp;lt;m_Stock-&amp;gt;ToString();
 }
 catch( xercesc::XMLException&amp;amp; e )
 {
  char* message = xercesc::XMLString::transcode( e.getMessage() );
  std::ostringstream errBuf;
  errBuf &amp;lt;&amp;lt; &quot;Error parsing file: &quot; &amp;lt;&amp;lt; message &amp;lt;&amp;lt; std::flush;
  XMLString::release( &amp;amp;message );
 }
}

int main(int argc, char** argv){
 struct soap *soap = soap_new(); 
 struct _ns1__GetQuote sym;
 struct _ns1__GetQuoteResponse quote;
 GetXml xml;
 std::string response=&quot;&quot;;
 std::string str(argv[1]);
 sym.symbol = &amp;amp;str;

 soap_init(soap);

 //Call the web service
 if (soap_call___ns1__GetQuote(soap, NULL, NULL, &amp;amp;sym, quote) == SOAP_OK) {
  //std::cout&amp;lt;&amp;lt;&quot;Symbol: &quot;&amp;lt;&amp;lt;*(sym.symbol)&amp;lt;&amp;lt;std::endl&amp;lt;&amp;lt;&quot; Quote: &quot;&amp;lt;&amp;lt;*(quote.GetQuoteResult)&amp;lt;&amp;lt;std::endl;
  response = *(quote.GetQuoteResult);
  free (quote.GetQuoteResult);
 }
 else {
  std::cout&amp;lt;&amp;lt;&quot;Error in execution of GetQuote:: &quot;&amp;lt;&amp;lt;soap-&amp;gt;buf&amp;lt;&amp;lt;std::endl;
  return(0);
 }

 //Parse the SOAP response 
 xml.readXml(response);
 return 0;
}

// Copied from StockQuoteSoap.nsmap file
SOAP_NMAC struct Namespace namespaces[] =
{
 {&quot;SOAP-ENV&quot;, &quot;http://www.w3.org/2003/05/soap-envelope&quot;, &quot;http://schemas.xmlsoap.org/soap/envelope/&quot;, NULL},
 {&quot;SOAP-ENC&quot;, &quot;http://www.w3.org/2003/05/soap-encoding&quot;, &quot;http://schemas.xmlsoap.org/soap/encoding/&quot;, NULL},
 {&quot;xsi&quot;, &quot;http://www.w3.org/2001/XMLSchema-instance&quot;, &quot;http://www.w3.org/*/XMLSchema-instance&quot;, NULL},
 {&quot;xsd&quot;, &quot;http://www.w3.org/2001/XMLSchema&quot;, &quot;http://www.w3.org/*/XMLSchema&quot;, NULL},
 {&quot;ns1&quot;, &quot;http://www.webserviceX.NET/&quot;, NULL, NULL},
 {NULL, NULL, NULL, NULL}
};
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;
//stock.hpp
#include &amp;lt;sstream&amp;gt;
class Stock
{
 std::string symbol_;
 std::string last_;
 std::string date_;
 std::string time_;
 std::string change_;
 std::string open_;
 std::string high_;
 std::string low_;
 std::string volume_;
 std::string mktcap_;
 std::string previousclose_;
 std::string percentagechange_;
 std::string annrange_;
 std::string earns_;
 std::string p_e_;
 std::string name_;

public:
 Stock() {}
 Stock(std::string symbol) {symbol_ = symbol;}

 void SetSymbol(std::string symbol) {symbol_ = symbol;}
 void SetLast(std::string last) {last_ = last;}
 void SetDate(std::string date) {date_ = date;}
 void SetTime(std::string time) {time_ = time;}
 void SetChange(std::string change) {change_ = change;}
 void SetOpen(std::string open) {open_ = open;}
 void SetHigh(std::string high) {high_ = high;}
 void SetLow(std::string low) {low_ = low;}
 void SetVolume(std::string volume) {volume_ = volume;}
 void SetMktCap(std::string mktcap) {mktcap_ = mktcap;}
 void SetPrevClose(std::string previousclose) {previousclose_ = previousclose;}
 void SetPercentChange(std::string percentagechange) {percentagechange_ = percentagechange;}
 void SetAnnRange(std::string annrange) {annrange_ = annrange;}
 void SetEarns(std::string earns) {earns_ = earns;}
 void SetPE(std::string p_e) {p_e_ = p_e;}
 void SetName(std::string name) {name_ = name;}

 //ToString function overridden to display in short format  
 std::string ToString() const
 {
  std::stringstream sstr;
  sstr &amp;lt;&amp;lt; &quot;\&#39;&quot; &amp;lt;&amp;lt; symbol_ &amp;lt;&amp;lt; &quot;\&#39; Open: &quot; &amp;lt;&amp;lt; open_
   &amp;lt;&amp;lt; &quot;, Last: &quot; &amp;lt;&amp;lt; last_;
  return sstr.str();
 }
};
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;
//parser.hpp
#include &quot;stock.hpp&quot;
class GetXml
{
public:
 GetXml();
 ~GetXml();

 //Function to read the XML string
 void readXml(std::string&amp;amp;) throw(std::runtime_error);


private:
 xercesc_3_1::XercesDOMParser *m_XmlParser; //DOM Parser pointer
 Stock *m_Stock;        //To save the returned data

 XMLCh* TAG_root;
 XMLCh* TAG_Stock;
 XMLCh* TAG_Symbol;
 XMLCh* TAG_Last;
 XMLCh* TAG_Date;
 XMLCh* TAG_Time;
 XMLCh* TAG_Change;
 XMLCh* TAG_Open;
 XMLCh* TAG_High;
 XMLCh* TAG_Low;
 XMLCh* TAG_Volume;
 XMLCh* TAG_MktCap;
 XMLCh* TAG_PrevClose;
 XMLCh* TAG_PercentChange;
 XMLCh* TAG_AnnRange;
 XMLCh* TAG_Earns;
 XMLCh* TAG_PE;
 XMLCh* TAG_Name;
};
&lt;/code&gt;
&lt;/pre&gt;

&lt;br /&gt;&lt;br /&gt;
&lt;li&gt;Now the project is ready to compile. Use F7 to compile the solution.&lt;/li&gt;
&lt;li&gt;After the binary is generated, run it like this :&lt;br /&gt;&amp;lt;binary-name&amp;gt;.exe&amp;lt;space&amp;gt;&amp;lt;Ticker-Name&amp;gt;&lt;br /&gt;&lt;br /&gt;e.g. If project name was soap&lt;br /&gt;soap.exe GOOG&lt;/li&gt;
&lt;li&gt;This program is specific to the Stock Quote web service provided by&amp;nbsp;&lt;a href=&quot;http://www.webservicex.net/stockquote.asmx?WSDL&quot;&gt;http://www.webservicex.net/&lt;/a&gt;&amp;nbsp;. This program can be modified to use any web service. Depending upon the expected SOAP response, the result can be parsed accordingly. Then following files will be modified :&lt;br /&gt;&lt;br /&gt;stock.hpp - Class which stores the data from SOAP response&lt;br /&gt;parser.hpp - Class which parses the XML result from SOAP response&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2014/10/create-soap-web-service-client-in-c.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjox1D6j-O6zV_8eUuRlKiJSNV6FtUYaZRbYraOrsLk4LduY-KX2Wjq1gzSI-eSVegmzaCt4HL_gNJFSGJg9irUOT9Gr5ol7qhqumbImE9HSoKDpS8AI2umxojjmf6Z6S-TSeP6iCkwYTHArz0UB_HbIzU7-_SNfQdyNVnXL_ta8N1fI4u74E1jiTh7lzs/s72-c/soap_black.jpeg" height="72" width="72"/><thr:total>3</thr:total><georss:featurename>Bengaluru, Karnataka, India</georss:featurename><georss:point>12.9715987 77.594562699999983</georss:point><georss:box>12.9715987 77.594562699999983 12.9715987 77.594562699999983</georss:box></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-4201802448737961412</guid><pubDate>Tue, 01 Apr 2014 20:21:00 +0000</pubDate><atom:updated>2023-12-21T00:18:35.910+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Builder</category><category domain="http://www.blogger.com/atom/ns#">Builder Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Design Patterns</category><title>Builder Design Pattern Implementation in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Sometimes an application gets too complicated and developing it becomes a pain. These applications contain complex objects which are made up from other objects from different classes. Now these objects may vary. So there has to be a process of building the complex objects so that there is scope of building different products using the same process.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
That is when a creational design pattern called &lt;b&gt;Builder&lt;/b&gt; comes into picture. It &lt;i&gt;separates the details of construction process from its representation&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Now what in the world that line means actually ?&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
It means that the construction process is made so generic, that multiple products can be produced using the same process. e.g. construction workers. Different type of buildings can be built using the same workers and same common set of process.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Here is a class diagram of the design pattern.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCuiSYtUz_LTTio4VHshLte_KO0DWfRso2jryCVDwLdee0Oh913-33V4M84BoMHb9twa8IV1WT005VGeNtCwYJRCwOTJBWkIqc33AoY0rlYmwgEVLZ771k4yhcKO55oXy6j6dPgBJBzI/s1600/Builder.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img alt=&quot;Builder Design Pattern&quot; border=&quot;0&quot; height=&quot;252&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCuiSYtUz_LTTio4VHshLte_KO0DWfRso2jryCVDwLdee0Oh913-33V4M84BoMHb9twa8IV1WT005VGeNtCwYJRCwOTJBWkIqc33AoY0rlYmwgEVLZ771k4yhcKO55oXy6j6dPgBJBzI/s1600/Builder.png&quot; title=&quot;Builder Design Pattern&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Builder Design Pattern&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
There are 4 major components:&lt;br /&gt;
&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Director&lt;/b&gt;: It constructs an object using the Builder interface.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Builder &lt;/b&gt;: It specifies an abstract interface to build parts of a product.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Concrete Classes &lt;/b&gt;: Implements builder interface.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Product &lt;/b&gt;: The complex object which is created at the end.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Director object is created and Builder interface is used. It notifies the Builder to create each part of the product. Upon the request from Director, Builder adds parts to the product. Finally the product is returned by the Builder.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We have to take care of when to use the Builder Design Pattern. Few points come into mind :&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;When the object to be created is complex enough and can have multiple representations.&lt;/li&gt;
&lt;li&gt;When the construction process can be broken down into multiple steps&lt;/li&gt;
&lt;li&gt;When the process of creation of an object can be independent of the parts to be used.&lt;/li&gt;
&lt;li&gt;When different products can have a common abstract class.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Now lets create a builder design pattern using an example.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLQfwhE-O-vlIphK4tG6E1bK1At9P1cK2rpc7N6FYcgM9P6AoqxR7rGdpVM3DtxtGq2hVpt0DbOtOumZWfqiBGgy4leuW_UCR26VbiIiNVNeS8NLEADowZB4USRJgy2oUuJroXNugrrxg/s1600/BuilderExample.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img alt=&quot;Builder Design Pattern&quot; border=&quot;0&quot; height=&quot;482&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLQfwhE-O-vlIphK4tG6E1bK1At9P1cK2rpc7N6FYcgM9P6AoqxR7rGdpVM3DtxtGq2hVpt0DbOtOumZWfqiBGgy4leuW_UCR26VbiIiNVNeS8NLEADowZB4USRJgy2oUuJroXNugrrxg/s1600/BuilderExample.png&quot; title=&quot;Builder Design Pattern&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Builder Example&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
In this example we create house as product. Now the house created may be different as per requirement of different people. It can be a lavish house with lots of amenities and expensive stuff. On the other hand, it could be a normal house with normal stuff.&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;The HouseBuilder class is the builder class which provides interface for creating the parts of the house.&lt;/li&gt;
&lt;li&gt;The House class is the final product that we want to build&lt;/li&gt;
&lt;li&gt;LavishHouse and NormalHouse are the concrete classes which implement the HouseBuilder interface.&lt;/li&gt;
&lt;li&gt;Contractor is the director which constructs the house using the HouseBuilder interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h1&gt;Builder Design Pattern Implementation(C++)&lt;/h1&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;iostream&amp;gt;

using namespace std;

/* Interface that will be returned as the product from builder */
class HousePlan{
public:
 virtual void setWindow(string window)=0;
 virtual void setDoor(string door)=0;
 virtual void setBathroom(string bathroom)=0;
 virtual void setKitchen(string kitchen)=0;
 virtual void setFloor(string floor)=0;
};

/* Concrete class for the HousePlan interface */
class House:public HousePlan{
private :
 string window, door, kitchen, bathroom, floor;

public:
 void setWindow(string window)
 {
  this-&amp;gt;window = window;
 }

 void setDoor(string door)
 {
  this-&amp;gt;door = door;
 }

 void setBathroom(string bathroom)
 {
  this-&amp;gt;bathroom = bathroom;
 }

 void setKitchen(string kitchen)
 {
  this-&amp;gt;kitchen = kitchen;
 }

 void setFloor(string floor)
 {
  this-&amp;gt;floor = floor;
 }
};

/* Builder Class */
class HouseBuilder
{
public:
 /* Abstract functions to build parts */
 virtual void buildWindow()=0;
 virtual void buildDoor()=0;
 virtual void buildKitchen()=0;
 virtual void buildBathroom()=0;
 virtual void buildFloor()=0;
 /* The product is returned by this function */
 virtual House* getHouse()=0;
};

/* Concrete class for the builder interface */
class LavishHouse:public HouseBuilder{
private:
 House *house;
public:
 LavishHouse()
 {
  house = new House();
 }

 void buildWindow()
 {
  house-&amp;gt;setWindow(&quot;French Window&quot;);
 }

 void buildDoor()
 {
  house-&amp;gt;setDoor(&quot;Wooden Door&quot;);
 }

 void buildBathroom()
 {
  house-&amp;gt;setBathroom(&quot;Modern Bathroom&quot;);
 }

 void buildKitchen()
 {
  house-&amp;gt;setKitchen(&quot;Modular Kitchen&quot;);
 }

 void buildFloor()
 {
  house-&amp;gt;setFloor(&quot;Wooden Floor&quot;);
 }

 House* getHouse()
 {
  return this-&amp;gt;house;
 }
};

/* Another Concrete class for the builder interface */
class NormalHouse:public HouseBuilder{
private:
 House *house;
public:
 NormalHouse()
 {
  house = new House();
 }

 void buildWindow()
 {
  house-&amp;gt;setWindow(&quot;Normal Window&quot;);
 }

 void buildDoor()
 {
  house-&amp;gt;setDoor(&quot;Metal Door&quot;);
 }

 void buildBathroom()
 {
  house-&amp;gt;setBathroom(&quot;Regular Bathroom&quot;);
 }

 void buildKitchen()
 {
  house-&amp;gt;setKitchen(&quot;Regular Kitchen&quot;);
 }

 void buildFloor()
 {
  house-&amp;gt;setFloor(&quot;Mosaic Floor&quot;);
 }

 House* getHouse()
 {
  return this-&amp;gt;house;
 }
};

/* The Director. Constructs the house */
class Contractor
{
private:
 HouseBuilder *houseBuilder;

public:
 Contractor(HouseBuilder *houseBuilder)
 {
  this-&amp;gt;houseBuilder = houseBuilder;
 }

 House *getHouse()
 {
  return houseBuilder-&amp;gt;getHouse();
 }

 void buildHouse()
 {
  houseBuilder-&amp;gt;buildWindow();
  houseBuilder-&amp;gt;buildDoor();
  houseBuilder-&amp;gt;buildBathroom();
  houseBuilder-&amp;gt;buildKitchen();
  houseBuilder-&amp;gt;buildFloor();
 }
};

/* Example on how to use the Builder design pattern */
int main()
{
 HouseBuilder *lavishHouseBldr = new LavishHouse();
 HouseBuilder *normalHouseBldr = new NormalHouse();

 Contractor *ctr1 = new Contractor(lavishHouseBldr);
 Contractor *ctr2 = new Contractor(normalHouseBldr);

 ctr1-&amp;gt;buildHouse();
 House *house1 = ctr1-&amp;gt;getHouse();
 cout&amp;lt;&amp;lt;&quot;Constructed: &quot;&amp;lt;&amp;lt;house1;

 ctr2-&amp;gt;buildHouse();
 House *house2 = ctr2-&amp;gt;getHouse();
 cout&amp;lt;&amp;lt;&quot;Constructed: &quot;&amp;lt;&amp;lt;house2;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2014/04/builder-design-pattern-implementation.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCuiSYtUz_LTTio4VHshLte_KO0DWfRso2jryCVDwLdee0Oh913-33V4M84BoMHb9twa8IV1WT005VGeNtCwYJRCwOTJBWkIqc33AoY0rlYmwgEVLZ771k4yhcKO55oXy6j6dPgBJBzI/s72-c/Builder.png" height="72" width="72"/><thr:total>7</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-3420951306635762427</guid><pubDate>Sun, 29 Dec 2013 14:46:00 +0000</pubDate><atom:updated>2023-12-21T00:04:21.166+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Decorator Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Design Patterns</category><title>Decorator Design Pattern Implementation in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Do you need to extend the capabilities of your existing class instance at run-time? If the answer is yes then Decorator design pattern just provides the functionality you need.&lt;br /&gt;
&lt;br /&gt;
When we have to change the capabilities of only a particular instance and not all the instances which will get created for a particular class, we have to use decorator design pattern.&lt;br /&gt;
&lt;br /&gt;
This is achieved by creating a decorator class, which wraps the original class. The original class is sub-classed into two parts. One is the concrete class which is essentially the original class with only basic features. The other one is the Decorator base class. This decorator base class implements the same interface as the original class. In addition it wraps the original base class.&lt;br /&gt;
&lt;br /&gt;
We can extend this Decorator base class to create multiple concrete decorator classes. Each of these concrete decorator classes implement their own methods and will call the base class&#39;s instance&#39;s method.&lt;br /&gt;
&lt;br /&gt;
Now this looks complete babbling. Let&#39;s see what I mean actually.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXtn5jOf6MH7fEQ8P-Md9cLVNV6va5hgmZ4YdgVERv_t8zncKzaMCba0CJXZC07judkq33n3nYqI7oMhe8GHJqFDe5aG3xvWVu-uimFBQa7PvcrLyGe-Mw5bxyK1U8kKtYM272Vbaz1k8/s1600/dec_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXtn5jOf6MH7fEQ8P-Md9cLVNV6va5hgmZ4YdgVERv_t8zncKzaMCba0CJXZC07judkq33n3nYqI7oMhe8GHJqFDe5aG3xvWVu-uimFBQa7PvcrLyGe-Mw5bxyK1U8kKtYM272Vbaz1k8/s640/dec_1.png&quot; height=&quot;504&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Decorator Design Pattern&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
I know the above diagram looks overwhelming. So let&#39;s explain it in more simple language with much simpler example.&lt;br /&gt;
&lt;br /&gt;
Lets prepare a subway burger. Shall we ;)&lt;br /&gt;
Now we all know that when we visit a Subway store, we have a variety of options to customize our Sub.&lt;br /&gt;
Assuming that we have chosen a foot-long already for the base bread, we start making our sandwich.&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;We can add cheese to the sandwich.&lt;/li&gt;
&lt;li&gt;We can add vegetables to our Sub.&lt;/li&gt;
&lt;li&gt;We can add mayonnaise,mustard, sweet onion etc .&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Depending on our choices, the sandwich is prepared. And we are ready to eat it .. Aren&#39;t we :)&lt;br /&gt;
&lt;br /&gt;
Now consider the bread(foot-long) as the Base&amp;nbsp;Component&amp;nbsp;Class. Over this component, we can place a Decorator Base Class SubDecorator and now the Concrete Decorators can be derived from this class.&lt;br /&gt;
&lt;br /&gt;
CheeseDecorator, VegDecorator, SauceDecorator are concrete decorators which implement their own functions and have their own members in addition to the base class functions cost() and description().&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbd1vZ3_Foqqkh3WErpSjOUbRS447SF8l3EM1AU_A4J6qyBARABImrYKdb2jHFV1Ug7hUlVKArgHN9GRwK5ORJKRHdWodTgZgJ0LG47c3cNSJNq4j91idzt1XygsK14KPkdFHBJjPbmNA/s1600/dec_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbd1vZ3_Foqqkh3WErpSjOUbRS447SF8l3EM1AU_A4J6qyBARABImrYKdb2jHFV1Ug7hUlVKArgHN9GRwK5ORJKRHdWodTgZgJ0LG47c3cNSJNq4j91idzt1XygsK14KPkdFHBJjPbmNA/s640/dec_2.png&quot; height=&quot;419&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
And here comes the code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;Decorator Design Pattern Implementation (C++)&lt;/h1&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;

//Uncomment the next line to enable debug logs
//#define DEBUG

std::string c(const std::string cls) {
    return &quot;\n&quot; + cls + &quot; Constructor&quot;;
}
std::string d(const std::string cls) {
    return &quot;\n&quot; +cls + &quot; Destructor&quot;;
}

/*Base component class*/
class Sandwich
{
public:
    virtual ~Sandwich() { }
    virtual double getCost()=0;
    virtual std::string getDesc()=0;
};

/*Concrete component class*/
class WheatBread:public Sandwich
{
public:
    WheatBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;WheatBread&quot;);
#endif
    }
    ~WheatBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;WheatBread&quot;);
#endif
    }
    std::string getDesc()
    {
        return &quot;Wheat Bread&quot;;
    }

    double getCost()
    {
        return 2.0;
    }
};

/*Concrete component class*/
class WholeGrainBread:public Sandwich
{
public:
    WholeGrainBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;WholeGrainBread&quot;);
#endif
    }
    ~WholeGrainBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;WholeGrainBread&quot;);
#endif
    }
    std::string getDesc()
    {
        return &quot;WholeGrain Bread&quot;;
    }

    double getCost()
    {
        return 3.0;
    }
};

/*Concrete component class*/
class ItalianBread:public Sandwich
{
public:
    ItalianBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;ItalianBread&quot;);
#endif
    }
    ~ItalianBread() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;ItalianBread&quot;);
#endif
    }
    std::string getDesc()
    {
        return &quot;Italian Bread&quot;;
    }

    double getCost()
    {
        return 2.5;
    }
};

/*Decorator Base class*/
class SubDecorator: public Sandwich
{
    Sandwich *sandwich;
public:
    SubDecorator(Sandwich *sandwichRef)
    {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;SubDecorator&quot;);
#endif
        sandwich = sandwichRef;
    }

    ~SubDecorator() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;SubDecorator&quot;);
#endif
        delete sandwich;
    }
    double getCost()
    {
        return sandwich-&amp;gt;getCost();
    }
    std::string getDesc()
    {
        return sandwich-&amp;gt;getDesc();
    }
};

/*Decorator concrete class*/
class CheeseDecorator:public SubDecorator
{
private:
    std::string cheese_desc()
    {
        return &quot; + Cheese&quot;;
    }

    double cheese_cost;

public:
    CheeseDecorator(Sandwich *sandwich):SubDecorator(sandwich)
    {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;CheeseDecorator&quot;);
#endif
        cheese_cost = 3.0;
    }

    ~CheeseDecorator() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;CheeseDecorator&quot;);
#endif
    }
    std::string getDesc()
    {
        return SubDecorator::getDesc().append(cheese_desc());
    }

    double getCost()
    {
        return SubDecorator::getCost() + cheese_cost;
    }
};

/*Decorator concrete class*/
class VegDecorator:public SubDecorator
{
private:
    std::string veg_desc()
    {
        return &quot; + Veg&quot;;
    }

    double veg_cost;

public:
    VegDecorator(Sandwich *sandwich):SubDecorator(sandwich)
    {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;VegDecorator&quot;);
#endif
        veg_cost = 2.0;
    }

    ~VegDecorator() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;VegDecorator&quot;);
#endif
    }
    std::string getDesc()
    {
        return SubDecorator::getDesc().append(veg_desc());
    }

    double getCost()
    {
        return SubDecorator::getCost() + veg_cost;
    }
};

/*Decorator concrete class*/
class SauceDecorator:public SubDecorator
{
private:
    std::string sauce_desc()
    {
        return &quot; + Sauce&quot;;
    }

    double sauce_cost;

public:
    SauceDecorator(Sandwich *sandwich):SubDecorator(sandwich)
    {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;c(&quot;SauceDecorator&quot;);
#endif
        sauce_cost = .5;
    }

    ~SauceDecorator() {
#ifdef DEBUG
        std::cout&amp;lt;&amp;lt;d(&quot;SauceDecorator&quot;);
#endif
    }
    std::string getDesc()
    {
        return SubDecorator::getDesc().append(sauce_desc());
    }

    double getCost()
    {
        return SubDecorator::getCost() + sauce_cost;
    }
};

int main()
{
    Sandwich *sandwich = new CheeseDecorator(new WheatBread());
    sandwich = new VegDecorator(sandwich);
    sandwich = new SauceDecorator(new SubDecorator(sandwich));
    std::cout&amp;lt;&amp;lt;&quot;\nYour sandwich is &quot;&amp;lt;&amp;lt;sandwich-&amp;gt;getDesc()&amp;lt;&amp;lt;&quot; and costs $&quot;&amp;lt;&amp;lt;sandwich-&amp;gt;getCost();
    delete sandwich;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2013/12/decorator-design-pattern-implementation-in-cplusplus.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXtn5jOf6MH7fEQ8P-Md9cLVNV6va5hgmZ4YdgVERv_t8zncKzaMCba0CJXZC07judkq33n3nYqI7oMhe8GHJqFDe5aG3xvWVu-uimFBQa7PvcrLyGe-Mw5bxyK1U8kKtYM272Vbaz1k8/s72-c/dec_1.png" height="72" width="72"/><thr:total>14</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5727076864756599282</guid><pubDate>Sun, 29 Dec 2013 11:08:00 +0000</pubDate><atom:updated>2023-12-21T00:23:22.969+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design Patterns</category><category domain="http://www.blogger.com/atom/ns#">Factory Method Design Pattern</category><title>Factory Method Design Pattern implementation in C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
What does a factory mean ? It is something which creates/manufactures some products.&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyw9di-SpP3jdr-P5iDprZQ94T84yX_1H2N26wLefq5_eNcvuSme1l3c8qKHFUJ7E8I6olGt1-wbSnvDJNC412mGJrY3bqEqURLpGzm0YpA622wBXTIk0fxedrgk13_4g1SlER_LvypSJ6hiSSoqUcQ40ShMH_iU0CB2eTns2GYV3OYLRtglBtgxIZ0HI/s1024/factory.jpeg&quot; style=&quot;display: block; padding: 1em 0px; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyw9di-SpP3jdr-P5iDprZQ94T84yX_1H2N26wLefq5_eNcvuSme1l3c8qKHFUJ7E8I6olGt1-wbSnvDJNC412mGJrY3bqEqURLpGzm0YpA622wBXTIk0fxedrgk13_4g1SlER_LvypSJ6hiSSoqUcQ40ShMH_iU0CB2eTns2GYV3OYLRtglBtgxIZ0HI/s400/factory.jpeg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;  
&lt;div&gt;
Same is the job of factory design pattern. It is responsible for instantiation/creation of objects. But wait, isn&#39;t that something what constructors do ? Yes call to constructor indeed creates the object and that&#39;s exactly what a factory method does but with an additional feature of option of choosing between different constructors based on some logic.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Factory methods decide logically what constructor to call. So, instead of directly calling the constructor for a class, we call a factory method to get the object. There can be multiple derived classes from a base class. The factory method instantiates the appropriate sub-class based on the arguments passed to it and returns the base class type. This base class object can be used to access the derived class members/methods.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Blah, blah, blah... Let&#39;s get down to business and understand what it actually is and what it does.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A basic structure:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCo7Hv7tdFun2M4ZrQbM06J3mQMAGCJgsFuntmZFRkepil8JGQnEpexkCHEcTVPkshq-tuARyZWZoRQ6KtuHPYTAENp0fqxgtupMMF1Un7xl0Lhb4U1sHIbSnYL5mRjJsTKdDnymZrFnY/s1600/factory_1.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;384&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCo7Hv7tdFun2M4ZrQbM06J3mQMAGCJgsFuntmZFRkepil8JGQnEpexkCHEcTVPkshq-tuARyZWZoRQ6KtuHPYTAENp0fqxgtupMMF1Un7xl0Lhb4U1sHIbSnYL5mRjJsTKdDnymZrFnY/s640/factory_1.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Basic structure of factory design pattern&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now let&#39;s explain it with a simple example:&lt;/div&gt;
&lt;div&gt;
Assume that we are an online Music Store . We every kind of music be it Rock, Classical, Jazz, Reggae, Techno and what not. Of course, to organize these we need categories based on different genres. Lets design this model using factory design pattern. Our base class is what we do. We provide music, so say &quot;Music&quot; is our base class.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now Music can be classified into multiple categories . We for the time being assume only three.&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Rock&lt;/li&gt;
&lt;li&gt;Pop&lt;/li&gt;
&lt;li&gt;Reggae&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
The class structure would be something like this:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJTP15JUjlBQukhAlP3slfHwYjy4AltdGHjx8i63zSwyWTd27zOul70v3ARg4W-TQj0wR8QjiFxy7CEHZUx7PtMajfTHThXEJ0wm2o-J6rWTo4EBzarRqyXt03XrUednda4T3AMJK2q-U/s1600/factory_2.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;265&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJTP15JUjlBQukhAlP3slfHwYjy4AltdGHjx8i63zSwyWTd27zOul70v3ARg4W-TQj0wR8QjiFxy7CEHZUx7PtMajfTHThXEJ0wm2o-J6rWTo4EBzarRqyXt03XrUednda4T3AMJK2q-U/s640/factory_2.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Class Structure&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
Here &lt;i&gt;Rock&lt;/i&gt;, &lt;i&gt;Pop &lt;/i&gt;and &lt;i&gt;Reggae &lt;/i&gt;are the derived classes from base class &lt;b&gt;Music&lt;/b&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We create a factory pattern for this class structure in which we provide a factory method getMusic(genre_e genre) to the user. Using this method, one can instantiate the object of any subclass by choosing the genre.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Here genre is the logic based on which any particular subclass is instantiated. Advantage of this pattern is that outer world need not instantiate specific objects using the different sub-class constructors. It is being masked in the implementation of factory method.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMLDskN4O7Zu8YWew4fcu_nxnMjl6wdifMo2bHToDY48HTbY7SaeA8g-ESUnESG50pzfu-NRl4GupCAn11pMFGh1Ye0_0a5Nvc3oWjZBdAlTsEVGA3hPsXAy7dvUyJQkr95s3GyCaxqn8/s1600/factory_3.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;435&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMLDskN4O7Zu8YWew4fcu_nxnMjl6wdifMo2bHToDY48HTbY7SaeA8g-ESUnESG50pzfu-NRl4GupCAn11pMFGh1Ye0_0a5Nvc3oWjZBdAlTsEVGA3hPsXAy7dvUyJQkr95s3GyCaxqn8/s640/factory_3.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Factory pattern for the class Music&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
Moreover if any new genre needs to be added, that can be done easily just by adding a new case in Factory method.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
And now the code :&lt;/div&gt;
&lt;h1&gt;Factory Method Design Pattern implementation (C++)&lt;/h1&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

enum genre_e{ROCK,POP, REGGAE, INVALID};

/*Base Class*/
class Music {
public:
 virtual void song() = 0;
};

/*Derived class Rock from Music*/
class Rock: public Music
{
public:
 void song()
 {
  cout&amp;lt;&amp;lt;&quot;Nirvana: Smells like a teen spirit\n&quot;;
 }
};

/*Derived class Pop from Music*/
class Pop: public Music
{
public:
 void song()
 {
  cout&amp;lt;&amp;lt;&quot;Michael Jackson: Billie Jean\n&quot;;
 }
};

/*Derived class Reggae from Music*/
class Reggae: public Music
{
public:
 void song()
 {
  cout&amp;lt;&amp;lt;&quot;Bob Marley: No woman, No cry\n&quot;;
 }
};

/*Factory Class*/
class MusicFactory
{
public:
 /*Factory Method*/
 Music *getMusic(genre_e genre)
 {
  Music *music = NULL;

  /*Logic based on Genre*/
  switch(genre)
  {
  case ROCK:
   music = new Rock();
   break;
  case POP:
   music = new Pop();
   break;
  case REGGAE:
   music = new Reggae();
   break;
  default:
   music = NULL;
   break;
  }
  return music;
 }
};

int main()
{
 /*Create factory*/
 MusicFactory *musicFactory = new MusicFactory();

 /*Factory instantiating an object of type ROCK*/
 Music *music = musicFactory-&amp;gt;getMusic(ROCK);

 cout&amp;lt;&amp;lt;&quot;Song: &quot;;
 if(music)
  music-&amp;gt;song();
 else
  cout&amp;lt;&amp;lt;&quot;Wrong selection dude/dudette !!&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2013/12/factory-method-design-pattern-in-cplusplus.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyw9di-SpP3jdr-P5iDprZQ94T84yX_1H2N26wLefq5_eNcvuSme1l3c8qKHFUJ7E8I6olGt1-wbSnvDJNC412mGJrY3bqEqURLpGzm0YpA622wBXTIk0fxedrgk13_4g1SlER_LvypSJ6hiSSoqUcQ40ShMH_iU0CB2eTns2GYV3OYLRtglBtgxIZ0HI/s72-c/factory.jpeg" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-2038718705840192646</guid><pubDate>Sun, 29 Sep 2013 12:01:00 +0000</pubDate><atom:updated>2023-12-21T00:09:42.295+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">BFS</category><category domain="http://www.blogger.com/atom/ns#">DAG</category><category domain="http://www.blogger.com/atom/ns#">DFS</category><category domain="http://www.blogger.com/atom/ns#">Graphs</category><category domain="http://www.blogger.com/atom/ns#">Quiver</category><title>Graph Implementation in C</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
A graph is a collection of nodes and edges. These nodes are connected by links(edges).&lt;br /&gt;
These edges may be directed or undirected. Moreover these edges can have weights associated with them&lt;br /&gt;
&lt;br /&gt;
So edges can be categorized as :&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Directed, weighted edges&lt;/li&gt;
&lt;li&gt;Directed, unweighted edges&lt;/li&gt;
&lt;li&gt;Undirected, weighted edges&lt;/li&gt;
&lt;li&gt;Undirected, unweighted edges&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Uses of graphs&lt;/span&gt;&lt;/h2&gt;
Graphs are extremely useful. Look everywhere and one can easily find use of graphs. Listed below are a few of the vast set of practical uses of graphs.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXSqdZdeGbFjp3Cpwdr9KeyhszF_rwBfqxmYcGdgYF8OlkWo2Pni8kwmNu8uW4g5m9QVYjVm4pBNhl3mRU23nKsMmakozNmJ80GmL7Cy-zVAx0sopUOg35zuMEURm4A67Sd_28EnDT1wU/s1600/dmrc.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXSqdZdeGbFjp3Cpwdr9KeyhszF_rwBfqxmYcGdgYF8OlkWo2Pni8kwmNu8uW4g5m9QVYjVm4pBNhl3mRU23nKsMmakozNmJ80GmL7Cy-zVAx0sopUOg35zuMEURm4A67Sd_28EnDT1wU/s640/dmrc.jpg&quot; height=&quot;524&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Delhi Metro Rail Map&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&amp;nbsp;Each station is a vertex, the distance in between is a weighted edge.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpY-LKsV1OQS4CLcoKVuFNrPnzGKplXd0MC9w8WLQfP855PhGm6nuxPxf7Rf3Ku8QqtjplRBihknpaIvV3z6izGQVkudO1wQxUbpei_QzKTolE0re1hMBXq8_WcVzwQVKYuzyYOEL9jA0/s1600/maze.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpY-LKsV1OQS4CLcoKVuFNrPnzGKplXd0MC9w8WLQfP855PhGm6nuxPxf7Rf3Ku8QqtjplRBihknpaIvV3z6izGQVkudO1wQxUbpei_QzKTolE0re1hMBXq8_WcVzwQVKYuzyYOEL9jA0/s320/maze.gif&quot; height=&quot;320&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;A Maze&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&amp;nbsp;Each corner is a vertex, Line between two corners is and edge.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicYvAmE16kInTqNgfO5YXaoyBrcDNDz5KgGPOGfvRgSdkk61mLtJVk2i34kV9wpfDlFMCghOMC23CRcgDYgoZeNPIHFm8gj1rlh_B9gOLK7kGh2Jx0g73TK7etO6N4eK5Rw-V-jcEGuD8/s1600/Tournament.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicYvAmE16kInTqNgfO5YXaoyBrcDNDz5KgGPOGfvRgSdkk61mLtJVk2i34kV9wpfDlFMCghOMC23CRcgDYgoZeNPIHFm8gj1rlh_B9gOLK7kGh2Jx0g73TK7etO6N4eK5Rw-V-jcEGuD8/s640/Tournament.png&quot; height=&quot;494&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;A tournament fixture&lt;br /&gt;
Courtesy:&amp;nbsp;&lt;a href=&quot;http://www.squadtd.com/&quot;&gt;http://www.squadtd.com/&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
Each team is a vertex, match between the teams is an edge.&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;h2&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Kind of graphs&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
There are numerous classifications and types of graphs available. I have collected a few of those types from various sources and organized a list of types of graphs:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Undirected Graphs&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmycfsD2KT69xNdFgNWSGfdmY8dh7Zu3pVhlJh461WtD6ZNq2FY9UUVwfeRUUG7I_1itjxTI_iTomDtQul3JvrHKnWOZPXsYtBHMH9ICm0Gm69dN9ycfJYLObjHvvWfFusqZdoXnPVNOI/s1600/undirected.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmycfsD2KT69xNdFgNWSGfdmY8dh7Zu3pVhlJh461WtD6ZNq2FY9UUVwfeRUUG7I_1itjxTI_iTomDtQul3JvrHKnWOZPXsYtBHMH9ICm0Gm69dN9ycfJYLObjHvvWfFusqZdoXnPVNOI/s1600/undirected.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Undirected Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Order of vertices doesn&#39;t matter&lt;/li&gt;
&lt;li&gt;1-2 is same as 2-1&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Directed Graphs&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1H8c9v3Qw9C_xULK28PEMd0XdyfgcSWYECEo1GAZWmvkF0VdI9bAoIYOIq_uVv6_xPfFkiOGThvGv8v7jIp4PsoT2hJpi6a2PmM4AS24EFZ4ZeBGdisQkQ1Iveb120twMv6RYbyx9TUs/s1600/directed.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1H8c9v3Qw9C_xULK28PEMd0XdyfgcSWYECEo1GAZWmvkF0VdI9bAoIYOIq_uVv6_xPfFkiOGThvGv8v7jIp4PsoT2hJpi6a2PmM4AS24EFZ4ZeBGdisQkQ1Iveb120twMv6RYbyx9TUs/s1600/directed.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Directed Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Order of vertices does matter&lt;/li&gt;
&lt;li&gt;1-2 is not same as 2-1&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Vertex labeled Graphs.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLEry05wAP8m9al42Oap0FOeodGWTM5JTZeK98BZ2sQBKpIGu20PtAkaQ1_CFgEpN0xmzvZXKXc3MbD0X0-907Ah6DbQ7zjaK3Q-qLhHX0pE981TLny1mJbHVXh2gzUqrV-T5FelFvqQM/s1600/vertexlabeled.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLEry05wAP8m9al42Oap0FOeodGWTM5JTZeK98BZ2sQBKpIGu20PtAkaQ1_CFgEpN0xmzvZXKXc3MbD0X0-907Ah6DbQ7zjaK3Q-qLhHX0pE981TLny1mJbHVXh2gzUqrV-T5FelFvqQM/s1600/vertexlabeled.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Vertex Labeled Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Each vertex contains additional information. e.g {2,orange}, {4,green}&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Cyclic Graphs.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw7bTnZILcmOOUjHdJXm1yMYTChBWdPimgd_VRAQ23si_pQP8wi7SqrANLdNXYMk_RbVYsTGXDF9CND3Xm0M3v-fmjDbbUIEdYStrB7nmVpnzOCtgQ5wi1K8X1bsUO0ygtic1aud5mP40/s1600/cyclic.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw7bTnZILcmOOUjHdJXm1yMYTChBWdPimgd_VRAQ23si_pQP8wi7SqrANLdNXYMk_RbVYsTGXDF9CND3Xm0M3v-fmjDbbUIEdYStrB7nmVpnzOCtgQ5wi1K8X1bsUO0ygtic1aud5mP40/s400/cyclic.png&quot; height=&quot;257&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Cyclic Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Graph contains at least one cycle.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Edge labeled Graphs.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH7QTRO61P1G_RFZmZja8ve468haA9IqoKvwL4mJSdiXEE23f8h4KpxlZ-lCLgfXG6zpOep9WncggOg2cOH-autHf9qvjuMrftxtgtAA0kvYDc61LFUr8vrXuwQl3b3-fBJpB4b6UzHME/s1600/edgelabeled.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH7QTRO61P1G_RFZmZja8ve468haA9IqoKvwL4mJSdiXEE23f8h4KpxlZ-lCLgfXG6zpOep9WncggOg2cOH-autHf9qvjuMrftxtgtAA0kvYDc61LFUr8vrXuwQl3b3-fBJpB4b6UzHME/s400/edgelabeled.png&quot; height=&quot;281&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Edge Labeled Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Edge has labels e.g an edge in the above graph will be represented as {orange,green,{blue,cyan}}&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Weighted Graphs.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6yHKQ1pBizTvlbqZT5ZnN_GWBjXz5OYjYKaQVQUihLzP19bv601vhGKfAEtytDsFnju7UyGaADb7Bcg9Vg89WVbStBTht8FucPH1unT5D2WsobrTm0eA59P-C8sfp0Vai0kYleVueyd0/s1600/weighted.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6yHKQ1pBizTvlbqZT5ZnN_GWBjXz5OYjYKaQVQUihLzP19bv601vhGKfAEtytDsFnju7UyGaADb7Bcg9Vg89WVbStBTht8FucPH1unT5D2WsobrTm0eA59P-C8sfp0Vai0kYleVueyd0/s320/weighted.png&quot; height=&quot;315&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Weighted Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Each edge has some weight associated with it.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Directed Acyclic Graphs.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY8g67bcsep5ogzT8dtXN7i8dl7b1NQFCVo8k4S8NaUlI0ql3s2QQctkRQ4X6cARWPSqv1fOnquCRa0jZjjedBjcKNaOqaQeOcGk0h4vGJ1VzXxfBd9GDNNLALExvbHAmV_IB_RnhKvYI/s1600/dag.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY8g67bcsep5ogzT8dtXN7i8dl7b1NQFCVo8k4S8NaUlI0ql3s2QQctkRQ4X6cARWPSqv1fOnquCRa0jZjjedBjcKNaOqaQeOcGk0h4vGJ1VzXxfBd9GDNNLALExvbHAmV_IB_RnhKvYI/s400/dag.png&quot; height=&quot;257&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Direct Acyclic Graph(DAG)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Graph has no cycles.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Disconnected Graphs&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG_RHRGT2ZteQsb_iX_1McURdDtSFByMysaRoRRjngmylmbpP2-XQWWVr2ik01DGrtqX7u8q8E_cfGFyKTCbinlVEMiAJkQ7p_qNycMC-5ARevZ9GeRhqNvYTHHOl2Y7IIUC0NppNy99s/s1600/disconnected.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG_RHRGT2ZteQsb_iX_1McURdDtSFByMysaRoRRjngmylmbpP2-XQWWVr2ik01DGrtqX7u8q8E_cfGFyKTCbinlVEMiAJkQ7p_qNycMC-5ARevZ9GeRhqNvYTHHOl2Y7IIUC0NppNy99s/s320/disconnected.png&quot; height=&quot;257&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Disconnected Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Vertices are disconnected&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Mixed graph&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWi6HcqeaQ_VHP15K9vvle5JrKjQoIjdk0il0ETBPofnFi0HUuxnYKj8sr9ehRDv7rgGUAu8l1i1KOJMvoh1lGphpRqBL3yeueL-daP5InglytK6vRh3LKK-jPMCMLxziYNApNM3LNvYs/s1600/mixed.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWi6HcqeaQ_VHP15K9vvle5JrKjQoIjdk0il0ETBPofnFi0HUuxnYKj8sr9ehRDv7rgGUAu8l1i1KOJMvoh1lGphpRqBL3yeueL-daP5InglytK6vRh3LKK-jPMCMLxziYNApNM3LNvYs/s320/mixed.png&quot; height=&quot;316&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Mixed Graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;background-color: white; line-height: 19.1875px;&quot;&gt;Some edges may be directed and some may be undirected&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;Multigraph&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ZXOQJ7CwZMicZmn_5WZMqI96eljAfnSBijb-7E0HL5HBnJgByK-SykxkzzS-IwpBec9pE8N0-R0_rk4Le5J1_L3kRLZ-Ce8W1Y7P2GDiBG6tx4ZMJsvGC2u-Aq7enJmJZ3GBB79Sch0/s1600/multigraph.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ZXOQJ7CwZMicZmn_5WZMqI96eljAfnSBijb-7E0HL5HBnJgByK-SykxkzzS-IwpBec9pE8N0-R0_rk4Le5J1_L3kRLZ-Ce8W1Y7P2GDiBG6tx4ZMJsvGC2u-Aq7enJmJZ3GBB79Sch0/s320/multigraph.png&quot; height=&quot;271&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Multigraph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;Characteristics:&lt;/b&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Multiple edges&lt;span style=&quot;background-color: white; line-height: 19.1875px;&quot;&gt;&amp;nbsp;(and sometimes loops) are allowed&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Quiver&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiENvwF3WejqoX7JUFzYFBoYGlJ65WAXI-epNmQL43IDQyF26j2lBL7STUNeGGGv3e2AVyZpTY1tGEcw-KTdRo0DIxYVNeruqSn0cJmcQAuRu3bK9vpGRD9cNsoD9QPoH6SZt9ae49lOZbS/s1600/quiver.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiENvwF3WejqoX7JUFzYFBoYGlJ65WAXI-epNmQL43IDQyF26j2lBL7STUNeGGGv3e2AVyZpTY1tGEcw-KTdRo0DIxYVNeruqSn0cJmcQAuRu3bK9vpGRD9cNsoD9QPoH6SZt9ae49lOZbS/s400/quiver.png&quot; height=&quot;356&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;Characteristics:&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white; line-height: 19.1875px;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Directed graph which may have more than one arrow from a given source to a given target. A quiver may also have directed loops in it.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Representation of graphs:&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirdUE_LP6I9-yyv7PSsl8Ml_jwE6sEvMjSuWCtHnlJoEvZi4OgcyQAle4qpn0_ED241uPNId62TmtANeE0W1lNIu6EwgEApAMeV_uj71vMfdZeTJVqFkZEeOsINYlv5cXtzhA-EDR58nI/s1600/adjacency.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirdUE_LP6I9-yyv7PSsl8Ml_jwE6sEvMjSuWCtHnlJoEvZi4OgcyQAle4qpn0_ED241uPNId62TmtANeE0W1lNIu6EwgEApAMeV_uj71vMfdZeTJVqFkZEeOsINYlv5cXtzhA-EDR58nI/s400/adjacency.png&quot; height=&quot;185&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Fig. 1: An undirected graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXRyck8oHv4oGKsSTV_04UlAZuxJ7zIh0srWepK_DE36bpdGQcK5yojW-j2sIVU6yuKsZf-YtsEXfXS6XmaIaXmEwnECQjcGBxiBXREZwapJ75sXy1nMgfJpECOYWSarvgLXfDau3jgN0/s1600/adjacency_dir.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXRyck8oHv4oGKsSTV_04UlAZuxJ7zIh0srWepK_DE36bpdGQcK5yojW-j2sIVU6yuKsZf-YtsEXfXS6XmaIaXmEwnECQjcGBxiBXREZwapJ75sXy1nMgfJpECOYWSarvgLXfDau3jgN0/s400/adjacency_dir.png&quot; height=&quot;185&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Fig 2: A directed graph&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
In order to use Graphs programatically , they need to be somehow represented in code. Following are the most widely used methods of representing a graph.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;&lt;u&gt;Adjacency Matrix :&lt;/u&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
For N vertices an adjacency matrix is an NxN array A such that&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A[i][j] = 1 if there is an edge E(i,j)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 0 otherwise&lt;br /&gt;
&lt;br /&gt;
For an undirected graph, A[i][j] = A[j][i]&lt;br /&gt;
&lt;br /&gt;
For weighted graphs,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A[i][j] = weight of the edge, if there is an edge E(i,j)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= a constant representing no edge (e.g a very large or very small value)&lt;br /&gt;
&lt;br /&gt;
For Fig 1, the adjacency matrix would be&amp;nbsp;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJhY9K-sebOVfJ6K0yQ7dhrYqttQiWyxYVT1H2KEgj1FuTxfHrIMKuRxHjzesl_8Ws4lDRu1vcEz3gILdDsHSXRyhMrR21sDRsG10lBODs-QPloYLjg78lL_qmTYbDVfSxSasvryuMadE/s1600/adjmatundirect.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJhY9K-sebOVfJ6K0yQ7dhrYqttQiWyxYVT1H2KEgj1FuTxfHrIMKuRxHjzesl_8Ws4lDRu1vcEz3gILdDsHSXRyhMrR21sDRsG10lBODs-QPloYLjg78lL_qmTYbDVfSxSasvryuMadE/s320/adjmatundirect.png&quot; height=&quot;273&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
The adjacency matrix for directed graph in Fig 2 would be:&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIxaaVLVBlzGl144oc27WbjsoUM3xuw8gjcjCr36GuL2OXPrd8YeN84wp2ojRlyZMQ5HdbySScyYetKO3Ek5OBpsOzbrQR_AbwaSR7D02PoojWiXWzaiuaSZSSgRaQOTr2NyFq1uEUI_k/s1600/adjmatdirect.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIxaaVLVBlzGl144oc27WbjsoUM3xuw8gjcjCr36GuL2OXPrd8YeN84wp2ojRlyZMQ5HdbySScyYetKO3Ek5OBpsOzbrQR_AbwaSR7D02PoojWiXWzaiuaSZSSgRaQOTr2NyFq1uEUI_k/s320/adjmatdirect.png&quot; height=&quot;269&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;h3&gt;
&lt;b&gt;&lt;u&gt;Adjacency List :&lt;/u&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
Adjacency matrix representation consume a lot of memory (O[N&lt;sup&gt;2&lt;/sup&gt;]). If the graph is complete or almost complete(i.e. contains most of the edges between the vertices), then this representation is good to use. But if there are very few edges as compared to number of vertices, it will unnecessarily consume extra space. Adjacency list can handle this situation very optimally.&lt;br /&gt;
&lt;br /&gt;
Every vertex has a linked list of the vertices it is connected with.&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
Adjacency list for Fig 1 would be:&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzMZfq-dDnVjaTSx762Q4YZkvvGiirR7w60Fhb2wbg6wqZVnCzzaAiTXQSFXJkzo9VZ83FK4-Cy06izljG0ZAhMxPnKUfnHL1HkXj6Mdyp4pJh_QMAbUI_hAY025DNy5pmDLDYu50gj6c/s1600/adjlistundirect.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzMZfq-dDnVjaTSx762Q4YZkvvGiirR7w60Fhb2wbg6wqZVnCzzaAiTXQSFXJkzo9VZ83FK4-Cy06izljG0ZAhMxPnKUfnHL1HkXj6Mdyp4pJh_QMAbUI_hAY025DNy5pmDLDYu50gj6c/s320/adjlistundirect.png&quot; height=&quot;265&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;div&gt;
Adjacency list for Fig 2 would be:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzNE7YL4VEHRnMxWPOed4otFpevwkhmg7WSAIdLQajBPdhEvL-DOk9X1ePj3MFC52Nn5KJ_uLTQCHM51DPOe9OzUoEO7qn2iSwmu8RVKuBT7_bxlt-8cuAtFpO87UrPfptxVn4Rt0Y_6s/s1600/adjlistdirect.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzNE7YL4VEHRnMxWPOed4otFpevwkhmg7WSAIdLQajBPdhEvL-DOk9X1ePj3MFC52Nn5KJ_uLTQCHM51DPOe9OzUoEO7qn2iSwmu8RVKuBT7_bxlt-8cuAtFpO87UrPfptxVn4Rt0Y_6s/s320/adjlistdirect.png&quot; height=&quot;265&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Following is code snippet to implement graphs in C using adjacency list.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-C&quot;&gt;/*graph.h*/
#ifndef _GRAPH_H_
#define _GRAPH_H_

typedef enum {UNDIRECTED=0,DIRECTED} graph_type_e;

/* Adjacency list node*/
typedef struct adjlist_node
{
    int vertex;                /*Index to adjacency list array*/
    struct adjlist_node *next; /*Pointer to the next node*/
}adjlist_node_t, *adjlist_node_p;

/* Adjacency list */
typedef struct adjlist
{
    int num_members;           /*number of members in the list (for future use)*/
    adjlist_node_t *head;      /*head of the adjacency linked list*/
}adjlist_t, *adjlist_p;

/* Graph structure. A graph is an array of adjacency lists.
   Size of array will be number of vertices in graph*/
typedef struct graph
{
    graph_type_e type;        /*Directed or undirected graph */
    int num_vertices;         /*Number of vertices*/
    adjlist_p adjListArr;     /*Adjacency lists&#39; array*/
}graph_t, *graph_p;

/* Exit function to handle fatal errors*/
__inline void err_exit(char* msg)
{
    printf(&quot;[Fatal Error]: %s \nExiting...\n&quot;, msg);
    exit(1);
}

#endif

&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-C&quot;&gt;/*graph.c*/
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &quot;graph.h&quot;

/* Function to create an adjacency list node*/
adjlist_node_p createNode(int v)
{
    adjlist_node_p newNode = (adjlist_node_p)malloc(sizeof(adjlist_node_t));
    if(!newNode)
        err_exit(&quot;Unable to allocate memory for new node&quot;);

    newNode-&amp;gt;vertex = v;
    newNode-&amp;gt;next = NULL;

    return newNode;
}

/* Function to create a graph with n vertices; Creates both directed and undirected graphs*/
graph_p createGraph(int n, graph_type_e type)
{
    int i;
    graph_p graph = (graph_p)malloc(sizeof(graph_t));
    if(!graph)
        err_exit(&quot;Unable to allocate memory for graph&quot;);
    graph-&amp;gt;num_vertices = n;
    graph-&amp;gt;type = type;

    /* Create an array of adjacency lists*/
    graph-&amp;gt;adjListArr = (adjlist_p)malloc(n * sizeof(adjlist_t));
    if(!graph-&amp;gt;adjListArr)
        err_exit(&quot;Unable to allocate memory for adjacency list array&quot;);

    for(i = 0; i &amp;lt; n; i++)
    {
        graph-&amp;gt;adjListArr[i].head = NULL;
        graph-&amp;gt;adjListArr[i].num_members = 0;
    }

    return graph;
}

/*Destroys the graph*/
void destroyGraph(graph_p graph)
{
    if(graph)
    {
        if(graph-&amp;gt;adjListArr)
        {
            int v;
            /*Free up the nodes*/
            for (v = 0; v &amp;lt; graph-&amp;gt;num_vertices; v++)
            {
                adjlist_node_p adjListPtr = graph-&amp;gt;adjListArr[v].head;
                while (adjListPtr)
                {
                    adjlist_node_p tmp = adjListPtr;
                    adjListPtr = adjListPtr-&amp;gt;next;
                    free(tmp);
                }
            }
            /*Free the adjacency list array*/
            free(graph-&amp;gt;adjListArr);
        }
        /*Free the graph*/
        free(graph);
    }
}

/* Adds an edge to a graph*/
void addEdge(graph_t *graph, int src, int dest)
{
    /* Add an edge from src to dst in the adjacency list*/
    adjlist_node_p newNode = createNode(dest);
    newNode-&amp;gt;next = graph-&amp;gt;adjListArr[src].head;
    graph-&amp;gt;adjListArr[src].head = newNode;
    graph-&amp;gt;adjListArr[src].num_members++;

    if(graph-&amp;gt;type == UNDIRECTED)
    {
        /* Add an edge from dest to src also*/
        newNode = createNode(src);
        newNode-&amp;gt;next = graph-&amp;gt;adjListArr[dest].head;
        graph-&amp;gt;adjListArr[dest].head = newNode;
        graph-&amp;gt;adjListArr[dest].num_members++;
    }
}

/* Function to print the adjacency list of graph*/
void displayGraph(graph_p graph)
{
    int i;
    for (i = 0; i &amp;lt; graph-&amp;gt;num_vertices; i++)
    {
        adjlist_node_p adjListPtr = graph-&amp;gt;adjListArr[i].head;
        printf(&quot;\n%d: &quot;, i);
        while (adjListPtr)
        {
            printf(&quot;%d-&amp;gt;&quot;, adjListPtr-&amp;gt;vertex);
            adjListPtr = adjListPtr-&amp;gt;next;
        }
        printf(&quot;NULL\n&quot;);
    }
}

int main()
{
    graph_p undir_graph = createGraph(5, UNDIRECTED);
    graph_p dir_graph = createGraph(5, DIRECTED);
    addEdge(undir_graph, 0, 1);
    addEdge(undir_graph, 0, 4);
    addEdge(undir_graph, 1, 2);
    addEdge(undir_graph, 1, 3);
    addEdge(undir_graph, 1, 4);
    addEdge(undir_graph, 2, 3);
    addEdge(undir_graph, 3, 4);

    addEdge(dir_graph, 0, 1);
    addEdge(dir_graph, 0, 4);
    addEdge(dir_graph, 1, 2);
    addEdge(dir_graph, 1, 3);
    addEdge(dir_graph, 1, 4);
    addEdge(dir_graph, 2, 3);
    addEdge(dir_graph, 3, 4);

    printf(&quot;\nUNDIRECTED GRAPH&quot;);
    displayGraph(undir_graph);
    destroyGraph(undir_graph);

    printf(&quot;\nDIRECTED GRAPH&quot;);
    displayGraph(dir_graph);
    destroyGraph(dir_graph);

    return 0;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Sources:&lt;/span&gt;&lt;br /&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Graph_(mathematics)&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;http://en.wikipedia.org/wiki/Graph_(mathematics)&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.blogger.com/goog_1776275656&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;http://web.cecs.pdx.edu/~sheard/course/Cs163/Doc/Graphs.html&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/goog_1776275656&quot;&gt;http://msdn.microsoft.com/en-us/library/ms379574(v=vs.80).aspx&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;fb-comments&quot; data-colorscheme=&quot;light&quot; data-href=&quot;http://simplestcodings.blogspot.in/2013/09/graphs.html&quot; data-numposts=&quot;5&quot; data-width=&quot;600&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
 SyntaxHighlighter.highlight();
&lt;/script&gt;&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2013/09/graphs.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXSqdZdeGbFjp3Cpwdr9KeyhszF_rwBfqxmYcGdgYF8OlkWo2Pni8kwmNu8uW4g5m9QVYjVm4pBNhl3mRU23nKsMmakozNmJ80GmL7Cy-zVAx0sopUOg35zuMEURm4A67Sd_28EnDT1wU/s72-c/dmrc.jpg" height="72" width="72"/><thr:total>23</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-2390350933796851984</guid><pubDate>Thu, 08 Nov 2012 14:01:00 +0000</pubDate><atom:updated>2023-12-20T22:41:23.654+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Trie</category><title>Trie implementation in C</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
To implement the kind of storage which stores strings as the search keys , there is a need to have special data structures which can store the strings efficiently and the searching of data based on the string keys is easier, efficient and faster. One such data structure is a tree based implementation called Trie.&lt;br /&gt;
&lt;br /&gt;
Trie is a data structure which can be used to implement a dictionary kind of application. It provides all the functionality to insert a string, search a string and delete a string from the dictionary. The insertion and deletion operation takes O(n) time where n is the length of the string to be deleted or inserted. &lt;br /&gt;
&lt;div&gt;
Some of the application of tries involve web based search engines, URL completion in autocomplete feature, Spell checker etc.&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Structure of Trie(Specific to this implementation):&lt;/h3&gt;
The trie implemented here consists of nodes. Each node has these fields:&lt;br /&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Key&lt;/strong&gt; - Part of the string to be serached,inserted or deleted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value&lt;/strong&gt; -&amp;nbsp; The value associated with a string (e.g In a dictionary it could be the meaning of the word which we are searching)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neighbour node address&lt;/strong&gt; - It consists of the address of the neighbouring node at the same level.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Previous neighbour address&lt;/strong&gt; - It consists of the address of the previous node at the same level.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Children node address&lt;/strong&gt; - It consists of the address of the child nodes of the current node.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parent node address&lt;/strong&gt; - It consists of the address of the parent node of the current node.&lt;/li&gt;
&lt;/ol&gt;
The additional nodes like &lt;em&gt;Parent&lt;/em&gt; and &lt;em&gt;Previous&lt;/em&gt; nodes are added to this implementation for making the search, and deletions easier.&lt;br /&gt;
&lt;br /&gt;
Here is a diagrammatical view of a trie nodes I have used in this implementation. The field &lt;em&gt;key&lt;/em&gt; is not represented in the diagram due to symmetry purposes.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyyoXgdnY_8wmBey5E6MSZ_3CMr5F7AsPOVmIsyl4OMDfxSRNiF21clUJNgcJeFj_ES1lQdSxZjD_UlHPiOITmhZcrPOyTbzm7WgRaCaAxgbhFEho5p4gp1JqAS0-VM-ZxVepMBh18xxak/s1600/TrieNodes.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;512&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyyoXgdnY_8wmBey5E6MSZ_3CMr5F7AsPOVmIsyl4OMDfxSRNiF21clUJNgcJeFj_ES1lQdSxZjD_UlHPiOITmhZcrPOyTbzm7WgRaCaAxgbhFEho5p4gp1JqAS0-VM-ZxVepMBh18xxak/s640/TrieNodes.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&amp;nbsp;&amp;nbsp;&lt;/div&gt;
Let us consider an example to understand tries in detail.&lt;br /&gt;
&lt;br /&gt;
Suppose we have to implement a database for the HR department of an organisation in which we have to store an employee&#39;s name and their ages. There is an assumption for this example that there each employee&#39;s name is unique.So there is a strange policy in this organisation that any new employee which has a name that already exists in the organisation, it would not hire that new employee.&lt;br /&gt;
&lt;br /&gt;
Let&#39;s use this hypothetical example just to understand how tries work.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Consider we have a new employee named Andrew with age 36. Lets populate our trie for &quot;andrew&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRkQQIKdrMrc3lF7p0Ks5CsWafymMTIaAY2WNPvLcTufu8pNynGWQb51h9l3VfZsukSZAKquPKA39hXL_cMVVncgA2cFXtMNSOgrVqY4ZJbcWg8OJwCqfqovNm00KUmF2jnZKr85CIhlj9/s1600/Trie1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRkQQIKdrMrc3lF7p0Ks5CsWafymMTIaAY2WNPvLcTufu8pNynGWQb51h9l3VfZsukSZAKquPKA39hXL_cMVVncgA2cFXtMNSOgrVqY4ZJbcWg8OJwCqfqovNm00KUmF2jnZKr85CIhlj9/s640/Trie1.png&quot; width=&quot;88&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Now add &quot;tina&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQvqCBg3tOBaxGa0ZeDE1Q5I81zQOVMePIoxibP94UoUfK67hiac-e-MUA6jdx-Zm8OuWssUb6eeFccnSwB52uc-AuGCSl7Tk0r6eRxJROfRKjKHO8MTyNLhmsxxToUkjRcQVwbvZvwIKU/s1600/Trie2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQvqCBg3tOBaxGa0ZeDE1Q5I81zQOVMePIoxibP94UoUfK67hiac-e-MUA6jdx-Zm8OuWssUb6eeFccnSwB52uc-AuGCSl7Tk0r6eRxJROfRKjKHO8MTyNLhmsxxToUkjRcQVwbvZvwIKU/s640/Trie2.png&quot; width=&quot;144&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add &quot;argo&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGQ1mmOXlDHfXXjpqM5sD8K1QG1V9XaZ4LIuuiFMFp1WINllNW8UcjdXtaWX10Vj80yqPB3fDmNDJYKa7J6dYIZ2jr7n47XY0h_Dbz0WAKBpUi5qeT6cyMeGIef_3n9yJinWmT8PuIgvQ/s1600/Trie3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGQ1mmOXlDHfXXjpqM5sD8K1QG1V9XaZ4LIuuiFMFp1WINllNW8UcjdXtaWX10Vj80yqPB3fDmNDJYKa7J6dYIZ2jr7n47XY0h_Dbz0WAKBpUi5qeT6cyMeGIef_3n9yJinWmT8PuIgvQ/s640/Trie3.png&quot; width=&quot;218&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add &quot;tim&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikwMX3T3ux-bghDQEEgvFkxMf7zjG0lkcFH-EaAthCk7zJwrFAIyTEyBfym18ouiwj4I9u4_LliCGCGWxePJxKI-cn-x-TTnjEPH4GMz5dD1xDZsvafaPTigXXtr9p-SHTu5tuyVasmB0N/s1600/Trie4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikwMX3T3ux-bghDQEEgvFkxMf7zjG0lkcFH-EaAthCk7zJwrFAIyTEyBfym18ouiwj4I9u4_LliCGCGWxePJxKI-cn-x-TTnjEPH4GMz5dD1xDZsvafaPTigXXtr9p-SHTu5tuyVasmB0N/s640/Trie4.png&quot; width=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add &quot;t&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43L3RM7dOY7tSbjrRduMPGPxdfKi6rmiBdIKMkSJQWMzb5DAdabKaP6-g3n7lXR2kJmcy3p4CcCPi96t7GdbqasbWos0cUpg5XcUfVuvYnTYDzdVQVHa7tMwdbN_NFTTYnvQ0EcS2Y-sr/s1600/Trie5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43L3RM7dOY7tSbjrRduMPGPxdfKi6rmiBdIKMkSJQWMzb5DAdabKaP6-g3n7lXR2kJmcy3p4CcCPi96t7GdbqasbWos0cUpg5XcUfVuvYnTYDzdVQVHa7tMwdbN_NFTTYnvQ0EcS2Y-sr/s640/Trie5.png&quot; width=&quot;378&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add &quot;amy&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPMlqDwT3KNWzIBgbxCcD1JLDB4T4EGmnUPYdiocG-j8bTj5cRf3th3umbfNYFu4by5PzWcO0BZQ22yhoxzne_I3anvjQkRgA7fZJjTwX4SKh1yJ3cU0G-Hiogn5n-CPB-_-N2p8aBDEOH/s1600/Trie6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPMlqDwT3KNWzIBgbxCcD1JLDB4T4EGmnUPYdiocG-j8bTj5cRf3th3umbfNYFu4by5PzWcO0BZQ22yhoxzne_I3anvjQkRgA7fZJjTwX4SKh1yJ3cU0G-Hiogn5n-CPB-_-N2p8aBDEOH/s640/Trie6.png&quot; width=&quot;454&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Add &quot;aramis&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9Ev4hsMXSIX0H1o2eCBv8lRQsnVkRJOH8QVwa_izHZihXrsEYVt_k5vcURb1f4iXwiZIsw1_u-DcUgj4sU7AwzumxDbPq4IbYanm0kj-HoDmm-BzGdJMigchdDMBlYtiFk9T6MNWKIn5W/s1600/Trie7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9Ev4hsMXSIX0H1o2eCBv8lRQsnVkRJOH8QVwa_izHZihXrsEYVt_k5vcURb1f4iXwiZIsw1_u-DcUgj4sU7AwzumxDbPq4IbYanm0kj-HoDmm-BzGdJMigchdDMBlYtiFk9T6MNWKIn5W/s640/Trie7.png&quot; width=&quot;546&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;br /&gt;
This is the complete Trie with all the entries. Now let us try deleting the names. I am not capturing the trivial cases. &lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Lets try deleting Argo.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-kUM7_5-rzI3wxmToOqXJsHqbN1Q2r4BNH1V-tHOfhyphenhyphenJDZeXRBI0lXJwXNm93ofcmAdk3b5OxqjdtCnSLEyjl5PD3l8FeYfBHWexSjQGhJVdHh8HEhJ10kJY1Bd3U-6wzav2gPKW7x-GS/s1600/TrieD1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-kUM7_5-rzI3wxmToOqXJsHqbN1Q2r4BNH1V-tHOfhyphenhyphenJDZeXRBI0lXJwXNm93ofcmAdk3b5OxqjdtCnSLEyjl5PD3l8FeYfBHWexSjQGhJVdHh8HEhJ10kJY1Bd3U-6wzav2gPKW7x-GS/s640/TrieD1.png&quot; width=&quot;548&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Delete Tina&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizzkmLSOiebTdMjnV-Jc5jy3d96tDzcgD4pbmJRc8hz1kefVrj0nhhgVBC5V0AfeGHAvhErBEPdLEp_uMkc-Pg4jIjw2GHzywIELu5nTx0ocasPOIiNaxJ_O5kpXbQ_kN4xXT9ztH7B14a/s1600/TrieD2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizzkmLSOiebTdMjnV-Jc5jy3d96tDzcgD4pbmJRc8hz1kefVrj0nhhgVBC5V0AfeGHAvhErBEPdLEp_uMkc-Pg4jIjw2GHzywIELu5nTx0ocasPOIiNaxJ_O5kpXbQ_kN4xXT9ztH7B14a/s640/TrieD2.png&quot; width=&quot;548&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Delete Andrew&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbOG45BzhShzt6yuebNAjj75Ue5QMbqedqiqiBCih7FiOw7hZ6urOgvRaRciLBMPNvSak-52G26VmLogQ_t_vP875j97ckLJdQcp5aqvhxIxrc9Yko5yMUauxbBPUqjdSHayYNBqSV1q0K/s1600/TrieD3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbOG45BzhShzt6yuebNAjj75Ue5QMbqedqiqiBCih7FiOw7hZ6urOgvRaRciLBMPNvSak-52G26VmLogQ_t_vP875j97ckLJdQcp5aqvhxIxrc9Yko5yMUauxbBPUqjdSHayYNBqSV1q0K/s640/TrieD3.png&quot; width=&quot;549&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
﻿&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
There is also a video from IIT Delhi which explains the tries. &lt;a href=&quot;http://www.youtube.com/watch?v=uhAUk63tLRM&quot; target=&quot;_blank&quot;&gt;Tries Explained&lt;/a&gt;.&lt;br /&gt;
The implementation for this Trie is given below. Please provide your suggestions to further improve the implementation.
&lt;!--pre class=&quot;cpp&quot; name=&quot;code&quot;--&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;/*trie.h*/
typedef int trieVal_t;

typedef struct trieNode {
    char key;
    trieVal_t value;
    struct trieNode *next;
    struct trieNode *prev;
    struct trieNode *children;
    struct trieNode *parent;
} trieNode_t;

void TrieCreate(trieNode_t **root);
trieNode_t* TrieSearch(trieNode_t *root, const char *key);
void TrieAdd(trieNode_t **root, char *key, int data);
void TrieRemove(trieNode_t **root, char *key);
void TrieDestroy( trieNode_t* root );
&lt;/code&gt;
&lt;/pre&gt;

&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;/*trie.c*/
#include &amp;lt;stdio.h&amp;gt;
#include &quot;trie.h&quot;
#include &amp;lt;stdlib.h&amp;gt;

trieNode_t *TrieCreateNode(char key, int data);

void TrieCreate(trieNode_t **root)
{
 *root = TrieCreateNode(&#39;\0&#39;, 0xffffffff);
}

trieNode_t *TrieCreateNode(char key, int data)
{
 trieNode_t *node = NULL;
 node = (trieNode_t *)malloc(sizeof(trieNode_t));

 if(NULL == node)
 {
  printf(&quot;Malloc failed\n&quot;);
  return node;
 }

 node-&amp;gt;key = key;
 node-&amp;gt;next = NULL;
 node-&amp;gt;children = NULL;
 node-&amp;gt;value = data;
 node-&amp;gt;parent= NULL;
 node-&amp;gt;prev= NULL;
 return node;
}

void TrieAdd(trieNode_t **root, char *key, int data)
{
 trieNode_t *pTrav = NULL;

 if(NULL == *root)
 {
  printf(&quot;NULL tree\n&quot;);
  return;
 }
#ifdef DEBUG
 printf(&quot;\nInserting key %s: \n&quot;,key);
#endif
 pTrav = (*root)-&amp;gt;children;



 if(pTrav == NULL)
 {
  /*First Node*/
  for(pTrav = *root; *key; pTrav = pTrav-&amp;gt;children)
  {
   pTrav-&amp;gt;children = TrieCreateNode(*key, 0xffffffff);
   pTrav-&amp;gt;children-&amp;gt;parent = pTrav;
#ifdef DEBUG
   printf(&quot;Inserting: [%c]\n&quot;,pTrav-&amp;gt;children-&amp;gt;key);
#endif
   key++;
  }

  pTrav-&amp;gt;children = TrieCreateNode(&#39;\0&#39;, data);
  pTrav-&amp;gt;children-&amp;gt;parent = pTrav;
#ifdef DEBUG
  printf(&quot;Inserting: [%c]\n&quot;,pTrav-&amp;gt;children-&amp;gt;key);
#endif
  return;
 }

 if(TrieSearch(pTrav, key))
 {
  printf(&quot;Duplicate!\n&quot;);
  return;
 }

 while(*key != &#39;\0&#39;)
 {
  if(*key == pTrav-&amp;gt;key)
  {
   key++;
#ifdef DEBUG
   printf(&quot;Traversing child: [%c]\n&quot;,pTrav-&amp;gt;children-&amp;gt;key);
#endif
   pTrav = pTrav-&amp;gt;children;
  }
  else
   break;
 }

 while(pTrav-&amp;gt;next)
 {
  if(*key == pTrav-&amp;gt;next-&amp;gt;key)
  {
   key++;
   TrieAdd(&amp;amp;(pTrav-&amp;gt;next), key, data);
   return;
  }
  pTrav = pTrav-&amp;gt;next;
 }

 if(*key)
 {
  pTrav-&amp;gt;next = TrieCreateNode(*key, 0xffffffff);
 }
 else
 {
  pTrav-&amp;gt;next = TrieCreateNode(*key, data);
 }

 pTrav-&amp;gt;next-&amp;gt;parent = pTrav-&amp;gt;parent;
 pTrav-&amp;gt;next-&amp;gt;prev = pTrav;

#ifdef DEBUG
 printf(&quot;Inserting [%c] as neighbour of [%c] \n&quot;,pTrav-&amp;gt;next-&amp;gt;key, pTrav-&amp;gt;key);
#endif

 if(!(*key))
  return;

 key++;

 for(pTrav = pTrav-&amp;gt;next; *key; pTrav = pTrav-&amp;gt;children)
 {
  pTrav-&amp;gt;children = TrieCreateNode(*key, 0xffffffff);
  pTrav-&amp;gt;children-&amp;gt;parent = pTrav;
#ifdef DEBUG
  printf(&quot;Inserting: [%c]\n&quot;,pTrav-&amp;gt;children-&amp;gt;key);
#endif
  key++;
 }

 pTrav-&amp;gt;children = TrieCreateNode(&#39;\0&#39;, data);
 pTrav-&amp;gt;children-&amp;gt;parent = pTrav;
#ifdef DEBUG
 printf(&quot;Inserting: [%c]\n&quot;,pTrav-&amp;gt;children-&amp;gt;key);
#endif
 return;
}

trieNode_t* TrieSearch(trieNode_t *root, const char *key)
{
 trieNode_t *level = root;
 trieNode_t *pPtr = NULL;

 int lvl=0;
 while(1)
 {
  trieNode_t *found = NULL;
  trieNode_t *curr;

  for (curr = level; curr != NULL; curr = curr-&amp;gt;next)
  {
   if (curr-&amp;gt;key == *key)
   {
    found = curr;
    lvl++;
    break;
   }
  }

  if (found == NULL)
   return NULL;

  if (*key == &#39;\0&#39;)
  {
   pPtr = curr;
   return pPtr;
  }

  level = found-&amp;gt;children;
  key++;
 }
}

void TrieRemove(trieNode_t **root, char *key)
{
 trieNode_t *tPtr = NULL;
 trieNode_t *tmp = NULL;

 if(NULL == *root || NULL == key)
  return;

 tPtr = TrieSearch((*root)-&amp;gt;children, key);

 if(NULL == tPtr)
 {
  printf(&quot;Key [%s] not found in trie\n&quot;, key);
  return;
 }

#ifdef DEBUG
 printf(&quot;Deleting key [%s] from trie\n&quot;, key);
#endif

 while(1)
 {
  if( tPtr-&amp;gt;prev &amp;amp;&amp;amp; tPtr-&amp;gt;next)
  {
   tmp = tPtr;
   tPtr-&amp;gt;next-&amp;gt;prev = tPtr-&amp;gt;prev;
   tPtr-&amp;gt;prev-&amp;gt;next = tPtr-&amp;gt;next;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
   break;
  }
  else if(tPtr-&amp;gt;prev &amp;amp;&amp;amp; !(tPtr-&amp;gt;next))
  {
   tmp = tPtr;
   tPtr-&amp;gt;prev-&amp;gt;next = NULL;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
   break;
  }
  else if(!(tPtr-&amp;gt;prev) &amp;amp;&amp;amp; tPtr-&amp;gt;next)
  {
   tmp = tPtr;
   tPtr-&amp;gt;parent-&amp;gt;children = tPtr-&amp;gt;next;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
   break;
  }
  else
  {
   tmp = tPtr;
   tPtr = tPtr-&amp;gt;parent;
   tPtr-&amp;gt;children = NULL;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
  }
 }

#ifdef DEBUG
 printf(&quot;Deleted key [%s] from trie\n&quot;, key);
#endif
}


void TrieDestroy( trieNode_t* root )
{
 trieNode_t *tPtr = root;
 trieNode_t *tmp = root;

    while(tPtr)
 {
  while(tPtr-&amp;gt;children)
   tPtr = tPtr-&amp;gt;children;

  if( tPtr-&amp;gt;prev &amp;amp;&amp;amp; tPtr-&amp;gt;next)
  {
   tmp = tPtr;
   tPtr-&amp;gt;next-&amp;gt;prev = tPtr-&amp;gt;prev;
   tPtr-&amp;gt;prev-&amp;gt;next = tPtr-&amp;gt;next;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
  }
  else if(tPtr-&amp;gt;prev &amp;amp;&amp;amp; !(tPtr-&amp;gt;next))
  {
   tmp = tPtr;
   tPtr-&amp;gt;prev-&amp;gt;next = NULL;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
  }
  else if(!(tPtr-&amp;gt;prev) &amp;amp;&amp;amp; tPtr-&amp;gt;next)
  {
   tmp = tPtr;
   tPtr-&amp;gt;parent-&amp;gt;children = tPtr-&amp;gt;next;
   tPtr-&amp;gt;next-&amp;gt;prev = NULL;
   tPtr = tPtr-&amp;gt;next;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
  }
  else
  {
   tmp = tPtr;
   if(tPtr-&amp;gt;parent == NULL)
   {
    /*Root*/
    free(tmp);
    return;
   }
   tPtr = tPtr-&amp;gt;parent;
   tPtr-&amp;gt;children = NULL;
#ifdef DEBUG
   printf(&quot;Deleted [%c] \n&quot;, tmp-&amp;gt;key);
#endif
   free(tmp);
  }
 }

}

&lt;/code&gt;
&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&lt;code class=&quot;language-cpp&quot;&gt;/*triedriver.c*/
/*
 * To Compile : gcc -o trie trie.c triedriver.c
 * To run: ./trie
 */
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &quot;trie.h&quot;

int main()
{
    trieNode_t *root;
    printf(&quot;Trie Example\n&quot;);
    
    /*Create a trie*/
    TrieCreate(&amp;amp;root);
    
    TrieAdd(&amp;amp;root, &quot;andrew&quot;, 1);
    TrieAdd(&amp;amp;root, &quot;tina&quot;, 2);
    TrieAdd(&amp;amp;root, &quot;argo&quot;, 3);
    TrieAdd(&amp;amp;root, &quot;timor&quot;, 5);
    TrieRemove(&amp;amp;root, &quot;tim&quot;);
    TrieAdd(&amp;amp;root, &quot;tim&quot;, 6);
    TrieRemove(&amp;amp;root, &quot;tim&quot;);
    TrieAdd(&amp;amp;root, &quot;ti&quot;, 6);
    TrieAdd(&amp;amp;root, &quot;amy&quot;, 7);
    TrieAdd(&amp;amp;root, &quot;aramis&quot;, 8);

    /*Destroy the trie*/
    TrieDestroy(root);
}

&lt;/code&gt;
&lt;/pre&gt;
In order to print the debug messages, use -DDEBUG while compiling with gcc:&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;gcc -o trie trie.c triedriver.c -DDEBUG&lt;/code&gt;
&lt;/pre&gt;

&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2012/11/trie-implementation-in-c.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyyoXgdnY_8wmBey5E6MSZ_3CMr5F7AsPOVmIsyl4OMDfxSRNiF21clUJNgcJeFj_ES1lQdSxZjD_UlHPiOITmhZcrPOyTbzm7WgRaCaAxgbhFEho5p4gp1JqAS0-VM-ZxVepMBh18xxak/s72-c/TrieNodes.png" height="72" width="72"/><thr:total>58</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-1180434876571261370</guid><pubDate>Wed, 31 Oct 2012 14:16:00 +0000</pubDate><atom:updated>2023-12-21T00:13:15.326+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">abstract binary search tree</category><category domain="http://www.blogger.com/atom/ns#">BST</category><category domain="http://www.blogger.com/atom/ns#">C programming</category><category domain="http://www.blogger.com/atom/ns#">Data Structures</category><category domain="http://www.blogger.com/atom/ns#">efficiency</category><category domain="http://www.blogger.com/atom/ns#">search algorithms</category><title>Abstract Binary Search Tree Implementation in C</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
There are several ways to store data using different data structures like Array, Linked Lists , Trees, Graphs, Hashmaps etc. The choice of the data structure depends on the application which extracts that data. On searching the web , one can easily find out which data structure is required for their application. Binary Search Tree is one such data structure which is generally used for storing data.&lt;br /&gt;
&lt;br /&gt;
A binary search tree consists of members called as nodes which have the data embedded in them. Generally, a BST node contains address fields and data field. The structure of a BST is something like this :&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYyxJVY1Z16EPtRK1R3aW0Q6hl0sC3hoS9At8kdcfE-OuQXcqvImPv6IIcKvR7kki1ZLMegJoSIPLIHpjzu4bl81qy8Q-dwUqH1z-NXSdH3TlFYqOFuAC3fghjRaGZvMgWYjvGdn767IA/s1600/bst.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;208&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYyxJVY1Z16EPtRK1R3aW0Q6hl0sC3hoS9At8kdcfE-OuQXcqvImPv6IIcKvR7kki1ZLMegJoSIPLIHpjzu4bl81qy8Q-dwUqH1z-NXSdH3TlFYqOFuAC3fghjRaGZvMgWYjvGdn767IA/s320/bst.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Each node can have a left subtree and right subtree which may or may not have any nodes.&lt;br /&gt;
&lt;br /&gt;
Binary Search tree has some properties which identifies it :&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;background-color: white; list-style-image: url(data:image/png; list-style-type: square; margin: 0.3em 0px 0px 1.6em; padding: 0px; text-align: -webkit-auto;&quot;&gt;
&lt;li style=&quot;margin-bottom: 0.1em;&quot;&gt;The left subtree members have a value which is always less than the value at the root node&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 0.1em;&quot;&gt;The right subtree members have a value which is always greater than the value at the root node&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 0.1em;&quot;&gt;Both the subtrees must be also a BST.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
The implementation provided in this post uses an abstract data type (void). To use this implementation as it is, one must implement these two functions&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;u&gt;Comparison Function&lt;/u&gt;&lt;/b&gt; - This function compares the data between two nodes. This function must return -1, 0 or 1 only. &amp;nbsp;The signature for this function is&amp;nbsp;&lt;b style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;&lt;i&gt;int &amp;lt;function-name&amp;gt; (void * data1, void * data2).&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Function should return 1 when data1 is greater than data2.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Function should return -1 when data1 is lesser than data2.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Function should return 0 when data1 is equal to data2. &amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;Display Function&lt;/b&gt;&lt;/u&gt; - This function is used for display purposes only. It displays the node data.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
A sample implementation of these two functions is presented in the driver example(&lt;i&gt;bstdriver.c&lt;/i&gt;) for the BST. This sample implementation uses &lt;i&gt;&lt;b&gt;int&lt;/b&gt; &lt;/i&gt;type as data.&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!--pre class=&quot;cpp&quot; name=&quot;code&quot;--&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;
/*bst.h*/
typedef struct bstNode
{
    struct bstNode *left;       /*Left Child*/
    struct bstNode *right;      /*Right Child*/
    struct bstNode *parent;     /*Parent Child*/
    void *data;                 /*Data*/
}BSTNode;

void BSTDestroy(BSTNode *root);
void BSTInsert(BSTNode **root, void *data, int (*cmp_fn)(void *, void *));
void BSTDelete(BSTNode **root, void *data, int (*cmp_fn)(void *, void *));
BSTNode* BSTSearch(BSTNode *root, void *data, int (*cmp_fn)(void *, void *));
void BSTDisplay(BSTNode *root, void (*display_fn)(BSTNode *));
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;
/*bst.c*/
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

#include &quot;bst.h&quot;

/* @brief Function to determine if a child is a left child or right child in a BST
 * @param data Pointer to the data to be used
 * @return LEFT - if left child
 *         RIGHT - if right child
 */
static inline const char* BSTFindChildLoc(BSTNode *parent, BSTNode *child)
{
    return (((parent-&amp;gt;left)==(child))?&quot;LEFT&quot;:&quot;RIGHT&quot;);
}

/* @brief Function to swap data between two nodes in a BST
 * @param data Pointer to the data to be used
 * @return void
 */
static inline void BSTSwapNodeData(BSTNode **node1, BSTNode **node2 )
{
    void *tmp;
    tmp = (*node1)-&amp;gt;data;
    (*node1)-&amp;gt;data = (*node2)-&amp;gt;data;
    (*node2)-&amp;gt;data = tmp;
}

/* @brief Function to create a node in a BST
 * @param data Pointer to the data to be used
 * @return Address of the node created
 */
BSTNode* BSTCreateNode(void *data)
{
    /*Allocate memory*/
    BSTNode* node= (BSTNode*)malloc(sizeof(BSTNode));

    if(NULL == node)
    {
        printf(&quot;Error: Memory Allocation could not be completed\n&quot;);
        return NULL;
    }

    /*Initialize links*/
    node-&amp;gt;left = NULL;
    node-&amp;gt;right= NULL;
    node-&amp;gt;parent= NULL;
    node-&amp;gt;data = data;

    printf(&quot;Allocated Node with address %p\n&quot;, node);
    return node;
}

/* @brief Function to destroy all nodes in a BST
 * @param root Pointer to the root of the BST
 * @return void
 */
void BSTDestroy(BSTNode *root)
{
    if(root)
    {
        /*Traverse down the left subtree*/
        if(root-&amp;gt;left)
            BSTDestroy(root-&amp;gt;left);
        /*Traverse down the right subtree*/
        if(root-&amp;gt;right)
            BSTDestroy(root-&amp;gt;right);
        /*Free the memory*/
        free(root);
        printf(&quot;DeAllocated Node with address %p\n&quot;, root);
    }
}

/* @brief Function to insert a node in a BST
 * @param root Pointer to pointer to the root of the BST
 * @param data Pointer to the data to be inserted
 * @param cmp_fn Funtion Pointer to the comparison function for BST[Provided by user]
 * @return void
 */
void BSTInsert(BSTNode **root, void *data, int (*cmp_fn)(void *, void *))
{
    BSTNode *tmp = NULL;
    BSTNode *ptr = NULL;

    if(NULL == root)
    {
        printf(&quot;Error: Null root\n&quot;);
        return;
    }


    if(!(*root))
    {
        /*Create a node*/
        tmp = BSTCreateNode(data);

        if(NULL == tmp)
        {
            printf(&quot;Error: Node insertion failed\n&quot;);
            return;
        }

        /*Root Node*/
        *root = tmp;
        return;
    }

    ptr = *root;

    /*If data is greater than the current node&#39;s data*/
    if(cmp_fn(data,ptr-&amp;gt;data) == 1)
    {
        /*data &amp;gt; ptr-&amp;gt;data : Insert to right*/
        if(ptr-&amp;gt;right == NULL)
        {
            /*Create a node*/
            tmp = BSTCreateNode(data);

            if(NULL == tmp)
            {
                printf(&quot;Error: Node insertion failed\n&quot;);
                return;
            }

            tmp-&amp;gt;parent = ptr;
            ptr-&amp;gt;right = tmp;
            return;
        }
        else
        {
            BSTInsert(&amp;amp;(ptr-&amp;gt;right), data, cmp_fn);
        }
    }
    /*If data is lesser than the current node&#39;s data*/
    else if(cmp_fn(data,ptr-&amp;gt;data) == -1)
    {
        /*data &amp;gt; ptr-&amp;gt;data : Insert to right*/
        if(ptr-&amp;gt;left == NULL)
        {
            tmp = BSTCreateNode(data);

            if(NULL == tmp)
            {
                printf(&quot;Error: Node insertion failed\n&quot;);
                return;
            }

            tmp-&amp;gt;parent = ptr;
            ptr-&amp;gt;left = tmp;
            return;
        }
        else
        {
            BSTInsert(&amp;amp;(ptr-&amp;gt;left), data, cmp_fn);
        }
    }
    /*If data is equal to the current node&#39;s data*/
    else
        printf(&quot;Error: Duplicate\n&quot;);
}

/* @brief Function to find the minimum valued node in the left subtree of a node
 * @param node Pointer to the node whose min valued child in left subtree has to be found
 * @return Address of the minimum valued node in the left subtree
 */
static BSTNode* BSTMinVal(BSTNode* node)
{
    BSTNode* current = node;

  /*Go to the leftmost member of the tree */
  while (current-&amp;gt;left != NULL)
  {
    current = current-&amp;gt;left;
  }
  return current;
}

/* @brief Function to find the Inorder successor of a node in a BST
 * @param node Pointer to the node whose inorder successor has to be found
 * @return Address of the Inorder successor
 */
static BSTNode* BSTInorderSuccessor(BSTNode* node)
{
    BSTNode *inOrdSucc = NULL;
    if(NULL == node)
        return NULL;

    /*Traverse the right subtree and find the minimum value */
    if( node-&amp;gt;right != NULL )
        return BSTMinVal(node-&amp;gt;right);

    inOrdSucc = node-&amp;gt;parent;

    while(inOrdSucc != NULL &amp;amp;&amp;amp; node == inOrdSucc-&amp;gt;right)
    {
        node = inOrdSucc;
        inOrdSucc = inOrdSucc-&amp;gt;parent;
    }
    return inOrdSucc;

}

/* @brief Helper Function to update the parent node links in a BST
 * @param node Pointer to pointer to the node whose parent will be updated
 * @param ptr Target Link
 * @return void
 */
static inline void updateParent(BSTNode **node, BSTNode *ptr)
{
    /*If the child is a left child*/
    if(BSTFindChildLoc((*node)-&amp;gt;parent, *node) == &quot;LEFT&quot;)
    {
        (*node)-&amp;gt;parent-&amp;gt;left = ptr;
    }
    /*If the child is a right child*/
    else
    {
        (*node)-&amp;gt;parent-&amp;gt;right = ptr;
    }
}

/* @brief Function to delete a node in a BST
 * @param root Pointer to pointer to the root of the BST
 * @param data Pointer to the data to be searched
 * @param cmp_fn Funtion Pointer to the comparison function for BST[Provided by user]
 * @return void
 */
void BSTDelete(BSTNode **root, void *data, int (*cmp_fn)(void *, void *))
{
    BSTNode *ptr = NULL;
    BSTNode *tmp = NULL;

    if(NULL == root)
    {
        printf(&quot;Error: Null root\n&quot;);
        return;
    }

    /*Search if the node exists in the BST*/
    ptr = BSTSearch(*root, data, cmp_fn);

    if(NULL == ptr)
    {
        printf(&quot;Error: Node not found\n&quot;);
        return;
    }

    /*If the node has no children*/
    if(ptr-&amp;gt;left == NULL &amp;amp;&amp;amp; ptr-&amp;gt;right == NULL)
    {
        /*No children*/
         tmp = ptr;

         /*Non-Root Node*/
         if(ptr-&amp;gt;parent)
            updateParent(&amp;amp;ptr, NULL);   /*Update the parent&#39;s link*/
         /*Root Node*/
         else
             *root = NULL;

         ptr = NULL;
         free(tmp);
         printf(&quot;DeAllocated Node with address %p\n&quot;, tmp);
    }
    /*If the node has single child*/
    else if((ptr-&amp;gt;left != NULL &amp;amp;&amp;amp; ptr-&amp;gt;right == NULL) || (ptr-&amp;gt;left == NULL &amp;amp;&amp;amp; ptr-&amp;gt;right != NULL))
    {
        tmp = ptr;

        /*Single Child*/
        if((ptr-&amp;gt;left != NULL) &amp;amp;&amp;amp; (ptr-&amp;gt;right == NULL))
        {
            ptr-&amp;gt;left-&amp;gt;parent = ptr-&amp;gt;parent;

            /*Non-Root Node*/
            if(ptr-&amp;gt;parent)
                updateParent(&amp;amp;ptr, ptr-&amp;gt;left);   /*Update the parent&#39;s link*/
            /*Root Node*/
            else
                *root = ptr-&amp;gt;left;
        }
        else
        {
            ptr-&amp;gt;right-&amp;gt;parent = ptr-&amp;gt;parent;   /*Update the parent&#39;s link*/
            /*Non-Root Node*/
            if(ptr-&amp;gt;parent)
                updateParent(&amp;amp;ptr, ptr-&amp;gt;right);
            /*Root Node*/
            else
                *root = ptr-&amp;gt;right;
        }

        free(tmp);
        printf(&quot;DeAllocated Node with address %p\n&quot;, tmp);
    }
    /*If the node has two children*/
    else if((ptr-&amp;gt;left != NULL) &amp;amp;&amp;amp; (ptr-&amp;gt;right != NULL))
    {
        /*Find the inorder successor of the node*/
        BSTNode *inOrdSucc = BSTInorderSuccessor(ptr);

        /*Swap the node&#39;s data with inorder successor&#39;s data*/
        BSTSwapNodeData(&amp;amp;ptr, &amp;amp;inOrdSucc);

        /*Delete the inorder successor node*/
        BSTDelete(&amp;amp;inOrdSucc, data, cmp_fn);
    }
}

/* @brief Function to search a data in a BST
 * @param root Pointer to the root of the BST
 * @param data Pointer to the data to be searched
 * @param cmp_fn Funtion Pointer to the comparison function for BST[Provided by user]
 * @return Address of the node found
 *         NULL if node not found
 */
BSTNode* BSTSearch(BSTNode *root, void *data, int (*cmp_fn)(void *, void *))
{
    BSTNode *ptr = NULL;

    if(NULL == root)
        return NULL;

    ptr = root;

    /*If the data is found*/
    if(cmp_fn(data, ptr-&amp;gt;data) == 0)
    {
        return ptr;
    }
    /*If data is greater than the current node&#39;s data*/
    else if(cmp_fn(data, ptr-&amp;gt;data) == 1)
    {
        return BSTSearch(ptr-&amp;gt;right, data, cmp_fn);
    }
    /*If data is lesser than the current node&#39;s data*/
    else if(cmp_fn(data, ptr-&amp;gt;data) == -1)
    {
        return BSTSearch(ptr-&amp;gt;left, data, cmp_fn);
    }

    return NULL;
}

/* @brief Function to traverse all nodes in a BST in InOrder
 * @param root Pointer to the root of the BST
 * @param display_fn Funtion Pointer to the display function for BST[Provided by user]
 * @return void
 */
static void BSTInOrder(BSTNode *root, void (*display_fn)(BSTNode *))
{
    if(NULL == root)
    {
        printf(&quot;Error: NULL root\n&quot;);
        return;
    }

    if(root-&amp;gt;left)
        BSTInOrder(root-&amp;gt;left, display_fn);

    printf(&quot;[%p]&quot;,root-&amp;gt;data);
    display_fn(root);

    if(root-&amp;gt;right)
        BSTInOrder(root-&amp;gt;right, display_fn);

}

/* @brief Function to traverse all nodes in a BST in PostOrder
 * @param root Pointer to the root of the BST
 * @param display_fn Funtion Pointer to the display function for BST[Provided by user]
 * @return void
 */
static void BSTPostOrder(BSTNode *root, void (*display_fn)(BSTNode *))
{
    if(NULL == root)
    {
        printf(&quot;Error: NULL root\n&quot;);
        return;
    }

    if(root-&amp;gt;left)
        BSTPostOrder(root-&amp;gt;left, display_fn);

    if(root-&amp;gt;right)
        BSTPostOrder(root-&amp;gt;right, display_fn);

    printf(&quot;[%p]&quot;,root-&amp;gt;data);
    display_fn(root);
}

/* @brief Function to traverse all nodes in a BST in PreOrder
 * @param root Pointer to the root of the BST
 * @param display_fn Funtion Pointer to the display function for BST[Provided by user]
 * @return void
 */
static void BSTPreOrder(BSTNode *root, void (*display_fn)(BSTNode *))
{
    if(NULL == root)
    {
        printf(&quot;Error: NULL root\n&quot;);
        return;
    }

    printf(&quot;[%p]&quot;,root-&amp;gt;data);
    display_fn(root);

    if(root-&amp;gt;left)
        BSTPreOrder(root-&amp;gt;left, display_fn);

    if(root-&amp;gt;right)
        BSTPreOrder(root-&amp;gt;right, display_fn);

}

/* @brief Function to display all nodes in a BST
 * @param root Pointer to the root of the BST
 * @param display_fn Funtion Pointer to the display function for BST[Provided by user]
 * @return void
 */
void BSTDisplay(BSTNode *root, void (*display_fn)(BSTNode *))
{
    printf(&quot;InOrder -&amp;gt;&quot;,root-&amp;gt;data);
    BSTInOrder(root,display_fn);
    printf(&quot;\n&quot;,root-&amp;gt;data);

    printf(&quot;PreOrder -&amp;gt;&quot;,root-&amp;gt;data);
    BSTPreOrder(root,display_fn);
    printf(&quot;\n&quot;,root-&amp;gt;data);

    printf(&quot;PostOrder -&amp;gt;&quot;,root-&amp;gt;data);
    BSTPostOrder(root,display_fn);
    printf(&quot;\n&quot;,root-&amp;gt;data);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;
/*bstdriver.c*/
/*
 * Compile: gcc -o test bst.c bstdriver.c
 * Run: ./test
 */
#include &amp;lt;stdio.h&amp;gt;
#include &quot;bst.h&quot;

int data[]={9,1,6,3,8,4,2,5,7};

/*Comparison function*/
int cmp_fn(void *data1, void *data2)
{
    if(*((int*)data1) &amp;gt; *((int*)data2))
        return 1;
    else if(*((int*)data1) &amp;lt; *((int*)data2))
        return -1;
    else
        return 0;
}

/*Display Function*/
static void displayNode(BSTNode *node)
{
    if(node)
        printf(&quot;%d &quot;,*((int*)node-&amp;gt;data));
}

int main()
{
    BSTNode *root = NULL;

    int i,sVal=-1;
    int size = sizeof(data)/sizeof(data[0]);

    for(i=0; i &amp;lt; size; i++)
        BSTInsert(&amp;amp;root, &amp;amp;data[i], cmp_fn);

    BSTDisplay(root, displayNode);

    printf(&quot;Search Value : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;sVal);

    if(NULL == BSTSearch(root, &amp;amp;sVal, cmp_fn))
        printf(&quot;Not Found\n&quot;);
    else
        printf(&quot;Found\n&quot;);

    printf(&quot;Delete Value : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;sVal);
    BSTDelete(&amp;amp;root, &amp;amp;sVal, cmp_fn);
    BSTDisplay(root, displayNode);

    BSTDestroy(root);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
 SyntaxHighlighter.highlight();
&lt;/script&gt;</description><link>http://simplestcodings.blogspot.com/2012/10/abstract-binary-search-tree.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYyxJVY1Z16EPtRK1R3aW0Q6hl0sC3hoS9At8kdcfE-OuQXcqvImPv6IIcKvR7kki1ZLMegJoSIPLIHpjzu4bl81qy8Q-dwUqH1z-NXSdH3TlFYqOFuAC3fghjRaGZvMgWYjvGdn767IA/s72-c/bst.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-6580887668707344186</guid><pubDate>Sun, 23 Sep 2012 18:31:00 +0000</pubDate><atom:updated>2023-12-21T00:27:43.525+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">File transfer protocol</category><category domain="http://www.blogger.com/atom/ns#">FTP</category><category domain="http://www.blogger.com/atom/ns#">FTP implementation in C</category><title>FTP implementation in C</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBF0T31WXW0AKpxMaQfg0FkDLnjBpQOCNUpKuIK_4hswYNROrZUDb6zhHsLFssekSVDvfkTaaJeYM5xHk4trVDG9nhE8qCBt4GQbaPyr2c2bcTPW8lZ8mYsKgX1sfpLQYJr40-IhYowJR6nUt9-95ahynhYaPN3RcxD3bEhKgXZZralcurHfUzb1yYmYY/s1024/ftp.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBF0T31WXW0AKpxMaQfg0FkDLnjBpQOCNUpKuIK_4hswYNROrZUDb6zhHsLFssekSVDvfkTaaJeYM5xHk4trVDG9nhE8qCBt4GQbaPyr2c2bcTPW8lZ8mYsKgX1sfpLQYJr40-IhYowJR6nUt9-95ahynhYaPN3RcxD3bEhKgXZZralcurHfUzb1yYmYY/s320/ftp.jpeg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Most of the beginners would wonder how the known services work. Well this post will give an overview of one of the well-written services in C , the FTP application. I thought that there is no need to re-invent the wheel and use this code as is from Apple&#39;s open source initiative.The code is written in C. &lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
I am providing the code only for the main file which contains FTP specific functions.
The rest of the supporting files including the Makefile can be downloaded from &lt;a href=&quot;https://docs.google.com/open?id=0B2BScYvBeeu-bU8xbmh5eW5zS2c&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Disclaimer&amp;nbsp;:&lt;/b&gt; This code is taken from&amp;nbsp;&lt;a href=&quot;http://opensource.apple.com/&quot; target=&quot;_blank&quot;&gt;Apple Opensource&lt;/a&gt;&amp;nbsp;. I don&#39;t want Apple to sue me ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;


&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;/*ftp.c*/

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * &quot;Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the &#39;License&#39;).  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an &#39;AS IS&#39; basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.&quot;
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * Copyright (c) 1985, 1989, 1993, 1994
 * The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 * This product includes software developed by the University of
 * California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS&#39;&#39; AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


#include &amp;lt;sys/param.h&amp;gt;
#include &amp;lt;sys/stat.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;
#include &amp;lt;sys/socket.h&amp;gt;
#include &amp;lt;sys/time.h&amp;gt;
#include &amp;lt;sys/file.h&amp;gt;

#include &amp;lt;netinet/in.h&amp;gt;
#include &amp;lt;netinet/in_systm.h&amp;gt;
#include &amp;lt;netinet/ip.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;
#include &amp;lt;arpa/ftp.h&amp;gt;
#include &amp;lt;arpa/telnet.h&amp;gt;

#include &amp;lt;ctype.h&amp;gt;
#include &amp;lt;err.h&amp;gt;
#include &amp;lt;errno.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;netdb.h&amp;gt;
#include &amp;lt;pwd.h&amp;gt;
#include &amp;lt;signal.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdarg.h&amp;gt;

#include &quot;ftp_var.h&quot;

extern int h_errno;

struct sockaddr_in hisctladdr;
struct sockaddr_in data_addr;
int data = -1;
int abrtflag = 0;
jmp_buf ptabort;
int ptabflg;
int ptflag = 0;
struct sockaddr_in myctladdr;
off_t restart_point = 0;

FILE *cin, *cout;

char *
hookup(host, port)
 char *host;
 int port;
{
 struct hostent *hp = 0;
 int s, len, tos;
 static char hostnamebuf[80];

 memset((char *)&amp;amp;hisctladdr, 0, sizeof (hisctladdr));
 hisctladdr.sin_addr.s_addr = inet_addr(host);
 if (hisctladdr.sin_addr.s_addr != -1) {
  hisctladdr.sin_family = AF_INET;
  (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
 } else {
  hp = gethostbyname(host);
  if (hp == NULL) {
   warnx(&quot;%s: %s&quot;, host, hstrerror(h_errno));
   code = -1;
   return ((char *) 0);
  }
  hisctladdr.sin_family = hp-&amp;gt;h_addrtype;
  memmove((caddr_t)&amp;amp;hisctladdr.sin_addr,
    hp-&amp;gt;h_addr_list[0], hp-&amp;gt;h_length);
  (void) strncpy(hostnamebuf, hp-&amp;gt;h_name, sizeof(hostnamebuf));
 }
 hostname = hostnamebuf;
 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
 if (s &amp;lt; 0) {
  warn(&quot;socket&quot;);
  code = -1;
  return (0);
 }
 hisctladdr.sin_port = port;
 while (connect(s, (struct sockaddr *)&amp;amp;hisctladdr, sizeof (hisctladdr)) &amp;lt; 0) {
  if (hp &amp;amp;&amp;amp; hp-&amp;gt;h_addr_list[1]) {
   int oerrno = errno;
   char *ia;

   ia = inet_ntoa(hisctladdr.sin_addr);
   errno = oerrno;
   warn(&quot;connect to address %s&quot;, ia);
   hp-&amp;gt;h_addr_list++;
   memmove((caddr_t)&amp;amp;hisctladdr.sin_addr,
     hp-&amp;gt;h_addr_list[0], hp-&amp;gt;h_length);
   fprintf(stdout, &quot;Trying %s...\n&quot;,
    inet_ntoa(hisctladdr.sin_addr));
   (void) close(s);
   s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
   if (s &amp;lt; 0) {
    warn(&quot;socket&quot;);
    code = -1;
    return (0);
   }
   continue;
  }
  warn(&quot;connect&quot;);
  code = -1;
  goto bad;
 }
 len = sizeof (myctladdr);
 if (getsockname(s, (struct sockaddr *)&amp;amp;myctladdr, &amp;amp;len) &amp;lt; 0) {
  warn(&quot;getsockname&quot;);
  code = -1;
  goto bad;
 }
#ifdef IP_TOS
 tos = IPTOS_LOWDELAY;
 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&amp;amp;tos, sizeof(int)) &amp;lt; 0)
  warn(&quot;setsockopt TOS (ignored)&quot;);
#endif
 cin = fdopen(s, &quot;r&quot;);
 cout = fdopen(s, &quot;w&quot;);
 if (cin == NULL || cout == NULL) {
  warnx(&quot;fdopen failed.&quot;);
  if (cin)
   (void) fclose(cin);
  if (cout)
   (void) fclose(cout);
  code = -1;
  goto bad;
 }
 if (verbose)
  printf(&quot;Connected to %s.\n&quot;, hostname);
 if (getreply(0) &amp;gt; 2) {  /* read startup message from server */
  if (cin)
   (void) fclose(cin);
  if (cout)
   (void) fclose(cout);
  code = -1;
  goto bad;
 }
#ifdef SO_OOBINLINE
 {
 int on = 1;

 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&amp;amp;on, sizeof(on))
  &amp;lt; 0 &amp;amp;&amp;amp; debug) {
   warn(&quot;setsockopt&quot;);
  }
 }
#endif /* SO_OOBINLINE */

 return (hostname);
bad:
 (void) close(s);
 return ((char *)0);
}

int
login(host)
 char *host;
{
 char tmp[80];
 char *user, *pass, *acct;
 int n, aflag = 0;

 user = pass = acct = 0;
 if (ruserpass(host, &amp;amp;user, &amp;amp;pass, &amp;amp;acct) &amp;lt; 0) {
  code = -1;
  return (0);
 }
 while (user == NULL) {
  char *myname = getlogin();

  if (myname == NULL) {
   struct passwd *pp = getpwuid(getuid());

   if (pp != NULL)
    myname = pp-&amp;gt;pw_name;
  }
  if (myname)
   printf(&quot;Name (%s:%s): &quot;, host, myname);
  else
   printf(&quot;Name (%s): &quot;, host);
  (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  tmp[strlen(tmp) - 1] = &#39;\0&#39;;
  if (*tmp == &#39;\0&#39;)
   user = myname;
  else
   user = tmp;
 }
 n = command(&quot;USER %s&quot;, user);
 if (n == CONTINUE) {
  if (pass == NULL)
   pass = getpass(&quot;Password:&quot;);
  n = command(&quot;PASS %s&quot;, pass);
 }
 if (n == CONTINUE) {
  aflag++;
  acct = getpass(&quot;Account:&quot;);
  n = command(&quot;ACCT %s&quot;, acct);
 }
 if (n != COMPLETE) {
  warnx(&quot;Login failed.&quot;);
  return (0);
 }
 if (!aflag &amp;amp;&amp;amp; acct != NULL)
  (void) command(&quot;ACCT %s&quot;, acct);
 if (proxy)
  return (1);
 for (n = 0; n &amp;lt; macnum; ++n) {
  if (!strcmp(&quot;init&quot;, macros[n].mac_name)) {
   (void) strcpy(line, &quot;$init&quot;);
   makeargv();
   domacro(margc, margv);
   break;
  }
 }
 return (1);
}

void
cmdabort()
{

 printf(&quot;\n&quot;);
 (void) fflush(stdout);
 abrtflag++;
 if (ptflag)
  longjmp(ptabort,1);
}

int command(const char *fmt, ...)
{
 va_list ap;
 int r;
 sig_t oldintr;

 abrtflag = 0;
 if (debug) {
  printf(&quot;---&amp;gt; &quot;);
  va_start(ap, fmt);
  if (strncmp(&quot;PASS &quot;, fmt, 5) == 0)
   printf(&quot;PASS XXXX&quot;);
  else 
   vfprintf(stdout, fmt, ap);
  va_end(ap);
  printf(&quot;\n&quot;);
  (void) fflush(stdout);
 }
 if (cout == NULL) {
  warn(&quot;No control connection for command&quot;);
  code = -1;
  return (0);
 }
 oldintr = signal(SIGINT, cmdabort);
 va_start(ap, fmt);
 vfprintf(cout, fmt, ap);
 va_end(ap);
 fprintf(cout, &quot;\r\n&quot;);
 (void) fflush(cout);
 cpend = 1;
 r = getreply(!strcmp(fmt, &quot;QUIT&quot;));
 if (abrtflag &amp;amp;&amp;amp; oldintr != SIG_IGN)
  (*oldintr)(SIGINT);
 (void) signal(SIGINT, oldintr);
 return (r);
}

char reply_string[BUFSIZ];  /* last line of previous reply */

int
getreply(expecteof)
 int expecteof;
{
 int c, n;
 int dig;
 int originalcode = 0, continuation = 0;
 sig_t oldintr;
 int pflag = 0;
 char *cp, *pt = pasv;

 oldintr = signal(SIGINT, cmdabort);
 for (;;) {
  dig = n = code = 0;
  cp = reply_string;
  while ((c = getc(cin)) != &#39;\n&#39;) {
   if (c == IAC) {     /* handle telnet commands */
    switch (c = getc(cin)) {
    case WILL:
    case WONT:
     c = getc(cin);
     fprintf(cout, &quot;%c%c%c&quot;, IAC, DONT, c);
     (void) fflush(cout);
     break;
    case DO:
    case DONT:
     c = getc(cin);
     fprintf(cout, &quot;%c%c%c&quot;, IAC, WONT, c);
     (void) fflush(cout);
     break;
    default:
     break;
    }
    continue;
   }
   dig++;
   if (c == EOF) {
    if (expecteof) {
     (void) signal(SIGINT,oldintr);
     code = 221;
     return (0);
    }
    lostpeer();
    if (verbose) {
     printf(&quot;421 Service not available, remote server has closed connection\n&quot;);
     (void) fflush(stdout);
    }
    code = 421;
    return (4);
   }
   if (c != &#39;\r&#39; &amp;amp;&amp;amp; (verbose &amp;gt; 0 ||
       (verbose &amp;gt; -1 &amp;amp;&amp;amp; n == &#39;5&#39; &amp;amp;&amp;amp; dig &amp;gt; 4))) {
    if (proxflag &amp;amp;&amp;amp;
       (dig == 1 || dig == 5 &amp;amp;&amp;amp; verbose == 0))
     printf(&quot;%s:&quot;,hostname);
    (void) putchar(c);
   }
   if (dig &amp;lt; 4 &amp;amp;&amp;amp; isdigit(c))
    code = code * 10 + (c - &#39;0&#39;);
   if (!pflag &amp;amp;&amp;amp; code == 227)
    pflag = 1;
   if (dig &amp;gt; 4 &amp;amp;&amp;amp; pflag == 1 &amp;amp;&amp;amp; isdigit(c))
    pflag = 2;
   if (pflag == 2) {
    if (c != &#39;\r&#39; &amp;amp;&amp;amp; c != &#39;)&#39;)
     *pt++ = c;
    else {
     *pt = &#39;\0&#39;;
     pflag = 3;
    }
   }
   if (dig == 4 &amp;amp;&amp;amp; c == &#39;-&#39;) {
    if (continuation)
     code = 0;
    continuation++;
   }
   if (n == 0)
    n = c;
   if (cp &amp;lt; &amp;amp;reply_string[sizeof(reply_string) - 1])
    *cp++ = c;
  }
  if (verbose &amp;gt; 0 || verbose &amp;gt; -1 &amp;amp;&amp;amp; n == &#39;5&#39;) {
   (void) putchar(c);
   (void) fflush (stdout);
  }
  if (continuation &amp;amp;&amp;amp; code != originalcode) {
   if (originalcode == 0)
    originalcode = code;
   continue;
  }
  *cp = &#39;\0&#39;;
  if (n != &#39;1&#39;)
   cpend = 0;
  (void) signal(SIGINT,oldintr);
  if (code == 421 || originalcode == 421)
   lostpeer();
  if (abrtflag &amp;amp;&amp;amp; oldintr != cmdabort &amp;amp;&amp;amp; oldintr != SIG_IGN)
   (*oldintr)(SIGINT);
  return (n - &#39;0&#39;);
 }
}

int
empty(mask, sec)
 struct fd_set *mask;
 int sec;
{
 struct timeval t;

 t.tv_sec = (long) sec;
 t.tv_usec = 0;
 return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &amp;amp;t));
}

jmp_buf sendabort;

void
abortsend()
{

 mflag = 0;
 abrtflag = 0;
 printf(&quot;\nsend aborted\nwaiting for remote to finish abort\n&quot;);
 (void) fflush(stdout);
 longjmp(sendabort, 1);
}

#define HASHBYTES 1024

void
sendrequest(cmd, local, remote, printnames)
 char *cmd, *local, *remote;
 int printnames;
{
 struct stat st;
 struct timeval start, stop;
 int c, d;
 FILE *fin, *dout = 0, *popen();
 int (*closefunc) __P((FILE *));
 sig_t oldintr, oldintp;
 long bytes = 0, hashbytes = HASHBYTES;
 char *lmode, buf[BUFSIZ], *bufp;

 if (verbose &amp;amp;&amp;amp; printnames) {
  if (local &amp;amp;&amp;amp; *local != &#39;-&#39;)
   printf(&quot;local: %s &quot;, local);
  if (remote)
   printf(&quot;remote: %s\n&quot;, remote);
 }
 if (proxy) {
  proxtrans(cmd, local, remote);
  return;
 }
 if (curtype != type)
  changetype(type, 0);
 closefunc = NULL;
 oldintr = NULL;
 oldintp = NULL;
 lmode = &quot;w&quot;;
 if (setjmp(sendabort)) {
  while (cpend) {
   (void) getreply(0);
  }
  if (data &amp;gt;= 0) {
   (void) close(data);
   data = -1;
  }
  if (oldintr)
   (void) signal(SIGINT,oldintr);
  if (oldintp)
   (void) signal(SIGPIPE,oldintp);
  code = -1;
  return;
 }
 oldintr = signal(SIGINT, abortsend);
 if (strcmp(local, &quot;-&quot;) == 0)
  fin = stdin;
 else if (*local == &#39;|&#39;) {
  oldintp = signal(SIGPIPE,SIG_IGN);
  fin = popen(local + 1, &quot;r&quot;);
  if (fin == NULL) {
   warn(&quot;%s&quot;, local + 1);
   (void) signal(SIGINT, oldintr);
   (void) signal(SIGPIPE, oldintp);
   code = -1;
   return;
  }
  closefunc = pclose;
 } else {
  fin = fopen(local, &quot;r&quot;);
  if (fin == NULL) {
   warn(&quot;local: %s&quot;, local);
   (void) signal(SIGINT, oldintr);
   code = -1;
   return;
  }
  closefunc = fclose;
  if (fstat(fileno(fin), &amp;amp;st) &amp;lt; 0 ||
      (st.st_mode&amp;amp;S_IFMT) != S_IFREG) {
   fprintf(stdout, &quot;%s: not a plain file.\n&quot;, local);
   (void) signal(SIGINT, oldintr);
   fclose(fin);
   code = -1;
   return;
  }
 }
 if (initconn()) {
  (void) signal(SIGINT, oldintr);
  if (oldintp)
   (void) signal(SIGPIPE, oldintp);
  code = -1;
  if (closefunc != NULL)
   (*closefunc)(fin);
  return;
 }
 if (setjmp(sendabort))
  goto abort;

 if (restart_point &amp;amp;&amp;amp;
     (strcmp(cmd, &quot;STOR&quot;) == 0 || strcmp(cmd, &quot;APPE&quot;) == 0)) {
  int rc;

  switch (curtype) {
  case TYPE_A:
   rc = fseek(fin, (long) restart_point, SEEK_SET);
   break;
  case TYPE_I:
  case TYPE_L:
   rc = lseek(fileno(fin), restart_point, SEEK_SET);
   break;
  }
  if (rc &amp;lt; 0) {
   warn(&quot;local: %s&quot;, local);
   restart_point = 0;
   if (closefunc != NULL)
    (*closefunc)(fin);
   return;
  }
  if (command(&quot;REST %ld&quot;, (long) restart_point)
   != CONTINUE) {
   restart_point = 0;
   if (closefunc != NULL)
    (*closefunc)(fin);
   return;
  }
  restart_point = 0;
  lmode = &quot;r+w&quot;;
 }
 if (remote) {
  if (command(&quot;%s %s&quot;, cmd, remote) != PRELIM) {
   (void) signal(SIGINT, oldintr);
   if (oldintp)
    (void) signal(SIGPIPE, oldintp);
   if (closefunc != NULL)
    (*closefunc)(fin);
   return;
  }
 } else
  if (command(&quot;%s&quot;, cmd) != PRELIM) {
   (void) signal(SIGINT, oldintr);
   if (oldintp)
    (void) signal(SIGPIPE, oldintp);
   if (closefunc != NULL)
    (*closefunc)(fin);
   return;
  }
 dout = dataconn(lmode);
 if (dout == NULL)
  goto abort;
 (void) gettimeofday(&amp;amp;start, (struct timezone *)0);
 oldintp = signal(SIGPIPE, SIG_IGN);
 switch (curtype) {

 case TYPE_I:
 case TYPE_L:
  errno = d = 0;
  while ((c = read(fileno(fin), buf, sizeof (buf))) &amp;gt; 0) {
   bytes += c;
   for (bufp = buf; c &amp;gt; 0; c -= d, bufp += d)
    if ((d = write(fileno(dout), bufp, c)) &amp;lt;= 0)
     break;
   if (hash) {
    while (bytes &amp;gt;= hashbytes) {
     (void) putchar(&#39;#&#39;);
     hashbytes += HASHBYTES;
    }
    (void) fflush(stdout);
   }
  }
  if (hash &amp;amp;&amp;amp; bytes &amp;gt; 0) {
   if (bytes &amp;lt; HASHBYTES)
    (void) putchar(&#39;#&#39;);
   (void) putchar(&#39;\n&#39;);
   (void) fflush(stdout);
  }
  if (c &amp;lt; 0)
   warn(&quot;local: %s&quot;, local);
  if (d &amp;lt; 0) {
   if (errno != EPIPE) 
    warn(&quot;netout&quot;);
   bytes = -1;
  }
  break;

 case TYPE_A:
  while ((c = getc(fin)) != EOF) {
   if (c == &#39;\n&#39;) {
    while (hash &amp;amp;&amp;amp; (bytes &amp;gt;= hashbytes)) {
     (void) putchar(&#39;#&#39;);
     (void) fflush(stdout);
     hashbytes += HASHBYTES;
    }
    if (ferror(dout))
     break;
    (void) putc(&#39;\r&#39;, dout);
    bytes++;
   }
   (void) putc(c, dout);
   bytes++;
 /*  if (c == &#39;\r&#39;) {      */
 /*  (void) putc(&#39;\0&#39;, dout);  // this violates rfc */
 /*   bytes++;    */
 /*  }                             */ 
  }
  if (hash) {
   if (bytes &amp;lt; hashbytes)
    (void) putchar(&#39;#&#39;);
   (void) putchar(&#39;\n&#39;);
   (void) fflush(stdout);
  }
  if (ferror(fin))
   warn(&quot;local: %s&quot;, local);
  if (ferror(dout)) {
   if (errno != EPIPE)
    warn(&quot;netout&quot;);
   bytes = -1;
  }
  break;
 }
 if (closefunc != NULL)
  (*closefunc)(fin);
 (void) fclose(dout);
 (void) gettimeofday(&amp;amp;stop, (struct timezone *)0);
 (void) getreply(0);
 (void) signal(SIGINT, oldintr);
 if (oldintp)
  (void) signal(SIGPIPE, oldintp);
 if (bytes &amp;gt; 0)
  ptransfer(&quot;sent&quot;, bytes, &amp;amp;start, &amp;amp;stop);
 return;
abort:
 (void) signal(SIGINT, oldintr);
 if (oldintp)
  (void) signal(SIGPIPE, oldintp);
 if (!cpend) {
  code = -1;
  return;
 }
 if (data &amp;gt;= 0) {
  (void) close(data);
  data = -1;
 }
 if (dout)
  (void) fclose(dout);
 (void) getreply(0);
 code = -1;
 if (closefunc != NULL &amp;amp;&amp;amp; fin != NULL)
  (*closefunc)(fin);
 (void) gettimeofday(&amp;amp;stop, (struct timezone *)0);
 if (bytes &amp;gt; 0)
  ptransfer(&quot;sent&quot;, bytes, &amp;amp;start, &amp;amp;stop);
}

jmp_buf recvabort;

void
abortrecv()
{

 mflag = 0;
 abrtflag = 0;
 printf(&quot;\nreceive aborted\nwaiting for remote to finish abort\n&quot;);
 (void) fflush(stdout);
 longjmp(recvabort, 1);
}

void
recvrequest(cmd, local, remote, lmode, printnames)
 char *cmd, *local, *remote, *lmode;
 int printnames;
{
 FILE *fout, *din = 0;
 int (*closefunc) __P((FILE *));
 sig_t oldintr, oldintp;
 int c, d, is_retr, tcrflag, bare_lfs = 0;
 static int bufsize;
 static char *buf;
 long bytes = 0, hashbytes = HASHBYTES;
 struct timeval start, stop;
 struct stat st;

 is_retr = strcmp(cmd, &quot;RETR&quot;) == 0;
 if (is_retr &amp;amp;&amp;amp; verbose &amp;amp;&amp;amp; printnames) {
  if (local &amp;amp;&amp;amp; *local != &#39;-&#39;)
   printf(&quot;local: %s &quot;, local);
  if (remote)
   printf(&quot;remote: %s\n&quot;, remote);
 }
 if (proxy &amp;amp;&amp;amp; is_retr) {
  proxtrans(cmd, local, remote);
  return;
 }
 closefunc = NULL;
 oldintr = NULL;
 oldintp = NULL;
 tcrflag = !crflag &amp;amp;&amp;amp; is_retr;
 if (setjmp(recvabort)) {
  while (cpend) {
   (void) getreply(0);
  }
  if (data &amp;gt;= 0) {
   (void) close(data);
   data = -1;
  }
  if (oldintr)
   (void) signal(SIGINT, oldintr);
  code = -1;
  return;
 }
 oldintr = signal(SIGINT, abortrecv);
 if (strcmp(local, &quot;-&quot;) &amp;amp;&amp;amp; *local != &#39;|&#39;) {
  if (access(local, 2) &amp;lt; 0) {
   char *dir = strrchr(local, &#39;/&#39;);

   if (errno != ENOENT &amp;amp;&amp;amp; errno != EACCES) {
    warn(&quot;local: %s&quot;, local);
    (void) signal(SIGINT, oldintr);
    code = -1;
    return;
   }
   if (dir != NULL)
    *dir = 0;
   d = access(dir ? local : &quot;.&quot;, 2);
   if (dir != NULL)
    *dir = &#39;/&#39;;
   if (d &amp;lt; 0) {
    warn(&quot;local: %s&quot;, local);
    (void) signal(SIGINT, oldintr);
    code = -1;
    return;
   }
   if (!runique &amp;amp;&amp;amp; errno == EACCES &amp;amp;&amp;amp;
       chmod(local, 0600) &amp;lt; 0) {
    warn(&quot;local: %s&quot;, local);
    (void) signal(SIGINT, oldintr);
    (void) signal(SIGINT, oldintr);
    code = -1;
    return;
   }
   if (runique &amp;amp;&amp;amp; errno == EACCES &amp;amp;&amp;amp;
      (local = gunique(local)) == NULL) {
    (void) signal(SIGINT, oldintr);
    code = -1;
    return;
   }
  }
  else if (runique &amp;amp;&amp;amp; (local = gunique(local)) == NULL) {
   (void) signal(SIGINT, oldintr);
   code = -1;
   return;
  }
 }
 if (!is_retr) {
  if (curtype != TYPE_A)
   changetype(TYPE_A, 0);
 } else if (curtype != type)
  changetype(type, 0);
 if (initconn()) {
  (void) signal(SIGINT, oldintr);
  code = -1;
  return;
 }
 if (setjmp(recvabort))
  goto abort;
 if (is_retr &amp;amp;&amp;amp; restart_point &amp;amp;&amp;amp;
     command(&quot;REST %ld&quot;, (long) restart_point) != CONTINUE)
  return;
 if (remote) {
  if (command(&quot;%s %s&quot;, cmd, remote) != PRELIM) {
   (void) signal(SIGINT, oldintr);
   return;
  }
 } else {
  if (command(&quot;%s&quot;, cmd) != PRELIM) {
   (void) signal(SIGINT, oldintr);
   return;
  }
 }
 din = dataconn(&quot;r&quot;);
 if (din == NULL)
  goto abort;
 if (strcmp(local, &quot;-&quot;) == 0)
  fout = stdout;
 else if (*local == &#39;|&#39;) {
  oldintp = signal(SIGPIPE, SIG_IGN);
  fout = popen(local + 1, &quot;w&quot;);
  if (fout == NULL) {
   warn(&quot;%s&quot;, local+1);
   goto abort;
  }
  closefunc = pclose;
 } else {
  fout = fopen(local, lmode);
  if (fout == NULL) {
   warn(&quot;local: %s&quot;, local);
   goto abort;
  }
  closefunc = fclose;
 }
 if (fstat(fileno(fout), &amp;amp;st) &amp;lt; 0 || st.st_blksize == 0)
  st.st_blksize = BUFSIZ;
 if (st.st_blksize &amp;gt; bufsize) {
  if (buf)
   (void) free(buf);
  buf = malloc((unsigned)st.st_blksize);
  if (buf == NULL) {
   warn(&quot;malloc&quot;);
   bufsize = 0;
   goto abort;
  }
  bufsize = st.st_blksize;
 }
 (void) gettimeofday(&amp;amp;start, (struct timezone *)0);
 switch (curtype) {

 case TYPE_I:
 case TYPE_L:
  if (restart_point &amp;amp;&amp;amp;
      lseek(fileno(fout), restart_point, SEEK_SET) &amp;lt; 0) {
   warn(&quot;local: %s&quot;, local);
   if (closefunc != NULL)
    (*closefunc)(fout);
   return;
  }
  errno = d = 0;
  while ((c = read(fileno(din), buf, bufsize)) &amp;gt; 0) {
   if ((d = write(fileno(fout), buf, c)) != c)
    break;
   bytes += c;
   if (hash) {
    while (bytes &amp;gt;= hashbytes) {
     (void) putchar(&#39;#&#39;);
     hashbytes += HASHBYTES;
    }
    (void) fflush(stdout);
   }
  }
  if (hash &amp;amp;&amp;amp; bytes &amp;gt; 0) {
   if (bytes &amp;lt; HASHBYTES)
    (void) putchar(&#39;#&#39;);
   (void) putchar(&#39;\n&#39;);
   (void) fflush(stdout);
  }
  if (c &amp;lt; 0) {
   if (errno != EPIPE)
    warn(&quot;netin&quot;);
   bytes = -1;
  }
  if (d &amp;lt; c) {
   if (d &amp;lt; 0)
    warn(&quot;local: %s&quot;, local);
   else
    warnx(&quot;%s: short write&quot;, local);
  }
  break;

 case TYPE_A:
  if (restart_point) {
   int i, n, ch;

   if (fseek(fout, 0L, SEEK_SET) &amp;lt; 0)
    goto done;
   n = restart_point;
   for (i = 0; i++ &amp;lt; n;) {
    if ((ch = getc(fout)) == EOF)
     goto done;
    if (ch == &#39;\n&#39;)
     i++;
   }
   if (fseek(fout, 0L, SEEK_CUR) &amp;lt; 0) {
done:
    warn(&quot;local: %s&quot;, local);
    if (closefunc != NULL)
     (*closefunc)(fout);
    return;
   }
  }
  while ((c = getc(din)) != EOF) {
   if (c == &#39;\n&#39;)
    bare_lfs++;
   while (c == &#39;\r&#39;) {
    while (hash &amp;amp;&amp;amp; (bytes &amp;gt;= hashbytes)) {
     (void) putchar(&#39;#&#39;);
     (void) fflush(stdout);
     hashbytes += HASHBYTES;
    }
    bytes++;
    if ((c = getc(din)) != &#39;\n&#39; || tcrflag) {
     if (ferror(fout))
      goto break2;
     (void) putc(&#39;\r&#39;, fout);
     if (c == &#39;\0&#39;) {
      bytes++;
      goto contin2;
     }
     if (c == EOF)
      goto contin2;
    }
   }
   (void) putc(c, fout);
   bytes++;
 contin2: ;
  }
break2:
  if (bare_lfs) {
   printf(&quot;WARNING! %d bare linefeeds received in ASCII mode\n&quot;, bare_lfs);
   printf(&quot;File may not have transferred correctly.\n&quot;);
  }
  if (hash) {
   if (bytes &amp;lt; hashbytes)
    (void) putchar(&#39;#&#39;);
   (void) putchar(&#39;\n&#39;);
   (void) fflush(stdout);
  }
  if (ferror(din)) {
   if (errno != EPIPE)
    warn(&quot;netin&quot;);
   bytes = -1;
  }
  if (ferror(fout))
   warn(&quot;local: %s&quot;, local);
  break;
 }
 if (closefunc != NULL)
  (*closefunc)(fout);
 (void) signal(SIGINT, oldintr);
 if (oldintp)
  (void) signal(SIGPIPE, oldintp);
 (void) fclose(din);
 (void) gettimeofday(&amp;amp;stop, (struct timezone *)0);
 (void) getreply(0);
 if (bytes &amp;gt; 0 &amp;amp;&amp;amp; is_retr)
  ptransfer(&quot;received&quot;, bytes, &amp;amp;start, &amp;amp;stop);
 return;
abort:

/* abort using RFC959 recommended IP,SYNC sequence  */

 if (oldintp)
  (void) signal(SIGPIPE, oldintr);
 (void) signal(SIGINT, SIG_IGN);
 if (!cpend) {
  code = -1;
  (void) signal(SIGINT, oldintr);
  return;
 }

 abort_remote(din);
 code = -1;
 if (data &amp;gt;= 0) {
  (void) close(data);
  data = -1;
 }
 if (closefunc != NULL &amp;amp;&amp;amp; fout != NULL)
  (*closefunc)(fout);
 if (din)
  (void) fclose(din);
 (void) gettimeofday(&amp;amp;stop, (struct timezone *)0);
 if (bytes &amp;gt; 0)
  ptransfer(&quot;received&quot;, bytes, &amp;amp;start, &amp;amp;stop);
 (void) signal(SIGINT, oldintr);
}

/*
 * Need to start a listen on the data channel before we send the command,
 * otherwise the server&#39;s connect may fail.
 */
int
initconn()
{
 char *p, *a;
 int result, len, tmpno = 0;
 int on = 1;
 int a0, a1, a2, a3, p0, p1;

 if (passivemode) {
  data = socket(AF_INET, SOCK_STREAM, 0);
  if (data &amp;lt; 0) {
   perror(&quot;ftp: socket&quot;);
   return(1);
  }
  if ((options &amp;amp; SO_DEBUG) &amp;amp;&amp;amp;
      setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&amp;amp;on,
          sizeof (on)) &amp;lt; 0)
   perror(&quot;ftp: setsockopt (ignored)&quot;);
  if (command(&quot;PASV&quot;) != COMPLETE) {
   printf(&quot;Passive mode refused.\n&quot;);
   goto bad;
  }

  /*
   * What we&#39;ve got at this point is a string of comma
   * separated one-byte unsigned integer values.
   * The first four are the an IP address. The fifth is
   * the MSB of the port number, the sixth is the LSB.
   * From that we&#39;ll prepare a sockaddr_in.
   */

  if (sscanf(pasv,&quot;%d,%d,%d,%d,%d,%d&quot;,
      &amp;amp;a0, &amp;amp;a1, &amp;amp;a2, &amp;amp;a3, &amp;amp;p0, &amp;amp;p1) != 6) {
   printf(&quot;Passive mode address scan failure. &quot;
          &quot;Shouldn&#39;t happen!\n&quot;);
   goto bad;
  }

  bzero(&amp;amp;data_addr, sizeof(data_addr));
  data_addr.sin_family = AF_INET;
  a = (char *)&amp;amp;data_addr.sin_addr.s_addr;
  a[0] = a0 &amp;amp; 0xff;
  a[1] = a1 &amp;amp; 0xff;
  a[2] = a2 &amp;amp; 0xff;
  a[3] = a3 &amp;amp; 0xff;
  p = (char *)&amp;amp;data_addr.sin_port;
  p[0] = p0 &amp;amp; 0xff;
  p[1] = p1 &amp;amp; 0xff;

  if (connect(data, (struct sockaddr *)&amp;amp;data_addr,
       sizeof(data_addr)) &amp;lt; 0) {
   perror(&quot;ftp: connect&quot;);
   goto bad;
  }
#ifdef IP_TOS
  on = IPTOS_THROUGHPUT;
  if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&amp;amp;on,
          sizeof(int)) &amp;lt; 0)
   perror(&quot;ftp: setsockopt TOS (ignored)&quot;);
#endif
  return(0);
 }

noport:
 data_addr = myctladdr;
 if (sendport)
  data_addr.sin_port = 0; /* let system pick one */ 
 if (data != -1)
  (void) close(data);
 data = socket(AF_INET, SOCK_STREAM, 0);
 if (data &amp;lt; 0) {
  warn(&quot;socket&quot;);
  if (tmpno)
   sendport = 1;
  return (1);
 }
 if (!sendport)
  if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&amp;amp;on, sizeof (on)) &amp;lt; 0) {
   warn(&quot;setsockopt (reuse address)&quot;);
   goto bad;
  }
 if (bind(data, (struct sockaddr *)&amp;amp;data_addr, sizeof (data_addr)) &amp;lt; 0) {
  warn(&quot;bind&quot;);
  goto bad;
 }
 if (options &amp;amp; SO_DEBUG &amp;amp;&amp;amp;
     setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&amp;amp;on, sizeof (on)) &amp;lt; 0)
  warn(&quot;setsockopt (ignored)&quot;);
 len = sizeof (data_addr);
 if (getsockname(data, (struct sockaddr *)&amp;amp;data_addr, &amp;amp;len) &amp;lt; 0) {
  warn(&quot;getsockname&quot;);
  goto bad;
 }
 if (listen(data, 1) &amp;lt; 0)
  warn(&quot;listen&quot;);
 if (sendport) {
  a = (char *)&amp;amp;data_addr.sin_addr;
  p = (char *)&amp;amp;data_addr.sin_port;
#define UC(b) (((int)b)&amp;amp;0xff)
  result =
      command(&quot;PORT %d,%d,%d,%d,%d,%d&quot;,
        UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
        UC(p[0]), UC(p[1]));
  if (result == ERROR &amp;amp;&amp;amp; sendport == -1) {
   sendport = 0;
   tmpno = 1;
   goto noport;
  }
  return (result != COMPLETE);
 }
 if (tmpno)
  sendport = 1;
#ifdef IP_TOS
 on = IPTOS_THROUGHPUT;
 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&amp;amp;on, sizeof(int)) &amp;lt; 0)
  warn(&quot;setsockopt TOS (ignored)&quot;);
#endif
 return (0);
bad:
 (void) close(data), data = -1;
 if (tmpno)
  sendport = 1;
 return (1);
}

FILE *
dataconn(lmode)
 char *lmode;
{
 struct sockaddr_in from;
 int s, fromlen = sizeof (from), tos;

 if (passivemode)
  return (fdopen(data, lmode));

 s = accept(data, (struct sockaddr *) &amp;amp;from, &amp;amp;fromlen);
 if (s &amp;lt; 0) {
  warn(&quot;accept&quot;);
  (void) close(data), data = -1;
  return (NULL);
 }
 (void) close(data);
 data = s;
#ifdef IP_TOS
 tos = IPTOS_THROUGHPUT;
 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&amp;amp;tos, sizeof(int)) &amp;lt; 0)
  warn(&quot;setsockopt TOS (ignored)&quot;);
#endif
 return (fdopen(data, lmode));
}

void
ptransfer(direction, bytes, t0, t1)
 char *direction;
 long bytes;
 struct timeval *t0, *t1;
{
 struct timeval td;
 float s;
 long bs;

 if (verbose) {
  tvsub(&amp;amp;td, t1, t0);
  s = td.tv_sec + (td.tv_usec / 1000000.);
#define nz(x) ((x) == 0 ? 1 : (x))
  bs = bytes / nz(s);
  printf(&quot;%ld bytes %s in %.3g seconds (%ld bytes/s)\n&quot;,
      bytes, direction, s, bs);
 }
}

/*
void
tvadd(tsum, t0)
 struct timeval *tsum, *t0;
{

 tsum-&amp;gt;tv_sec += t0-&amp;gt;tv_sec;
 tsum-&amp;gt;tv_usec += t0-&amp;gt;tv_usec;
 if (tsum-&amp;gt;tv_usec &amp;gt; 1000000)
  tsum-&amp;gt;tv_sec++, tsum-&amp;gt;tv_usec -= 1000000;
}
*/

void
tvsub(tdiff, t1, t0)
 struct timeval *tdiff, *t1, *t0;
{

 tdiff-&amp;gt;tv_sec = t1-&amp;gt;tv_sec - t0-&amp;gt;tv_sec;
 tdiff-&amp;gt;tv_usec = t1-&amp;gt;tv_usec - t0-&amp;gt;tv_usec;
 if (tdiff-&amp;gt;tv_usec &amp;lt; 0)
  tdiff-&amp;gt;tv_sec--, tdiff-&amp;gt;tv_usec += 1000000;
}

void
psabort()
{

 abrtflag++;
}

void
pswitch(flag)
 int flag;
{
 sig_t oldintr;
 static struct comvars {
  int connect;
  char name[MAXHOSTNAMELEN];
  struct sockaddr_in mctl;
  struct sockaddr_in hctl;
  FILE *in;
  FILE *out;
  int tpe;
  int curtpe;
  int cpnd;
  int sunqe;
  int runqe;
  int mcse;
  int ntflg;
  char nti[17];
  char nto[17];
  int mapflg;
  char mi[MAXPATHLEN];
  char mo[MAXPATHLEN];
 } proxstruct, tmpstruct;
 struct comvars *ip, *op;

 abrtflag = 0;
 oldintr = signal(SIGINT, psabort);
 if (flag) {
  if (proxy)
   return;
  ip = &amp;amp;tmpstruct;
  op = &amp;amp;proxstruct;
  proxy++;
 } else {
  if (!proxy)
   return;
  ip = &amp;amp;proxstruct;
  op = &amp;amp;tmpstruct;
  proxy = 0;
 }
 ip-&amp;gt;connect = connected;
 connected = op-&amp;gt;connect;
 if (hostname) {
  (void) strncpy(ip-&amp;gt;name, hostname, sizeof(ip-&amp;gt;name) - 1);
  ip-&amp;gt;name[strlen(ip-&amp;gt;name)] = &#39;\0&#39;;
 } else
  ip-&amp;gt;name[0] = 0;
 hostname = op-&amp;gt;name;
 ip-&amp;gt;hctl = hisctladdr;
 hisctladdr = op-&amp;gt;hctl;
 ip-&amp;gt;mctl = myctladdr;
 myctladdr = op-&amp;gt;mctl;
 ip-&amp;gt;in = cin;
 cin = op-&amp;gt;in;
 ip-&amp;gt;out = cout;
 cout = op-&amp;gt;out;
 ip-&amp;gt;tpe = type;
 type = op-&amp;gt;tpe;
 ip-&amp;gt;curtpe = curtype;
 curtype = op-&amp;gt;curtpe;
 ip-&amp;gt;cpnd = cpend;
 cpend = op-&amp;gt;cpnd;
 ip-&amp;gt;sunqe = sunique;
 sunique = op-&amp;gt;sunqe;
 ip-&amp;gt;runqe = runique;
 runique = op-&amp;gt;runqe;
 ip-&amp;gt;mcse = mcase;
 mcase = op-&amp;gt;mcse;
 ip-&amp;gt;ntflg = ntflag;
 ntflag = op-&amp;gt;ntflg;
 (void) strncpy(ip-&amp;gt;nti, ntin, 16);
 (ip-&amp;gt;nti)[strlen(ip-&amp;gt;nti)] = &#39;\0&#39;;
 (void) strcpy(ntin, op-&amp;gt;nti);
 (void) strncpy(ip-&amp;gt;nto, ntout, 16);
 (ip-&amp;gt;nto)[strlen(ip-&amp;gt;nto)] = &#39;\0&#39;;
 (void) strcpy(ntout, op-&amp;gt;nto);
 ip-&amp;gt;mapflg = mapflag;
 mapflag = op-&amp;gt;mapflg;
 (void) strncpy(ip-&amp;gt;mi, mapin, MAXPATHLEN - 1);
 (ip-&amp;gt;mi)[strlen(ip-&amp;gt;mi)] = &#39;\0&#39;;
 (void) strcpy(mapin, op-&amp;gt;mi);
 (void) strncpy(ip-&amp;gt;mo, mapout, MAXPATHLEN - 1);
 (ip-&amp;gt;mo)[strlen(ip-&amp;gt;mo)] = &#39;\0&#39;;
 (void) strcpy(mapout, op-&amp;gt;mo);
 (void) signal(SIGINT, oldintr);
 if (abrtflag) {
  abrtflag = 0;
  (*oldintr)(SIGINT);
 }
}

void
abortpt()
{

 printf(&quot;\n&quot;);
 (void) fflush(stdout);
 ptabflg++;
 mflag = 0;
 abrtflag = 0;
 longjmp(ptabort, 1);
}

void
proxtrans(cmd, local, remote)
 char *cmd, *local, *remote;
{
 sig_t oldintr;
 int secndflag = 0, prox_type, nfnd;
 char *cmd2;
 struct fd_set mask;

 if (strcmp(cmd, &quot;RETR&quot;))
  cmd2 = &quot;RETR&quot;;
 else
  cmd2 = runique ? &quot;STOU&quot; : &quot;STOR&quot;;
 if ((prox_type = type) == 0) {
  if (unix_server &amp;amp;&amp;amp; unix_proxy)
   prox_type = TYPE_I;
  else
   prox_type = TYPE_A;
 }
 if (curtype != prox_type)
  changetype(prox_type, 1);
 if (command(&quot;PASV&quot;) != COMPLETE) {
  printf(&quot;proxy server does not support third party transfers.\n&quot;);
  return;
 }
 pswitch(0);
 if (!connected) {
  printf(&quot;No primary connection\n&quot;);
  pswitch(1);
  code = -1;
  return;
 }
 if (curtype != prox_type)
  changetype(prox_type, 1);
 if (command(&quot;PORT %s&quot;, pasv) != COMPLETE) {
  pswitch(1);
  return;
 }
 if (setjmp(ptabort))
  goto abort;
 oldintr = signal(SIGINT, abortpt);
 if (command(&quot;%s %s&quot;, cmd, remote) != PRELIM) {
  (void) signal(SIGINT, oldintr);
  pswitch(1);
  return;
 }
 sleep(2);
 pswitch(1);
 secndflag++;
 if (command(&quot;%s %s&quot;, cmd2, local) != PRELIM)
  goto abort;
 ptflag++;
 (void) getreply(0);
 pswitch(0);
 (void) getreply(0);
 (void) signal(SIGINT, oldintr);
 pswitch(1);
 ptflag = 0;
 printf(&quot;local: %s remote: %s\n&quot;, local, remote);
 return;
abort:
 (void) signal(SIGINT, SIG_IGN);
 ptflag = 0;
 if (strcmp(cmd, &quot;RETR&quot;) &amp;amp;&amp;amp; !proxy)
  pswitch(1);
 else if (!strcmp(cmd, &quot;RETR&quot;) &amp;amp;&amp;amp; proxy)
  pswitch(0);
 if (!cpend &amp;amp;&amp;amp; !secndflag) {  /* only here if cmd = &quot;STOR&quot; (proxy=1) */
  if (command(&quot;%s %s&quot;, cmd2, local) != PRELIM) {
   pswitch(0);
   if (cpend)
    abort_remote((FILE *) NULL);
  }
  pswitch(1);
  if (ptabflg)
   code = -1;
  (void) signal(SIGINT, oldintr);
  return;
 }
 if (cpend)
  abort_remote((FILE *) NULL);
 pswitch(!proxy);
 if (!cpend &amp;amp;&amp;amp; !secndflag) {  /* only if cmd = &quot;RETR&quot; (proxy=1) */
  if (command(&quot;%s %s&quot;, cmd2, local) != PRELIM) {
   pswitch(0);
   if (cpend)
    abort_remote((FILE *) NULL);
   pswitch(1);
   if (ptabflg)
    code = -1;
   (void) signal(SIGINT, oldintr);
   return;
  }
 }
 if (cpend)
  abort_remote((FILE *) NULL);
 pswitch(!proxy);
 if (cpend) {
  FD_ZERO(&amp;amp;mask);
  FD_SET(fileno(cin), &amp;amp;mask);
  if ((nfnd = empty(&amp;amp;mask, 10)) &amp;lt;= 0) {
   if (nfnd &amp;lt; 0) {
    warn(&quot;abort&quot;);
   }
   if (ptabflg)
    code = -1;
   lostpeer();
  }
  (void) getreply(0);
  (void) getreply(0);
 }
 if (proxy)
  pswitch(0);
 pswitch(1);
 if (ptabflg)
  code = -1;
 (void) signal(SIGINT, oldintr);
}

void
reset(argc, argv)
 int argc;
 char *argv[];
{
 struct fd_set mask;
 int nfnd = 1;

 FD_ZERO(&amp;amp;mask);
 while (nfnd &amp;gt; 0) {
  FD_SET(fileno(cin), &amp;amp;mask);
  if ((nfnd = empty(&amp;amp;mask,0)) &amp;lt; 0) {
   warn(&quot;reset&quot;);
   code = -1;
   lostpeer();
  }
  else if (nfnd) {
   (void) getreply(0);
  }
 }
}

char *
gunique(local)
 char *local;
{
 static char new[MAXPATHLEN];
 char *cp = strrchr(local, &#39;/&#39;);
 int d, count=0;
 char ext = &#39;1&#39;;

 if (cp)
  *cp = &#39;\0&#39;;
 d = access(cp ? local : &quot;.&quot;, 2);
 if (cp)
  *cp = &#39;/&#39;;
 if (d &amp;lt; 0) {
  warn(&quot;local: %s&quot;, local);
  return ((char *) 0);
 }
 (void) strcpy(new, local);
 cp = new + strlen(new);
 *cp++ = &#39;.&#39;;
 while (!d) {
  if (++count == 100) {
   printf(&quot;runique: can&#39;t find unique file name.\n&quot;);
   return ((char *) 0);
  }
  *cp++ = ext;
  *cp = &#39;\0&#39;;
  if (ext == &#39;9&#39;)
   ext = &#39;0&#39;;
  else
   ext++;
  if ((d = access(new, 0)) &amp;lt; 0)
   break;
  if (ext != &#39;0&#39;)
   cp--;
  else if (*(cp - 2) == &#39;.&#39;)
   *(cp - 1) = &#39;1&#39;;
  else {
   *(cp - 2) = *(cp - 2) + 1;
   cp--;
  }
 }
 return (new);
}

void
abort_remote(din)
 FILE *din;
{
 char buf[BUFSIZ];
 int nfnd;
 struct fd_set mask;

 /*
  * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
  * after urgent byte rather than before as is protocol now
  */
 sprintf(buf, &quot;%c%c%c&quot;, IAC, IP, IAC);
 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
  warn(&quot;abort&quot;);
 fprintf(cout,&quot;%cABOR\r\n&quot;, DM);
 (void) fflush(cout);
 FD_ZERO(&amp;amp;mask);
 FD_SET(fileno(cin), &amp;amp;mask);
 if (din) { 
  FD_SET(fileno(din), &amp;amp;mask);
 }
 if ((nfnd = empty(&amp;amp;mask, 10)) &amp;lt;= 0) {
  if (nfnd &amp;lt; 0) {
   warn(&quot;abort&quot;);
  }
  if (ptabflg)
   code = -1;
  lostpeer();
 }
 if (din &amp;amp;&amp;amp; FD_ISSET(fileno(din), &amp;amp;mask)) {
  while (read(fileno(din), buf, BUFSIZ) &amp;gt; 0)
   /* LOOP */;
 }
 if (getreply(0) == ERROR &amp;amp;&amp;amp; code == 552) {
  /* 552 needed for nic style abort */
  (void) getreply(0);
 }
 (void) getreply(0);
}

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

&lt;/div&gt;</description><link>http://simplestcodings.blogspot.com/2012/09/ftp-implementation-in-c.html</link><author>noreply@blogger.com (Varun)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBF0T31WXW0AKpxMaQfg0FkDLnjBpQOCNUpKuIK_4hswYNROrZUDb6zhHsLFssekSVDvfkTaaJeYM5xHk4trVDG9nhE8qCBt4GQbaPyr2c2bcTPW8lZ8mYsKgX1sfpLQYJr40-IhYowJR6nUt9-95ahynhYaPN3RcxD3bEhKgXZZralcurHfUzb1yYmYY/s72-c/ftp.jpeg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-647300920750858334</guid><pubDate>Thu, 28 Jun 2012 18:42:00 +0000</pubDate><atom:updated>2018-05-01T09:07:42.991+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">SSC 2018</category><category domain="http://www.blogger.com/atom/ns#">SSC Adit card 2018</category><category domain="http://www.blogger.com/atom/ns#">SSC Combined Graduate Level Examination 2012 Admit Card</category><category domain="http://www.blogger.com/atom/ns#">SSC Exam 2018</category><title>SSC Combined Graduate Level Examination 2012 Admit Card</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
This would be helpful to those candidates who are having trouble finding their Admit Card for&amp;nbsp; SSC Combined Graduate Level Examination 2012.&lt;br /&gt;
&lt;br /&gt;
Please visit your local(state) SSC website and download the list of eligible candidates from there.&lt;br /&gt;
You can find your Roll No. Enlisted there and then it could be used to retrieve the Admit Card from the same site.&lt;br /&gt;
&lt;br /&gt;
For Example, In Karntaka roll no. can be found using following steps:&lt;br /&gt;
&lt;br /&gt;
1. Visit &lt;a href=&quot;http://www.ssckkr.kar.nic.in/&quot;&gt;http://www.ssckkr.kar.nic.in/&lt;/a&gt;&lt;br /&gt;
2. On the homepage find the link&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;&lt;a class=&quot;style11&quot; href=&quot;http://www.ssckkr.kar.nic.in/PROVISIONALLY_ACCEPTcgl12.pdf&quot;&gt;1.&#39;&quot;Click here to see the Roll NO. of the list of the provisionally eligible candidates for Combined Graduate Level Exam, 2012&quot;.&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;3. Then try to search your name in the list.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;4. Then visit the link &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;http://www.ssckkr.kar.nic.in/sschallticket/CGLE2012/result.asp&quot;&gt;1.Download Duplicate Admission Certificates for Combined Graduate Level EXAMINATION 2012 scheduled to be held on 01.07.2012&lt;/a&gt;&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;5. Enter your roll no. there and download your admit card.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;This steps is valid for Karnataka State Candidates, It might be valid for other states too but somebody will have to check.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;These are sites for various regions&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://sscnr.net.in/newlook/cgladmintcard2012/additional_cisf_cisf_2012.aspx&quot; target=&quot;_blank&quot;&gt;SSC Northern Region Delhi (SSCNR)&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://www.sscnwr.org/cgl_tier_1_2012.php&quot; target=&quot;_blank&quot;&gt;SSC North Western Region Chandigarh&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://www.ssc-cr.org/cgl_tier_1_2012.php&quot; target=&quot;_blank&quot;&gt;SSC Central Region (SSCCR) Allahabad&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://www.sscer.org/MATTER/DOWNLOAD_AC.html&quot; target=&quot;_blank&quot;&gt;SSC Eastern Region Kolkata (SSCER)&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://www.sscner.org.in/CGL2012/admit.asp&quot; target=&quot;_blank&quot;&gt;SSC North Eastern Region (SSCNER) Guwahati&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://sscmpr.org/index.php?Page=cgl_tier_1_2012&quot; target=&quot;_blank&quot;&gt;SSC Madhya Pradesh Region (SSCMPR)&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;SSC Southern Region (SSCSR)&lt;/i&gt;&lt;/b&gt; &lt;b&gt;&lt;a href=&quot;http://www.sscsr.gov.in/CGL-2012-FN.htm&quot; target=&quot;_blank&quot;&gt;(Forenoon)&lt;/a&gt;&lt;/b&gt;&amp;nbsp;|| &lt;a href=&quot;http://www.sscsr.gov.in/CGL-2012-AN.htm&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;(Afternoon)&lt;/b&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://sscwr.net/index.php?Page=cgl_tier_1_2012&quot; target=&quot;_blank&quot;&gt;SSC Western Region (SSCWR) Maharashtra&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&lt;a href=&quot;http://www.ssckkr.kar.nic.in/sschallticket/CGLE2012/result.asp&quot; target=&quot;_blank&quot;&gt;SSC Kerala, Karnataka Region (SSCKKR)&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;


&lt;b&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;&quot;&gt;
&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;b style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Whereever you have filled the centre of examination , that will be you region &lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style8&quot;&gt;&lt;span class=&quot;style9&quot;&gt;&lt;span class=&quot;style10&quot;&gt;&lt;span class=&quot;style13&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
</description><link>http://simplestcodings.blogspot.com/2012/06/ssc-combined-graduate-level-examination.html</link><author>noreply@blogger.com (Varun)</author><thr:total>26</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-5976287721405048255</guid><pubDate>Thu, 23 Feb 2012 13:10:00 +0000</pubDate><atom:updated>2023-12-21T00:41:52.437+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">C++</category><category domain="http://www.blogger.com/atom/ns#">Libconfig</category><category domain="http://www.blogger.com/atom/ns#">Read configuration files</category><title>libconfig to read configuration files in C/C++</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
There are so many open-source libraries already available for parsing configuration files in c/c++ , but still we there are some which make their place up than rest of the others. One such library is &lt;a href=&quot;http://www.hyperrealm.com/libconfig/&quot; target=&quot;_blank&quot;&gt;libconfig&amp;nbsp;&lt;/a&gt;. The reason being its simplicity and much lesser memory footprint. Most of the library for configuration files are XML based , but this library is text based and the structure of the configuration files is pretty simple.&lt;br /&gt;
e.g. In its simplest form a configuration file can look like :&lt;br /&gt;
&lt;span style=&quot;text-align: -webkit-auto; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;/div&gt;
&lt;pre style=&quot;white-space: pre-wrap; word-wrap: break-word;&quot;&gt;port = 5000;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
It can provide even more simpler configuration file for much complex data group. For example :&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;text-align: -webkit-auto; white-space: pre-wrap; word-wrap: break-word;&quot;&gt;books = ( &quot;inventory&quot;,
          { title  = &quot;Treasure Island&quot;;
            author = &quot;Robert Louis Stevenson&quot;;
            price  = 29.99;
            qty    = 5; },
          { title  = &quot;Snow Crash&quot;;
            author = &quot;Neal Stephenson&quot;;
            price  = 9.99;
            qty    = 8; },&amp;nbsp;&lt;/pre&gt;
&lt;span style=&quot;text-align: -webkit-auto; white-space: pre-wrap;&quot;&gt;          { } );&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here there is a set of data for the inventory of books with multiple fields for each book.&lt;br /&gt;
&lt;br /&gt;
One of the most important feature of this library is that it supports a&lt;span style=&quot;text-align: -webkit-auto;&quot;&gt;&amp;nbsp;fully re-entrant parser which means that different configurations can be parsed in concurrent threads at the same time. Moreover the APIs are available for both C and C++ languages and there are hooks provided in the library to facilitate its use in other programming languages too.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;text-align: -webkit-auto;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;text-align: -webkit-auto;&quot;&gt;The detailed documentation of this library can be found at&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://www.hyperrealm.com/libconfig/libconfig_manual.html&quot;&gt;Libconfig Manual&lt;/a&gt;. It supports multiple platforms such as Windows, Linux , Mac OS X and Solaris (POSIX compliant platforms).&lt;br /&gt;
&lt;br /&gt;
To use it in a C/C++ program one just needs to add a single preprocessor directive&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;smallexample&quot; style=&quot;font-size: smaller; text-align: -webkit-auto;&quot;&gt;&lt;/pre&gt;
&lt;pre class=&quot;smallexample&quot; style=&quot;text-align: -webkit-auto;&quot;&gt;#include &amp;lt;libconfig.h&amp;gt;      /*For C*/  &lt;/pre&gt;
&lt;pre class=&quot;smallexample&quot; style=&quot;text-align: -webkit-auto;&quot;&gt;&lt;pre class=&quot;smallexample&quot;&gt;#include &amp;lt;libconfig.h++&amp;gt;    /*For C++*/&lt;/pre&gt;
&lt;/pre&gt;
&lt;pre class=&quot;smallexample&quot; style=&quot;text-align: -webkit-auto;&quot;&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Times, &#39;Times New Roman&#39;, serif;&quot;&gt;For dynamic linking -lconfig/-lconfig++ must be used for C/C++ respectively. Otherwise the libraries can be statically linked using the static linking option during the compilation.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Times, &#39;Times New Roman&#39;, serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;e.g. ( -static $(LIBPTHREAD_INSTALL_DIR)/libpthread.a)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Times, &#39;Times New Roman&#39;, serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Times, &#39;Times New Roman&#39;, serif;&quot;&gt;&lt;b&gt;Issues as per the libconfig &lt;a href=&quot;http://www.hyperrealm.com/libconfig/libconfig_manual.html&quot;&gt;website&lt;/a&gt;:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Times, &#39;Times New Roman&#39;, serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;/div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;i&gt;Libconfig&lt;/i&gt;&amp;nbsp;is fully&amp;nbsp;&lt;dfn&gt;reentrant&lt;/dfn&gt;; the functions in the library do not make use of global variables and do not maintain state between successive calls. Therefore two independent configurations may be safely manipulated concurrently by two distinct threads.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Libconfig&lt;/i&gt;&amp;nbsp;is not&amp;nbsp;&lt;dfn&gt;thread-safe&lt;/dfn&gt;. The library is not aware of the presence of threads and knows nothing about the host system&#39;s threading model. Therefore, if an instance of a configuration is to be accessed from multiple threads, it must be suitably protected by synchronization mechanisms like read-write locks or mutexes; the standard rules for safe multithreaded access to shared data must be observed.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Libconfig&lt;/i&gt;&amp;nbsp;is not&amp;nbsp;&lt;dfn&gt;async-safe&lt;/dfn&gt;. Calls should not be made into the library from signal handlers, because some of the C library routines that it uses may not be async-safe.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Libconfig&lt;/i&gt;&amp;nbsp;is not guaranteed to be&amp;nbsp;&lt;dfn&gt;cancel-safe&lt;/dfn&gt;. Since it is not aware of the host system&#39;s threading model, the library does not contain any thread cancellation points. In most cases this will not be an issue for multithreaded programs. However, be aware that some of the routines in the library (namely those that read/write configurations from/to files or streams) perform I/O using C library routines which may potentially block; whether or not these C library routines are cancel-safe depends on the host system.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
We will provide a simple example of how to read from a configuration file using libconfig:&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;
/*config.c*/
/*
To compile : gcc -o config config.c -lconfig
To run     : ./config
*/
#include &lt;stdio.h&gt;
#include &lt;libconfig.h&gt;

int main()
{
    config_t cfg;               /*Returns all parameters in this structure */
    config_setting_t *setting;
    const char *str1, *str2;
    int tmp;

    char *config_file_name = &quot;config.txt&quot;;

    /*Initialization */
    config_init(&amp;amp;cfg);

    /* Read the file. If there is an error, report it and exit. */
    if (!config_read_file(&amp;amp;cfg, config_file_name))
    {
        printf(&quot;\n%s:%d - %s&quot;, config_error_file(&amp;amp;cfg), config_error_line(&amp;amp;cfg), config_error_text(&amp;amp;cfg));
        config_destroy(&amp;amp;cfg);
        return -1;
    }

    /* Get the configuration file name. */
    if (config_lookup_string(&amp;amp;cfg, &quot;filename&quot;, &amp;amp;str1))
        printf(&quot;\nFile Type: %s&quot;, str1);
    else
        printf(&quot;\nNo &#39;filename&#39; setting in configuration file.&quot;);

    /*Read the parameter group*/
    setting = config_lookup(&amp;amp;cfg, &quot;params&quot;);
    if (setting != NULL)
    {
        /*Read the string*/
        if (config_setting_lookup_string(setting, &quot;param1&quot;, &amp;amp;str2))
        {
            printf(&quot;\nParam1: %s&quot;, str2);
        }
        else
            printf(&quot;\nNo &#39;param1&#39; setting in configuration file.&quot;);

        /*Read the integer*/
        if (config_setting_lookup_int(setting, &quot;param2&quot;, &amp;amp;tmp))
        {
            printf(&quot;\nParam2: %d&quot;, tmp);
        }
        else
            printf(&quot;\nNo &#39;param2&#39; setting in configuration file.&quot;);

        printf(&quot;\n&quot;);
    }

    config_destroy(&amp;amp;cfg);
}


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

And corresponding configuration file : 

&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; &lt;code class=&quot;language-cpp&quot;&gt;
//config.txt
// Basic Information:
filename = &quot;Sample Configuration File&quot;;

// Parameters
params = 
{
param1 = &quot;Hello&quot;;

param2 = 1234;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
 SyntaxHighlighter.highlight();
&lt;/script&gt;</description><link>http://simplestcodings.blogspot.com/2012/02/libconfig-to-read-configuration-files.html</link><author>noreply@blogger.com (Varun)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-3536660542629144989</guid><pubDate>Tue, 14 Feb 2012 06:10:00 +0000</pubDate><atom:updated>2012-02-14T11:40:41.519+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Generic</category><title>Articles needed !</title><description>Due to lack of time, I am not being able to write more posts. If anyone feels that they have some good topic to write about, please write to me and after moderation i can publish it on the blog.</description><link>http://simplestcodings.blogspot.com/2012/02/articles-needed.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3459284654925679524.post-271216525921643791</guid><pubDate>Sun, 28 Nov 2010 10:35:00 +0000</pubDate><atom:updated>2013-10-01T18:23:46.057+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Generic</category><title>Serialization using Google protobuf</title><description>Protocol buffers (that&#39;s what protobuf means :)) are a means to serialize structured data. Now you may be wondering what this &#39;serialize&#39; means. &lt;br /&gt;
&lt;br /&gt;
To be brief : Serialization is a process of packing the data structures or objects into sequence of bits so that they can be stored in a file or a buffer and transmitted across the network and then can be retrieved on the same or other system environment. Examples include XML, JSON, ASN.1, YAML, ProtoBuf etc.&lt;br /&gt;
&lt;br /&gt;
Advantages :&lt;br /&gt;
1. Persistent object creation&lt;br /&gt;
2. RPC enabling&lt;br /&gt;
3. Are simple&lt;br /&gt;
4. Save space on disk&lt;br /&gt;
5. Very fast &lt;br /&gt;
6. Platform and language independent&lt;br /&gt;
&lt;br /&gt;
ProtoBuf is available freely from Google (&lt;a 
href=&quot;http://code.google.com/p/protobuf/&quot;&gt;http://code.google.com/p/protobuf/&lt;/a&gt;). Procedure of installation and compilation is present there.&lt;br /&gt;
&lt;br /&gt;
Everything that needs to be serialized is put in a protocol buffer message (a .proto file). This file tells the compiler how the data is to be serialized.&lt;br /&gt;
&lt;br /&gt;
For each field there are setter and getter functions fieldname() is a getter and set_fieldname() is a setter. Remember to use these functions as the exact way it is told here. &lt;br /&gt;
The tutorials for the different languages can be found &lt;a href=&quot;http://code.google.com/apis/protocolbuffers/docs/tutorials.html&quot;&gt;here&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I present a small simple example to use the protobuf library and there is much more than that one can do with the protobuf :)&lt;br /&gt;
&lt;br /&gt;
To make and run the example (on linux) follow the steps :&lt;br /&gt;
1. Download the tar.gz package from &lt;a href=&quot;http://code.google.com/p/protobuf/downloads/list&quot;&gt;here&lt;/a&gt;&lt;br /&gt;
2. Login as root&lt;br /&gt;
3. Untar it in your home directory (say user1)&lt;br /&gt;
4. Go inside the protobuf directory and run ./configure&lt;br /&gt;
5. Add the path /usr/local/lib to the environment variable LD_LIBRARY_PATH&lt;br /&gt;
6. Then run :&lt;br /&gt;
make&lt;br /&gt;
make install&lt;br /&gt;
7. You are now ready to use the library.&lt;br /&gt;
8. To use protobuf you will need following files (I am explaining for c++ only):&lt;br /&gt;
.cc file&lt;br /&gt;
.proto file&lt;br /&gt;
Makefile&lt;br /&gt;
Rest of the files are generated on the fly.&lt;br /&gt;
&lt;br /&gt;
Here is an example of a Vehicle parts which contains three fields , two mandatory and one optional.&lt;br /&gt;
-Part ID (mandatory)&lt;br /&gt;
-Part Name (mandatory)&lt;br /&gt;
-Vendor (optional)&lt;br /&gt;
&lt;br /&gt;
We write this in .proto file&lt;br /&gt;
&lt;br /&gt;
&lt;!--pre name=&quot;code&quot; class=&quot;cpp&quot;--&gt;
&lt;pre class=brush:cpp&gt;
//partbook.proto
package tutorial;

message Part {
  required string name = 1;
  required int32 partid = 2;        // Unique ID number for this part
  optional string vendor = 3;

}

message PartDetails {
  repeated Part part = 1;
}

&lt;/pre&gt;&lt;br /&gt;
Then we write a c++ program to use the library and .proto to add serialized data to the data file.&lt;br /&gt;
&lt;!--pre name=&quot;code&quot; class=&quot;cpp&quot;--&gt;
&lt;pre class=brush:cpp&gt;/*add_part.cc*/
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;fstream&amp;gt;
#include &amp;lt;string&amp;gt;
#include &quot;partbook.pb.h&quot;
using namespace std;

/* This function fills in a Part message based on user input.*/
void PromptForPart(tutorial::Part* part) {
  cout &amp;lt;&amp;lt; &quot;Enter part ID number: &quot;;
  int partid;
  cin &amp;gt;&amp;gt; partid;
  part-&amp;gt;set_partid(partid);
  cin.ignore(256, &#39;\n&#39;);

  cout &amp;lt;&amp;lt; &quot;Enter part name: &quot;;
  getline(cin, *part-&amp;gt;mutable_name());

  cout &amp;lt;&amp;lt; &quot;Enter vendor name (blank for none): &quot;;
  string vendor;
  getline(cin, vendor);
  if (!vendor.empty()) {
    part-&amp;gt;set_vendor(vendor);
  }

}

/* Main function:  Reads the entire part list from a file,
 * adds one part based on user input, then writes it back out to the same
 *   file.
 */
int main(int argc, char* argv[]) {
  /* Verify that the version of the library that we linked against is
   * compatible with the version of the headers we compiled against.
   */
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2) {
    cerr &amp;lt;&amp;lt; &quot;Usage:  &quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &quot; PART_BOOK_FILE&quot; &amp;lt;&amp;lt; endl;
    return -1;
  }

  tutorial::PartDetails part_book;

  {
    // Read the existing part book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!input) {
      cout &amp;lt;&amp;lt; argv[1] &amp;lt;&amp;lt; &quot;: File not found.  Creating a new file.&quot; &amp;lt;&amp;lt; endl;
    } else if (!part_book.ParseFromIstream(&amp;input)) {
      cerr &amp;lt;&amp;lt; &quot;Failed to parse part book.&quot; &amp;lt;&amp;lt; endl;
      return -1;
    }
  }

  // Add a new part.
  PromptForPart(part_book.add_part());

  {
    // Write the new part book back to disk.
    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
    if (!part_book.SerializeToOstream(&amp;output)) {
      cerr &amp;lt;&amp;lt; &quot;Failed to write part book.&quot; &amp;lt;&amp;lt; endl;
      return -1;
    }
  }

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

&lt;/pre&gt;&lt;br /&gt;
Then we write a c++ program to use the library and .proto to serialize the data.&lt;br /&gt;
&lt;!--pre name=&quot;code&quot; class=&quot;cpp&quot;--&gt;
&lt;pre class=brush:cpp&gt;
/*list_parts.cc*/
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;fstream&amp;gt;
#include &amp;lt;string&amp;gt;
#include &quot;partbook.pb.h&quot;
using namespace std;

// Iterates though all parts in the PartDetails and prints info about them.
void ListParts(const tutorial::PartDetails&amp; part_book) {
  for (int i = 0; i &amp;lt; part_book.part_size(); i++) {
    const tutorial::Part&amp; part = part_book.part(i);

    cout &amp;lt;&amp;lt; &quot;Part ID: &quot; &amp;lt;&amp;lt; part.partid() &amp;lt;&amp;lt; endl;
    cout &amp;lt;&amp;lt; &quot;  Name: &quot; &amp;lt;&amp;lt; part.name() &amp;lt;&amp;lt; endl;
    if (part.has_vendor()) {
      cout &amp;lt;&amp;lt; &quot;  Vendor: &quot; &amp;lt;&amp;lt; part.vendor() &amp;lt;&amp;lt; endl;
    }

  }
}

// Main function:  Reads the entire part book from a file and prints all
//   the information inside.
int main(int argc, char* argv[]) {
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2) {
    cerr &amp;lt;&amp;lt; &quot;Usage:  &quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &quot; PART_BOOK_FILE&quot; &amp;lt;&amp;lt; endl;
    return -1;
  }

  tutorial::PartDetails part_book;

  {
    // Read the existing data file.
    fstream input(argv[1], ios::in | ios::binary);
    if (!part_book.ParseFromIstream(&amp;input)) {
      cerr &amp;lt;&amp;lt; &quot;Failed to parse part book.&quot; &amp;lt;&amp;lt; endl;
      return -1;
    }
  }

  ListParts(part_book);

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;!--pre name=&quot;code&quot; class=&quot;cpp&quot;--&gt;
&lt;pre class=brush:cpp&gt;
#Makefile
#This creates executables for python cpp and java , to create only one language use #&#39;make cpp&#39; or &#39;make python&#39; or &#39;make java&#39;

.PHONY: all cpp java python clean

all: cpp java python

cpp:    add_part_cpp    list_parts_cpp
java:   add_part_java   list_parts_java
python: add_part_python list_parts_python

clean:
 rm -f add_part_cpp list_parts_cpp add_part_java list_parts_java add_part_python list_parts_python
 rm -f javac_middleman AddPart*.class ListParts*.class com/example/tutorial/*.class
 rm -f protoc_middleman partbook.pb.cc partbook.pb.h partbook.pb2.py com/example/tutorial/PartBookProtos.java
 rm -f *.pyc
 rmdir com/example/tutorial 2&amp;gt;/dev/null || true
 rmdir com/example 2&amp;gt;/dev/null || true
 rmdir com 2&amp;gt;/dev/null || true

protoc_middleman: partbook.proto
 protoc --cpp_out=. --java_out=. --python_out=. partbook.proto
 @touch protoc_middleman

add_part_cpp: add_part.cc protoc_middleman
 pkg-config --cflags protobuf  # fails if protobuf is not installed
 c++ add_part.cc partbook.pb.cc -o add_part_cpp `pkg-config --cflags --libs protobuf`

list_parts_cpp: list_parts.cc protoc_middleman
 pkg-config --cflags protobuf  # fails if protobuf is not installed
 c++ list_parts.cc partbook.pb.cc -o list_parts_cpp `pkg-config --cflags --libs protobuf`

javac_middleman: AddPart.java ListParts.java protoc_middleman
 javac AddPart.java ListParts.java com/example/tutorial/PartBookProtos.java
 @touch javac_middleman

add_part_java: javac_middleman
 @echo &quot;Writing shortcut script add_part_java...&quot;
 @echo &#39;#! /bin/sh&#39; &amp;gt; add_part_java
 @echo &#39;java -classpath .:$$CLASSPATH AddPart &quot;$$@&quot;&#39; &amp;gt;&amp;gt; add_part_java
 @chmod +x add_part_java

list_parts_java: javac_middleman
 @echo &quot;Writing shortcut script list_parts_java...&quot;
 @echo &#39;#! /bin/sh&#39; &amp;gt; list_parts_java
 @echo &#39;java -classpath .:$$CLASSPATH ListParts &quot;$$@&quot;&#39; &amp;gt;&amp;gt; list_parts_java
 @chmod +x list_parts_java

add_part_python: add_part.py protoc_middleman
 @echo &quot;Writing shortcut script add_part_python...&quot;
 @echo &#39;#! /bin/sh&#39; &amp;gt; add_part_python
 @echo &#39;./add_part.py &quot;$$@&quot;&#39; &amp;gt;&amp;gt; add_part_python
 @chmod +x add_part_python

list_parts_python: list_parts.py protoc_middleman
 @echo &quot;Writing shortcut script list_parts_python...&quot;
 @echo &#39;#! /bin/sh&#39; &amp;gt; list_parts_python
 @echo &#39;./list_parts.py &quot;$$@&quot;&#39; &amp;gt;&amp;gt; list_parts_python
 @chmod +x list_parts_python

&lt;/pre&gt;&lt;br /&gt;
Save all these files under &amp;lt;proto-installation-path&amp;gt;/examples/ and run make&lt;br /&gt;
&lt;br /&gt;
To run the example&lt;br /&gt;
./add_part_cpp &amp;lt;data-filename&amp;gt;&lt;br /&gt;
./list_parts_cpp &amp;lt;data-filename&amp;gt;

&lt;script type=&quot;text/javascript&quot;&gt;
 SyntaxHighlighter.highlight();
&lt;/script&gt;</description><link>http://simplestcodings.blogspot.com/2010/11/serialization-using-google-protobuf.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>2</thr:total></item></channel></rss>