Сделать все элементы массива уникальными
Есть массив с 10 элементами, содержащими числа от 0 до 20. Надо сделать так, чтобы не было одинаковых элементов, чтобы они заменились на любое другое число (от 0 до 20). Ума не приложу, как это сделать.
Готовый код не нужен, просто подкиньте алгоритм, как это всё организовать. |
Код:
WhoIs = {} |
а если сразу формировать массив с уникальными элементами ? чтоб его потом не проверять на повторы
|
рони, тогда массив станет меньше. А если добавить в него рандомное число, оно может совпасть с каким-нибудь оставшимся в массиве числом.
micscr, а причём тут хэш? |
Цитата:
|
Цитата:
|
-------------
Есть вариант — напустить на массив array_unique, потом, пока массив не примет прежний размер, добавлять в него рандомные числа, предварительно проверяя, не нахоятся ли они уже внутри него. Но порядок чисел должен сохраняться, поэтому это не подходит. |
Цитата:
|
функция формирования массива с уникальными данными с заданной длиной и диапазоном
<script language="JavaScript" type="text/javascript"> function random(min,max,l) {var arr = [],m = [],n = 0; if (max - min < l-1) return; for (var i=0; i<=(max-min); i++)m[i] = i + min; for (var i=0; i<l; i++) {n = Math.floor(Math.random()*(m.length)); arr[i]=m.splice(n,1)[0];}; return arr } document.write(JSON.stringify(random(0,20,10))) </script> |
вариант отлова на скорую руку
<script language="JavaScript" type="text/javascript"> function usefloor(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } var m = [], s = [], t = []; var l = 10; //длина массива var min = 0; var max = 20; //создание массива m с неуникальными элементами for (var i = 0; i < l; i++) { m[i] = usefloor(min, max) } var test="<br>" + m; //создание массива t из оставшихся элементов на случай замены for (var i = 0; i <= (max - min); i++) { s[i] = 1; } for (var i = 0; i < l; i++) { s[m[i]] = 0; } for (var i = 0; i < s.length; i++) { if (s[i] == 1) t.push(i) } test+="<br>" + t; //проверка m на уникальность и замена повторяющихся элементов for (var i = 0; i < l; i++) { for (var k = i + 1; k < l; k++) { if (m[k] == m[i]) { n = usefloor(0, (t.length - 1)); m[k] = "<font color='#FF0000'>" + t[n] + "</font>"; t.splice(n, 1); } } } document.write(test+"<br>" + m); </script> |
|
рони, спасибо за помощь. То, что нужно.
|
Здравствуйте. При использовании данной функции,взятой из этой темы(спасибо рони), очень часто выскакивает значение "undefined". Не могу понять, где я накосячил переделывая написанное рони в функцию.
function addArray(letterOfArray, arrayOfCorrelation) { function usefloor(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } var m = [], s = [], t = []; var l = 9; //длина массива var min = 1; var max = 9; //создание массива m с неуникальными элементами for (var i = 0; i < l; i++) { m[i] = usefloor(min, max) } var test = m; //создание массива t из оставшихся элементов на случай замены for (var i = 0; i <= (max - min); i++) { s[i] = 1; } for (var i = 0; i < l; i++) { s[m[i]] = 0; } for (var i = 0; i < s.length; i++) { if (s[i] == 1) t.push(i) } test = t; //проверка m на уникальность и замена повторяющихся элементов for (var i = 0; i < l; i++) { for (var k = i + 1; k < l; k++) { if (m[k] == m[i] || m[k]=="undefined") { n = usefloor(1, (t.length - 1)); m[k] = t[n]; t.splice(n, 1); } } } for (var i = 0; i < l; i++) { var count = i + 1; document.getElementById(letterOfArray + count).value = m[i]; } var arrayOfCorrelation =this.arrayOfCorrelation= m; return arrayOfCorrelation; } var arrayA; addArray("a", arrayA); addArray("b", arrayA); addArray("c", arrayA); addArray("d", arrayA); addArray("e", arrayA); addArray("f", arrayA); addArray("g", arrayA); addArray("h", arrayA); addArray("i", arrayA); document.write(arrayA); |
Stroy,
Вы лучше описали бы, что Вы хотите получить в итоге? Случайно перемешанный массив ? function Peremeshivalka(lng){ var a = {},i,out=[],n=0; for(i=0;i<lng;i++)a[i]=i; while (n!=lng){ i = Math.floor(lng*Math.random()); if(typeof(a[i])!='undefined'){ out.push(a[i]); delete a[i]; n++; } } return out; } var arr = "abcdefghi".split(''); //Массив перемешивания; var lng = arr.length; var index = Peremeshivalka(lng); var out = []; for(var i=0;i<lng;i++)out.push(arr[index[i]]); alert(out) |
Deff,
Есть 2-х мерный массив 9Х9. Хочу построчно заполнить его случайными числами в диапазоне 1-9. Каждая ячейка имеет свой id. Буква(a-i)+цифра от1-9. С функцией взятой из этой темы вроде все получается. Но частенько во второй половине массива по горизонтали вместо числа, выдается значение undefied. |
Stroy,
так взяли бы код из 9 поста и запустили девять раз , а не проверочный из 10 или вам нужно чтоб кроме строк и столбцы были разными?судоку ? |
Цитата:
При каждом запуске получите массив случайный из 9 элементов function Peremeshivalka(lng){ var a = {},i,out=[],n=0; for(i=0;i<lng;i++)a[i]=i; while (n!=lng){ i = Math.floor(lng*Math.random()); if(typeof(a[i])!='undefined'){ out.push(a[i]+1); //Добавил 1(чтобы не от 0) delete a[i]; n++; } } return out; } var out =[]; for(var i=0;i<9;i++){ out.push(Peremeshivalka(9).join(','));} alert(out.join(',\n')) // ========================== Хотя пост 9 делает тож самое не хуже // Замерил на 10000 элементах - мой быстрее :) (наверно splice(n,1)[0]; дольше, чем delete a[i]; |
Цитата:
|
Deff,
Спасибо. Попробую прикрутить Вашу функцию. Или ф-цию рони из поста 9. |
судоку sudoku
Stroy,
Судоку, простая генерация в лоб :) ... если вы видите число 300000 значит вам не повезло. :cray: <!DOCTYPE HTML> <html> <head> <title>sudoku</title> <meta charset="utf-8"> </head> <body> <script> Array.prototype.shuffle = function() { for (var a = this.length - 1; 0 < a; a--) { var b = Math.floor(Math.random() * (a + 1)), c = this[b]; this[b] = this[a]; this[a] = c } return this }; for (var arr = [], b = [], obj = {}, column = {}, d = 0, i = 0; 9 > i; i++) b.push(i + 1), obj[i] = {}, column[i] = {}; for (var k = 0; 9 > k;) { b = b.slice().shuffle(); var a = b.every(function(c, e, f) { f = (e / 3 | 0) + 3 * (k / 3 | 0); return !obj[f][c] && !column[e][c] }); d++; if (300000 <= d) break; a && (arr.push(b), b.forEach(function(c, e, f) { obj[(e / 3 | 0) + 3 * (k / 3 | 0)][c] = column[e][c] = !0 }), k++) }; document.write(arr.join('<br>')+ '<br>'+d) </script> </body> </html> |
рони,
Ну по идее - 90% судоку мон получить по первому столбцу, сдвигая элементы первого столбца для генерации следующего на один элемент по кругу Т.е. первый - генерим рандомно с наличием всех цифр по высоте, второй получаем сдвигая элементы первого столбца по кругу)мон не на один элемент, а на два(произвольное число), но идентично на такое же число для всех последующих столбцов 1 4 3 2 2 1 4 3 3 2 1 4 4 3 2 1 =========== И да, проще наверно сдвигать по строкам(метода идентична) Т.е рандом первой строки и рандом цифры циклического сдвига для всех строк |
Deff,
не уверен что твой алгоритм правильный, где гарантия что квадрат три на три будет заполнен уникально... |
рони,
Я уже делал так, сам подумай по логике! (Там еще потом мон еще строки, или столбцы свапировать (обменивать с друг с другом) случайным образом, после заполнения таблички такой методой(типо раширения вариаций) Свиг соседних не может быть кратен числу элементов в строке или столбце( а так произвольный, наверно меньше строка(или столбец).length, не помню уже, и постоянен для всех строк. |
Deff,
нет кода, нет результата, нет дум :) |
Цитата:
|
рони,
Я сбацаю, делал на фортране ёщё(Просто табличку доделываю для рулетки) |
Deff,
подожду код. Цитата:
|
Cм. Спойлер:
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="robots" content="noindex"> <title> Sudoku </title> <script src='http://code.jquery.com/jquery-1.11.0.js'></script> <style> #out { table-layout:fixed; } #out td{ width:34px; height:34px; text-align:center; vaertical-align: middle; } #out, #out tr, #out td{ padding: 0px; margin: 0px; border:none 0; border-collapse:collapse; } #out td{ border: rgba(0,0,0,.1) solid 1px; } </style> </head> <body> <div id=wrap><table id=out><tbody></tbody></table></div> <p></p> <p></p> <input type="number" min="2" max="20" value="4" id="in00"><input type="button" value="go" onclick="randomSudoku(+(in00.value))"> <script> function indexRandom(lng){ var a = {},i,out=[],n=0; for(i=0;i<lng;i++)a[i]=i; while (n!=lng){ i = Math.floor(lng*Math.random()); if(typeof(a[i])!='undefined'){ out.push(a[i]); delete a[i]; n++; } } return out; } randomSudoku = function (lng) { var ind = indexRandom(lng); //рандом первой строки; var ranTR = indexRandom(lng); //рандом перекида порядка строк в таблице; var ranCols = indexRandom(lng); //рандом перекида порядка стобцов в таблице; var ar0 = [],arr = [],i,j; ar0[0]=ind; //Рандом для первой строки for(i=1;i<lng;i++){ //Формируем табличку ar0[i]=ar0[i-1].slice(0); ar0[i].unshift(ar0[i].pop()); } for(i=0;i<lng;i++){ //рандом стобцов; arr[i]=[]; for(j=0;j<lng;j++)arr[i][j]=ar0[i][ranCols[j]]; } var out=[];$('#out tr').remove(); for(i=0;i<lng;i++){ out[i]=arr[ranTR[i]];//рандом строк; var str ='<tr>'; for(j=0;j<lng;j++)str+='<td>'+out[i][j]+'</td>'; str+='</tr>';$('#out tbody').append(str) } } </script> </body> </html> ========================== Гы, хотя это может еще не судоку - посмотрел Вики(я то неповторяемость по строкам и столбцам смотрел, а там ток с 9Х9 и чоб в 3Х3 не повторялось); Можа завтра докую... А может и Судоку... (Засыпаю ... нужон критик...) |
Deff,
судоку варианты заполнения по строкам - критично 6 строка - если нет вариантов - 5 строка неправильный вариант по квадратам - не пробовал пока по цифрам- сначала 9 единичек и т.д. - неправильные варианты могут возникать уже на третей цифре ... самый пробивной вариант строить дерево :write: |
рони,
Да, я изучил Википедь, вроде есть одна идейка... Но чот я седни недоспал... мож к вечеру... Ксать иногда выходят если десятка два перебрать ... но пока не интересно перебором... нун алгоритм попробовать... |
Вроде родил алгоритм, если не отвлекут седни выложу
|
Ну вчерне(осталось еще парочку рандомов сделать...
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="robots" content="noindex"> <title> Sudoku </title> <script src='http://code.jquery.com/jquery-1.11.0.js'></script> <style> #out td{ width:34px; height:34px; text-align:center; vaertical-align: middle; } #out, #out tr, #out td{ padding: 0px; margin: 0px; border:none 0; border-collapse:collapse; } #out td{ border: rgba(0,0,0,.2) solid 1px; color: rgba(0,0,204,.611) } #out td:nth-child(3n+1) { border-left: rgba(0,0,0,.2) solid 3px; } #out tr:nth-child(3n) { border-bottom: rgba(0,0,0,.2) solid 3px; } #out{ table-layout:fixed; border-top: rgba(0,0,0,.2) solid 3px; border-right: rgba(0,0,0,.2) solid 3px; } </style> </head> <body> <div id=wrap><table id=out><tbody> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> </tbody></table></div> <p></p> <p></p> <input type="button" value="Запустить!" onclick="getSudoku ()"> <script> function indexRandom(lng){ var a = {},i,out=[],n=0; while (n!=lng){ i = Math.floor(lng*Math.random()); if(typeof(a[i])=='undefined'){ a[i]=i; out.push(a[i]); n++; } } return out; } //Cдвиг группы из N строк на n-ячеек влево; function shiftLinetoN(Nstart,N,n,arr){ var j,x; for(j=Nstart;j<Nstart+N;j++){ for(x=0;x<n;x++)arr[j].unshift(arr[j].pop()); } } //Рандомная перестановка группы из трёх строк; function swap3nLines (Nstart,arr){ var i,del,index = indexRandom(3); del = arr.slice(Nstart,Nstart+3); for(i=0;i<3;i++) arr[Nstart+index[i]]=del[i]; } getSudoku = function () { var i,j,ind, arr = []; //Таблица; var line0 = arr[0] = [1,2,3,4,5,6,7,8,9]; //Рандом-Перестановка элементов первой строки; var ind=indexRandom(9); arr[0].forEach(function (x,i){arr[0][i]=ind[i]+1;}); var line1 = arr[1] = arr[0].slice(0); shiftLinetoN(1,1,3,arr); var line2 = arr[2] = arr[1].slice(0); shiftLinetoN(2,1,3,arr); //Cоздаём остальные cтроки таблицы; for(j=3;j<9;j++){ arr[j]=arr[j%3].slice(0); if(j%3==2) shiftLinetoN(j-2,3,parseInt(j/3),arr); } //Рандом-Перестановка строк в триадах строк; for(j=0;j<6;j++){ if(j%3==2) swap3nLines(j-2,arr); } //Записываем в таблу $('#out td').each(function (j){ $(this).html(arr[parseInt(j/9)][j%9]); }); } //alert(JSON.stringify(del)) </script> </body> </html> |
Deff,
:dance: |
рони,
Ну еще осталось покрутить матрицу и перестановки триад меж собою рони, Ночью Вчера осенило, (из перво-сделанной таблицы), двигать в первой триаде не на одну ячейку а на высоту минитаблы, а в остальных метод тот жа, чо и в первоначальном скрипте |
Deff,
:yes: |
Забавно, из 10 000 табличек подряд, не повторилось ни одной... (создались за 40 сек...
Гы, из 100 000 тож ни одного повтора (388 сек) =========================== Статистика на миллионе табличек: дважды повторились идентичные: 9359, (0.9% от всех) Трижды: 110, Четырежды: 3; =========== Время создания: 4230сек; ________________________________________________ Выяснил что за 800 000 антикореляционные возможности текущих перестановок существенно снижаются, вероятнсть совпадений возрастает... Мон прикинуть число комбинаций за счет перестановок наверно в районе 10^7 - 10^8 Нун добавлять Варианты перестановок. Википедь пишет, что число Вариантов табличек в районе 10^21 (Т.е у меня чичас 21/3 (= 7) - не хватает как раз двух вариантов свапа триад и кручения матрицы |
.forEach Замедлил в 4 раза с 4.5с на 1000 до 20с (ужос)
Выкинул нафиг(удобен но не для длинных тестов) |
Deff,
:) |
Deff, если есть желание проверь на повторяемость :)
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> div{ border: 3px groove #8B4513; float: left; } </style> </head> <body> <script> Array.prototype.shuffle = function() { for (var a = this.length - 1; 0 < a; a--) { var b = Math.floor(Math.random() * (a + 1)), c = this[b]; this[b] = this[a]; this[a] = c } return this }; function fn() { for (var f = [], b = [], g = {}, h = {}, n = 0, a = 0; 9 > a; a++) b.push(a + 1), g[a] = {}, h[a] = {}; for (var c = 0; 9 > c;) { for (var a = b.slice(), d = [], k = 0; 9 > d.length;) { var l = d.length, q = (l / 3 | 0) + 3 * (c / 3 | 0), e = (3 > l ? a.slice(-6) : a).filter(function(a) { return !h[l][a] && !g[q][a] && -1 === d.indexOf(a) }); if (e.length) { var m = Math.floor(Math.random() * e.length), e = e[m]; d.push(e); m = a.indexOf(e); a.splice(m, 1) } else a = b.slice(), d = []; k++; if (50 <= k) { k = 0; break } } a = d.concat(a.shuffle()); b = !c || a.every(function(a, p, b) { b = (p / 3 | 0) + 3 * (c / 3 | 0); return !g[b][a] && !h[p][a] }); n++; if (40 <= n) break; b ? (f.push(a), a.forEach(function(a, b, d) { g[(b / 3 | 0) + 3 * (c / 3 | 0)][a] = h[b][a] = !0 }), c++) : (c--, 0 > c && (c = 0), a = f[c] || [], f.length = c, a.forEach(function(a, b, d) { g[(b / 3 | 0) + 3 * (c / 3 | 0)][a] = h[b][a] = !1 })); b = a } return 9 == f.length ? f : fn() }; var d = performance.now(); for (var i=0; i<10000 ; i++) {fn()}; alert('10000 => '+((performance.now()-d)/100|0)/10 + 's') //время генерации 10000 for (var i=0; i<500 ; i++) {document.write('<div>'+fn().join('<br>')+'</div>') }//500 вариантов для визуальной проверки </script> </body> </html> |
Ну да, у тьву шустро - 10000 за 3.5 сек(В Мозилле)) (Но у я свой тестил со старой оперы, своё там существенно медленней, и второе - у мну добавлено еще рандомы и кручение таблы. Ксать неплохо бы выводить цифру текущего кол-ва, а то в Опере думал зависло
|
Часовой пояс GMT +3, время: 21:07. |