PageSourceSearch

https://thesearch.space/episodes/6-adam-smith-on-answer-set-programming/

html thesearch.space collected 2026-09-24 18:48:24 UTC 22,627 bytes, 157 lines download raw bytes

1<!DOCTYPE html><html lang="en" data-theme="slack-ochin" data-dark-theme="slack-dark" data-light-theme="slack-ochin" data-theme-mode="light-dark-auto" data-theme-hash="e66e1d5f" style="--theme-font: Crimson Pro;--ec-frm-frameBoxShdCssVal: none;--ec-frm-edTabBrdRad: 0;--ec-frm-edTabBarBrdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);--ec-brdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);"> <head><meta charset="UTF-8"><meta content="width=device-width, initial-scale=1.0" name="viewport"><meta name="generator" content="Astro v5.13.5"><meta name="title" content="#6 - Adam Smith on Answer Set Programming - The Search Space"><meta name="description" content="Adam Smith talks about Answer Set Programming, and how he's used it in game design and other areas."><meta name="author" content="Felix Holmgren"><meta property="og:title" content="#6 - Adam Smith on Answer Set Programming - The Search Space"><meta property="og:description" content="Adam Smith talks about Answer Set Programming, and how he's used it in game design and other areas."><meta property="og:url" content="https://thesearch.space/episodes/6-adam-smith-on-answer-set-programming"><meta property="og:type" content="website"><meta property="og:image" content="https://thesearch.space/social-cards/__default.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#6 - Adam Smith on Answer Set Programming - The Search Space"><meta name="twitter:description" content="Adam Smith talks about Answer Set Programming, and how he's used it in game design and other areas."><meta name="twitter:image" content="https://thesearch.space/social-cards/__default.png"><meta name="keywords" content="logic programming, prolog, podcast, ai, programming languages, symbolic ai, answer set programming, constraint programming, game design"><link rel="canonical" href="https://thesearch.space/episodes/6-adam-smith-on-answer-set-programming"><link rel="sitemap" href="/sitemap-index.xml"><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="manifest" href="/site.webmanifest" crossorigin="use-credentials"><link rel="alternate" type="application/rss+xml" title="The Search Space" href="https://thesearch.space/rss.xml"><title>#6 - Adam Smith on Answer Set Programming - The Search Space</title><style>:root[data-theme="slack-ochin"] {
2--theme-foreground: #000;
3--theme-background: #fff;
4--theme-accent: #000;
5--theme-heading1: #000;
6--theme-heading2: #000;
7--theme-heading3: #000;
8--theme-heading4: #000;
9--theme-heading5: #000;
10--theme-heading6: #000;
11--theme-list: #000;
12--theme-italic: #c792ea;
13--theme-link: #000;
14--theme-separator: #000;
15--theme-note: #6182b8;
16--theme-tip: #91b859;
17--theme-important: #7c4dff;
18--theme-caution: #ffb62c;
19--theme-warning: #e53935;
20--theme-blue: #6182b8;
21--theme-green: #91b859;
22--theme-red: #e53935;
23--theme-yellow: #ffb62c;
24--theme-magenta: #7c4dff;
25--theme-cyan: #39adb5;
26}
27:root[data-theme="slack-dark"] {
28--theme-foreground: #e6e6e6;
29--theme-background: #222222;
30--theme-accent: #569cd6;
31--theme-heading1: #569cd6;
32--theme-heading2: #569cd6;
33--theme-heading3: #569cd6;
34--theme-heading4: #569cd6;
35--theme-heading5: #569cd6;
36--theme-heading6: #569cd6;
37--theme-list: #6796e6;
38--theme-italic: #e6e6e6;
39--theme-link: #e6e6e6;
40--theme-separator: #e6e6e6;
41--theme-note: #2472c8;
42--theme-tip: #0dbc79;
43--theme-important: #bc3fbc;
44--theme-caution: #e5e510;
45--theme-warning: #cd3131;
46--theme-blue: #2472c8;
47--theme-green: #0dbc79;
48--theme-red: #cd3131;
49--theme-yellow: #e5e510;
50--theme-magenta: #bc3fbc;
51--theme-cyan: #11a8cd;
52}</style>
52<script>
53  ;(function loadTheme() {
54    const pageDefaultTheme = document.documentElement.getAttribute('data-theme')
55    const pageDarkTheme = document.documentElement.getAttribute('data-dark-theme')
56    const pageLightTheme = document.documentElement.getAttribute('data-light-theme')
57    const pageThemeHash = document.documentElement.getAttribute('data-theme-hash')
58    if (!pageDefaultTheme || !pageDarkTheme || !pageLightTheme || !pageThemeHash) {
59      throw new Error('Theme attributes are required.')
60    }
61    const getStoredTheme = () => localStorage.getItem('data-theme')
62    let storedTheme = getStoredTheme()
63    const storedThemeHash = localStorage.getItem('data-theme-hash')
64    const themeHashMatches = storedThemeHash === pageThemeHash
65
66    if (!storedTheme || !storedThemeHash || !themeHashMatches) {
67      // Should be the first time loading the website
68      localStorage.setItem('data-theme', pageDefaultTheme)
69      localStorage.setItem('data-theme-hash', pageThemeHash)
70    }
71
72    if (
73      themeHashMatches &&
74      storedTheme &&
75      storedTheme !== 'auto' &&
76      storedTheme !== pageDefaultTheme
77    ) {
78      // The stored theme is different from the default theme, apply it
79      document.documentElement.setAttribute('data-theme', storedTheme)
80    } else if (pageDefaultTheme === 'auto' || storedTheme === 'auto') {
81      // If the default or stored theme is 'auto', apply the system preference
82      const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)')
83      document.documentElement.setAttribute(
84        'data-theme',
85        prefersDarkScheme.matches ? pageDarkTheme : pageLightTheme,
86      )
87      prefersDarkScheme.addEventListener('change', (e) => {
88        if (getStoredTheme() === 'auto') {
89          const newTheme = e.matches ? pageDarkTheme : pageLightTheme
90          document.documentElement.setAttribute('data-theme', newTheme)
91        }
92      })
93    }
94  })()
95</script>
95<link rel="stylesheet" href="/_astro/about.CZr4GseN.css">
96<style>iframe.giscus-frame{margin-block:32px}button[data-astro-cid-a264jexy].scroll-up{transform:translateY(0);opacity:1;transition:transform .3s ease-in-out,opacity .5s cubic-bezier(.4,0,.2,1),background-color .15s cubic-bezier(.4,0,.2,1)}button[data-astro-cid-a264jexy].scroll-up:not(.active){transform:translateY(10px);opacity:0}
97:where([data-astro-image]){object-fit:var(--fit);object-position:var(--pos);height:auto}:where([data-astro-image=full-width]){width:100%}:where([data-astro-image=constrained]){max-width:100%}
98</style>
98<script type="module" src="/_astro/page.V2R8AmkL.js"></script>
98</head> <body class="w-full h-full m-0 bg-background text-foreground" style="--theme-font: Crimson Pro;--ec-frm-frameBoxShdCssVal: none;--ec-frm-edTabBrdRad: 0;--ec-frm-edTabBarBrdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);--ec-brdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);"> <div class="flex flex-col max-w-3xl min-h-screen border-accent/10 m-auto p-3 sm:py-5 sm:px-6 md:py-10" style="--theme-font: Crimson Pro;--ec-frm-frameBoxShdCssVal: none;--ec-frm-edTabBrdRad: 0;--ec-frm-edTabBarBrdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);--ec-brdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);"> <header> <div class="relative flex items-center justify-between bg-accent/10 rounded-xl"> <a id="logo" href="/" class="block px-4 py-1.5 max-w-full no-underline items-center bg-accent text-background font-bold rounded-xl font-sans"> The Search Space </a> <div class="flex items-center gap-3 sm:mr-3"> <site-search class="ms-auto" id="search" data-trailing-slashes="false"> <button class="hover:text-accent flex cursor-pointer items-center justify-center rounded-md" aria-keyshortcuts="Control+K Meta+K" data-open-modal disabled> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-6 text-accent"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg> <span class="sr-only">Open Search</span> </button> <dialog aria-label="search" class="text-foreground! bg-background max-h-5/6 min-h-48 w-7/8 sm:w-5/6 max-w-xl border-double! border-4 border-accent/30 shadow-sm backdrop:backdrop-blur-sm open:flex mx-auto mt-10 sm:mt-16 mb-auto rounded-xl"> <div class="dialog-frame flex grow flex-col gap-4 p-6 pt-6 max-w-full"> <button class="cursor-pointer fixed top-2 right-2 rounded-full" data-close-modal> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-6 text-accent/50"><circle cx="12" cy="12" r="10" /><path d="m15 9-6 6" /><path d="m9 9 6 6" /></svg> </button> <div class="search-container"> <div id="pagefind-search" class="max-w-full"></div> </div> </div> </dialog> </site-search>  
98<script type="module" src="/_astro/Search.astro_astro_type_script_index_0_lang.DgEFfGQ3.js"></script>
98 <button id="theme-change-button" class="block ml-auto" data-light="slack-ochin" data-dark="slack-dark"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="hidden size-6 text-accent" id="icon-light"><circle cx="12" cy="12" r="4" /><path d="M12 2v2" /><path d="M12 20v2" /><path d="m4.93 4.93 1.41 1.41" /><path d="m17.66 17.66 1.41 1.41" /><path d="M2 12h2" /><path d="M20 12h2" /><path d="m6.34 17.66-1.41 1.41" /><path d="m19.07 4.93-1.41 1.41" /></svg> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="hidden size-6 text-accent" id="icon-dark"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" /></svg> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="hidden size-6 text-accent" id="icon-auto"><path d="M12 2v2" /><path d="M13 8.129A4 4 0 0 1 15.873 11" /><path d="m19 5-1.256 1.256" /><path d="M20 12h2" /><path d="M9 8a5 5 0 1 0 7 7 7 7 0 1 1-7-7" /></svg> </button> 
98<script type="module">const t=document.getElementById("theme-change-button"),s=t?.getAttribute("data-light"),a=t?.getAttribute("data-dark"),o=t?.querySelector("#icon-light"),c=t?.querySelector("#icon-dark"),n=t?.querySelector("#icon-auto"),i=d=>{d===s?(o?.classList.remove("hidden"),c?.classList.add("hidden"),n?.classList.add("hidden")):d===a?(o?.classList.add("hidden"),c?.classList.remove("hidden"),n?.classList.add("hidden")):(o?.classList.add("hidden"),c?.classList.add("hidden"),n?.classList.remove("hidden"))};let r=localStorage.getItem("data-theme")||"auto";i(r);t?.addEventListener("click",()=>{const d=localStorage.getItem("data-theme")||a;let e;if(d===s?e=a:d===a?e="auto":e=s,e)if(i(e),localStorage.setItem("data-theme",e),e==="auto"){const l=window.matchMedia("(prefers-color-scheme: dark)");document.documentElement.setAttribute("data-theme",l.matches?a||"auto":s||"auto")}else document.documentElement.setAttribute("data-theme",e)});</script>
98  <nav id="nav-mobile" aria-label="Menu" class="p-0 text-accent sm:hidden"> <button id="nav-mobile-button" class="px-3 py-1 h-full cursor-pointer border-2 rounded-xl bg-background font-sans" type="button" aria-expanded="false" aria-controls="nav-menu-list">
99▾
100</button> <ul id="nav-mobile-list" class="invisible absolute flex flex-col bg-background shadow text-accent border-2 m-0 p-2.5 top-11.5 left-auto right-0 z-50 rounded-xl"> <li class="p-1" aria-expanded="false"> <a class="font-sans" href="/"> Home </a> </li><li class="p-1" aria-expanded="false"> <a class="font-sans" href="/about"> About </a> </li><li class="p-1" aria-expanded="false"> <a class="font-sans underline" href="/episodes"> Episodes </a> </li><li class="p-1" aria-expanded="false"> <a class="font-sans" href="/subscribe"> Subscribe </a> </li> </ul> </nav> </div> </div> <nav aria-label="Menu" class="p-0 mt-4 ml-0.5 text-accent hidden sm:block"> <ul class="flex flex-row text-accent"> <li class="mr-5" aria-expanded="true"> <a class="font-sans" href="/"> Home </a> </li><li class="mr-5" aria-expanded="true"> <a class="font-sans" href="/about"> About </a> </li><li class="mr-5" aria-expanded="true"> <a class="font-sans underline" href="/episodes"> Episodes </a> </li><li class="mr-5" aria-expanded="true"> <a class="font-sans" href="/subscribe"> Subscribe </a> </li> </ul> </nav> </header> 
100<script type="module">const t=document.getElementById("nav-mobile-button"),n=document.getElementById("nav-mobile-list"),o=n?.querySelectorAll("li"),a=i=>{let e=!1;e=!n?.classList.toggle("invisible"),t?.setAttribute("aria-expanded",e?"true":"false"),o?.forEach(l=>{l.setAttribute("aria-expanded",e?"true":"false")})};t?.addEventListener("click",i=>{a()});</script>
100 <main class="flex flex-col py-1" style="--theme-font: Crimson Pro;--ec-frm-frameBoxShdCssVal: none;--ec-frm-edTabBrdRad: 0;--ec-frm-edTabBarBrdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);--ec-brdCol: color-mix(in srgb, var(--theme-foreground), 10%, transparent);">  <article class="max-w-full py-7.5" data-pagefind-body> <div class="md:mx-2"> <h1 id="6-adam-smith-on-answer-set-programming" class="mb-2 tracking-tight text-4xl/10 pb-3 border-b-6
101        md:mb-4 md:leading-16 md:border-b-10 md:text-6xl md:pb-8"> #6 - Adam Smith on Answer Set Programming </h1> <div class="my-2 mb-12 py-2"> <p class="text-base text-foreground/80"> February 15, 2024  • 73 Minutes </p> <div class="mt-2 flex flex-wrap gap-2"> <span class="text-xs font-mono bg-accent/10 text-accent px-2 py-1 rounded"> logic programming </span><span class="text-xs font-mono bg-accent/10 text-accent px-2 py-1 rounded"> answer set programming </span><span class="text-xs font-mono bg-accent/10 text-accent px-2 py-1 rounded"> constraint programming </span><span class="text-xs font-mono bg-accent/10 text-accent px-2 py-1 rounded"> game design </span> </div> </div> </div> <div class="my-8"> <iframe width="100%" height="180" frameborder="no" scrolling="no" seamless src="https://share.transistor.fm/e/50769725"></iframe> </div> <div class="mb-5 prose"> <p>Adam Smith talks about Answer Set Programming, and how he’s used it in game design, information visualization, and other areas.</p>
102<h2 id="show-notes"><a href="#show-notes">Show notes</a></h2>
103<p><a href="https://www.cs.uni-potsdam.de/~torsten/" rel="noreferrer noopener" target="_blank">Torsten Schaub at Potsdam University</a></p>
104<p>Several of his presentations contain the formula:</p>
105<p><strong>ASP = DB + LP + KR + SMT^n</strong></p>
106<ul>
107<li>ASP: Answer Set Programming</li>
108<li>DB: Database</li>
109<li>LP: Logic Programming</li>
110<li>KR: Knowledge Representation</li>
111<li>SMT: <a href="https://en.wikipedia.org/wiki/Satisfiability_modulo_theories" rel="noreferrer noopener" target="_blank">SAT Modulo Theories</a></li>
112</ul>
113<p>SAT solver: <a href="https://en.wikipedia.org/wiki/SAT_solver" rel="noreferrer noopener" target="_blank">Boolean Satisfiability</a></p>
114<blockquote>
115<p>this refraction game that I had made a puzzle generator for</p>
116</blockquote>
117<p>Described in <a href="https://adamsmith.as/dissertation/" rel="noreferrer noopener" target="_blank">Adam’s dissertation</a>.</p>
118<blockquote>
119<p>the Potassco tools from University of Potsdam</p>
120</blockquote>
121<p><a href="https://potassco.org/" rel="noreferrer noopener" target="_blank">potassco.org</a></p>
122<blockquote>
123<p>A book called Procedural Content Generation in Games</p>
124</blockquote>
125<p><a href="https://www.pcgbook.com/" rel="noreferrer noopener" target="_blank">www.pcgbook.com</a></p>
126<blockquote>
127<p>There’s this idea due to Kate Compton … of the 10,000 bowls of oatmeal problem</p>
128</blockquote>
129<p><a href="http://www.galaxykate.com/blog/generator.html" rel="noreferrer noopener" target="_blank">http://www.galaxykate.com/blog/generator.html</a></p>
130<blockquote>
131<p>We modeled a design space of information visualizations, line plots and scatter plots and bar charts</p>
132</blockquote>
133<p><a href="https://adamsmith.as/papers/08440847.pdf" rel="noreferrer noopener" target="_blank">“Formalizing Visualization Design Knowledge as Constraints: Actionable and Extensible Models in Draco”</a></p>
134<blockquote>
135<p>a Python library called Clorm .. so that you can define your problem instances with Python objects</p>
136</blockquote>
137<p><a href="https://github.com/potassco/clorm" rel="noreferrer noopener" target="_blank">github.com/potassco/clorm</a></p>
138<blockquote>
139<p>the concept of <strong>elaboration tolerance</strong> that when someone gives you some clarification about how your domain works, can you incorporate that change by just adding more code to add more choices or more constraints?</p>
140</blockquote>
141<p>John McCarthy’s <a href="http://jmc.stanford.edu/articles/elaboration.html" rel="noreferrer noopener" target="_blank">paper on elaboration tolerance</a></p>
142<blockquote>
143<p>a paper from Google DeepMind … describing a system called the Apperception Engine</p>
144</blockquote>
145<p><a href="https://arxiv.org/abs/1910.02227" rel="noreferrer noopener" target="_blank">“Making sense of sensory input”</a>, Evans et al</p>
146<blockquote>
147<p>taught a class called <strong>Applied ASP</strong> a few years ago</p>
148</blockquote>
149<p>Lecture slides, programming assignments, reading assignments here: <a href="https://canvas.ucsc.edu/courses/1338" rel="noreferrer noopener" target="_blank">canvas.ucsc.edu/courses/1338</a></p>
150<blockquote>
151<p>Once you want to write a program that’s more than 30 lines long, how do you profile it? How do you test it? How do you deploy it?</p>
152</blockquote>
153<p>Slides from a talk about Adam’s test automation framework: <a href="https://docs.google.com/presentation/d/1iJr9ieR9ad9hRetFi0vjFe6Uw8-6WxTgernaguI_QtY" rel="noreferrer noopener" target="_blank">Unit Test Automation for ASP with Ansunit</a></p>
154<p>Try ASP from your browser: <a href="https://potassco.org/clingo/run/" rel="noreferrer noopener" target="_blank">https://potassco.org/clingo/run/</a></p> </div> </article> <div class="flex flex-col sm:flex-row items-center justify-around sm:gap-5 max-w-full mb-6 py-10 bg-accent/8 p-4 rounded-xl"> <img src="/_astro/felix-holmgren-portrait.CiC7cI8h_1JiceV.webp" srcset="/_astro/felix-holmgren-portrait.CiC7cI8h_262FNn.webp 288w" alt="Felix Holmgren" loading="lazy" decoding="async" fetchpriority="auto" width="144" height="144" class="rounded-full border-8 border-accent/15 size-36 aspect-square box-content shrink-0"> <div> <div class="m-4 max-w-full prose">  <p>Thanks for listening! Feel free to check out other episodes or contact me via the social links in the footer. Or go <a href="https://ko-fi.com/searchspace" rel="noreferrer noopener" target="_blank">buy me a coffee</a>!</p>  </div> </div> </div><button hidden class="scroll-up size-11 fixed flex items-center justify-center bg-background z-100 bottom-3 right-3 rounded-full border-2 border-accent/20 hover:bg-accent/10 md:size-12 md:bottom-5 md:right-5 lg:size-13 lg:bottom-6 lg:right-6" data-astro-cid-a264jexy> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-accent/50 
154size-8 lg:size-9" data-astro-cid-a264jexy="true"><path d="m18 15-6-6-6 6" /></svg> </button> 
154<script type="module">function c(t,n,r){const e=o=>{o.target===t&&o.propertyName===n&&(t.setAttribute("hidden","true"),t.removeEventListener("transitionend",e))};return{show(){t.removeEventListener("transitionend",e),t.removeAttribute("hidden"),t.offsetHeight,t.classList.add(r)},hide(){t.addEventListener("transitionend",e),t.classList.remove(r)}}}function d(){const t=document.querySelector("button.scroll-up"),n=document.querySelector("h1"),r=n?n.offsetTop:0;if(!t){console.warn("Scroll up button not found in the document.");return}t.addEventListener("click",()=>{window.scrollTo({top:r,behavior:"smooth"})});const e=document.querySelector("article div.prose");if(!e){console.warn("Prose element not found in the article.");return}const o=c(t,"opacity","active");new IntersectionObserver(i=>{i.forEach(s=>{s.isIntersecting?o.show():o.hide()})},{rootMargin:"0px 0px -95% 0px"}).observe(e)}d();</script>
154   </main> <footer class="mt-auto pt-9 md:pt-11 grow-0 flex flex-col gap-6 items-center justify-between max-w-full text-foreground/80"> <div class="flex w-full max-w-md items-center justify-between px-4">  <a href="https://mathstodon.xyz/@thesearchspace" target="_blank" rel="noopener noreferrer" class="social-link"> <span class="sr-only">Mastodon</span> <svg width="24" height="24" viewBox="0 0 24 24" class="size-7"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M15.5 21.5c-10.5 2.5 -12.5 -2.5 -12.5 -8.5v-3c0 -6 2.5 -7 7 -7h4c4.5 0 7 1.5 7 5.5v4c0 6.5 -10 4 -13.5 4c-1 0 -1.5 7 8 5Z" /><path d="M7 13.5l0 -5.5c0 0 0.5 -2 2.5 -2c2 0 2.5 2 2.5 2l0 2.5l0 -2.5c0 0 0.5 -2 2.5 -2c2 0 2.5 2 2.5 2l0 5.5" /></g></svg> </a>  <a href="https://www.linkedin.com/in/felixholmgren" target="_blank" rel="noopener noreferrer" class="social-link"> <span class="sr-only">LinkedIn</span> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-7"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" /><rect width="4" height="12" x="2" y="9" /><circle cx="4" cy="4" r="2" /></svg> </a>  <a href="mailto:[email protected]" target="_blank" rel="noopener noreferrer" class="social-link"> <span class="sr-only">Email</span> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-7"><path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" /><rect x="2" y="4" width="20" height="16" rx="2" /></svg> </a> <a href="/rss.xml" class="social-link"> <span class="sr-only">RSS</span> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-7"><path d="M4 11a9 9 0 0 1 9 9" /><path d="M4 4a16 16 0 0 1 16 16" /><circle cx="5" cy="19" r="1" /></svg> </a> </div> <div class="flex flex-col md:flex-row flex-wrap flex-1 items-center justify-center"> <span class="my-1"> Felix Holmgren © 2025
155</span> <span class="mx-5 hidden md:block"> :: </span> <span class="my-1">
156Powered by <a class="underline" target="_blank" rel="noopener noreferrer" href="https://astro.build">Astro</a>
157& <a class="underline" target="_blank" rel="noopener noreferrer" href="https://github.com/stelcodes/multiterm-astro">MultiTerm</a> </span> </div> </footer> </div> </body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.