Esse desafio é ler linhas aleatórias de um arquivo potencialmente enorme sem ler o arquivo inteiro na memória.
Entrada
Um número inteiro n
e o nome de um arquivo de texto.
Resultado
n
linhas do arquivo de texto escolhidas uniformemente aleatoriamente sem substituição.
Você pode assumir que n
está no intervalo de 1 ao número de linhas no arquivo.
Tenha cuidado ao amostrar n
números aleatoriamente no intervalo em que a resposta que você obtém é uniforme. rand()%n
em C não é uniforme, por exemplo. Todo resultado deve ser igualmente provável.
Regras e restrições
Cada linha do arquivo de texto terá o mesmo número de caracteres e não terá mais que 80.
Seu código não deve ler nenhum conteúdo do arquivo de texto, exceto:
- Aquelas linhas que produz.
- A primeira linha a descobrir quantos caracteres por linha existem no arquivo de texto.
Podemos assumir que cada caractere no arquivo de texto ocupa exatamente um byte.
Supõe-se que os separadores de linha tenham 1 byte de comprimento. As soluções podem usar separadores de linha longa de 2 bytes apenas se especificarem essa necessidade. Você também pode assumir que a última linha é encerrada por um separador de linhas.
Sua resposta deve ser um programa completo, mas você pode especificar a entrada da maneira que for mais conveniente.
Línguas e bibliotecas
Você pode usar qualquer idioma ou biblioteca que desejar.
Notas
Havia uma preocupação em calcular o número de linhas no arquivo. Como nimi aponta nos comentários, você pode inferir isso do tamanho do arquivo e do número de caracteres por linha.
Motivação
No bate-papo, algumas pessoas perguntaram se essa é realmente uma pergunta "Faça X sem Y". Interpreto isso para perguntar se as restrições são extraordinariamente artificiais.
A tarefa de amostragem aleatória de linhas de arquivos enormes não é incomum e é de fato uma que às vezes tenho que fazer. Uma maneira de fazer isso é no bash:
shuf -n <num-lines>
No entanto, isso é muito lento para arquivos grandes, pois ele lê o arquivo inteiro.
fseek
, e impossível em outros. Além disso, e se n
for maior que o número de linhas no arquivo?
sum()
. Não ler um arquivo na memória é uma restrição clara e consistente que não é de forma alguma arbitrária. Ele pode ser testado com um arquivo maior que a memória, que não pode ser contornado por diferenças de idioma. Também tem aplicativos do mundo real (embora isso não seja necessário para um golfe ...).