{
  "id": 154304,
  "title": "21st place solution",
  "content": "<p>First of all thank you so much François Chollet and kaggle team for organizing this awesome competition.\nIt has been really fun and creative competition for me. I have been getting score 1 for a month lol.</p>\n\n<p>My solution was similar to DSL methods we have been discussed.\nAll the training code and test/evaluation code was processed by python methods which has the following interfaces.</p>\n\n<ul>\n<li><p>def converter(inp, objects, c) returns objects</p>\n\n<ul><li>inp: The original input from the dataset</li>\n<li>objects: processed input data representation with some metadata. eg) rectangle info</li>\n<li>c: Context object which is shared between training and testing. eg) Colors observed only in output. output shape information.</li></ul></li>\n<li><p>def merger(objects, c):</p>\n\n<ul><li>objects: processed input data</li>\n<li>c: the context object</li></ul></li>\n</ul>\n\n<p>I have more than 100 converter methods and 10 merger methods defined.</p>\n\n<p>For example one task might be solved by\n- [converter] identify_objects\n  - Convert input array into rectangle pieces as objects\n- [converter] color_with_out_color\n  - Color all the found objects with color which appears only in output\n- [merger] simple_merge\n  - Merge all the object into one array.</p>\n\n<p>I have rotation, fill, flip, move, draw_line and many types of converters and or_merge, and_merge, select_biggest_object and more mergers.</p>\n\n<p>That's about it.\nI'm looking forward to seeing more creative ideas and solutions than mine :)</p>\n\n<p>One more note for the first month, CNN based image generation model. But it didn't work as we have so few training data.</p>\n\n<h2>Real code for identify objects</h2>\n\n<p>```\ndef identify_rec2(y, x, a, visited, c, rect):</p>\n\n<pre><code>if visited[y + 1][x + 1]:\n    return\nvisited[y + 1][x + 1] = True\nif a[y][x] == c.bg_color:\n    return\nif y &lt; rect.y1:\n    rect.y1 = y\nif y &gt; rect.y2:\n    rect.y2 = y\nif x &lt; rect.x1:\n    rect.x1 = x\nif x &gt; rect.x2:\n    rect.x2 = x\nidentify_rec2(y + 1, x + 1, a, visited, c, rect)\nidentify_rec2(y + 1, x, a, visited, c, rect)\nidentify_rec2(y, x + 1, a, visited, c, rect)   \nidentify_rec2(y - 1, x - 1, a, visited, c, rect)\nidentify_rec2(y + 1, x - 1, a, visited, c, rect)\nidentify_rec2(y - 1, x + 1, a, visited, c, rect)    \nidentify_rec2(y - 1, x, a, visited, c, rect)\nidentify_rec2(y, x - 1, a, visited, c, rect)        \n</code></pre>\n\n<p>def identify_greedy(inp, objects, c):\n    if len(objects) != 1:\n        raise SkipException <br>\n        return objects\n    a = objects[0].data\n    height, width = a.shape\n    if height &gt; 30 and width &gt; 30:\n        raise SkipException <br>\n        return objects\n    visited = init_visited(height, width)\n    objs = []\n    for y in range(height):\n        for x in range(width):\n            if visited[y + 1][x + 1]:\n                continue\n            if a[y][x] == c.bg_color:\n                visited[y + 1][x + 1] = True\n                continue\n            if not visited[y + 1][x + 1]:\n                rec = Rect(y,y, x, x)\n                identify_rec2(y, x, a, visited, c, rec)\n                obj = Object(a)\n                obj.rectangle = (rec.y1, rec.y2, rec.x1, rec.x2)\n                objs.append(obj)\n    if len(objs) == 0:\n        raise SkipException <br>\n        return objects\n    return objs    </p>\n\n<p>```</p>",
  "comments": [
    {
      "id": 864347,
      "author_name": "Froggy McFrogson",
      "author_url": "",
      "post_date": "2020-05-28T00:41:15.973000",
      "content": "<p>That sounds similar to what I did. But you probably did it much better! (I got 126 on the training though so not too bad).</p>\n\n<p>Some functions I had was getShapes() either as pixels, blobs, or blobs allowing diagonal connections. If I had more time I would have implemented multicolouted blobs too, and lines. Then this would also store properties such as color, number of holes, number of pixels, what is it next to, how many \"twins\" does it have, what colors does it \"see\" in different directions, is it a rectangle,  and so on...</p>\n\n<p>And then pattern matching to match up properties such as width with properties of shapes.</p>\n\n<p>And a \"generaliser\", which if there are 2 rules like \"next to red--&gt;turn red\" and \"next to blue--&gt;turn blue\" generalises to \"next to X--&gt; turn X\".</p>\n\n<p>Two things I did wrong I think are: not applying enough filters in order (just 1 or 2).</p>\n\n<p>And also mixing up classes of properties instead of finding the simplest rules. </p>\n\n<p>I didn't use any machine learning at all just algorithms. Maybe that's why I did so badly. lol.</p>\n\n<p>I also made a cellular automata which worked on a few cases. Which applied only the rules where there was no contradiction. But this didn't work on the leaderboard.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 864359,
          "author_name": "higepon",
          "author_url": "",
          "post_date": "2020-05-28T00:50:33.410000",
          "content": "<p>Thanks for sharing. I think we're doing very similar.\nI put one of my identify objects method above. It was a bit tricky.</p>\n\n<p>Yeah applying enough filters with limited time was hard too. I defined early stopping exception to try all the possible combinations.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    }
  ],
  "comment_count": 2,
  "messages": [
    {
      "id": 864334,
      "postDate": "2020-05-28T00:33:32.870Z",
      "content": "<p>First of all thank you so much François Chollet and kaggle team for organizing this awesome competition.\nIt has been really fun and creative competition for me. I have been getting score 1 for a month lol.</p>\n\n<p>My solution was similar to DSL methods we have been discussed.\nAll the training code and test/evaluation code was processed by python methods which has the following interfaces.</p>\n\n<ul>\n<li><p>def converter(inp, objects, c) returns objects</p>\n\n<ul><li>inp: The original input from the dataset</li>\n<li>objects: processed input data representation with some metadata. eg) rectangle info</li>\n<li>c: Context object which is shared between training and testing. eg) Colors observed only in output. output shape information.</li></ul></li>\n<li><p>def merger(objects, c):</p>\n\n<ul><li>objects: processed input data</li>\n<li>c: the context object</li></ul></li>\n</ul>\n\n<p>I have more than 100 converter methods and 10 merger methods defined.</p>\n\n<p>For example one task might be solved by\n- [converter] identify_objects\n  - Convert input array into rectangle pieces as objects\n- [converter] color_with_out_color\n  - Color all the found objects with color which appears only in output\n- [merger] simple_merge\n  - Merge all the object into one array.</p>\n\n<p>I have rotation, fill, flip, move, draw_line and many types of converters and or_merge, and_merge, select_biggest_object and more mergers.</p>\n\n<p>That's about it.\nI'm looking forward to seeing more creative ideas and solutions than mine :)</p>\n\n<p>One more note for the first month, CNN based image generation model. But it didn't work as we have so few training data.</p>\n\n<h2>Real code for identify objects</h2>\n\n<p>```\ndef identify_rec2(y, x, a, visited, c, rect):</p>\n\n<pre><code>if visited[y + 1][x + 1]:\n    return\nvisited[y + 1][x + 1] = True\nif a[y][x] == c.bg_color:\n    return\nif y &lt; rect.y1:\n    rect.y1 = y\nif y &gt; rect.y2:\n    rect.y2 = y\nif x &lt; rect.x1:\n    rect.x1 = x\nif x &gt; rect.x2:\n    rect.x2 = x\nidentify_rec2(y + 1, x + 1, a, visited, c, rect)\nidentify_rec2(y + 1, x, a, visited, c, rect)\nidentify_rec2(y, x + 1, a, visited, c, rect)   \nidentify_rec2(y - 1, x - 1, a, visited, c, rect)\nidentify_rec2(y + 1, x - 1, a, visited, c, rect)\nidentify_rec2(y - 1, x + 1, a, visited, c, rect)    \nidentify_rec2(y - 1, x, a, visited, c, rect)\nidentify_rec2(y, x - 1, a, visited, c, rect)        \n</code></pre>\n\n<p>def identify_greedy(inp, objects, c):\n    if len(objects) != 1:\n        raise SkipException <br>\n        return objects\n    a = objects[0].data\n    height, width = a.shape\n    if height &gt; 30 and width &gt; 30:\n        raise SkipException <br>\n        return objects\n    visited = init_visited(height, width)\n    objs = []\n    for y in range(height):\n        for x in range(width):\n            if visited[y + 1][x + 1]:\n                continue\n            if a[y][x] == c.bg_color:\n                visited[y + 1][x + 1] = True\n                continue\n            if not visited[y + 1][x + 1]:\n                rec = Rect(y,y, x, x)\n                identify_rec2(y, x, a, visited, c, rec)\n                obj = Object(a)\n                obj.rectangle = (rec.y1, rec.y2, rec.x1, rec.x2)\n                objs.append(obj)\n    if len(objs) == 0:\n        raise SkipException <br>\n        return objects\n    return objs    </p>\n\n<p>```</p>",
      "rawMarkdown": "First of all thank you so much François Chollet and kaggle team for organizing this awesome competition.\nIt has been really fun and creative competition for me. I have been getting score 1 for a month lol.\n\nMy solution was similar to DSL methods we have been discussed.\nAll the training code and test/evaluation code was processed by python methods which has the following interfaces.\n\n- def converter(inp, objects, c) returns objects\n  - inp: The original input from the dataset\n  - objects: processed input data representation with some metadata. eg) rectangle info\n  - c: Context object which is shared between training and testing. eg) Colors observed only in output. output shape information.\n\n- def merger(objects, c):\n  - objects: processed input data\n  - c: the context object\n\nI have more than 100 converter methods and 10 merger methods defined.\n\nFor example one task might be solved by\n- [converter] identify_objects\n  - Convert input array into rectangle pieces as objects\n- [converter] color_with_out_color\n  - Color all the found objects with color which appears only in output\n- [merger] simple_merge\n  - Merge all the object into one array.\n\n\nI have rotation, fill, flip, move, draw_line and many types of converters and or_merge, and_merge, select_biggest_object and more mergers.\n\nThat's about it.\nI'm looking forward to seeing more creative ideas and solutions than mine :)\n\nOne more note for the first month, CNN based image generation model. But it didn't work as we have so few training data.\n\n## Real code for identify objects\n```\ndef identify_rec2(y, x, a, visited, c, rect):\n\n    if visited[y + 1][x + 1]:\n        return\n    visited[y + 1][x + 1] = True\n    if a[y][x] == c.bg_color:\n        return\n    if y &lt; rect.y1:\n        rect.y1 = y\n    if y &gt; rect.y2:\n        rect.y2 = y\n    if x &lt; rect.x1:\n        rect.x1 = x\n    if x &gt; rect.x2:\n        rect.x2 = x\n    identify_rec2(y + 1, x + 1, a, visited, c, rect)\n    identify_rec2(y + 1, x, a, visited, c, rect)\n    identify_rec2(y, x + 1, a, visited, c, rect)   \n    identify_rec2(y - 1, x - 1, a, visited, c, rect)\n    identify_rec2(y + 1, x - 1, a, visited, c, rect)\n    identify_rec2(y - 1, x + 1, a, visited, c, rect)    \n    identify_rec2(y - 1, x, a, visited, c, rect)\n    identify_rec2(y, x - 1, a, visited, c, rect)        \n\n\ndef identify_greedy(inp, objects, c):\n    if len(objects) != 1:\n        raise SkipException                    \n        return objects\n    a = objects[0].data\n    height, width = a.shape\n    if height &gt; 30 and width &gt; 30:\n        raise SkipException                    \n        return objects\n    visited = init_visited(height, width)\n    objs = []\n    for y in range(height):\n        for x in range(width):\n            if visited[y + 1][x + 1]:\n                continue\n            if a[y][x] == c.bg_color:\n                visited[y + 1][x + 1] = True\n                continue\n            if not visited[y + 1][x + 1]:\n                rec = Rect(y,y, x, x)\n                identify_rec2(y, x, a, visited, c, rec)\n                obj = Object(a)\n                obj.rectangle = (rec.y1, rec.y2, rec.x1, rec.x2)\n                objs.append(obj)\n    if len(objs) == 0:\n        raise SkipException                    \n        return objects\n    return objs    \n\n```",
      "votes": 14
    },
    {
      "id": 864347,
      "postDate": "2020-05-28T00:41:15.973Z",
      "content": "<p>That sounds similar to what I did. But you probably did it much better! (I got 126 on the training though so not too bad).</p>\n\n<p>Some functions I had was getShapes() either as pixels, blobs, or blobs allowing diagonal connections. If I had more time I would have implemented multicolouted blobs too, and lines. Then this would also store properties such as color, number of holes, number of pixels, what is it next to, how many \"twins\" does it have, what colors does it \"see\" in different directions, is it a rectangle,  and so on...</p>\n\n<p>And then pattern matching to match up properties such as width with properties of shapes.</p>\n\n<p>And a \"generaliser\", which if there are 2 rules like \"next to red--&gt;turn red\" and \"next to blue--&gt;turn blue\" generalises to \"next to X--&gt; turn X\".</p>\n\n<p>Two things I did wrong I think are: not applying enough filters in order (just 1 or 2).</p>\n\n<p>And also mixing up classes of properties instead of finding the simplest rules. </p>\n\n<p>I didn't use any machine learning at all just algorithms. Maybe that's why I did so badly. lol.</p>\n\n<p>I also made a cellular automata which worked on a few cases. Which applied only the rules where there was no contradiction. But this didn't work on the leaderboard.</p>",
      "rawMarkdown": "That sounds similar to what I did. But you probably did it much better! (I got 126 on the training though so not too bad).\n\nSome functions I had was getShapes() either as pixels, blobs, or blobs allowing diagonal connections. If I had more time I would have implemented multicolouted blobs too, and lines. Then this would also store properties such as color, number of holes, number of pixels, what is it next to, how many \"twins\" does it have, what colors does it \"see\" in different directions, is it a rectangle,  and so on...\n\nAnd then pattern matching to match up properties such as width with properties of shapes.\n\nAnd a \"generaliser\", which if there are 2 rules like \"next to red--&gt;turn red\" and \"next to blue--&gt;turn blue\" generalises to \"next to X--&gt; turn X\".\n\nTwo things I did wrong I think are: not applying enough filters in order (just 1 or 2).\n\nAnd also mixing up classes of properties instead of finding the simplest rules. \n\nI didn't use any machine learning at all just algorithms. Maybe that's why I did so badly. lol.\n\nI also made a cellular automata which worked on a few cases. Which applied only the rules where there was no contradiction. But this didn't work on the leaderboard.",
      "votes": 1,
      "replies": [
        {
          "id": 864359,
          "postDate": "2020-05-28T00:50:33.410Z",
          "content": "<p>Thanks for sharing. I think we're doing very similar.\nI put one of my identify objects method above. It was a bit tricky.</p>\n\n<p>Yeah applying enough filters with limited time was hard too. I defined early stopping exception to try all the possible combinations.</p>",
          "rawMarkdown": "Thanks for sharing. I think we're doing very similar.\nI put one of my identify objects method above. It was a bit tricky.\n\nYeah applying enough filters with limited time was hard too. I defined early stopping exception to try all the possible combinations.",
          "votes": 1
        }
      ]
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-19T22:05:34Z",
  "competition_id": 18329,
  "competition_slug": "abstraction-and-reasoning-challenge",
  "team_id": 4565447,
  "solution_url": "/competitions/abstraction-and-reasoning-challenge/writeups/higepon-21st-place-solution"
}