제 질문의 제목은 자기 설명 적입니다. 3 개의 64 비트 변수 구조를 해시 할 필요가 있습니다 (각 문자열을 문자로 변환합니다). 각각 하나의 카드 - 카드 게임 앱이 포함되어 있으므로 이러한 변수에서 일부 문자를 서로 바꿔야 동일한 해시를 생성 할 수 있습니다. 한 가지 방법은 결과 문자열을 정렬하는 것입니다. 더 나은 해결책이 있습니까?char의 위치를 존중하지 않는 문자열의 해시 함수
답변
손 모양이 비트 세트와 비슷하면 이미 순서가 지정되어 있습니다. 당신은 카드의 조합을 나타내는 비트 마스크의 조합을 사용하는 경우이
A♠ - 0x00000001
2♠ - 0x00000002
3♠ - 0x00000004
4♠ - 0x00000008
...
K♠ - 0x00001000
A♥ - 0x00002000
2♥ - 0x00004000
...
는 다음 비트의 조합을 사용하여 손을 나타낼 수처럼 예를 들어, 다음과 같이 말한다 :
A♠ 4♠ 2♥ - 0x00004009
이 표현 위치가 독립적이므로 핸드 4♠ A♠ 2♥
및 2♥ 4♠ A♠
은 정확히 A♠ 4♠ 2♥
과 같은 표현을 갖습니다. 이 표현을 개별 비트 반복을 통해 필요에 따라 문자열로 변환하고 1로 설정된 비트를 발견 할 때마다 문자열 표현에 카드를 추가 할 수 있습니다.
이 표현은 다음과 같이 계산할 수 있습니다 하위 32 비트로 표현의 상위 32 개 비트를 XOR이 한창 의해 32 비트 해시 코드 :
uint64_t hand = ... // A representation of hand similar to what's described above
uint32_t hash = (uint32_t)(hand^(hand >> 32));
현 내 카드 바이트로 표현되지만, 두 카드에서의 비트는 중첩 할 수
A♣ = 0x11; 10♣=0x12; K♣=0x13
있다. .. 등등.
당신은 해시 코드를 계산할 때 위에서 설명한 하나에이 표현을 변환하고, 그런 식으로 정렬 피할 수
:
// Each card is a number from 1 to 53, inclusive
uint8_t hand[HAND_SIZE] = ...; // The hand
uint64_t set = 0;
for (int i = 0 ; i != HAND_SIZE ; i++) {
set |= (1LL << hand[i]);
}
uint32_t hash = (uint32_t)(set^(set >> 32));
'uint32_t hash = (uint32_t) (set^(set >> 32)); 두 카드 (비트 위치의 32 비트 차이 포함)는 같은 값으로 해시합니다. – wildplasser
@wildplasser 왜? 슈트는 13 비트 씩 떨어져 있고 13은 32 또는 64로 나눠지지 않습니다. 일반적으로 64 비트 숫자에는 완벽한 해시가 없으며 XOR 방식이 널리 보급되어 있습니다. 예를 들어, [Java는'Long'의 해시를 계산하기 위해 이것을 사용합니다.] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Long .Java # Long.hashCode % 28 % 29) – dasblinkenlight
아니요, 처음에는 4 * 16 비트를 할당했다고 생각했지만 사용중인 하위 4 * 13 비트 만있는 것으로 보입니다. 소송 이동은 정확한 것은 아니지만 0x01 (카드 # 0)과 0x100000000 (카드 # 32)은 여전히 동일한 비트 마스크를 산출합니다. – wildplasser
이 작업을 수행하는 다른 방법은 각각의 발생 수를 계산하는 것입니다 문자를 찾은 다음 결과 벡터를 해시합니다 (벡터 count
, count[c]
은 문자 발생 횟수를 나타냅니다) c
. 나는 그것이 정렬보다 낫다는 것을 말하지 않을 것이다. (문자의 수는 고정되어 있고 (아마 꽤 낮다) 그래서 기수 정렬을 사용할 수있다.) 그러나 (나는 더 나쁜 것도 말할 수 없다). 기수 정렬을 사용한 정렬과 각 문자의 발생 횟수 계산은 선형입니다 (또한 기수 정렬 및 계수 문자는 거의 동일합니다). 따라서이 두 가지 사이에는 큰 차이가 없어야합니다.
- 1. 문자열의 해시 함수
- 2. char의 스왑 함수 *
- 3. 보안 해시 함수에서 서명되지 않은 char의 mod
- 4. C 문자열의 해싱 함수
- 5. Centerx/Y를 존중하지 않는 빌딩
- 6. 문자열의 파이썬 hash() 함수
- 7. 빠른 해시 함수
- 8. 해시 함수 .NET
- 9. 문자열의 단순 MD5 해시
- 10. 연관 noncommutative 해시 함수
- 11. Internet Explorer 스크립트 오류에서 line/char의 실제 위치를 찾으십니까?
- 12. 문자열에서 char의 색인을 찾으십니까?
- 13. C의 문자열의 위치를 반대로
- 14. 문자열의 문자 위치를 찾으십시오.
- 15. 문자열의 인덱스 위치를 호출하여
- 16. 해시 함수
- 17. 알려진 문자열의 거의 완벽한 해시
- 18. 쿠키를 존중하지 않는 Android 브라우저가 사용 중지되었습니다.
- 19. Edge는 존중하지 않는 CSS를 중요한 순서
- 20. Doctrine ORM : 케이스를 존중하지 않는 모델
- 21. 들여 쓰기를 존중하지 않는 파이썬 매크로 다운
- 22. CSS가 CSS3 열을 존중하지 않는 이유는 무엇입니까?
- 23. 페이팔 Webservice를 존중하지 않는 STARTDATE/종료 날짜
- 24. XMLDecoder가 transient 키워드를 존중하지 않는 이유는 무엇입니까?
- 25. 흐름이 포함 옵션을 존중하지 않는 것 같습니까?
- 26. Integer.MAX_VALUE를 초과하지 않는 int를 반환하는 Java 해시 함수
- 27. 크립토나 패키지의 해시 함수 해시
- 28. 퍼펙트 해시 함수
- 29. 문자열의 경우 해시 코드의 범위
- 30. XML 문자열의 해시 맵 - Android
유일한 방법은 문자 집합의 각 문자 빈도에 해시 함수를 적용하는 것입니다. – sashas
'Zobrist hashing'에 대한 Google 검색 – wildplasser