September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -9,7 +9,7 @@ There are several approaches to this.   One is to sort the elements, and th
Sorting would take at least &nbsp; <big><span style="font-family: serif">O(''n''log''n'')</span></big>. &nbsp; Another approach would be to build a priority queue from the elements, and then extract half of the elements to get to the middle element(s). &nbsp; This would also take &nbsp; <big><span style="font-family: serif">O(''n''log''n'')</span></big>. &nbsp; The best solution is to use the &nbsp; [[wp:Selection algorithm|selection algorithm]] &nbsp; to find the median in &nbsp; <big><span style="font-family: serif">O(''n'')</span></big> &nbsp; time.
{{task heading|See also}}
[[Quickselect_algorithm]]
{{Related tasks/Statistical measures}}
<hr>

View file

@ -1,15 +1,17 @@
-- MEDIAN ---------------------------------------------------------------------
-- median :: [Num] -> Num
on median(xs)
-- nth :: [Num] -> Int -> Maybe Num
script nth
on lambda(xxs, n)
on |λ|(xxs, n)
if length of xxs > 0 then
set {x, xs} to uncons(xxs)
script belowX
on lambda(y)
on |λ|(y)
y < x
end lambda
end |λ|
end script
set {ys, zs} to partition(belowX, xs)
@ -18,24 +20,24 @@ on median(xs)
x
else
if k > n then
lambda(ys, n)
|λ|(ys, n)
else
lambda(zs, n - k - 1)
|λ|(zs, n - k - 1)
end if
end if
else
missing value
end if
end lambda
end |λ|
end script
set n to length of xs
if n > 0 then
tell nth
if n mod 2 = 0 then
(lambda(xs, n div 2) + lambda(xs, (n div 2) - 1)) / 2
(|λ|(xs, n div 2) + |λ|(xs, (n div 2) - 1)) / 2
else
lambda(xs, n div 2)
|λ|(xs, n div 2)
end if
end tell
else
@ -43,8 +45,7 @@ on median(xs)
end if
end median
-- TEST
-- TEST -----------------------------------------------------------------------
on run
map(median, [¬
@ -56,9 +57,31 @@ on run
--> {missing value, 4, 3.5, 2.1}
end run
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- GENERIC FUNCTIONS
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- partition :: predicate -> List -> (Matches, nonMatches)
-- partition :: (a -> Bool) -> [a] -> ([a], [a])
@ -67,7 +90,7 @@ on partition(f, xs)
set lst to {{}, {}}
repeat with x in xs
set v to contents of x
set end of item ((lambda(v) as integer) + 1) of lst to v
set end of item ((|λ|(v) as integer) + 1) of lst to v
end repeat
end tell
{item 2 of lst, item 1 of lst}
@ -81,27 +104,3 @@ on uncons(xs)
missing value
end if
end uncons
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn

View file

@ -1,31 +1,32 @@
#define system.
#define system'routines.
#define system'math.
#define extensions.
import system'routines.
import system'math.
import extensions.
#class(extension) op
extension op
{
#method median
median
[
#var aSorted := self ascendant.
var aSorted := self ascendant.
#var aLen := aSorted length.
(aLen == 0)
? [ ^ nil. ]
! [
#var aMiddleIndex := aLen / 2.
(aLen mod:2 == 0)
? [ ^ (aSorted@(aMiddleIndex - 1) + aSorted@aMiddleIndex) / 2. ]
! [ ^ aSorted@aMiddleIndex. ].
].
var aLen := aSorted length.
if (aLen == 0)
[ ^ nil ];
[
var aMiddleIndex := aLen / 2.
if (aLen mod:2 == 0)
[ ^ (aSorted[aMiddleIndex - 1] + aSorted[aMiddleIndex]) / 2 ];
[ ^ aSorted[aMiddleIndex] ]
]
]
}
#symbol program =
program =
[
#var a1 := (4.1r, 5.6r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r).
#var a2 := (4.1r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r).
var a1 := (4.1r, 5.6r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r).
var a2 := (4.1r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r).
console writeLine:"median of (":a1:") is ":(a1 median).
console writeLine:"median of (":a2:") is ":(a2 median).
console printLine("median of (",a1,") is ",a1 median).
console printLine("median of (",a2,") is ",a2 median).
console readChar.
].

View file

@ -0,0 +1,3 @@
K = N/2
MEDIAN = FINDELEMENT(K + 1,A,N)
IF (MOD(N,2).EQ.0) MEDIAN = (FINDELEMENT(K,A,N) + MEDIAN)/2

View file

@ -1,11 +1,26 @@
nth (x:xs) n
| k == n = x
| k > n = nth ys n
| otherwise = nth zs $ n - k - 1
where (ys, zs) = partition (< x) xs
k = length ys
import Data.List (partition)
median xs | even n = (nth xs (div n 2) + nth xs (div n 2 - 1)) / 2.0
| otherwise = nth xs (div n 2)
nth :: Ord t => [t] -> Int -> t
nth (x:xs) n
| k == n = x
| k > n = nth ys n
| otherwise = nth zs $ n - k - 1
where
n = length xs
(ys, zs) = partition (< x) xs
k = length ys
medianMay :: (Fractional a, Ord a) => [a] -> Maybe a
medianMay xs
| n < 1 = Nothing
| even n = Just ((nth xs (div n 2) + nth xs (div n 2 - 1)) / 2.0)
| otherwise = Just (nth xs (div n 2))
where
n = length xs
main :: IO ()
main =
mapM_
(printMay . medianMay)
[[], [7], [5, 3, 4], [5, 4, 2, 3], [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]]
where
printMay = maybe (putStrLn "(not defined)") print

View file

@ -1,5 +1,5 @@
// Note: this function modifies the input list
public static double median(List<Double> list){
Collections.sort(list);
return (list.get(list.size() / 2) + list.get((list.size() - 1) / 2)) / 2;
public static double median(List<Double> list) {
Collections.sort(list);
return (list.get(list.size() / 2) + list.get((list.size() - 1) / 2)) / 2;
}

View file

@ -1,10 +1,10 @@
public static double median2(List<Double> list){
PriorityQueue<Double> pq = new PriorityQueue<Double>(list);
int n = list.size();
for (int i = 0; i < (n-1)/2; i++)
pq.poll(); // discard first half
if (n % 2 != 0) // odd length
return pq.poll();
else
return (pq.poll() + pq.poll()) / 2.0;
public static double median2(List<Double> list) {
PriorityQueue<Double> pq = new PriorityQueue<Double>(list);
int n = list.size();
for (int i = 0; i < (n - 1) / 2; i++)
pq.poll(); // discard first half
if (n % 2 != 0) // odd length
return pq.poll();
else
return (pq.poll() + pq.poll()) / 2.0;
}

View file

@ -1,10 +1,15 @@
# Version 5.2
function median2(n)
s = sort(n)
len = length(n)
len%2 == 0 && return (s[ifloor(len/2)+1] + s[ifloor(len/2)])/2
return s[ifloor(len/2)+1]
if len % 2 == 0
return (s[floor(Int, len / 2) + 1] + s[floor(Int, len / 2)]) / 2
else
return s[floor(Int, len / 2) + 1]
end
end
a = [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
b = [4.1, 7.2, 1.7, 9.3, 4.4, 3.2]
@assert median(a) == median2(a)
@assert median(b) == median2(b)
@show a b median2(a) median(a) median2(b) median(b)

View file

@ -1,5 +1,7 @@
fun median(l: List<Double>) = l.sorted().let { (it[it.size / 2] + it[(it.size - 1) / 2]) / 2 }
median(listOf(5.0, 3.0, 4.0)).let { println(it) } // 4
median(listOf(5.0, 4.0, 2.0, 3.0)).let { println(it) } // 3.5
median(listOf(3.0, 4.0, 1.0, -8.4, 7.2, 4.0, 1.0, 1.2)).let { println(it) } // 2.1
fun main(args: Array<String>) {
median(listOf(5.0, 3.0, 4.0)).let { println(it) } // 4
median(listOf(5.0, 4.0, 2.0, 3.0)).let { println(it) } // 3.5
median(listOf(3.0, 4.0, 1.0, -8.4, 7.2, 4.0, 1.0, 1.2)).let { println(it) } // 2.1
}

View file

@ -1,6 +1,6 @@
import algorithm, strutils
proc median(xs): float =
proc median(xs: seq[float]): float =
var ys = xs
sort(ys, system.cmp[float])
0.5 * (ys[ys.high div 2] + ys[ys.len div 2])

View file

@ -0,0 +1,36 @@
call testMedian .array~of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
call testMedian .array~of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, .11)
call testMedian .array~of(10, 20, 30, 40, 50, -100, 4.7, -11e2)
call testMedian .array~new
::routine testMedian
use arg numbers
say "numbers =" numbers~toString("l", ", ")
say "median =" median(numbers)
say
::routine median
use arg numbers
if numbers~isempty then return 0
-- make a copy so the sort does not alter the
-- original set. This also means this will
-- work with lists and queues as well
numbers = numbers~makearray
-- sort and return the middle element
numbers~sortWith(.numbercomparator~new)
size = numbers~items
-- this handles the odd value too
return numbers[size%2 + size//2]
-- a custom comparator that sorts strings as numeric values rather than
-- strings
::class numberComparator subclass comparator
::method compare
use strict arg left, right
-- perform the comparison on the names. By subtracting
-- the two and returning the sign, we give the expected
-- results for the compares
return (left - right)~sign

View file

@ -0,0 +1,4 @@
set obs 100000
gen x=rbeta(0.2,1.3)
quietly summarize x, detail
display r(p50)

View file

@ -0,0 +1,12 @@
program calcmedian, rclass sortpreserve
sort `1'
if mod(_N,2)==0 {
return scalar p50=(`1'[_N/2]+`1'[_N/2+1])/2
}
else {
return scalar p50=`1'[(_N-1)/2]
}
end
calcmedian x
display r(p50)

View file

@ -0,0 +1,7 @@
var quickSelect=Import("quickSelect").qselect;
fcn median(xs){
n:=xs.len();
if (n.isOdd) return(quickSelect(xs,n/2));
( quickSelect(xs,n/2-1) + quickSelect(xs,n/2) )/2;
}

View file

@ -0,0 +1,2 @@
median(T( 5.1, 2.6, 6.2, 8.8, 4.6, 4.1 )); //-->4.85
median(T( 5.1, 2.6, 8.8, 4.6, 4.1 )); //-->4.6