<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Нахождения кратчайшего пути]]></title>
		<link>http://forum.script-coding.com/viewtopic.php?id=11560</link>
		<atom:link href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=11560&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Нахождения кратчайшего пути».]]></description>
		<lastBuildDate>Tue, 17 May 2016 16:52:55 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103882#p103882</link>
			<description><![CDATA[<p>Вот ещё быстрее и проще.</p><p>Сравнение на вычислениях более 2 секунд.<br /></p><div class="codebox"><pre><code>
#SingleInstance Force
#NoEnv

 
SetBatchLines, -1
length := 2000
MaxLinks := 111

start:
Map := CreateMap(length, MaxLinks)
p := GetRandomNumbers(length, 2)

start := A_TickCount
text1 := GetWaysText(GetShortWays(Map, p[1], p[2]))
time1 := A_TickCount - start
RegExReplace(text1, &quot;m`a)$&quot;, &quot;&quot;, Count1)
SoundBeep
if !(time1 &gt; 2000)
	goto start
SoundBeep
start := A_TickCount
text2 := AllShortPath(p[1], p[2], Map, 1)
time2 := A_TickCount - start
RegExReplace(text2, &quot;m`a)$&quot;, &quot;&quot;, Count2)

MsgBox, % &quot;teadrinker:`nTime = &quot; time1 &quot;`nCount = &quot; Count1 &quot;`n`n&quot; text1 &quot;`n`nserzh82saratov:`nTime = &quot; time2 &quot;`nCount = &quot; Count2 &quot;`n`n&quot; text2
Return

GetShortWays(points, start, end)
{
	max := 4
	Loop  {
		if !IsObject(jumps := GetJumps(points, start, end, [start]))
			Return [[start, end]]
		ways := [], CurrentNode := {way: [start], jumps: jumps, PrevNode: &quot;&quot;}, max *= 2
		while CurrentNode  {
			m := ways.1.MaxIndex(), c := CurrentNode.way.MaxIndex()
			if ( c + 1 = m || c &gt; max || !(NextPoint := CurrentNode.jumps.Pop()) )  {
				CurrentNode := CurrentNode.PrevNode
				continue
			}
			way := CurrentNode.way.Clone()
			if jumps := GetJumps(points, NextPoint, end, way)  {
				if IsObject(jumps) &amp;&amp; way.Push(NextPoint)
					CurrentNode := {way: way, jumps: jumps, PrevNode: CurrentNode}
				else
					way.Push(NextPoint, jumps), (way.MaxIndex() &lt; m &amp;&amp; ways := []), ways.Push(way)
			}
		}
	} until ways.1.1 || max &gt; points.MaxIndex()
	Return ways
}
	
GetJumps(points, p, end, way)
{
	jumps := []
	for k, v in points[p]  {
		if (v = end)
			Return v
		
		for i, c in way
			if (v = c)
				continue 2
		
		jumps.Push(v)
	}
	Return jumps
}

GetWaysText(ways)
{
	for k, v in ways  {
		text .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
		for k, v in v
			text .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	}
	Return text
}

;***********************************************************************************************************

AllShortPath(From, To, Map, RetText = 0) {
	Bridge := [[From]], Find := [], Exist := []
	While !Find.MaxIndex() &amp;&amp; Bridge.MaxIndex() {
		For k, v in Bridge
			Exist[v[v.MaxIndex()]] := 1
		For k, b in Bridge.Clone(), Bridge := []
			For k, p in Map[b[b.MaxIndex()]]
				If !Exist[p] &amp;&amp; (a := b.Clone(), a.Push(p))
					If (p = To &amp;&amp; Find.Push(a)) || !Bridge.Push(a)
						Break
	} If RetText
		For k, v in Find
			For k, v in v, Find .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
				Find .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Find
}

;********************************************************************************************************************

CreateMap(len, max)
{
	arr := []
	Loop % len
		arr[A_Index] := []
	IndexArr := []
	Loop % len
		IndexArr[A_Index] := A_Index
	
	Loop % len  {
		i := A_Index
		m := arr[i].MaxIndex(), (!m &amp;&amp; m := 0)
		rest := max - m
		if (rest = 0)
			continue
		
		WithoutCurrent := IndexArr.Clone()
		RemoveFromIdx(i, WithoutCurrent)
		
		Random, rand, 1, rest
		for k, v in keys := GetRandomNumbers(WithoutCurrent.MaxIndex(), rand)  {
			idx := WithoutCurrent[v]
			arr[idx].Push(i)
			( arr[idx].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(idx, IndexArr) )
			arr[i].Push(idx)
		}
		( arr[i].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(i, IndexArr) )
	}
	Return arr
}

RemoveFromIdx(n, arr)
{
	for k, v in arr
		if (v = n)
			break
	arr.RemoveAt(k)
}

GetRandomNumbers(len, num)
{
	arr := []
	Loop % len
		arr[A_Index] := A_Index
	RetArr := []
	Loop % num  {
		Random, rand, 1, arr.MaxIndex()
		RetArr.Push(arr.RemoveAt(rand))
	}
	Return RetArr
} 
</code></pre></div><p>Функция.<br /></p><div class="codebox"><pre><code>AllShortPath(From, To, Map, RetText = 0) {
	Bridge := [[From]], Find := [], Exist := []
	While !Find.MaxIndex() &amp;&amp; Bridge.MaxIndex() {
		For k, v in Bridge
			Exist[v[v.MaxIndex()]] := 1
		For k, b in Bridge.Clone(), Bridge := []
			For k, p in Map[b[b.MaxIndex()]]
				If !Exist[p] &amp;&amp; (a := b.Clone(), a.Push(p))
					If (p = To &amp;&amp; Find.Push(a)) || !Bridge.Push(a)
						Break
	} If RetText
		For k, v in Find
			For k, v in v, Find .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
				Find .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Find
}</code></pre></div><p>Или вариант пошустрее, если нужен только один путь.<br /></p><div class="codebox"><pre><code>ShortPath(From, To, Map, RetText = 0) {
	Bridge := [[From]], Exist := [], Exist[From] := 1
	While Bridge.MaxIndex()
		For k, b in Bridge.Clone(), Bridge := [] 
			For k, p in Map[b[b.MaxIndex()]]
				If !Exist[p] &amp;&amp; (a := b.Clone(), a.Push(p))
					If (p = To &amp;&amp; Find := a) || !(Bridge.Push(a) &amp;&amp; Exist[p] := 1)
						Break 3
	If RetText
		For k, v in Find
			Find .= (k = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Find
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Tue, 17 May 2016 16:52:55 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103882#p103882</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103813#p103813</link>
			<description><![CDATA[<p>Понял теперь, тоже думал про такой же вариант но почему то решил что разницы не будет, а оно вон как. <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sun, 15 May 2016 19:25:46 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103813#p103813</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103811#p103811</link>
			<description><![CDATA[<p>Я твой не разбирал. А у меня небольшой хак применён. Вначале ищутся короткие пути, если путь длиннее определённого значения, он бросается и ищется новый. Если ничего не найдено, значение увеличивается вдвое.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sun, 15 May 2016 19:21:28 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103811#p103811</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103790#p103790</link>
			<description><![CDATA[<div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>Можно посоревноваться:</p></blockquote></div><p>Да результаты впечатляют, было даже 250 против моих 16000. Так и не осилил, в чём заключается принципиальная разница?</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sun, 15 May 2016 08:43:50 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103790#p103790</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103631#p103631</link>
			<description><![CDATA[<p>У меня пока так вышло:<br /></p><div class="codebox"><pre><code>Points := { 1: [9,10], 2: [3,9], 3: [2,8], 4: [5,8,16], 5: [4,7,12], 6: [7,20], 7: [5,6], 8: [3,4,14,20], 9: [1,2,10,12,14], 10: [1,9,11], 11: [10,12]
			, 12: [5,9,11,13], 13: [12,14,15], 14: [8,9,13,15], 15: [13,14,16], 16: [4,15,17,20], 17: [16,18], 18: [17,19], 19: [18,20], 20: [6,8,16,19] }
			
ways := GetShortWays(Points, 11, 20)

for k, v in ways  {
	text .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
	for k, v in v
		text .= (A_Index = 1 ? &quot;&quot; : &quot; —&gt; &quot;) . v
}
MsgBox, % text

GetShortWays(points, start, end)
{
	max := 4
	Loop  {
		if !IsObject(jumps := GetJumps(points, start, end, [start]))
			Return [[start, end]]
		ways := [], CurrentNode := {way: [start], jumps: jumps, PrevNode: &quot;&quot;}, max *= 2
		while CurrentNode  {
			m := ways.1.MaxIndex(), c := CurrentNode.way.MaxIndex()
			if ( c + 1 = m || c &gt; max || !(NextPoint := CurrentNode.jumps.Pop()) )  {
				CurrentNode := CurrentNode.PrevNode
				continue
			}
			way := CurrentNode.way.Clone()
			if jumps := GetJumps(points, NextPoint, end, way)  {
				if IsObject(jumps) &amp;&amp; way.Push(NextPoint)
					CurrentNode := {way: way, jumps: jumps, PrevNode: CurrentNode}
				else
					way.Push(NextPoint, jumps), (way.MaxIndex() &lt; m &amp;&amp; ways := []), ways.Push(way)
			}
		}
	} until ways.1.1 || max &gt; points.MaxIndex()
	Return ways
}
	
GetJumps(points, p, end, way)
{
	jumps := []
	for k, v in points[p]  {
		if (v = end)
			Return v
		
		for i, c in way
			if (v = c)
				continue 2
		
		jumps.Push(v)
	}
	Return jumps
}</code></pre></div><p>Можно посоревноваться:<br /></p><div class="codebox"><pre><code>SetBatchLines, -1
length := 1000
MaxLinks := 5

Map := CreateMap(length, MaxLinks)
p := GetRandomNumbers(length, 2)

start := A_TickCount
text1 := GetWaysText(GetShortWays(Map, p[1], p[2]))
time1 := A_TickCount - start
SoundBeep
start := A_TickCount
text2 := ShortPath(p[1], p[2], Map, 1)
time2 := A_TickCount - start

MsgBox, % &quot;teadrinker:`n`nTime = &quot; time1 &quot;`n&quot; text1 &quot;`n`nserzh82saratov:`n`nTime = &quot; time2 &quot;`n&quot; text2

GetShortWays(points, start, end)
{
	max := 4
	Loop  {
		if !IsObject(jumps := GetJumps(points, start, end, [start]))
			Return [[start, end]]
		ways := [], CurrentNode := {way: [start], jumps: jumps, PrevNode: &quot;&quot;}, max *= 2
		while CurrentNode  {
			m := ways.1.MaxIndex(), c := CurrentNode.way.MaxIndex()
			if ( c + 1 = m || c &gt; max || !(NextPoint := CurrentNode.jumps.Pop()) )  {
				CurrentNode := CurrentNode.PrevNode
				continue
			}
			way := CurrentNode.way.Clone()
			if jumps := GetJumps(points, NextPoint, end, way)  {
				if IsObject(jumps) &amp;&amp; way.Push(NextPoint)
					CurrentNode := {way: way, jumps: jumps, PrevNode: CurrentNode}
				else
					way.Push(NextPoint, jumps), (way.MaxIndex() &lt; m &amp;&amp; ways := []), ways.Push(way)
			}
		}
	} until ways.1.1 || max &gt; points.MaxIndex()
	Return ways
}
	
GetJumps(points, p, end, way)
{
	jumps := []
	for k, v in points[p]  {
		if (v = end)
			Return v
		
		for i, c in way
			if (v = c)
				continue 2
		
		jumps.Push(v)
	}
	Return jumps
}

GetWaysText(ways)
{
	for k, v in ways  {
		text .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
		for k, v in v
			text .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	}
	Return text
}

;***********************************************************************************************************

ShortPath(From, To, Map, RetText = 0) {
	Bridge := [From], Index := [1], Exist := [], Finds := []
	Loop
	{
		M := Bridge.MaxIndex(), B := Bridge[M], I := Index[M], N := Map[b][i], Exist[b] := 1
		If (M = 1 &amp;&amp; !N)
			Break
		If (!N || Min &amp;&amp; M &gt; Min)
		{
			Exist[Bridge.Pop()] := 0, Index.Pop(), ++Index[Bridge.MaxIndex()]
			Continue
		}
		 ; If (I = 1 &amp;&amp; (From = To ? M &gt; 2 : 1))  ; для кольцевых маршрутов
		If (I = 1) 
			For k, v in Map[b]
				If (v = To)
				{  
					Find := Bridge.Clone(), Find.Push(To), Finds.Push(Find), Min := M 
					If (M = 1)
						Break 2
					Exist[Bridge.Pop()] := 0, Index.Pop(), ++Index[Bridge.MaxIndex()]
					Continue 2
				}
		If Exist[N]
			++Index[M]
		Else
			Bridge.Push(N), Index.Push(1)
	}
	For k, v in Finds, Ret := []
		v.MaxIndex() = Min + 1 ? Ret.Push(v) : 0
	If RetText
		For k, v in Ret 
			For k, v in v, Ret .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
				Ret .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Ret 
}

;********************************************************************************************************************

CreateMap(len, max)
{
	arr := []
	Loop % len
		arr[A_Index] := []
	IndexArr := []
	Loop % len
		IndexArr[A_Index] := A_Index
	
	Loop % len  {
		i := A_Index
		m := arr[i].MaxIndex(), (!m &amp;&amp; m := 0)
		rest := max - m
		if (rest = 0)
			continue
		
		WithoutCurrent := IndexArr.Clone()
		RemoveFromIdx(i, WithoutCurrent)
		
		Random, rand, 1, rest
		for k, v in keys := GetRandomNumbers(WithoutCurrent.MaxIndex(), rand)  {
			idx := WithoutCurrent[v]
			arr[idx].Push(i)
			( arr[idx].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(idx, IndexArr) )
			arr[i].Push(idx)
		}
		( arr[i].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(i, IndexArr) )
	}
	Return arr
}

RemoveFromIdx(n, arr)
{
	for k, v in arr
		if (v = n)
			break
	arr.RemoveAt(k)
}

GetRandomNumbers(len, num)
{
	arr := []
	Loop % len
		arr[A_Index] := A_Index
	RetArr := []
	Loop % num  {
		Random, rand, 1, arr.MaxIndex()
		RetArr.Push(arr.RemoveAt(rand))
	}
	Return RetArr
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 11 May 2016 06:17:24 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103631#p103631</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103562#p103562</link>
			<description><![CDATA[<p>А у меня пока не было времени, завтра тоже попробую.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Mon, 09 May 2016 12:51:20 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103562#p103562</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103557#p103557</link>
			<description><![CDATA[<div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>Но если точек больше, иногда крашится. Похоже, по-хорошему надо заменять рекурсию на цикл.</p></blockquote></div><p>Вроде так, проверил на больших значениях. Постарался максимально оптимизировать, перебора всех возможных путей нет, как в прошлом варианте. Возвращает один путь (первый найденный с минимальными номерами точек), это заметно ускоряет вычисления.<br />Результат можно вернуть в виде текста а не массива, указав 4 параметр в true. <br /></p><div class="codebox"><pre><code>
Map := { 1: [9,10], 2: [3,9], 3: [2,8], 4: [5,8,16], 5: [4,7,12], 6: [7,20], 7: [5,6], 8: [3,4,14,20], 9: [1,2,10,12,14], 10: [1,9,11], 11: [10,12]
		, 12: [5,9,11,13], 13: [12,14,15], 14: [8,9,13,15], 15: [13,14,16], 16: [4,15,17,20], 17: [16,18], 18: [17,19], 19: [18,20], 20: [6,8,16,19] }

From := 1
To := 19
MsgBox % ShortPath(From, To, Map, 1) 
Return

ShortPath(From, To, Map, RetText = 0) {
	Bridge := [From], Index := [1], Exist := []
	Loop
	{
		M := Bridge.MaxIndex(), B := Bridge[M], I := Index[M], N := Map[b][i], Exist[b] := 1
		If (M = 1 &amp;&amp; !N)
			Break
		If (!N || Min &amp;&amp; M &gt;= Min)
		{
			Exist[Bridge.Pop()] := 0, Index.Pop(), ++Index[Bridge.MaxIndex()]
			Continue
		}
 		; If (I = 1 &amp;&amp; (From = To ? M &gt; 2 : 1))  ; для кольцевых маршрутов
		If (I = 1) 
			For k, v in Map[b]
				If (v = To)
				{ 
					Finds := Bridge.Clone(), Finds.Push(To), Min := M
					If (M &lt; 3)
						Break 2
					Exist[Bridge.Pop()] := 0, Exist[Bridge.Pop()] := 0
					Index.Pop(), Index.Pop(), ++Index[Bridge.MaxIndex()]
					Continue 2
				}
		If Exist[N]
			++Index[M]
		Else
			Bridge.Push(N), Index.Push(1)
	}
	If RetText
		For k, v in Finds
			Finds .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Finds 
}
</code></pre></div><p>Вариант под спойлером возвращает все короткие пути, но само собой на больших картах будет искать заметно дольше.<br /></p><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><div class="codebox"><pre><code>
Map := { 1: [9,10], 2: [3,9], 3: [2,8], 4: [5,8,16], 5: [4,7,12], 6: [7,20], 7: [5,6], 8: [3,4,14,20], 9: [1,2,10,12,14], 10: [1,9,11], 11: [10,12]
		, 12: [5,9,11,13], 13: [12,14,15], 14: [8,9,13,15], 15: [13,14,16], 16: [4,15,17,20], 17: [16,18], 18: [17,19], 19: [18,20], 20: [6,8,16,19] }

From := 2
To := 13 

MsgBox % ShortPath(From, To, Map, 1) 
Return


ShortPath(From, To, Map, RetText = 0) {
	Bridge := [From], Index := [1], Exist := [], Finds := []
	Loop
	{
		M := Bridge.MaxIndex(), B := Bridge[M], I := Index[M], N := Map[b][i], Exist[b] := 1
		If (M = 1 &amp;&amp; !N)
			Break
		If (!N || Min &amp;&amp; M &gt; Min)
		{
			Exist[Bridge.Pop()] := 0, Index.Pop(), ++Index[Bridge.MaxIndex()]
			Continue
		}
		 ; If (I = 1 &amp;&amp; (From = To ? M &gt; 2 : 1))  ; для кольцевых маршрутов
		If (I = 1) 
			For k, v in Map[b]
				If (v = To)
				{  
					Find := Bridge.Clone(), Find.Push(To), Finds.Push(Find), Min := M 
					If (M = 1)
						Break 2
					Exist[Bridge.Pop()] := 0, Index.Pop(), ++Index[Bridge.MaxIndex()]
					Continue 2
				}
		If Exist[N]
			++Index[M]
		Else
			Bridge.Push(N), Index.Push(1)
	}
	For k, v in Finds, Ret := []
		v.MaxIndex() = Min + 1 ? Ret.Push(v) : 0
	If RetText
		For k, v in Ret 
			For k, v in v, Ret .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
				Ret .= (A_Index = 1 ? &quot;&quot; : &quot;, &quot;) . v
	Return Ret 
}
</code></pre></div></div></div>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Mon, 09 May 2016 11:38:05 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103557#p103557</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103468#p103468</link>
			<description><![CDATA[<p>Ясно. Я с уходом в даун разобрался, но пути теперь возвращает не оптимальные, буду думать. А так, спасибо.</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sat, 07 May 2016 22:31:29 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103468#p103468</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103467#p103467</link>
			<description><![CDATA[<p>Нет, не должно помочь, это для переменных, но не для стека.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 07 May 2016 22:28:41 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103467#p103467</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103466#p103466</link>
			<description><![CDATA[<div class="quotebox"><cite>wikipedia пишет:</cite><blockquote><p>Эта ошибка случается по трём причинам.</p></blockquote></div><p>Тут не осилил, может #MaxMem?</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sat, 07 May 2016 22:27:31 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103466#p103466</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103465#p103465</link>
			<description><![CDATA[<p>При рекурсивном вызове функции может случиться <a href="https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81%D1%82%D0%B5%D0%BA%D0%B0">переполнение стека</a>. При циклическом решении подобных задач тоже может случиться переполнение памяти, но запас в этом случае больше.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 07 May 2016 22:25:19 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103465#p103465</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103464#p103464</link>
			<description><![CDATA[<div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>Похоже, по-хорошему надо заменять рекурсию на цикл.</p></blockquote></div><p>Так и знал что теперь спрошу, а в чём отличие по твоему?</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sat, 07 May 2016 22:15:08 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103464#p103464</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103461#p103461</link>
			<description><![CDATA[<p>Вот, собственно, виртуальная карта точек длиной <em>length</em> и количеством связей между точками от 1 до <em>MaxLinks</em>:<br /></p><div class="codebox"><pre><code>Map := CreateMap(length, MaxLinks)

CreateMap(len, max)
{
	arr := []
	Loop % len
		arr[A_Index] := []
	IndexArr := []
	Loop % len
		IndexArr[A_Index] := A_Index
	
	Loop % len  {
		i := A_Index
		m := arr[i].MaxIndex(), (!m &amp;&amp; m := 0)
		rest := max - m
		if (rest = 0)
			continue
		
		WithoutCurrent := IndexArr.Clone()
		RemoveFromIdx(i, WithoutCurrent)
		
		Random, rand, 1, rest
		for k, v in keys := GetRandomNumbers(WithoutCurrent.MaxIndex(), rand)  {
			idx := WithoutCurrent[v]
			arr[idx].Push(i)
			( arr[idx].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(idx, IndexArr) )
			arr[i].Push(idx)
		}
		( arr[i].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(i, IndexArr) )
	}
	Return arr
}

RemoveFromIdx(n, arr)
{
	for k, v in arr
		if (v = n)
			break
	arr.RemoveAt(k)
}

GetRandomNumbers(len, num)
{
	arr := []
	Loop % len
		arr[A_Index] := A_Index
	RetArr := []
	Loop % num  {
		Random, rand, 1, arr.MaxIndex()
		RetArr.Push(arr.RemoveAt(rand))
	}
	Return RetArr
}</code></pre></div><p>Я слегка <a href="http://forum.script-coding.com/viewtopic.php?pid=103385#p103385">оптимизировал</a> свой вариант, он легко справляется с массивом в 400 точек с количеством связей от 1 до 5:<br /></p><div class="codebox"><pre><code>SetBatchLines, -1
length := 400
MaxLinks := 5

Map := CreateMap(length, MaxLinks)
p := GetRandomNumbers(length, 2)

PointsObj := new ShortWay(Map)
ways := PointsObj.GetShortWays(p[1], p[2])

for k, v in ways  {
	text .= A_Index = 1 ? &quot;&quot; : &quot;`n&quot;
	for k, v in v
		text .= (A_Index = 1 ? &quot;&quot; : &quot; —&gt; &quot;) . v
}
MsgBox, % text

CreateMap(len, max)
{
	arr := []
	Loop % len
		arr[A_Index] := []
	IndexArr := []
	Loop % len
		IndexArr[A_Index] := A_Index
	
	Loop % len  {
		i := A_Index
		m := arr[i].MaxIndex(), (!m &amp;&amp; m := 0)
		rest := max - m
		if (rest = 0)
			continue
		
		WithoutCurrent := IndexArr.Clone()
		RemoveFromIdx(i, WithoutCurrent)
		
		Random, rand, 1, rest
		for k, v in keys := GetRandomNumbers(WithoutCurrent.MaxIndex(), rand)  {
			idx := WithoutCurrent[v]
			arr[idx].Push(i)
			( arr[idx].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(idx, IndexArr) )
			arr[i].Push(idx)
		}
		( arr[i].MaxIndex() &gt;= max &amp;&amp; RemoveFromIdx(i, IndexArr) )
	}
	Return arr
}

RemoveFromIdx(n, arr)
{
	for k, v in arr
		if (v = n)
			break
	arr.RemoveAt(k)
}

GetRandomNumbers(len, num)
{
	arr := []
	Loop % len
		arr[A_Index] := A_Index
	RetArr := []
	Loop % num  {
		Random, rand, 1, arr.MaxIndex()
		RetArr.Push(arr.RemoveAt(rand))
	}
	Return RetArr
}

class ShortWay
{
	__New(points)  {
		this.points := points
		this.ways := []
	}
	GetShortWays(start, end)  {
		this.SearchWays(start, end, [start])
		Return this.ways
	}
	SearchWays(p1, p2, way = &quot;&quot;, prev = &quot;&quot;)  {
		m := this.ways.1.MaxIndex()
		if ( (m &amp;&amp; (way.MaxIndex() &gt; m - 1)) || !(jumps := this.GetJumps(p1, prev, p2, way)) )
			Return
		
		if !IsObject(jumps)  {
			way.Push(jumps)
			( m &amp;&amp; way.MaxIndex() &lt; m &amp;&amp; this.ways := [] )
			this.ways.Push(way)
			Return
		}
		for k, v in jumps
			node := way.Clone(), node.Push(v), this.SearchWays(v, p2, node, p1)
	}
	GetJumps(p, prev, end, way)  {
		jumps := []
		for k, v in this.points[p]  {
			if (v = end)
				Return v
			
			for i, c in way
				if (v = c)
					continue 2
			
			( this.points[v].MaxIndex() &gt; 1 &amp;&amp; v != prev &amp;&amp; jumps.Push(v) )
		}
		Return jumps
	}
}</code></pre></div><p>Но если точек больше, иногда крашится. Похоже, по-хорошему надо заменять рекурсию на цикл.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 07 May 2016 21:47:29 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103461#p103461</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103440#p103440</link>
			<description><![CDATA[<p>С 1,9 — работает, с 1, 2 — нет, зацикливается.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 07 May 2016 11:47:25 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103440#p103440</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Нахождения кратчайшего пути]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=103438#p103438</link>
			<description><![CDATA[<p>С любыми точками не работает?</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sat, 07 May 2016 11:43:39 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=103438#p103438</guid>
		</item>
	</channel>
</rss>
