Matlab 最后一个人站着-闭式方程
我写了一个matlab代码,以便找到最后一个支持给定问题的人 问题:Matlab 最后一个人站着-闭式方程,matlab,Matlab,我写了一个matlab代码,以便找到最后一个支持给定问题的人 问题:n人们手里拿着枪站成一圈。1杀2,3杀4,5杀6等等(循环),直到我们只剩下一个人。谁将是最后一个活着的人 function N = lastManStanding(n) while length(n) ~= 1 if mod(length(n),2) == 0 for ii = 1:length(n)/2 a(ii) = [ii*2]; end
n
人们手里拿着枪站成一圈。1杀2,3杀4,5杀6等等(循环),直到我们只剩下一个人。谁将是最后一个活着的人
function N = lastManStanding(n)
while length(n) ~= 1
if mod(length(n),2) == 0
for ii = 1:length(n)/2
a(ii) = [ii*2];
end
n(a) = [];
a = [];
end
if mod(length(n),2) == 1
for jj = 1:floor(length(n)/2)
b(jj) = [jj*2];
end
n(b) = [];
n = circshift(n,[0,1]);
b = [];
end
end
N = n;
这段代码的基本功能是将范围数组(1,…,n)作为输入,并返回最后剩余的索引。我想知道是否存在一个封闭形式的方程来解决这个问题,或者上面的代码是否可以进一步简化
更新
在下面找到更新的代码
function N = lastManStanding(n)
while length(n) ~= 1
if mod(length(n),2) == 0
n(2:2:end) = [];
else mod(length(n),2) == 1
n(2:2:end) = [];
n = circshift(n,[0,1]);
end
end
N = n;
更新的代码已损坏,在
else
语句之前有一个end
语句。您的代码:
function N = lastManStanding(n)
while length(n) ~= 1
if mod(length(n),2) == 0
n(2:2:end) = [];
end % <------------------------ PROBLEM!! end before else
else mod(length(n),2) == 1 % <- PROBLEM!! condition not needed for else
n(2:2:end) = [];
n = circshift(n,[0,1]);
end
end
N = n;
另外,如果完全是因为你的mod
的输出要么是0
要么是1
,那么你实际上可以删除,这就是你想要的移位量
function N = lastManStanding(n)
while length(n) ~= 1
shft = mod(length(n),2); % Have to calculate here before n gets changed
n(2:2:end) = [];
n = circshift(n,[0,shft]);
end
N = n;
注释中建议的最后一个优化是根本不使用N
。因为n
在末尾只是一个标量,所以使用
function n = lastManStanding(n)
while length(n) ~= 1
shft = mod(length(n),2); % Have to calculate here before n gets changed
n(2:2:end) = [];
n = circshift(n,[0,shft]);
end
请注意,我没有测试答案是否正确,但结果与您的相同 更新后的代码已损坏,在else
语句之前有一个end
语句。您的代码:
function N = lastManStanding(n)
while length(n) ~= 1
if mod(length(n),2) == 0
n(2:2:end) = [];
end % <------------------------ PROBLEM!! end before else
else mod(length(n),2) == 1 % <- PROBLEM!! condition not needed for else
n(2:2:end) = [];
n = circshift(n,[0,1]);
end
end
N = n;
另外,如果
完全是因为你的mod
的输出要么是0
要么是1
,那么你实际上可以删除,这就是你想要的移位量
function N = lastManStanding(n)
while length(n) ~= 1
shft = mod(length(n),2); % Have to calculate here before n gets changed
n(2:2:end) = [];
n = circshift(n,[0,shft]);
end
N = n;
注释中建议的最后一个优化是根本不使用N
。因为n
在末尾只是一个标量,所以使用
function n = lastManStanding(n)
while length(n) ~= 1
shft = mod(length(n),2); % Have to calculate here before n gets changed
n(2:2:end) = [];
n = circshift(n,[0,shft]);
end
请注意,我没有测试答案是否正确,但结果与您的相同 您也可以用更数学的方式解决这个问题,而无需循环:
%for n in [1,inf[
lastManStanding = mod(n,2.^floor((log(n)/log(2))))*2+1;
根据wolfie的建议,您也可以直接使用函数log2
lastManStanding = mod(n,2.^floor(log2(n)))*2+1;
函数mod可以处理向量,因此n可以是一个向量。您也可以不使用循环,以更数学的方式解决此问题:
%for n in [1,inf[
lastManStanding = mod(n,2.^floor((log(n)/log(2))))*2+1;
根据wolfie的建议,您也可以直接使用函数log2
lastManStanding = mod(n,2.^floor(log2(n)))*2+1;
函数mod可以处理向量,因此n可以是向量。闭式解:
如果您使用脚本绘制n=1:100的“幸存者”索引i,您将看到一个锯齿形函数,每n=2^k返回1,其中k为整数值。
这意味着在这些点上mod(n,2^k)=0
你可以发现2^k是n的2的下一个小倍数。因此k是:
在函数的边之间,当n>2^k时,函数以2*mod(n,2^k)上升。由于函数的偏移量为1,因此我们可以将闭式解写成:
i = 2 * mod(n, 2^k) + 1;
或内联:
i = 2 * mod(n, 2.^floor(log2(n))) + 1;
绘图:
更新:
这个问题也被称为约瑟夫问题。您可以在这里找到一个更一般、数学上更严格的推导:
.封闭式解决方案:
如果您使用脚本绘制n=1:100的“幸存者”索引i,您将看到一个锯齿形函数,每n=2^k返回1,其中k为整数值。
这意味着在这些点上mod(n,2^k)=0
你可以发现2^k是n的2的下一个小倍数。因此k是:
在函数的边之间,当n>2^k时,函数以2*mod(n,2^k)上升。由于函数的偏移量为1,因此我们可以将闭式解写成:
i = 2 * mod(n, 2^k) + 1;
或内联:
i = 2 * mod(n, 2.^floor(log2(n))) + 1;
绘图:
更新:
这个问题也被称为约瑟夫问题。您可以在这里找到一个更一般、数学上更严格的推导:
.考虑直接索引以从n
数组中删除条目。例如n(2:2:end)=[]
将删除没有嵌套的for
循环的内容。另外,您不需要第二条if
语句。只需添加一个else
分支。是的,我添加了。。。现在解决方案看起来好多了在之前没有结束
(在更新的代码中)考虑直接索引以从n
数组中删除条目。例如n(2:2:end)=[]
将删除没有嵌套的for
循环的内容。另外,您不需要第二条if
语句。只需添加一个else
分支。是的,我添加了。。。现在解决方案看起来好多了在之前没有end
(在更新的代码中)另一个“优化”是删除N
,只让函数N=lastManStanding(N)
使用额外的end是一个错误。现在删除它。另一个“优化”是删除N
,只让函数N=lastManStanding(N)
使用附加端是一个错误。现在删除它。由于问题是关于代码缩短的,可能值得注意的是,您可以使用log2
来缩短这个(已经非常好的)答案,例如:lastManStanding=mod(n,2^floor(log2(n)))*2+1
。你有这个解决方案的来源吗?因为问题是关于代码缩短的,也许值得注意的是,你可以使用log2
来缩短这个(已经非常好的)答案,比如:lastmanstation=mod(n,2^ floor(log2(n)))*2+1
。你有这个解决方案的来源吗?我添加了一个关于“约瑟夫问题”的参考。我添加了一个关于“约瑟夫问题”的参考。