Initial data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 72d218235f
commit f23f22d71c
199087 changed files with 3378941 additions and 0 deletions

View file

@ -0,0 +1,48 @@
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use scripting additions
on letterFrequencyinFile(theFile)
-- Read the file as an NSString, letting the system guess the encoding.
set fileText to current application's class "NSString"'s stringWithContentsOfFile:(POSIX path of theFile) ¬
usedEncoding:(missing value) |error|:(missing value)
-- Get the NSString's non-letter delimited runs, lower-cased, as an AppleScript list of texts.
-- The switch to vanilla objects is for speed and the ability to extract 'characters'.
set nonLetterSet to current application's class "NSCharacterSet"'s letterCharacterSet()'s invertedSet()
script o
property letterRuns : (fileText's lowercaseString()'s componentsSeparatedByCharactersInSet:(nonLetterSet)) as list
end script
-- Extract the characters from the runs and add them to an NSCountedSet to have the occurrences of each value counted.
-- No more than 50,000 characters are extracted in one go to avoid slowing or freezing the script.
set countedSet to current application's class "NSCountedSet"'s new()
repeat with i from 1 to (count o's letterRuns)
set thisRun to item i of o's letterRuns
set runLength to (count thisRun)
repeat with i from 1 to runLength by 50000
set j to i + 49999
if (j > runLength) then set j to runLength
tell countedSet to addObjectsFromArray:(characters i thru j of thisRun)
end repeat
end repeat
-- Work through the counted set's contents and build a list of records showing how many of what it received.
set output to {}
repeat with thisLetter in countedSet's allObjects()
set thisCount to (countedSet's countForObject:(thisLetter))
set end of output to {letter:thisLetter, |count|:thisCount}
end repeat
-- Derive an array of dictionaries from the list and sort it on the letters.
set output to current application's class "NSMutableArray"'s arrayWithArray:(output)
set byLetter to current application's class "NSSortDescriptor"'s sortDescriptorWithKey:("letter") ¬
ascending:(true) selector:("localizedStandardCompare:")
tell output to sortUsingDescriptors:({byLetter})
-- Convert back to a list of records and return the result.
return output as list
end letterFrequencyinFile
-- Test with the text file for the "Word frequency" task.
set theFile to ((path to desktop as text) & "135-0.txt") as alias
return letterFrequencyinFile(theFile)

View file

@ -0,0 +1,508 @@
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
------------- CHARACTER COUNTS FROM FILE PATH -------------
-- charCounts :: FilePath -> Either String [(Char, Int)]
on charCounts(fp)
script go
on |λ|(s)
|Right|(sortBy(flip(comparing(my snd)), ¬
map(fanArrow(my head, my |length|), ¬
groupBy(my eq, sort(characters of s)))))
end |λ|
end script
bindLR(readFileLR(fp), go)
end charCounts
-------------------------- TEST ---------------------------
on run
set intColumns to 4
either(identity, frequencyTabulation(intColumns), ¬
charCounts("~/Code/charCount/readme.txt"))
end run
------------------------- DISPLAY -------------------------
-- frequencyTabulation :: Int -> [(Char, Int)] -> String
on frequencyTabulation(intCols)
script
on |λ|(xs)
set w to length of (snd(item 1 of xs) as string)
script go
on |λ|(x)
justifyRight(5, " ", showChar(fst(x))) & ¬
" -> " & justifyRight(w, " ", snd(x) as string)
end |λ|
end script
showColumns(intCols, map(go, xs))
end |λ|
end script
end frequencyTabulation
-------------------- GENERIC FUNCTIONS --------------------
-- Left :: a -> Either a b
on |Left|(x)
{type:"Either", |Left|:x, |Right|:missing value}
end |Left|
-- Right :: b -> Either a b
on |Right|(x)
{type:"Either", |Left|:missing value, |Right|:x}
end |Right|
-- Tuple (,) :: a -> b -> (a, b)
on Tuple(a, b)
-- Constructor for a pair of values, possibly of two different types.
{type:"Tuple", |1|:a, |2|:b, length:2}
end Tuple
-- Absolute value.
-- abs :: Num -> Num
on abs(x)
if 0 > x then
-x
else
x
end if
end abs
-- bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
on bindLR(m, mf)
if missing value is not |Left| of m then
m
else
mReturn(mf)'s |λ|(|Right| of m)
end if
end bindLR
-- chunksOf :: Int -> [a] -> [[a]]
on chunksOf(n, xs)
set lng to length of xs
script go
on |λ|(a, i)
set x to (i + n) - 1
if x lng then
a & {items i thru -1 of xs}
else
a & {items i thru x of xs}
end if
end |λ|
end script
foldl(go, {}, enumFromThenTo(1, 1 + n, lng))
end chunksOf
-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
script
on |λ|(a, b)
tell mReturn(f)
set fa to |λ|(a)
set fb to |λ|(b)
if fa < fb then
-1
else if fa > fb then
1
else
0
end if
end tell
end |λ|
end script
end comparing
-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
set lng to length of xs
set acc to {}
tell mReturn(f)
repeat with i from 1 to lng
set acc to acc & (|λ|(item i of xs, i, xs))
end repeat
end tell
return acc
end concatMap
-- either :: (a -> c) -> (b -> c) -> Either a b -> c
on either(lf, rf, e)
if missing value is |Left| of e then
tell mReturn(rf) to |λ|(|Right| of e)
else
tell mReturn(lf) to |λ|(|Left| of e)
end if
end either
-- enumFromThenTo :: Int -> Int -> Int -> [Int]
on enumFromThenTo(x1, x2, y)
set xs to {}
set gap to x2 - x1
set d to max(1, abs(gap)) * (signum(gap))
repeat with i from x1 to y by d
set end of xs to i
end repeat
return xs
end enumFromThenTo
-- eq (==) :: Eq a => a -> a -> Bool
on eq(a, b)
a = b
end eq
-- Compose a function from a simple value to a tuple of
-- the separate outputs of two different functions
-- fanArrow (&&&) :: (a -> b) -> (a -> c) -> (a -> (b, c))
on fanArrow(f, g)
script
on |λ|(x)
Tuple(mReturn(f)'s |λ|(x), mReturn(g)'s |λ|(x))
end |λ|
end script
end fanArrow
-- flip :: (a -> b -> c) -> b -> a -> c
on flip(f)
script
property g : mReturn(f)
on |λ|(x, y)
g's |λ|(y, x)
end |λ|
end script
end flip
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- fst :: (a, b) -> a
on fst(tpl)
if class of tpl is record then
|1| of tpl
else
item 1 of tpl
end if
end fst
-- Typical usage: groupBy(on(eq, f), xs)
-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
set mf to mReturn(f)
script enGroup
on |λ|(a, x)
if length of (active of a) > 0 then
set h to item 1 of active of a
else
set h to missing value
end if
if h is not missing value and mf's |λ|(h, x) then
{active:(active of a) & {x}, sofar:sofar of a}
else
{active:{x}, sofar:(sofar of a) & {active of a}}
end if
end |λ|
end script
if length of xs > 0 then
set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, rest of xs)
if length of (active of dct) > 0 then
sofar of dct & {active of dct}
else
sofar of dct
end if
else
{}
end if
end groupBy
-- head :: [a] -> a
on head(xs)
if xs = {} then
missing value
else
item 1 of xs
end if
end head
-- identity :: a -> a
on identity(x)
-- The argument unchanged.
x
end identity
-- justifyRight :: Int -> Char -> String -> String
on justifyRight(n, cFiller, strText)
if n > length of strText then
text -n thru -1 of ((replicate(n, cFiller) as text) & strText)
else
strText
end if
end justifyRight
-- length :: [a] -> Int
on |length|(xs)
set c to class of xs
if list is c or string is c then
length of xs
else
(2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
end if
end |length|
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of 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
-- max :: Ord a => a -> a -> a
on max(x, y)
if x > y then
x
else
y
end if
end max
-- maximum :: Ord a => [a] -> a
on maximum(xs)
script
on |λ|(a, b)
if a is missing value or b > a then
b
else
a
end if
end |λ|
end script
foldl(result, missing value, xs)
end maximum
-- partition :: (a -> Bool) -> [a] -> ([a], [a])
on partition(f, xs)
tell mReturn(f)
set ys to {}
set zs to {}
repeat with x in xs
set v to contents of x
if |λ|(v) then
set end of ys to v
else
set end of zs to v
end if
end repeat
end tell
Tuple(ys, zs)
end partition
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- readFileLR :: FilePath -> Either String IO String
on readFileLR(strPath)
set ca to current application
set e to reference
set {s, e} to (ca's NSString's ¬
stringWithContentsOfFile:((ca's NSString's ¬
stringWithString:strPath)'s ¬
stringByStandardizingPath) ¬
encoding:(ca's NSUTF8StringEncoding) |error|:(e))
if s is missing value then
|Left|((localizedDescription of e) as string)
else
|Right|(s as string)
end if
end readFileLR
-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length
-- replicate :: Int -> a -> [a]
on replicate(n, a)
set out to {}
if 1 > n then return out
set dbl to {a}
repeat while (1 < n)
if 0 < (n mod 2) then set out to out & dbl
set n to (n div 2)
set dbl to (dbl & dbl)
end repeat
return out & dbl
end replicate
-- showChar :: Char -> String
on showChar(c)
if space is c then
"SPACE"
else if tab is c then
"TAB"
else if linefeed is c then
"LF"
else
c
end if
end showChar
-- showColumns :: Int -> [String] -> String
on showColumns(n, xs)
set w to maximum(map(my |length|, xs))
set m to (length of xs) div n
unlines(map(my unwords, ¬
transpose(chunksOf(m, xs))))
end showColumns
-- signum :: Num -> Num
on signum(x)
if x < 0 then
-1
else if x = 0 then
0
else
1
end if
end signum
-- snd :: (a, b) -> b
on snd(tpl)
if class of tpl is record then
|2| of tpl
else
item 2 of tpl
end if
end snd
-- sort :: Ord a => [a] -> [a]
on sort(xs)
((current application's NSArray's arrayWithArray:xs)'s ¬
sortedArrayUsingSelector:"compare:") as list
end sort
-- Enough for small scale sorts.
-- Use instead sortOn (Ord b => (a -> b) -> [a] -> [a])
-- which is equivalent to the more flexible sortBy(comparing(f), xs)
-- and uses a much faster ObjC NSArray sort method
-- sortBy :: (a -> a -> Ordering) -> [a] -> [a]
on sortBy(f, xs)
if length of xs > 1 then
set h to item 1 of xs
set f to mReturn(f)
script
on |λ|(x)
f's |λ|(x, h) 0
end |λ|
end script
set lessMore to partition(result, rest of xs)
sortBy(f, |1| of lessMore) & {h} & ¬
sortBy(f, |2| of lessMore)
else
xs
end if
end sortBy
-- transpose :: [[String]] -> [[String]]
on transpose(rows)
script cols
on |λ|(_, iCol)
script cell
on |λ|(row)
if iCol > length of row then
""
else
item iCol of row
end if
end |λ|
end script
concatMap(cell, rows)
end |λ|
end script
map(cols, item 1 of rows)
end transpose
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set str to xs as text
set my text item delimiters to dlm
str
end unlines
-- unwords :: [String] -> String
on unwords(xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, space}
set s to xs as text
set my text item delimiters to dlm
return s
end unwords

View file

@ -0,0 +1,306 @@
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
------ CASE AND ACCENT-INSENSITIVE FREQUENCIES OF A-Z ----
-- romanLetterFrequencies :: FilePath -> Maybe [(Char, Int)]
on romanLetterFrequencies(fp)
if doesFileExist(fp) then
set patterns to enumFromToChar("a", "z")
set counts to ap(map(my matchCount, patterns), ¬
{readFile(fp)'s ¬
decomposedStringWithCanonicalMapping's ¬
lowercaseString})
sortBy(flip(comparing(my snd)))'s ¬
|λ|(zip(patterns, counts))
else
missing value
end if
end romanLetterFrequencies
--------------------------- TEST -------------------------
on run
set fpText to scriptFolder() & "miserables.txt"
set azFrequencies to romanLetterFrequencies(fpText)
if missing value is not azFrequencies then
script arrow
on |λ|(kv)
set {k, v} to kv
unwords({k, "->", v})
end |λ|
end script
unlines(map(arrow, azFrequencies))
else
display dialog "Text file not found in this script's folder:" & ¬
linefeed & tab & fpText
end if
end run
------------------------- GENERIC ------------------------
-- Tuple (,) :: a -> b -> (a, b)
on Tuple(a, b)
-- Constructor for a pair of values, possibly of two different types.
{a, b}
end Tuple
-- ap (<*>) :: [(a -> b)] -> [a] -> [b]
on ap(fs, xs)
-- e.g. [(*2),(/2), sqrt] <*> [1,2,3]
-- --> ap([dbl, hlf, root], [1, 2, 3])
-- --> [2,4,6,0.5,1,1.5,1,1.4142135623730951,1.7320508075688772]
-- Each member of a list of functions applied to
-- each of a list of arguments, deriving a list of new values
set lst to {}
repeat with f in fs
tell mReturn(contents of f)
repeat with x in xs
set end of lst to |λ|(contents of x)
end repeat
end tell
end repeat
return lst
end ap
-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
script
on |λ|(a, b)
tell mReturn(f)
set fa to |λ|(a)
set fb to |λ|(b)
if fa < fb then
-1
else if fa > fb then
1
else
0
end if
end tell
end |λ|
end script
end comparing
-- doesFileExist :: FilePath -> IO Bool
on doesFileExist(strPath)
set ca to current application
set oPath to (ca's NSString's stringWithString:strPath)'s ¬
stringByStandardizingPath
set {bln, int} to (ca's NSFileManager's defaultManager's ¬
fileExistsAtPath:oPath isDirectory:(reference))
bln and (int 1)
end doesFileExist
-- enumFromToChar :: Char -> Char -> [Char]
on enumFromToChar(m, n)
set {intM, intN} to {id of m, id of n}
if intM intN then
set xs to {}
repeat with i from intM to intN
set end of xs to character id i
end repeat
return xs
else
{}
end if
end enumFromToChar
-- flip :: (a -> b -> c) -> b -> a -> c
on flip(f)
script
property g : mReturn(f)
on |λ|(x, y)
g's |λ|(y, x)
end |λ|
end script
end flip
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of 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
-- matchCount :: String -> NSString -> Int
on matchCount(regexString)
-- A count of the matches for a regular expression
-- in a given NSString
script
on |λ|(s)
set ca to current application
((ca's NSRegularExpression's ¬
regularExpressionWithPattern:regexString ¬
options:(ca's NSRegularExpressionAnchorsMatchLines) ¬
|error|:(missing value))'s ¬
numberOfMatchesInString:s ¬
options:0 ¬
range:{location:0, |length|:s's |length|()}) as integer
end |λ|
end script
end matchCount
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- partition :: (a -> Bool) -> [a] -> ([a], [a])
on partition(f, xs)
tell mReturn(f)
set ys to {}
set zs to {}
repeat with x in xs
set v to contents of x
if |λ|(v) then
set end of ys to v
else
set end of zs to v
end if
end repeat
end tell
{ys, zs}
end partition
-- readFile :: FilePath -> IO NSString
on readFile(strPath)
set ca to current application
set e to reference
set {s, e} to (ca's NSString's ¬
stringWithContentsOfFile:((ca's NSString's ¬
stringWithString:strPath)'s ¬
stringByStandardizingPath) ¬
encoding:(ca's NSUTF8StringEncoding) |error|:(e))
if missing value is e then
s
else
(localizedDescription of e) as string
end if
end readFile
-- scriptFolder :: () -> IO FilePath
on scriptFolder()
-- The path of the folder containing this script
tell application "Finder" to ¬
POSIX path of ((container of (path to me)) as alias)
end scriptFolder
-- snd :: (a, b) -> b
on snd(tpl)
item 2 of tpl
end snd
-- sortBy :: (a -> a -> Ordering) -> [a] -> [a]
on sortBy(f)
-- Enough for small scale sorts.
-- The NSArray sort method in the Foundation library
-- gives better permormance for longer lists.
script go
on |λ|(xs)
if length of xs > 1 then
set h to item 1 of xs
set f to mReturn(f)
script
on |λ|(x)
f's |λ|(x, h) 0
end |λ|
end script
set lessMore to partition(result, rest of xs)
|λ|(item 1 of lessMore) & {h} & ¬
|λ|(item 2 of lessMore)
else
xs
end if
end |λ|
end script
end sortBy
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
-- unwords :: [String] -> String
on unwords(xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, space}
set s to xs as text
set my text item delimiters to dlm
return s
end unwords
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
zipWith(Tuple, xs, ys)
end zip
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
if 1 > lng then
return {}
else
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end if
end zipWith