# Code golf with a HashSet intersection algorithm

Hi All, I have some working code but would be interested in suggestions on how to make it more idiomatic and/or cleaner. The algorithm is that I build the union of sets and then take the intersection of that large set with another, smaller set. It feels like I should be able to use the `Union` and `Intersection` structures more cleanly rather than my current, verbose "iterate and insert into a temporary set" code.

``````    // Build a set of all the tiles that are illuminated in the map
let mut illuminated_tiles = HashSet::new();
let mut query_light = <(&Point, &FieldOfLight)>::query();
query_light.iter(ecs)
.for_each(|(pt, fol)| {
let lit_tiles = field_of_view_set(*pt, fol.radius, map);
// illuminated_tiles = illuminated_tiles.union(&lit_tiles).collect::<HashSet<Point>>();
for pt in lit_tiles.into_iter() {
illuminated_tiles.insert(pt);
}
});

// The viewable tiles is the intersection between the actors
// view radius and the set of illuminated tiles
let mut query_view = <(&Point, &mut FieldOfView)>::query();
query_view.iter_mut(ecs)
.filter(|(_, fov)| fov.is_dirty )
.for_each(|(pt, fov)| {
let pt = *pt;
let view_set = field_of_view_set(pt, fov.radius, map);
let intersection = illuminated_tiles.intersection(&view_set);

let mut view_set = HashSet::new();
for pt in intersection {
view_set.insert(*pt);
}
fov.visible_tiles = view_set;
fov.is_dirty = false;
});
``````

`illuminated_tiles.extend(lit_tiles)`

1 Like

something like this ought to work:

``````    // Build a set of all the tiles that are illuminated in the map
let mut query_light = <(&Point, &FieldOfLight)>::query();
let illuminated_tiles = query_light
.iter(ecs)
.flat_map(|(pt, fol)| field_of_view_set(*pt, fol.radius, map))
.collect::<HashSet<_>>();
``````
1 Like

perhaps:
`fov.visible_tiles = &illuminated_tiles & &field_of_view_set(*pt, fov.radius, map);`

1 Like

This worked perfectly and seems very clean. The other solution (using `extend`) also worked. If you were doing a code review would you prefer one over the other?

EDIT: wish I could mark more than one response as the Solution.

That worked too. I feel a little dumb missing the `&` operator on HashSet. I assumed the default behavior of `intersection` would do what this does. Thank you.

EDIT: after refactors the code looks like the following. The `&` looks a little magical to me (something I'd expect to see in ruby) but I'll get used to it.

``````    // Build a set of all the tiles that are illuminated in the map
let mut query_light = <(&Point, &FieldOfLight)>::query();
let illuminated_tiles = query_light.iter(ecs)
.flat_map(|(pt, fol)| field_of_view_set(*pt, fol.radius, map))
.collect::<HashSet<_>>();

// The viewable tiles is the intersection between the actors
// view radius and the set of illuminated tiles
let mut query_view = <(&Point, &mut FieldOfView)>::query();
query_view.iter_mut(ecs)
.filter(|(_, fov)| fov.is_dirty )
.for_each(|(pt, fov)| {
fov.visible_tiles = &illuminated_tiles & &field_of_view_set(*pt, fov.radius, map);
fov.is_dirty = false;
});
``````

Iād prefer the one using `flat_map`.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.