You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.7 KiB
112 lines
2.7 KiB
"use strict"; |
|
|
|
function main() { |
|
let result = document.getElementById("result"); |
|
|
|
let arr = document.forms[0].elements[0].value; |
|
arr = arr.trim().split(" "); |
|
let checkResult = arr.some( elem => isNotNumber(elem) ); |
|
if (checkResult) { |
|
result.innerHTML = "<p class='fail'>Ошибка: введите только целые числа, разделенные пробелом!</p>"; |
|
return; |
|
} else if (arr.length < 2) { |
|
result.innerHTML = "<p class='fail'>Ошибка: введите минимум 2 числа!</p>"; |
|
return; |
|
} else { |
|
arr = arr.map( elem => Number(elem) ); |
|
} |
|
|
|
let graph = createGraph(arr); |
|
let path = findPath(graph); |
|
|
|
if (path == undefined) { |
|
result.innerHTML = "<p class='fail'>Результат: путь не найден!</p>"; |
|
return; |
|
} |
|
|
|
arr[0] = "Start"; |
|
arr[arr.length - 1] = "End"; |
|
|
|
let table = "<table id='table'><tr><th>Метка</th><th>Номер прыжка</th></tr>"; |
|
arr.forEach( elem => table += "<tr><td>" + elem + "</td><td></td></tr>" ); |
|
table += "</table>"; |
|
|
|
result.innerHTML = "<p class='success'>Результат: путь найден! Прыжков в пути: " + (path.length - 1) + "</p>" + table; |
|
|
|
path.forEach( (elem, index) => |
|
document.getElementById("table").rows[elem + 1].cells[1].innerHTML = index |
|
); |
|
|
|
} |
|
|
|
function createGraph(arr) { |
|
let result = []; |
|
|
|
// Добавляем узлы берегов |
|
arr.unshift(1); |
|
arr.push(0); |
|
|
|
length = arr.length; |
|
arr.forEach( (elem, index) => { |
|
result[index] = { |
|
prev: undefined, |
|
dist: Number.POSITIVE_INFINITY, |
|
visited: false, |
|
childs: [] |
|
}; |
|
|
|
if (elem <= index) { |
|
result[index].childs.push(index - elem); |
|
} |
|
|
|
let forwardIndex = elem >= (length - index) ? length - 1 : index + elem; |
|
result[index].childs.push(forwardIndex); |
|
}); |
|
|
|
return result; |
|
} |
|
|
|
function findPath(graph) { |
|
|
|
let queue = []; |
|
|
|
queue.push(0); |
|
graph[0].dist = 0; |
|
|
|
mainLoop: while(queue.length > 0) { |
|
let v = queue.shift() |
|
for (let child of graph[v].childs) { |
|
if (!graph[child].visited) { |
|
queue.push(child) |
|
graph[v].visited = true; |
|
|
|
let dist = graph[v].dist + 1; |
|
if ( dist < graph[child].dist ) { |
|
graph[child].prev = v; |
|
graph[child].dist = dist; |
|
} |
|
|
|
if (child == graph.length - 1) { |
|
break mainLoop; |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (graph[graph.length - 1].dist == Number.POSITIVE_INFINITY) { |
|
return undefined; |
|
} |
|
|
|
let path = []; |
|
let index = graph.length - 1; |
|
while (index >= 0) { |
|
path.push(index); |
|
index = graph[index].prev; |
|
} |
|
|
|
return path.reverse(); |
|
} |
|
|
|
function isNotNumber(val) { |
|
return val.replace(/\s/g, '').length === 0 || isNaN(val) || !Number.isInteger(Number(val)); |
|
}
|
|
|