<?php
/* http://d...content-available-to-author-only...2.net/ */
define ( 'SUBWAY' , "едешь на метро" ) ; define ( 'FOOT' , "идешь пешком" ) ; define ( 'BUS' , "едешь на автобусе" ) ;
/* Чтобы не писать много раз array('time' => ..., 'by' => ...), используем функцию.
«canGet» переводится как «можно попасть» */
function canGet( $time , $byWhat ) {
return array ( 'time' => $time , 'by' => $byWhat ) ; }
P_PET => 'ст. м. Петроградская' ,
P_CHK => 'ст. м. Чкаловская' ,
P_GOR => 'ст. м. Горьковская' ,
P_SPO => 'ст. м. Спортивная' ,
P_VAS => 'ст. м. Василеостровская' ,
P_KRE => 'Петропавловская крепость' ,
P_LET => 'Летний сад' ,
P_DVO => 'Дворцовая площадь' ,
P_ISA => 'Исакиевский собор' ,
P_NOV => 'Новая Голландия' ,
P_RAS => 'Дом Раскольникова' ,
P_GOS => 'Гостиный Двор' ,
P_SEN => 'Сенная Площадь' ,
P_VLA => 'ст. м. Владимирская' ,
P_VIT => 'Витебский вокзал' ,
P_TEH => 'Технологический Институт'
) ;
P_CHK => canGet( 10 , BUS) ,
P_GOR => canGet( 3 , SUBWAY)
) ,
P_PET => canGet( 10 , BUS) ,
P_SPO => canGet( 3 , SUBWAY)
) ,
P_PET => canGet( 3 , BUS) ,
P_KRE => canGet( 5 , FOOT) ,
P_GOS => canGet( 6 , SUBWAY)
) ,
P_CHK => canGet( 3 , SUBWAY) ,
P_VAS => canGet( 10 , BUS) ,
P_SEN => canGet( 7 , SUBWAY)
) ,
P_SPO => canGet( 10 , BUS) ,
P_GOS => canGet( 7 , SUBWAY) ,
P_NOV => canGet( 11 , FOOT)
) ,
P_GOR => canGet( 5 , FOOT)
) ,
P_DVO => canGet( 6 , FOOT) ,
P_GOS => canGet( 7 , FOOT)
) ,
P_ISA => canGet( 6 , FOOT) ,
P_GOS => canGet( 6 , FOOT) ,
P_LET => canGet( 6 , FOOT)
) ,
P_DVO => canGet( 6 , FOOT) ,
P_NOV => canGet( 5 , FOOT)
) ,
P_VAS => canGet( 11 , FOOT) ,
P_ISA => canGet( 5 , FOOT) ,
P_RAS => canGet( 7 , BUS)
) ,
P_NOV => canGet( 7 , BUS) ,
P_SEN => canGet( 3 , FOOT)
) ,
P_VAS => canGet( 7 , SUBWAY) ,
P_SEN => canGet( 3 , SUBWAY) ,
P_DVO => canGet( 6 , FOOT) ,
P_GOR => canGet( 6 , SUBWAY) ,
P_LET => canGet( 7 , FOOT) ,
P_VLA => canGet( 7 , FOOT)
) ,
P_RAS => canGet( 3 , FOOT) ,
P_SPO => canGet( 7 , SUBWAY) ,
P_GOS => canGet( 3 , SUBWAY) ,
P_VLA => canGet( 4 , SUBWAY) ,
P_VIT => canGet( 2 , SUBWAY) ,
P_TEH => canGet( 3 , SUBWAY)
) ,
P_SEN => canGet( 4 , SUBWAY) ,
P_GOS => canGet( 7 , FOOT) ,
P_VIT => canGet( 3 , SUBWAY)
) ,
P_SEN => canGet( 2 , SUBWAY) ,
P_TEH => canGet( 2 , SUBWAY) ,
P_VLA => canGet( 3 , SUBWAY)
) ,
P_SEN => canGet( 3 , SUBWAY) ,
P_VIT => canGet( 2 , SUBWAY)
)
) ;
/*Функция построения кратчайшего пути.
Возвращает пустой массив, если кратчайший путь не содержит промежуточных нодов.
Иначе, возвращает массив промежуточных нодов.
*/
function getPath( $start , $end , $interimStep ) {
$temp = $end ;
for ( ; $temp != $start ; $temp = $interimStep [ $start ] [ $temp ] ) {
}
return $shortestPath ;
}
/*
Функция вывода пути.
*/
function printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) {
if ( $startPoint == $endPoint ) {
echo "Ты собираешься попасть в точку, в которой уже находишься.(\" {$pointNames [$startPoint ]}\" )\n \n " ;
return ;
}
echo "Начальная точка: \" {$pointNames [$startPoint ]}\" \n " ;
$temp = $startPoint ;
foreach ( $shortestPath as $node ) {
echo "Из нее {$paths [$temp ][$node ]['by']} до точки \" {$pointNames [$node ]}\" {$pathCost [$temp ][$node ]} мин.\n " ;
$temp = $node ;
}
echo "В итоге ты попадешь в точку \" {$pointNames [$endPoint ]}\" за {$pathCost [$startPoint ][$endPoint ]} мин. Приятной поездки!\n \n " ;
}
$numberOfNodes = count ( $pointNames ) ;
/*
Делаем квадратную матрицу путей размера $numberOfNodes, которая будет содержать время кратчайшего пути.
Если путь не существует, то присваиваем ему значение бесконечности.
*/
for ( $i = 0 ; $i < $numberOfNodes ; $i ++ ) {
for ( $j = 0 ; $j < $numberOfNodes ; $j ++ ) {
if ( $i == $j ) {
$pathCost [ $i ] [ $j ] = 0 ;
} elseif ( ! isset ( $paths [ $i ] [ $j ] [ 'time' ] ) ) { $pathCost [ $i ] [ $j ] = INF;
} else {
$pathCost [ $i ] [ $j ] = $paths [ $i ] [ $j ] [ 'time' ] ;
}
}
}
//Массив, который будет содержать предпоследний шаг кратчайшего пути.
for ( $i = 0 ; $i < $numberOfNodes ; $i ++ ) {
$interimStep [ $i ] = array ( ) ; for ( $j = 0 ; $j < $numberOfNodes ; $j ++ ) {
if ( $i == $j ) {
$interimStep [ $i ] [ $j ] = PATH_TO_ITSELF;
} else {
$interimStep [ $i ] [ $j ] = $i ;
}
}
}
//Алгоритм Флойда-Уоршелла.
for ( $k = 0 ; $k < $numberOfNodes ; $k ++ ) {
for ( $i = 0 ; $i < $numberOfNodes ; $i ++ ) {
for ( $j = 0 ; $j < $numberOfNodes ; $j ++ ) {
if ( ( $pathCost [ $i ] [ $k ] + $pathCost [ $k ] [ $j ] ) < $pathCost [ $i ] [ $j ] ) {
$pathCost [ $i ] [ $j ] = $pathCost [ $i ] [ $k ] + $pathCost [ $k ] [ $j ] ;
$interimStep [ $i ] [ $j ] = $interimStep [ $k ] [ $j ] ;
}
}
}
}
$startPoint = 0 ; // Петроградская
$endPoint = 9 ; // Новая Голландия
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
//Сенная Площадь -> Новая Голландия
$startPoint = 12 ;
$endPoint = 9 ;
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
$startPoint = P_VIT;
$endPoint = P_NOV;
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
$startPoint = P_LET;
$endPoint = P_KRE;
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
$startPoint = P_NOV;
$endPoint = P_NOV;
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
$startPoint = P_VAS;
$endPoint = P_NOV;
$shortestPath = getPath( $startPoint , $endPoint , $interimStep ) ;
printPath( $startPoint , $endPoint , $shortestPath , $paths , $pointNames , $pathCost ) ;
PD9waHAKIAplcnJvcl9yZXBvcnRpbmcoLTEpOwovKiBodHRwOi8vZC4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uMi5uZXQvICovCgpkZWZpbmUoJ1NVQldBWScsICLQtdC00LXRiNGMINC90LAg0LzQtdGC0YDQviIpOwpkZWZpbmUoJ0ZPT1QnLCAi0LjQtNC10YjRjCDQv9C10YjQutC+0LwiKTsKZGVmaW5lKCdCVVMnLCAi0LXQtNC10YjRjCDQvdCwINCw0LLRgtC+0LHRg9GB0LUiKTsKCmRlZmluZSgnUF9QRVQnLCAwKTsKZGVmaW5lKCdQX0NISycsIDEpOwpkZWZpbmUoJ1BfR09SJywgMik7CmRlZmluZSgnUF9TUE8nLCAzKTsKZGVmaW5lKCdQX1ZBUycsIDQpOwpkZWZpbmUoJ1BfS1JFJywgNSk7CmRlZmluZSgnUF9MRVQnLCA2KTsKZGVmaW5lKCdQX0RWTycsIDcpOwpkZWZpbmUoJ1BfSVNBJywgOCk7CmRlZmluZSgnUF9OT1YnLCA5KTsKZGVmaW5lKCdQX1JBUycsIDEwKTsKZGVmaW5lKCdQX0dPUycsIDExKTsKZGVmaW5lKCdQX1NFTicsIDEyKTsKZGVmaW5lKCdQX1ZMQScsIDEzKTsKZGVmaW5lKCdQX1ZJVCcsIDE0KTsKZGVmaW5lKCdQX1RFSCcsIDE1KTsKCmRlZmluZSgnUEFUSF9UT19JVFNFTEYnLCAtMSk7CgovKiDQp9GC0L7QsdGLINC90LUg0L/QuNGB0LDRgtGMINC80L3QvtCz0L4g0YDQsNC3IGFycmF5KCd0aW1lJyA9PiAuLi4sICdieScgPT4gLi4uKSwg0LjRgdC/0L7Qu9GM0LfRg9C10Lwg0YTRg9C90LrRhtC40Y4uIAogICAgwqtjYW5HZXTCuyDQv9C10YDQtdCy0L7QtNC40YLRgdGPINC60LDQuiDCq9C80L7QttC90L4g0L/QvtC/0LDRgdGC0YzCuyAqLwpmdW5jdGlvbiBjYW5HZXQoJHRpbWUsICRieVdoYXQpIHsKICAgIHJldHVybiBhcnJheSgndGltZScgICAgID0+ICAkdGltZSwgJ2J5JyA9PiAgJGJ5V2hhdCk7Cn0KCiRwb2ludE5hbWVzID0gYXJyYXkoCiAgICBQX1BFVCAgID0+ICAn0YHRgi4g0LwuINCf0LXRgtGA0L7Qs9GA0LDQtNGB0LrQsNGPJywKICAgIFBfQ0hLICAgPT4gICfRgdGCLiDQvC4g0KfQutCw0LvQvtCy0YHQutCw0Y8nLAogICAgUF9HT1IgICA9PiAgJ9GB0YIuINC8LiDQk9C+0YDRjNC60L7QstGB0LrQsNGPJywKICAgIFBfU1BPICAgPT4gICfRgdGCLiDQvC4g0KHQv9C+0YDRgtC40LLQvdCw0Y8nLAogICAgUF9WQVMgICA9PiAgJ9GB0YIuINC8LiDQktCw0YHQuNC70LXQvtGB0YLRgNC+0LLRgdC60LDRjycsCiAgICBQX0tSRSAgID0+ICAn0J/QtdGC0YDQvtC/0LDQstC70L7QstGB0LrQsNGPINC60YDQtdC/0L7RgdGC0YwnLAogICAgUF9MRVQgICA9PiAgJ9Cb0LXRgtC90LjQuSDRgdCw0LQnLAogICAgUF9EVk8gICA9PiAgJ9CU0LLQvtGA0YbQvtCy0LDRjyDQv9C70L7RidCw0LTRjCcsCiAgICBQX0lTQSAgID0+ICAn0JjRgdCw0LrQuNC10LLRgdC60LjQuSDRgdC+0LHQvtGAJywKICAgIFBfTk9WICAgPT4gICfQndC+0LLQsNGPINCT0L7Qu9C70LDQvdC00LjRjycsCiAgICBQX1JBUyAgID0+ICAn0JTQvtC8INCg0LDRgdC60L7Qu9GM0L3QuNC60L7QstCwJywKICAgIFBfR09TICAgPT4gICfQk9C+0YHRgtC40L3Ri9C5INCU0LLQvtGAJywKICAgIFBfU0VOICAgPT4gICfQodC10L3QvdCw0Y8g0J/Qu9C+0YnQsNC00YwnLAogICAgUF9WTEEgICA9PiAgJ9GB0YIuINC8LiDQktC70LDQtNC40LzQuNGA0YHQutCw0Y8nLAogICAgUF9WSVQgICA9PiAgJ9CS0LjRgtC10LHRgdC60LjQuSDQstC+0LrQt9Cw0LsnLAogICAgUF9URUggICA9PiAgJ9Ci0LXRhdC90L7Qu9C+0LPQuNGH0LXRgdC60LjQuSDQmNC90YHRgtC40YLRg9GCJwopOwoKJHBhdGhzID0gYXJyYXkoCiAgICBQX1BFVCAgID0+ICBhcnJheSgKICAgICAgICBQX0NISyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgUF9HT1IgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCiAKICAgIFBfQ0hLICAgPT4gIGFycmF5KAogICAgICAgIFBfUEVUICAgPT4gIGNhbkdldCgxMCwgQlVTKSwKICAgICAgICBQX1NQTyAgID0+ICBjYW5HZXQoMywgU1VCV0FZKQogICAgKSwKIAogICAgUF9HT1IgICA9PiAgYXJyYXkoCiAgICAgICAgUF9QRVQgICA9PiAgY2FuR2V0KDMsIEJVUyksCiAgICAgICAgUF9LUkUgICA9PiAgY2FuR2V0KDUsIEZPT1QpLAogICAgICAgIFBfR09TICAgPT4gIGNhbkdldCg2LCBTVUJXQVkpCiAgICApLAogCiAgICBQX1NQTyAgID0+ICBhcnJheSgKICAgICAgICBQX0NISyAgID0+ICBjYW5HZXQoMywgU1VCV0FZKSwKICAgICAgICBQX1ZBUyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgUF9TRU4gICA9PiAgY2FuR2V0KDcsIFNVQldBWSkKICAgICksCiAKICAgIFBfVkFTICAgPT4gIGFycmF5KAogICAgICAgIFBfU1BPICAgPT4gIGNhbkdldCgxMCwgQlVTKSwKICAgICAgICBQX0dPUyAgID0+ICBjYW5HZXQoNywgU1VCV0FZKSwKICAgICAgICBQX05PViAgID0+ICBjYW5HZXQoMTEsIEZPT1QpCiAgICApLAogCiAgICBQX0tSRSAgID0+ICBhcnJheSgKICAgICAgICBQX0dPUiAgID0+ICBjYW5HZXQoNSwgRk9PVCkKICAgICksCiAKICAgIFBfTEVUICAgPT4gIGFycmF5KAogICAgICAgIFBfRFZPICAgPT4gIGNhbkdldCg2LCBGT09UKSwKICAgICAgICBQX0dPUyAgID0+ICBjYW5HZXQoNywgRk9PVCkKICAgICksCiAKICAgIFBfRFZPICAgPT4gIGFycmF5KAogICAgICAgIFBfSVNBICAgPT4gIGNhbkdldCg2LCBGT09UKSwKICAgICAgICBQX0dPUyAgID0+ICBjYW5HZXQoNiwgRk9PVCksCiAgICAgICAgUF9MRVQgICA9PiAgY2FuR2V0KDYsIEZPT1QpCiAgICApLAogCiAgICBQX0lTQSAgID0+ICBhcnJheSgKICAgICAgICBQX0RWTyAgID0+ICBjYW5HZXQoNiwgRk9PVCksCiAgICAgICAgUF9OT1YgICA9PiAgY2FuR2V0KDUsIEZPT1QpCiAgICApLAogCiAgICBQX05PViAgID0+ICBhcnJheSgKICAgICAgICBQX1ZBUyAgID0+ICBjYW5HZXQoMTEsIEZPT1QpLAogICAgICAgIFBfSVNBICAgPT4gIGNhbkdldCg1LCBGT09UKSwKICAgICAgICBQX1JBUyAgID0+ICBjYW5HZXQoNywgQlVTKQogICAgKSwKIAogICAgUF9SQVMgICA9PiAgYXJyYXkoCiAgICAgICAgUF9OT1YgICA9PiAgY2FuR2V0KDcsIEJVUyksCiAgICAgICAgUF9TRU4gICA9PiAgY2FuR2V0KDMsIEZPT1QpCiAgICApLAogCiAgICBQX0dPUyAgID0+ICBhcnJheSgKICAgICAgICBQX1ZBUyAgID0+ICBjYW5HZXQoNywgU1VCV0FZKSwKICAgICAgICBQX1NFTiAgID0+ICBjYW5HZXQoMywgU1VCV0FZKSwKICAgICAgICBQX0RWTyAgID0+ICBjYW5HZXQoNiwgRk9PVCksCiAgICAgICAgUF9HT1IgICA9PiAgY2FuR2V0KDYsIFNVQldBWSksCiAgICAgICAgUF9MRVQgICA9PiAgY2FuR2V0KDcsIEZPT1QpLAogICAgICAgIFBfVkxBICAgPT4gIGNhbkdldCg3LCBGT09UKSAgICAgICAgCiAgICApLAogCiAgICBQX1NFTiAgID0+ICBhcnJheSgKICAgICAgICBQX1JBUyAgID0+ICBjYW5HZXQoMywgRk9PVCksCiAgICAgICAgUF9TUE8gICA9PiAgY2FuR2V0KDcsIFNVQldBWSksCiAgICAgICAgUF9HT1MgICA9PiAgY2FuR2V0KDMsIFNVQldBWSksCiAgICAgICAgUF9WTEEgICA9PiAgY2FuR2V0KDQsIFNVQldBWSksCiAgICAgICAgUF9WSVQgICA9PiAgY2FuR2V0KDIsIFNVQldBWSksCiAgICAgICAgUF9URUggICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCiAKICAgIFBfVkxBICAgPT4gIGFycmF5KAogICAgICAgIFBfU0VOICAgPT4gIGNhbkdldCg0LCBTVUJXQVkpLAogICAgICAgIFBfR09TICAgPT4gIGNhbkdldCg3LCBGT09UKSwKICAgICAgICBQX1ZJVCAgID0+ICBjYW5HZXQoMywgU1VCV0FZKQogICAgKSwKIAogICAgUF9WSVQgICA9PiAgYXJyYXkoCiAgICAgICAgUF9TRU4gICA9PiAgY2FuR2V0KDIsIFNVQldBWSksCiAgICAgICAgUF9URUggICA9PiAgY2FuR2V0KDIsIFNVQldBWSksCiAgICAgICAgUF9WTEEgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCiAKICAgIFBfVEVIICAgPT4gIGFycmF5KAogICAgICAgIFBfU0VOICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpLAogICAgICAgIFBfVklUICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpICAgICAgICAKICAgICkKKTsKIAoKLyrQpNGD0L3QutGG0LjRjyDQv9C+0YHRgtGA0L7QtdC90LjRjyDQutGA0LDRgtGH0LDQudGI0LXQs9C+INC/0YPRgtC4LgrQktC+0LfQstGA0LDRidCw0LXRgiDQv9GD0YHRgtC+0Lkg0LzQsNGB0YHQuNCyLCDQtdGB0LvQuCDQutGA0LDRgtGH0LDQudGI0LjQuSDQv9GD0YLRjCDQvdC1INGB0L7QtNC10YDQttC40YIg0L/RgNC+0LzQtdC20YPRgtC+0YfQvdGL0YUg0L3QvtC00L7Qsi4K0JjQvdCw0YfQtSwg0LLQvtC30LLRgNCw0YnQsNC10YIg0LzQsNGB0YHQuNCyINC/0YDQvtC80LXQttGD0YLQvtGH0L3Ri9GFINC90L7QtNC+0LIuCiovCmZ1bmN0aW9uIGdldFBhdGgoJHN0YXJ0LCAkZW5kLCAkaW50ZXJpbVN0ZXApewogICAgJHNob3J0ZXN0UGF0aCA9IGFycmF5KCk7CiAgICAkdGVtcCA9ICRlbmQ7CiAgICBmb3IgKCA7ICR0ZW1wICE9ICRzdGFydDsgJHRlbXAgPSAkaW50ZXJpbVN0ZXBbJHN0YXJ0XVskdGVtcF0pIHsKICAgICAgICBhcnJheV91bnNoaWZ0KCRzaG9ydGVzdFBhdGgsICR0ZW1wKTsKICAgIH0KICAgIHJldHVybiAkc2hvcnRlc3RQYXRoOwp9CgovKgrQpNGD0L3QutGG0LjRjyDQstGL0LLQvtC00LAg0L/Rg9GC0LguCiovCmZ1bmN0aW9uIHByaW50UGF0aCgkc3RhcnRQb2ludCwgJGVuZFBvaW50LCAkc2hvcnRlc3RQYXRoLCAkcGF0aHMsICRwb2ludE5hbWVzLCAkcGF0aENvc3QpewogICAgaWYgKCRzdGFydFBvaW50ID09ICRlbmRQb2ludCkgewogICAgICAgIGVjaG8gItCi0Ysg0YHQvtCx0LjRgNCw0LXRiNGM0YHRjyDQv9C+0L/QsNGB0YLRjCDQsiDRgtC+0YfQutGDLCDQsiDQutC+0YLQvtGA0L7QuSDRg9C20LUg0L3QsNGF0L7QtNC40YjRjNGB0Y8uKFwieyRwb2ludE5hbWVzWyRzdGFydFBvaW50XX1cIilcblxuIjsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBlY2hvICLQndCw0YfQsNC70YzQvdCw0Y8g0YLQvtGH0LrQsDogXCJ7JHBvaW50TmFtZXNbJHN0YXJ0UG9pbnRdfVwiXG4iOwogICAgJHRlbXAgPSAkc3RhcnRQb2ludDsKICAgIGZvcmVhY2ggKCRzaG9ydGVzdFBhdGggYXMgJG5vZGUpIHsKICAgICAgICBlY2hvICLQmNC3INC90LXQtSB7JHBhdGhzWyR0ZW1wXVskbm9kZV1bJ2J5J119INC00L4g0YLQvtGH0LrQuCBcInskcG9pbnROYW1lc1skbm9kZV19XCIgeyRwYXRoQ29zdFskdGVtcF1bJG5vZGVdfSDQvNC40L0uXG4iOwogICAgICAgICR0ZW1wID0gJG5vZGU7CiAgICB9CiAgICBlY2hvICLQkiDQuNGC0L7Qs9C1INGC0Ysg0L/QvtC/0LDQtNC10YjRjCDQsiDRgtC+0YfQutGDIFwieyRwb2ludE5hbWVzWyRlbmRQb2ludF19XCIg0LfQsCB7JHBhdGhDb3N0WyRzdGFydFBvaW50XVskZW5kUG9pbnRdfSDQvNC40L0uINCf0YDQuNGP0YLQvdC+0Lkg0L/QvtC10LfQtNC60LghXG5cbiI7Cn0KCiRudW1iZXJPZk5vZGVzID0gY291bnQoJHBvaW50TmFtZXMpOwoKLyoK0JTQtdC70LDQtdC8INC60LLQsNC00YDQsNGC0L3Rg9GOINC80LDRgtGA0LjRhtGDINC/0YPRgtC10Lkg0YDQsNC30LzQtdGA0LAgJG51bWJlck9mTm9kZXMsINC60L7RgtC+0YDQsNGPINCx0YPQtNC10YIg0YHQvtC00LXRgNC20LDRgtGMINCy0YDQtdC80Y8g0LrRgNCw0YLRh9Cw0LnRiNC10LPQviDQv9GD0YLQuC4K0JXRgdC70Lgg0L/Rg9GC0Ywg0L3QtSDRgdGD0YnQtdGB0YLQstGD0LXRgiwg0YLQviDQv9GA0LjRgdCy0LDQuNCy0LDQtdC8INC10LzRgyDQt9C90LDRh9C10L3QuNC1INCx0LXRgdC60L7QvdC10YfQvdC+0YHRgtC4LgoKKi8KJHBhdGhDb3N0ID0gYXJyYXkoKTsKZm9yICgkaSA9IDA7ICRpIDwgJG51bWJlck9mTm9kZXM7ICRpKyspIHsKICAgIGZvciAoJGogPSAwOyAkaiA8ICRudW1iZXJPZk5vZGVzOyAkaisrKSB7CiAgICAgICAgaWYgKCRpID09ICRqKSB7CiAgICAgICAgICAgICRwYXRoQ29zdFskaV1bJGpdID0gMDsKICAgICAgICB9IGVsc2VpZiAoIWlzc2V0KCRwYXRoc1skaV1bJGpdWyd0aW1lJ10pKSB7CiAgICAgICAgICAgICRwYXRoQ29zdFskaV1bJGpdID0gSU5GOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICRwYXRoQ29zdFskaV1bJGpdID0gJHBhdGhzWyRpXVskal1bJ3RpbWUnXTsKICAgICAgICB9CiAgICB9Cn0KCi8v0JzQsNGB0YHQuNCyLCDQutC+0YLQvtGA0YvQuSDQsdGD0LTQtdGCINGB0L7QtNC10YDQttCw0YLRjCDQv9GA0LXQtNC/0L7RgdC70LXQtNC90LjQuSDRiNCw0LMg0LrRgNCw0YLRh9Cw0LnRiNC10LPQviDQv9GD0YLQuC4KJGludGVyaW1TdGVwID0gYXJyYXkoKTsKZm9yICgkaSA9IDA7ICRpIDwgJG51bWJlck9mTm9kZXM7ICRpKyspIHsKICAgICRpbnRlcmltU3RlcFskaV0gPSBhcnJheSgpOyAKICAgIGZvciAoJGogPSAwOyAkaiA8ICRudW1iZXJPZk5vZGVzOyAkaisrKSB7CiAgICAgICAgaWYgKCRpID09ICRqKSB7CiAgICAgICAgICAgICRpbnRlcmltU3RlcFskaV1bJGpdID0gUEFUSF9UT19JVFNFTEY7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJGludGVyaW1TdGVwWyRpXVskal0gPSAkaTsKICAgICAgICB9CiAgICB9Cn0KCi8v0JDQu9Cz0L7RgNC40YLQvCDQpNC70L7QudC00LAt0KPQvtGA0YjQtdC70LvQsC4KZm9yICgkayA9IDA7ICRrIDwgJG51bWJlck9mTm9kZXM7ICRrKyspIHsKICAgIGZvciAoJGkgPSAwOyAkaSA8ICRudW1iZXJPZk5vZGVzOyAkaSsrKSB7CiAgICAgICAgZm9yICgkaiA9IDA7ICRqIDwgJG51bWJlck9mTm9kZXM7ICRqKyspIHsKICAgICAgICAgICAgaWYgKCgkcGF0aENvc3RbJGldWyRrXSArICRwYXRoQ29zdFska11bJGpdKSA8ICRwYXRoQ29zdFskaV1bJGpdKSB7CiAgICAgICAgICAgICAgICAkcGF0aENvc3RbJGldWyRqXSA9ICRwYXRoQ29zdFskaV1bJGtdICsgJHBhdGhDb3N0WyRrXVskal07CiAgICAgICAgICAgICAgICAkaW50ZXJpbVN0ZXBbJGldWyRqXSA9ICRpbnRlcmltU3RlcFska11bJGpdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9Cgokc3RhcnRQb2ludCA9IDA7IC8vINCf0LXRgtGA0L7Qs9GA0LDQtNGB0LrQsNGPCiRlbmRQb2ludCA9IDk7IC8vINCd0L7QstCw0Y8g0JPQvtC70LvQsNC90LTQuNGPCiRzaG9ydGVzdFBhdGggPSBnZXRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRpbnRlcmltU3RlcCk7CnByaW50UGF0aCgkc3RhcnRQb2ludCwgJGVuZFBvaW50LCAkc2hvcnRlc3RQYXRoLCAkcGF0aHMsICRwb2ludE5hbWVzLCAkcGF0aENvc3QpOwoKLy/QodC10L3QvdCw0Y8g0J/Qu9C+0YnQsNC00YwgLT4g0J3QvtCy0LDRjyDQk9C+0LvQu9Cw0L3QtNC40Y8KJHN0YXJ0UG9pbnQgPSAxMjsKJGVuZFBvaW50ID0gOTsKJHNob3J0ZXN0UGF0aCA9IGdldFBhdGgoJHN0YXJ0UG9pbnQsICRlbmRQb2ludCwgJGludGVyaW1TdGVwKTsKcHJpbnRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRzaG9ydGVzdFBhdGgsICRwYXRocywgJHBvaW50TmFtZXMsICRwYXRoQ29zdCk7Cgokc3RhcnRQb2ludCA9IFBfVklUOwokZW5kUG9pbnQgPSBQX05PVjsKJHNob3J0ZXN0UGF0aCA9IGdldFBhdGgoJHN0YXJ0UG9pbnQsICRlbmRQb2ludCwgJGludGVyaW1TdGVwKTsKcHJpbnRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRzaG9ydGVzdFBhdGgsICRwYXRocywgJHBvaW50TmFtZXMsICRwYXRoQ29zdCk7Cgokc3RhcnRQb2ludCA9IFBfTEVUOwokZW5kUG9pbnQgPSBQX0tSRTsKJHNob3J0ZXN0UGF0aCA9IGdldFBhdGgoJHN0YXJ0UG9pbnQsICRlbmRQb2ludCwgJGludGVyaW1TdGVwKTsKcHJpbnRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRzaG9ydGVzdFBhdGgsICRwYXRocywgJHBvaW50TmFtZXMsICRwYXRoQ29zdCk7Cgokc3RhcnRQb2ludCA9IFBfTk9WOwokZW5kUG9pbnQgPSBQX05PVjsKJHNob3J0ZXN0UGF0aCA9IGdldFBhdGgoJHN0YXJ0UG9pbnQsICRlbmRQb2ludCwgJGludGVyaW1TdGVwKTsKcHJpbnRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRzaG9ydGVzdFBhdGgsICRwYXRocywgJHBvaW50TmFtZXMsICRwYXRoQ29zdCk7Cgokc3RhcnRQb2ludCA9IFBfVkFTOwokZW5kUG9pbnQgPSBQX05PVjsKJHNob3J0ZXN0UGF0aCA9IGdldFBhdGgoJHN0YXJ0UG9pbnQsICRlbmRQb2ludCwgJGludGVyaW1TdGVwKTsKcHJpbnRQYXRoKCRzdGFydFBvaW50LCAkZW5kUG9pbnQsICRzaG9ydGVzdFBhdGgsICRwYXRocywgJHBvaW50TmFtZXMsICRwYXRoQ29zdCk7