powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / рекурсивная функция делает переполнение кучи.
132 сообщений из 132, показаны все 6 страниц
рекурсивная функция делает переполнение кучи.
    #39364021
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день , друзья.

Помогите дилетанту .
Не могу разобраться , почему моя рекурсивная функция переполняет кучу.
Тупая реализация классической задачки на обход конем доски. Я правда так и не разобрался пока как закончить её выполнение. Но это не сильно и важно. (на данный момент просто хотелось бы добиться чтобы высветилось хотя бы одно решение, пусть и с зацикливанием)
Пытаюсь даже выводить грубо глубину рекурсии - она теоретически не должна превышать 64 - так и есть.
Однако при длительной работе (а дерево разрастается очень стремительно) высвечивает Java heap space.


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
package horses;
import java.util.concurrent.TimeUnit;
public class horse {
int qty_of_hourse = 65;
int [][] x = new int[9][9];
int [] is = new int[65];
int [] js = new int[65];
long depth = 0;
int i_start=1;
int j_start=1;
int horse_count = 1;
public horse() {
x[i_start][j_start]=1; 
is[1] = i_start;js[1] = j_start;
System.out.println("start");
print_field();
}
public String try_horse(int current_horse) {
String res="good" ;
int [] moving= new int [2];
int mc=1; 
int x1=0;
int y1=0; 
depth++;
System.out.println("Глубина = " + depth);
if (current_horse==2) {x1=i_start; y1=j_start; is[current_horse] = x1;js[current_horse] = y1;}
do {
moving = move_horse(mc,is[current_horse-1],js[current_horse-1]);
if (moving[0]!=0 && moving[1]!=0) { //если можно поставить коня
	x1 = moving[0];
	y1 = moving[1];
x[x1][y1]=current_horse;/*ставим*/
is[current_horse] = x1;
js[current_horse] = y1;
System.out.println("Можно !  Передвигаем коня на "+x1+ " "+y1+", ход №"+current_horse);
print_field();
if (current_horse<=64) { res=try_horse(current_horse+1); }
if (res=="bad") {
	System.out.println("Плохо !  Вынуждены убрать коня с "+is[current_horse]+ " "+js[current_horse]);
	x[is[current_horse]][js[current_horse]]=0;
	is[current_horse]=0;
	js[current_horse]=0;
	res="good";
} 
} 
mc++;
if (mc==9) {res="bad";}
} while (!(res=="bad" || mc==9 )) ;
depth--;
return res;
}
public int [] move_horse(int i1 , int i , int j ) { 
int [] result= new int [2]; 
result[0] = 0 ;
result[1] = 0 ;
int is=0;
int js=0;

System.out.println("Попытка "+ i1 +" из 8. проверим можно ли передвинуть с " +i+ " "+  j);

if (i1==1 && i-2>=1 && j-1>=1 && x[i-2][j-1]==0) {is=i-2 ; js=j-1; result[0] = is ;result[1] = js ; 

} 
if (i1==2 && i-1>=1 && j-2>=1 && x[i-1][j-2]==0) {is=i-1 ; js=j-2; result[0] = is ;result[1] = js ; 

} 
if (i1==3 && i+1<=8 && j-2>=1 && x[i+1][j-2]==0) {is=i+1 ; js=j-2; result[0] = is ;result[1] = js; 

}
if (i1==4 && i+2<=8 && j-1>=1 && x[i+2][j-1]==0) {is=i+2 ; js=j-1; result[0] = is ;result[1] = js; 

}
if (i1==5 && i+2<=8 && j+1<=8 && x[i+2][j+1]==0) {is=i+2 ; js=j+1; result[0] = is ;result[1] = js; 

}
if (i1==6 && i+1<=8 && j+2<=8 && x[i+1][j+2]==0) {is=i+1 ; js=j+2; result[0] = is ;result[1] = js; 

}
if (i1==7 && i-1>=1 && j+2<=8 && x[i-1][j+2]==0) {is=i-1 ; js=j+2; result[0] = is ;result[1] = js; 

}
if (i1==8 && i-2>=1 && j+1<=8 && x[i-2][j+1]==0) {is=i-2 ; js=j+1; result[0] = is ;result[1] = js ; 

}
return result;
}
public void print_field() {
int i1;
int j1;
for (i1 = 1; i1 <= 8; i1++) {
for (j1 = 1; j1 <= 8; j1++) {
if (x[i1][j1]>0) {System.out.print(x[i1][j1]+" ");}
if (x[i1][j1]<0) {System.out.print("B ");}
if (x[i1][j1]==0) {System.out.print("0 ");}
}
System.out.println();
}
System.out.println();
}
}




Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
package horses;

public class main {
	public static void main(String args[]) {
		 horse h = new  horse();
		 
		 h.try_horse(2);

		
	}
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364025
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 ** 64 ~ 10 ** 18
Терабайт это 10 ** 12
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364032
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov2 ** 64 ~ 10 ** 18
Терабайт это 10 ** 12

то есть вы хотите сказать, что когда 64 процедуры вызывают последовательно друг друга , то памяти отъедается более терабайта ? :-)
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364035
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я хочу сказать, что есть "рекурсия вглубь" и "рекурсия вширь".

P.S. Мне лень разбираться в попытках решить методом полного перебора задачу, которую (насколько мне изменяет склероз) умные люди давно решили вручную.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364037
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

эта именно тупо вглубь .
что значит решили вручную ? ))))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364043
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, например, в старом журнале ("Наука и жизнь", если правильно помню) была статья, где в качестве одного из способа запоминания ходов автор придумал стихи, строчки которых были мнемониками шахматных клеток. Журнал - не младше середины-конца восьмидесятых.

P.S. Насколько я помню вполне классическую "Алгоритмы + структуры данных = программы", принципиально разных решений всего двенадцать. Издание начала восьмидесятых.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364048
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя, вру - у Вирта решается задача расстановки восьми ферзей.
Чтобы рекурсия была вглубь требуются две вещи стратегия обхода и запоминание "границы отсечения".
Когда на каждом шаге перебираются все возможные варианты это именно что рекурсия вширь.

P.S. Я бы предложил разбираться с рекурсией на гораздо более простой задаче: лабиринт без циклов, где на каждом шаге можно повернуть или влево или вправо и глубина любого пути не превышает заданного (небольшого) числа шагов.
Начинать с лабиринтов, которые можно нарисовать на листе школьной тетради в клеточку.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364052
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

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


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

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

одна процедура резервирует грубо говоря:
3 переменных int (96 байт),
один массив (64 байта)
переменная типа String
может в последней проблема ? я толком не понимаю пока эта переменная фиксированной длины или же переменной ?

почему вы насчитали, что памяти должно резервироваться более терабайта
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364053
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovХотя, вру - у Вирта решается задача расстановки восьми ферзей.


нет, не врете. кони тоже решаются в моем издании
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364056
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ещё: чтобы не путать глубину рекурсии с числом (активных) рекурсивных вызовов - сделайте статическую, которая будет увеличиваться на входе в рекурсивный метод и уменьшаться на выходе. Ну и печатайте значение этой переменной по мере надобности.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364058
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovИ ещё: чтобы не путать глубину рекурсии с числом (активных) рекурсивных вызовов - сделайте статическую, которая будет увеличиваться на входе в рекурсивный метод и уменьшаться на выходе. Ну и печатайте значение этой переменной по мере надобности.


так и делал . за исключением статики
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364059
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

стоп. статическую что вы имеете ввиду ? переменную или метод вызова статический ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364060
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

это вы имеете ввиду ?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class horse {
...
static long depth = 0;
...

public String try_horse(int current_horse) {
string result;
depth ++;
     ....
try_horse(current_horse+1) ;
     ....
depth --;

return  result ;
}



у меня переменная depth сейчас считается так же за исключением того , что объявлена она не как static.
честно говоря не чувствую разницы
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364061
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Статика непринципиальна.
Просто вы считаете именно что глубину рекурсии, а считать надо число активных вызовов.
Цепочка вызовов активна до тех пор пока мы или не нашли (очередное) решение или не обнаружили, что эта цепочка ходов решением не является.
Когда вы осознаете, что каждый узел в цепочке вызовов порождает свою цепочку вызовов, вам станет понятнее "куда девается память".
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364072
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

как я понимаю мой алгоритм в любой момент времени хранит только лишь текущую самую глубокую ветку и всю цепочку до неё .
остальные пройденные субдеревья и не приведшие к удаче в данный момент не хранятся. Или нет ?

вот на рисунке мы скажем в данный промежуток времени проделали маршрут 1->7->8->9->12. мы этот маршрут и храним.
пусть даже до этого были маршруты
1->2-> 3-> 4
1->2-> 3-> 5
1->2-> 3-> 6
а так же
1->7->8->9->10->11
но они не привели к решению . ну значит мы по ним и выполнили всюду return-ы , а это значит и память по ним расчистилась. Или же нет ?

а маршрут 1->7->8->9->12 это 5 вызовов. и глубина = 5. или же нет ??
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364080
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЦепочка вызовов активна до тех пор пока мы или не нашли (очередное) решение или не обнаружили, что эта цепочка ходов решением не является.


верно и это понятно. но цепочка вызовов не может превышать 64 (число ходов, а значит клеток на шахматной доске).
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364109
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, об ограничениях ...
Чтобы шестьдесят четвёртым ходом оказаться в точке (0,0), на шестьдесят третьем ходу надо быть или в точке (2,1) или в точке (1,2).
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364111
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

блин, да нет же. задача стоит проще: просто обойти абсолютно все клетки , закрасив их.

кстати, я Вам соврал. похоже, что ругается консоль . "io console updater java heap space" я наверно превысил допустимое число вывода на экран . кстати , можно ли выводить не в консоль , а в файл (Eclipse) ? гугл не помог.

а "ругань" превышения допустимых вызовов рекурсивной функции выглядит иначе. достаточно накидать программу n! и поставить в качестве входного параметра скажем громадное число. там со стэком будет ошибка.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364112
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

P.s. стоит задача обойти все клетки конем побывав ровно по одному в каждой
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364421
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

=) помню сдавал такую курсовую два раза за обучение :)

Вот пример . тут даже с графикой )


http://5fan.ru/wievjob.php?id=49236
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364430
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364472
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,

спасибо , конечно, интересней самому решить, что я и сделал.

для начальной точки 1,1 выдаёт решения за время меньше минуты.
а вот на точке 1,2 выходит в ступор. дерево разрастается настолько , что и за 40 минут ни одного решения не выдаёт
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364476
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1 http://algolist.manual.ru/maths/combinat/knight.php

хотя интересное правило Варнсдорфа описано.
но я правило такого не знал. поэтому у меня тупой перебор всего дерева. поэтому видимо и долго
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364485
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лет 10 назад я кодил на С++/Win32 GDI приложение для решения horse problem.

Чтоб рекурсия не заходила в слишком глубокие поиски я разработал правила
построения кориродов (только для прямоугольной доски) чтобы ограничить
для коня следущие несколько N ходов. Для этого я выбирал ширину коридора
(4 клетки) и змейкой заполнял всю доску.

К сожалению сорцы потерял.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364488
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

мне не сильно важна оптимизация пока моего алгоритма. важен сам факт - ищет / не ищет. тем более решение кое-какие находит.
А вообще я пытаюсь разобраться с рекурсией.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364539
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Субъективно. Много лишних непонятных действий. Что это? Почему 2? Что это за магическая константа?
Код: java
1.
2.
        Horse h = new Horse();
        h.tryHorse(2);


Далее. System.out флудит беспощадно и блокирует скорость вычислений. Даже с заглушкой в /dev/null все равно
будет обеспечет терафлоп ненужной работы которую никто не смотрит. Вобщем вынести в slf4j или JUL с уровнем trace.

Результат вычислений возвращается через строковую константу. Это странно. Так обычно не делают.

Есть flow где имеет смысл добавить линию else чтобы отключить избыточные расчеты.
Есть повторы вычисления одного выражения которые можно зарефакторить через
introduce temp variable.

Очень много замечаний к codeStyle. Классы с маленькой буквы а имена переменных с dash.
Это ломает зрение.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364548
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

большое спасибо за критику и за то, что не поленились изучить мой код )

1) 2 это потому, что одного коня мы ставим уже в конструкторе , его координата int i_start=1;int j_start=1;. поэтому в рекурсивную функцию уже подаём 2.
2) System.out я использовал чтобы видеть, что он делает. о протоколировании по средствам slf4j даже и не догадывался. изучу . спасибо
3) Конечно же Вы правы. исправлю на boolean
4) Где вы предлагаете добавить ?
5) Поясните какие , пожалуйста.
6) Конечно, учту !
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364580
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81mayton,

большое спасибо за критику и за то, что не поленились изучить мой код )

1) 2 это потому, что одного коня мы ставим уже в конструкторе , его координата int i_start=1;int j_start=1;. поэтому в рекурсивную функцию уже подаём 2.
2) System.out я использовал чтобы видеть, что он делает. о протоколировании по средствам slf4j даже и не догадывался. изучу . спасибо
3) Конечно же Вы правы. исправлю на boolean
4) Где вы предлагаете добавить ?
5) Поясните какие , пожалуйста.
6) Конечно, учту !

Ничего страшного, немного причесал код. Память расходует от 120 до 260 МБ хипа, вроде сбрасывает до 140 примерно, особо ждать времени не было когда закончится цикл или хип.

1. Поставьте хипа хотя бы 512МБ, дефолтные размер может переполниться. Пример с гигом: java -Xmx1024m
2. Настройте логгирование, полезная вещь, читать и скачивать jar для log4j фасада и реализации в вашем случае скорее всего logback standalone http://logback.qos.ch/
3. Придерживайтесь рекомендуемого стиля Java кода: Sun (Oracle) http://www.oracle.com/technetwork/java/codeconvtoc-136057.html Google https://google.github.io/styleguide/javaguide.html

Код после легкой рехтовки, возможно легкомысленно изменил перебор if/if/if на if else/if else/.. в паре мест, проверьте, это просто пример. В алгоритм не вникал.

PS используйте переносы, разделяйте блоки кода, хотя на вкус и цвет товарищей нет...
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
package ru.sql.forum.samples.horse;

import org.slf4j.Logger;

public class Horse {

    private Logger logger = org.slf4j.LoggerFactory.getLogger(Horse.class);

    int hourseCount = 65;
    int[][] x = new int[9][9];
    int[] is = new int[hourseCount];
    int[] js = new int[hourseCount];
    long depth = 0;
    int iStartPos = 1;
    int jStartPos = 1;

    public Horse() {
        x[iStartPos][jStartPos] = 1;
        is[1] = iStartPos;
        js[1] = jStartPos;

        logger.debug("start");

        printState();
    }

    public static void main(String args[]) {
        Horse h = new  Horse();

        h.tryHorse(2);
    }

    public boolean tryHorse(int horseIndex) {
        boolean success = true;
        int[] moving;
        int mc = 1;
        int x1;
        int y1;
        depth++;
        logger.debug("Глубина = {}", depth);

        if (horseIndex == 2) {
            x1 = iStartPos;
            y1 = jStartPos;
            is[horseIndex] = x1;
            js[horseIndex] = y1;
        }

        do {
            moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);
            if (moving[0] != 0 && moving[1] != 0) { //если можно поставить коня
                x1 = moving[0];
                y1 = moving[1];

                x[x1][y1] = horseIndex;/*ставим*/
                is[horseIndex] = x1;
                js[horseIndex] = y1;

                logger.debug("Можно !  Передвигаем коня на  x={} y={}, ход {}", x1, y1, horseIndex);

                printState();

                if (horseIndex <= 64) {
                    success = tryHorse(horseIndex + 1);
                }

                if (!success) {
                    logger.debug("Плохо !  Вынуждены убрать коня с x={} y={} ", is[horseIndex], js[horseIndex]);

                    x[is[horseIndex]][js[horseIndex]] = 0;
                    is[horseIndex] = 0;
                    js[horseIndex] = 0;
                    success = true;
                }
            }
            mc++;
            if (mc == 9) {
                success = false;
            }
        } while (!(!success || mc == 9));

        depth--;

        return success;
    }

    public int[] moveHorse(int i1, int i, int j) {
        int[] result = new int[2];
        result[0] = 0;
        result[1] = 0;
        int is;
        int js;

        logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);

        if (i1 == 1 && i - 2 >= 1 && j - 1 >= 1 && x[i - 2][j - 1] == 0) {
            is = i - 2;
            js = j - 1;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 2 && i - 1 >= 1 && j - 2 >= 1 && x[i - 1][j - 2] == 0) {
            is = i - 1;
            js = j - 2;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 3 && i + 1 <= 8 && j - 2 >= 1 && x[i + 1][j - 2] == 0) {
            is = i + 1;
            js = j - 2;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 4 && i + 2 <= 8 && j - 1 >= 1 && x[i + 2][j - 1] == 0) {
            is = i + 2;
            js = j - 1;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 5 && i + 2 <= 8 && j + 1 <= 8 && x[i + 2][j + 1] == 0) {
            is = i + 2;
            js = j + 1;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 6 && i + 1 <= 8 && j + 2 <= 8 && x[i + 1][j + 2] == 0) {
            is = i + 1;
            js = j + 2;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 7 && i - 1 >= 1 && j + 2 <= 8 && x[i - 1][j + 2] == 0) {
            is = i - 1;
            js = j + 2;
            result[0] = is;
            result[1] = js;

        } else if (i1 == 8 && i - 2 >= 1 && j + 1 <= 8 && x[i - 2][j + 1] == 0) {
            is = i - 2;
            js = j + 1;
            result[0] = is;
            result[1] = js;

        }
        return result;
    }

    public void printState() {
        if(logger.isInfoEnabled()) {
            StringBuilder sb = new StringBuilder();

            for (int x = 1; x <= 8; x++) {
                for (int y = 1; y <= 8; y++) {
                    if (this.x[x][y] > 0) {
                        sb.append(this.x[x][y]).append(" ");
                    } else if (this.x[x][y] < 0) {
                        sb.append("B ");
                    } else if (this.x[x][y] == 0) {
                        sb.append("0 ");
                    }
                }
                sb.append("\n");
            }
            sb.append("\n");

            logger.info(sb.toString());
        }
    }
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364708
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
uid unique,
вот допустим, на 64 ходу найдено решение. Вопрос: выйдет ли код из цикла?
Код: java
1.
while (!(!success || mc == 9))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364710
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поскольку исходник живет своей жизнью то я буду комментировать последнюю версию
независимо от автора. Я сделал еще один машинальный рефакторинг.

1) Магические константы типа размер доски = 8 я вынес в отдельную static final переменную.
Это упрощает анализ кода и делает его более строгим.

2) StringBuilder можно инстанциировать заведомо известным размером. Это избавит нас от реаллокаций.

3) Была большая путаница в локальных переменных и переменных класса. Я заменил x,y на i,j и ушел
this и загадочный ...x[x]....

4) Я использовал temp variable чтобы убрать повторные вычисления в блоках if.

Вот что получилось.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
 static final int DESK_SIZE = 8;
    
    public void printState() {
        if(logger.isInfoEnabled()) {
             StringBuilder sb = new StringBuilder(200);
             for (int j = 1; j <= DESK_SIZE; j++) {
                 for (int i = 1; i <= DESK_SIZE; i++) {
                     int cell = x[j][i];
                     if (cell > 0) {
                        sb.append(cell).append(" ");
                    } else if (cell < 0) {
                        sb.append("B ");
                    } else if (cell == 0) {
                        sb.append("0 ");
                    }
                }
                sb.append("\n");
            }
            sb.append("\n");

            logger.info(sb.toString());
        }
    }
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364716
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Далее.

Код: java
1.
if (i1 == 1 && i - 2 >= 1 && j - 1 >= 1 && x[i - 2][j - 1] == 0) {  



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

Код: java
1.
 if (i1 == 1 && i >= 3 && j >= 2 && x[i - 2][j - 1] == 0) {
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364720
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanrauid unique,
вот допустим, на 64 ходу найдено решение. Вопрос: выйдет ли код из цикла?
Код: java
1.
while (!(!success || mc == 9))



я в курсе не завершится никогда .
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364727
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу multidimensional arrays в Java.

Код: java
1.
int[][] x = new int[DESK_SIZE+1][DESK_SIZE+1];



есть основания говорить о том что они не очень эффективны. Правильнее сказать что их реализация
для нашей задачи (шахматная доска) весьма избыточна. Нам хватит и обычного одномерного массива.

Код: java
1.
int[] x = new int[2*(DESK_SIZE+1)];



для доступа к элементу (i,j) мы должны использовать следующий getter

Код: java
1.
2.
3.
int getCellValue(int i, int j){
     return i * (DESK_SIZE+1) + j;
}



Сеттер кодится точно также. Почему i умножается на размер доски а не j - это вопрос договорённостей.
Можно и наоборот. Это влияет на обход доски слева-направо-сверху-вниз или сверху-вниз ... и.т.д.

Обычно на больших матрицах выбирают обход таким образом чтобы доступ к линейным участкам памяти
не сильно "распылялся". Это тоже один из хинтов перформанса.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364728
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стоп я ошибся. Размер доски в квадрате от стороны.

Код: java
1.
int[] x = new int[(DESK_SIZE+1)*(DESK_SIZE+1)];
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364752
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andron81ivanrauid unique,
вот допустим, на 64 ходу найдено решение. Вопрос: выйдет ли код из цикла?
Код: java
1.
while (!(!success || mc == 9))


я в курсе не завершится никогда .
Не так, он завершится при mc == 9.
На самом деле, код вроде должен перебирать все решения, но вот с определением, что решение найдено - проблемы.
Во-первых, tryHorse всегда возвращает false, почему бы не преобразовать этот метод в void и не убрать лишнюю переменную?
Во-вторых, опять посмотрим на 64-й ход (horseIndex==64). При найденном решении мы заходим в if(), а там:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
                if (horseIndex <= 64) {
                    success = tryHorse(horseIndex + 1); // tryHorse(65)==false
                }

                if (!success) {
                    logger.debug("Плохо !  Вынуждены убрать коня с x={} y={} ", is[horseIndex], js[horseIndex]);

                    x[is[horseIndex]][js[horseIndex]] = 0;
                    is[horseIndex] = 0;
                    js[horseIndex] = 0;
                    success = true;
                }


это решение признано ошибочным
Конечно, правильное решение было выведено строчкой раньше
Код: java
1.
printState();

, но как мы найдем его среди всего этого флуда (до первого решения может быть выведено на консоль хот миллион неправильных)?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364841
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если посмотреть на исходник глазами статического анализатора то можно видеть

The Cyclomatic Complexity of this method "moveHorse" is 33 which is greater than 10 authorized.

Complex code can perform poorly and will in any case be difficult to understand and therefore to maintain.

Я не знаю откуда он взял 33. Возможно просуммировал все предикаты в if-else и посчитал
их ветками логики. Но нам повезло что порядок проверки - декартовый и этот список
условий более-менее ясен. А если их заменить на некие абстрактные f1(), f2() то
тогда надо раскуривать сорс очень долго.

Кстати есть мысль что стоит отмечать свободые позиции битовой маской.
Кажется я так делал в своём С++ horse route.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364843
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uid unique1. Поставьте хипа хотя бы 512МБ, дефолтные размер может переполниться. Пример с гигом: java -Xmx1024m
2. Настройте логгирование, полезная вещь, читать и скачивать jar для log4j фасада и реализации в вашем случае скорее всего logback standalone http://logback.qos.ch/


возможно надо выполнить пункт №1, но я не знаю как это сделать.
сделал я только №2. у меня всё та же привычная ошибка : "io console updater java heap space"
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364849
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonКстати есть мысль что стоит отмечать свободые позиции битовой маской.


вы имеете ввиду что наш двухмерный массив должен быть boolean ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364865
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я думаю о том как свести арифметические операции проверки координат
к проверке масок.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364871
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЯ думаю о том как свести арифметические операции проверки координат
к проверке масок.

это, конечно , здорово но это уж совсем слишком вы заморочились с оптимизацией алгоритма. ))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364888
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Совершенству нет предела. А учитывая бесконечные возможности параллелизма
данной задачи (мы можем не шарить шахматную доску между процессами)
то эта задача скейлируется достаточно выгодно.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364897
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonСовершенству нет предела. А учитывая бесконечные возможности параллелизма
данной задачи (мы можем не шарить шахматную доску между процессами)
то эта задача скейлируется достаточно выгодно.

многопоточность тогда давайте прикрутим
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364904
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81 учитывая бесконечные возможности параллелизма
данной задачи


вот странно если начальная точка 1:1, то решения находятся довольно быстро - меньше минуты
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364906
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Надо подумать как задачи раздать. Чтоб повторов не было.

У вас уже есть мысли по этому вопросу?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364917
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНадо подумать как задачи раздать. Чтоб повторов не было.

У вас уже есть мысли по этому вопросу?

да это я так про многопоточность.
это очень серьёзный вопрос. боюсь , что мне не по зубам.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364928
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

легче воспользоваться Правилом Варнсдорфа как тут советовали ранее:

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

На практике это реализуется, например, следующим образом. Перед каждым ходом коня вычисляется рейтинг ближайших доступных полей - полей, на которых конь еще не был, и на которые он может перейти за один ход. Рейтинг поля определяется числом ближайших доступных с него полей. Чем меньше рейтинг, тем он лучше. Потом делается ход на поле с наименьшим рейтингом (на любое из таковых, если их несколько), и так далее, пока есть куда ходить.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364932
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

и выход , завершение нужно при нахождении хотя бы одного решения прописать каким-то образом как верно подмечал ivanra
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364957
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
uid unique,
еще неплохо было бы улучшить копипастный код метода moveHorse(). Например, итерацией по массиву
Код: java
1.
int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364976
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81mayton,

легче воспользоваться Правилом Варнсдорфа как тут советовали ранее:
Данное правило, насколько я понял меняет некоторые характеристики
базового однопоточного алгоритма. Возможно улучшает o(n).

Но к предлагаемому мной вопросу (параллельный запуск нескольких
процессов и способ раздачи работ) Варнсдорф не имеет отношения.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364998
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanrauid unique,
еще неплохо было бы улучшить копипастный код метода moveHorse(). Например, итерацией по массиву
Код: java
1.
int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};




Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
  public int[] moveHorse(int i1, int i, int j) {
    	int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
        int[] result = new int[2];
        result[0] = 0;
        result[1] = 0;
        int is;
        int js;

        logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);
        if (i + horseMoves[i1][0] >= 1 && i + horseMoves[i1][0] <= 8 &&
            j + horseMoves[i1][1] >= 1 && j + horseMoves[i1][1] <= 8
             && x[(i + horseMoves[i1][0])][(j + horseMoves[i1][1])] == 0
        		) {
        	
            is = i + horseMoves[i1][0];
            js = j +  horseMoves[i1][1];
            result[0] = is;
            result[1] = js;
        	
        }
        
        return result;
    }



так ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365007
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

отваливается всё равно по ошибке IOConsole Updater "An internal error has occurred.
Java heap space" даже прикрутив логатер . Вопрос: можно ли чтобы он сохранял лог в файл , а не на выводил на экран ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365033
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81, чувак я-же тебе писал. Подключи нормальные библиотеки логгирования. Настрой appenders.
Настрой их на запись в текстовые файлы. Вот тебе ссылки.

https://logging.apache.org/log4j/2.x/manual/appenders.html
http://logback.qos.ch/manual/appenders.html

А текстовое окошко внизу которое тебе ЛЮБЕЗНО предоставляет среда разработки
перепоелняет heap и правильно делает ибо нефиг слать терабайты текста в
ИНФОРМАЦИОННОЕ (!) на минуточку окошко.

Да вообще ничего писать не надо! Напиши только резалт когда функция закончит работу.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365041
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
Да вообще ничего писать не надо! Напиши только резалт когда функция закончит работу.

закончит , но не скоро )
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365084
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня на С++ в 2003 году на Celeron-300 эта задача решалась за минут пять.

А щас учитывая рост перформанса можно просто умножать на десять. Тоесть
за полминуты должна решаться.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365093
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonУ меня на С++ в 2003 году на Celeron-300 эта задача решалась за минут пять.

А щас учитывая рост перформанса можно просто умножать на десять. Тоесть
за полминуты должна решаться.

вы когда о процессах говорили вы многопоточность имели ввиду ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365095
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я говорил о способности этой задачи исполнятся параллельно. А будь это процесссы (ProcessBuilder)
или потоки (Thread) - это уже детали реализации.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365096
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

хорошо, тогда я не вижу иного способа как иметь n разных массивов и работать с ними параллельно. а ещё вести один глобальный массив куда складывались бы тупиковые маршруты . таким образом мы исключим повторений по тупиковым путям в разных потоках
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365118
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем вам нужен глобальный массив?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365128
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЗачем вам нужен глобальный массив?

глобальный , ну я честно говоря уже запамятовал как потоками пользоваться, я сказал так в предположении , что каждый поток это отдельный класс. мне видимо надо эту тему освежить.
не пинайте сильно :)
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365129
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonУ меня на С++ в 2003 году на Celeron-300 эта задача решалась за минут пять.


для стартовой точки 1:1 выдает менее чем за минуту кучу решений .
а вот для других уходит в думы
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365149
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81maytonЗачем вам нужен глобальный массив?

глобальный , ну я честно говоря уже запамятовал как потоками пользоваться, я сказал так в предположении , что каждый поток это отдельный класс. мне видимо надо эту тему освежить.
не пинайте сильно :)
Давай порассуждаем. У тебя - идеальная задача. Она идеально параллелится.
Можно в 4 Thread запустить разные экземпляры расчетов только задав им разные
условия чтобы пути коней не пересекались. Это нужно для повышения КПД а вовсе
не для решения коллизий. Задейстовать либо Random с разными seed либо hash-функции.

Или если рассматривать проблему коня как поиск маршрутов в дереве
то нам достаточно описать простой алгоритм расщепления дерева на 4
поддерева.

Включать в эту модель какой-то глобальный массив нет смысла. Во первых
это замедлит прозводительность. 4 потока будут конкурентно писать туда.

Во вторых единой точкой соприкосновения этих потоков реально будет только
публикация отчота. Или финал работы.

Число 4 я взял просто для примера. Пока - необоснованно. Но можно брать и другие
числа.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365152
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanrauid unique,
вот допустим, на 64 ходу найдено решение. Вопрос: выйдет ли код из цикла?
Код: java
1.
while (!(!success || mc == 9))



там достаточно
Код: java
1.
while (success)


было потому что когда мс 9, то success = false.
пардон, в алгоритм не вникал.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365184
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonandron81, чувак я-же тебе писал. Подключи нормальные библиотеки логгирования. Настрой appenders.
Настрой их на запись в текстовые файлы. Вот тебе ссылки.

https://logging.apache.org/log4j/2.x/manual/appenders.html
http://logback.qos.ch/manual/appenders.html

А текстовое окошко внизу которое тебе ЛЮБЕЗНО предоставляет среда разработки
перепоелняет heap и правильно делает ибо нефиг слать терабайты текста в
ИНФОРМАЦИОННОЕ (!) на минуточку окошко.

Да вообще ничего писать не надо! Напиши только резалт когда функция закончит работу.

Положите вот такой файлиk logback.xml в папку с библиотеками или в корень класс файлов
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
<?xml version="1.0" encoding="UTF-8"?>

<configuration>
  
  <!--Console logger -->
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
  </appender>
 <!-- DEBUG log -->
  <appender name="DEBUG_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/test.debug.log</file>
	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
		<!-- daily rollover -->
		<fileNamePattern>logs/test.debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
		<timeBasedFileNamingAndTriggeringPolicy	class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
			<!-- or whenever the file size reaches 32MB -->
			<maxFileSize>32MB</maxFileSize>
		</timeBasedFileNamingAndTriggeringPolicy>
		<!-- N days' worth of history -->
		<maxHistory>3</maxHistory>
	</rollingPolicy>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
  
  <appender name="DEBUG_LOG" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="DEBUG_LOG_FILE" />
  </appender> 

  <root level="INFO">
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="DEBUG_LOG"/>
  </root>
</configuration>



main метод запускайте установив переменную Java Xmx (максимальный размер памяти)
java -Xmx1024m ru.sql.forum.samples.Horse (поправьте имя класса)

Скачайте и добавьте в путь logback-classic-<VERSION>.jar и slf4j-api-<VERSION подходящая к версии logback>.jar
Библиотеки и инструкции/примеры здесь:
http://logback.qos.ch/download.html

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

1. замена массива int[64] на 2 int или 1 long (64 bit). Доступ к битам с помощью маски, это быстрая операция.
2. для больших массивов можно использовать bitset https://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html
вам он скорее всего не нужен так как в этом классе накладные расходы не окупятся для 64 бит (2 int | 1 long).

пример работы с маской
Код: java
1.
2.
3.
4.
5.
6.
long i = 0;

// set 1 bit to position 3 from right
i = i | (1 << 3);
//set 1 bit to position 53
i = i | (1 << 53)



Аналогично работа с нулями (логический &) и считыванием (маска и сдвиг вправо на нужное кол-во позиций)

Как выше заметили, задача хорошо распараллеливается но вам пожалуй пока рано за это браться.
Если будет желание посмотрите java thread api, task executor.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365288
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonМожно в 4 Thread запустить разные экземпляры расчетов только задав им разные
условия чтобы пути коней не пересекались. Это нужно для повышения КПД а вовсе
не для решения коллизий. Задейстовать либо Random с разными seed либо hash-функции.


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



maytonИли если рассматривать проблему коня как поиск маршрутов в дереве
то нам достаточно описать простой алгоритм расщепления дерева на 4
поддерева.


это вообще трудно себе представить . как вы сделаете, чтобы в одном потоке робот не лез на клетки другого дерева ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365290
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81, кажется вы меня не слышите.

Я уже говорил о том что данное ПО не требует шаринга шахматной доски. В этом суть моего месседжа.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365391
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonandron81, кажется вы меня не слышите.

это непросто .

вы про это ?
maytonВключать в эту модель какой-то глобальный массив нет смысла. Во первых
это замедлит прозводительность. 4 потока будут конкурентно писать туда.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365441
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
uid uniquemain метод запускайте установив переменную Java Xmx (максимальный размер памяти)
java -Xmx1024m ru.sql.forum.samples.Horse (поправьте имя класса)Не нужно этой задаче столько памяти. Похоже, там консоль эклипса валится от флуда
Код: plaintext
1.
2.
 [code=powershell]
io console updater java heap space

...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365447
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanrauid uniquemain метод запускайте установив переменную Java Xmx (максимальный размер памяти)
java -Xmx1024m ru.sql.forum.samples.Horse (поправьте имя класса)Не нужно этой задаче столько памяти. Похоже, там консоль эклипса валится от флуда
Код: plaintext
1.
2.
 [code=powershell]
io console updater java heap space



я об этом уже давно твердил. но в слабость моей компетентности в JAVA к моему мнение никто не прислушивается )))
конечно , не надо. максимальная глубина 64. подумаешь ...
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365451
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton, хотел у Вас спросить .

Вот это имеет ли шанс на удачу или же чушь несусветная ?

andron81то есть вы предлагаете просто рандомно , а не последовательно как у нас выбирать следующего кандидата в разных независимых потоках. не ведя никаких проверок на совпадения (а они будут, но не велика проблема)
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365568
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81Atum1 http://algolist.manual.ru/maths/combinat/knight.php

хотя интересное правило Варнсдорфа описано.
но я правило такого не знал. поэтому у меня тупой перебор всего дерева. поэтому видимо и долго

Есть еще правило Эйлера (см вики по данной проблеме)

делаете до упора рекурсию а на остальные ходы делает обход с конца с 64 клетки.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365575
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1
делаете до упора рекурсию а на остальные ходы делает обход с конца с 64 клетки.



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

вот интересно послушать mayton .
Верно ли я его понял, что он предлагал обход дерева осуществлять не последовательно от ветки к ветке , а брать случайную. и всё это в нескольких потоках вести юзая разные массивы.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365934
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну вот 8 потоков зарядил. задумывал как в предыдущем своём сообщении

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
package thread;

public class th {
	public static void main (String[] args) {
   Thread t1 = new Thread(new Logica(1));
   Thread t2 = new Thread(new Logica(2));
   Thread t3 = new Thread(new Logica(3));
   Thread t4 = new Thread(new Logica(4));
   Thread t5 = new Thread(new Logica(5));
   Thread t6 = new Thread(new Logica(6));
   Thread t7 = new Thread(new Logica(7));
   Thread t8 = new Thread(new Logica(8));
   
   t1.start();
   t2.start();
   t3.start();
   t4.start();
   t5.start();
   t6.start();
   t7.start();
   t8.start();
   
}
}



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
package thread;

import java.util.* ;

public class Logica implements Runnable {

	 int hourseCount = 65;
	    int[][] x = new int[9][9];
	    int[] is = new int[hourseCount];
	    int[] js = new int[hourseCount];
	    long depth = 0;
	    int iStartPos = 1;
	    int jStartPos = 1;
	    int thread_name;
	 public Logica(int t) {
		 thread_name=t;
		 x[iStartPos][jStartPos] = 1;
	        is[1] = iStartPos;
	        js[1] = jStartPos;
	 }
	 
	 
	 public boolean tryHorse(int horseIndex) {
	        boolean success = true;
	        int[] moving;
	        int mc  = (int)(Math.random() * 8);
	        int x1;
	        int y1;
	        depth++;
	       //logger.debug("Глубина = {}", depth);
	      
	        if (horseIndex == 2) {
	            x1 = iStartPos;
	            y1 = jStartPos;
	            is[horseIndex] = x1;
	            js[horseIndex] = y1;
	        }

	        do {
	            moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);
	            if (moving[0] != 0 && moving[1] != 0) { //если можно поставить коня
	                x1 = moving[0];
	                y1 = moving[1];

	                x[x1][y1] = horseIndex;/*ставим*/
	                is[horseIndex] = x1;
	                js[horseIndex] = y1;

	              //  logger.debug("Можно !  Передвигаем коня на  x={} y={}, ход {}", x1, y1, horseIndex);
	                //printState();

	                if (horseIndex <= 64) {
	                    success = tryHorse(horseIndex + 1);
	                } 
	                if (horseIndex >= 60) {
	                	
	                	printState();
	                }

	                if (!success) {
	          //          logger.debug("Плохо !  Вынуждены убрать коня с x={} y={} ", is[horseIndex], js[horseIndex]);

	                    x[is[horseIndex]][js[horseIndex]] = 0;
	                    is[horseIndex] = 0;
	                    js[horseIndex] = 0;
	                    success = true;
	                }
	            }
	            mc  = (int)(Math.random() * 8);
	            if (mc == 7) {
	                success = false;
	            }
	        } while (!(!success || mc == 7));

	        depth--;

	        return success;
	    }

	    public int[] moveHorse(int i1, int i, int j) {
	    	int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
	        int[] result = new int[2];
	        result[0] = 0;
	        result[1] = 0;
	        int is;
	        int js;

	        //logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);
	        if (i + horseMoves[i1][0] >= 1 && i + horseMoves[i1][0] <= 8 &&
	            j + horseMoves[i1][1] >= 1 && j + horseMoves[i1][1] <= 8
	             && x[(i + horseMoves[i1][0])][(j + horseMoves[i1][1])] == 0
	        		) {
	        	
	            is = i + horseMoves[i1][0];
	            js = j +  horseMoves[i1][1];
	            result[0] = is;
	            result[1] = js;
	        	
	        }
	        
	        return result;
	    }

	    public void printState() {
	        
	    	System.out.println("Поток # "+thread_name);
	            for (int x = 1; x <= 8; x++) {
	                for (int y = 1; y <= 8; y++) {
	                    if (this.x[x][y] > 0) {
	                    	
	                    	System.out.print(this.x[x][y]+" ");

	                    } else if (this.x[x][y] < 0) {
	                     
	                        System.out.print("B ");
	                    } else if (this.x[x][y] == 0) {
	                        System.out.print("0 ");
	                    }
	                }
	                System.out.println();
	            }
	            System.out.println();
	    }
	
	public void run() {

//		 try{
			 tryHorse(2);
			 
//		 }catch(Exception e) {}

	}
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365936
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81ну вот 8 потоков зарядил. задумывал как в предыдущем своём сообщении
https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365943
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

то есть я сделал туфту ? )))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365949
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81Blazkowicz,

то есть я сделал туфту ? )))
Просто самое время изучить что-то новое и уменьшить немного накал говнокода.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365961
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczandron81Blazkowicz,

то есть я сделал туфту ? )))
Просто самое время изучить что-то новое и уменьшить немного накал говнокода.
Да. Собственно для юноши-джуниора сейчас важно научится правильно
использовать инструмент разработки язык и среду. Скажу честно что я глубоко не разбирал его
алгоритм. Я даже не вижу толком как он работает. Единственно - машинально
отметил какую-то избыточность в return-параметрах (зачем они вообще там?)
и неумение делать простейшие трансформации кода для достижения краткости.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365968
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81mayton, хотел у Вас спросить .

Вот это имеет ли шанс на удачу или же чушь несусветная ?

andron81то есть вы предлагаете просто рандомно , а не последовательно как у нас выбирать следующего кандидата в разных независимых потоках. не ведя никаких проверок на совпадения (а они будут, но не велика проблема)

Давайте вернемся немножко к теории самой задачи.

Если вы планируете найти 1-е попавшееся решение - то вам пойдет вариант с запуском
десятка вычислительных потоков с разной старовой клеткой и с разным раскладом
"проб коня". Какой-то из потоков первый завершит работу - и это будет успех.

Второй вариант - вы хотите найти минимум N обходов. Нам также подходит этот алгоритм
единственный нюанс надо искать зеркальные отражения и повороты на 90 градусов
базового решения (это самые первые которое мы найдем) и учитывать их как не-уникальные.

Третий вариант - вы хотите искать все решений 100% покрытий конём доски.

Здесь я затрудняюсь. Я не знаю разумное ли это число? Возможно оно астрономически
велико. Но даже для такого варианта надо что-то предложить. Я здесь я предложу
еще раз рассмотреть все решения как набор деревьев 8-чатого порядка и просто
разрезать это множество на M частей и раздать это M потокам.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39365979
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81вот интересно послушать mayton .
Верно ли я его понял, что он предлагал обход дерева осуществлять не последовательно от ветки к ветке , а брать случайную. и всё это в нескольких потоках вести юзая разные массивы.
Это мозговой штурм. Я не говорю что это единственно верное решение.
Чтобы потоки не "лупили" по одним и тем-же маршрутам надо:

1) Инстанциировать потоки разной стартовой клеточкой. Например
new HorseThread(1,new Position("a1");
new HorseThread(2,new Position("g8");

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

3) Как только все потоки сформируют теоретическое количество X ответов
(которое мы вычислим или вычитаем в умных книжках) то мы скажем
что все решения найдены и больше в природе не существует и прервем
работу всех потоков.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366386
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton1) Инстанциировать потоки разной стартовой клеточкой. Например
new HorseThread(1,new Position("a1");
new HorseThread(2,new Position("g8");

не пойдет. старт должен исходить из одной определённой клетки - условие задачи.

maytonnew HorseThread(1,new Position("a1");
new HorseThread(2,new Position("g8");
...




потоки нагибают систему конкретненько.
попробовал с одним потоком поискать решения на полях 5x5 , 6x6 с разных начальных точек. ищет все решения и довольно быстро. а вот поля 7x7 ? 8x8 надолго сильно задумывается.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366426
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81потоки нагибают систему конкретненько.
попробовал с одним потоком поискать решения на полях 5x5 , 6x6 с разных начальных точек. ищет все решения и довольно быстро. а вот поля 7x7 ? 8x8 надолго сильно задумывается.
Это норм. Так и нужно. Утилизация ибо. После топика рендеринга
картинок я пришел к выводу что для процессов которые интенсивно
используют CPU и почти не конкурируют по памяти (типа численный метод;
один раз получил задание и ушел в себя надолго) оптимальная формула
числа Java- потоков

Jt = m * n + 1

Где m - число ядер и n - число hyper-threads на ядро. Для моего слабого ноутбука
это было 5. Дальнейшее увеличение числа потоков не повышало эффективности
алгоритма.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366428
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81не пойдет. старт должен исходить из одной определённой клетки - условие задачи.

Хорошо. Пускай они стартуют с одной точки. Тогда нам нужны несколько потоков
параметризованные только генератором случайных чисел с разным начальным вектором.

Код: java
1.
2.
3.
new HorseThread(new Random(1),new Position("a1");
new HorseThread(new Random(2),new Position("a1");
....
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366769
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,
мозговой штурм , а именно :
рандомно , а не последовательно как у нас выбирать следующего кандидата в разных независимых потоках. не ведя никаких проверок на совпадения" быстрых решений не приносит - более часа ни одного решения не найдено.
а оно даже немного и понятно. Ведь на каждом шаге 9 вариантов которые выбираются случайно (9 - выход на уровень выше). таким образом в данной ветке мы можем как сразу выйти к предку , так и побродить - 9-ка может не выпадать.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366849
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

а про метод Варнсдорфа прочитал, что может в тупик заводить. контр.примеры писали что существуют.
остаётся метод деления дерева на поддеревья подсказанный mayton. но я не представляю как этот способ реализуется.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366978
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81mayton,
мозговой штурм , а именно :
рандомно , а не последовательно как у нас выбирать следующего кандидата в разных независимых потоках. не ведя никаких проверок на совпадения" быстрых решений не приносит - более часа ни одного решения не найдено.
а оно даже немного и понятно. Ведь на каждом шаге 9 вариантов которые выбираются случайно (9 - выход на уровень выше). таким образом в данной ветке мы можем как сразу выйти к предку , так и побродить - 9-ка может не выпадать.
Ну и зачем ты сразу выходишь наверх? Обойди все восемь узлов дерева в рандом порядке.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39366995
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonandron81mayton,
мозговой штурм , а именно :
рандомно , а не последовательно как у нас выбирать следующего кандидата в разных независимых потоках. не ведя никаких проверок на совпадения" быстрых решений не приносит - более часа ни одного решения не найдено.
а оно даже немного и понятно. Ведь на каждом шаге 9 вариантов которые выбираются случайно (9 - выход на уровень выше). таким образом в данной ветке мы можем как сразу выйти к предку , так и побродить - 9-ка может не выпадать.
Ну и зачем ты сразу выходишь наверх? Обойди все восемь узлов дерева в рандом порядке.

нет, ну не сразу, а волею случая.
а вы уверены , что если проверять рандомно все 8 узлов и в случае ни одного успешного выходить на уровень выше, то это будет выигрыш по сравнению последовательного обхода ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367054
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81maytonпропущено...

Ну и зачем ты сразу выходишь наверх? Обойди все восемь узлов дерева в рандом порядке.

нет, ну не сразу, а волею случая.
а вы уверены , что если проверять рандомно все 8 узлов и в случае ни одного успешного выходить на уровень выше, то это будет выигрыш по сравнению последовательного обхода ?
А ты думал о том что при последовательном обходе у тебя все threads будут делать одну и ту же работу дублируя друг друга? И зачем такой параллелизм?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367077
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonА ты думал о том что при последовательном обходе у тебя все threads будут делать одну и ту же работу дублируя друг друга? И зачем такой параллелизм?

нет, конечно.

я думал и запрограммировал вот так :
пусть точка отсчета 1:1 во всех потоках.
в каждой вершине дерева случайно выбираем одно из возможных направлений + направление назад, делаем это в разных независимых потоках ( в результате будут разные маршруты). не ведя нигде никаких проверок на совпадения. таким образом в каждой вершине случайным образом выбирается одно из возможных направлений или может выбраться путь к предку назад.
Путь обратно может быть выбран как сразу так и потом , волей случайности .
Этот алгоритм успеха не принёс
вы же предлагаете рандомить возможные направления , а по их исчерпанию возвращаться назад.
Вот я и предположил , что вот последовательный ход по вершинам и случайный ход. И там и там обход всех вершин . поэтому и вопрос откуда такая уверенность , что последний приведёт к успеху.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367153
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81maytonА ты думал о том что при последовательном обходе у тебя все threads будут делать одну и ту же работу дублируя друг друга? И зачем такой параллелизм?

нет, конечно.

я думал и запрограммировал вот так :
пусть точка отсчета 1:1 во всех потоках.
в каждой вершине дерева случайно выбираем одно из возможных направлений + направление назад, делаем это в разных независимых потоках ( в результате будут разные маршруты). не ведя нигде никаких проверок на совпадения. таким образом в каждой вершине случайным образом выбирается одно из возможных направлений или может выбраться путь к предку назад.
Путь обратно может быть выбран как сразу так и потом , волей случайности .
Этот алгоритм успеха не принёс
вы же предлагаете рандомить возможные направления , а по их исчерпанию возвращаться назад.
Вот я и предположил , что вот последовательный ход по вершинам и случайный ход. И там и там обход всех вершин . поэтому и вопрос откуда такая уверенность , что последний приведёт к успеху.
Да ладно. Нигде я не предлагал ходить назад.

Я ещё раз предложу тебе публиковать актуальный исходник а то получается что мы просто ведем философской дискурс
Причём ты весьма вольно дополняешь мои мысли своими и потом говоришь театрально "успеха не принёс"..
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367223
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДа ладно. Нигде я не предлагал ходить назад.


а тут ?

maytonНу и зачем ты сразу выходишь наверх? Обойди все восемь узлов дерева в рандом порядке.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367224
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

смутило слово "СРАЗУ" . словно ход назад вы всё же не отрицаете
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367230
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне лень спорить. Я-то свои мысли знаю. Мдя.

А с тебя - должок. Гони сорцы. :)
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367235
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
package horses;

import java.util.* ;

public class Horse implements Runnable {
	int lll=6;/*длина доски*/
	 int hourseCount = 65;
	    int[][] x = new int[lll+1][lll+1];
	    int[] is = new int[hourseCount];
	    int[] js = new int[hourseCount];
	    long depth = 0;
	    int thread_name;
	    int iStartPos ;
	    int jStartPos;
	 public Horse(int t,int iStartPos , int jStartPos )
			  {
		 thread_name=t;
		 x[iStartPos][jStartPos] = 1;
		 this.jStartPos=jStartPos ;
		 this.iStartPos=iStartPos;
	        is[1] = iStartPos;
	        js[1] = jStartPos;
	 }
	 
	 
	 public boolean tryHorse(int horseIndex) {
	        boolean success = true;
	        int[] moving;
	        int mc  = (int)(Math.random() * 8);
	        int x1;
	        int y1;
	        depth++;
	        //System.out.println("tryHorse("+horseIndex+")");
	        printState();
	       //logger.debug("Глубина = {}", depth);
	      
	        if (horseIndex == 2) {
	            x1 = this.iStartPos;
	            y1 = this.jStartPos;
	            is[horseIndex] = x1;
	            js[horseIndex] = y1;
	            printState();
	        }

	        do {
	            moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);
	            if (moving[0] != 0 && moving[1] != 0) { //если можно поставить коня
	                x1 = moving[0];
	                y1 = moving[1];

	                x[x1][y1] = horseIndex;/*ставим*/
	                is[horseIndex] = x1;
	                js[horseIndex] = y1;

	                //System.out.println("Можно !  Передвигаем коня на "+ x1+" "+y1 +" ход "+ horseIndex);
	                printState();
	                if (horseIndex >=lll*lll) 	{
	                	printState();}
	                if (horseIndex <= lll*lll+1) {
	                    success = tryHorse(horseIndex + 1);
	                } 
	                
	                	
	     
	                

	                
	                if (!success) {
	                	
	          //          logger.debug("Плохо !  Вынуждены убрать коня с x={} y={} ", is[horseIndex], js[horseIndex]);
	                printState();
	                    x[is[horseIndex]][js[horseIndex]] = 0;
	                    //System.out.println("Плохо !   Вынуждены убрать коня "+ is[horseIndex]+" "+js[horseIndex] +" ход ");
	                    is[horseIndex] = 0;
	                    js[horseIndex] = 0;
	                    success = true;
	                    
	                }
	            }
	            mc = (int)(Math.random() * 9);
	            if (mc == 8) {
	                success = false;
	            }
	        } while (!(!success || mc == 8));

	        depth--;

	        return success;
	    }

	    public int[] moveHorse(int i1, int i, int j) {
	    	int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
	        int[] result = new int[2];
	        result[0] = 0;
	        result[1] = 0;
	        int is;
	        int js;

	        //logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);
	        if (i + horseMoves[i1][0] >= 1 && i + horseMoves[i1][0] <= lll &&
	            j + horseMoves[i1][1] >= 1 && j + horseMoves[i1][1] <= lll
	             && x[(i + horseMoves[i1][0])][(j + horseMoves[i1][1])] == 0
	        		) {
	        	
	            is = i + horseMoves[i1][0];
	            js = j +  horseMoves[i1][1];
	            result[0] = is;
	            result[1] = js;
	        	
	        }
	        
	        return result;
	    }

	    public void printState() {
	        
	    	System.out.println("Поток # "+thread_name);
	            for (int x = 1; x <= lll; x++) {
	                for (int y = 1; y <= lll; y++) {
	                    if (this.x[x][y] > 0) {
	                    	
	                    	System.out.print(this.x[x][y]+" ");

	                    } else if (this.x[x][y] < 0) {
	                     
	                        System.out.print("B ");
	                    } else if (this.x[x][y] == 0) {
	                        System.out.print("0 ");
	                    }
	                }
	                System.out.println();
	            }
	            System.out.println();
	    }
	
	public void run() {

//		 try{
			 tryHorse(2);
			 
//		 }catch(Exception e) {}

	}
}



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
package horses;

public class main {
	public static void main (String[] args) {
   
		Thread t1 = new Thread(new Horse(1,1,2));
		/*
		Thread t1 = new Thread(new Horse(1,5,5));
   Thread t2 = new Thread(new Horse(2,4,2));
   
   Thread t4 = new Thread(new Horse(4,3,2));
   Thread t5 = new Thread(new Horse(5,6,4));
   Thread t6 = new Thread(new Horse(6,1,3));
   Thread t7 = new Thread(new Horse(7,2,1));
   Thread t8 = new Thread(new Horse(8,3,4));
   */
		
   t1.start();
/*   t2.start();
   t3.start();
   t4.start();
   t5.start();
   t6.start();
   t7.start();
   t8.start();
  */ 
}
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367236
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну йошкин крот. Мой рефакторинг ты конечно проигнорировал.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367238
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНу йошкин крот. Мой рефакторинг ты конечно проигнорировал.

так всё ужасно читается ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367251
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да не в том дело. Яж тебе совет давал и по performance.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367721
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДа не в том дело. Яж тебе совет давал и по performance.


1. System.out флудит беспощадно и блокирует скорость вычислений. Даже с заглушкой в /dev/null все равно
будет обеспечет терафлоп ненужной работы которую никто не смотрит. Вобщем вынести в slf4j или JUL с уровнем trace.

ну честно , я не увидел разницы по скорости с протоколированием slf4j. Если на то пошло можно принты и поотключать.
оставить только вывод матрицы. и протокол по средствам slf4j так же вызывает перегруз кучи.
на замене System.out.print протоколирование по средствам slf4j в данном случае не хотел бы заострять внимание.


2. Результат вычислений возвращается через строковую константу. Это странно. Так обычно не делают.

любезно с этим помогли. теперь булеан


3. Есть flow где имеет смысл добавить линию else чтобы отключить избыточные расчеты.
Есть повторы вычисления одного выражения которые можно зарефакторить через
introduce temp variable.

боюсь где-нибудь подкосячить добавлением Else . поэтому не делал.


4. Очень много замечаний к codeStyle. Классы с маленькой буквы а имена переменных с dash.
Это ломает зрение.

ну извиняюсь. пока мало опыта. Глаза разбегаются там от требований после того как погуглил. я это делать буду пол. дня.
пока как я должен по минимуму:
1) классы с большой буквы , переменные с маленькой и никаких подчеркиваний ?
2) в наименовании методов, классов, переменных использование английских слов.
подскажите , я перепишу
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39367990
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81ну извиняюсь. пока мало опыта.

Отличная отмазка чтобы ничего не делать.

andron81Глаза разбегаются там от требований после того как погуглил. я это делать буду пол. дня.

Ерунда. Переименовать все переменные через рефакторинг и попросить IDE отформатировать код. 15 минут, на придумать внятные имена.

andron81подскажите , я перепишу
Пример

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int boardSize = 6;/*длина доски*/
int[][] board = new int[boardSize][boardSize];

int numberOfSteps = 65;
int[] stepTrailForPurpose = new int[numberOfSteps];
int[] stepTrailForAnotherPurpose = new int[numberOfSteps];
long depth = 0;
int threadName;
int purposeStartPosition ;
int anotherPurposeStartPosition;



Никаких mс, t, j, is, js, xs и прочих угадаек. Имя точно должно объяснять нафига тут эта переменная и что в ней.

i допускается только в циклах. Иногда можно сокращать b, s, c для временных переменных byte, String, char, но их область видимости должна быть минимальной - 2-3 рядом стоящие строки. У вас же такие переменные шатаются по всему коду.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368171
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron811. System.out флудит беспощадно и блокирует скорость вычислений. Даже с заглушкой в /dev/null все равно
будет обеспечет терафлоп ненужной работы которую никто не смотрит. Вобщем вынести в slf4j или JUL с уровнем trace.

ну честно , я не увидел разницы по скорости с протоколированием slf4j. Если на то пошло можно принты и поотключать.
оставить только вывод матрицы. и протокол по средствам slf4j так же вызывает перегруз кучи.
на замене System.out.print протоколирование по средствам slf4j в данном случае не хотел бы заострять внимание.

Смотри раз уж пошла такая пьянка. Давай сделаем так. Я помаркирую твой исходник секциями
Код: java
1.
// TODO: ....


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

И ты, позадавав уточняющие вопросы это сделаешь. А после этого запустишь еще этого
"блуждающего коня" померяешь эффект. И скажешь - помогло или нет. ОК?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368276
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton, хокей !
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368301
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Держи. Я поставил отметки TODO: только там где на мой взгляд имеет место
недостаток performance.

TODO не удаляй до тех пор пока фактически не будет
сделано по ним исправление. Задавай вопросы. Отвечу.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
package horses;

import java.util.* ;

public class Horse implements Runnable {
    int lll=6;/*длина доски*/
    int hourseCount = 65;
    // TODO: заименить int[][] x  на  int[] x. Переписать логику соотв.
    int[][] x = new int[lll+1][lll+1];
    int[] is = new int[hourseCount];
    int[] js = new int[hourseCount];
    long depth = 0;
    int thread_name;
    int iStartPos ;
    int jStartPos;
    public Horse(int t,int iStartPos , int jStartPos )
    {
        thread_name=t;
        x[iStartPos][jStartPos] = 1;
        this.jStartPos=jStartPos ;
        this.iStartPos=iStartPos;
        is[1] = iStartPos;
        js[1] = jStartPos;
    }


    public boolean tryHorse(int horseIndex) {
        boolean success = true;
        int[] moving;
        int mc  = (int)(Math.random() * 8);
        int x1;
        int y1;
        depth++;
        //System.out.println("tryHorse("+horseIndex+")");
        // TODO: Убрать printState()
        printState();
        //logger.debug("Глубина = {}", depth);

        if (horseIndex == 2) {
            x1 = this.iStartPos;
            y1 = this.jStartPos;
            is[horseIndex] = x1;
            js[horseIndex] = y1;
            // TODO: Убрать printState()
            printState();
        }

        do {
            moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);
            if (moving[0] != 0 && moving[1] != 0) { //если можно поставить коня
                x1 = moving[0];
                y1 = moving[1];

                x[x1][y1] = horseIndex;/*ставим*/
                is[horseIndex] = x1;
                js[horseIndex] = y1;
                // TODO: Убрать printState()
                //System.out.println("Можно !  Передвигаем коня на "+ x1+" "+y1 +" ход "+ horseIndex);
                printState();
                if (horseIndex >=lll*lll) 	{
                    // TODO: Оставить printState только там где найден вариант решения этой задачи.
                    printState();}
                if (horseIndex <= lll*lll+1) {
                    success = tryHorse(horseIndex + 1);
                }






                if (!success) {

                    //          logger.debug("Плохо !  Вынуждены убрать коня с x={} y={} ", is[horseIndex], js[horseIndex]);
                    // TODO: Убрать printState()
                    printState();
                    x[is[horseIndex]][js[horseIndex]] = 0;
                    //System.out.println("Плохо !   Вынуждены убрать коня "+ is[horseIndex]+" "+js[horseIndex] +" ход ");
                    is[horseIndex] = 0;
                    js[horseIndex] = 0;
                    success = true;

                }
            }
            mc = (int)(Math.random() * 9);
            if (mc == 8) {
                success = false;
            }
        } while (!(!success || mc == 8));

        depth--;

        return success;
    }

    // TODO: Сделать методом moveHorse inline. Отказаться от returnvalue.
    public int[] moveHorse(int i1, int i, int j) {
        // TODO: заименить horseMoves[][] x  на  одномерный массив int[] x, или два одномерных.
        int[][] horseMoves = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
        int[] result = new int[2];
        result[0] = 0;
        result[1] = 0;
        int is;
        int js;

        //logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);
        if (i + horseMoves[i1][0] >= 1 && i + horseMoves[i1][0] <= lll &&
                j + horseMoves[i1][1] >= 1 && j + horseMoves[i1][1] <= lll
                && x[(i + horseMoves[i1][0])][(j + horseMoves[i1][1])] == 0
                ) {

            is = i + horseMoves[i1][0];
            js = j +  horseMoves[i1][1];
            result[0] = is;
            result[1] = js;

        }

        return result;
    }

    public void printState() {

        System.out.println("Поток # "+thread_name);
        for (int x = 1; x <= lll; x++) {
            for (int y = 1; y <= lll; y++) {
                if (this.x[x][y] > 0) {

                    System.out.print(this.x[x][y]+" ");

                } else if (this.x[x][y] < 0) {

                    System.out.print("B ");
                } else if (this.x[x][y] == 0) {
                    System.out.print("0 ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }

    public void run() {

//		 try{
        tryHorse(2);

//		 }catch(Exception e) {}

    }
}

...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368805
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДержи. Я поставил отметки TODO: только там где на мой взгляд имеет место
недостаток performance.

TODO не удаляй до тех пор пока фактически не будет
сделано по ним исправление. Задавай вопросы. Отвечу.



постараюсь выполнить за выходные .

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

но блин код вышел это полный трэш . никуда не годиться )))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368883
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и сразу вопрос

mayton // TODO: заименить int[][] x на int[] x. Переписать логику соотв.
int[][] x = new int[lll+1][lll+1];


а как вы собираетесь проверять был ли конь в клетке i,j ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368904
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81и сразу вопрос

mayton // TODO: заименить int[][] x на int[] x. Переписать логику соотв.
int[][] x = new int[lll+1][lll+1];


а как вы собираетесь проверять был ли конь в клетке i,j ?

это же простая развертка двумерного массива в одномерный, на пальцах:

массив а=int[8][10] приводим в b=int[80];

a[5][3] = b[5 *10 + 3] = b[53]
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39368939
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uid uniqueandron81и сразу вопрос

пропущено...


а как вы собираетесь проверять был ли конь в клетке i,j ?

это же простая развертка двумерного массива в одномерный, на пальцах:

массив а=int[8][10] приводим в b=int[80];

a[5][3] = b[5 *10 + 3] = b[53]

зачем ? в чем выигрыш ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369040
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81зачем ? в чем выигрыш ?

Оптимизация по скорости и расходу памяти, ведь каждый объект занимает дополнительное место (описание и связи), каждый вызов метода примерно на 15% медленнее выполнения inline кода или доступа к полю напрямую.

Нашел такой тест, не поленился его запустить в микро-бенчмарке

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
package org.sample;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.sample.Measure.X;
import static org.sample.Measure.Y;

@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@OperationsPerInvocation(X*Y)
@Warmup(iterations = 30, time = 100, timeUnit=MILLISECONDS)
@Measurement(iterations = 5, time = 1000, timeUnit=MILLISECONDS)
@State(Scope.Thread)
@Threads(1)
@Fork(1)
public class Measure
{
    static final int X = 100_000, Y = 10;
    private final int[] single = new int[X*Y];
    private final int[][] multi = new int[X][Y];

    @Setup
    public void setup() {
        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
        for (int i=0; i<single.length; i++) single[i] = rnd.nextInt();
        for (int i=0; i<multi.length; i++)
            for (int j=0; j<multi[0].length; j++)
                multi[i][j] = rnd.nextInt();
    }

    @Benchmark
    public long sumSingle() { return sumSingle(single); }

    @Benchmark
    public long sumMulti() { return sumMulti(multi); }

    public static long sumSingle(int[] arr) {
        int total = 0;
        for (int i=0; i<arr.length; i++)
            total+=arr[i];
        return total;
    }

    public static long sumMulti(int[][] arr) {
        int total = 0;
        for (int i=0; i<arr.length; i++)
            for (int j=0; j<arr[0].length; j++)
                total+=arr[i][j];
        return total;
    }
}



Результат (на 8 Java):

# Run complete. Total time: 00:00:16

Benchmark Mode Cnt Score Error Units
Measure.sumMulti avgt 5 0.655 ± 0.037 ns/op
Measure.sumSingle avgt 5 0.288 ± 0.023 ns/op

Примерно в 2 раза медленне подсчет суммы (из за циклов / проверок) в многомерном массиве чем в одномерном.

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

Аналогично, целочисленное деление и умножение быстрее примерно в 2 раза чем с плавающей точкой (но это тоже не нужно, просто к сведению)

По расходу памяти когда запускал пример (с первой страницы форума), хип был в пределах 120 - 270 МБ, периодически сбрасывался на 120-140 те расход небольшой. Out of memory мог быть вызван тем что использовался размер хипа по умолчанию близкий к 250МБ

Как проверить размер хипа по умолчанию

java -XX:+PrintFlagsFinal -version | findstr HeapSize

или на юниксе/линуксе/маке

java -XX:+PrintFlagsFinal -version | grep HeapSize

У меня вывела 256МБ начальный размер хипа по умолчанию:

uintx ErgoHeapSizeLimit = 0 {product}
uintx HeapSizePerGCThread = 87241520 {product}
uintx InitialHeapSize := 268435456 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 4294967296 {product}

PS пардон что не вникаю в тему, у меня сейчас разгребания Java кода конца 90х (почти Java 1.1) нaписанного в стиле 80х (даже коллекций нет и процедурное программирование к зачатками объектов), голова уже не соображает, особенно в пятницу... ;-) Хороших выходных!
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369346
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДержи. Я поставил отметки TODO: только там где на мой взгляд имеет место
недостаток performance.

TODO не удаляй до тех пор пока фактически не будет
сделано по ним исправление. Задавай вопросы. Отвечу.



Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
package horses;

import java.util.* ;

public class Horse implements Runnable {
    int sideofBoard=6;/*сторона доски*/
    int Count = sideofBoard*sideofBoard; /*количество ходов кот. нужно сделать*/
    // TODO: заименить int[][] x  на  int[] x. Переписать логику соотв.
    int[] board = new int[sideofBoard*10+sideofBoard+1]; 
    int[] iresultLog = new int[Count+1]; /*лог результат по вертикале.   hourseCount+1 , потому как хочу индекс вести не с 0, а с 1  */
    int[] jresultLog = new int[Count+1]; /*лог результат по горизонтале. hourseCount+1 , потому как хочу индекс вести не с 0, а с 1  */
    long depth = 0;
    int threadName;                            /*имя потока*/
    int iStartPos ;							   /*старт координата по вертикале*/	
    int jStartPos;							   /*старт координата по горизонтале*/	
    public Horse(int t,int iStartPos , int jStartPos )
    {
        threadName=t;						   /*именуем поток */
        board[iStartPos*10+jStartPos] = 1;	   /*ставим первый ход в массиве на доске*/
        this.jStartPos=jStartPos ;
        this.iStartPos=iStartPos;
        iresultLog[1] = iStartPos;			   /*ставим первый ход в лог по вертикале*/
        jresultLog[1] = jStartPos;			   /*ставим первый ход в лог по горизонтале*/	
    }
  public boolean tryHorse(int horseIndex) {
        boolean success = true;
        int[] moving;
        int variant  = (int)(Math.random() * 8);
        int x1;
        int y1;
        depth++;
        // TODO: Убрать printState()
       if (horseIndex == 2) {
            x1 = this.iStartPos;
            y1 = this.jStartPos;
            iresultLog[horseIndex] = x1;
            jresultLog[horseIndex] = y1;
            // TODO: Убрать printState() 
        }
        do {
            moving = moveHorse( variant, iresultLog[horseIndex - 1], jresultLog[horseIndex - 1]);
            if (moving[0] != 0 && moving[1] != 0) { //если можно поставить коня
                x1 = moving[0];
                y1 = moving[1];
                 board[x1*10+y1] = horseIndex;/*ставим*/
                iresultLog[horseIndex] =  x1;
                jresultLog[horseIndex] =  y1;
                // TODO: Убрать printState()
              if (horseIndex ==sideofBoard*sideofBoard) 	{
                	// TODO: Оставить printState только там где найден вариант решения этой задачи.
                	printState();}
                if (horseIndex <= sideofBoard*sideofBoard+1) {
                    success = tryHorse(horseIndex + 1);
                } 
                if (!success) {
                // TODO: Убрать printState()
                    board[iresultLog[horseIndex]*10+jresultLog[horseIndex]] = 0;
                    //System.out.println("Плохо !   Вынуждены убрать коня "+ is[horseIndex]+" "+js[horseIndex] +" ход ");
					iresultLog[horseIndex] = 0;
                	jresultLog[horseIndex] = 0;
                    success = true;                    
                }
            }
            variant = (int)(Math.random() * 9);
            if ( variant == 8) {
                success = false;
            }
        } while (!(!success ||  variant == 8));
        depth--;
        return success;
    }
    

    // TODO: Сделать методом moveHorse inline. Отказаться от returnvalue.
    public int[] moveHorse(int i1, int i, int j) {
        // TODO: заименить horseMoves[][] x  на  одномерный массив int[] x, или два одномерных.
        int[] horseMovesI = {1,2, 2, 1,-1,-2,-2,-1};
        int[] horseMovesJ = {2,1,-1,-2,-2,-1,1,2};
        int[] result = new int[2];
        result[0] = 0;
        result[1] = 0;
        int is;
        int js;
        //logger.debug("Попытка {} из 8. проверим можно ли передвинуть с {} {} ",i1, i, j);
        if (i + horseMovesI[i1] >= 1 && i + horseMovesI[i1] <= sideofBoard &&
                j + horseMovesJ[i1] >= 1 && j + horseMovesJ[i1] <= sideofBoard
                && board[(i + horseMovesI[i1])*10+(j + horseMovesJ[i1])] == 0
                ) {
            is = i + horseMovesI[i1];
            js = j +  horseMovesJ[i1];
            result[0] = is;
            result[1] = js;
        }
        return result;
    }
    public void printState() {
        System.out.println("Поток # "+threadName);
        for (int i = 1; i <= sideofBoard; i++) {
        	for (int j = 1; j <= sideofBoard; j++) {
                System.out.print(board[i*10+j]+ " ");
                   	}
        	System.out.println();        	
        }        
    }
    public void run() {

//		 try{
        tryHorse(2);
//		 }catch(Exception e) {}
    }
}




не справился с inline функцией . то есть погуглив я выяснил(не знаю правда ошибочно или нет), что inline методы в java создать не выйдет. Можно сделать только статик.
Но даже это если и так , то как мне избавится от returnValue совсем неясно. можете привести простой пример ? скажем функцию
вычисляющая x + 10 как сделать inline ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369347
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81 скажем функцию
вычисляющая x + 10 как сделать inline ?

инлайн и без рreturnValue
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369354
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uid unique Вам эта оптимизация сейчас не нужна, отработайте алгоритм вначале.


согласен, думаю пример не для отработки (не лёгкий), но раз уж понеслась , то придется )



uid uniqueКак проверить размер хипа по умолчанию

java -XX:+PrintFlagsFinal -version | findstr HeapSize


петрушками типа -XX: вообще не умею пользоваться
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369418
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас поясню суть рефакторинга с inline.

Я обратил внимание на то что функция

Код: java
1.
 moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);



Используется 1 единственный раз. При этом она использует return int[] с одной целью - обеспечить
возврат пары координат (moving[]). Поскольку стандарт Java language не дает возможности
делать out-parameters то автор это решает за счет возврата array.

Далее я рассудил так. Если мы тело функции перенесем в 1 единственную точку ее вызова
то мы избавляемся от такого странного способа возврата. А результат работы moveHorse
мы можем записать в переменные.

Код: java
1.
2.
moving[0] => mx
moving[1] => my



Из алгоритма уходят операции индексации moving и операция передачи через стек ссылки
на array. Сам array и его аллокация new[] тоже уходит т.к. массив становится не нужен.
+положительный эффект - меньше нагрузка на heap.

С точки зрения Мартина Фаулера - мы сделали не очень хорошо т.к. увеличиваем размер
метода. Но с точки зрения performance и GC - мы улучшим картину.

Если-бы функция moveHorse использовалась много раз или была-бы рекурсивной то
мы не смогли-бы такой фокус провернуть.

Сам термин inline пускай вас не смущает. Можете заменить его на копи-пасту. Это тоже самое.
Так в C++ например работают механизмы развёртывания макросов.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369422
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81зачем ? в чем выигрыш ?
Это мой старый добрый рефакторинг который я юзаю уже много лет.
В основном он эффективен в растровой графике. Задавать картинку
и работать с ней удобнее через int[] rgbColors чем через int[][] rgbColors.
Так скорость выше. Это я знаю еще со времен С++. В некоторых случаях
длину строки выравнивают на число байт кратных машинному WORD
процессора. Типа padding строки. Плюс есть еще много нюансов
связанных с тем как аллокатор int[][] размещает суб-массивы в куче.
При удачном стечении обстоятельств (обходим массив слева направо
и сверху вниз) канал памяти получает тразнакции чтения по линейным
адресам. Это благоприятный кейс. Но возможно будет и не-благоприятный.

Когда я задаю матрицу или куб (или гиперкуб) через линейный массив
то я сам вручную обеспечиваю линейный порядок доступа к элементам
памяти.

Некий господин выше не поленился и даже привел бенчмарк с использованием JMH
и с прогревом компиллятора как положено. Что-ж. Я не буду с ним спорить.
Мои последние бенчмарки я делал еще во время JDK6 а тогда
и деревья были выше и оптимизатор был попроще.

Возможно сейчас и нет острой необходимости выключать int[][] но я
лишний раз замечу что наша задача выгодно отличается от других.
У нас - квадратное поле (а не зубчатое) и ширина строки заведомо известна.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369463
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНекий господин выше не поленился и даже привел бенчмарк с использованием JMH
и с прогревом компиллятора как положено. Что-ж. Я не буду с ним спорить.
Мои последние бенчмарки я делал еще во время JDK6 а тогда
и деревья были выше и оптимизатор был попроще.
JMH тест как раз показываeт большую производительность у линейного массива (> 2 раз) чем у многомерного, как и ожидалось. Если без микробенчмарка делать, с System.currentTime, то скорее всего разница будет менее заметна.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369471
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
о гспди....обалденно почитать всё это нубу )))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369503
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonСейчас поясню суть рефакторинга с inline.

Я обратил внимание на то что функция

Код: java
1.
 moving = moveHorse(mc, is[horseIndex - 1], js[horseIndex - 1]);



Используется 1 единственный раз. При этом она использует return int[] с одной целью - обеспечить
возврат пары координат (moving[]). Поскольку стандарт Java language не дает возможности
делать out-parameters то автор это решает за счет возврата array.

Далее я рассудил так. Если мы тело функции перенесем в 1 единственную точку ее вызова
то мы избавляемся от такого странного способа возврата. А результат работы moveHorse
мы можем записать в переменные.

Код: java
1.
2.
moving[0] => mx
moving[1] => my



Из алгоритма уходят операции индексации moving и операция передачи через стек ссылки
на array. Сам array и его аллокация new[] тоже уходит т.к. массив становится не нужен.
+положительный эффект - меньше нагрузка на heap.

С точки зрения Мартина Фаулера - мы сделали не очень хорошо т.к. увеличиваем размер
метода. Но с точки зрения performance и GC - мы улучшим картину.

Если-бы функция moveHorse использовалась много раз или была-бы рекурсивной то
мы не смогли-бы такой фокус провернуть.

Сам термин inline пускай вас не смущает. Можете заменить его на копи-пасту. Это тоже самое.
Так в C++ например работают механизмы развёртывания макросов.

понял. переделаю
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369683
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81понял. переделаю
Вроде немного очухался за выходной. Если будете делать перебор в нескольких потоках, то придется либо лочить общий ресурс, либо делать его volatile, что для больших объектов плохо.

Для отдельных локов на чрение и запись, можете использовать подобный код:
(Предупреждаю что сам по себе код бессмысленный, просто пример с расшареным ресурсом):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Horse implements Runnable {

    static final int[][] HORSE_MOVES = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
    static final int HOURSE_COUNT = 65;
    static final int BOARD_DIMENSION =6;/*длина доски*/

    static int[][] USED_BOARD_CELLS = new int[BOARD_DIMENSION +1][BOARD_DIMENSION +1];
    static ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();

    final int[] xPositions = new int[HOURSE_COUNT];
    final int[] yPositions = new int[HOURSE_COUNT];

    long depth = 0;
    int threadId;
    int startXPos;
    int startYPos;


    public Horse(int threadId, int startXPos, int startYPos )
    {
        this.threadId =threadId;

        writeLock.lock();
        try {
            //Double check after obtaining write lock that cell is available
            if(USED_BOARD_CELLS[startXPos][startYPos] != 0) {
                //Cell is used by another Horse
                throw new RuntimeException("Board cell "+startXPos + "x"+startYPos+" is already used!");
            }
            USED_BOARD_CELLS[startXPos][startYPos] = 1;
        } finally {
            //release write lock
            writeLock.unlock();
        }

        this.startYPos =startYPos ;
        this.startXPos =startXPos;

        xPositions[1] = startXPos;
        yPositions[1] = startYPos;
    }

    public static void main (String[] args) {

        Thread t1 = new Thread(new Horse(1,1,2));
		/*
		Thread t1 = new Thread(new Horse(1,5,5));
   Thread t2 = new Thread(new Horse(2,4,2));

   Thread t4 = new Thread(new Horse(4,3,2));
   Thread t5 = new Thread(new Horse(5,6,4));
   Thread t6 = new Thread(new Horse(6,1,3));
   Thread t7 = new Thread(new Horse(7,2,1));
   Thread t8 = new Thread(new Horse(8,3,4));
   */

        t1.start();
/*   t2.start();
   t3.start();
   t4.start();
   t5.start();
   t6.start();
   t7.start();
   t8.start();
  */
    }


    public boolean tryHorse(int horseIndex) {
        boolean success = true;

        int xPos;
        int yPos;
        depth++;
        //System.out.println("tryHorse("+horseIndex+")");
        printState();
        //logger.debug("Глубина = {}", depth);

        if (horseIndex == 2) {
            xPos = this.startXPos;
            yPos = this.startYPos;
            xPositions[horseIndex] = xPos;
            yPositions[horseIndex] = yPos;
            printState();
        }

        int i;
        int j;
        int nextX;
        int nextY;

        for(int stepIndex = 0; stepIndex < HORSE_MOVES.length; stepIndex++){
            i = xPositions[horseIndex - 1];
            j = yPositions[horseIndex - 1];


            readLock.lock();
            try {
                if (i + HORSE_MOVES[stepIndex][0] >= 1 && i + HORSE_MOVES[stepIndex][0] <= BOARD_DIMENSION &&
                        j + HORSE_MOVES[stepIndex][1] >= 1 && j + HORSE_MOVES[stepIndex][1] <= BOARD_DIMENSION
                        && USED_BOARD_CELLS[(i + HORSE_MOVES[stepIndex][0])][(j + HORSE_MOVES[stepIndex][1])] == 0) {
                    nextX = i + HORSE_MOVES[stepIndex][0];
                    nextY = j + HORSE_MOVES[stepIndex][1];

                    //если можно поставить коня
                    xPos = nextX;
                    yPos = nextY;
                } else {
                    // Continue next
                    continue;
                }
            } finally {
                readLock.unlock();
            }


            writeLock.lock();
            try {
                if(USED_BOARD_CELLS[startXPos][startYPos] == 1) {
                    //Cell is used by another Horse, skip and continue
                    continue;
                }
                USED_BOARD_CELLS[xPos][yPos] = horseIndex;/*ставим*/
            } finally {
                writeLock.unlock();
            }

            xPositions[horseIndex] = xPos;
            yPositions[horseIndex] = yPos;

            //System.out.println("Можно !  Передвигаем коня на "+ x1+" "+y1 +" ход "+ horseIndex);
            //printState();

            if (horseIndex <= BOARD_DIMENSION * BOARD_DIMENSION +1) {
                if (!tryHorse(horseIndex + 1)) {
                    //          logger.debug("Плохо !  Вынуждены убрать коня с USED_BOARD_CELLS={} y={} ", xPositions[horseIndex], yPositions[horseIndex]);
                    printState();

                    writeLock.lock();
                    try {
                        USED_BOARD_CELLS[xPositions[horseIndex]][yPositions[horseIndex]] = 0;
                    } finally {
                        writeLock.unlock();
                    }
                    //System.out.println("Плохо !   Вынуждены убрать коня "+ xPositions[horseIndex]+" "+yPositions[horseIndex] +" ход ");
                    xPositions[horseIndex] = 0;
                    yPositions[horseIndex] = 0;
                }
            }
        }

        depth--;

        return success;
    }



    public void printState() {

        System.out.println("Поток # "+ threadId);
        for (int x = 1; x <= BOARD_DIMENSION; x++) {
            for (int y = 1; y <= BOARD_DIMENSION; y++) {
                if (this.USED_BOARD_CELLS[x][y] > 0) {

                    System.out.print(this.USED_BOARD_CELLS[x][y]+" ");

                } else if (this.USED_BOARD_CELLS[x][y] < 0) {

                    System.out.print("B ");
                } else if (this.USED_BOARD_CELLS[x][y] == 0) {
                    System.out.print("0 ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }

    public void run() {

//		 try{
        tryHorse(2);

//		 }catch(Exception e) {}

    }



Без обид но код я не понял, те если за 5 минут код непонятен то нет желания долго с ним копаться.

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

Основной класс.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
package knight;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class Knight {

    public static int boardSize = 8;

    static final int [] X_STEPS = {1, 2, 2, 1, -1, -2, -2, -1};
    static final int [] Y_STEPS = {2, 1, -1, -2, -2, -1, 1, 2};

    public Set<Position> getReachableSet(Position pos, int numberofMoves) {
        return getReachableSet(pos, numberofMoves, null);
    }

    protected Set<Position> getReachableSet(Position pos, int numberofMoves, Set<Position> reachableSet) {
        if(reachableSet == null) {
            reachableSet = new HashSet<>();
        }

        if (!reachableSet.contains(pos)) reachableSet.add(pos);

        if (numberofMoves == 0) return reachableSet;

        ArrayList<Position> moves = new ArrayList<>();

        for (int i = 0; i < 8; i++) {
            Position candidate = new Position (pos.x + X_STEPS[i], pos.y + Y_STEPS[i]);

            if (!moveIsPossible(candidate)) continue;

            if (!reachableSet.contains(candidate)) {
                moves.add(candidate);
            }
        }

        for (int j = 0; j < moves.size(); j++) {
            reachableSet = getReachableSet(moves.get(j), numberofMoves-1, reachableSet);
        }

        return reachableSet;
    }

    private static boolean moveIsPossible (Position pos) {
        return (pos.x >= 0 && pos.x <= 7) && (pos.y >= 0 && pos.y <= 7);
    }
}



Позиция, можно использовать что то готовое из awt пакета, там вроде был подобный класс. Для учебного процесса лучше свое написать
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
package knight;


public class Position implements Comparable<Position> {
    /**
     * The row on the chess board
     */
    public int x;

    /**
     * The column on the chess board
     */
    public int y;

    /**
     * Create a new position object
     * @param x the row on the chess board
     * @param y the column on the chess board
     */
    public Position(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(Position o) {
        if(x == o.x) {
            return Integer.compare(y, o.y);
        } else {
            return Integer.compare(x, o.x);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Position position = (Position) o;

        if (x != position.x) return false;
        return y == position.y;

    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }

    @Override
    public String toString() {
        return "{" + x + ", " + y + "}";
    }
}



На десерт, тест класс. Нужно его доработать, убрать сортировку и сделать сравнение коллекций покультурнее, без печати в строку

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
package knight;


import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class KnightTests {

    Knight knight;

    @Before
    public void setup() {
        knight = new Knight();
    }

    private String printSet(Collection<Position> positions)
    {
        StringBuffer s = new StringBuffer("\n  ");
        for (int x=0; x<Knight.boardSize; x++) {
            s.append(x);
        }
        s.append("\n  ");
        for (int x=0; x<Knight.boardSize; x++) {
            s.append("-");
        }
        s.append("\n");

        for (int y=0; y<Knight.boardSize; y++) {
            s.append(y).append("|");
            for (int x=0; x<Knight.boardSize; x++) {
                if (positions.contains(new Position(x, y))) {
                    s.append("X");
                } else {
                    s.append(" ");
                }
            }
            s.append("\n");
        }
        return s.toString();
    }

    private void compare(Set<Position> result, int[]... expected) {
        List<Position> orderedPositions = new ArrayList<>(result);

        Collections.sort(orderedPositions);

        ArrayList<Position> expectedList = new ArrayList<>(expected.length);
        for (int[] pos : expected) {
            expectedList.add(new Position(pos[0], pos[1]));
        }
        Collections.sort(expectedList);

        Assert.assertEquals(printSet(orderedPositions), expectedList.toString(), orderedPositions.toString());
    }

    @Test
    public void noHop() {
        Set<Position> result = knight.getReachableSet(new Position(4, 4), 0);
        int expected[][] = { { 4, 4 } };
        compare(result, expected);
    }

    @Test
    public void oneHop() {
        Set<Position> result = knight.getReachableSet(new Position(4, 4), 1);
        int expected[][] = { {2, 3}, {2, 5}, {3, 2}, {3, 6}, {4, 4}, {5, 2}, {5, 6}, {6, 3}, {6, 5} };
        compare(result, expected);
    }

    @Test
    public void oneHopCorner() {
        Set<Position> result = knight.getReachableSet(new Position(0, 0), 1);
        int expected[][] = { { 0, 0 }, { 1, 2 }, { 2, 1 } };
        compare(result, expected);
    }

    @Test
    public void twoHopsCorner() {
        Set<Position> result = knight.getReachableSet(new Position(0, 0), 2);
        int expected[][] = { { 0, 0 }, { 0, 2 }, { 0, 4 }, { 1, 2 }, { 1, 3 },
                { 2, 0 }, { 2, 1 }, { 2, 4 }, { 3, 1 }, { 3, 3 }, { 4, 0 },
                { 4, 2 } };
        compare(result, expected);
    }

    @Test
    public void threeHops() {
        Set<Position> result = knight.getReachableSet(new Position(4, 4), 3);
        int expected[][] = {
                {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7},
                {4, 5}, {4, 4}, {4, 7}, {4, 6}, {5, 0}, {5, 1}, {5, 2}, {5, 3}, {5, 4},
                {1, 0}, {1, 3}, {1, 4}, {1, 1}, {1, 2}, {1, 7}, {1, 5}, {1, 6}, {5, 7},
                {5, 6}, {5, 5}, {6, 0}, {6, 1}, {6, 4}, {6, 5}, {6, 3}, {2, 1}, {2, 0},
                {2, 7}, {2, 3}, {2, 4}, {2, 5}, {6, 7}, {7, 3}, {7, 4}, {7, 5}, {7, 6},
                {7, 0}, {7, 1}, {7, 2}, {3, 0}, {3, 2}, {3, 1}, {3, 7}, {3, 5}, {3, 6},
                {3, 3}, {3, 4}, {7, 7}, {4, 3}, {4, 2}, {4, 1}, {4, 0}
        };
        compare(result, expected);
    }

    @Test
    public void fourHops() {
        Set<Position> result = knight.getReachableSet(new Position(4, 4), 4);
        int expected[][] = { {0, 0}, {0, 1}, {0, 2}, {0, 4}, {0, 6}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6},
                {1, 7}, {2, 0}, {2, 2}, {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {3, 1}, {3, 2}, {3, 3}, {3, 5}, {3, 6},
                {3, 7}, {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 5}, {4, 6}, {4, 7}, {5, 1}, {5, 2}, {5, 3}, {5, 4},
                {5, 5}, {5, 6}, {5, 7}, {6, 0}, {6, 2}, {6, 3}, {6, 4}, {6, 5}, {6, 6}, {6, 7}, {7, 1}, {7, 2}, {7, 3},
                {7, 5}, {7, 6}, {7, 7}
        };
        compare(result, expected);
    }
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369857
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uid uniqueНа десерт, тест класс. Нужно его доработать, убрать сортировку и сделать сравнение коллекций покультурнее, без печати в строку


что этот тест класс делает ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369865
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uid uniqueЕсли будете делать перебор в нескольких потоках



у меня складывается впечатление , что потоки тут не помощники.
помогло только Правило Варнсдорфа. находит множество решений (я правда не уверен , что все они уникальные, но это пустяк) причем с любых начальных точек . обычный перебор находил только для досок 6x6 и с начальной точки 1:1.
НО код вышел просто ужасный . Ужасней чем последний, что я выкладывал.
боюсь его показывать - запинаете )
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369867
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

даже не знаю стоит ли его прилизывать , чтобы выложить сюда . будет кто-нибудь читать разбираться - не знаю
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39369911
uid unique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81uid uniqueНа десерт, тест класс. Нужно его доработать, убрать сортировку и сделать сравнение коллекций покультурнее, без печати в строку


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

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

статья для начанающих
https://habrahabr.ru/post/169381/

Сайт http://junit.org/junit4/

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

Поставьте простой мавен проект и работайте в нем, будет проще прогонять тесты и тд
http://www.apache-maven.ru/
https://habrahabr.ru/post/77382/

Учитесь сразу делать правильно, нет ничего затратнее чем переучивание в будущем (двойная работа).
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370383
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonandron81зачем ? в чем выигрыш ?
Это мой старый добрый рефакторинг который я юзаю уже много лет.
В основном он эффективен в растровой графике. Задавать картинку
и работать с ней удобнее через int[] rgbColors чем через int[][] rgbColors.
Так скорость выше. Это я знаю еще со времен С++. В некоторых случаях
длину строки выравнивают на число байт кратных машинному WORD
процессора. Типа padding строки. Плюс есть еще много нюансов
связанных с тем как аллокатор int[][] размещает суб-массивы в куче.
При удачном стечении обстоятельств (обходим массив слева направо
и сверху вниз) канал памяти получает тразнакции чтения по линейным
адресам. Это благоприятный кейс. Но возможно будет и не-благоприятный.

Когда я задаю матрицу или куб (или гиперкуб) через линейный массив
то я сам вручную обеспечиваю линейный порядок доступа к элементам
памяти.

Некий господин выше не поленился и даже привел бенчмарк с использованием JMH
и с прогревом компиллятора как положено. Что-ж. Я не буду с ним спорить.
Мои последние бенчмарки я делал еще во время JDK6 а тогда
и деревья были выше и оптимизатор был попроще.

Возможно сейчас и нет острой необходимости выключать int[][] но я
лишний раз замечу что наша задача выгодно отличается от других.
У нас - квадратное поле (а не зубчатое) и ширина строки заведомо известна.



ну понял вас.
по самому алгоритму всё же неясность. Вы говорите , что как-то удавалось получать решения (видимо используя поточную технологию) . бродить по возможным ходам вы предлагаете случайно, а вот Варнсдорф предлагает брать сначала ветки с наименьшим кол-вом ходов и довольно успешный метод (проверял), в любом случае выходим на уровень выше в случае исчерпания.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370634
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81ну понял вас.
по самому алгоритму всё же неясность. Вы говорите , что как-то удавалось получать решения (видимо используя поточную технологию) . бродить по возможным ходам вы предлагаете случайно, а вот Варнсдорф предлагает брать сначала ветки с наименьшим кол-вом ходов и довольно успешный метод (проверял), в любом случае выходим на уровень выше в случае исчерпания.
Так. Стоп-машина. Давай вернемся в самое начало. Я не знаю алгоритма Варнсдорфа. Но мне это и не важно.
Я утверждаю. Что почти все (99.9%) алгоритмов поиска в шахматах можно запускать параллельно.
Отсюда мы имеем в нашем топике 4 возможных варианта реализации.

1. Обычный (он-же - "поиск в глубину")
2. Варнсдорф.
3. Обычный многопточный (при условии что все потоки старуют из одной точки A1)
4. Варнсдорф многопоточный (при условии что все потоки старуют из одной точки A1)

Ты согласен этим?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370691
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonandron81ну понял вас.
по самому алгоритму всё же неясность. Вы говорите , что как-то удавалось получать решения (видимо используя поточную технологию) . бродить по возможным ходам вы предлагаете случайно, а вот Варнсдорф предлагает брать сначала ветки с наименьшим кол-вом ходов и довольно успешный метод (проверял), в любом случае выходим на уровень выше в случае исчерпания.
Так. Стоп-машина. Давай вернемся в самое начало. Я не знаю алгоритма Варнсдорфа. Но мне это и не важно.
Я утверждаю. Что почти все (99.9%) алгоритмов поиска в шахматах можно запускать параллельно.
Отсюда мы имеем в нашем топике 4 возможных варианта реализации.

1. Обычный (он-же - "поиск в глубину")
2. Варнсдорф.
3. Обычный многопточный (при условии что все потоки старуют из одной точки A1)
4. Варнсдорф многопоточный (при условии что все потоки старуют из одной точки A1)

Ты согласен этим?

согласен.
1. - работает крайне очень медленно. терпения дождаться хотя бы одного решения не хватает.
2. - вышло .
3. - вот этот хочу реализовать.
Вы тут предлагаете поиск в глубину используя потоки ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370698
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

тогда как будем строить алгоритм ?
допустим у нас 8 потоков в каждом свой массив с полем - x[].
предположим мы находимся в одной из вершин как Вы предлагаете будем двигаться от ветки к ветке ? Выше обсуждалось , что будем случайно выбирать по какой ветке двигаться .
На уровень выше переходим только в случае исчерпания веток куда можно ступить или же плюс к этому на уровень выше делаем тоже как возможный 9-ый ход кот тоже может выбраться случайно ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370749
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron813. - вот этот хочу реализовать.
Вы тут предлагаете поиск в глубину используя потоки ?
Я предлагаю еще раз описать условие задачи (новое условие). Потому-как я и другие мемберы не понимают
конечную цель.

Типа:
Код: java
1.
2.
3.
4.
5.
Реализовать мультипоточный алгоритм Варнсдорфа. Исходные данные. N - количество потоков,
M - минимальное число маршрутов коня которые нужно найти. Стартовая координата - A1 
для всех маршрутов.

M,N - заданы в виде аргументов командной строки.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39370775
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

ок.
Но оставим Варнсдорфа в покое. так как в общем случае мы этого правила не знаем. и им вышло, а мне этого мало.

Формулирую.

Реализовать мультипоточный (4 - потока = const) алгоритм методом обхода в глубину .
Исходные данные:
4 потока(константа) - задано жестко в программе.
M - минимальное число маршрутов коня которые нужно найти.
i,j - стартовая точка.

M,i,j - задаются в виде аргументов командной строки.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371078
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81, надо написать полное условие задачи в т ч что речь идёт о шахматном коне
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371154
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,


Требуется реализовать задачу обхода шахматного коня всей шахматной доски 8x8 из клетки (i,j) так, чтобы в каждой клетке он побывал ровно по одному разу.
Способ реализации мультипоточный (4 - потока = const) алгоритм методом обхода в глубину .
Исходные данные:
4 потока(константа) - задано жестко в программе.
M - минимальное число маршрутов коня которые нужно найти.
i,j - стартовая точка.

M,i,j - задаются в виде аргументов командной строки.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371318
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ок нормально.

Я б предложил стартануть с нового топика а этот попросить модера закрыть.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371405
rema174
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
оффтоп: да, это в традициях этого форума - через шесть страниц сформулировать, что-же все-таки требуется. шесть страниц коту под хвост...
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371407
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rema174,

в мой огород камень или нет ? )))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371408
rema174
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andron81,

я ж говорю - оффтоп ))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371413
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rema174andron81,

я ж говорю - оффтоп ))


ну по сути я давно получил ответ на свой вопрос (см. тему).
возможно надо было раньше закончить и открыть новую.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39371429
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Расслабтесь. Ветка живет своей жизнью отдельно от автора. Это нормально.

Андрон. Стартуй новую.
...
Рейтинг: 0 / 0
132 сообщений из 132, показаны все 6 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / рекурсивная функция делает переполнение кучи.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]