罗兰谈MATLAB的艺术

将想法转化为MATLAB

请注意

罗兰谈MATLAB的艺术已存档,不会更新。

寻找零附近的最大正值

最近,Steve写了一篇博客,讨论代码的清晰度/模糊性一行代码的解决金宝搏官方网站方案。简单地说,他解决的问题是这样的。找出与零相邻的数组中最大的值。肯定有无数种方法,对吧?

内容

一个例子

让我从一个例子开始。如果问题中的数组是一个

A = [1,5,3,0,2,7,0,8,9,1 0];

正确答案是8。

史蒂夫的第一个解决方案

作为图像处理大师,史蒂夫立即想出了一个使用图像处理技术的解决方案。对我来说,发生了什么并不明显!如果我继承了这段代码,我就需要做一些工作来理解它。

fs = @(A) max(A(imdilate(A == 0, [1 1 1 1])));fs (A)
Ans = 8

只适用于正数值

然后史蒂夫注意到他的解决方案只适用于正值。

B = [5 4 -1 0 -2 0 -5 8];fs (B)
Ans = 0

史蒂夫的第二个回答

于是史蒂夫又试了一次。再说一次,虽然我知道面具是什么,但我不完全理解解决方案,可能会求助于阅读imdilate文档从图像处理工具箱

zero_mask = (B = 0);Adjacent_to_zero_mask = imdilate(zero_mask, [1 0 1]);max_value_adjacent_to_zero = max(B(adjacent_to_zero_mask))
Max_value_adjacent_to_zero = -1

道格的回答

在这里,我们看到Doug的答案,除了MATLAB,没有依赖于任何东西。很好的解决方案,但我得再考虑一下。再说一遍,我知道面具是什么,我知道我们在找什么除以0后的值,我们会找到0,卷积得到这些0的邻域,然后找到它们的最大值。唷!我现在很努力,但我明白。

掩码= isnan(conv(1。/ b,[0 10 0],“相同”));fd = @(B) max(B(isnan(conv(1);/ b,[0 10 0],“相同”))));fd (B)
Ans = -1

乔斯的下一个解决方案

下一个建议来自乔斯。它很晦涩,但最终我能理解。首先,创建一个2行向量,数据在每一端用值1填充,并对齐,使第一个值高于第3个值,第2个高于第4个值,等等(即,移动2个元素)。检查每一列,看看是否有值为0。从值为零的列中选择数据,并找到这些值的最大值。

fj = @(X) max(X(any([1 X(1:end-1);X(2:end) 1]==0))) fj(A) fj(B)
fj = @ (X)马克斯(X(任何([1,X (1: end-1); X(2:结束),1]= = 0)))= 8岁= 1

重新开始

轮到我重新开始思考这个问题了。首先,我想找到数组中0的下标。从那里,我构造了一个邻居数组。

zind = find(B==0) maxcandidate = [zind-1 zind+1]
Zind = 4 6 maxcandidate = 3 5 5 7

接下来,剔除范围之外的值(可能是第一个和最后一个)。

maxcandidate = maxcandidate ((maxcandidate > 0) & (maxcandidate <= length(B)))
maxcandidate = 3 5 5 7

现在我索引我的候选人,并获得最大的价值!

马克斯(B (maxcandidates))
Ans = -1

就像大厨泰尔说的,“非常简单,非常简单。”

我可以用一个语句写出这个算法,但我担心它会立即失去清晰度。

重复的零——清晰的问题陈述

我开始想,如果有重复的0,问题的发起者想要的结果是什么。为什么?因为我可能得零分?这是有意的吗?这里所有的解决方金宝搏官方网站案都允许这样做,所以我的解决方案也允许这样做,我不需要做更多的事情。我们来看看会发生什么。

C = [1 2 -4 0 0];fj (C)
Ans = 0

你的想法呢?

在MATLAB中编写漂亮、紧凑和非常密集的一行程序绝对是有趣和具有挑战性的。但我通常不喜欢回到代码中,解密代码以便进行更新或其他什么。我喜欢编写注释不需要比代码长很多的代码!你有什么想法?将它们贴在这里




使用MATLAB®7.8发布


评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。