Skip to content

Commit e823618

Browse files
authored
Add median (#19)
1 parent 2bd33e6 commit e823618

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

.spec/math/median_spec.lua

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
describe("median", function()
2+
local median = require("math.median")
3+
4+
local function check(expected, nums)
5+
assert.equal(expected, median(nums))
6+
local shuffle = require("random.shuffle")
7+
for _ = 1, 2 * #nums do
8+
shuffle(nums)
9+
assert.equal(expected, median(nums))
10+
end
11+
end
12+
13+
it("should handle general cases", function()
14+
check(1, { 1 })
15+
check(1.5, { 1, 2 })
16+
check(3, { 3, 1, 2, 5, 5 })
17+
check(2.5, { 2, 3, 1, 4 })
18+
check(0, { 11, 0, 0, 0, 0, 0, 0, 0, 10 })
19+
check(4, { 1, 2, 3, 4, 5, 6, 7 })
20+
check(4.5, { 1, 2, 3, 4, 5, 6, 7, 8 })
21+
end)
22+
23+
it("should return nil for empty input", function()
24+
assert.equal(nil, median({}))
25+
end)
26+
27+
it("should not change the input", function()
28+
local some_nums = { 4, 3, 5, 1 }
29+
median(some_nums)
30+
assert.same(some_nums, { 4, 3, 5, 1 })
31+
end)
32+
end)

src/math/median.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
local quickselect = require("sorting.quickselect_median_of_medians")
2+
3+
-- Computes the median of the input list `nums`.
4+
return function(nums)
5+
if #nums == 0 then
6+
return nil
7+
end
8+
if #nums == 1 then
9+
return nums[1]
10+
end
11+
local copy = {}
12+
for i = 1, #nums do
13+
copy[i] = nums[i]
14+
end
15+
local mid_pos = quickselect(copy, math.ceil(#copy / 2))
16+
if #nums % 2 == 1 then
17+
return copy[mid_pos]
18+
end
19+
local next_mid_pos = quickselect(copy, 1, nil, mid_pos + 1)
20+
return (copy[mid_pos] + copy[next_mid_pos]) / 2
21+
end

0 commit comments

Comments
 (0)