Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   массив со случайными числами (https://javascript.ru/forum/misc/47757-massiv-so-sluchajjnymi-chislami.html)

optron 06.06.2014 02:26

массив со случайными числами
 
Помогите создать массив c четырьмя числами. Одно число известное, три случайных в пределах от 0 до n. Ни одно из трех случайных чисел не должно быть равно известному.
И порядок всех четырех чисел в массиве должен быть случайным.

p.s. Ни одно число в массиве не должно повторятся

Aetae 06.06.2014 03:20

function rand(val,max){
    var arr = [], 
        i = 3, 
        pos = Math.floor(Math.random()*(i+1));
    while(i--){
        var rnd = Math.floor(Math.random()*max);
        arr.push(rnd >= val ? ++rnd : rnd);
    }
    arr.splice(pos,0,val);
    return arr
}

alert(rand(3,5))

optron 06.06.2014 03:31

спасибо
Работает но я еще забыл упомянуть что ни одно число не должно повторяться

jsnb 06.06.2014 03:45

Цитата:

Сообщение от optron (Сообщение 315231)
но я еще забыл упомянуть что ни одно число не должно повторяться

var num = 5;
var arr = [num];
var n = 10;
for(var i = 0; i < 3; i++) {
  do {
    var randNum = Math.round( -0.5 + Math.random()*(n+1) );
  } while( arr.indexOf(randNum) !== -1);
  arr.push(randNum);
}
arr.sort(function(){ return Math.random()-0.5 });
alert(arr);

Aetae 06.06.2014 04:38

jsnb, ужасно, даже чудовищно. Так делать нельзя никогда.

Конечно на конкретной задаче с массивом из 4 чисел вся мерзость заметна не будет, но за такой код я бы клаву об голову разбил, да.

jsnb 06.06.2014 04:58

Цитата:

Сообщение от Aetae (Сообщение 315233)
jsnb, ужасно, даже чудовищно. Так делать нельзя никогда.

Конечно на конкретной задаче с массивом из 4 чисел вся мерзость заметна не будет, но за такой код я бы клаву об голову разбил, да.

Так а как еще гарантировано обеспечить уникальность чисел в массиве, если не сравнивать с уже существующими элементами? Или ужас-ужас в сортировке?

Aetae 06.06.2014 05:20

И в сортировке - ибо она псевдорандомна и не даёт нормального распределения, и в потенциальном вечном(очень долгом) цикле бессмысленного брутфорса.
Как? Ответ в моём решении например, если его расширить.

jsnb 06.06.2014 05:36

Цитата:

Сообщение от Aetae (Сообщение 315235)
Как? Ответ в моём решении например, если его расширить.

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

Aetae 06.06.2014 05:45

Вот функция:
function rand(max, min, length){
	var result = [],
		resultSorted = [];

	if(typeof max !== 'number') return Math.random();
	if(typeof min !== 'number') return Math.floor(Math.random() * ++max);

	if(min > max) min = [max, max = min][0];                 

	if(!length || typeof length !== 'number') return Math.floor(Math.random() * (max - min + 1)) + min;

	if(length > max - min + 1) throw new RangeError('invalid length.');

	for(var j = 0, random, index; j < length; j++, max--){
		random = Math.floor(Math.random() * (max - min + 1)) + min;

		for(index = j; index && resultSorted[index-1] <= random; index--) random++; 

		result.push(random);
		resultSorted.splice(index, 0, random);
	}

	return result;
}

Генерирует массив не повторяющихся рандомных чисел из заданного диапазона заданной длины. Кое что ещё можно пооптимизировать, но суть должна быть понятна.

рони 06.06.2014 10:07

:write:
ещё вариант ... без проверки входных данных
function rand(val, min, max, length) {
        var obj = {}, arr = [val];
        obj[val] = true;
        length--;
        while (length) {
            var rnd = Math.floor(Math.random() * (max - min + 1)) + min;
            if (!obj[rnd]) {
                obj[rnd] = true;
                length--;
                arr[Math.random() > .5 ? 'push' : 'unshift'](rnd)
            };
        }

        return arr
    }

    alert(rand(3, 7, 12, 4))

Aetae 06.06.2014 15:58

рони, то же что у jsnb, только в профиль. Опять потенциально бесконечный цикл, при неудачном рандоме. И чем массив долинее тем шансы на это больше.

dwarf 07.06.2014 17:03

Aetae, а если так оформить рендом.... все равно может в бесконечность уйти ?
var random = Math.round(min - 0.5 + Math.random()*(max-min+1));

рони 07.06.2014 17:12

Aetae,
:)
<script language="JavaScript" type="text/javascript">
function random(val,min,max,l)
{var arr = [],m = [],n = void(0), len = max-min;
  l--;
  if (len < l) return;
  for (var i=0; i<= len; i++){
      m[i] = i + min;
      m[i] == val && (n = i);
  }
  n !=  void(0) &&  m.splice(n,1)
  for (var i=0; i<l; i++) {n = Math.floor(Math.random()*(m.length)); arr[i]=m.splice(n,1);};
  n = Math.floor(Math.random()*(arr.length));
  arr.splice(n,0,val)
  return arr
}
document.write(random(3,0,20,4))
</script>

источник )))

Aetae 07.06.2014 18:29

рони, вот, другое дело. Кончено при слишком большом диапазоне в памяти будет висеть гигантский массив, и я всё ещё считаю свой вариант лучше, но хоть так.)

рони 07.06.2014 21:42

Цитата:

Сообщение от Aetae
но суть должна быть понятна.

Цитата:

Сообщение от Aetae
for(index = j; index && resultSorted[index-1] <= random; index--) random++;

а что делает эта строка?

Aetae 07.06.2014 23:38

рони,
Пока есть среди уже подобранных(и отсортированных) числа меньше или равные числу сгенерированному на текущей итерации - инкрементируем оное.
Т.о. не допускается повторов, и при этом соблюдается нормальное распределение.

В моём коде две проблемы: наличие дублирующего, но отсортированного массива и использование условно-медленного splice.


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