Jeśli głównym problemem jest dobra dystrybucja chciałbym użyć pseudo losową dobry silnik:
$colorKey = bin2hex(openssl_random_pseudo_bytes(1))[0];
return '#' . $colors[$colorKey];
Nie mogę powiedzieć, jak to porównać do podziału pierwszego char z hash, ale to na pewno działa dobrze dla twoich celów.
Edit: Ponieważ wymaga mieszania, testowałem różne mieszań przeciwko pliku tekstowego 500 losowymi nazwami i znalazł CRC32 mieć najbardziej równomierne. Nie wiem, ile nazw można się spodziewać i jak dobry rozkład jest potrzebna, ale rozwiązanie wydaje się dobrym wyborem do mnie:
<?php
function sd_square($x, $mean) { return pow($x - $mean,2); }
function sd($array) {
return sqrt(array_sum(array_map("sd_square", $array, array_fill(0,count($array), (array_sum($array)/count($array)))))/(count($array)-1));
}
$crcColorCounts = array_fill_keys(range(0, 15), 0);
$file = fopen('random_names.txt', 'r');
while ($contact = fgets($file)) {
$hash = hash('crc32', $contact);
$letter = $hash[0];
$crcColorCounts[hexdec($letter)]++;
}
fclose($file);
print_r($crcColorCounts);
echo 'Standard deviation: ', sd($crcColorCounts);
wyjściowa:
Array
(
[0] => 32
[1] => 26
[2] => 33
[3] => 31
[4] => 40
[5] => 29
[6] => 33
[7] => 20
[8] => 33
[9] => 30
[10] => 39
[11] => 27
[12] => 36
[13] => 33
[14] => 29
[15] => 30
)
Standard deviation: 4.8815127436755
(standardowa funkcja odchylenie wzięte od this answer.)
Próbowałem również MD5, SHA1 i ostatni znak CRC32. Wszystkie zwrócone odchylenia standardowe około 7, czyniąc pierwszy znak CRC32 zwycięzcą.
Nie, moje zadanie nie jest losowe, ale za każdym razem takie samo (stałe) hash dla tej samej osoby, oparte na nazwie tej osoby. – vatavale
@vatavale Proszę zobaczyć moją edycję. Przetestowałem dystrybucję skrótu. –
Wow! To imponująca odpowiedź. Dziękuję Ci! – vatavale