セット内で最高(または最低)の値を抽出する方法はありますか?たとえば、次の「バイトのセット」がある場合:デルファイセットから最高の価値を得るには?
[0, 1, 2, 4, 5, 28, 199]
私はそれを実行して結果として199を返すことができますか?
EDIT:for..inループを含む明白な強硬な解決策があります。可能であれば、私はそれより良い方法を見つけたいと思っています。
セット内で最高(または最低)の値を抽出する方法はありますか?たとえば、次の「バイトのセット」がある場合:デルファイセットから最高の価値を得るには?
[0, 1, 2, 4, 5, 28, 199]
私はそれを実行して結果として199を返すことができますか?
EDIT:for..inループを含む明白な強硬な解決策があります。可能であれば、私はそれより良い方法を見つけたいと思っています。
ループは実際には正式に正しい方法です。
type
TSetType = set of TEnumType;
function HighestMember(const s: TSetType): TEnumType;
begin
for Result := High(Result) downto Low(Result) do
if Result in s then
exit;
raise Exception.Create('empty sets have no highest member');
end;
ソリューションの他の種類は、型の安全性を失うことを強制どちらも、タイプキャストやアセンブラが必要になります - 彼らは行く「言語の外に、」いわば。
あなたのセットが32個以下の要素を持つことが保証できるならば、そのセットは通常の整数でオーバレイでき、あなたの質問は32ビットで設定された最高ビットの位置を求めるのと同じです整数。あなたがセットタイプの32の要素の制限を持っていない場合、あなたはDelphiの256要素に制限されてい
、および任意のビット:それはかなり、前にここで質問されています-twiddlingソリューションは、32- バイトの入力を処理する必要があります。
セットは順不同なので、ループよりもはるかに良くなりません。常に最小値/最大値を調べる場合は、heap data structureを使用します。これはO(1)ルックアップを使用して最小/最大値を取得し、O(log n)ルックアップを他の値に適用します。
ここでは、バイトセットの内部構造の知識を使用した少し速いバージョンです。
type
TByteSet = set of Byte;
function HighestElement(const ByteSet: TByteSet): Byte;
type
TSetBytes = array[0..SizeOf(TByteSet) - 1] of Byte;
var
I, J: Integer;
B: Byte;
SetBytes: TSetBytes;
begin
if ByteSet <> [] then
begin
SetBytes := TSetBytes(ByteSet);
// Start at the top and work down, one byte at a time
for I := SizeOf(TByteSet) - 1 downto 0 do
begin
// Any bits set here
B := SetBytes[I];
if B <> 0 then
begin
Result := I * 8;
for J := 0 to 7 do
if (B shr J) and 1 <> 0 then
begin
Result := Result + J;
Exit;
end;
end;
end;
end else
// No elements set
end;
セットのタイプ(TByteSet)をほぼすべてのセットタイプに変更できますが、この機能は引き続き有効です。関数declとbodyの中のTByteSetをあなたのセットの型に置き換えてください。また、AnsiCharのセットを使用している場合は実際の要素タイプを返すように、また一部の列挙型のセットを返すように変更することもできます。最低値を取得するには、 "I"ループを "0〜SizeOf(TByteSet)-1"に変更し、 "J"ループのifテストを "if(B shl J)および$ 80 <> 0"に変更します。
ええと、 "platform"と "deprecated"以外にも、 "endianunsafe"指示が時間内に必要になります:-) –
ほぼ同じですが、短い:
type
TByteSet = set of Byte;
function MaxSet(S: TByteSet): Byte;
var
CardArr: Array [0..7] of Cardinal absolute S;
i: Byte;
begin
i := 7;
while (i > 0) AND (CardArr[i] = 0) do
Dec(i);
Result := i + Floor(Log2(CardArr[i]));
end;
最高と最低、数学ユニットを使用しない:最高のビットセットを見つけるため
type
TCharSet = set of Char;
function MaxOfSet(aSet: TCharSet):Char;
var
Data:array[0..SizeOf(TCharSet)-1] of Byte absolute aSet;
i,r:Byte;
begin
if aSet<>[] then begin
i:=SizeOf(TCharSet)-1;
while (i>0) and (Data[i]=0) do
Dec(i);
r:=i*8;
i:=Data[i];
while (i and $80)=0 do begin
i:=i shl 1;
Dec(r)
end;
Result:=Chr(r+7)
end
else
raise Exception.Create('Unable to extract max value from an empty set');
end;
function MinOfSet(aSet: TCharSet):Char;
var
Data:array[0..SizeOf(TCharSet)-1] of Byte absolute aSet;
i,r:Byte;
begin
if aSet<>[] then begin
i:=0;
while (i<SizeOf(TCharSet)-1) and (Data[i]=0) do
Inc(i);
r:=i*8;
i:=Data[i];
while (i and 1)=0 do begin
i:=i shr 1;
Inc(r)
end;
Result:=Chr(r)
end
else
raise Exception.Create('Unable to extract min value from an empty set');
end;
答えにいくつかの説明を追加してください。ほんの一片のコードよりも役に立ちます。 – Billa
256-MAX-カウントループは、ブルートフォースではありません。国防総省への攻撃やRSAの解読を試みることは無頓着です。これが最適なソリューションです。読みやすさのためにコードを書いてください。スピードは秒です(実際のボトルネックを発見した場合のみ)。 – paxdiablo
そのようなものは、ビットセットとしてセットの内部実装に依存していますか?それ以外の場合、可能なすべての値をループするのではなく、要素の要素をループすることをお勧めします。 – jpfollenius
もっとスマッシュで、可能なすべての値をチェックする以外はセットの内容を列挙する方法はありません。内部的には、これが "for-in"ループの仕組みです。私がコードで実演した方法は、内部表現に依存せず、集合は有限である。どんなビットレートの解決策も内部表現に依存していますが、これは非常に安全な前提です。彼らはTurbo Pascalに戻ったのと同じです。 –