Esta questão é sobre gerar números aleatórios entre um intervalo, o que é bom, mas não se encaixa no meu caso.
Vou explicar em termos de SQL porque me parece mais fácil de entender, embora a pergunta seja sobre bash
. Minha ideia é com os resultados do bash
código construir um script SQL.
Eu tenho duas tabelas MySQL, uma de pessoas e outra de lugares. Cada registro tem um id inteiro único que vai de 1 a 139 (lugares) e 1 a 1519 (pessoas). Eles estão ligados entre si por uma chave estrangeira, ou seja: um lugar pode ter muitas pessoas, mas uma pessoa pode ter apenas um lugar.
# 1-139 # 1-1519
place1 → person1
→ person2
→ person3
... and so on
Os dados que tenho agora é que em um lugar todas as pessoas estão vinculadas, e o resto dos lugares sem nenhuma.
Os lugares são 139 e as pessoas são 1519, então eu tenho um lugar com 1519 pessoas.
Meu objetivo é distribuir as pessoas aleatoriamente pelos lugares, e que cada lugar tenha pelo menos uma pessoa.
Meu código até agora é este:
$ c=1519
$ while [[ $c -ne 0 ]]; do
x=$((shuf -i 1-139 -n 1))
[[ $x -gt 139 ]] && continue
echo $x
(( c-- ))
done
Este código gera 1519 números aleatórios entre 1-139, então agora posso ter cada pessoa vinculada a um lugar aleatório.
Minhas perguntas são:
- Existe uma maneira mais eficiente de fazer isso?
- Como posso controlar que cada lugar tenha pelo menos uma pessoa?
Eu prefiro fazer isso no bash
, mas estou aberto a outras soluções que não envolvam isso.
Se você quiser fazer isso apenas usando ferramentas comumente disponíveis (pelo menos em distribuições Linux), a maneira mais eficiente provavelmente é perguntar
shuf
:Isso produz 1519 números escolhidos aleatoriamente entre 1 e 139.
Para garantir que cada lugar receba uma pessoa, embaralhe primeiro 139 números sem repetir:
Para reduzir o efeito “primeiros 139” (as primeiras 139 pessoas acabariam em lugares diferentes), embaralhe tudo novamente:
Assumindo que as pessoas estão armazenadas na
person
tabela e que cada pessoa tem umplace_id
que precisa ser um inteiro entre 1 e 139. Usando SQL, atualizando aperson
tabela diretamente:Isso deve atualizar cada entrada na tabela, randomizando a
place_id
chave. No entanto, é totalmente não testado.Após a atualização, você pode testar se cada lugar é representado usando
Isso deve retornar
1
se todos os lugares estiverem representados, caso contrário, retornará0
.Se quisermos que os valores sejam distribuídos o mais uniformemente possível (considerando o fato de que 1519 é 10 a menos de ser um múltiplo exato de 139), em vez de apenas evitar lugares vazios, devemos gerar uma sequência de repetição suficientemente grande de 1, ..., 139, 1, ..., 139, 1, ..., e então embaralhe os primeiros 1519 membros disso:
Se precisarmos de mapeamentos de pessoas para lugares, podemos simplesmente numerar as linhas de saída:
NB isso é tudo shell padrão; não há necessidade de nenhuma extensão Bash.