我正在寻找一种更有效的算法来确定一个数组是否包含从1到数组长度的所有值。我设计的解决方案使用Ada2012可以正常工作。
------------------------------------------------------------------
-- Build a function to determine whether an array contains --
-- all the values from 1 through the length of the array. --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
procedure Sequence_test is
type Sequence_Array is array(Positive range <>) of Integer;
function Is_Sequence(Item : Sequence_Array) return Boolean is
Flags : Array(Positive range 1..Item'Length) of Boolean := (Others => False);
begin
for Num of Item loop
if Num in Flags'Range then
Flags(Num) := True;
else
exit;
end if;
end loop;
return (for all P of Flags => P = True);
end Is_Sequence;
A : Sequence_Array := (1,2,3,4,5,6);
B : Sequence_Array := (6,5,4,3,2,1);
C : Sequence_Array := (1,1,1,6,6,6);
D : Sequence_Array := (1,2,3,4,6);
E : Sequence_Array := (6,1,5,2,4,3);
F : Sequence_Array := (1,1,1,2,3,4,5,9,10,11);
begin
Put_Line("A is " & Boolean'Image(Is_Sequence(A)));
Put_Line("B is " & Boolean'Image(Is_Sequence(B)));
Put_Line("C is " & Boolean'Image(Is_Sequence(C)));
Put_Line("D is " & Boolean'Image(Is_Sequence(D)));
Put_Line("E is " & Boolean'Image(Is_Sequence(E)));
Put_Line("F slice is " & Boolean'Image(Is_Sequence(F(3..7))));
end Sequence_test;我的程序的输出是
A is TRUE
B is TRUE
C is FALSE
D is FALSE
E is TRUE
F slice is TRUE发布于 2017-02-06 23:24:19
您可以使用一些内置的set support。我不认为它可以保证执行得更快,但是如果你打开了完全优化,并且你的编译器的优化器很好,它可能会执行得更快。我之所以这样说,是因为它可以打包数组,一次比较32个布尔,而不是每个布尔都需要循环迭代。同样,它也可以一次创建32个布尔比较数组。
当然,如果您的优化器是 good,那么它可能会知道如何使用您已有的代码做同样的事情。
function Is_Sequence(Item : Sequence_Array) return Boolean is
All_There constant : Array(Positive range 1..Item'Length) of Boolean
:= (Others => True);
Flags : Array(Positive range 1..Item'Length) of Boolean := not All_There;
begin
for Num of Item loop
if Num in Flags'Range then
Flags(Num) := True;
else
exit;
end if;
end loop;
return Flags = All_There;
end Is_Sequence;我对您的另一个建议是用您知道它不匹配的return False;替换该退出语句,因此在例程中挂起并做更多的工作是没有意义的。
发布于 2017-02-07 00:43:49
在我的电脑上,我得到了一个稍微好一点的结果
for Num of Item loop
exit when Num not in Flags'Range;
Flags(Num) := True;
end loop;
return (for all P of Flags => P);更令人惊讶的是,命名的子类型似乎提供了更好的结果:
type Item_Length_Array is array(Positive range 1..Item'Length) of Boolean;
Flags : Item_Length_Array := (others => False);测试时使用:
Start_Time := Ada.Real_Time.Clock;
for I in 1..10_000_000 loop
Ignore := Is_Sequence(A);
Ignore := Is_Sequence(B);
Ignore := Is_Sequence(C);
Ignore := Is_Sequence(D);
Ignore := Is_Sequence(E);
Ignore := Is_Sequence(F(3..7));
end loop;
End_Time := Ada.Real_Time.Clock;https://stackoverflow.com/questions/42070891
复制相似问题