Espero poder contribuir com algo novo para esse problema. Percebi que todas as respostas negligenciam o fato de que existem dois pontos em que você pode executar o pré-processamento , sem diminuir o desempenho geral da lavanderia.
Além disso, não precisamos assumir um grande número de meias, mesmo para famílias grandes. As meias são retiradas da gaveta e desgastadas e depois jogadas em um local (talvez uma lixeira) onde ficam antes de serem lavadas. Embora eu não chamasse o bin bin de LIFO-Stack, eu diria que é seguro assumir que
- as pessoas jogam as duas meias aproximadamente na mesma área da lixeira,
- o compartimento não é randomizado em nenhum momento e, portanto,
- qualquer subconjunto retirado da parte superior desse compartimento geralmente contém as duas meias de um par.
Como todas as máquinas de lavar roupa que eu conheço são de tamanho limitado (independentemente de quantas meias você precisa lavar), e a randomização real ocorre na máquina de lavar, não importa quantas meias nós temos, sempre temos pequenos subconjuntos que quase não contêm singletons.
Nossas duas etapas de pré-processamento são "colocar as meias no varal" e "Tirar as meias do varal", o que temos que fazer para obter meias que não são apenas limpas, mas também secas. Assim como as máquinas de lavar, os varais são finitos e presumo que tenhamos toda a parte da linha em que colocamos nossas meias à vista.
Aqui está o algoritmo para put_socks_on_line ():
while (socks left in basket) {
take_sock();
if (cluster of similar socks is present) {
Add sock to cluster (if possible, next to the matching pair)
} else {
Hang it somewhere on the line, this is now a new cluster of similar-looking socks.
Leave enough space around this sock to add other socks later on
}
}
Não perca seu tempo movendo as meias ou procurando a melhor combinação, tudo isso deve ser feito em O (n), que também seria necessário para colocá-las na linha sem classificação. As meias ainda não estão emparelhadas, só temos vários grupos de similaridade em jogo. É útil termos um conjunto limitado de meias aqui, pois isso nos ajuda a criar grupos "bons" (por exemplo, se houver apenas meias pretas no conjunto de meias, agrupar por cores não seria o caminho a seguir).
Aqui está o algoritmo para take_socks_from_line ():
while(socks left on line) {
take_next_sock();
if (matching pair visible on line or in basket) {
Take it as well, pair 'em and put 'em away
} else {
put the sock in the basket
}
Devo ressaltar que, para melhorar a velocidade das etapas restantes, é aconselhável não escolher aleatoriamente a próxima meia, mas sequencialmente tirar meia após meia de cada cluster. Ambas as etapas de pré-processamento não levam mais tempo do que colocar as meias na linha ou na cesta, o que temos que fazer, não importa o que aconteça, portanto isso deve melhorar muito o desempenho da lavanderia.
Depois disso, é fácil executar o algoritmo de particionamento de hash. Normalmente, cerca de 75% das meias já estão emparelhadas, deixando-me com um subconjunto muito pequeno de meias, e esse subconjunto já está (um pouco) agrupado (não introduzo muita entropia na minha cesta após as etapas de pré-processamento). Outra coisa é que os clusters restantes tendem a ser pequenos o suficiente para serem manuseados de uma só vez, portanto, é possível retirar um cluster inteiro da cesta.
Aqui está o algoritmo para sort_remaining_clusters ():
while(clusters present in basket) {
Take out the cluster and spread it
Process it immediately
Leave remaining socks where they are
}
Depois disso, restam apenas algumas meias. É aqui que introduzo meias anteriormente não emparelhadas no sistema e processo as meias restantes sem nenhum algoritmo especial - as meias restantes são muito poucas e podem ser processadas visualmente muito rapidamente.
Para todas as meias restantes, suponho que os colegas ainda não estejam lavados e os guardo para a próxima iteração. Se você registrar um crescimento de meias não emparelhadas ao longo do tempo (um "vazamento de meia"), verifique sua lixeira - ela pode ser aleatória (você tem gatos que dormem lá?)
Eu sei que esses algoritmos têm muitas suposições: uma lixeira que funciona como algum tipo de pilha LIFO, uma máquina de lavar normal limitada e um varal normal, limitado - mas isso ainda funciona com um número muito grande de meias.
Sobre o paralelismo: contanto que você jogue as duas meias na mesma lixeira, é possível paralelizar facilmente todas essas etapas.