Модераторы: Sardar, Aliance

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> генерация таблицы игр чемпионата 
:(
    Опции темы
krinart
Дата 10.4.2008, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



народ!! подскажите как написать рабочий алгоритм генерации таблицы игр для n команд....

сколько пытался - не получается.. всё время получается зацикливание.... smile 
PM MAIL ICQ   Вверх
JackYF
Дата 10.4.2008, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: нет
Всего: 162



Попытки кода в студию.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
krinart
Дата 10.4.2008, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



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

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

заранее спасибо, жду вашего мнения

Код


var team, tour; // переменный циклы, названы для удобства
var n= 6;        // количество команд, можно изменять
var a= new Array(); // основная, формируемая таблица


function print(str)
{    document.write(str)    }

// выводит содержимое таблицы в удобной форме
function table(a)
{    
    print("<table border=1>");
    print("<th></th>");
    for(i=1; i<=n; i++)
        print("<th width='5%'>"+i+"</th>");
    
    for(i=1; i<=n-1; i++)
    {
        print("<tr>");
        print("<td width='5%'>"+"<b>"+i+"</b>"+"</td>")
        for(j=1; j<=n;j++)        
            print("<td>"+a[i][j]+"</td>");        
        print("</tr>");
    }
    print("</table>");
}

/***********************************************************************************/
// функция, которая проверят, находится ли элемент в составе двух массивов и ещё одного элемента
function my(checked, mas_team, mas_tour)
{    
    var team, tour;
    
    if(checked==mas_team)
        return true;        
    // проверим в столбце mas_team матрицы a
    for(tour=1; tour<=n-1;tour++)
        if(checked==a[tour][mas_team])
            return true;    
    // проверим в строке mas_tour матрицы a
    for(team=1; team<=n;team++)    
        if(checked==a[mas_tour][team])
            return true;        
    return false;    
}


/**********************************************************************************/
// обнулим таблицу
for(tour=1; tour<=n-1; tour++)
{
    a[tour]= new Array();        
    
    for(team=1; team<=n;team++)    
    {
        //a[i][j]= Math.floor(Math.random() * (n)+1);        
        a[tour][team]= 0;        
    }    
}



/**********************************************************************************/
// РАБОЧАЯ ЦИКЛ, СОЗДАЮШИЙ ТАБЛИЦУ

// для этого будем идти по каждой команде, 
for(team=1; team<=n; team++)
{        
    
    // теперь будем двигаться по турам и составлять таблицу
    for(tour=1; tour<=n-1; tour++)
    {                
        // проверим, нет ли данных в этой клетке
        if(a[tour][team])
            continue;
        
        // составим массив из команд, которые могут теоритически выпасть для данной команды
        // для этого снова пройдём все команды и добавим в массив те, которые ещё не играли с этой командой и не играли в данном туре
        mas= new Array();
        for(team2=1; team2<=n; team2++)
        {                
            if( !my(team2, team, tour))            
            {                
                mas[mas.length]= team2;
                print(team2);
            }            
        }
        print("-");                
        len= mas.length;
        //print(len);
        //выбираем команду наугад из созданного массива
        kom= Math.floor(Math.random() * (len));        
        print("{"+mas[kom]+"("+kom+")}=");
        
        // создаём записи в таблице
        a[tour][team]= mas[kom];
        a[tour][mas[kom]]= team;
    }    
    print("<br>");
}
table(a);



PM MAIL ICQ   Вверх
archimed7592
Дата 11.4.2008, 01:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: нет
Всего: 93




M
archimed7592
Эмм... krinart, в будущем, смотри на раздел, в котором тему создаёшь...



--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
krinart
Дата 11.4.2008, 08:41 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



понял... приношу извинения
дело в том что сначала-то я в С++ пытался, а потом незаметно для себя перешёл на javascript))
обещаю исправиться
PM MAIL ICQ   Вверх
TryLight
Дата 11.4.2008, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



На самом деле то, что ты пытаешься сделать называется "магический квадрат", т.е. матрица размером NxN, в которой элементы по строке и по столбцу не повторяются.


Твой алгоритм такой:

идем по строкам j от 1 до N
     идем по столбцам i от 1 до N
        a[i][j] = Arr[random], где Arr - массив тех элементов, которых еще нет в ни столбце(!), ни в строке(!)
след. i, j


И реально получаются накладки, вида

........|...2...|........
...1...|.Non.|...3...|...4...|...5...|...6...


Решение:
По-видимому, развертку надо делать не построчную, а диагональную, т.е.

[1][1]
[1][2], [2][1]
[1][3], [2][2], [3][1]
...

этот пример выводит в ячейки значения mas.length
Код

<html>
<head>
<meta http-equiv="Conkomtenkomt-Type" content="text/html; charset=winkomdows-1251">
<style>td{width:50px}</style>
</head>


<body>

<script>
var N = 6;
var a = new Array();

// создаем пустрой массив NxN
for(j=1;j<=N;j++){
  a[j] = new Array();
  for(i=1;i<=N;i++) {
  a[j][i]=0;
  }
}


// ф-ция проверки строки&столбца на наличие числа
function my(chk,rw,cl){
  var ret=true;
//  if (chk==rw) ret=false; - условие не нужно, в столбце может находиться
// число, совпадающее с номером столбца; потом эти ячейкни надо будет
// заштриховать
  for(w=1;w<=N;w++)
    if(a[rw][w]==chk || a[w][cl]==chk) ret=false;
  return ret;
}

// генерим левый верхний треугольник вкл. диагональ (1,6)-(6,1)
for(n=1; n<=N; n++) {
  for(m=1; m<=n; m++) {
    i = n - (m-1)
    j = m;
    mas=new Array();
    for(l=1;l<=N;l++){
       if(my(l,i,j)) mas[mas.length]=l;
    }
//    a[i][j] = i+","+j;
    a[i][j] = mas.length;
  }
}

// правый нижний треугольник
for(n=N+1; n<=2*N-1; n++) {
  for(m=n; m<=2*N-1; m++) {
    i = m-N+1;
    j = 2*N-1 - n +2;
    mas=new Array();
    for(l=1;l<=N;l++) {
       if(my(l,i,j)) mas[mas.length]=l;
    }
//    a[i][j] = i+","+j;
    a[i][j] = mas.length;
  }
}


// выводим массив
document.write("<table border=1>");
for(j=1;j<=N;j++){
  document.write("<tr>");
  for(i=1;i<=N;i++) {
    document.write("<td>"+a[i][j]+"</td>");
  }
  document.write("</tr>");
}
document.write("</table>");

</script>
</body>
</html>

PM MAIL WWW   Вверх
krinart
Дата 11.4.2008, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



чтото это не совсем то.. вот что у меня получилось... 

6    5    4    3    2    1
5    5    4    3    2    1
4    4    5    3    2    1
3    3    3    4    3    2
2    2    2    4    3    2
1    1    2    3    3    3


странно, может я чегото недопонял, и мне дали только идею, но... да и где же тут случайность?

хотя признаюсь в код я ещё не сильно вчитывался, щас этим и займусь... но всё равно спасибо за уделённое время 
PM MAIL ICQ   Вверх
TryLight
Дата 11.4.2008, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



krinart, 
как было сказано, это пример, который в ячейках таблицы выводит колличество возможных значений для данной ячейки.

да, я дал идею, к которой надо добавить random.

Это сообщение отредактировал(а) TryLight - 11.4.2008, 21:44
PM MAIL WWW   Вверх
krinart
Дата 12.4.2008, 00:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



дело в том что мне ведь нужна матрица не N*N, а (N-1)*N...

я сделал дополнительную проверку в ваших функциях, чтобы индексы не доходили до последней строки, 

Код


if(j==N)
    continue;



однако опять появляется ситуация, когда "не из чего выбирать"

в комментарии вы написали что клетки, в которых число совпадает с номером столбца(лишние клетки) надо будет заштриховать, но мне то нужно чтобы они были в одной строке(то есть в одном "туре")...  вот тут я снова в тупике...

был бы очень признателен за ещё одну подсказку))
PM MAIL ICQ   Вверх
TryLight
Дата 12.4.2008, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



тогда так

Код

for(n=1; n<=N-1; n++) {
...
for(m=...
...
j = 2*N-1 - n +1;
...


ну и там кое-что доделать.

и давай на "ты", я не такой уж крутой программист    smile smile 
PM MAIL WWW   Вверх
krinart
Дата 12.4.2008, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



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

Код


function my(chk,rw,cl){
  var ret=true;
  if (chk==rw) 
    ret=false; // я всётаки вернул это сравнение, потому как без него никак
  for(w=1;w<=N;w++)
    if(a[rw][w]==chk || a[w][cl]==chk) ret=false;
  return ret;
}


// здесь изменили на N-1
for(n=1; n<=N-1; n++) {
  for(m=1; m<=n; m++) {
    i = n - (m-1)
    j = m;
    if(a[i][j])  // если в этой клетке уже есть данные
        continue;
    mas=new Array();
    for(l=1;l<=N;l++){
       if(my(l,i,j)) mas[mas.length]=l;
    }
    // вместо длины массива заносим случайный элемент этого массива
    kom= Math.floor(Math.random() * (mas.length));    
    a[i][j] = mas[kom];
    // заносим соответствующие данные в другую клетку 
    a[mas[kom]][j]= i
  }
}


for(n=N+1; n<=2*N-1; n++) {
  for(m=n; m<=2*N-1; m++) {
    i = m-N+1;
    
    // здесь у тебя было n+2, но я сделал +1, чтобы занять места освободившейся диагонали
    j = 2*N-1 - n +1; 

    if(a[i][j])  // если в этой клетке уже есть данные
        continue;
    mas=new Array();
    for(l=1;l<=N;l++){
       if(my(l,i,j)) mas[mas.length]=l;
    }
    // вместо длины массива заносим случайный элемент этого массива
    kom= Math.floor(Math.random() * (mas.length));    
    a[i][j] = mas[kom];
    // заносим соответствующие данные в другую клетку 
    a[mas[kom]][j]= i
  }
}



всётаки чтото там не работает...

я немного модифицировал свой алгоритм.. можно сказать, сделал его бесконечным)) 
теперь он будет работать до тех пор , пока всётаки на сможет сформировать эту таблицу...
конечно, не тупо его зациклил, а сделал вот что(даже два варианта):

1. если встречается ситуация, когда не из чего выбирать, то у нас есть 10 попыток заново составить эту строку... если же и это не помогает, тогда заново начинаем составлять всю таблицу

2. если не удаётся за 10 попыток сотавить строку, тогда пытаемся заново составить предыдущую, и так до бесконечности smile 

к сожалению алгоритм получился очень сложным.. за 10 часов не смог составить таблицу для 100 команд, но вот в случаях до 20 команд работает исправно, только изредка подтормаживает

теперь вот думаю, можно ли его использовать на практике...
PM MAIL ICQ   Вверх
ksnk
Дата 13.4.2008, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 48
Всего: 386



Цитата(krinart @  11.4.2008,  19:32 Найти цитируемый пост)
6    5    4    3    2    1
5    5    4    3    2    1
4    4    5    3    2    1
3    3    3    4    3    2
2    2    2    4    3    2
1    1    2    3    3    3

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


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
TryLight
Дата 14.4.2008, 01:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



Цитата("krinart ")

всётаки чтото там не работает...


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

В общем, как я ни пробовал - и по числам, т.е. взять 1, разбрасать ее по таблице, потом 2 и т.д., всегда получается одно и то же: в какой-то момент оказывается, что свободные клетки ряда блокируются числами в столбцах. Возникает ситуация, о которой ты говорил "не из чего выбирать".

Задачу можно решить, если принципиально изменить концепцию: мы берем укомплектованную таблицу, а потом тасуем столбцы и строки.

Возникает только вопрос: откуда как сформировать такую таблицу произвольного размера. Первое, что приходит в голову - составить ее из рядов вида 1,2,3,... Т.е. примерно так
1 - {2, 3, 4, 5, 6, 1} 
2 - {3, 4, 5, 6, 1, 2}
...
6 - {1, 2, 3, 4, 5, 6} (на выброс)

Собственно, это я и сделал. И перетасовал строки. Столбцы менять местами мы не можем, т.к. появятся тождественные чиста в столбцах. Но то, что получилось, мне не очень нравиться; видно, что ряды составлены из восходящей последовательности чисел. И избежать этого, по-моему, не удасться.


Код

var N = 6;
var a = new Array();
var helper;

//формируем таблицу со сдвигом
for (i=1;i<=N;i++) {         //если нужна таблица N*(N-1), здесь N надо заменить на N-1
  a[i] = new Array();
  for (j=1;j<=N;j++) { 
     k = j + i; 
     if (k>N) k = k - N;
     a[i][j] = k;
  }
}
print(); //наслаждаемся предварительным результатом


//тасуем строки (меняем местами произвольные строки N/2 раз)
//можно еще добавить проверку "не тасованых" строк :)

for (i=1;i<=Math.floor(N/2);i++) {
  row1 = Math.floor(Math.random()*(N-1))+1;
  row2 = Math.floor(Math.random()*(N-1))+1;
  for (j=1;j<=N;j++) {
     helper = a[row2][j];
     a[row2][j] = a[row1][j];
     a[row1][j] = helper;
  }
}
print("<br><br>");


/* //меняем местами столбцы
for (i=1;i<=Math.floor(N/2);i++) {                    //этот абзац можно выкинуть
  col1 = Math.floor(Math.random()*(N-1))+1;
  col2 = Math.floor(Math.random()*(N-1))+1;
  for (j=1;j<=N;j++) {
     helper = a[j][col2];
     a[j][col2] = a[j][col1];
     a[j][col1] = helper;
  }
}
print("<br><br>");
*/


function print(beforeTBL) {
  if (beforeTBL) document.write(beforeTBL);
  document.write("<table border=1>");
  for (i=1;i<=N;i++) {                                    //а так же здесь N надо заменить на N-1
    document.write("<tr>");
    for (j=1;j<=N;j++)
      document.write("<td>"+a[i][j]+"</td>");
    document.write("</tr>");
  }
  document.write("</table>");
}

PM MAIL WWW   Вверх
krinart
Дата 14.4.2008, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 10.4.2008
Где: Донецк

Репутация: нет
Всего: нет



Цитата

Задачу можно решить, если принципиально изменить концепцию: мы берем укомплектованную таблицу, а потом тасуем столбцы и строки.

Возникает только вопрос: откуда как сформировать такую таблицу произвольного размера. Первое, что приходит в голову - составить ее из рядов вида 1,2,3,... Т.е. примерно так
1 - {2, 3, 4, 5, 6, 1} 
2 - {3, 4, 5, 6, 1, 2}
...
6 - {1, 2, 3, 4, 5, 6} (на выброс)



вся проблема в том что нужно не просто расставить числа так, чтобы они не повторялись в столбцах и строках, а ну жно ещё сделать так, чтобы в каждой строке если в 1 столбце стоит 4, то в четвёртом столбце соответственно должна стоять единица, и так для каждой команды, так как команды должны попарно играть в туре... и поэтому такой подход тоже не подходит, так как числа не могут идти подряд по возрастанию или убыванию.....  нужно чтото совершенно другое, но вот что именно я придумать не могу, так как теперь задача получается больше математическая, и если будет общая идея как это сделать, запрогроммировать её будет несложно.... неужели здесь нету людей, имеющих познания в комбинаторике, по моему это именно из этой области....
PM MAIL ICQ   Вверх
TryLight
Дата 14.4.2008, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



Опять новое ограничения. Я решаю одну задачу, на деле оказывается другая.

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

Давай мы эту тему закроем, а ты математически-корректно сформулируешь условие задачи и предложишь ее, наверно даже и не на этом форуме.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0620 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.