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

我写了一个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(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
。你有这个解决方案的来源吗?我添加了一个关于“约瑟夫问题”的参考。我添加了一个关于“约瑟夫问题”的参考。