I'm trying to finish a school homework question about finding the most distant country(-ies) regarding number of border crossing using BaseX GUI and mondial database. I wrote a recursive function using BFS to complete this. The query should return a bunch of country names that are most distant to the input country.
When I called the function as below to find the most distant country to Nicaragua, a bunch of country names including "Canada" and "Argentina" should be returned.
let $return-list := local:reachable-far($country[name="Nicaragua"])
return $return-list/country/name
However, I only got Canada in my return value but not other countries, like Argentina or Suriname.
<name>Canada</name>
I tried to debug the query by calling
let $return-list := local:reachable-far($country[name="Nicaragua"])
return $return-list/country[name="Argentina"]/name
The return value is
<name>Argentina</name>
which I think means Argentina (and other countries) is in the return value but somehow not showing. What's wrong with my code here? The full function declaration is pasted below.
declare variable $mondial := doc("D:/mondial.xml")/mondial;
declare variable $country := $mondial/country;
declare function local:reachable-far($curr)
{
if ($curr = ()) then ()
else
(
local:reachable-bfsl($curr, $curr, $curr, $curr, 0)
)
};
declare function local:reachable-bfsl($queue, $seen, $lastoflevel, $currlevel, $depth)
{
(:return current level if stack is empty (should never happen):)
if (empty($queue)) then (<row>{$currlevel} <depth>{$depth}</depth></row>)
else
(
let $curr := $queue[1]
let $neighbors-all := $curr/border/@country
let $neighbors-code := $neighbors-all[not(.=$seen/@car_code)]
let $neighbors := $country[@car_code = $neighbors-code]
(:if current country is not the last of level, continue with current level:)
return if ($curr/@car_code != $lastoflevel/@car_code)
then
(
local:reachable-bfsl(($queue[position()>1], $neighbors),
($seen, $neighbors),
$lastoflevel,
$currlevel union $curr,
$depth)
)
(:if current country is the last of level:)
else
(
(:current contury has searchable neighbors or stack is not empty after popping:)
if (not(empty($neighbors)) or not(empty($queue[position()>1])))
then
( (:clear current level, continue next level, update last of level to last in stack, depth++:)
local:reachable-bfsl(($queue[position()>1], $neighbors),
($seen, $neighbors),
($queue[position()>1], $neighbors)[last()],
(),
$depth + 1)
)
(:current country does not have searchable neighbors and stack is empty after popping:)
else
(
<row>{trace($currlevel union $curr)} <depth>{$depth}</depth></row>
)
)
)
};
let $return-list := local:reachable-far($country[name="Nicaragua"])
return $return-list/country/name
return <out>{$return-list/country/name}</out>
– Michael Kay