Skip to content

Remove color function from flood fill because it is redundant #766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions contents/flood_fill/code/c/flood_fill.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ int inbounds(struct point p, struct canvas c) {
return (p.x < 0 || p.y < 0 || p.y >= c.max_y || p.x >= c.max_x) ? 0 : 1;
}

void color(struct canvas c, struct point p, int old_val, int new_val) {
if (inbounds(p, c) && c.data[p.x + c.max_x * p.y] == old_val) {
c.data[p.x + c.max_x * p.y] = new_val;
}
}

int find_neighbors(struct canvas c, struct point p, int old_val, int new_val,
struct point *neighbors) {
int cnt = 0;
Expand Down Expand Up @@ -93,7 +87,7 @@ void stack_fill(struct canvas c, struct point p, int old_val, int new_val) {
while (!stack_empty(stk)) {
struct point cur_loc = stack_pop(&stk);
if (c.data[cur_loc.x + c.max_x * cur_loc.y] == old_val) {
color(c, cur_loc, old_val, new_val);
c.data[cur_loc.x + c.max_x * cur_loc.y] = new_val;

struct point neighbors[4];
int cnt = find_neighbors(c, cur_loc, old_val, new_val, neighbors);
Expand Down Expand Up @@ -163,7 +157,7 @@ void queue_fill(struct canvas c, struct point p, int old_val, int new_val) {
while (!queue_empty(q)) {
struct point cur_loc = dequeue(&q);
if (c.data[cur_loc.x + c.max_x * cur_loc.y] == old_val) {
color(c, cur_loc, old_val, new_val);
c.data[cur_loc.x + c.max_x * cur_loc.y] = new_val;

struct point neighbors[4];
int cnt = find_neighbors(c, cur_loc, old_val, new_val, neighbors);
Expand All @@ -184,7 +178,7 @@ void recursive_fill(struct canvas c, struct point p, int old_val,
return;
}

color(c, p, old_val, new_val);
c.data[p.x + c.max_x * p.y] = new_val;

struct point neighbors[4];
int cnt = find_neighbors(c, p, old_val, new_val, neighbors);
Expand Down
22 changes: 4 additions & 18 deletions contents/flood_fill/code/julia/flood_fill.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@ function inbounds(canvas_size, loc)
end
end

function color!(canvas, loc::CartesianIndex, old_val, new_val)
# bounds check, do not color if no in bounds!
if !inbounds(size(canvas), loc)
return
end

# Only change color if the element value is the old value
if (canvas[loc] != old_val)
return
else
canvas[loc] = new_val
end
end

function find_neighbors(canvas, loc::CartesianIndex, old_val, new_val)

# Finding north, south, east, west neighbors
Expand Down Expand Up @@ -65,7 +51,7 @@ function stack_fill!(canvas, loc::CartesianIndex, old_val, new_val)
while length(s) > 0
current_loc = pop!(s)
if canvas[current_loc] == old_val
color!(canvas, current_loc, old_val, new_val)
canvas[current_loc] = new_val
possible_neighbors = find_neighbors(canvas, current_loc,
old_val, new_val)
for neighbor in possible_neighbors
Expand All @@ -86,7 +72,7 @@ function queue_fill!(canvas, loc::CartesianIndex, old_val, new_val)
enqueue!(q, loc)

# Coloring the initial location
color!(canvas, loc, old_val, new_val)
canvas[loc] = new_val

while length(q) > 0
current_loc = dequeue!(q)
Expand All @@ -96,7 +82,7 @@ function queue_fill!(canvas, loc::CartesianIndex, old_val, new_val)

# Coloring as we are enqueuing neighbors
for neighbor in possible_neighbors
color!(canvas, neighbor, old_val, new_val)
canvas[neighbor] = new_val
enqueue!(q,neighbor)
end

Expand All @@ -109,7 +95,7 @@ function recursive_fill!(canvas, loc::CartesianIndex, old_val, new_val)
return
end

color!(canvas, loc, old_val, new_val)
canvas[loc] = new_val

possible_neighbors = find_neighbors(canvas, loc, old_val, new_val)
for possible_neighbor in possible_neighbors
Expand Down
11 changes: 4 additions & 7 deletions contents/flood_fill/code/python/flood_fill.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
def inbounds(canvas_shape, p):
return min(p) >= 0 and p.x < canvas_shape[0] and p.y < canvas_shape[1]

def color(canvas, p, new_val):
canvas[p] = new_val

def find_neighbors(canvas, p, old_val, new_val):
# north, south, east, west neighbors
possible_neighbors = [
Expand All @@ -35,7 +32,7 @@ def stack_fill(canvas, p, old_val, new_val):

while stack:
cur_loc = stack.pop()
color(canvas, cur_loc, new_val)
canvas[cur_loc] = new_val
stack += find_neighbors(canvas, cur_loc, old_val, new_val)

def queue_fill(canvas, p, old_val, new_val):
Expand All @@ -45,21 +42,21 @@ def queue_fill(canvas, p, old_val, new_val):
q = Queue()
q.put(p)

color(canvas, p, new_val)
canvas[p] = new_val

while not q.empty():
cur_loc = q.get()
neighbors = find_neighbors(canvas, cur_loc, old_val, new_val)

for neighbor in neighbors:
color(canvas, neighbor, new_val)
canvas[neighbor] = new_val
q.put(neighbor)

def recursive_fill(canvas, p, old_val, new_val):
if old_val == new_val:
return

color(canvas, p, new_val)
canvas[p] = new_val

neighbors = find_neighbors(canvas, p, old_val, new_val)
for neighbor in neighbors:
Expand Down
35 changes: 12 additions & 23 deletions contents/flood_fill/flood_fill.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ In code, this might look like this:

{% method %}
{% sample lang="jl" %}
[import:37-55, lang:"julia"](code/julia/flood_fill.jl)
[import:23-41, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:34-52, lang:"c"](code/c/flood_fill.c)
[import:28-46, lang:"c"](code/c/flood_fill.c)
{% sample lang="py" %}
[import:13-28, lang="python"](code/python/flood_fill.py)
[import:10-25, lang="python"](code/python/flood_fill.py)
{% endmethod %}


Expand All @@ -105,22 +105,11 @@ In code, it might look like this:

{% method %}
{% sample lang="jl" %}
[import:106-118, lang:"julia"](code/julia/flood_fill.jl)
[import:92-104, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:180-195, lang:"c"](code/c/flood_fill.c)
[import:174-189, lang:"c"](code/c/flood_fill.c)
{% sample lang="py" %}
[import:58-66, lang="python"](code/python/flood_fill.py)
{% endmethod %}

All code snippets for this chapter rely on an exterior `color` function, defined as

{% method %}
{% sample lang="jl" %}
[import:23-35, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:28-32, lang:"c"](code/c/flood_fill.c)
{% sample lang="py" %}
[import:10-11, lang="python"](code/python/flood_fill.py)
[import:55-63, lang="python"](code/python/flood_fill.py)
{% endmethod %}

The above code continues recursing through available neighbors as long as neighbors exist, and this should work so long as we are adding the correct set of neighbors.
Expand All @@ -129,11 +118,11 @@ Additionally, it is possible to do the same type of traversal by managing a stac

{% method %}
{% sample lang="jl" %}
[import:57-77, lang:"julia"](code/julia/flood_fill.jl)
[import:43-63, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:85-108, lang:"c"](code/c/flood_fill.c)
[import:79-102, lang:"c"](code/c/flood_fill.c)
{% sample lang="py" %}
[import:30-39, lang="python"](code/python/flood_fill.py)
[import:27-36, lang="python"](code/python/flood_fill.py)
{% endmethod %}

This is ultimately the same method of traversal as before; however, because we are managing our own data structure, there are a few distinct differences:
Expand Down Expand Up @@ -170,11 +159,11 @@ The code would look something like this:

{% method %}
{% sample lang="jl" %}
[import:80-104, lang:"julia"](code/julia/flood_fill.jl)
[import:66-90, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:155-178, lang:"c"](code/c/flood_fill.c)
[import:149-172, lang:"c"](code/c/flood_fill.c)
{% sample lang="py" %}
[import:41-56, lang="python"](code/python/flood_fill.py)
[import:38-53, lang="python"](code/python/flood_fill.py)
{% endmethod %}

Now, there is a small trick in this code that must be considered to make sure it runs optimally.
Expand Down