<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Blog</title>
  <subtitle>Bryon Tjanaka&#39;s blog.</subtitle>
  <link rel="self" type="application/atom+xml"
        href="https://btjanaka.net/feed.xml" />
  <link rel="alternate" type="text/html" href="https://btjanaka.net/" />
  <updated>2026-04-07T10:10:40Z</updated>
  <id>https://btjanaka.net/</id>
  <author>
    <name>Bryon Tjanaka</name>
    <uri>https://btjanaka.net/</uri>
  </author>
  <entry>
    <title>Tic-Tac-Toe</title>
    <link href="https://btjanaka.net/blog/tictactoe/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tic-tac-toe game built with vanilla JS.</summary>
    <updated>2019-04-08T18:00:00Z</updated>
    <id>https://btjanaka.net/blog/tictactoe/</id>
    <content type="html">

&lt;div class=&quot;max-w-screen-md mx-auto&quot;&gt;
  &lt;div class=&quot;w-3/4 sm:w-1/3 mx-auto text-center&quot;&gt;
    &lt;div class=&quot;p-3 rounded-lg dark:bg-gray-900 shadow-lg dark:shadow-gray-600 my-4&quot;&gt;
      &lt;div class=&quot;flex flex-wrap&quot; id=&quot;tictactoediv&quot;&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell1&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell2&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell3&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell4&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell5&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell6&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell7&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell8&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-1/3&quot;&gt;
            &lt;div class=&quot;relative&quot; style=&quot;padding-bottom: 100%&quot;&gt;
              &lt;button class=&quot;absolute left-0 top-0 w-full h-full
                             block
                             border-2 border-gray-300 dark:border-gray-500
                             bg-gray-100 hover:bg-gray-200
                             dark:bg-gray-800 dark:hover:bg-gray-600
                             text-6xl text-center dark:text-darktext-light&quot; aria-label=&quot;Place a piece&quot; id=&quot;tictactoecell9&quot;&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;&lt;div class=&quot;w-full flex justify-between
                    border-2 border-gray-300 dark:border-gray-500
                    dark:text-darktext-light&quot;&gt;
          &lt;p class=&quot;pt-3 px-2&quot; id=&quot;tictactoeinfo&quot;&gt;
          &lt;/p&gt;
          &lt;p class=&quot;text-5xl text-right pr-2&quot; id=&quot;tictactoeplayer&quot;&gt;
          &lt;/p&gt;
        &lt;/div&gt;
        &lt;button class=&quot;w-full gray-button mt-2&quot; id=&quot;tictactoereset&quot;&gt;
          Reset
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
// Logic for a tic tac toe game.
&quot;use strict&quot;;

const TicTacToe = (function() {
  //
  // Constants
  //

  const NUM_CELLS = 9;
  const CELL_EMPTY = &quot;&quot;;
  const CELL_X = &quot;&amp;times;&quot;;
  const CELL_O = &quot;&amp;#9679;&quot;;
  const WINNER_NONE = &quot;none&quot;;
  const WINNER_TIE = &quot;tie&quot;;
  const NEXT_TURN = {};
  NEXT_TURN[CELL_X] = CELL_O;
  NEXT_TURN[CELL_O] = CELL_X;

  // Combos of cells that have to be the same to result in a win
  const WIN_COMBOS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  //
  // Utility
  //

  // Checks for a winner in the given array of cells, where each cell is an HTML
  // button. Returns the player that won if there was any, and CELL_EMPTY
  // otherwise.
  function checkWinner(cells) {
    for (const combo of WIN_COMBOS) {
      if (
        cells[combo[2]].innerHTML == cells[combo[0]].innerHTML &amp;&amp;
        cells[combo[1]].innerHTML == cells[combo[0]].innerHTML &amp;&amp;
        cells[combo[0]].innerHTML != CELL_EMPTY
      ) {
        return cells[combo[0]].innerHTML;
      }
    }
    return CELL_EMPTY;
  }

  // Returns a bool telling whether the given cells indicate a game that is
  // a tie
  function checkTie(cells) {
    return (
      checkWinner(cells) == CELL_EMPTY &amp;&amp;
      cells.every(c =&gt; c.innerHTML != CELL_EMPTY)
    );
  }

  // Finds all the tictactoe cells
  function findCells() {
    const cells = [];
    for (let i = 1; i &lt;= NUM_CELLS; ++i) {
      cells.push(document.getElementById(&quot;tictactoecell&quot; + i));
    }
    return cells;
  }

  //
  // Event handling
  //

  // Returns a function which can reset the game to a new state
  function newGame(game) {
    return function() {
      game[&quot;turn&quot;] = CELL_X;
      game[&quot;winner&quot;] = WINNER_NONE;
      for (const cell of game[&quot;cells&quot;]) {
        cell.innerHTML = CELL_EMPTY;
      }
      game[&quot;infobox&quot;].innerHTML = &quot;Next Player:&quot;;
      game[&quot;playerbox&quot;].innerHTML = game[&quot;turn&quot;];
    };
  }

  // Returns a function which can handle a click for the given game and cell
  function handleClick(game, cell) {
    return function() {
      if (cell.innerHTML != CELL_EMPTY) return;
      if (game[&quot;winner&quot;] != WINNER_NONE) return;

      cell.innerHTML = game[&quot;turn&quot;];
      game[&quot;turn&quot;] = NEXT_TURN[game[&quot;turn&quot;]];
      game[&quot;infobox&quot;].innerHTML = &quot;Next Player:&quot;;
      game[&quot;playerbox&quot;].innerHTML = game[&quot;turn&quot;];

      const winner = checkWinner(game[&quot;cells&quot;]);
      if (winner != CELL_EMPTY) {
        game[&quot;winner&quot;] = winner;
        game[&quot;infobox&quot;].innerHTML = &#39;&lt;span class=&quot;font-bold text-green-600&quot;&gt;Winner:&lt;/span&gt;&#39;
        game[&quot;playerbox&quot;].innerHTML = winner;
        return;
      }

      if (checkTie(game[&quot;cells&quot;])) {
        game[&quot;winner&quot;] = WINNER_TIE;
        game[&quot;infobox&quot;].innerHTML = `&lt;span class=&quot;font-bold text-orange-500&quot;&gt;Cat Scratch!&lt;/span&gt;`;
        game[&quot;playerbox&quot;].innerHTML = &quot;&amp;nbsp;&quot;;
        return;
      }
    };
  }

  return {
    // Builds the entire game, with event listeners for appropriate buttons.
    // |enclosingDivId| is the id of the div where the game should be built.
    buildGame: function() {
      const game = {
        div: document.getElementById(&quot;tictactoediv&quot;),
        cells: findCells(),
        infobox: document.getElementById(&quot;tictactoeinfo&quot;),
        playerbox: document.getElementById(&quot;tictactoeplayer&quot;),
        reset: document.getElementById(&quot;tictactoereset&quot;),
        turn: &quot;&quot;,
        winner: &quot;&quot;,
      };
      game[&quot;reset&quot;].onclick = newGame(game);
      for (let i = 0; i &lt; game[&quot;cells&quot;].length; ++i) {
        game[&quot;cells&quot;][i].onclick = handleClick(game, game[&quot;cells&quot;][i]);
      }
      newGame(game)();
    },
  };
})();

TicTacToe.buildGame();
&lt;/script&gt;
&lt;div class=&quot;prose dark:prose-dark max-w-screen-md mx-auto first:pt-4 last:pb-4
            prose-img:w-full sm:prose-img:w-3/4 prose-img:mx-auto
            prose-figure:my-0 prose-figcaption:text-center&quot;&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Website History</title>
    <link href="https://btjanaka.net/blog/website-history/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A brief history of my personal website.</summary>
    <updated>2019-12-25T00:00:00Z</updated>
    <id>https://btjanaka.net/blog/website-history/</id>
    <content type="html">&lt;p&gt;My personal website has gone through several iterations. Here I briefly describe
the motivation and technologies behind each major version.&lt;/p&gt;
&lt;h2 id=&quot;v1---jekyll&quot;&gt;V1 - Jekyll &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/website-history/#v1---jekyll&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Inspired by several friends, I began learning about web development in
December 2018. Using &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; with the
&lt;a href=&quot;https://github.com/TaylanTatli/Moon&quot;&gt;Moon theme&lt;/a&gt;, I built a personal website
and hosted it on &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;. Though the website
looked good, I hardly knew how it worked, so I explored further.&lt;/p&gt;
&lt;h2 id=&quot;v2---%E2%80%9Cvanilla%E2%80%9D&quot;&gt;V2 - “Vanilla” &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/website-history/#v2---%E2%80%9Cvanilla%E2%80%9D&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To better understand basic web technologies, I built a new website from the
ground up with vanilla HTML, CSS, and JavaScript. Eventually, I used
&lt;a href=&quot;http://browserify.org/&quot;&gt;Browserify&lt;/a&gt; to modularize my JavaScript code. I also
used &lt;a href=&quot;https://www.npmjs.com/package/liquidjs&quot;&gt;liquidjs&lt;/a&gt; to build a primitive
static site generator similar to Jekyll. Overall, this project taught me about
the wide variety of libraries and tools available for web developers.&lt;/p&gt;
&lt;h2 id=&quot;v3---react&quot;&gt;V3 - React &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/website-history/#v3---react&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To gain more experience with high-level frameworks, I built the next version of
my website with &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;. Though I enjoyed the flexibility
React provided, I also found it too heavy for a personal website. React is
tailored for large, interactive websites, but my personal website was small and
static. Furthermore, using pure React on the client-side meant that JavaScript
had to be executed before any content was rendered, so search engines had a
harder time indexing my content. Some search engines, like Google, did execute
the JavaScript and analyze the result, but others, like DuckDuckGo, did not, and
so my website did not show up. Hence, I concluded that I should use a static
site framework like Jekyll, while plugging in small React components if needed.&lt;/p&gt;
&lt;h2 id=&quot;v4---jekyll-(again)&quot;&gt;V4 - Jekyll (again) &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/website-history/#v4---jekyll-(again)&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Thus, I came full circle and decided to use Jekyll once more, initially with the
&lt;a href=&quot;https://github.com/alshedivat/al-folio&quot;&gt;al-folio&lt;/a&gt; theme, and then with the
&lt;a href=&quot;https://github.com/kitian616/jekyll-TeXt-theme&quot;&gt;TeXt&lt;/a&gt; theme – with numerous
custom tweaks, of course. I also integrated React into this theme, allowing me
to add interactive components when needed.&lt;/p&gt;
&lt;h2 id=&quot;v5---eleventy&quot;&gt;V5 - Eleventy &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/website-history/#v5---eleventy&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most recently, I have adopted the &lt;a href=&quot;https://11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; framework.
Eleventy fulfills a similar role as Jekyll, but since it is implemented in
JavaScript, I can more easily integrate many of my favorite tools, including
&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind CSS&lt;/a&gt;,
&lt;a href=&quot;https://markdown-it.github.io/&quot;&gt;markdown-it&lt;/a&gt;, &lt;a href=&quot;https://katex.org/&quot;&gt;KaTeX&lt;/a&gt;, and
&lt;a href=&quot;https://preactjs.com/&quot;&gt;Preact&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Integer Replacement</title>
    <link href="https://btjanaka.net/blog/integer-replacement/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>LeetCode problem 397.</summary>
    <updated>2020-01-13T19:00:00Z</updated>
    <id>https://btjanaka.net/blog/integer-replacement/</id>
    <content type="html">&lt;p&gt;This is a problem I brought along to the WICSxACM Technical Interview Prep
workshop on January 13, 2020.&lt;/p&gt;
&lt;h2 id=&quot;problem-description&quot;&gt;Problem Description &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/integer-replacement/#problem-description&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://leetcode.com/problems/integer-replacement/&quot;&gt;LeetCode 397&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Given a positive integer &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, you can perform the following operations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is even, replace &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n/2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;If &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is odd, replace &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with either &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.66666em;vertical-align:-0.08333em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n - 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.66666em;vertical-align:-0.08333em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What is the minimum number of replacements needed for &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to become &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;?&lt;/p&gt;
&lt;h2 id=&quot;hints&quot;&gt;Hints &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/integer-replacement/#hints&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The initial temptation is to go for a fancy, math-based &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; solution, but
there are more general approaches that will increase your chances of actually
coming up with a solution. What are some other approaches you can think of?&lt;/li&gt;
&lt;li&gt;How can you think of the problem as a graph? (For this workshop, I know there
have been quite a few other graph problems, so this will be fresh in your
mind.)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/integer-replacement/#solution&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have implemented one possible solution to the problem in C++.&lt;/p&gt;
&lt;h3 id=&quot;approach-1%3A-bfs&quot;&gt;Approach 1: BFS &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/integer-replacement/#approach-1%3A-bfs&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This solution was suggested in the &lt;a href=&quot;https://btjanaka.net/blog/integer-replacement/#hints&quot;&gt;Hints&lt;/a&gt;. The idea is to think of the
numbers as a graph, where each number is a node and there are edges connecting
each node &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x/2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; if &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is even, or to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.66666em;vertical-align:-0.08333em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x - 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.66666em;vertical-align:-0.08333em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; if &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is odd.
We can then perform a BFS (Breadth-First Search) on the graph to find the length
of the shortest path from &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Time complexity: &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; – we can only encounter numbers in the range
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[1, 2n]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.16666666666666666em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; since if you reach &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, you wasted a bunch of steps because &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
can just be divided by &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.64444em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to get &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Since we never visit the same number
twice, the time complexity is &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(2n) = O(n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2777777777777778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2777777777777778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Space complexity: &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; – same reason as above.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__0&quot;&gt;
&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Solution&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;integerReplacement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Queue for BFS -- each pair holds a number `x` and the number&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// of steps it is from `n`. We use `long long` to account for the&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// edge case when `n == INT_MAX`. Note that as we pop nodes from&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// and add nodes to this queue, the number of steps gradually&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// increases. Furthermore, note that we are guaranteed to visit all nodes&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// that are `k` steps from `n` before any nodes that are `k + 1` steps&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// from `n`.&lt;/span&gt;&lt;br /&gt;    queue&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; q&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Visited set -- holds numbers that have already been encountered.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Numbers enter this set when they are first encountered by the&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// algorithm. We do not want to revisit these numbers because we only&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// care about the minimum number of steps to visit them.&lt;/span&gt;&lt;br /&gt;    unordered_set&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; visited&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// The queue starts with `n` at 0 steps, and `n` is visited to begin with.&lt;/span&gt;&lt;br /&gt;    q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// BFS loop.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Retrieve the next `x` and `steps` from the queue.&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; steps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;tie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; steps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;front&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// See std::tie&lt;/span&gt;&lt;br /&gt;      q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// We solved the problem -- return the number of steps.&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; steps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// If x is even, the only node connected to it will be `x/2`&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;// Make sure to record that `x/2` is visited.&lt;/span&gt;&lt;br /&gt;          visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;// Add `x/2` with one more step than `x`.&lt;/span&gt;&lt;br /&gt;          q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; steps &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Same as above, except we now have `x + 1` and `x - 1`&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; steps &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; steps &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// If for some reason no solution was found.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__0&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;h3 id=&quot;alternate-approaches&quot;&gt;Alternate Approaches &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/integer-replacement/#alternate-approaches&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you look at the
&lt;a href=&quot;https://leetcode.com/problems/integer-replacement/discuss/&quot;&gt;discussions&lt;/a&gt; on the
original LeetCode problem, you will see references to dynamic programming (DP)
and recursion.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>N-Queens</title>
    <link href="https://btjanaka.net/blog/n-queens/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>Visualize a brute-force search for solutions to the n-queens problem.</summary>
    <updated>2020-06-06T03:00:00Z</updated>
    <id>https://btjanaka.net/blog/n-queens/</id>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Eight_queens_puzzle&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;-queens&lt;/a&gt; problem is
the problem of placing &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; queens on an &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n &#92;times n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.66666em;vertical-align:-0.08333em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; chessboard such that no two
queens are attacking each other. The following tool provides a visualization of
a “brute-force” algorithm for solving the problem. This algorithm advances
across the board column by column. In each column, the queen is moved down until
it no longer conflicts with any of the previous queens. Once such a position is
found, the queen in the next column is placed. This continues until the last
queen is placed, solving the problem. If at any time a queen in a certain column
cannot be placed anywhere, we “backtrack” to the previous column and move that
queen down to its next valid position. Once we have placed all &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; queens, we
can continue this algorithm to find other solutions.&lt;/p&gt;
&lt;p&gt;This tool shows the current queen in blue. Queens that conflict with the current
queen as it is moved are shown in red. The top row of numbers shows the position
(row number) of each queen in the corresponding column. The controls on the side
adjust board size and speed of the visualization. There are also buttons for
running the visualization, taking a single step, and stopping.&lt;/p&gt;

&lt;div class=&quot;__preact_n_queens__ max-w-screen-md mx-auto my-6&quot;&gt;
&lt;noscript&gt;
  &lt;p class=&quot;text-center text-orange-500 font-bold italic&quot;&gt;
    (JavaScript must be enabled to run this component.)
  &lt;/p&gt;
&lt;/noscript&gt;
&lt;/div&gt;
&lt;div class=&quot;prose dark:prose-dark max-w-screen-md mx-auto first:pt-4 last:pb-4
            prose-img:w-full sm:prose-img:w-3/4 prose-img:mx-auto
            prose-figure:my-0 prose-figcaption:text-center&quot;&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/n-queens/#notes&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;For example implementations of this algorithm in C++, refer to this
&lt;a href=&quot;https://github.com/btjanaka/algorithm-problems/tree/master/_reference/n-queens&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;While the algorithm described and visualized above is designed to find &lt;em&gt;all&lt;/em&gt;
solutions to the &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;-queens problem for any &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, it is not the most efficient
if we only seek to find &lt;em&gt;one&lt;/em&gt; solution. In this case, we can turn to a
closed-form solution, such as the one described in the paper
&lt;a href=&quot;https://dl.acm.org/doi/10.1145/122319.122322&quot;&gt;Explicit solutions to the N-queens problem for all N&lt;/a&gt;
and implemented &lt;a href=&quot;https://gist.github.com/IanCal/1858601&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Applying to Grad School</title>
    <link href="https://btjanaka.net/blog/grad-school/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>Tips for those pursuing a Ph.D. in CS.</summary>
    <updated>2020-07-25T18:00:00Z</updated>
    <id>https://btjanaka.net/blog/grad-school/</id>
    <content type="html">&lt;p&gt;Having applied to CS Ph.D. programs over the past year or so, I decided to write
down a few lessons I learned. To begin, I will talk about my overall experience.
The summer after high school (2017), I took the GRE, as I knew I wanted to
pursue graduate education, and the GRE was not much of a stretch after the SAT
and ACT. In spring 2019, I spoke to my professors about what grad school
entailed, and whether it would be a good fit for me. These professors
recommended I apply to CS Ph.D. programs as well as the
&lt;a href=&quot;https://nsfgrfp.org/&quot;&gt;NSF GRFP&lt;/a&gt;. After touring the schools where I was accepted
earlier this year (2020), I chose to attend USC. Below is a list of tips I
learned throughout this process – some items come from first-hand experience,
while others were passed along to me.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Figure out what you’re getting yourself into.&lt;/strong&gt; Grad school is no small
undertaking. Basically, you’ll be spending up to 6 years working full-time as
a researcher in your advisor’s lab. Unlike in undergraduate, courses will be
secondary – you’ll take a few, but they will mostly be aimed at
supplementing your research. In short, grad school is more like a job than
“school.” One article I found particularly helpful in understanding grad
school was
&lt;a href=&quot;https://stefanosnikolaidis.blogspot.com/2018/12/7-rules-of-grad-school-game.html&quot;&gt;this blog post&lt;/a&gt;
from my advisor at USC.
&lt;ul&gt;
&lt;li&gt;Some have asked whether they should do a master’s before / instead of a
Ph.D. My general impression is that master’s degrees are more focused on
coursework, though many programs do involve writing a thesis. In general,
if you are pursuing a research career, a Ph.D. is the way to go.
Furthermore, many Ph.D. programs allow you to petition for a master’s once
you have passed certain milestones. If you are thinking of completing a
master’s and then a Ph.D., keep in mind that a master’s is not required to
pursue a Ph.D. (i.e. you can go straight from undergrad to Ph.D.), and a
master’s will not necessarily take time off your Ph.D.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talk to as many people as possible.&lt;/strong&gt; Get advice from lots of people when
you are trying to figure out the program and school to which you should
apply. Keep in mind that you will receive many viewpoints, some conflicting
with each other. It is up to you to distill the information that is helpful
for your situation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Figure out an area in which to specialize.&lt;/strong&gt; You should be going into a
Ph.D. program with a general idea of what problems you want to work on. This
will help you decide which professors you want to work with, as well as what
you write in your various application materials. Certainly, this will require
some soul searching – read some papers, think about your personal history,
and figure out what you want to work on next.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose the professor(s), not just the school.&lt;/strong&gt; Grad school is all about
the people, since you are basically picking your manager and coworkers for
the next several years. Thus, as you select schools, make sure you are
looking through professors’ publications/websites. You may also want to check
whether the school has multiple professors working in your field of interest,
as having a community of like-minded researchers can be beneficial. To this
end, &lt;a href=&quot;http://csrankings.org/&quot;&gt;CS rankings&lt;/a&gt; is a great website for finding
prominent schools and professors in your field of interest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Email professors who you may be interested in working with.&lt;/strong&gt; If you are
genuinely interested in working with certain professors, spend some time
composing an email asking about their recent research. Importantly, &lt;strong&gt;do
not&lt;/strong&gt; go around asking professors if they will accept you, but &lt;strong&gt;do&lt;/strong&gt; ask if
they are accepting students for their lab. If a professor is not taking any
students, your application may be wasted. Note: some professors will
explicitly ask that you &lt;em&gt;not&lt;/em&gt; email them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose your recommenders carefully.&lt;/strong&gt; Recommenders must be people who know
you well enough that they can write a letter about your ability to do
independent research. Ideally, they are professors with whom you have done
research. If you have not done research with enough professors, get to know
your current instructors by attending their office hours. Above all, do not
be afraid to ask for a recommendation. Writing recommendations is a regular
part of a professor’s job, and if they know you well enough, they will be
willing to help you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ask your recommenders early, and keep them in the loop.&lt;/strong&gt; Give your
recommenders as much time as possible to write your recommendations. By June
of 2019, I had asked two of my recommenders, and by the end of the summer, I
had asked my third. As I applied, I kept them updated on my list of grad
schools, and I let them know when I had sent out requests for letters
(usually, the application system lets you send a letter request to your
recommender; the recommender then opens this email and submits the letter).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The personal statement is the part that you can control.&lt;/strong&gt; Most of your
application will already be set by the time you start applying. Your GPA
probably will not change much, your GRE scores will be set, your recommenders
will write what they write, and you will not suddenly gain a plethora of new
research experiences. However, the personal statement is something that you
can change &lt;em&gt;right now&lt;/em&gt;, so make sure that it is pristine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get everyone to review your application.&lt;/strong&gt; This is especially true for the
personal statement. Send it to as many people as you can – not just the
professors / recommenders you are working with, but also counselors, family
members, and (especially) peers. In particular, I found it really helpful to
get advice from friends who had just applied to and entered grad school, as
well as friends who were currently applying to grad school.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consider if you want to go abroad.&lt;/strong&gt; The advice in this list is tailored to
US programs, but you can always consider places like the UK, Canada, and
Singapore. Keep in mind that the processes and programs in other countries
may be different. For instance, UK Ph.D. programs tend to be shorter than US
ones.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apply to fellowships too.&lt;/strong&gt; Fellowships like the
&lt;a href=&quot;https://nsfgrfp.org/&quot;&gt;NSF GRFP&lt;/a&gt; provide funding to graduate students and come
with high prestige. Some schools also have offices dedicated to helping
students apply to such awards. For example, UCI has the
&lt;a href=&quot;http://scholars.uci.edu/&quot;&gt;Scholarship Opportunities Program&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start early.&lt;/strong&gt; Applying to grad school is a tedious process, and you will
need as much time as you can get. Starting early means you have more time to
write your essays and get reviews from professors and anyone else helping
you. If you’re reading this article a couple months before you would apply,
you’re already on the right track.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The application process does not end with &lt;em&gt;submit&lt;/em&gt;.&lt;/strong&gt; Unfortunately, you’re
not done when you hit the submit button on your application. Though
applications are typically due in mid-December (with some in late November or
early January), expect to be contacted for interviews and visits with
professors starting in January. Essentially, before choosing to work with you
for the next several years, professors will want to know more about you than
they can glean from your application. To prepare for these interviews, review
the professor’s recent work and make sure you can answer questions about
everything on your application, especially research experiences. Of course,
make sure to ask if there is anything you should prepare when a professor
contacts you.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With that, I hope this list has clarified some of the Ph.D. application process.
Best of luck on your applications!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CPPN Image Generator</title>
    <link href="https://btjanaka.net/blog/cppn/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>Generate abstract art in the browser.</summary>
    <updated>2020-12-17T03:00:00Z</updated>
    <id>https://btjanaka.net/blog/cppn/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Compositional_pattern-producing_network&quot;&gt;Compositional Pattern-Producing Networks (CPPNs)&lt;/a&gt;
are networks which, among other things, may be used to encode images at
(theoretically) infinite resolution. While other networks simultaneously output
all pixels for an image, CPPNs take in individual &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.19444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; coordinate and
output one pixel at time. This demo generates random images with a CPPN. The
CPPN architecture is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An input layer takes in a random latent vector with values in the range
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[-1, 1]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.16666666666666666em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, as well as &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.19444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; coordinates of the pixel and a radius
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msqrt&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r =
 &#92;sqrt{x^2 + y^2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2777777777777778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2777777777777778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.24em;vertical-align:-0.2821659999999999em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord sqrt&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9578340000000001em;&quot;&gt;&lt;span class=&quot;svg-align&quot; style=&quot;top:-3.2em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3.2em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot; style=&quot;padding-left:1em;&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.740108em;&quot;&gt;&lt;span style=&quot;top:-2.9890000000000003em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222222222222222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.740108em;&quot;&gt;&lt;span style=&quot;top:-2.9890000000000003em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.917834em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3.2em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;hide-tail&quot; style=&quot;min-width:1.02em;height:1.28em;&quot;&gt;&lt;svg width=&quot;400em&quot; height=&quot;1.28em&quot; viewBox=&quot;0 0 400000 1296&quot; preserveAspectRatio=&quot;xMinYMin slice&quot;&gt;&lt;path d=&quot;M263,681c0.7,0,18,39.7,52,119
c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120
c340,-704.7,510.7,-1060.3,512,-1067
l0 -0
c4.7,-7.3,11,-11,19,-11
H40000v40H1012.3
s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232
c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1
s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26
c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z
M1001 80h400000v40h-400000z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2821659999999999em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;The inputs flow through several fully connected layers with tanh activations.&lt;/li&gt;
&lt;li&gt;Finally, there is an output layer of size 1 (for greyscale images) or size 3
(for RGB images) with sigmoid activation (this ensures all outputs are in the
range &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[0, 1]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.16666666666666666em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All weights are initially drawn from a unit normal distribution. When you press
the &lt;code&gt;Restart&lt;/code&gt; button, these weights will be re-initialized. To get the final
image, pixel values are calculated on a grid of &lt;code&gt;width&lt;/code&gt; uniformly spaced
coordinates in the &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.43056em;vertical-align:0em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; direction and &lt;code&gt;height&lt;/code&gt; uniformly spaced coordinates in
the &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.19444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; direction.&lt;/p&gt;
&lt;p&gt;For more info about CPPNs, I recommend referring to David Ha’s
&lt;a href=&quot;https://blog.otoro.net/2016/03/25/generating-abstract-patterns-with-tensorflow/&quot;&gt;blog post&lt;/a&gt;.
This demo is based on that blog post, as well as the corresponding
&lt;a href=&quot;https://otoro.net/ml/netart/&quot;&gt;demo&lt;/a&gt;. The network in this demo was implemented
with &lt;a href=&quot;https://www.tensorflow.org/js&quot;&gt;TensorFlow.js&lt;/a&gt;. The implementation is
contained in the HTML for this page (i.e. you can view it with “inspect
element”).&lt;/p&gt;
&lt;div class=&quot;__blog__cppn__ max-w-screen-md mx-auto pt-4&quot;&gt;&lt;div class=&quot;grid grid-cols-1 md:grid-cols-2 gap-2&quot; id=&quot;controls&quot;&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;output-width&quot;&gt;
        Width: &lt;span id=&quot;output-width-val&quot;&gt;240&lt;/span&gt;
      &lt;/label&gt;
      &lt;input type=&quot;range&quot; min=&quot;100&quot; max=&quot;1920&quot; value=&quot;240&quot; step=&quot;10&quot; class=&quot;slider&quot; id=&quot;output-width&quot; /&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;output-height&quot;&gt;
        Height: &lt;span id=&quot;output-height-val&quot;&gt;240&lt;/span&gt;
      &lt;/label&gt;
      &lt;input type=&quot;range&quot; min=&quot;100&quot; max=&quot;1920&quot; value=&quot;240&quot; step=&quot;10&quot; class=&quot;slider&quot; id=&quot;output-height&quot; /&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;hidden-layers&quot;&gt;
        Hidden Layers: &lt;span id=&quot;hidden-layers-val&quot;&gt;8&lt;/span&gt;
      &lt;/label&gt;
      &lt;input type=&quot;range&quot; min=&quot;0&quot; max=&quot;16&quot; value=&quot;8&quot; step=&quot;1&quot; class=&quot;slider&quot; id=&quot;hidden-layers&quot; /&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;hidden-dim&quot;&gt;
        Hidden Layer Dimension: &lt;span id=&quot;hidden-dim-val&quot;&gt;16&lt;/span&gt;
      &lt;/label&gt;
      &lt;input type=&quot;range&quot; min=&quot;1&quot; max=&quot;64&quot; value=&quot;16&quot; step=&quot;1&quot; class=&quot;slider&quot; id=&quot;hidden-dim&quot; /&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;output-mode&quot;&gt;Color Mode&lt;/label&gt;
      &lt;select id=&quot;output-mode&quot; name=&quot;Mode&quot;&gt;
        &lt;option value=&quot;grey&quot;&gt;Greyscale&lt;/option&gt;
        &lt;option value=&quot;rgb&quot;&gt;RGB&lt;/option&gt;
      &lt;/select&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label class=&quot;control-label&quot; for=&quot;latent-size&quot;&gt;
        Latent Vector Size: &lt;span id=&quot;latent-size-val&quot;&gt;2&lt;/span&gt;
      &lt;/label&gt;
      &lt;input type=&quot;range&quot; min=&quot;0&quot; max=&quot;16&quot; value=&quot;2&quot; step=&quot;1&quot; class=&quot;slider&quot; id=&quot;latent-size&quot; /&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;mt-4 grid grid-cols-2 md:grid-cols-4 gap-2&quot;&gt;
    &lt;button class=&quot;block gray-button&quot; id=&quot;button-draw&quot;&gt;
      &lt;i class=&quot;fas fa-paint-brush mr-1 text-gray-400&quot;&gt;&lt;/i&gt;Draw
    &lt;/button&gt;
    &lt;button class=&quot;block gray-button&quot; id=&quot;button-save&quot;&gt;
      &lt;i class=&quot;fas fa-save mr-1.5 text-gray-400&quot;&gt;&lt;/i&gt;Save
    &lt;/button&gt;
    &lt;button class=&quot;block gray-button&quot; id=&quot;button-restart&quot;&gt;
      &lt;i class=&quot;fas fa-redo mr-1.5 text-gray-400&quot;&gt;&lt;/i&gt;Restart
    &lt;/button&gt;
    &lt;button class=&quot;block gray-button&quot; id=&quot;button-randomize&quot;&gt;
      &lt;i class=&quot;fas fa-random mr-1 text-gray-400&quot;&gt;&lt;/i&gt; Randomize Latent
    &lt;/button&gt;
  &lt;/div&gt;
  &lt;canvas id=&quot;output-image&quot; width=&quot;240&quot; height=&quot;240&quot; class=&quot;shadow-lg dark:shadow-gray-600 mx-auto my-5&quot;&gt;
  &lt;/canvas&gt;
  &lt;!-- TensorFlow.js --&gt;
  &lt;script src=&quot;https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js&quot; defer=&quot;&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js&quot; defer=&quot;&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;module&quot;&gt;
  // Provides methods for using a TensorFlow CPPN.
  const CPPN = (function () {
    // Generates a new model. outputMode is either &quot;grey&quot; or &quot;rgb&quot;.
    function newModel(latentSize, hiddenDim, hiddenLayers, outputMode) {
      const inputDim = latentSize + 3; // 3 for x, y, r.
      const outputDim = outputMode == &quot;grey&quot; ? 1 : 3;
      const model = tf.sequential();

      let curDim = inputDim;
      for (let i = 0; i &lt; hiddenLayers; ++i) {
        model.add(
          tf.layers.dense({
            inputShape: [curDim],
            units: hiddenDim,
            useBias: false,
            activation: &quot;tanh&quot;,
            weights: [tf.randomNormal([curDim, hiddenDim])],
          })
        );
        curDim = hiddenDim;
      }
      model.add(
        tf.layers.dense({
          inputShape: [curDim],
          units: outputDim,
          useBias: false,
          activation: &quot;sigmoid&quot;,
          weights: [tf.randomNormal([curDim, outputDim])],
        })
      );

      return model;
    }

    function randomLatentVec(latentSize) {
      return tf.randomUniform([latentSize], -1, 1);
    }

    // Generates an image from the model and draws it onto the given imageData --
    // imageData is taken from a canvas.
    function drawImage(model, latentVec, width, height, outputMode, imageData) {
      return tf.tidy(() =&gt; {
        const latent = latentVec.expandDims(0).tile([width, 1]);
        const ys = tf.linspace(-1, 1, width);
        const xs = tf.linspace(-1, 1, height).expandDims(1);
        const ones = tf.ones([width, 1]);

        // Calculate and set each row.
        ys.dataSync().forEach((y, yIdx) =&gt; {
          const yFull = ones.mul(tf.scalar(y));
          const r = tf.add(xs.square(), yFull.square()).sqrt();
          const inputs = tf.concat([latent, xs, yFull, r], 1);
          const output = model.predict(inputs).arraySync();

          const start = yIdx * width * 4;
          const end = (yIdx + 1) * width * 4;
          let outIdx = 0;
          for (let i = start; i &lt; end; i += 4) {
            const pixel =
              outputMode == &quot;grey&quot;
                ? [output[outIdx][0], output[outIdx][0], output[outIdx][0]]
                : output[outIdx];
            imageData.data[i] = pixel[0] * 255.0;
            imageData.data[i + 1] = pixel[1] * 255.0;
            imageData.data[i + 2] = pixel[2] * 255.0;
            imageData.data[i + 3] = 255;

            ++outIdx;
          }
        });
      });
    }

    return {
      newModel,
      randomLatentVec,
      drawImage,
    };
  })();

  // Interactivity.
  (function () {
    // Model vars.
    let hiddenLayers = 8;
    let hiddenDim = 16;
    let outputMode = &quot;grey&quot;;
    let model;
    let latentSize = 2;
    const maxLatentSize = 16;
    let latentVec = CPPN.randomLatentVec(maxLatentSize).dataSync();

    function restart() {
      model = CPPN.newModel(latentSize, hiddenDim, hiddenLayers, outputMode);
    }

    // Sets up the label value to change when the slider changes.
    function linkVal(slider, valId) {
      const val = document.getElementById(valId);
      slider.oninput = () =&gt; {
        val.innerHTML = slider.value;
      };
    }

    //
    // Set up controls.
    //

    const widthSlider = document.getElementById(&quot;output-width&quot;);
    linkVal(widthSlider, &quot;output-width-val&quot;);

    const heightSlider = document.getElementById(&quot;output-height&quot;);
    linkVal(heightSlider, &quot;output-height-val&quot;);

    const hiddenLayerSlider = document.getElementById(&quot;hidden-layers&quot;);
    linkVal(hiddenLayerSlider, &quot;hidden-layers-val&quot;);
    hiddenLayerSlider.onchange = () =&gt; {
      hiddenLayers = parseInt(hiddenLayerSlider.value, 10);
      restart();
    };

    const hiddenDimSlider = document.getElementById(&quot;hidden-dim&quot;);
    linkVal(hiddenDimSlider, &quot;hidden-dim-val&quot;);
    hiddenDimSlider.onchange = () =&gt; {
      hiddenDim = parseInt(hiddenDimSlider.value, 10);
      restart();
    };

    const modeSelector = document.getElementById(&quot;output-mode&quot;);
    modeSelector.onchange = () =&gt; {
      outputMode = modeSelector.value;
      restart();
    };

    // Controls for setting latent vectors.
    const latentSliders = [];
    const latentControls = [];
    const latentControlsDiv = document.getElementById(&quot;controls&quot;);
    for (let i = 0; i &lt; maxLatentSize; ++i) {
      const label = document.createElement(&quot;label&quot;);
      label.setAttribute(&quot;class&quot;, &quot;control-label&quot;);
      label.setAttribute(&quot;for&quot;, `latent-${i}`);
      label.innerHTML = `Latent ${i + 1}: ${latentVec[i].toFixed(2)}`;

      const slider = document.createElement(&quot;input&quot;);
      slider.setAttribute(&quot;type&quot;, &quot;range&quot;);
      slider.setAttribute(&quot;min&quot;, -100);
      slider.setAttribute(&quot;max&quot;, 100);
      slider.setAttribute(&quot;value&quot;, latentVec[i] * 100);
      slider.setAttribute(&quot;step&quot;, 1);
      slider.setAttribute(&quot;class&quot;, &quot;slider&quot;);
      slider.setAttribute(&quot;id&quot;, `latent-${i}`);
      slider.oninput = () =&gt; {
        latentVec[i] = slider.value / 100.0;
        label.innerHTML = `Latent ${i + 1}: ${latentVec[i].toFixed(2)}`;
      };

      const control = document.createElement(&quot;div&quot;);
      control.appendChild(label);
      control.appendChild(slider);

      // Hide controls that are not being used.
      if (i &gt;= latentSize) control.style.display = &quot;none&quot;;

      latentControlsDiv.appendChild(control);
      latentControls.push(control);
      latentSliders.push(slider);
    }

    const latentSizeSlider = document.getElementById(&quot;latent-size&quot;);
    linkVal(latentSizeSlider, &quot;latent-size-val&quot;);
    latentSizeSlider.onchange = () =&gt; {
      // Make the latent controls appear when the slider value changes.
      latentSize = parseInt(latentSizeSlider.value, 10);
      for (let i = 0; i &lt; maxLatentSize; ++i) {
        if (i &lt; latentSize) {
          latentControls[i].style.display = &quot;block&quot;;
        } else {
          latentControls[i].style.display = &quot;none&quot;;
        }
      }
      restart();
    };

    //
    // Buttons.
    //

    document.getElementById(&quot;button-restart&quot;).onclick = restart;

    document.getElementById(&quot;button-randomize&quot;).onclick = () =&gt; {
      latentVec = CPPN.randomLatentVec(maxLatentSize).dataSync();
      for (let i = 0; i &lt; maxLatentSize; ++i) {
        latentSliders[i].value = latentVec[i] * 100;
        latentSliders[i].oninput();
      }
    };

    const canvas = document.getElementById(&quot;output-image&quot;);
    const ctx = canvas.getContext(&quot;2d&quot;);

    // Redraw the image when the draw button is clicked.
    const drawButton = document.getElementById(&quot;button-draw&quot;);
    drawButton.onclick = () =&gt; {
      const width = parseInt(widthSlider.value, 10);
      const height = parseInt(heightSlider.value, 10);
      const imageData = ctx.createImageData(width, height);

      canvas.width = width;
      canvas.height = height;

      CPPN.drawImage(
        model,
        tf.tensor1d(latentVec.slice(0, latentSize)),
        width,
        height,
        outputMode,
        imageData
      );
      ctx.putImageData(imageData, 0, 0);
    };

    // Save the image when the save button is clicked.
    const saveButton = document.getElementById(&quot;button-save&quot;);
    saveButton.onclick = () =&gt; {
      saveButton.download = &quot;image.png&quot;;
      saveButton.href = canvas
        .toDataURL(&quot;image/png&quot;)
        .replace(/^data:image&#92;/[^;]/, &quot;data:application/octet-stream&quot;);
    };

    // Load the model and draw initial image when page loads.
    document.addEventListener(&quot;DOMContentLoaded&quot;, () =&gt; {
      restart();
      drawButton.onclick();
    });
  })();
  &lt;/script&gt;
&lt;/div&gt;
&lt;div class=&quot;prose dark:prose-dark max-w-screen-md mx-auto first:pt-4 last:pb-4
            prose-img:w-full sm:prose-img:w-3/4 prose-img:mx-auto
            prose-figure:my-0 prose-figcaption:text-center&quot;&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Using CMA-ME to Land a Lunar Lander Like a Space Shuttle</title>
    <link href="https://btjanaka.net/blog/lunar_lander/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2021-02-05T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/lunar_lander/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/lunar_lander.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/lunar_lander.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Learning a Repertoire of Robot Arm Configurations</title>
    <link href="https://btjanaka.net/blog/arm_repertoire/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2021-02-05T08:00:01Z</updated>
    <id>https://btjanaka.net/blog/arm_repertoire/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/arm_repertoire.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/arm_repertoire.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Illuminating the Latent Space of an MNIST GAN</title>
    <link href="https://btjanaka.net/blog/lsi_mnist/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2021-02-05T08:00:02Z</updated>
    <id>https://btjanaka.net/blog/lsi_mnist/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/lsi_mnist.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/lsi_mnist.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Generating Images to Fool an MNIST Classifier</title>
    <link href="https://btjanaka.net/blog/fooling_mnist/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2021-02-05T08:00:03Z</updated>
    <id>https://btjanaka.net/blog/fooling_mnist/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/fooling_mnist.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/fooling_mnist.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Running Distributed Quality-Diversity Algorithms on HPC</title>
    <link href="https://btjanaka.net/blog/qd-on-hpc/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>Tips and tricks to avoid a world of pain.</summary>
    <updated>2021-02-17T06:00:00Z</updated>
    <id>https://btjanaka.net/blog/qd-on-hpc/</id>
    <content type="html">&lt;p&gt;View the tutorial and slides &lt;a href=&quot;https://slides.btjanaka.net/qd-on-hpc/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Matplotlib Figures and File Formats</title>
    <link href="https://btjanaka.net/blog/matplotlib-figures/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>What&#39;s the best file format for saving that magnificent figure you just made in Matplotlib?</summary>
    <updated>2022-05-27T16:00:00Z</updated>
    <id>https://btjanaka.net/blog/matplotlib-figures/</id>
    <content type="html">&lt;p&gt;You’ve visualized your data with &lt;a href=&quot;https://matplotlib.org/&quot;&gt;Matplotlib&lt;/a&gt;, and now
you want to include your figures in your paper, presentation, website, or other
document. However, exporting your figure from Matplotlib is not always trivial
if you want to ensure high quality — a look at the
&lt;a href=&quot;https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html&quot;&gt;&lt;code&gt;plt.savefig()&lt;/code&gt;&lt;/a&gt;
function shows there are over a dozen arguments you can tweak when saving your
figures. In this post, I’ll focus on one small aspect of this problem, namely,
how to choose the correct file format for saving your figure. For a quick
summary of the tips in this article, see the &lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/#conclusion&quot;&gt;Conclusion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (May 30, 2022): To clarify, this article only reviews the common formats
I am familiar with. For a full list of file formats supported by Matplotlib, see
&lt;a href=&quot;https://matplotlib.org/stable/users/explain/backends.html#the-builtin-backends&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#setup&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, we’ll use the following code, adapted from this
&lt;a href=&quot;https://matplotlib.org/stable/gallery/shapes_and_collections/scatter.html#sphx-glr-gallery-shapes-and-collections-scatter-py&quot;&gt;Matplotlib scatter plot example&lt;/a&gt;.
This code should work as long as you have &lt;code&gt;numpy&lt;/code&gt; and &lt;code&gt;matplotlib&lt;/code&gt; installed.&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__1&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;Example of saving a scatterplot to different image formats.&lt;br /&gt;&lt;br /&gt;Adapted from&lt;br /&gt;https://matplotlib.org/stable/gallery/shapes_and_collections/scatter.html#sphx-glr-gallery-shapes-and-collections-scatter-py&lt;br /&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; matplotlib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pyplot &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; plt&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; np&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Fixing random state for reproducibility&lt;/span&gt;&lt;br /&gt;np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;seed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;19680801&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;N &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;br /&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;colors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;random&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 0 to 15 point radii&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scatter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;area&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;colors&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; alpha&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tight_layout&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Save to various formats.&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.pdf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.svg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dpi&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.jpg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Avoid using JPEGs if possible!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__1&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;This code outputs the following plot in PDF, SVG, PNG, and JPEG formats.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/plot.svg&quot;&gt;&lt;img src=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/plot.svg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;Scatter plot output by the code above.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;lesson-1%3A-prefer-vector-based-formats&quot;&gt;Lesson 1: Prefer vector-based formats &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#lesson-1%3A-prefer-vector-based-formats&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When exporting figures, the first lesson is to always prefer vector-based image
formats. To see why this is, we need to understand the difference between
&lt;a href=&quot;https://en.wikipedia.org/wiki/Vector_graphics&quot;&gt;vector&lt;/a&gt; and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Raster_graphics&quot;&gt;raster&lt;/a&gt; graphics. Vector
graphics represent images with shapes such as points, lines and curves, while
raster graphics represent images with pixels. Importantly, vector graphics have
infinite resolution, meaning that you can zoom in and the image will still
appear clear, while raster images will become blurry/pixelated. While raster
images are excellent for photos of the “real world” (e.g. people and places),
most plots consist of points, lines, and curves, making vector graphics the
ideal format.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/vector-and-raster.svg&quot;&gt;&lt;img src=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/vector-and-raster.svg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;Difference between vector and raster graphics. In a vector graphic, the image still appears sharp when zoomed in because the image is composed of various geometric shapes. In raster graphics, the image appears blurry when zoomed in because the image is composed of pixels.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In practice, there are two vector-based formats to stick to. First, if writing a
paper with Latex, save your figure as a
&lt;a href=&quot;https://en.wikipedia.org/wiki/PDF&quot;&gt;PDF&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__2&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.pdf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__2&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;Then, include the PDF in your Latex document as follows (assuming you are using
the &lt;code&gt;graphicx&lt;/code&gt; package). See
&lt;a href=&quot;https://latex-tutorial.com/tutorials/figures/&quot;&gt;here&lt;/a&gt; for more info about Latex
and figures.&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__3&quot;&gt;
&lt;pre class=&quot;language-latex&quot;&gt;&lt;code class=&quot;language-latex&quot;&gt;&lt;span class=&quot;token function selector&quot;&gt;&#92;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function selector&quot;&gt;&#92;includegraphics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;width=&lt;span class=&quot;token function selector&quot;&gt;&#92;linewidth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;plot.pdf&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function selector&quot;&gt;&#92;caption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;My awesome plot.&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function selector&quot;&gt;&#92;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fig:plot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function selector&quot;&gt;&#92;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__3&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;Second, if you are creating your figure for a website, save it as an
&lt;a href=&quot;https://en.wikipedia.org/wiki/Scalable_Vector_Graphics&quot;&gt;SVG&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__4&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.svg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__4&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;Then, include the SVG with an &lt;code&gt;img&lt;/code&gt; tag, e.g.&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__5&quot;&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;plot.svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My awesome plot&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__5&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;With these two formats, your plots will remain crisp and clear when your
audience needs to zoom in :)&lt;/p&gt;
&lt;p&gt;Several notes regarding SVGs and PDFs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fonts:&lt;/strong&gt; Both PDFs and SVGs will be fully independent in terms of fonts,
i.e. if you use font X in your plot, you will not need to have font X
installed on your system when you open the PDF or SVG version of the plot.
This is because for PDF, all necessary fonts are embedded in the PDF during
export, and for SVG, all text is converted to paths (i.e. lines and curves).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embedding SVG directly in HTML:&lt;/strong&gt; It may be possible to embed the SVG
directly in the HTML (i.e. without an &lt;code&gt;img&lt;/code&gt; tag), but I find that this causes
the SVG to always have a fixed size, i.e. even if the screen is small the SVG
will not shrink correspondingly. I have yet to find a simple way to make SVGs
easily scale their size when directly embedding them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;lesson-2%3A-when-raster-based-formats-are-necessary%2C-use-png&quot;&gt;Lesson 2: When raster-based formats are necessary, use PNG &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#lesson-2%3A-when-raster-based-formats-are-necessary%2C-use-png&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In some cases, you will find it necessary to use a raster-based format because a
vector-based format is not feasible. For example, many web-based tools (e.g.
Google Docs, Google Slides) prohibit SVGs because
&lt;a href=&quot;https://blog.online-convert.com/svg-file-and-its-danger/&quot;&gt;SVGs may contain malicious CSS and JavaScript&lt;/a&gt;.
Furthermore, such tools do not accept PDFs because PDFs are technically not
images. In such cases, it is necessary to save the image in a raster-based
format like &lt;a href=&quot;https://en.wikipedia.org/wiki/Portable_Network_Graphics&quot;&gt;PNG&lt;/a&gt; or
&lt;a href=&quot;https://en.wikipedia.org/wiki/JPEG&quot;&gt;JPEG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When doing so, &lt;em&gt;use PNGs for the highest image quality&lt;/em&gt;. The key difference
between PNGs and JPEGs lies in how they compress images. While PNGs use
&lt;em&gt;lossless compression&lt;/em&gt;, which reduces the image size without losing any data,
JPEGs use &lt;em&gt;lossy compression&lt;/em&gt;, which deletes image data in order to reduce the
image size further. This means that plots saved as JPEGs often have
&lt;a href=&quot;https://en.wikipedia.org/wiki/Compression_artifact&quot;&gt;compression artifacts&lt;/a&gt;,
i.e. distortions which occur because the JPEG removed image data when saving.
For more information, refer to this
&lt;a href=&quot;https://www.adobe.com/creativecloud/file-types/image/comparison/jpeg-vs-png.html&quot;&gt;comparison between JPEG and PNG&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/png-and-jpg.svg&quot;&gt;&lt;img src=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/png-and-jpg.svg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;Comparison between images saved in PNG and JPEG formats. While the circles in the PNG have a smooth color, the JPEG introduces compression artifacts.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;While raster-based images will not be as crisp as vector-based images, you can
compensate for this by increasing the resolution when saving. To do this, pass
the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dots_per_inch&quot;&gt;DPI (dots per inch)&lt;/a&gt;
parameter, e.g.&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__6&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;savefig&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;plot.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dpi&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__6&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;The DPI required will depend on (1) the size of your Matplotlib figure in
inches, and (2) the size of the image you need in your document. 300 DPI is
usually sufficient, though you will need to go higher if your image is larger in
the final document than in Matplotlib (e.g. if it is 8in. x 6in. in the final
document but only 4in. x 3in. in Matplotlib).&lt;/p&gt;
&lt;h2 id=&quot;alternative-formats&quot;&gt;Alternative Formats &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#alternative-formats&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Finally, here are some alternative image formats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PGF:&lt;/strong&gt; Matplotlib supports saving images as a PGF file, which is a set of
commands that can be parsed by the Latex &lt;a href=&quot;https://www.ctan.org/pkg/pgf&quot;&gt;pgf&lt;/a&gt;
package to create figures directly in a Latex document. I have not used this
format because it requires having Latex installed on the system where I am
plotting, and PDFs are already sufficient for my purposes. For more
information on saving to PGF, see
&lt;a href=&quot;https://timodenk.com/blog/exporting-matplotlib-plots-to-latex/&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TIFF:&lt;/strong&gt; TIFFs are a raster-based format typically used in print
applications. Since I spend most of my time working with the web, I am more
familiar with PNGs. For a comparison between PNGs and TIFFs, see
&lt;a href=&quot;https://www.adobe.com/creativecloud/file-types/image/comparison/tiff-vs-png.html&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it may be sufficient to save all your Matplotlib figures in one format,
choosing the right format can make your figures clearer and more professional.
This article introduces several guidelines for choosing the right format, which
may be summarized by the following table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where will you use your figure?&lt;/th&gt;
&lt;th&gt;You should save your figure in this format:&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Latex document (e.g. a paper or report)&lt;/td&gt;
&lt;td&gt;PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Website&lt;/td&gt;
&lt;td&gt;SVG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web-based tool (e.g. Google Docs, Google Slides)&lt;/td&gt;
&lt;td&gt;SVG if allowed, PNG otherwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Word processor (e.g. Microsoft Word)&lt;/td&gt;
&lt;td&gt;SVG if allowed, PNG otherwise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;bonus-tips&quot;&gt;Bonus Tips &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#bonus-tips&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;truetype-fonts&quot;&gt;TrueType Fonts &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#truetype-fonts&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many venues require that your paper use Type 1 / TrueType fonts, but Matplotlib
uses Type 3 fonts by default. To make sure you use TrueType fonts when exporting
your figures to PDF, use the following code:&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__7&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; matplotlib&lt;br /&gt;matplotlib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rcParams&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;pdf.fonttype&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;br /&gt;matplotlib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rcParams&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ps.fonttype&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__7&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;See &lt;a href=&quot;http://phyletica.org/matplotlib-fonts/&quot;&gt;this blog post&lt;/a&gt; for more info.&lt;/p&gt;
&lt;h3 id=&quot;heatmaps&quot;&gt;Heatmaps &lt;a class=&quot;permalink&quot; href=&quot;https://btjanaka.net/blog/matplotlib-figures/#heatmaps&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When saving heatmaps e.g. those generated by Seaborn’s
&lt;a href=&quot;https://seaborn.pydata.org/generated/seaborn.heatmap.html&quot;&gt;&lt;code&gt;heatmap()&lt;/code&gt;&lt;/a&gt; or
Matplotlib’s
&lt;a href=&quot;https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.pcolormesh.html&quot;&gt;&lt;code&gt;pcolormesh()&lt;/code&gt;&lt;/a&gt;,
you may find that the PDF shows thin white lines between the cells, even if you
did not specify any borders around the heatmap cells. This occurs because the
PDF viewer is struggling to render the large number of independent cell objects.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/heatmap-lines.png&quot;&gt;&lt;img src=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/heatmap-lines.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;Thin white lines show up between the cells when saving this heatmap in a PDF.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;To resolve this issue, rasterize the heatmap cells by passing &lt;code&gt;rasterized=True&lt;/code&gt;
to &lt;code&gt;heatmap()&lt;/code&gt; or &lt;code&gt;pcolormesh()&lt;/code&gt;, i.e.&lt;/p&gt;
&lt;div class=&quot;relative&quot;&gt;
  &lt;div id=&quot;__clipboard__8&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;sns&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;heatmap&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rasterized&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pcolormeash&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rasterized&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
  &lt;button class=&quot;clipboard group transition cursor-pointer flex items-center
                 absolute right-0 top-0 p-2
                 text-xs text-gray-400 hover:text-white focus:text-white&quot; aria-label=&quot;Copy&quot; data-clipboard-target=&quot;#__clipboard__8&quot;&gt;
      &lt;span class=&quot;pr-2 hidden group-hover:inline-block group-focus:inline-block group-active:hidden&quot;&gt;
        Copy
      &lt;/span&gt;
      &lt;span class=&quot;pr-2 hidden group-active:inline-block&quot;&gt;
        Copied!
      &lt;/span&gt;
      &lt;span class=&quot;material-icons&quot;&gt;content_copy&lt;/span&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;This will convert the cells of the heatmap (but not the rest of the plot) into a
single image which can easily be rendered. See this
&lt;a href=&quot;https://stackoverflow.com/questions/27092991/white-lines-in-matplotlibs-pcolor&quot;&gt;StackOverflow question&lt;/a&gt;
for more info.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/heatmap-no-lines.png&quot;&gt;&lt;img src=&quot;https://btjanaka.net/blog/matplotlib-figures/imgs/heatmap-no-lines.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;The heatmap after rasterizing the cells – note there are no more unwanted white lines.&lt;/figcaption&gt;&lt;/figure&gt;
</content>
  </entry>
  <entry>
    <title>Upgrading CMA-ME to CMA-MAE on the Sphere Benchmark</title>
    <link href="https://btjanaka.net/blog/cma_mae/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2023-02-22T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/cma_mae/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/cma_mae.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/cma_mae.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Generating Tom Cruise Images with DQD Algorithms</title>
    <link href="https://btjanaka.net/blog/tom_cruise_dqd/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2023-02-22T08:00:01Z</updated>
    <id>https://btjanaka.net/blog/tom_cruise_dqd/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/tom_cruise_dqd.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/tom_cruise_dqd.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Scaling CMA-MAE on the Sphere Benchmark</title>
    <link href="https://btjanaka.net/blog/scalable_cma_mae/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2023-12-16T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/scalable_cma_mae/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/scalable_cma_mae.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/scalable_cma_mae.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Incorporating Human Feedback into Quality Diversity for Diversified Text-to-Image Generation</title>
    <link href="https://btjanaka.net/blog/qdhf/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2024-03-14T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/qdhf/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/qdhf.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/qdhf.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Exploring Deceptive Mazes with Novelty Search</title>
    <link href="https://btjanaka.net/blog/ns_maze/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2025-06-26T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/ns_maze/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/ns_maze.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/ns_maze.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Orchestrating LLMs to Write Diverse Stories with Quality Diversity through AI Feedback</title>
    <link href="https://btjanaka.net/blog/qdaif/"/>
    <author>
      <name>Bryon Tjanaka</name>
      <uri>https://btjanaka.net/</uri>
    </author>
    <summary>A tutorial in the pyribs library.</summary>
    <updated>2025-08-12T08:00:00Z</updated>
    <id>https://btjanaka.net/blog/qdaif/</id>
    <content type="html">&lt;p&gt;This post was published as a tutorial in the pyribs library. Head over there to
learn more! &lt;a href=&quot;https://docs.pyribs.org/en/stable/tutorials/qdaif.html&quot;&gt;https://docs.pyribs.org/en/stable/tutorials/qdaif.html&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
</feed>
