{"id":190,"date":"2009-07-01T18:17:30","date_gmt":"2009-07-01T18:17:30","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/2009\/07\/01\/find-largest-positive-value-next-to-zero\/"},"modified":"2009-06-11T18:40:01","modified_gmt":"2009-06-11T18:40:01","slug":"find-largest-positive-value-next-to-zero","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2009\/07\/01\/find-largest-positive-value-next-to-zero\/","title":{"rendered":"Find Largest Positive Value Next to Zero"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>Recently, Steve wrote a blog discussing code clarity\/obscurity in the context of <a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/27\/learning-lessons-from-a-one-liner\/\">one-line<\/a> code solutions.  Simply stated, the problem he solved is this.  Find the largest value in an array adjacent to a zero value.\r\n          Must be zillions of ways, right?\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">An Example<\/a><\/li>\r\n         <li><a href=\"#3\">Steve's First Solution<\/a><\/li>\r\n         <li><a href=\"#4\">Good for Only Positive Values<\/a><\/li>\r\n         <li><a href=\"#5\">Steve's Second Answer<\/a><\/li>\r\n         <li><a href=\"#6\">Doug's answer<\/a><\/li>\r\n         <li><a href=\"#7\">Jos' Solution Next<\/a><\/li>\r\n         <li><a href=\"#8\">Start Over<\/a><\/li>\r\n         <li><a href=\"#13\">Repeated Zeros - Clarity of Problem Statement<\/a><\/li>\r\n         <li><a href=\"#14\">Your Thoughts?<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>An Example<a name=\"1\"><\/a><\/h3>\r\n   <p>Let me start with an example.  If the array in question is <tt>A<\/tt>,\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">A =  [1, 5, 3, 0, 2, 7, 0, 8, 9, 1 0];<\/pre><p>the correct answer is 8.<\/p>\r\n   <h3>Steve's First Solution<a name=\"3\"><\/a><\/h3>\r\n   <p>Steve, being an image processing guru, immediately arrived at a solution using image processing techniques.  For me, not so\r\n      obvious what is going on!  If I inherited this code, I'd have some work cut out for me to understand it.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">fs = @(A) max(A(imdilate(A == 0, [1 1 1])));\r\nfs(A)<\/pre><pre style=\"font-style:oblique\">ans =\r\n     8\r\n<\/pre><h3>Good for Only Positive Values<a name=\"4\"><\/a><\/h3>\r\n   <p>Steve then noticed his solution was only good for positive values.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">B = [5 4 -1 0 -2 0 -5 8];\r\nfs(B)<\/pre><pre style=\"font-style:oblique\">ans =\r\n     0\r\n<\/pre><h3>Steve's Second Answer<a name=\"5\"><\/a><\/h3>\r\n   <p>So Steve tried again.  Again, though I understand what a mask is, I don't fully comprehend the solution, and would probably\r\n      resort to reading the <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009a\/toolbox\/images\/imdilate.html\"><tt>imdilate<\/tt><\/a> documentation from <a href=\"https:\/\/www.mathworks.com\/products\/image\/\">Image Processing Toolbox<\/a>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">zero_mask = (B == 0);\r\nadjacent_to_zero_mask = imdilate(zero_mask, [1 0 1]);\r\nmax_value_adjacent_to_zero = max(B(adjacent_to_zero_mask))<\/pre><pre style=\"font-style:oblique\">max_value_adjacent_to_zero =\r\n    -1\r\n<\/pre><h3>Doug's answer<a name=\"6\"><\/a><\/h3>\r\n   <p>Here we see Doug's answer, written without dependence on anything but MATLAB.  Very nice solution, but I have to think about\r\n      it a bit.  Again, I know what a mask is, I see we are looking for <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009a\/techdoc\/ref\/nan.html\"><tt>NaN<\/tt><\/a> values after division by 0, so we'll find the zeros, convolve to get the neighbors of the zeros, and find the maximum of\r\n      those.  Whew!  I'm working hard now but I get it.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">mask = isnan(conv(1.\/B,[0 1 0],<span style=\"color: #A020F0\">'same'<\/span>));\r\nfd = @(B) max(B(isnan(conv(1.\/B,[0 1 0],<span style=\"color: #A020F0\">'same'<\/span>))));\r\nfd(B)<\/pre><pre style=\"font-style:oblique\">ans =\r\n    -1\r\n<\/pre><h3>Jos' Solution Next<a name=\"7\"><\/a><\/h3>\r\n   <p>The next suggestion that appeared is from Jos.  It's dense, but ultimately comprehensible to me.  First, create a 2 row vector\r\n      with the data padded at each end with the value 1, and aligned so the first value is above the 3rd, the 2nd above the 4th,\r\n      etc. (i.e., shifted over by 2 elements).  Check each column to see if any of the values are 0.  Select the data from the columns\r\n      with a zero value, and find the maximum of those values.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">fj = @(X) max(X(any([1 X(1:end-1) ; X(2:end) 1]==0)))\r\nfj(A)\r\nfj(B)<\/pre><pre style=\"font-style:oblique\">fj = \r\n    @(X)max(X(any([1,X(1:end-1);X(2:end),1]==0)))\r\nans =\r\n     8\r\nans =\r\n    -1\r\n<\/pre><h3>Start Over<a name=\"8\"><\/a><\/h3>\r\n   <p>My turn to start over and think about the problem.  First, I want to find the indices of zeros in the array.  From there,\r\n      I construct an array of the neighbors.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">zind = find(B==0)\r\nmaxcandidates = [zind-1 zind+1]<\/pre><pre style=\"font-style:oblique\">zind =\r\n     4     6\r\nmaxcandidates =\r\n     3     5     5     7\r\n<\/pre><p>Next, I weed out values outside the range (possibly the first and last).<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">maxcandidates = maxcandidates((maxcandidates &gt; 0) &amp; (maxcandidates &lt;= length(B)))<\/pre><pre style=\"font-style:oblique\">maxcandidates =\r\n     3     5     5     7\r\n<\/pre><p>Now I index into my candidates and get the maximum value!<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">max(B(maxcandidates))<\/pre><pre style=\"font-style:oblique\">ans =\r\n    -1\r\n<\/pre><p>As Chef Tell would say, \"Very simple, very easy.\"<\/p>\r\n   <p>I could write this algorithm in one statement, but I fear it would immediately lose clarity.<\/p>\r\n   <h3>Repeated Zeros - Clarity of Problem Statement<a name=\"13\"><\/a><\/h3>\r\n   <p>I got to wondering what result the originator of the question had in mind if there were repeated zeros.  Why?  Because I could\r\n      possibly get a zero result?  Was that intended?  All the solutions here allow that, so mine does too and I don't need to do\r\n      anything more.  Let's check what happens.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">C = [1 2 -4 0 0];\r\nfj(C)<\/pre><pre style=\"font-style:oblique\">ans =\r\n     0\r\n<\/pre><h3>Your Thoughts?<a name=\"14\"><\/a><\/h3>\r\n   <p>It can definitely be fun and challenging to write nifty, compact, and very dense one-liners in MATLAB.  But the horror of\r\n      going back to that code later, deciphering it so it can be updated or whatever, is not for me typically.  I like to write\r\n      code where the comments don't have to be a lot longer than the code!  What are your thoughts?  Post them <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=190#respond\">here<\/a>.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_2f2cdea7187045d9bfc6921b6eff7930() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='2f2cdea7187045d9bfc6921b6eff7930 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 2f2cdea7187045d9bfc6921b6eff7930';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Loren Shure';\r\n        copyright = 'Copyright 2009 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_2f2cdea7187045d9bfc6921b6eff7930()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.8<br><\/p>\r\n<\/div>\r\n<!--\r\n2f2cdea7187045d9bfc6921b6eff7930 ##### SOURCE BEGIN #####\r\n%%  Find Largest Positive Value Next to Zero\r\n% Recently, Steve wrote a blog discussing code clarity\/obscurity in the\r\n% context of \r\n% <https:\/\/blogs.mathworks.com\/steve\/2009\/05\/27\/learning-lessons-from-a-one-liner\/ one-line>\r\n% code solutions.  Simply stated, the problem he solved is this.  Find the\r\n% largest value in an array adjacent to a zero value.  Must be zillions of\r\n% ways, right?\r\n%% An Example\r\n% Let me start with an example.  If the array in question is |A|, \r\nA =  [1, 5, 3, 0, 2, 7, 0, 8, 9, 1 0];\r\n%%\r\n% the correct answer is 8.\r\n%% Steve's First Solution\r\n% Steve, being an image processing guru, immediately arrived at a solution\r\n% using image processing techniques.  For me, not so obvious what is going\r\n% on!  If I inherited this code, I'd have some work cut out for me to\r\n% understand it.\r\nfs = @(A) max(A(imdilate(A == 0, [1 1 1])));\r\nfs(A)\r\n%% Good for Only Positive Values\r\n% Steve then noticed his solution was only good for positive values.\r\nB = [5 4 -1 0 -2 0 -5 8];\r\nfs(B)\r\n%% Steve's Second Answer\r\n% So Steve tried again.  Again, though I understand what a mask is, I don't\r\n% fully comprehend the solution, and would probably resort to reading the\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009a\/toolbox\/images\/imdilate.html |imdilate|>\r\n% documentation from \r\n% <https:\/\/www.mathworks.com\/products\/image\/ Image Processing Toolbox>.\r\nzero_mask = (B == 0);\r\nadjacent_to_zero_mask = imdilate(zero_mask, [1 0 1]);\r\nmax_value_adjacent_to_zero = max(B(adjacent_to_zero_mask))\r\n\r\n%% Doug's answer\r\n% Here we see Doug's answer, written without dependence on anything but\r\n% MATLAB.  Very nice solution, but I have to think about it a bit.  Again,\r\n% I know what a mask is, I see we are looking for \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009a\/techdoc\/ref\/nan.html |NaN|>\r\n% values after division by 0, so we'll find the zeros, convolve to get the\r\n% neighbors of the zeros, and find the maximum of those.  Whew!  I'm\r\n% working hard now but I get it.\r\nmask = isnan(conv(1.\/B,[0 1 0],'same'));\r\nfd = @(B) max(B(isnan(conv(1.\/B,[0 1 0],'same'))));\r\nfd(B)\r\n%% Jos' Solution Next\r\n% The next suggestion that appeared is from Jos.  It's dense, but\r\n% ultimately comprehensible to me.  First, create a 2 row vector with the\r\n% data padded at each end with the value 1, and aligned so the first value\r\n% is above the 3rd, the 2nd above the 4th, etc. (i.e., shifted over by 2 \r\n% elements).  Check each column to see if any of the values are 0.  Select\r\n% the data from the columns with a zero value, and find the maximum of\r\n% those values.\r\nfj = @(X) max(X(any([1 X(1:end-1) ; X(2:end) 1]==0)))\r\nfj(A)\r\nfj(B)\r\n%% Start Over\r\n% My turn to start over and think about the problem.  First, I want to find\r\n% the indices of zeros in the array.  From there, I construct an array of \r\n% the neighbors.\r\nzind = find(B==0)\r\nmaxcandidates = [zind-1 zind+1]\r\n%%\r\n% Next, I weed out values outside the range (possibly the first and last).\r\nmaxcandidates = maxcandidates((maxcandidates > 0) & (maxcandidates <= length(B)))\r\n%%\r\n% Now I index into my candidates and get the maximum value!\r\nmax(B(maxcandidates))\r\n%%\r\n% As Chef Tell would say, \"Very simple, very easy.\"\r\n%% \r\n% I could write this algorithm in one statement, but I fear it would\r\n% immediately lose clarity.\r\n%% Repeated Zeros - Clarity of Problem Statement\r\n% I got to wondering what result the originator of the question had in mind\r\n% if there were repeated zeros.  Why?  Because I could possibly get a zero\r\n% result?  Was that intended?  All the solutions here allow that, so mine\r\n% does too and I don't need to do anything more.  Let's check what happens.\r\nC = [1 2 -4 0 0];\r\nfj(C)\r\n%%  Your Thoughts?\r\n% It can definitely be fun and challenging to write nifty, compact, and\r\n% very dense one-liners in MATLAB.  But the horror of going back to that\r\n% code later, deciphering it so it can be updated or whatever, is not for\r\n% me typically.  I like to write code where the comments don't have to be\r\n% a lot longer than the code!  What are your thoughts?  Post them\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=190#respond here>.\r\n\r\n\r\n\r\n\r\n\r\n\r\n##### SOURCE END ##### 2f2cdea7187045d9bfc6921b6eff7930\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Recently, Steve wrote a blog discussing code clarity\/obscurity in the context of one-line code solutions.  Simply stated, the problem he solved is this.  Find the largest value in an... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2009\/07\/01\/find-largest-positive-value-next-to-zero\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,8],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/190"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=190"}],"version-history":[{"count":0,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/190\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}