Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,44 @@
set alist to {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}
set med to medi(alist)
on medi(alist)
set temp to {}
set lcount to count alist
if lcount is equal to 2 then
return ((item 1 of alist) + (item 2 of alist)) / 2
else if lcount is less than 2 then
return item 1 of alist
else --if lcount is greater than 2
set min to findmin(alist)
set max to findmax(alist)
repeat with x from 1 to lcount
if x is not equal to min and x is not equal to max then set end of temp to item x of alist
end repeat
set med to medi(temp)
end if
return med
end medi
on findmin(alist)
set min to 1
set alength to count every item of alist
repeat with x from 1 to alength
if item x of alist is less than item min of alist then set min to x
end repeat
return min
end findmin
on findmax(alist)
set max to 1
set alength to count every item of alist
repeat with x from 1 to alength
if item x of alist is greater than item max of alist then set max to x
end repeat
return max
end findmax

View file

@ -0,0 +1 @@
4.5

View file

@ -0,0 +1,106 @@
-- MEDIAN ---------------------------------------------------------------------
-- median :: [Num] -> Num
on median(xs)
-- nth :: [Num] -> Int -> Maybe Num
script nth
on |λ|(xxs, n)
if length of xxs > 0 then
set {x, xs} to uncons(xxs)
script belowX
on |λ|(y)
y < x
end |λ|
end script
set {ys, zs} to partition(belowX, xs)
set k to length of ys
if k = n then
x
else
if k > n then
|λ|(ys, n)
else
|λ|(zs, n - k - 1)
end if
end if
else
missing value
end if
end |λ|
end script
set n to length of xs
if n > 0 then
tell nth
if n mod 2 = 0 then
(|λ|(xs, n div 2) + |λ|(xs, (n div 2) - 1)) / 2
else
|λ|(xs, n div 2)
end if
end tell
else
missing value
end if
end median
-- TEST -----------------------------------------------------------------------
on run
map(median, [¬
[], ¬
[5, 3, 4], ¬
[5, 4, 2, 3], ¬
[3, 4, 1, -8.4, 7.2, 4, 1, 1.2]])
--> {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
-- 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])
on partition(f, xs)
tell mReturn(f)
set lst to {{}, {}}
repeat with x in xs
set v to contents of x
set end of item ((|λ|(v) as integer) + 1) of lst to v
end repeat
end tell
{item 2 of lst, item 1 of lst}
end partition
-- uncons :: [a] -> Maybe (a, [a])
on uncons(xs)
if length of xs > 0 then
{item 1 of xs, rest of xs}
else
missing value
end if
end uncons

View file

@ -0,0 +1 @@
{missing value, 4, 3.5, 2.1}

View file

@ -0,0 +1,73 @@
-- Return the median value of items l thru r of a list of numbers.
on getMedian(theList, l, r)
if (theList is {}) then return theList
script o
property lst : theList's items l thru r -- Copy of the range to be searched.
end script
set rangeLength to (r - l + 1)
set m to (rangeLength + 1) div 2 -- Central position in the range copy, or the leftmost of two.
set {l, r} to {1, rangeLength} -- Outer partition indices.
set previousR to r -- Reminder of previous r.
repeat -- quickselect repeat
set pivot to o's lst's item ((l + r) div 2)
set i to l
set j to r
repeat until (i > j)
set lv to o's lst's item i
repeat while (lv < pivot)
set i to i + 1
set lv to o's lst's item i
end repeat
set rv to o's lst's item j
repeat while (rv > pivot)
set j to j - 1
set rv to o's lst's item j
end repeat
if (i > j) then
else
set o's lst's item i to rv
set o's lst's item j to lv
set i to i + 1
set j to j - 1
end if
end repeat
-- If i and j have crossed at m, item m's the median value.
-- Otherwise reset to partition the partition containing m.
if (j < m) then
if (i > m) then exit repeat
set l to i
else
set previousR to r
set r to j
end if
end repeat
set median to item m of o's lst
-- If the range has an even number of items, find the lowest value to the right of m and average it
-- with the median just obtained. We only need to search to the end of the range just partitioned —
-- unless that's where m is, in which case to end of the most recent extent beyond that (if any).
if (rangeLength mod 2 is 0) then
set median2 to item i of o's lst
if (r = m) then set r to previousR
repeat with i from (i + 1) to r
set v to item i of o's lst
if (v < median2) then set median2 to v
end repeat
set median to (median + median2) / 2
end if
return median
end getMedian
-- Demo:
local testList
set testList to {}
repeat with i from 1 to 8
set end of testList to (random number 500) / 5
end repeat
return {|numbers|:testList, median:getMedian(testList, 1, (count testList))}

View file

@ -0,0 +1,62 @@
-- Based on the heap sort algorithm ny J.W.J. Williams.
on getMedian(theList, l, r)
script o
property lst : theList's items l thru r -- Copy of the range to be searched.
-- Sift a value down into the heap from a given root node.
on siftDown(siftV, root, endOfHeap)
set child to root * 2
repeat until (child comes after endOfHeap)
set childV to item child of my lst
if (child comes before endOfHeap) then
set child2 to child + 1
set child2V to item child2 of my lst
if (child2V > childV) then
set child to child2
set childV to child2V
end if
end if
if (childV > siftV) then
set item root of my lst to childV
set root to child
set child to root * 2
else
exit repeat
end if
end repeat
set item root of my lst to siftV
end siftDown
end script
set r to (r - l + 1)
-- Arrange the sort range into a "heap" with its "top" at the leftmost position.
repeat with i from (r + 1) div 2 to 1 by -1
tell o to siftDown(item i of its lst, i, r)
end repeat
-- Work the heap as if extracting the values that would come after the median when sorted.
repeat with endOfHeap from r to (r - (r + 1) div 2 + 2) by -1
tell o to siftDown(item endOfHeap of its lst, 1, endOfHeap - 1)
end repeat
-- Extract the median itself, now at the top of the heap.
set median to beginning of o's lst
-- If the range has an even number of items, also get the value that would come before the median
-- just obtained. By now it's either the second or third item in the heap, so no need to sift for it.
-- Get the average if it and the median.
if (r mod 2 is 0) then
set median2 to item 2 of o's lst
if ((r > 2) and (item 3 of o's lst > median2)) then set median2 to item 3 of o's lst
set median to (median + median2) / 2
end if
return median
end getMedian
-- Demo:
local testList
set testList to {}
repeat with i from 1 to 8
set end of testList to (random number 500) / 5
end repeat
return {|numbers|:testList, median:getMedian(testList, 1, (count testList))}

View file

@ -0,0 +1 @@
{|numbers|:{28.0, 75.6, 21.4, 51.8, 79.6, 25.0, 95.4, 31.2}, median:41.5}