Números continuam dando repetidos

HTML

JavaScript

Lógica de programação

31/08/2022

Tento executar o sorteador de números(para a loteria) e funciona corretamente,porém algumas vezes retorna números repetidos :( Já tentei algumas opções mas continua do mesmo jeito ou remove algum número.Qual a melhor alternativa???



<!DOCTYPE html>
<html>

<head>
<button onclick="sorteio()">Sortear números!</button>

<h1 id="resultado"></h1>
<link href="style.css" rel="stylesheet" type="text/css" />

</head>
</html>

<script>
function sorteio(){
const numeroAleatorio = (min, max) => {
return Math.floor(Math.random() * 59 + 1)
};

const gerarNumerosEntre1a60 = n => {
const resultado = [];
for (let i = 0; i < n; ++i) {
resultado.push(numeroAleatorio(1,60));
}
return resultado;

}
document.getElementById("resultado").innerHTML=gerarNumerosEntre1a60(6);
}

</script>
Isabele

Isabele

Curtidas 0

Respostas

Arthur Heinrich

Arthur Heinrich

31/08/2022

Este problema se tornou clássico quando a Apple introduziu a função Shuffle nos iPods. Ele sorteava as músicas aleatoriamente e repetia muitas vezes.

Se você quer gerar uma sequência de números aleatórios sem repetição, precisa armazenar os números em um array e embaralhá-los. Depois, retorna cada número do array sequencialmente.
GOSTEI 0
Leandro Chiodini

Leandro Chiodini

31/08/2022

Tento executar o sorteador de números(para a loteria) e funciona corretamente,porém algumas vezes retorna números repetidos :( Já tentei algumas opções mas continua do mesmo jeito ou remove algum número.Qual a melhor alternativa???



<!DOCTYPE html>
<html>

<head>
<button onclick="sorteio()">Sortear números!</button>

<h1 id="resultado"></h1>
<link href="style.css" rel="stylesheet" type="text/css" />

</head>
</html>

<script>
function sorteio(){
const numeroAleatorio = (min, max) => {
return Math.floor(Math.random() * 59 + 1)
};

const gerarNumerosEntre1a60 = n => {
const resultado = [];
for (let i = 0; i < n; ++i) {
resultado.push(numeroAleatorio(1,60));
}
return resultado;

}
document.getElementById("resultado").innerHTML=gerarNumerosEntre1a60(6);
}

</script>



Para quem possa interessar.
Para sanar esse erro pode ser feitos dois passos no código já criado.

1) Substituir a estrutura de repetição FOR pela WHILE assim permitindo um controle da variável cont para que somente caso ocorrer a inserção do numero no array ela seja incrementada.

2) colocar uma validação no array que esta sendo gerado para que antes de adicionar um novo numero compare para verificar se o numero já não existe no array. Assim somente números que não são repetidos serão inseridos no array.

Código:

<!DOCTYPE html>
<html>

<head>
    <button onclick="sorteio()">Sortear números!</button>

    <h1 id="resultado"></h1>

</head>

</html>

<script>
    function sorteio() {
        const numeroAleatorio = (min, max) => {
            return Math.floor(Math.random() * 59 + 1)
        };

        const gerarNumerosEntre1a60 = n => {
            let cont = 1;
            const resultado = [];

            //Substituido o for por while para controlar a variavel por adição
            while (cont != n) {
                let numeroSorteado = numeroAleatorio(1, 60)
                
                // Inserido um check no numero gerado para verificar se ja existe no array
                if (!resultado.includes(numeroSorteado)) {
                    resultado.push(numeroSorteado);
                    cont++
                }
            }

            return resultado;

        }
        document.getElementById("resultado").innerHTML = gerarNumerosEntre1a60(6);
    }

</script>

GOSTEI 0
Arthur Heinrich

Arthur Heinrich

31/08/2022

Tento executar o sorteador de números(para a loteria) e funciona corretamente,porém algumas vezes retorna números repetidos :( Já tentei algumas opções mas continua do mesmo jeito ou remove algum número.Qual a melhor alternativa???



<!DOCTYPE html>
<html>

<head>
<button onclick="sorteio()">Sortear números!</button>

<h1 id="resultado"></h1>
<link href="style.css" rel="stylesheet" type="text/css" />

</head>
</html>

<script>
function sorteio(){
const numeroAleatorio = (min, max) => {
return Math.floor(Math.random() * 59 + 1)
};

const gerarNumerosEntre1a60 = n => {
const resultado = [];
for (let i = 0; i < n; ++i) {
resultado.push(numeroAleatorio(1,60));
}
return resultado;

}
document.getElementById("resultado").innerHTML=gerarNumerosEntre1a60(6);
}

</script>



Para quem possa interessar.
Para sanar esse erro pode ser feitos dois passos no código já criado.

1) Substituir a estrutura de repetição FOR pela WHILE assim permitindo um controle da variável cont para que somente caso ocorrer a inserção do numero no array ela seja incrementada.

2) colocar uma validação no array que esta sendo gerado para que antes de adicionar um novo numero compare para verificar se o numero já não existe no array. Assim somente números que não são repetidos serão inseridos no array.

Código:

<!DOCTYPE html>
<html>

<head>
    <button onclick="sorteio()">Sortear números!</button>

    <h1 id="resultado"></h1>

</head>

</html>

<script>
    function sorteio() {
        const numeroAleatorio = (min, max) => {
            return Math.floor(Math.random() * 59 + 1)
        };

        const gerarNumerosEntre1a60 = n => {
            let cont = 1;
            const resultado = [];

            //Substituido o for por while para controlar a variavel por adição
            while (cont != n) {
                let numeroSorteado = numeroAleatorio(1, 60)
                
                // Inserido um check no numero gerado para verificar se ja existe no array
                if (!resultado.includes(numeroSorteado)) {
                    resultado.push(numeroSorteado);
                    cont++
                }
            }

            return resultado;

        }
        document.getElementById("resultado").innerHTML = gerarNumerosEntre1a60(6);
    }

</script>



Acredito que a expressão (return Math.floor(Math.random() * 59 + 1)) retorne valores de 1 a 59.

Geralmente, a função random retorna valores no intervalo: 0 <= random < 1. Logo, se nunca retorna 1, multiplicar este valor por 59 retornará um valor < 59 e o floor removerá a parte fracionária, gerando números de 0 a 58.

O correto seria: return Math.floor(Math.random() * 60 + 1)

Para criar um array com 60 valores aleatórios entre 1 e 60, sem repetição, um algoritmo é:

var
  numeros : array[1..60] of integer;
  i, j : integer;
begin
  for i:=1 to 60 do
    begin
      j:=Random(i)+1; // retorna um inteiro tal que 0 <= j < i;
      if (j>0) then numeros[i]:=numeros[j];
      numeros[j]:=i;
    end;
end;


Desta forma, você terá os seus 60 números aleatórios, sem repetição.

Outra possibilidade seria criar um array com todos os números, sequencialmente, como se fossem um conjunto de números selecionáveis.

A cada sorteio, você seleciona uma posição do array, entre o primeiro e enésimo elemento, para ser retornado, e preenche a lacuna (espaço do array que foi desalocado) com o último elemento do array (posição n), diminuindo o "n". Enquanto n for maior que zero, significa que o conjunto ainda contém elementos não sorteados.
GOSTEI 0
Arthur Heinrich

Arthur Heinrich

31/08/2022


Acredito que a expressão (return Math.floor(Math.random() * 59 + 1)) retorne valores de 1 a 59.

Geralmente, a função random retorna valores no intervalo: 0 <= random < 1. Logo, se nunca retorna 1, multiplicar este valor por 59 retornará um valor < 59 e o floor removerá a parte fracionária, gerando números de 0 a 58.

O correto seria: return Math.floor(Math.random() * 60 + 1)

Para criar um array com 60 valores aleatórios entre 1 e 60, sem repetição, um algoritmo é:

var
  numeros : array[1..60] of integer;
  i, j : integer;
begin
  for i:=1 to 60 do
    begin
      j:=Random(i)+1; // retorna um inteiro tal que 0 <= j < i;
      if (j>0) then numeros[i]:=numeros[j];
      numeros[j]:=i;
    end;
end;


Desta forma, você terá os seus 60 números aleatórios, sem repetição.

Outra possibilidade seria criar um array com todos os números, sequencialmente, como se fossem um conjunto de números selecionáveis.

A cada sorteio, você seleciona uma posição do array, entre o primeiro e enésimo elemento, para ser retornado, e preenche a lacuna (espaço do array que foi desalocado) com o último elemento do array (posição n), diminuindo o "n". Enquanto n for maior que zero, significa que o conjunto ainda contém elementos não sorteados.


Eu cometi um erro no meu algoritmo.

O correto é:

var
  numeros : array[1..60] of integer;
  i, j : integer;
begin
  for i:=1 to 60 do
    begin
      j:=Random(i)+1; // retorna um inteiro tal que 1 <= j <= i;
      if (j<i) then numeros[i]:=numeros[j];
      numeros[j]:=i;
    end;
end;


Neste algoritmo, o que é sorteado aleatoriamente é a posição no array onde o próximo elemento será armazenado, executando o loop uma única vez para cada número. O algoritmo tem um custo de ordem O(n).

No outro algoritmo, onde se sorteia um número aleatório a ser armazenado na próxima posição do array, para que não haja repetição, é necessário varrer o array para ver se ainda não foi sorteado. Quanto mais próximo do final, maior a chance de já ter sido sorteado e ter que repetir o sorteio, aumentando o custo do processamento. O custo desse algoritmo é de ordem O(n2), ou pior.
GOSTEI 0
POSTAR