2009-05-06 3 views
2

집합에서 가장 높은 (또는 가장 낮은) 값을 추출 할 수있는 방법이 있습니까? I는 "이 바이트의 집합"다음 경우 예를 들어, :델파이 세트에서 가장 높은 값을 얻는 방법?

[0, 1, 2, 4, 5, 28, 199] 

내가 그 실행하고 다시 199 결과를 얻을 수있는 기능이있다?

EDIT : for..in 루프와 관련된 명백한 강력한 해결책이 있습니다. 가능하다면 그보다 나은 방법을 찾고 싶습니다.

답변

13

루프는 형식적으로 올바른 방법입니다.

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 요소 제한이없는 경우

는, 당신은 델파이의 256 요소 한계가 있고, 어떤 비트 : 그건 꽤 많이, 이곳에 질문 됐어요 -twiddling 솔루션은 32- 바이트 입력을 처리해야합니다.

+3

256 맥스 카운트 루프 최상위 비트 세트 무력 아니다 찾을. 국방부에 대한 공격이나 RSA 암호 해독 시도는 무차별 적 공격입니다. 이것이 최상의 솔루션입니다. 가독성 우선 코드를 작성하십시오 (실제 병목 현상이 발생한 경우에만). – paxdiablo

+0

그런 종류의 비트 집합으로 내부 구현에 의존하지 않는가? 그렇지 않으면 모든 가능한 값을 반복하는 대신 집합의 요소를 반복하는 것이 좋습니다. – jpfollenius

+0

더 매끄럽고 모든 가능한 값을 확인하는 것 외에는 집합의 내용을 열거 할 방법이 없습니다. 내부적으로 "for-in"루프가 작동하는 방식입니다. 코드로 시연 한 메서드는 내부 표현에 의존하지 않고 집합 만 유한합니다.비트 열렬한 해결책은 내부 표현에 의존하지만 이는 매우 안전한 가정입니다. 델리는 결코 변하지 않았습니다. 그들은 터보 파스칼에서 돌아온 것과 같습니다. –

6

세트의 순서는 정해져 있지 않으므로 루프보다 훨씬 좋을 것입니다. 한 세트의 최소/최대 값을 지속적으로 찾으려면 heap data structure을 사용하십시오.이 값은 최소값/최대 값을 얻기 위해 O (1) 검색을 제공하고 다른 값에는 O (log n) 검색을 제공합니다.

2

다음은 바이트 세트의 내부 구조에 대한 지식을 사용하는 조금 더 빠른 버전입니다.

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을 거의 모든 설정 유형으로 변경할 수 있으며이 기능은 여전히 ​​작동해야합니다. 함수의 decland와 body 안에있는 TByteSet을 설정의 타입으로 대체하면됩니다. 또한 AnsiChar 집합이나 일부 열거 형 집합을 사용하는 경우 실제 요소 형식을 반환하도록 수정할 수 있습니다. 가장 낮은 값을 얻으려면 "I"for 루프를 "0 to SizeOf (TByteSet) - 1"로 변경하고 "J"루프의 if 테스트를 "if (B shl J) 및 $ 80 <> 0"으로 변경하십시오.

+1

흠 "platform"과 "deprecated"외에도 "endianunsafe"지시어가 필요합니다 :-) –

1
거의 동일한

있지만 짧을 :

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; 
1
최고

최저 수학 기기를 사용하지 :

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; 
+1

답변에 대한 설명을 추가하십시오. 그것은 단지 코드 조각보다 도움이 될 것입니다. – Billa

관련 문제