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

@ -1,6 +1,8 @@
use framework "Foundation"
use scripting additions
-- BOXING THE COMPASS --------------------------------------------------------
property plstLangs : [{|name|:"English"} & ¬
{expansions:{N:"north", S:"south", E:"east", W:"west", b:" by "}} & ¬
{|N|:"N", |NNNE|:"NbE", |NNE|:"N-NE", |NNENE|:"NEbN", |NE|:"NE", |NENEE|:"NEbE"} & ¬
@ -34,14 +36,15 @@ on compassKeys(intDepth)
-- Necessity drives recursive subdivision of broader directions, shrinking
-- boxes down to a workable level of precision:
script subdivision
on lambda(lstCompass, N)
on |λ|(lstCompass, N)
if N 1 then
lstCompass
else
script subKeys
on lambda(a, x, i, xs)
on |λ|(a, x, i, xs)
-- Borders between N and S engender E and W.
-- further subdivisions (boxes) concatenate their two parent keys.
-- further subdivisions (boxes)
-- concatenate their two parent keys.
if i > 1 then
cond(N = intDepth, ¬
a & {cond(x = "N", "W", "E")} & x, ¬
@ -49,21 +52,22 @@ on compassKeys(intDepth)
else
a & x
end if
end lambda
end |λ|
end script
lambda(foldl(subKeys, {}, lstCompass), N - 1)
|λ|(foldl(subKeys, {}, lstCompass), N - 1)
end if
end lambda
end |λ|
end script
tell subdivision to items 1 thru -2 of lambda(urCompass, intDepth)
tell subdivision to items 1 thru -2 of |λ|(urCompass, intDepth)
end compassKeys
-- pointIndex :: Int -> Num -> String
on pointIndex(power, degrees)
set nBoxes to 2 ^ power
set i to round (degrees + (360 / (nBoxes * 2))) mod 360 * nBoxes / 360 rounding up
set i to round (degrees + (360 / (nBoxes * 2))) ¬
mod 360 * nBoxes / 360 rounding up
cond(i > 0, i, 1)
end pointIndex
@ -72,7 +76,7 @@ on pointNames(precision, iBox)
set k to item iBox of compassKeys(precision)
script translation
on lambda(recLang)
on |λ|(recLang)
set maybeTrans to keyValue(recLang, k)
set strBrief to cond(maybeTrans is missing value, k, maybeTrans)
@ -80,10 +84,10 @@ on pointNames(precision, iBox)
if recExpand is not missing value then
script expand
on lambda(c)
on |λ|(c)
set t to keyValue(recExpand, c)
cond(t is not missing value, t, c)
end lambda
end |λ|
end script
set strName to (intercalate(cond(precision > 5, " ", ""), ¬
map(expand, characters of strBrief)))
@ -91,7 +95,7 @@ on pointNames(precision, iBox)
else
strBrief
end if
end lambda
end |λ|
end script
map(translation, plstLangs)
@ -99,15 +103,7 @@ end pointNames
-- maxLen :: [String] -> Int
on maxLen(xs)
-- compareByLength = (String, String) -> (-1 | 0 | 1)
script compareByLength
on lambda(a, b)
set {intA, intB} to {length of a, length of b}
cond(intA < intB, -1, cond(intA > intB, 1, 0))
end lambda
end script
length of maximumBy(compareByLength, xs)
length of maximumBy(comparing(my |length|), xs)
end maxLen
-- alignRight :: Int -> String -> String
@ -136,43 +132,43 @@ on compassTable(precision, xs)
set join to curry(my intercalate)
-- INDEX COLUMN
set lstIndex to map(lambda(precision) of curry(pointIndex), xs)
set lstIndex to map(|λ|(precision) of curry(pointIndex), xs)
set lstStrIndex to map(show, lstIndex)
set nIndexWidth to maxLen(lstStrIndex)
set colIndex to map(lambda(nIndexWidth + intPad) of rightAligned, lstStrIndex)
set colIndex to map(|λ|(nIndexWidth + intPad) of rightAligned, lstStrIndex)
-- ANGLES COLUMN
script degreeFormat
on lambda(x)
on |λ|(x)
set {c, m} to splitOn(".", x as string)
c & "." & (text 1 thru 2 of (m & "0")) & "°"
end lambda
end |λ|
end script
set lstAngles to map(degreeFormat, xs)
set nAngleWidth to maxLen(lstAngles) + intPad
set colAngles to map(lambda(nAngleWidth) of rightAligned, lstAngles)
set colAngles to map(|λ|(nAngleWidth) of rightAligned, lstAngles)
-- NAMES COLUMNS
script precisionNames
on lambda(iBox)
on |λ|(iBox)
pointNames(precision, iBox)
end lambda
end |λ|
end script
set lstTrans to transpose(map(precisionNames, lstIndex))
set lstTransWidths to map(maxLen, lstTrans)
script spacedNames
on lambda(lstLang, i)
map(lambda((item i of lstTransWidths) + 2) of leftAligned, lstLang)
end lambda
on |λ|(lstLang, i)
map(|λ|((item i of lstTransWidths) + 2) of leftAligned, lstLang)
end |λ|
end script
set colsTrans to map(spacedNames, lstTrans)
-- TABLE
intercalate(linefeed, ¬
map(lambda("") of join, ¬
map(|λ|("") of join, ¬
transpose({colIndex} & {colAngles} & ¬
{replicate(length of lstIndex, " ")} & colsTrans)))
end if
@ -180,9 +176,8 @@ end compassTable
-- TEST
-- TEST ----------------------------------------------------------------------
on run
set xs to [0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, ¬
84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, ¬
185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, ¬
@ -196,23 +191,52 @@ on run
-- to substitute for missing names for very finely divided boxes.
compassTable(5, xs) -- // 2^5 -> 32 boxes
end run
-- GENERIC FUNCTIONS
-- 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 lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
set mf to mReturn(f)
script
on |λ|(a, b)
set x to mf's |λ|(a)
set y to mf's |λ|(b)
if x < y then
-1
else
if x > y then
1
else
0
end if
end if
end |λ|
end script
end comparing
-- cond :: Bool -> a -> a -> a
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- curry :: (Script|Handler) -> Script
on curry(f)
script
on |λ|(a)
script
on |λ|(b)
|λ|(a, b) of mReturn(f)
end |λ|
end script
end |λ|
end script
end curry
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
@ -220,66 +244,12 @@ on foldl(f, startValue, xs)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to lambda(v, item i of xs, i, xs)
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- curry :: (Script|Handler) -> Script
on curry(f)
script
on lambda(a)
script
on lambda(b)
lambda(a, b) of mReturn(f)
end lambda
end script
end lambda
end script
end curry
-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on lambda(_, iCol)
script row
on lambda(xs)
item iCol of xs
end lambda
end script
map(row, xss)
end lambda
end script
map(column, item 1 of xss)
end transpose
-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
set cmp to mReturn(f)
script max
on lambda(a, b)
if a is missing value or cmp's lambda(a, b) < 0 then
b
else
a
end if
end lambda
end script
foldl(max, missing value, xs)
end maximumBy
-- splitOn :: Text -> Text -> [Text]
on splitOn(strDelim, strMain)
set {dlm, my text item delimiters} to {my text item delimiters, strDelim}
set xs to text items of strMain
set my text item delimiters to dlm
return xs
end splitOn
-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
@ -288,39 +258,6 @@ on intercalate(strText, lstText)
return strJoined
end intercalate
-- keyValue :: Record -> String -> Maybe String
on keyValue(rec, strKey)
set ca to current application
set v to (ca's NSDictionary's dictionaryWithDictionary:rec)'s objectForKey:strKey
if v is not missing value then
item 1 of ((ca's NSArray's arrayWithObject:v) as list)
else
missing value
end if
end keyValue
-- toLower :: String -> String
on toLower(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
lowercaseStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toLower
-- toUpper :: String -> String
on toUpper(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
uppercaseStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toUpper
-- toTitle :: String -> String
on toTitle(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
capitalizedStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toTitle
-- justifyLeft :: Int -> Char -> Text -> Text
on justifyLeft(N, cFiller, strText)
if N > length of strText then
@ -339,6 +276,62 @@ on justifyRight(N, cFiller, strText)
end if
end justifyRight
-- keyValue :: Record -> String -> Maybe String
on keyValue(rec, strKey)
set ca to current application
set v to (ca's NSDictionary's dictionaryWithDictionary:rec)'s objectForKey:strKey
if v is not missing value then
item 1 of ((ca's NSArray's arrayWithObject:v) as list)
else
missing value
end if
end keyValue
-- length :: [a] -> Int
on |length|(xs)
length of xs
end |length|
-- 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
-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
set cmp to mReturn(f)
script max
on |λ|(a, b)
if a is missing value or cmp's |λ|(a, b) < 0 then
b
else
a
end if
end |λ|
end script
foldl(max, missing value, xs)
end maximumBy
-- 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
-- replicate :: Int -> a -> [a]
on replicate(N, a)
set out to {}
@ -353,23 +346,48 @@ on replicate(N, a)
return out & dbl
end replicate
-- 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
-- splitOn :: Text -> Text -> [Text]
on splitOn(strDelim, strMain)
set {dlm, my text item delimiters} to {my text item delimiters, strDelim}
set xs to text items of strMain
set my text item delimiters to dlm
return xs
end splitOn
-- cond :: Bool -> a -> a -> a
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on |λ|(_, iCol)
script row
on |λ|(xs)
item iCol of xs
end |λ|
end script
map(row, xss)
end |λ|
end script
map(column, item 1 of xss)
end transpose
-- toLower :: String -> String
on toLower(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
lowercaseStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toLower
-- toTitle :: String -> String
on toTitle(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
capitalizedStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toTitle
-- toUpper :: String -> String
on toUpper(str)
set ca to current application
((ca's NSString's stringWithString:(str))'s ¬
uppercaseStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toUpper

View file

@ -8,10 +8,11 @@ defmodule Box do
end)
|> Enum.with_index
|> Enum.map(fn {s, i} -> {i+1, String.capitalize(s)} end)
|> Map.new
end
def compass do
header = Enum.into(head, Map.new)
header = head()
angles = Enum.map(0..32, fn i -> i * 11.25 + elem({0, 5.62, -5.62}, rem(i, 3)) end)
Enum.each(angles, fn degrees ->
index = rem(round(32 * degrees / 360), 32) + 1

View file

@ -0,0 +1,19 @@
Public Sub Main()
Dim fDeg As Float[] = [0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, 84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, 185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, 270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, 354.38]
Dim cHeading As Collection = ["N": "North", "S": "South", "W": "West", "E": "East", "b": "by"]
Dim sHeading As String[] = ["N", "NbE", "NNE", "NEbE", "NE", "NEbE", "ENE", "EbN", "E", "EbS", "ESE", "SEbE", "SE", "SEbS", "SSE", "SbE", "S", "SbW", "SSW", "SWbS", "SW", "SWbW", "WSW", "WbS", "W", "WbN", "WNW", "NWbW", "NW", "NWbN", "NNW", "NbW"]
Dim siLoop As Short
Dim sDirection As String
Dim fCount, fTemp As Float
For Each fCount In fDeg
fTemp = Round(fCount / 11.25)
If fTemp = 32 Then fTemp = 0
For siLoop = 0 To Len(sHeading[fTemp])
sDirection &= cHeading[Mid(sHeading[fTemp], siLoop + 1, 1)] & " "
Next
Print "Index=" & Format(fTemp + 1, "#0") & " " & Format(Str(fCount), "##0.00") & " degrees = " & sDirection
sDirection = ""
Next
End

View file

@ -1,25 +1,70 @@
import Data.Char
import Data.Maybe
import Text.Printf
import Data.Char (toUpper)
dirs = ["N", "NbE", "N-NE", "NEbN", "NE", "NEbE", "E-NE", "EbN",
"E", "EbS", "E-SE", "SEbE", "SE", "SEbS", "S-SE", "SbE",
"S", "SbW", "S-SW", "SWbS", "SW", "SWbW", "W-SW", "WbS",
"W", "WbN", "W-NW", "NWbW", "NW", "NWbN", "N-NW", "NbW"]
import Data.Maybe (fromMaybe)
-- Given an index between 0 and 31 return the corresponding compass point name.
import Text.Printf (PrintfType, printf)
dirs :: [String]
dirs =
[ "N"
, "NbE"
, "N-NE"
, "NEbN"
, "NE"
, "NEbE"
, "E-NE"
, "EbN"
, "E"
, "EbS"
, "E-SE"
, "SEbE"
, "SE"
, "SEbS"
, "S-SE"
, "SbE"
, "S"
, "SbW"
, "S-SW"
, "SWbS"
, "SW"
, "SWbW"
, "W-SW"
, "WbS"
, "W"
, "WbN"
, "W-NW"
, "NWbW"
, "NW"
, "NWbN"
, "N-NW"
, "NbW"
]
-- Index between 0 and 31 -> the corresponding compass point name.
pointName :: Int -> String
pointName = capitalize . concatMap (fromMaybe "?" . fromChar) . (dirs !!)
where fromChar c = lookup c [('N', "north"), ('S', "south"), ('E', "east"),
('W', "west"), ('b', " by "), ('-', "-")]
capitalize (c:cs) = toUpper c : cs
where
fromChar c =
lookup
c
[ ('N', "north")
, ('S', "south")
, ('E', "east")
, ('W', "west")
, ('b', " by ")
, ('-', "-")
]
capitalize (c:cs) = toUpper c : cs
-- Convert degrees to a compass point index between 0 and 31.
pointIndex d = (round (d*1000) + 5625) `mod` 360000 `div` 11250
-- Degrees -> compass point index between 0 and 31.
pointIndex :: Double -> Int
pointIndex d = (round (d * 1000) + 5625) `mod` 360000 `div` 11250
printPointName d = let deg = read d :: Double
idx = pointIndex deg
in printf "%2d %-18s %6.2f°\n" (idx+1) (pointName idx) deg
printPointName :: PrintfType t => String -> t
printPointName d =
let deg = read d :: Double
idx = pointIndex deg
in printf "%2d %-18s %6.2f°\n" (idx + 1) (pointName idx) deg
main = do
input <- getContents
mapM_ printPointName $ lines input
main :: IO ()
main = mapM_ (printPointName . show) [0 .. 31]

View file

@ -0,0 +1,26 @@
# v0.6
function degree2compasspoint(d::Float64)::String
const MAJORS = ("north", "east", "south", "ovest", "north", "east", "south", "ovest")
const QUART1 = ("N", "N by E", "N-NE", "NE by N", "NE", "NE by E", "E-NE", "E by N")
const QUART2 = tuple((replace(p, "NE", "EN") for p in QUART1)...)
d = (d % 360) + 360/64
majorindex, minor = divrem(d, 90)
minorindex = div(minor * 4, 45)
majorindex += 1
minorindex += 1
p1, p2 = MAJORS[majorindex:majorindex+1]
if p1 in ("north", "south"); q = QUART1
else q = QUART1 end
return titlecase(replace(replace(q[minorindex], 'N', p1), 'E', p2))
end
for i in 0:32
d = i * 11.25
m = i % 3
if m == 1; d += 5.62 end
if m == 2; d -= 5.62 end
n = i % 32 + 1
@printf("%2i %-17s %10.2f°\n", n, degree2compasspoint(d), d)
end

View file

@ -0,0 +1,37 @@
// version 1.1.2
fun expand(cp: String): String {
val sb = StringBuilder()
for (c in cp) {
sb.append(when (c) {
'N' -> "north"
'E' -> "east"
'S' -> "south"
'W' -> "west"
'b' -> " by "
else -> "-"
})
}
return sb.toString().capitalize()
}
fun main(args: Array<String>) {
val cp = arrayOf(
"N", "NbE", "N-NE", "NEbN", "NE", "NEbE", "E-NE", "EbN",
"E", "EbS", "E-SE", "SEbE", "SE", "SEbS", "S-SE", "SbE",
"S", "SbW", "S-SW", "SWbS", "SW", "SWbW", "W-SW", "WbS",
"W", "WbN", "W-NW", "NWbW", "NW", "NWbN", "N-NW", "NbW"
)
println("Index Degrees Compass point")
println("----- ------- -------------")
val f = "%2d %6.2f %s"
for (i in 0..32) {
val index = i % 32
var heading = i * 11.25
when (i % 3) {
1 -> heading += 5.62
2 -> heading -= 5.62
}
println(f.format(index + 1, heading, expand(cp[index])))
}
}

View file

@ -0,0 +1,36 @@
/*Boxing The Compass by rbytes December 2017*/
GET SCREEN SIZE sw,sh
OPTION BASE 1
DIM point$(32,5)
FOR i=1 TO 32
FOR j=1 TO 5
READ point$(i,j)
NEXT j
NEXT i
html$= "<table border=1>"
html$&= "<TR><TD align=right></td><td>Boxing The Compass</td><td>Abbr</td><td>Min</td><td>Med</td><td>Max</td></tr>"
FOR i =1 TO 32
html$&= "<TR><TD align=right>"&i&"</td><td>"&point$(i,1)&"</td><td>"&point$(i,2)&"</td><td>"&point$(i,3)&"</td><td>"&point$(i,4)&"</td><td>"&point$(i,5)&"</td></tr>"
NEXT i
html$&= "</table>"
BROWSER "compass" AT 0,0 SIZE sw-20,sh-20
BROWSER "compass" TEXT html$
PAUSE 20
END
DATA "North", "N", "354.38", "0", "5.62", "North by east", "NbE", "5.63", "11.25", "16.87"
DATA "North-northeast", "NNE", "16.88", "22.50", "28.12", "Northeast by north", "NEbN", "28.13", "33.75", "39.37"
DATA "Northeast", "NE", "39.38", "45.00", "50.62", "Northeast by east", "NEbE", "50.63", "56.25", "61.87"
DATA "East-northeast", "ENE", "61.88", "67.50", "73.12", "East by north", "EbN", "73.13", "78.75", "84.37"
DATA "East", "E", "84.38", "90.00", "95.62", "East by south", "EbS", "95.63", "101.25", "106.87"
DATA "East-southeast", "ESE", "106.88", "112.50", "118.12", "Southeast by east", "SEbE", "118.13", "123.75", "129.37"
DATA "Southeast", "SE", "129.38", "135.00", "140.62", "Southeast by south", "SEbS", "140.63", "146.25", "151.87"
DATA "South-southeast", "SSE", "151.88", "157.50", "163.12", "South by east", "SbE", "163.13", "168.75", "174.37"
DATA "South", "S", "174.38", "180.00", "185.62", "South by west", "SbW", "185.63", "191.25", "196.87"
DATA "South-southwest", "SSW", "196.88", "202.50", "208.12", "Southwest by south", "SWbS", "208.13", "213.75", "219.37"
DATA "Southwest", "SW", "219.38", "225.00", "230.62", "Southwest by west", "SWbW", "230.63", "236.25", "241.87"
DATA "West-southwest", "WSW", "241.88", "247.50", "253.12", "West by south", "WbS", "253.13", "258.75", "264.37"
DATA "West", "W", "264.38", "270.00", "275.62", "West by north", "WbN", "275.63", "281.25", "286.87"
DATA "West-northwest", "WNW", "286.88", "292.50", "298.12", "Northwest by west", "NWbW", "298.13", "303.75", "309.37"
DATA "Northwest", "NW", "309.38", "315.00", "320.62", "Northwest by north", "NWbN", "320.63", "326.25", "331.87"
DATA "North-northwest", "NNW", "331.88", "337.50", "343.12", "North by west", "NbW", "343.13", "348.75", "354.37"

View file

@ -0,0 +1,17 @@
A:=("X N NbE NNE NEbN NE NEbE ENE EbN E EbS ESE " // one based array
"SEbE SE SEbS SSE SbE S SbW SSW SWbS SW SWbW "
"WSW WbS W WbN WNW NWbW NW NWbN NNW NbW").split(" ");
fcn compassBox(d){
return(( ( (d + 360.0 / 64.0) % 360.0) * 32.0 / 360.0).ceil());
}
foreach i in ([0..32]){
heading:=11.25*i;
switch(i%3){ // or heading+=5.62*((i+1).divr(3)[1]-1);
case(1){ heading+=5.62 }
case(2){ heading-=5.62 }
}
box:=compassBox(heading);
println("%6.2f\UB0; : %2d\t%s".fmt(heading,box,A[box]));
}