2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -3,12 +3,13 @@ Avast me hearties!
|
|||
There be many a [http://www.talklikeapirate.com/howto.html land lubber] that knows [http://oxforddictionaries.com/view/entry/m_en_gb0550020#m_en_gb0550020 naught] of the pirate ways and gives direction by degree!
|
||||
They know not how to [[wp:Boxing the compass|box the compass]]!
|
||||
|
||||
'''Task description'''
|
||||
|
||||
;Task description:
|
||||
# Create a function that takes a heading in degrees and returns the correct 32-point compass heading.
|
||||
# Use the function to print and display a table of Index, Compass point, and Degree; rather like the corresponding columns from, the first table of the [[wp:Boxing the compass|wikipedia article]], but use only the following 33 headings as input:
|
||||
:<code>[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]</code>. (They should give the same order of points but are spread throughout the ranges of acceptance).
|
||||
|
||||
|
||||
;Notes;
|
||||
* The headings and indices can be calculated from this pseudocode:
|
||||
<pre>for i in 0..32 inclusive:
|
||||
|
|
@ -19,3 +20,4 @@ They know not how to [[wp:Boxing the compass|box the compass]]!
|
|||
end
|
||||
index = ( i mod 32) + 1</pre>
|
||||
* The column of indices can be thought of as an enumeration of the thirty two cardinal points (see [[Talk:Box the compass#Direction, index, and angle|talk page]])..
|
||||
<br><br>
|
||||
|
|
|
|||
375
Task/Box-the-compass/AppleScript/box-the-compass.applescript
Normal file
375
Task/Box-the-compass/AppleScript/box-the-compass.applescript
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
use framework "Foundation"
|
||||
use scripting additions
|
||||
|
||||
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"} & ¬
|
||||
{|NEE|:"E-NE", |NEEE|:"EbN", |E|:"E", |EEES|:"EbS", |EES|:"E-SE", |EESES|:"SEbE"} & ¬
|
||||
{|ES|:"SE", |ESESS|:"SEbS", |ESS|:"S-SE", |ESSS|:"SbE", |S|:"S", |SSSW|:"SbW"} & ¬
|
||||
{|SSW|:"S-SW", |SSWSW|:"SWbS", |SW|:"SW", |SWSWW|:"SWbW", |SWW|:"W-SW"} & ¬
|
||||
{|SWWW|:"WbS", |W|:"W", |WWWN|:"WbN", |WWN|:"W-NW", |WWNWN|:"NWbW"} & ¬
|
||||
{|WN|:"NW", |WNWNN|:"NWbN", |WNN|:"N-NW", |WNNN|:"NbW"}, ¬
|
||||
¬
|
||||
{|name|:"Chinese", |N|:"北", |NNNE|:"北微东", |NNE|:"东北偏北"} & ¬
|
||||
{|NNENE|:"东北微北", |NE|:"东北", |NENEE|:"东北微东", |NEE|:"东北偏东"} & ¬
|
||||
{|NEEE|:"东微北", |E|:"东", |EEES|:"东微南", |EES|:"东南偏东", |EESES|:"东南微东"} & ¬
|
||||
{|ES|:"东南", |ESESS|:"东南微南", |ESS|:"东南偏南", |ESSS|:"南微东", |S|:"南"} & ¬
|
||||
{|SSSW|:"南微西", |SSW|:"西南偏南", |SSWSW|:"西南微南", |SW|:"西南"} & ¬
|
||||
{|SWSWW|:"西南微西", |SWW|:"西南偏西", |SWWW|:"西微南", |W|:"西"} & ¬
|
||||
{|WWWN|:"西微北", |WWN|:"西北偏西", |WWNWN|:"西北微西", |WN|:"西北"} & ¬
|
||||
{|WNWNN|:"西北微北", |WNN|:"西北偏北", |WNNN|:"北微西"}]
|
||||
|
||||
-- Scale invariant keys for points of the compass
|
||||
-- (allows us to look up a translation for one scale of compass (32 here)
|
||||
-- for use in another size of compass (8 or 16 points)
|
||||
-- (Also semi-serviceable as more or less legible keys without translation)
|
||||
|
||||
-- compassKeys :: Int -> [String]
|
||||
on compassKeys(intDepth)
|
||||
-- Simplest compass divides into two hemispheres
|
||||
-- with one peak of ambiguity to the left,
|
||||
-- and one to the right (encoded by the commas in this list):
|
||||
set urCompass to ["N", "S", "N"]
|
||||
|
||||
-- Necessity drives recursive subdivision of broader directions, shrinking
|
||||
-- boxes down to a workable level of precision:
|
||||
script subdivision
|
||||
on lambda(lstCompass, N)
|
||||
if N ≤ 1 then
|
||||
lstCompass
|
||||
else
|
||||
script subKeys
|
||||
on lambda(a, x, i, xs)
|
||||
-- Borders between N and S engender E and W.
|
||||
-- further subdivisions (boxes) concatenate their two parent keys.
|
||||
if i > 1 then
|
||||
cond(N = intDepth, ¬
|
||||
a & {cond(x = "N", "W", "E")} & x, ¬
|
||||
a & {item (i - 1) of xs & x} & x)
|
||||
else
|
||||
a & x
|
||||
end if
|
||||
end lambda
|
||||
end script
|
||||
|
||||
lambda(foldl(subKeys, {}, lstCompass), N - 1)
|
||||
end if
|
||||
end lambda
|
||||
end script
|
||||
|
||||
tell subdivision to items 1 thru -2 of lambda(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
|
||||
cond(i > 0, i, 1)
|
||||
end pointIndex
|
||||
|
||||
-- pointNames :: Int -> Int -> [String]
|
||||
on pointNames(precision, iBox)
|
||||
set k to item iBox of compassKeys(precision)
|
||||
|
||||
script translation
|
||||
on lambda(recLang)
|
||||
set maybeTrans to keyValue(recLang, k)
|
||||
set strBrief to cond(maybeTrans is missing value, k, maybeTrans)
|
||||
|
||||
set recExpand to keyValue(recLang, "expansions")
|
||||
|
||||
if recExpand is not missing value then
|
||||
script expand
|
||||
on lambda(c)
|
||||
set t to keyValue(recExpand, c)
|
||||
cond(t is not missing value, t, c)
|
||||
end lambda
|
||||
end script
|
||||
set strName to (intercalate(cond(precision > 5, " ", ""), ¬
|
||||
map(expand, characters of strBrief)))
|
||||
toUpper(text item 1 of strName) & text items 2 thru -1 of strName
|
||||
else
|
||||
strBrief
|
||||
end if
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(translation, plstLangs)
|
||||
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)
|
||||
end maxLen
|
||||
|
||||
-- alignRight :: Int -> String -> String
|
||||
on alignRight(nWidth, x)
|
||||
justifyRight(nWidth, space, x)
|
||||
end alignRight
|
||||
|
||||
-- alignLeft :: Int -> String -> String
|
||||
on alignLeft(nWidth, x)
|
||||
justifyLeft(nWidth, space, x)
|
||||
end alignLeft
|
||||
|
||||
-- show :: asString => a -> Text
|
||||
on show(x)
|
||||
x as string
|
||||
end show
|
||||
|
||||
-- compassTable :: Int -> [Num] -> Maybe String
|
||||
on compassTable(precision, xs)
|
||||
if precision < 1 then
|
||||
missing value
|
||||
else
|
||||
set intPad to 2
|
||||
set rightAligned to curry(alignRight)
|
||||
set leftAligned to curry(alignLeft)
|
||||
set join to curry(my intercalate)
|
||||
|
||||
-- INDEX COLUMN
|
||||
set lstIndex to map(lambda(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)
|
||||
|
||||
-- ANGLES COLUMN
|
||||
script degreeFormat
|
||||
on lambda(x)
|
||||
set {c, m} to splitOn(".", x as string)
|
||||
c & "." & (text 1 thru 2 of (m & "0")) & "°"
|
||||
end lambda
|
||||
end script
|
||||
set lstAngles to map(degreeFormat, xs)
|
||||
set nAngleWidth to maxLen(lstAngles) + intPad
|
||||
set colAngles to map(lambda(nAngleWidth) of rightAligned, lstAngles)
|
||||
|
||||
-- NAMES COLUMNS
|
||||
script precisionNames
|
||||
on lambda(iBox)
|
||||
pointNames(precision, iBox)
|
||||
end lambda
|
||||
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
|
||||
end script
|
||||
|
||||
set colsTrans to map(spacedNames, lstTrans)
|
||||
|
||||
-- TABLE
|
||||
intercalate(linefeed, ¬
|
||||
map(lambda("") of join, ¬
|
||||
transpose({colIndex} & {colAngles} & ¬
|
||||
{replicate(length of lstIndex, " ")} & colsTrans)))
|
||||
end if
|
||||
end compassTable
|
||||
|
||||
|
||||
|
||||
-- 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, ¬
|
||||
270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, ¬
|
||||
354.38]
|
||||
|
||||
-- If we supply other precisions, like 4 or 6, (2^n -> 16 or 64 boxes)
|
||||
-- the bearings will be divided amongst smaller or larger numbers of boxes,
|
||||
-- either using name translations retrieved by the generic hash
|
||||
-- or using the keys of the hash itself (combined with any expansions)
|
||||
-- to substitute for missing names for very finely divided boxes.
|
||||
|
||||
compassTable(5, xs) -- // 2^5 -> 32 boxes
|
||||
|
||||
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 lambda(item i of xs, i, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
-- 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 lambda(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}
|
||||
set strJoined to lstText as text
|
||||
set my text item delimiters to dlm
|
||||
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
|
||||
text 1 thru N of (strText & replicate(N, cFiller))
|
||||
else
|
||||
strText
|
||||
end if
|
||||
end justifyLeft
|
||||
|
||||
-- justifyRight :: Int -> Char -> Text -> Text
|
||||
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
|
||||
|
||||
-- replicate :: Int -> a -> [a]
|
||||
on replicate(N, a)
|
||||
set out to {}
|
||||
if N < 1 then return out
|
||||
set dbl to {a}
|
||||
|
||||
repeat while (N > 1)
|
||||
if (N mod 2) > 0 then set out to out & dbl
|
||||
set N to (N div 2)
|
||||
set dbl to (dbl & dbl)
|
||||
end repeat
|
||||
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
|
||||
|
||||
-- cond :: Bool -> a -> a -> a
|
||||
on cond(bool, f, g)
|
||||
if bool then
|
||||
f
|
||||
else
|
||||
g
|
||||
end if
|
||||
end cond
|
||||
67
Task/Box-the-compass/COBOL/box-the-compass.cobol
Normal file
67
Task/Box-the-compass/COBOL/box-the-compass.cobol
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
identification division.
|
||||
program-id. box-compass.
|
||||
data division.
|
||||
working-storage section.
|
||||
01 point pic 99.
|
||||
01 degrees usage float-short.
|
||||
01 degrees-rounded pic 999v99.
|
||||
01 show-degrees pic zz9.99.
|
||||
01 box pic z9.
|
||||
01 fudge pic 9.
|
||||
01 compass pic x(4).
|
||||
01 compass-point pic x(18).
|
||||
01 shortform pic x.
|
||||
01 short-names.
|
||||
05 short-name pic x(4) occurs 33 times.
|
||||
01 overlay.
|
||||
05 value "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 " & "N ".
|
||||
|
||||
procedure division.
|
||||
display "Index Compass point Degree"
|
||||
|
||||
move overlay to short-names.
|
||||
perform varying point from 0 by 1 until point > 32
|
||||
compute box = function mod(point 32) + 1
|
||||
compute degrees = point * 11.25
|
||||
compute fudge = function mod(point 3)
|
||||
evaluate fudge
|
||||
when equal 1
|
||||
add 5.62 to degrees
|
||||
when equal 2
|
||||
subtract 5.62 from degrees
|
||||
end-evaluate
|
||||
|
||||
compute degrees-rounded rounded = degrees
|
||||
move degrees-rounded to show-degrees
|
||||
inspect show-degrees replacing trailing '00' by '0 '
|
||||
inspect show-degrees replacing trailing '50' by '5 '
|
||||
|
||||
move short-name(point + 1) to compass
|
||||
move spaces to compass-point
|
||||
display space box space space space with no advancing
|
||||
perform varying tally from 1 by 1 until tally > 4
|
||||
move compass(tally:1) to shortform
|
||||
move function concatenate(function trim(compass-point),
|
||||
function substitute(shortform,
|
||||
"N", "North",
|
||||
"E", "East",
|
||||
"S", "South",
|
||||
"W", "West",
|
||||
"b", " byZ",
|
||||
"-", "-"))
|
||||
to compass-point
|
||||
end-perform
|
||||
move function substitute(compass-point, "Z", " ")
|
||||
to compass-point
|
||||
move function lower-case(compass-point) to compass-point
|
||||
move function upper-case(compass-point(1:1))
|
||||
to compass-point(1:1)
|
||||
display compass-point space show-degrees
|
||||
end-perform
|
||||
goback.
|
||||
239
Task/Box-the-compass/JavaScript/box-the-compass-2.js
Normal file
239
Task/Box-the-compass/JavaScript/box-the-compass-2.js
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// GENERIC FUNCTIONS
|
||||
|
||||
// toTitle :: String -> String
|
||||
let toTitle = s => s.length ? (s[0].toUpperCase() + s.slice(1)) : '';
|
||||
|
||||
// COMPASS DATA AND FUNCTIONS
|
||||
|
||||
// Scale invariant keys for points of the compass
|
||||
// (allows us to look up a translation for one scale of compass (32 here)
|
||||
// for use in another size of compass (8 or 16 points)
|
||||
// (Also semi-serviceable as more or less legible keys without translation)
|
||||
|
||||
// compassKeys :: Int -> [String]
|
||||
let compassKeys = depth => {
|
||||
let urCompass = ['N', 'S', 'N'],
|
||||
subdivision = (compass, n) => n <= 1 ? (
|
||||
compass
|
||||
) : subdivision( // Borders between N and S engender E and W.
|
||||
// other new boxes concatenate their parent keys.
|
||||
compass.reduce((a, x, i, xs) => {
|
||||
if (i > 0) {
|
||||
return (n === depth) ? (
|
||||
a.concat([x === 'N' ? 'W' : 'E'], x)
|
||||
) : a.concat([xs[i - 1] + x, x]);
|
||||
} else return a.concat(x);
|
||||
}, []),
|
||||
n - 1
|
||||
);
|
||||
return subdivision(urCompass, depth)
|
||||
.slice(0, -1);
|
||||
};
|
||||
|
||||
// https://zh.wikipedia.org/wiki/%E7%BD%97%E7%9B%98%E6%96%B9%E4%BD%8D
|
||||
let lstLangs = [{
|
||||
'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',
|
||||
'NEE': 'E-NE',
|
||||
'NEEE': 'EbN',
|
||||
'E': 'E',
|
||||
'EEES': 'EbS',
|
||||
'EES': 'E-SE',
|
||||
'EESES': 'SEbE',
|
||||
'ES': 'SE',
|
||||
'ESESS': 'SEbS',
|
||||
'ESS': 'S-SE',
|
||||
'ESSS': 'SbE',
|
||||
'S': 'S',
|
||||
'SSSW': 'SbW',
|
||||
'SSW': 'S-SW',
|
||||
'SSWSW': 'SWbS',
|
||||
'SW': 'SW',
|
||||
'SWSWW': 'SWbW',
|
||||
'SWW': 'W-SW',
|
||||
'SWWW': 'WbS',
|
||||
'W': 'W',
|
||||
'WWWN': 'WbN',
|
||||
'WWN': 'W-NW',
|
||||
'WWNWN': 'NWbW',
|
||||
'WN': 'NW',
|
||||
'WNWNN': 'NWbN',
|
||||
'WNN': 'N-NW',
|
||||
'WNNN': 'NbW'
|
||||
}, {
|
||||
'name': 'Chinese',
|
||||
'N': '北',
|
||||
'NNNE': '北微东',
|
||||
'NNE': '东北偏北',
|
||||
'NNENE': '东北微北',
|
||||
'NE': '东北',
|
||||
'NENEE': '东北微东',
|
||||
'NEE': '东北偏东',
|
||||
'NEEE': '东微北',
|
||||
'E': '东',
|
||||
'EEES': '东微南',
|
||||
'EES': '东南偏东',
|
||||
'EESES': '东南微东',
|
||||
'ES': '东南',
|
||||
'ESESS': '东南微南',
|
||||
'ESS': '东南偏南',
|
||||
'ESSS': '南微东',
|
||||
'S': '南',
|
||||
'SSSW': '南微西',
|
||||
'SSW': '西南偏南',
|
||||
'SSWSW': '西南微南',
|
||||
'SW': '西南',
|
||||
'SWSWW': '西南微西',
|
||||
'SWW': '西南偏西',
|
||||
'SWWW': '西微南',
|
||||
'W': '西',
|
||||
'WWWN': '西微北',
|
||||
'WWN': '西北偏西',
|
||||
'WWNWN': '西北微西',
|
||||
'WN': '西北',
|
||||
'WNWNN': '西北微北',
|
||||
'WNN': '西北偏北',
|
||||
'WNNN': '北微西'
|
||||
}];
|
||||
|
||||
// pointIndex :: Int -> Num -> Int
|
||||
let pointIndex = (power, degrees) => {
|
||||
let nBoxes = (power ? Math.pow(2, power) : 32);
|
||||
return Math.ceil(
|
||||
(degrees + (360 / (nBoxes * 2))) % 360 * nBoxes / 360
|
||||
) || 1;
|
||||
};
|
||||
|
||||
// pointNames :: Int -> Int -> [String]
|
||||
let pointNames = (precision, iBox) => {
|
||||
let k = compassKeys(precision)[iBox - 1];
|
||||
return lstLangs.map(dctLang => {
|
||||
let s = dctLang[k] || k, // fallback to key if no translation
|
||||
dctEx = dctLang.expansions;
|
||||
|
||||
return dctEx ? toTitle(s.split('')
|
||||
.map(c => dctEx[c])
|
||||
.join(precision > 5 ? ' ' : ''))
|
||||
.replace(/ /g, ' ') : s;
|
||||
});
|
||||
};
|
||||
|
||||
// maximumBy :: (a -> a -> Ordering) -> [a] -> a
|
||||
let maximumBy = (f, xs) =>
|
||||
xs.reduce((a, x) => a === undefined ? x : (
|
||||
f(x, a) > 0 ? x : a
|
||||
), undefined);
|
||||
|
||||
// justifyLeft :: Int -> Char -> Text -> Text
|
||||
let justifyLeft = (n, cFiller, strText) =>
|
||||
n > strText.length ? (
|
||||
(strText + replicate(n, cFiller)
|
||||
.join(''))
|
||||
.substr(0, n)
|
||||
) : strText;
|
||||
|
||||
// justifyRight :: Int -> Char -> Text -> Text
|
||||
let justifyRight = (n, cFiller, strText) =>
|
||||
n > strText.length ? (
|
||||
(replicate(n, cFiller)
|
||||
.join('') + strText)
|
||||
.slice(-n)
|
||||
) : strText;
|
||||
|
||||
// replicate :: Int -> a -> [a]
|
||||
let replicate = (n, a) => {
|
||||
let v = [a],
|
||||
o = [];
|
||||
if (n < 1) return o;
|
||||
while (n > 1) {
|
||||
if (n & 1) o = o.concat(v);
|
||||
n >>= 1;
|
||||
v = v.concat(v);
|
||||
}
|
||||
return o.concat(v);
|
||||
};
|
||||
|
||||
// transpose :: [[a]] -> [[a]]
|
||||
let transpose = xs =>
|
||||
xs[0].map((_, iCol) => xs.map((row) => row[iCol]));
|
||||
|
||||
// length :: [a] -> Int
|
||||
// length :: Text -> Int
|
||||
let length = xs => xs.length;
|
||||
|
||||
// compareByLength = (a, a) -> (-1 | 0 | 1)
|
||||
let compareByLength = (a, b) => {
|
||||
let [na, nb] = [a, b].map(length);
|
||||
return na < nb ? -1 : na > nb ? 1 : 0;
|
||||
};
|
||||
|
||||
// maxLen :: [String] -> Int
|
||||
let maxLen = xs => maximumBy(compareByLength, xs)
|
||||
.length;
|
||||
|
||||
// compassTable :: Int -> [Num] -> Maybe String
|
||||
let compassTable = (precision, xs) => {
|
||||
if (precision < 1) return undefined;
|
||||
else {
|
||||
let intPad = 2;
|
||||
|
||||
let lstIndex = xs.map(x => pointIndex(precision, x)),
|
||||
lstStrIndex = lstIndex.map(x => x.toString()),
|
||||
nIndexWidth = maxLen(lstStrIndex),
|
||||
colIndex = lstStrIndex.map(
|
||||
x => justifyRight(nIndexWidth, ' ', x)
|
||||
);
|
||||
|
||||
let lstAngles = xs.map(x => x.toFixed(2) + '°'),
|
||||
nAngleWidth = maxLen(lstAngles) + intPad,
|
||||
colAngles = lstAngles.map(x => justifyRight(nAngleWidth, ' ', x));
|
||||
|
||||
let lstTrans = transpose(
|
||||
lstIndex.map(i => pointNames(precision, i))
|
||||
),
|
||||
lstTransWidths = lstTrans.map(x => maxLen(x) + 2),
|
||||
colsTrans = lstTrans
|
||||
.map((lstLang, i) => lstLang
|
||||
.map(x => justifyLeft(lstTransWidths[i], ' ', x))
|
||||
);
|
||||
|
||||
return transpose([colIndex]
|
||||
.concat([colAngles], [replicate(lstIndex.length, " ")])
|
||||
.concat(colsTrans))
|
||||
.map(x => x.join(''))
|
||||
.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// TEST
|
||||
let xs = [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
|
||||
];
|
||||
|
||||
// If we supply other precisions, like 4 or 6, (2^n -> 16 or 64 boxes)
|
||||
// the bearings will be divided amongst smaller or larger numbers of boxes,
|
||||
// either using name translations retrieved by the generic hash
|
||||
// or using the hash itself (combined with any expansions)
|
||||
// to substitute for missing names for very finely divided boxes.
|
||||
|
||||
return compassTable(5, xs); // 2^5 -> 32 boxes
|
||||
})();
|
||||
16
Task/Box-the-compass/PowerShell/box-the-compass-1.psh
Normal file
16
Task/Box-the-compass/PowerShell/box-the-compass-1.psh
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
function Convert-DegreeToDirection ( [double]$Degree )
|
||||
{
|
||||
|
||||
$Directions = @( 'n','n by e','n-ne','ne by n','ne','ne by e','e-ne','e by n',
|
||||
'e','e by s','e-se','se by e','se','se by s','s-se','s by e',
|
||||
's','s by w','s-sw','sw by s','sw','sw by w','w-sw','w by s',
|
||||
'w','w by n','w-nw','nw by w','nw','nw by n','n-nw','n by w',
|
||||
'n'
|
||||
).Replace( 's', 'south' ).Replace( 'e', 'east' ).Replace( 'n', 'north' ).Replace( 'w', 'west' )
|
||||
|
||||
$Directions[[math]::floor(( $Degree % 360 ) / 11.25 + 0.5 )]
|
||||
}
|
||||
|
||||
$x = 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
|
||||
|
||||
$x | % { Convert-DegreeToDirection -Degree $_ }
|
||||
23
Task/Box-the-compass/PowerShell/box-the-compass-2.psh
Normal file
23
Task/Box-the-compass/PowerShell/box-the-compass-2.psh
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
function Convert-DegreeToDirection ( [double]$Degree, [int]$Points )
|
||||
{
|
||||
|
||||
$Directions = @( 'n','n by e','n-ne','ne by n','ne','ne by e','e-ne','e by n',
|
||||
'e','e by s','e-se','se by e','se','se by s','s-se','s by e',
|
||||
's','s by w','s-sw','sw by s','sw','sw by w','w-sw','w by s',
|
||||
'w','w by n','w-nw','nw by w','nw','nw by n','n-nw','n by w',
|
||||
'n'
|
||||
).Replace( 's', 'south' ).Replace( 'e', 'east' ).Replace( 'n', 'north' ).Replace( 'w', 'west' )
|
||||
|
||||
$Directions[[math]::floor((( $Degree % 360 ) * $Points / 360 + 0.5 )) * 32 / $Points ]
|
||||
}
|
||||
|
||||
$x = 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
|
||||
|
||||
|
||||
$Values = @()
|
||||
ForEach ( $Degree in $X ) { $Values += [pscustomobject]@{ Degree = $Degree
|
||||
32 = ( Convert-DegreeToDirection -Degree $Degree -Points 32 )
|
||||
16 = ( Convert-DegreeToDirection -Degree $Degree -Points 16 )
|
||||
8 = ( Convert-DegreeToDirection -Degree $Degree -Points 8 )
|
||||
4 = ( Convert-DegreeToDirection -Degree $Degree -Points 4 ) } }
|
||||
$Values | Format-Table
|
||||
|
|
@ -1,29 +1,29 @@
|
|||
/*REXX program "boxes the compass" (from º headings ───► a 32 point set).*/
|
||||
parse arg # /*allow a º heading to be specified.*/
|
||||
if #='' then #= 0 16.87 16.88 33.75 50.62 50.63 67.5 84.37 84.38 101.25 118.12,
|
||||
118.13 135 151.87 151.88 168.75 185.62 185.63 202.5 219.37,
|
||||
219.38 236.25 253.12 253.13 270 286.87 286.88 303.75 320.62,
|
||||
320.63 337.5 354.37 354.38 /* [↑] use default in degrees.*/
|
||||
/*REXX program "boxes the compass" [from degree (º) headings ───► a 32 point set]. */
|
||||
parse arg $ /*allow a º heading to be specified. */
|
||||
if $='' then $= 0 16.87 16.88 33.75 50.62 50.63 67.5 84.37 84.38 101.25 118.12 118.13 ,
|
||||
135 151.87 151.88 168.75 185.62 185.63 202.5 219.37 219.38 236.25 ,
|
||||
253.12 253.13 270 286.87 286.88 303.75 320.62 320.63 337.5 354.37 354.38
|
||||
/* [↑] use default, they're in degrees*/
|
||||
@pts= '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"
|
||||
|
||||
points= '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'
|
||||
#=words(@pts) + 1 /*#: used for integer ÷ remainder (//)*/
|
||||
dirs= 'north south east west' /*define cardinal compass directions. */
|
||||
/* [↓] choose a glyph for degree (°).*/
|
||||
if 4=='f4'x then degSym= "a1"x /*is this system an EBCDIC system? */
|
||||
else degSym= "a7"x /*'f8'x is the degree symbol: ° vs º */
|
||||
/*──────────────────────────── f8 vs a7*/
|
||||
say right(degSym'heading', 30) center("compass heading", 20)
|
||||
say right( '════════', 30) copies( "═", 20)
|
||||
|
||||
dirs= 'north south east west' /*define cardinal compass directions.*/
|
||||
/* [↓] choose a degree (°) glyph. */
|
||||
if 4=='f4'x then degSym='a1'x /*is this system an EBCDIC system? */
|
||||
else degSym='f8'x /*although 'a7'x looks better: ° vs º*/
|
||||
/*─────────────────────────── f8 a7*/
|
||||
say right(degSym'heading',30) center('compass heading',20)
|
||||
say right( '────────',30) copies('─' ,20)
|
||||
|
||||
do j=1 for words(#); x=word(#,j) /*get one of the degree headings*/
|
||||
say right(format(x,,2)degSym,30-1) ' ' boxHeading(x)
|
||||
do j=1 for words($); x=word($, j) /*obtain one of the degree headings. */
|
||||
say right(format(x, , 2)degSym, 30-1) ' ' boxHeading(x)
|
||||
end /*j*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
boxHeading: _=arg(1)//360; if _<0 then _=360-_ /*normalize the heading.*/
|
||||
_=word(points,trunc(max(1,(_/11.25+1.5)//33)))
|
||||
do k=1 for words(dirs); d=word(dirs,k)
|
||||
_=changestr(left(d,1), _, d)
|
||||
end /*k*/
|
||||
return changestr('b', _, " by ") /*expand "b" ──► "by"*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
boxHeading: y=arg(1)//360; if y<0 then y=360 - y /*normalize heading within unit circle.*/
|
||||
z=word(@pts, trunc(max(1, (y/11.25+1.5) // #))) /*convert degrees─►heading*/
|
||||
do k=1 for words(dirs); d=word(dirs, k)
|
||||
z=changestr( left(d,1), z, d)
|
||||
end /*k*/ /* [↑] old, haystack, new*/
|
||||
return changestr('b', z, " by ") /*expand "b" ──► " by " */
|
||||
|
|
|
|||
26
Task/Box-the-compass/ZX-Spectrum-Basic/box-the-compass.zx
Normal file
26
Task/Box-the-compass/ZX-Spectrum-Basic/box-the-compass.zx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
10 DATA "North","North by east","North-northeast"
|
||||
20 DATA "Northeast by north","Northeast","Northeast by east","East-northeast"
|
||||
30 DATA "East by north","East","East by south","East-southeast"
|
||||
40 DATA "Southeast by east","Southeast","Southeast by south","South-southeast"
|
||||
50 DATA "South by east","South","South by west","South-southwest"
|
||||
60 DATA "Southwest by south","Southwest","Southwest by west","West-southwest"
|
||||
70 DATA "West by south","West","West by north","West-northwest"
|
||||
80 DATA "Northwest by west","Northwest","Northwest by north","North-northwest"
|
||||
90 DATA "North by west"
|
||||
100 DIM p$(32,18)
|
||||
110 FOR i=1 TO 32
|
||||
120 READ p$(i)
|
||||
130 NEXT i
|
||||
140 FOR i=0 TO 32
|
||||
150 LET h=i*11.25
|
||||
160 LET r=FN m(i,3)
|
||||
170 IF r=1 THEN LET h=h+5.62: GO TO 190
|
||||
180 IF r=2 THEN LET h=h-5.62
|
||||
190 LET ind=FN m(i,32)+1
|
||||
200 PRINT ind;TAB 4;
|
||||
210 LET x=h/11.25+1.5
|
||||
220 IF x>=33 THEN LET x=x-32
|
||||
230 PRINT p$(INT x);TAB 25;h
|
||||
240 NEXT i
|
||||
250 STOP
|
||||
260 DEF FN m(i,n)=((i/n)-INT (i/n))*n : REM modulus function
|
||||
Loading…
Add table
Add a link
Reference in a new issue