{"id":5423,"date":"2018-03-25T13:00:28","date_gmt":"2018-03-25T13:00:28","guid":{"rendered":"http:\/\/writeasync.net\/?p=5423"},"modified":"2018-04-27T14:57:55","modified_gmt":"2018-04-27T14:57:55","slug":"more-four-fours","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=5423","title":{"rendered":"More four fours"},"content":{"rendered":"<p>Astute readers may have noticed in my <a href=\"http:\/\/writeasync.net\/?p=5421\">previous post about the four fours<\/a> that I neglected to include exponents in the set of supported mathematical operations. Well, <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/9c0de92cd7f1a898f70e5c4458e52f8f9af9eb67#diff-3150319addb38a73a34c196731d5d114\">that is fixed now<\/a>. Perhaps these imagined readers also noticed that my recursive algorithm was slightly more verbose than required, as it unnecessarily handled unary and binary operators separately. I <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/21709342fb0f692013d9125fbad455e78aa8df14#diff-3150319addb38a73a34c196731d5d114\">fixed that<\/a> too!<\/p>\n<p>While making the above fixes I also experimented with the performance a bit. It turns out that <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/2e97a5fe1003225af3ce5c30ad8e814a13549091#diff-3150319addb38a73a34c196731d5d114\">recursing on operators before operands<\/a> seems to save time when searching for the first 100 solutions. I assume this is because if it is asked to handle operands first, the search ends up producing answers which are ultimately ignored for being too large. While doing this, I also checked to see if switching from my custom stack to the .NET Core <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.collections.immutable.immutablestack-1?view=netcore-2.0\">ImmutableStack&lt;T&gt;<\/a> changed the performance in any significant way. It didn&#8217;t seem to have a noticeable effect one way or the other, so I <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/cd86df46974c6cda73a3f0870bc47fc956f649db#diff-3150319addb38a73a34c196731d5d114\">ditched my custom stack<\/a>. All things being equal, less custom code is better (especially if it is &#8220;unusual&#8221;).<\/p>\n<p>As a final tweak, I <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/9c0de92cd7f1a898f70e5c4458e52f8f9af9eb67#diff-3150319addb38a73a34c196731d5d114\">swapped the order of 4 and 44<\/a> in the operands list. This produced slightly simpler solutions in many cases (e.g. &#8220;(44 &#8211; 44)!&#8221; for 1, instead of &#8220;(4!+4-4-4!)!&#8221;). Overall, I am pleased with the result. As a bonus, it seems to be a different (simpler?) approach than the one <a href=\"https:\/\/en.wikipedia.org\/wiki\/Four_fours#Algorithmics_of_the_problem\">discussed on Wikipedia<\/a> and on any <a href=\"https:\/\/github.com\/necocen\/four-fours\">publicly<\/a> <a href=\"https:\/\/github.com\/nidi3\/four-fours\">available<\/a> <a href=\"https:\/\/github.com\/saibaba\/four4s\">code<\/a> I could find.<\/p>\n<p>Now the only thing left to do is generalize. First, let&#8217;s see if it can solve the &#8220;three threes&#8221; problem. This will require <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/bc9229030ed7b5e3788261a3bc70bf36cc2a6448#diff-3150319addb38a73a34c196731d5d114\">getting rid of any special cases involving the numeral 4<\/a>. After that, it is a simple matter of <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/c23ec7d27c06c7bfd847690edc056018258f5c6c#diff-3150319addb38a73a34c196731d5d114\">propagating a user-defined value for the numeral count<\/a> instead of assuming we always want four digits. Then it&#8217;s a just small fix up to the app to <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/96e84f690e4d084e70a0ce92cc280fdea2daabe4#diff-3150319addb38a73a34c196731d5d114\">support digits other than 4<\/a>.<\/p>\n<p>Unfortunately, running the app in &#8220;3&#8221; mode produces an exception:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUnhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow.\r\n   at Four4.Number..ctor(Int32 num, Int32 denom) in Four4Sample\\Four4\\Number.cs:line 25\r\n   at Four4.Number.Pow(Number exp) in Four4Sample\\Four4\\Number.cs:line 177\r\n   at Four4.Expression.&lt;&gt;c.&lt;Append&gt;b__12_4(Number x, Number y) in Four4Sample\\Four4\\Expression.cs:line 59\r\n   at Four4.Expression.NumberStack.Apply2(Func`3 op) in Four4Sample\\Four4\\Expression.cs:line 187\r\n   at Four4.Expression.Binary(String token, Func`3 op) in Four4Sample\\Four4\\Expression.cs:line 95\r\n   at Four4.Expression.Append(String token) in Four4Sample\\Four4\\Expression.cs:line 59\r\n . . .\r\n<\/pre>\n<p>The specific expression it fails on is &#8220;3 ! ! 3 ^ .3 \/ 3 ^&#8221;, i.e. <code>(((3!)!)^3 \/ .3)^3<\/code>. This does indeed overflow the range of a 32-bit signed integer, but I was sure I handled this case&#8230;. By adding a few more tests, I should be able to figure out where this breaks down. Indeed, it turns out the problem is not actually with Pow, but with Multiply!<\/p>\n<p>The unit test for the expression &#8220;3 ! ! 3 ^ .3 \/&#8221; reproduces the issue. It should produce &#8220;1244160000&#8221; but during the course of multiplying the numerators together, it sees an intermediate result greater than <code>int.MaxValue<\/code>. The fix I have chosen is to <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/7229bdb9c215efba309a54b87fb3e9252c081b38#diff-3150319addb38a73a34c196731d5d114\">return &#8220;NaN&#8221; for any overflow<\/a>, even if the reduced result would be in range. It is perhaps a simplistic assumption but it doesn&#8217;t affect the goal of finding solutions inside a &#8220;reasonable&#8221; bound.<\/p>\n<p>Fixing the case for a large positive numerator makes the new tests pass. But running the program results in another unhandled case, &#8220;3 ! ! 3 ^ .3 33 &#8211; \/&#8221;, i.e. <code>((3!)!)^3 \/ (.3 - 33)<\/code>. In this case, it is more of an &#8220;underflow&#8221; since the value is a too-small negative number. That can be handled similarly with <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/e8ffde36f02f62ecc141e9e16bffef890918e1b0#diff-3150319addb38a73a34c196731d5d114\">another lower bound range check<\/a>.<\/p>\n<p>Alas, another bad expression still slips through, &#8220;3 ! ! .3 3 ! &#8211; \/ 3 ^&#8221;, i.e. <code>(((3!)!)\/(.3 - 3!))^3<\/code>. This time, Pow is the culprit. It was simply missing <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/f9db227e4bd9e7a25d3de8358ab737855c3ccb1f#diff-3150319addb38a73a34c196731d5d114\">a similar lower bound check<\/a> as above.<\/p>\n<p>With these fixes, the three threes search doesn&#8217;t crash but produces incorrect results. First error: the program doesn&#8217;t initialize the NumeralCount &#8212; <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/42ac4e6a571401d70740184687e780a1aef3a861#diff-3150319addb38a73a34c196731d5d114\">easy to fix<\/a>. Still, it produces the wrong result. Ah, I forgot that <code>Results<\/code> also specifically checks for a numeral count of 4. A few tests and code changes later, <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/45d07d6e154dee7857b6383f96c6c0e2ecbd7a94#diff-3150319addb38a73a34c196731d5d114\">that is also fixed<\/a>. Now it works!<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFound 43 results in 45 ms.\r\n1 = (((((3)!)!-((3)!)!))!^3)\r\n2 = ((((3)!)!+((3)!)!)\/((3)!)!)\r\n3 = ((((3)!)!+3)-((3)!)!)\r\n4 = (((((3)!)!-((3)!)!))!+3)\r\n5 = (((3)!\/3)+3)\r\n . . .\r\n<\/pre>\n<p>According to my program, the first missing result is 22. In fact, only 43 of the first 100 whole numbers appear to have a solution.<\/p>\n<p>What about the two twos? <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/f1d1c0a4db7c90a50e563a42439d0c564cb457e6#diff-3150319addb38a73a34c196731d5d114\">One more generalization<\/a> and the program tells us:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFound 9 results in 19 ms.\r\n1 = ((2-2))!\r\n2 = sqrt((2+2))\r\n3 = sqrt((2\/.2_))\r\n4 = (2+2)\r\n6 = (sqrt((2\/.2_)))!\r\n9 = (2\/.2_)\r\n10 = (2\/.2)\r\n22 = 22\r\n24 = ((2+2))!\r\n<\/pre>\n<p>The final gauntlet &#8212; the five fives!<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFound 100 results in 480 ms.\r\n1 = (((55-55))!^5)\r\n2 = (((55-55))!\/.5)\r\n3 = sqrt((((55-5)-5)\/5))\r\n4 = (sqrt(sqrt(((55\/5)+5)))\/.5)\r\n5 = (((55-55))!*5)\r\n . . . \r\n<\/pre>\n<p>Just a <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/73399b42c7e166ae303b2b62f438b8c05bb73adb#diff-3150319addb38a73a34c196731d5d114\">few more changes<\/a> to get the Main() method down to its bare essentials, and set the min and max search values:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSolving 3 3s (min=1, max=1000)...\r\nFound 109 results in 44 ms.\r\n1 = (((((3)!)!-((3)!)!))!^3)\r\n2 = ((((3)!)!+((3)!)!)\/((3)!)!)\r\n3 = ((((3)!)!+3)-((3)!)!)\r\n4 = (((((3)!)!-((3)!)!))!+3)\r\n . . .\r\n936 = (((3)!)!+(((3)!)!*.3))\r\n960 = ((((3)!)!\/3)+((3)!)!)\r\n1000 = ((3\/.3)^3)\r\n<\/pre>\n<p>At that point, I thought I was done, but as I was exploring higher valued solutions of the five fives, I encountered more overflow problems. Drat! This time it was because of a division, which pointed to the denominator of a multiplication being too large. I probably could have predicted this given that I only &#8220;spot fixed&#8221; the problem last time. Well, now for <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/ca77a03c4965611a70608f02a7acbca999c5520a#diff-3150319addb38a73a34c196731d5d114\">a real solution<\/a>. Luckily, we don&#8217;t have to deal with underflow because the denominator is never negative. At any rate, while I&#8217;m at it, I should <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/da754d4a95bf9295bb09f69e8cdb4f13dc7f253a#diff-3150319addb38a73a34c196731d5d114\">fix potential overflow issues in addition<\/a> (writing tests first, of course).<\/p>\n<p>The final improvement is to ensure that numbers of any allowed size are used. Originally I used the one and two digit numbers for the given digit (e.g. 4 and 44, 5 and 55, etc.). But technically 444, 4444, etc. should be allowed, as well as 55555 for five fives, and so on. One <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commit\/01d510d9e8598e8b65629b49f32cb37334e98edf#diff-3150319addb38a73a34c196731d5d114\">last correction<\/a> for that:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSolving 4 4s (min=110, max=111)...\r\nFound 2 results in 18 ms.\r\n110 = (sqrt(sqrt((44^4)))\/.4)\r\n111 = (444\/4)\r\n<\/pre>\n<p>That concludes my four fours exploration. I promise I&#8217;ll write about something less overtly mathematical next time!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Astute readers may have noticed in my previous post about the four fours that I neglected to include exponents in the set of supported mathematical operations. Well, that is fixed now. Perhaps these imagined readers also noticed that my recursive&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[91,103,41],"tags":[],"class_list":["post-5423","post","type-post","status-publish","format-standard","hentry","category-design","category-math","category-tdd"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5423","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5423"}],"version-history":[{"count":11,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5423\/revisions"}],"predecessor-version":[{"id":5436,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5423\/revisions\/5436"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5423"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5423"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}