{
  "id": 619321,
  "title": "7th place write-up: LogicLynx",
  "content": "<h1>Google Code Golf Championship 2025 Solution Report</h1>\n<h2>1. Introduction</h2>\n<p>This article reports on our approach to the Google Code Golf Championship 2025. In this competition, we had to perform code golf in Python for 400 ARC-AGI format problems, requiring the shortest possible code for each problem.</p>\n<p>With the constraint of a maximum team size of 5 people, we determined that individually optimizing 400 problems would be impractical, and adopted a strategy centered on automating code compression using generative AI.</p>\n<h2>2. Semi-Automated Code Shortening with LLMs</h2>\n<h3>2.1 Automation with Codex</h3>\n<p>To improve code shortening efficiency, we utilized <a href=\"https://chatgpt.com/codex\" target=\"_blank\">Codex (Web version)</a>. The browser version of Codex has the capability to output up to 4 results for a single prompt input. While multiple generation results typically create review costs in normal development, in code golf there is a clear evaluation criterion where \"shorter code\" = \"better code\", so review is completed simply by selecting the shortest among the 4 outputs.</p>\n<h3>2.2 Semi-Automated Workflow</h3>\n<p>Rather than complete automation, we achieved semi-automation by combining the following elements:</p>\n<ul>\n<li><p><strong>Automated processes</strong></p>\n<ul>\n<li>Prompt generation</li>\n<li>PR merge processing</li></ul></li>\n<li><p><strong>Manual processes</strong></p>\n<ul>\n<li>Prompt input</li>\n<li>Correctness review</li></ul></li>\n</ul>\n<h3>2.3 Context Provided to Generative AI</h3>\n<p>To achieve effective code golf, we provided three types of context to the generative AI.</p>\n<h4>2.3.1 General Code Golf Knowledge</h4>\n<p>In the early stages of the competition, we collected general techniques from existing resources such as <a href=\"https://code.golf/wiki/langs/python\" target=\"_blank\">code.golf/wiki/langs/python</a> and incorporated them into prompts.</p>\n<h4>2.3.2 Knowledge Accumulated Through Competition</h4>\n<p>As the competition progressed and we became able to produce near-optimal code, we had the generative AI analyze those codes to extract generally applicable techniques and managed them as knowledge.</p>\n<h4>2.3.3 Work History Recording</h4>\n<p>Codex performs work based on knowledge described in <code>AGENTS.md</code> and prompts. To prevent repeated suggestions of the same shortening ideas when sending multiple prompts for the same problem, we managed a memo for each task. By recording experimental content for shortening and instructing not to re-execute experiments written in the memo, we achieved efficient exploration. When code was shortened, past experiments could become effective, so we cleared the memo each time.</p>\n<h3>2.4 Prompt Design Innovations</h3>\n<h4>2.4.1 XML Structure Description</h4>\n<p>Based on knowledge that XML structure is more understandable than Markdown, prompts were written in XML structure.</p>\n<h4>2.4.2 Work Termination Conditions</h4>\n<p>To have Codex work for extended periods, we set the termination condition as \"shorten by at least 1 character from the current code length\".</p>\n<h2>3. Implementation Techniques Collection</h2>\n<h3>3.1 Recursive Processing</h3>\n<h4>3.1.1 Overview</h4>\n<p>For several tasks, an approach of repeatedly changing each cell's color based on information from surrounding cells was effective. Below, we denote the 2D list representing the input grid as <code>g</code>.</p>\n<h4>3.1.2 Utilizing List Comprehensions</h4>\n<p>Python's list comprehensions allow concise description of update operations for each cell. While double for-loops can achieve similar processing, list comprehensions are expressions, so the updated grid is obtained as a return value, which is compatible with code golf.</p>\n<p>However, when updating local variables simultaneously with the grid, or performing complex branching or repetition with if/while statements, list comprehensions are difficult to implement or increase character count, requiring process simplification.</p>\n<h4>3.1.3 Recursion with Lambda Expressions</h4>\n<p>In many problems, the answer is obtained by repeating the same list comprehension multiple times. Since list comprehensions are expressions, combining them with lambda expressions enables recursive processing without writing unnecessary characters like return.</p>\n<pre><code>p= g,i=repetition_count-:-i*g  p(list_comprehension_on_g,i-)\n</code></pre>\n<h4>3.1.4 Rotation and Transposition</h4>\n<p>In many problems, updating each cell requires referencing adjacent cells in four directions, or rows and columns. When conditions for each direction are independent, it's more efficient to look at only one direction, perform updates, and repeat rotation or transposition to obtain the answer.</p>\n<ul>\n<li>Transposition: <code>[*zip(*g)]</code></li>\n<li>Rotation: <code>[*zip(*g[::-1])]</code></li>\n</ul>\n<p>In most cases, recursion combining these operations is shorter than naively writing processing for all 4 directions.</p>\n<p><strong>Task 2 Implementation Example:</strong></p>\n<pre><code>p= g,i=:-i*g [(d:=)[d:=c&amp;-&gt;&gt;d (i&lt;)* c  r] r  (*p(g,i-)[::-])]\n</code></pre>\n<h4>3.1.5 Pseudo-Recursion Using eval</h4>\n<p>Some problems require performing different update processes in two stages. Normally, this would combine three lambda expressions as follows, but should be avoided due to character count:</p>\n<pre><code>f= g,i=repetition_count-:-i*g  f(processing1_on_g,i-)\nh= g,i=repetition_count-:-i*g  h(processing2_on_g,i-)\np= g:h(f(g))\n</code></pre>\n<p>This problem can be solved using the <code>eval</code> function. Python's <code>eval</code> executes a given string as an expression and returns the result. Also, string repetition in Python can be expressed by multiplication of string and number. Using these, list comprehensions can be expanded directly without using lambda expressions.</p>\n<p><strong>Task 196 Implementation Example (using lambda):</strong></p>\n<pre><code>f= g,i=:-i*g  f([*(*((c|v&amp;-c  c,v  (r,(,*r))) r  g[::-]))],i-)\nh= g,i=:-i*g  h([*(*((c|v-&amp;  c,v  (r,(,*r))) r  g[::-]))],i-)\np= g:((h(f(g))).replace(*))\n</code></pre>\n<p>When expanded:</p>\n<pre><code>p= g:(((*+*++*+*)).replace(*))\n</code></pre>\n<p>Consolidating common processing, since <code>[::-1]))]</code> is exactly the same, it can be <code>\"[::-1]))]\"*56</code>. Also, using the format specifier <code>%s</code> enables further shortening:</p>\n<pre><code>p= g,s=:(((s%*+s%*++*)).replace(*))\n</code></pre>\n<p>Final shortened version:</p>\n<pre><code>p= g,s=:(s%+s%*+s%*++*)\n</code></pre>\n<h3>3.2 Regular Expressions</h3>\n<h4>3.2.1 Overview</h4>\n<p>Some tasks can be solved correctly just by replacing grids or strings with Python's <code>replace</code> or <code>re.sub</code>. Below, we denote the input grid or string as <code>g</code>.</p>\n<h4>3.2.2 Combination with Rotation and Transposition</h4>\n<p>In grid processing, rotation or transposition can be combined with regular expression replacement.</p>\n<p><strong>Template performing 16 replacements while rotating:</strong></p>\n<pre><code> re;p= g,k=:k  p((re.sub(,,([*(*g[::-])]))),k-) g\n</code></pre>\n<p>Improved version:</p>\n<pre><code> re;p= g,k=:-k*g  p((re.sub(,,([*(*g[::-])]))),k-)\n</code></pre>\n<h4>3.2.3 Vertical Pattern Recognition</h4>\n<p>Depending on the task, the size of <code>g</code> may be fixed regardless of test cases. When the number of horizontal cells is n, there are 3n+1 characters between a cell and the cell below it. Using this, problems like \"detecting L-shapes\" can be addressed.</p>\n<p><strong>Task 081 Implementation Example:</strong></p>\n<pre><code> re;p= g,k=:-k*g [*(*(re.sub(,,(p(g,k-)[::-]))))]\n</code></pre>\n<p>Since the width of Task 081 is 7, the pattern <code>8.{19}8</code> represents \"an 8 cell with another 8 immediately below-left\". This code performs the operation \"replace with 1 any 0 cell that has immediately to the right 'an 8 cell with an 8 below-left'\" while repeating 90-degree rotations.</p>\n<h3>3.3 Full Grid Search</h3>\n<h4>3.3.1 Basic Approach</h4>\n<p>To process all cells in an a×b rectangular region, normally a double loop is used:</p>\n<pre><code> i  (a):\n     j  (b):\n        \n</code></pre>\n<h4>3.3.2 Utilizing Chinese Remainder Theorem</h4>\n<p>When processing order doesn't matter and gcd(a,b)=1, the Chinese Remainder Theorem can be used to write with a single loop:</p>\n<pre><code> k  (a*b):\n    \n</code></pre>\n<p>This is effective when combined with pseudo-recursion using <code>exec</code>.</p>\n<h4>3.3.3 Handling gcd(a,b)≠1 Cases</h4>\n<p>Even when the condition gcd(a,b)=1 is not satisfied, this technique can be applied with some ingenuity.</p>\n<p><strong>Task 074 Implementation Example:</strong></p>\n<pre><code>k=;p= g:(*) g\n</code></pre>\n<p>This problem requires searching a 30×30 board, but since they are not coprime, modulo is first taken with 31 and 30, then taken again with 30.</p>\n<p><strong>Task 240 Implementation Example:</strong></p>\n<pre><code>k=;p= g:(*) g\n</code></pre>\n<p>This problem only needs to modify cells where both coordinates are odd. By narrowing the 19×19 board search to 19×18, gcd(a,b)=1 is satisfied, and by incrementing k by 2, the required number of repetitions is kept under 1000, saving 1 byte. This technique achieved a 10-byte reduction compared to the shortest code published by other teams.</p>\n<h3>3.4 Compression Processing</h3>\n<h4>3.4.1 Overview</h4>\n<p>Some problems result in byte counts exceeding 200 bytes even with code golf alone. For such problems, representing compressed code as a byte string, then decompressing and executing it, leads to shorter overall byte count.</p>\n<h4>3.4.2 Compression Method</h4>\n<h5>Compression Software Used</h5>\n<p>In this competition, only Python standard library imports are permitted. Therefore, compression software must be decompressible by Python's standard library. We adopted <strong>zopfli</strong>.</p>\n<p>zopfli supports decompression by zlib, and while compression takes longer than other software, the compression ratio is several percent higher. Since compression time is negligible in this case, the drawback is not an issue.</p>\n<h5>Writing Compression Results</h5>\n<p>While zopfli's compression results are byte strings, using base64 encoding or hexadecimal notation diminishes compression benefits. By interpreting the byte string as <strong>ISO-8859-1 (Latin-1)</strong>, it can be represented as a string.</p>\n<p>Control characters, newlines, and quotation marks may occur:</p>\n<ul>\n<li><strong>Null character and CR</strong>: Require escape processing as they prevent proper decoding</li>\n<li><strong>Newlines</strong>: Can avoid escaping using triple quotes, but escaping is often shorter</li>\n<li><strong>Quotation marks</strong>: Escape whichever appears less in the string, and enclose with that quotation mark</li>\n</ul>\n<h4>3.4.3 Execution Method</h4>\n<p>To execute compressed programs, the following processing is required:</p>\n<ol>\n<li>Interpret the compression result string as a byte string</li>\n<li>Decompress with the byte string as input</li>\n<li>Interpret and execute the decompressed result as a program</li>\n</ol>\n<p>Implementation methods for each step:</p>\n<ul>\n<li><strong>String→Byte string</strong>: Specify <code>'L1'</code> in the second argument of <code>bytes</code> function to interpret as Latin-1</li>\n<li><strong>Decompression</strong>: Import <code>zlib</code> and execute <code>decompress</code> function</li>\n<li><strong>Execution</strong>: Pass decompression result to <code>exec</code> function</li>\n</ul>\n<p>Also, since the program file must be encoded in Latin-1, write <code>#coding:L1</code> on the first line.</p>\n<p><strong>Execution Program Example:</strong></p>\n<pre><code>\n zlib;(zlib.decompress((,)))\n</code></pre>\n<h4>3.4.4 Code Efficiency Optimization</h4>\n<h5>Expanding Identical Processing</h5>\n<p>Even if the original code length is short, the compressed code won't necessarily be short. zlib's Deflate algorithm includes processing (LZSS) that compresses previously appeared substrings into information about their position and length.</p>\n<p>For some code containing repetitive processing, naively writing similar statements consecutively rather than cleverly reducing original code character count can result in shorter compressed code. Particularly for <strong>Task 086</strong>, expanding complex loops into simple, character-heavy loops produced shorter code.</p>\n<h5>Variable Name Search</h5>\n<p>In code compression, there is room for optimization in which alphabet letters to assign as variable names. We performed variable name searches for all tasks where compression was effective.</p>\n<p>The method is simple: first extract variable name portions from code, take one correspondence from random single-letter alphabet to single-letter alphabet, and simultaneously replace variable names. Then perform compression and correctness verification, and adopt if compression effectiveness improves without issues.</p>\n<p>This method achieved <strong>improvements of about 2-12 bytes</strong> for each task where compression was effective.</p>\n<h2>4. Conclusion</h2>\n<p>In this competition, we tackled large-scale code golf of 400 problems through semi-automation utilizing LLMs and combinations of diverse implementation techniques. The following points were particularly effective:</p>\n<ul>\n<li>Multiple solution generation and automatic selection with Codex</li>\n<li>Avoiding duplicate exploration through work history management</li>\n<li>Technical techniques including recursive processing, regular expressions, full grid search, and compression processing</li>\n<li>Optimization methods such as variable name search</li>\n</ul>\n<p>By combining these approaches, we achieved efficient and effective code golf.</p>",
  "comments": [
    {
      "id": 3323425,
      "author_name": "Sivalinga Kumar",
      "author_url": "",
      "post_date": "2025-11-14T07:45:36.540000",
      "content": "<p>It's compelling to see how generative AI is becoming a central tool in code golf competitions. Your team's success in automating the compression process challenges the traditional view of code golf as a purely human-driven puzzle. I'm interested to hear your thoughts on where this trend might lead. Will future competitions need to adapt their rules or problem types to account for highly effective LLM-based strategies?</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3335862,
          "author_name": "nesya",
          "author_url": "",
          "post_date": "2025-11-18T07:55:48.343000",
          "content": "<p>I think one reason generative AI worked so well is simply the sheer number of problems: with so many tasks, AI can repeatedly apply its strength—spotting tiny optimizations that humans often overlook. Task020 is a good example: almost the entire solution came from AI-driven improvement loops with virtually no human intervention, yet it still achieved the shortest standalone code.</p>\n<p>That said, the AI clearly had weaknesses. For tasks that use regular expressions, humans still had to design the overall approach because the model struggled there. Task240 was more of a hybrid effort: the core idea came from a human, but the AI contributed meaningful refinements—like the 1-byte k+=2 improvement—so it really was a two-person (or human–AI) collaboration.</p>\n<p>Judging from the write-ups of the top three teams, it seems they barely used AI at all. So at the moment, AI is a very powerful tool that can surpass humans in certain areas, but it still can’t outperform true specialists across the board.</p>\n<p>All of our team members actively do competitive programming, and in that field generative AI has already become quite strong (though still slightly behind the very top competitors). Some competitions have even started introducing rules to regulate or prohibit AI use. Given how fast these models are improving, it’s hard to predict what the landscape will look like in the future.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    }
  ],
  "comment_count": 2,
  "messages": [
    {
      "id": 3322994,
      "postDate": "2025-11-13T23:52:00.790Z",
      "content": "<h1>Google Code Golf Championship 2025 Solution Report</h1>\n<h2>1. Introduction</h2>\n<p>This article reports on our approach to the Google Code Golf Championship 2025. In this competition, we had to perform code golf in Python for 400 ARC-AGI format problems, requiring the shortest possible code for each problem.</p>\n<p>With the constraint of a maximum team size of 5 people, we determined that individually optimizing 400 problems would be impractical, and adopted a strategy centered on automating code compression using generative AI.</p>\n<h2>2. Semi-Automated Code Shortening with LLMs</h2>\n<h3>2.1 Automation with Codex</h3>\n<p>To improve code shortening efficiency, we utilized <a href=\"https://chatgpt.com/codex\" target=\"_blank\">Codex (Web version)</a>. The browser version of Codex has the capability to output up to 4 results for a single prompt input. While multiple generation results typically create review costs in normal development, in code golf there is a clear evaluation criterion where \"shorter code\" = \"better code\", so review is completed simply by selecting the shortest among the 4 outputs.</p>\n<h3>2.2 Semi-Automated Workflow</h3>\n<p>Rather than complete automation, we achieved semi-automation by combining the following elements:</p>\n<ul>\n<li><p><strong>Automated processes</strong></p>\n<ul>\n<li>Prompt generation</li>\n<li>PR merge processing</li></ul></li>\n<li><p><strong>Manual processes</strong></p>\n<ul>\n<li>Prompt input</li>\n<li>Correctness review</li></ul></li>\n</ul>\n<h3>2.3 Context Provided to Generative AI</h3>\n<p>To achieve effective code golf, we provided three types of context to the generative AI.</p>\n<h4>2.3.1 General Code Golf Knowledge</h4>\n<p>In the early stages of the competition, we collected general techniques from existing resources such as <a href=\"https://code.golf/wiki/langs/python\" target=\"_blank\">code.golf/wiki/langs/python</a> and incorporated them into prompts.</p>\n<h4>2.3.2 Knowledge Accumulated Through Competition</h4>\n<p>As the competition progressed and we became able to produce near-optimal code, we had the generative AI analyze those codes to extract generally applicable techniques and managed them as knowledge.</p>\n<h4>2.3.3 Work History Recording</h4>\n<p>Codex performs work based on knowledge described in <code>AGENTS.md</code> and prompts. To prevent repeated suggestions of the same shortening ideas when sending multiple prompts for the same problem, we managed a memo for each task. By recording experimental content for shortening and instructing not to re-execute experiments written in the memo, we achieved efficient exploration. When code was shortened, past experiments could become effective, so we cleared the memo each time.</p>\n<h3>2.4 Prompt Design Innovations</h3>\n<h4>2.4.1 XML Structure Description</h4>\n<p>Based on knowledge that XML structure is more understandable than Markdown, prompts were written in XML structure.</p>\n<h4>2.4.2 Work Termination Conditions</h4>\n<p>To have Codex work for extended periods, we set the termination condition as \"shorten by at least 1 character from the current code length\".</p>\n<h2>3. Implementation Techniques Collection</h2>\n<h3>3.1 Recursive Processing</h3>\n<h4>3.1.1 Overview</h4>\n<p>For several tasks, an approach of repeatedly changing each cell's color based on information from surrounding cells was effective. Below, we denote the 2D list representing the input grid as <code>g</code>.</p>\n<h4>3.1.2 Utilizing List Comprehensions</h4>\n<p>Python's list comprehensions allow concise description of update operations for each cell. While double for-loops can achieve similar processing, list comprehensions are expressions, so the updated grid is obtained as a return value, which is compatible with code golf.</p>\n<p>However, when updating local variables simultaneously with the grid, or performing complex branching or repetition with if/while statements, list comprehensions are difficult to implement or increase character count, requiring process simplification.</p>\n<h4>3.1.3 Recursion with Lambda Expressions</h4>\n<p>In many problems, the answer is obtained by repeating the same list comprehension multiple times. Since list comprehensions are expressions, combining them with lambda expressions enables recursive processing without writing unnecessary characters like return.</p>\n<pre><code>p= g,i=repetition_count-:-i*g  p(list_comprehension_on_g,i-)\n</code></pre>\n<h4>3.1.4 Rotation and Transposition</h4>\n<p>In many problems, updating each cell requires referencing adjacent cells in four directions, or rows and columns. When conditions for each direction are independent, it's more efficient to look at only one direction, perform updates, and repeat rotation or transposition to obtain the answer.</p>\n<ul>\n<li>Transposition: <code>[*zip(*g)]</code></li>\n<li>Rotation: <code>[*zip(*g[::-1])]</code></li>\n</ul>\n<p>In most cases, recursion combining these operations is shorter than naively writing processing for all 4 directions.</p>\n<p><strong>Task 2 Implementation Example:</strong></p>\n<pre><code>p= g,i=:-i*g [(d:=)[d:=c&amp;-&gt;&gt;d (i&lt;)* c  r] r  (*p(g,i-)[::-])]\n</code></pre>\n<h4>3.1.5 Pseudo-Recursion Using eval</h4>\n<p>Some problems require performing different update processes in two stages. Normally, this would combine three lambda expressions as follows, but should be avoided due to character count:</p>\n<pre><code>f= g,i=repetition_count-:-i*g  f(processing1_on_g,i-)\nh= g,i=repetition_count-:-i*g  h(processing2_on_g,i-)\np= g:h(f(g))\n</code></pre>\n<p>This problem can be solved using the <code>eval</code> function. Python's <code>eval</code> executes a given string as an expression and returns the result. Also, string repetition in Python can be expressed by multiplication of string and number. Using these, list comprehensions can be expanded directly without using lambda expressions.</p>\n<p><strong>Task 196 Implementation Example (using lambda):</strong></p>\n<pre><code>f= g,i=:-i*g  f([*(*((c|v&amp;-c  c,v  (r,(,*r))) r  g[::-]))],i-)\nh= g,i=:-i*g  h([*(*((c|v-&amp;  c,v  (r,(,*r))) r  g[::-]))],i-)\np= g:((h(f(g))).replace(*))\n</code></pre>\n<p>When expanded:</p>\n<pre><code>p= g:(((*+*++*+*)).replace(*))\n</code></pre>\n<p>Consolidating common processing, since <code>[::-1]))]</code> is exactly the same, it can be <code>\"[::-1]))]\"*56</code>. Also, using the format specifier <code>%s</code> enables further shortening:</p>\n<pre><code>p= g,s=:(((s%*+s%*++*)).replace(*))\n</code></pre>\n<p>Final shortened version:</p>\n<pre><code>p= g,s=:(s%+s%*+s%*++*)\n</code></pre>\n<h3>3.2 Regular Expressions</h3>\n<h4>3.2.1 Overview</h4>\n<p>Some tasks can be solved correctly just by replacing grids or strings with Python's <code>replace</code> or <code>re.sub</code>. Below, we denote the input grid or string as <code>g</code>.</p>\n<h4>3.2.2 Combination with Rotation and Transposition</h4>\n<p>In grid processing, rotation or transposition can be combined with regular expression replacement.</p>\n<p><strong>Template performing 16 replacements while rotating:</strong></p>\n<pre><code> re;p= g,k=:k  p((re.sub(,,([*(*g[::-])]))),k-) g\n</code></pre>\n<p>Improved version:</p>\n<pre><code> re;p= g,k=:-k*g  p((re.sub(,,([*(*g[::-])]))),k-)\n</code></pre>\n<h4>3.2.3 Vertical Pattern Recognition</h4>\n<p>Depending on the task, the size of <code>g</code> may be fixed regardless of test cases. When the number of horizontal cells is n, there are 3n+1 characters between a cell and the cell below it. Using this, problems like \"detecting L-shapes\" can be addressed.</p>\n<p><strong>Task 081 Implementation Example:</strong></p>\n<pre><code> re;p= g,k=:-k*g [*(*(re.sub(,,(p(g,k-)[::-]))))]\n</code></pre>\n<p>Since the width of Task 081 is 7, the pattern <code>8.{19}8</code> represents \"an 8 cell with another 8 immediately below-left\". This code performs the operation \"replace with 1 any 0 cell that has immediately to the right 'an 8 cell with an 8 below-left'\" while repeating 90-degree rotations.</p>\n<h3>3.3 Full Grid Search</h3>\n<h4>3.3.1 Basic Approach</h4>\n<p>To process all cells in an a×b rectangular region, normally a double loop is used:</p>\n<pre><code> i  (a):\n     j  (b):\n        \n</code></pre>\n<h4>3.3.2 Utilizing Chinese Remainder Theorem</h4>\n<p>When processing order doesn't matter and gcd(a,b)=1, the Chinese Remainder Theorem can be used to write with a single loop:</p>\n<pre><code> k  (a*b):\n    \n</code></pre>\n<p>This is effective when combined with pseudo-recursion using <code>exec</code>.</p>\n<h4>3.3.3 Handling gcd(a,b)≠1 Cases</h4>\n<p>Even when the condition gcd(a,b)=1 is not satisfied, this technique can be applied with some ingenuity.</p>\n<p><strong>Task 074 Implementation Example:</strong></p>\n<pre><code>k=;p= g:(*) g\n</code></pre>\n<p>This problem requires searching a 30×30 board, but since they are not coprime, modulo is first taken with 31 and 30, then taken again with 30.</p>\n<p><strong>Task 240 Implementation Example:</strong></p>\n<pre><code>k=;p= g:(*) g\n</code></pre>\n<p>This problem only needs to modify cells where both coordinates are odd. By narrowing the 19×19 board search to 19×18, gcd(a,b)=1 is satisfied, and by incrementing k by 2, the required number of repetitions is kept under 1000, saving 1 byte. This technique achieved a 10-byte reduction compared to the shortest code published by other teams.</p>\n<h3>3.4 Compression Processing</h3>\n<h4>3.4.1 Overview</h4>\n<p>Some problems result in byte counts exceeding 200 bytes even with code golf alone. For such problems, representing compressed code as a byte string, then decompressing and executing it, leads to shorter overall byte count.</p>\n<h4>3.4.2 Compression Method</h4>\n<h5>Compression Software Used</h5>\n<p>In this competition, only Python standard library imports are permitted. Therefore, compression software must be decompressible by Python's standard library. We adopted <strong>zopfli</strong>.</p>\n<p>zopfli supports decompression by zlib, and while compression takes longer than other software, the compression ratio is several percent higher. Since compression time is negligible in this case, the drawback is not an issue.</p>\n<h5>Writing Compression Results</h5>\n<p>While zopfli's compression results are byte strings, using base64 encoding or hexadecimal notation diminishes compression benefits. By interpreting the byte string as <strong>ISO-8859-1 (Latin-1)</strong>, it can be represented as a string.</p>\n<p>Control characters, newlines, and quotation marks may occur:</p>\n<ul>\n<li><strong>Null character and CR</strong>: Require escape processing as they prevent proper decoding</li>\n<li><strong>Newlines</strong>: Can avoid escaping using triple quotes, but escaping is often shorter</li>\n<li><strong>Quotation marks</strong>: Escape whichever appears less in the string, and enclose with that quotation mark</li>\n</ul>\n<h4>3.4.3 Execution Method</h4>\n<p>To execute compressed programs, the following processing is required:</p>\n<ol>\n<li>Interpret the compression result string as a byte string</li>\n<li>Decompress with the byte string as input</li>\n<li>Interpret and execute the decompressed result as a program</li>\n</ol>\n<p>Implementation methods for each step:</p>\n<ul>\n<li><strong>String→Byte string</strong>: Specify <code>'L1'</code> in the second argument of <code>bytes</code> function to interpret as Latin-1</li>\n<li><strong>Decompression</strong>: Import <code>zlib</code> and execute <code>decompress</code> function</li>\n<li><strong>Execution</strong>: Pass decompression result to <code>exec</code> function</li>\n</ul>\n<p>Also, since the program file must be encoded in Latin-1, write <code>#coding:L1</code> on the first line.</p>\n<p><strong>Execution Program Example:</strong></p>\n<pre><code>\n zlib;(zlib.decompress((,)))\n</code></pre>\n<h4>3.4.4 Code Efficiency Optimization</h4>\n<h5>Expanding Identical Processing</h5>\n<p>Even if the original code length is short, the compressed code won't necessarily be short. zlib's Deflate algorithm includes processing (LZSS) that compresses previously appeared substrings into information about their position and length.</p>\n<p>For some code containing repetitive processing, naively writing similar statements consecutively rather than cleverly reducing original code character count can result in shorter compressed code. Particularly for <strong>Task 086</strong>, expanding complex loops into simple, character-heavy loops produced shorter code.</p>\n<h5>Variable Name Search</h5>\n<p>In code compression, there is room for optimization in which alphabet letters to assign as variable names. We performed variable name searches for all tasks where compression was effective.</p>\n<p>The method is simple: first extract variable name portions from code, take one correspondence from random single-letter alphabet to single-letter alphabet, and simultaneously replace variable names. Then perform compression and correctness verification, and adopt if compression effectiveness improves without issues.</p>\n<p>This method achieved <strong>improvements of about 2-12 bytes</strong> for each task where compression was effective.</p>\n<h2>4. Conclusion</h2>\n<p>In this competition, we tackled large-scale code golf of 400 problems through semi-automation utilizing LLMs and combinations of diverse implementation techniques. The following points were particularly effective:</p>\n<ul>\n<li>Multiple solution generation and automatic selection with Codex</li>\n<li>Avoiding duplicate exploration through work history management</li>\n<li>Technical techniques including recursive processing, regular expressions, full grid search, and compression processing</li>\n<li>Optimization methods such as variable name search</li>\n</ul>\n<p>By combining these approaches, we achieved efficient and effective code golf.</p>",
      "rawMarkdown": "# Google Code Golf Championship 2025 Solution Report\n\n## 1. Introduction\n\nThis article reports on our approach to the Google Code Golf Championship 2025. In this competition, we had to perform code golf in Python for 400 ARC-AGI format problems, requiring the shortest possible code for each problem.\n\nWith the constraint of a maximum team size of 5 people, we determined that individually optimizing 400 problems would be impractical, and adopted a strategy centered on automating code compression using generative AI.\n\n## 2. Semi-Automated Code Shortening with LLMs\n\n### 2.1 Automation with Codex\n\nTo improve code shortening efficiency, we utilized [Codex (Web version)](https://chatgpt.com/codex). The browser version of Codex has the capability to output up to 4 results for a single prompt input. While multiple generation results typically create review costs in normal development, in code golf there is a clear evaluation criterion where \"shorter code\" = \"better code\", so review is completed simply by selecting the shortest among the 4 outputs.\n\n### 2.2 Semi-Automated Workflow\n\nRather than complete automation, we achieved semi-automation by combining the following elements:\n\n- **Automated processes**\n  - Prompt generation\n  - PR merge processing\n\n- **Manual processes**\n  - Prompt input\n  - Correctness review\n\n### 2.3 Context Provided to Generative AI\n\nTo achieve effective code golf, we provided three types of context to the generative AI.\n\n#### 2.3.1 General Code Golf Knowledge\n\nIn the early stages of the competition, we collected general techniques from existing resources such as [code.golf/wiki/langs/python](https://code.golf/wiki/langs/python) and incorporated them into prompts.\n\n#### 2.3.2 Knowledge Accumulated Through Competition\n\nAs the competition progressed and we became able to produce near-optimal code, we had the generative AI analyze those codes to extract generally applicable techniques and managed them as knowledge.\n\n#### 2.3.3 Work History Recording\n\nCodex performs work based on knowledge described in `AGENTS.md` and prompts. To prevent repeated suggestions of the same shortening ideas when sending multiple prompts for the same problem, we managed a memo for each task. By recording experimental content for shortening and instructing not to re-execute experiments written in the memo, we achieved efficient exploration. When code was shortened, past experiments could become effective, so we cleared the memo each time.\n\n### 2.4 Prompt Design Innovations\n\n#### 2.4.1 XML Structure Description\n\nBased on knowledge that XML structure is more understandable than Markdown, prompts were written in XML structure.\n\n#### 2.4.2 Work Termination Conditions\n\nTo have Codex work for extended periods, we set the termination condition as \"shorten by at least 1 character from the current code length\".\n\n## 3. Implementation Techniques Collection\n\n### 3.1 Recursive Processing\n\n#### 3.1.1 Overview\n\nFor several tasks, an approach of repeatedly changing each cell's color based on information from surrounding cells was effective. Below, we denote the 2D list representing the input grid as `g`.\n\n#### 3.1.2 Utilizing List Comprehensions\n\nPython's list comprehensions allow concise description of update operations for each cell. While double for-loops can achieve similar processing, list comprehensions are expressions, so the updated grid is obtained as a return value, which is compatible with code golf.\n\nHowever, when updating local variables simultaneously with the grid, or performing complex branching or repetition with if/while statements, list comprehensions are difficult to implement or increase character count, requiring process simplification.\n\n#### 3.1.3 Recursion with Lambda Expressions\n\nIn many problems, the answer is obtained by repeating the same list comprehension multiple times. Since list comprehensions are expressions, combining them with lambda expressions enables recursive processing without writing unnecessary characters like return.\n\n```python\np=lambda g,i=repetition_count-1:-i*g or p(list_comprehension_on_g,i-1)\n```\n\n#### 3.1.4 Rotation and Transposition\n\nIn many problems, updating each cell requires referencing adjacent cells in four directions, or rows and columns. When conditions for each direction are independent, it's more efficient to look at only one direction, perform updates, and repeat rotation or transposition to obtain the answer.\n\n- Transposition: `[*zip(*g)]`\n- Rotation: `[*zip(*g[::-1])]`\n\nIn most cases, recursion combining these operations is shorter than naively writing processing for all 4 directions.\n\n**Task 2 Implementation Example:**\n```python\np=lambda g,i=67:-i*g or[(d:=0)or[d:=c&-5>>d or(i<1)*4for c in r]for r in zip(*p(g,i-1)[::-1])]\n```\n\n#### 3.1.5 Pseudo-Recursion Using eval\n\nSome problems require performing different update processes in two stages. Normally, this would combine three lambda expressions as follows, but should be avoided due to character count:\n\n```python\nf=lambda g,i=repetition_count-1:-i*g or f(processing1_on_g,i-1)\nh=lambda g,i=repetition_count-1:-i*g or h(processing2_on_g,i-1)\np=lambda g:h(f(g))\n```\n\nThis problem can be solved using the `eval` function. Python's `eval` executes a given string as an expression and returns the result. Also, string repetition in Python can be expressed by multiplication of string and number. Using these, list comprehensions can be expanded directly without using lambda expressions.\n\n**Task 196 Implementation Example (using lambda):**\n```python\nf=lambda g,i=47:-i*g or f([*zip(*((c|v&2-c for c,v in zip(r,(2,*r)))for r in g[::-1]))],i-1)\nh=lambda g,i=7:-i*g or h([*zip(*((c|v-1&2 for c,v in zip(r,(2,*r)))for r in g[::-1]))],i-1)\np=lambda g:eval(str(h(f(g))).replace(*'20'))\n```\n\nWhen expanded:\n```python\np=lambda g:eval(str(eval(\"[*zip(*((c|v-1&2 for c,v in zip(r,(2,*r)))for r in \"*8+\"[*zip(*((c|v&2-c for c,v in zip(r,(2,*r)))for r in \"*48+\"g\"+\"[::-1]))]\"*48+\"[::-1]))]\"*8)).replace(*'20'))\n```\n\nConsolidating common processing, since `[::-1]))]` is exactly the same, it can be `\"[::-1]))]\"*56`. Also, using the format specifier `%s` enables further shortening:\n\n```python\np=lambda g,s=\"[*zip(*((c|v%s for c,v in zip(r,(2,*r)))for r in \":eval(str(eval(s%\"-1&2\"*8+s%\"&2-c\"*48+\"g\"+\"[::-1]))]\"*56)).replace(*'20'))\n```\n\nFinal shortened version:\n```python\np=lambda g,s=\"[*zip(*((c%s for c,v in zip(r,(2,*r)))for r in \":eval(s%\"%2*c\"+s%\"|v-1&2\"*8+s%\"|v&2-c\"*47+\"g\"+\"[::-1]))]\"*56)\n```\n\n### 3.2 Regular Expressions\n\n#### 3.2.1 Overview\n\nSome tasks can be solved correctly just by replacing grids or strings with Python's `replace` or `re.sub`. Below, we denote the input grid or string as `g`.\n\n#### 3.2.2 Combination with Rotation and Transposition\n\nIn grid processing, rotation or transposition can be combined with regular expression replacement.\n\n**Template performing 16 replacements while rotating:**\n```python\nimport re;p=lambda g,k=16:k and p(eval(re.sub(r'',r'',str([*zip(*g[::-1])]))),k-1)or g\n```\n\nImproved version:\n```python\nimport re;p=lambda g,k=15:-k*g or p(eval(re.sub(r'',r'',str([*zip(*g[::-1])]))),k-1)\n```\n\n#### 3.2.3 Vertical Pattern Recognition\n\nDepending on the task, the size of `g` may be fixed regardless of test cases. When the number of horizontal cells is n, there are 3n+1 characters between a cell and the cell below it. Using this, problems like \"detecting L-shapes\" can be addressed.\n\n**Task 081 Implementation Example:**\n```python\nimport re;p=lambda g,k=7:-k*g or[*zip(*eval(re.sub('0(?=, 8.{19}8)','1',str(p(g,k-1)[::-1]))))]\n```\n\nSince the width of Task 081 is 7, the pattern `8.{19}8` represents \"an 8 cell with another 8 immediately below-left\". This code performs the operation \"replace with 1 any 0 cell that has immediately to the right 'an 8 cell with an 8 below-left'\" while repeating 90-degree rotations.\n\n### 3.3 Full Grid Search\n\n#### 3.3.1 Basic Approach\n\nTo process all cells in an a×b rectangular region, normally a double loop is used:\n\n```python\nfor i in range(a):\n    for j in range(b):\n        # processing for g[i][j]\n```\n\n#### 3.3.2 Utilizing Chinese Remainder Theorem\n\nWhen processing order doesn't matter and gcd(a,b)=1, the Chinese Remainder Theorem can be used to write with a single loop:\n\n```python\nfor k in range(a*b):\n    # processing for g[k%a][k%b]\n```\n\nThis is effective when combined with pseudo-recursion using `exec`.\n\n#### 3.3.3 Handling gcd(a,b)≠1 Cases\n\nEven when the condition gcd(a,b)=1 is not satisfied, this technique can be applied with some ingenuity.\n\n**Task 074 Implementation Example:**\n```python\nk=0;p=lambda g:exec(\"k+=1;g[i][j]=min(g[j:=k%31%30][i:=k%30],g[i][1-j^(j<2)]);\"*2093)or g\n```\n\nThis problem requires searching a 30×30 board, but since they are not coprime, modulo is first taken with 31 and 30, then taken again with 30.\n\n**Task 240 Implementation Example:**\n```python\nk=1;p=lambda g:exec(\"k+=2;g[i:=k%19][j:=k%18]|=g[i][j-2]*(i<j-2<16-i)|g[j][~i];\"*746)or g\n```\n\nThis problem only needs to modify cells where both coordinates are odd. By narrowing the 19×19 board search to 19×18, gcd(a,b)=1 is satisfied, and by incrementing k by 2, the required number of repetitions is kept under 1000, saving 1 byte. This technique achieved a 10-byte reduction compared to the shortest code published by other teams.\n\n### 3.4 Compression Processing\n\n#### 3.4.1 Overview\n\nSome problems result in byte counts exceeding 200 bytes even with code golf alone. For such problems, representing compressed code as a byte string, then decompressing and executing it, leads to shorter overall byte count.\n\n#### 3.4.2 Compression Method\n\n##### Compression Software Used\n\nIn this competition, only Python standard library imports are permitted. Therefore, compression software must be decompressible by Python's standard library. We adopted **zopfli**.\n\nzopfli supports decompression by zlib, and while compression takes longer than other software, the compression ratio is several percent higher. Since compression time is negligible in this case, the drawback is not an issue.\n\n##### Writing Compression Results\n\nWhile zopfli's compression results are byte strings, using base64 encoding or hexadecimal notation diminishes compression benefits. By interpreting the byte string as **ISO-8859-1 (Latin-1)**, it can be represented as a string.\n\nControl characters, newlines, and quotation marks may occur:\n\n- **Null character and CR**: Require escape processing as they prevent proper decoding\n- **Newlines**: Can avoid escaping using triple quotes, but escaping is often shorter\n- **Quotation marks**: Escape whichever appears less in the string, and enclose with that quotation mark\n\n#### 3.4.3 Execution Method\n\nTo execute compressed programs, the following processing is required:\n\n1. Interpret the compression result string as a byte string\n2. Decompress with the byte string as input\n3. Interpret and execute the decompressed result as a program\n\nImplementation methods for each step:\n\n- **String→Byte string**: Specify `'L1'` in the second argument of `bytes` function to interpret as Latin-1\n- **Decompression**: Import `zlib` and execute `decompress` function\n- **Execution**: Pass decompression result to `exec` function\n\nAlso, since the program file must be encoded in Latin-1, write `#coding:L1` on the first line.\n\n**Execution Program Example:**\n```python\n#coding:L1\nimport zlib;exec(zlib.decompress(bytes(\"compression_result\",'L1')))\n```\n\n#### 3.4.4 Code Efficiency Optimization\n\n##### Expanding Identical Processing\n\nEven if the original code length is short, the compressed code won't necessarily be short. zlib's Deflate algorithm includes processing (LZSS) that compresses previously appeared substrings into information about their position and length.\n\nFor some code containing repetitive processing, naively writing similar statements consecutively rather than cleverly reducing original code character count can result in shorter compressed code. Particularly for **Task 086**, expanding complex loops into simple, character-heavy loops produced shorter code.\n\n##### Variable Name Search\n\nIn code compression, there is room for optimization in which alphabet letters to assign as variable names. We performed variable name searches for all tasks where compression was effective.\n\nThe method is simple: first extract variable name portions from code, take one correspondence from random single-letter alphabet to single-letter alphabet, and simultaneously replace variable names. Then perform compression and correctness verification, and adopt if compression effectiveness improves without issues.\n\nThis method achieved **improvements of about 2-12 bytes** for each task where compression was effective.\n\n## 4. Conclusion\n\nIn this competition, we tackled large-scale code golf of 400 problems through semi-automation utilizing LLMs and combinations of diverse implementation techniques. The following points were particularly effective:\n\n- Multiple solution generation and automatic selection with Codex\n- Avoiding duplicate exploration through work history management\n- Technical techniques including recursive processing, regular expressions, full grid search, and compression processing\n- Optimization methods such as variable name search\n\nBy combining these approaches, we achieved efficient and effective code golf.\n",
      "votes": 13
    },
    {
      "id": 3323425,
      "postDate": "2025-11-14T07:45:36.540Z",
      "content": "<p>It's compelling to see how generative AI is becoming a central tool in code golf competitions. Your team's success in automating the compression process challenges the traditional view of code golf as a purely human-driven puzzle. I'm interested to hear your thoughts on where this trend might lead. Will future competitions need to adapt their rules or problem types to account for highly effective LLM-based strategies?</p>",
      "rawMarkdown": "It's compelling to see how generative AI is becoming a central tool in code golf competitions. Your team's success in automating the compression process challenges the traditional view of code golf as a purely human-driven puzzle. I'm interested to hear your thoughts on where this trend might lead. Will future competitions need to adapt their rules or problem types to account for highly effective LLM-based strategies?",
      "replies": [
        {
          "id": 3335862,
          "postDate": "2025-11-18T07:55:48.343Z",
          "content": "<p>I think one reason generative AI worked so well is simply the sheer number of problems: with so many tasks, AI can repeatedly apply its strength—spotting tiny optimizations that humans often overlook. Task020 is a good example: almost the entire solution came from AI-driven improvement loops with virtually no human intervention, yet it still achieved the shortest standalone code.</p>\n<p>That said, the AI clearly had weaknesses. For tasks that use regular expressions, humans still had to design the overall approach because the model struggled there. Task240 was more of a hybrid effort: the core idea came from a human, but the AI contributed meaningful refinements—like the 1-byte k+=2 improvement—so it really was a two-person (or human–AI) collaboration.</p>\n<p>Judging from the write-ups of the top three teams, it seems they barely used AI at all. So at the moment, AI is a very powerful tool that can surpass humans in certain areas, but it still can’t outperform true specialists across the board.</p>\n<p>All of our team members actively do competitive programming, and in that field generative AI has already become quite strong (though still slightly behind the very top competitors). Some competitions have even started introducing rules to regulate or prohibit AI use. Given how fast these models are improving, it’s hard to predict what the landscape will look like in the future.</p>",
          "rawMarkdown": "I think one reason generative AI worked so well is simply the sheer number of problems: with so many tasks, AI can repeatedly apply its strength—spotting tiny optimizations that humans often overlook. Task020 is a good example: almost the entire solution came from AI-driven improvement loops with virtually no human intervention, yet it still achieved the shortest standalone code.\n\nThat said, the AI clearly had weaknesses. For tasks that use regular expressions, humans still had to design the overall approach because the model struggled there. Task240 was more of a hybrid effort: the core idea came from a human, but the AI contributed meaningful refinements—like the 1-byte k+=2 improvement—so it really was a two-person (or human–AI) collaboration.\n\nJudging from the write-ups of the top three teams, it seems they barely used AI at all. So at the moment, AI is a very powerful tool that can surpass humans in certain areas, but it still can’t outperform true specialists across the board.\n\nAll of our team members actively do competitive programming, and in that field generative AI has already become quite strong (though still slightly behind the very top competitors). Some competitions have even started introducing rules to regulate or prohibit AI use. Given how fast these models are improving, it’s hard to predict what the landscape will look like in the future.",
          "votes": 1
        }
      ]
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-19T12:51:04Z",
  "competition_id": 95282,
  "competition_slug": "google-code-golf-2025",
  "team_id": 14195225,
  "solution_url": "/competitions/google-code-golf-2025/writeups/7th-place-write-up-logiclynx"
}