I was solving this problem in Zig and came up with the below function signature (I’m not sure of its correctness):
fn insertInterval(alloc: std.mem.Allocator, intervals: []Interval, new_interval: *Interval) ![]Interval {
// implementation
}
I tried declaring the third function parameter (new_interval: *Interval
), without a pointer, but running unit tests gave errors.
I was able to get around by changing things based on errors, but dont understand it clearly:
-
Why does the third parameter have to be
new_interval: *Interval
instead ofnew_interval: Interval
-
Why does the second parameter
intervals: []Interval
work without a pointer.
Also wanted to know if there’s a better way to go about it ?
Implementation & Tests
const std = @import("std");
const testing = std.testing;
const test_alloc = testing.allocator;
const Interval = struct {
start: u16,
end: u16,
};
fn insertInterval(alloc: std.mem.Allocator, intervals: []Interval, new_interval: *Interval) ![]Interval {
var periods: std.ArrayListUnmanaged(Interval) = .empty;
for (0..intervals.len) |i| {
if (new_interval.end < intervals[i].start) {
try periods.append(alloc, new_interval.*);
new_interval.* = intervals[i];
} else if (new_interval.start > intervals[i].end) {
try periods.append(alloc, intervals[i]);
} else {
new_interval.*.start = @min(new_interval.start, intervals[i].start);
new_interval.*.end = @max(new_interval.end, intervals[i].end);
}
}
try periods.append(alloc, new_interval.*);
return periods.toOwnedSlice(alloc);
}
test "new interval overlaps with the first interval" {
var initial = [2]Interval{
.{ .start = 1, .end = 3 },
.{ .start = 6, .end = 9 },
};
var new = Interval{ .start = 2, .end = 5 };
const expected = [2]Interval{
.{ .start = 1, .end = 5 },
.{ .start = 6, .end = 9 },
};
const result = try insertInterval(test_alloc, &initial, &new);
defer test_alloc.free(result);
try testing.expectEqualSlices(Interval, &expected, result);
}
test "new interval overlaps with three current intervals" {
var initial = [5]Interval{
.{ .start = 1, .end = 2 },
.{ .start = 3, .end = 5 },
.{ .start = 6, .end = 7 },
.{ .start = 8, .end = 10 },
.{ .start = 12, .end = 16 },
};
var new = Interval{ .start = 4, .end = 8 };
const expected = [3]Interval{
.{ .start = 1, .end = 2 },
.{ .start = 3, .end = 10 },
.{ .start = 12, .end = 16 },
};
const result = try insertInterval(test_alloc, &initial, &new);
defer test_alloc.free(result);
try testing.expectEqualSlices(Interval, &expected, result);
}