RosettaCodeData/Task/Ranking-methods/AppleScript/ranking-methods-1.applescript

128 lines
4.7 KiB
AppleScript

use AppleScript version "2.3.1" -- Mac OS 10.9 (Mavericks) or later.
use sorter : script ¬
"Custom Iterative Ternary Merge Sort" -- <www.macscripter.net/t/timsort-and-nigsort/71383/3>
(* The ranking methods are implemented as script objects sharing inherited code. *)
script standardRanking
-- Properties and handlers inherited or overridden by the other script objects.
-- The 'reference' is to a value that won't exist until 'results' is set to a list.
-- 'me' and 'my' pertain to the script object using the code at the time.
property results : missing value
property startIndex : 1
property endIndex : a reference to my results's length
property step : 1
property currentRank : missing value
property currentScore : missing value
-- Main handler.
on resultsFrom(theScores)
copy theScores to my results
tell sorter to sort(my results, my startIndex, my endIndex, {comparer:me})
set my currentScore to my results's item (my startIndex)'s score
set my currentRank to my startIndex's contents
repeat with i from (my startIndex) to (my endIndex) by (my step)
my rankResult(i)
end repeat
set r to my results
set my results to missing value
return r
end resultsFrom
-- Comparison handler used by the sort.
on isGreater(a, b)
if (a's score < b's score) then return true
return ((a's score = b's score) and (a's competitor comes after b's competitor))
end isGreater
-- Ranking handler. Inherited by the modifiedRanking script; overridden by the others.
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not currentScore) then
set my currentRank to i
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:my currentRank}
end rankResult
end script
script modifiedRanking
property parent : standardRanking
property startIndex : a reference to my results's length
property endIndex : 1
property step : -1
end script
script denseRanking
property parent : standardRanking
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not my currentScore) then
set my currentRank to (my currentRank) + 1
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:my currentRank}
end rankResult
end script
script ordinalRanking
property parent : standardRanking
on rankResult(i)
set my results's item i to (my results's item i) & {rank:i}
end rankResult
end script
script fractionalRanking
property parent : standardRanking
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not my currentScore) then
-- The average of any run of consecutive integers is that of the first and last.
set average to (i - 1 + (my currentRank)) / 2
repeat with j from (my currentRank) to (i - 1)
set my results's item j's rank to average
end repeat
set my currentRank to i
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:i as real}
end rankResult
end script
-- Task code:
on formatRankings(type, theResults)
set rankings to {type}
repeat with thisResult in theResults
set end of rankings to (thisResult's rank as text) & tab & ¬
thisResult's competitor & " (" & thisResult's score & ")"
end repeat
return join(rankings, linefeed)
end formatRankings
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
local theScores, output
set theScores to {{score:44, competitor:"Solomon"}, {score:42, competitor:"Jason"}, ¬
{score:42, competitor:"Errol"}, {score:41, competitor:"Garry"}, {score:41, competitor:"Bernard"}, ¬
{score:41, competitor:"Barry"}, {score:39, competitor:"Stephen"}}
set output to {¬
formatRankings("Standard ranking:", standardRanking's resultsFrom(theScores)), ¬
formatRankings("Modified ranking:", modifiedRanking's resultsFrom(theScores)), ¬
formatRankings("Dense ranking:", denseRanking's resultsFrom(theScores)), ¬
formatRankings("Ordinal ranking:", ordinalRanking's resultsFrom(theScores)), ¬
formatRankings("Fractional ranking:", fractionalRanking's resultsFrom(theScores)) ¬
}
return join(output, linefeed & linefeed)