Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Генерация случайных числ без повторений (https://javascript.ru/forum/misc/75537-generaciya-sluchajjnykh-chisl-bez-povtorenijj.html)

ytil 17.10.2018 16:46

Генерация случайных числ без повторений
 
Привет обитателям форума :)

учебная задача с которой я сегодня столкнулся звучит так:

Цитата:

"Сделайте функцию, каждый вызов который будет генерировать случайные числа от 1 до 100, но так, чтобы они не повторялись, пока не будут перебраны все числа из этого промежутка. Решите задачу через замыкания - в замыкании должен хранится массив чисел, которые уже были сгенерированы функцией."
В процессе решения данной задачи получилось следующее:
function makeRand() {
    var usedNumbers = [];
    function f() {

        outer:
        while(true) {
            var num = Math.floor(Math.random() * 100) + 1;
            for (var i = 0; i < usedNumbers.length; i++) {
                if (usedNumbers[i] === num) break outer;
            } break;
        }
        usedNumbers.push(num);
        return num;

    }
    return f;
}

var func = makeRand();

func();


но данный код почему-то не работает, в массив попадают уже использованные числа, после еще часа мучений было придумано решение с рекурсией которое работает, но кажется выглядит как дикий костыль.

function makeRand() {
    var usedNumbers = [];
    function f() {
        if (usedNumbers.length === 100) {
            return;
        }
        var num = Math.floor(Math.random() * 100) + 1;
        for (var i = 0; i < usedNumbers.length; i++) {
            if (num === usedNumbers[i]) return f();
        }
        usedNumbers.push(num);
        return num;
    }
    return f;
}

var func = makeRand();

//ниже вызов много раз
func();


Собственно вопросы:
1. Почему код с конструкцией while(true) break output не работает правильно
2. Какое оптимальное решение вы видите в данной задаче?

рони 17.10.2018 17:00

ytil,
создать массив и перемешать.

ytil 17.10.2018 17:16

Цитата:

Сообщение от рони (Сообщение 496521)
ytil,
создать массив и перемешать.

если без создания нового массива?

рони 17.10.2018 17:23

Цитата:

Сообщение от ytil
если без создания нового массива?

не понимаю, а где хранить результат?

рони 17.10.2018 17:33

Генерация случайных числ без повторений
 
ytil,
<script>
function makeRand(num) {
    var usedNumbers = [num--];
    !function f() {
        var i = Math.round(Math.random() * usedNumbers.length);
        usedNumbers.splice(i,0,num--);
        num && f()
    }();
    return usedNumbers;
}

var arr = makeRand(100);

document.write(arr)
  </script>

ytil 17.10.2018 18:00

задача там не в том, чтобы хранить результат, а в том чтобы выводить числа которые были не использованы. Почему мой код с циклом не работает? можете взглянуть?

рони 17.10.2018 18:22

Цитата:

Сообщение от ytil
том чтобы выводить числа которые были не использованы.

так создайте упорядоченый массив и доставайте из него хаотично
Цитата:

Сообщение от ytil
Почему мой код с циклом не работает? можете взглянуть?

не могу помочь, проще ещё кучу своих варииантов написать

ytil 17.10.2018 18:25

Цитата:

Сообщение от рони (Сообщение 496529)
так создайте упорядоченый массив и доставайте из него хаотично

спасибо за советы

рони 17.10.2018 18:35

Цитата:

Сообщение от ytil
чтобы выводить числа которые были не использованы

<script>
function makeRand(num) {
    var usedNumbers = {length : 0};
    function f() {
        if(usedNumbers.length == num) usedNumbers = {length : 0};
        var i = Math.floor(Math.random() * num);
        return i in usedNumbers ? f() : (usedNumbers.length++, usedNumbers[i]=true, ++i)

    }
    return f;
}

var x = makeRand(100);

document.write(x()+"<br>");
document.write(x()+"<br>");
document.write(x()+"<br>");
  </script>

рони 17.10.2018 18:44

ytil,
для новых браузеров
<script>
function makeRand(num) {
    var usedNumbers = [];
    function f() {
        if(usedNumbers.length == num) usedNumbers = [];
        var i = Math.floor(Math.random() * num) + 1;
        return usedNumbers.includes(i) ? f() : (usedNumbers.push(i),i)

    }
    return f;
}

var x = makeRand(100);

document.write(x()+"<br>");
document.write(x()+"<br>");
document.write(x()+"<br>");
  </script>


Часовой пояс GMT +3, время: 19:42.