dc, 120 122 bytes
9kzsa0si[li:sli1+dsila>A]dsAx[1scddd;sr1-;sli:sr1-:s]sR[lidd1-;sr;s<R1+dsila>S]sS[1si0sclSxlc1=M]dsMxla2/dd1%-;sr.5-;s+2/p
Try it online!
My original code worked for all the provided test cases, but was actually faulty, so +2 bytes for the fix. Dang!
Lots of bytes since dc
doesn't have any inbuilt sorting mechanism, and very little in the way of stack manipulation.
9k
sets the precision to 9 places since we need the possibility of digits past the decimal point. dc
doesn't float, so hopefully this is satisfactory.
zsa0si[li:sli1+dsila>A]dsAx
dumps the entirety of the stack into array s
, and preserves the number of items in register a
.
Macros M
, S
, and R
all make up a bubble sort. M
is our 'main' macro, so to speak, so I'll cover that one first.
[1si0sclSxlc1=M]dsMx
We reset increment register i
to 1, and check register c
to 0. We run macro S
, which is one pass through the array. If S
(actually, R
, but S
by proxy) made any changes, it would have set register c
to one, so if this is the case we loop through M
again.
[lidd1-;sr;s<R1+dsila>S]sS
One pass through the array. We load the increment counter i
, duplicate it twice, and decrement the top version of it by one. Essentially i
is always high, so we compare i
and i-1
. Load the two values from array s
, compare them, and if they're going the wrong way we run our swapping macro, R
. Then we keep on incrementing i
, comparing it to a
, and running S
until that comparison tells us we've hit the end of our array.
[1scddd;sr1-;sli:sr1-:s]sR
An individual instance of swappery in array a
. First we set our check register c
to 1 so that M
knows we made changes to the array. i
should still be on the stack from earlier, so we duplicate it three times. We retrieve i
indexed item from a
, swap our top-of-stack so that i
is present again, subtract one from it, and then retrieve that item from a
. Here we run into a stack manipulation limitation, so we have to load i
again and we store our previous i-1
value into that index in a
. Now we just have our old i
-indexed a
value on the stack and i
itself, so we swap these, subtract 1 from i
, and replace the value in a
.
Eventually M
will stop running when it sees no changes have been made, and now that things are sorted we can do the actual median operation.
la2/dd1%-;sr.5-;s+2/p
Since a
already has the length of array s
, we load it and divide by two. Testing for evenness would be costly, so we rely on the fact that dc uses the floor of a non-whole value for its index. We divide a
by two and duplicate the value. We then get from s
the values indexed by (a
/2-.5) and (a
/2-((a
/2)mod 1)). This gives us the middle value twice for an odd number of values, or the middle two values for an even number. +2/p
averages them and prints the result.
7/2
or8/2
) \$\endgroup\$