Chinese zodiac: Difference between revisions

m
→‎JavaScript ES6: Tidied, updated output.
No edit summary
m (→‎JavaScript ES6: Tidied, updated output.)
Line 2,169:
{{Trans|Haskell}}
<lang JavaScript>(() => {
'"use strict'";
 
// GENERIC FUNCTIONS ------------------------------------------ TRADITIONAL CALENDAR STRINGS -----------
 
// charsats :: StringArray ->Int [Char](String, String)
const charsats = s() => s.split('');
// 天干 tiangan – 10 heavenly stems
 
zip(
// concat :: [[a]] -> [a] | [String] -> String
chars("甲乙丙丁戊己庚辛壬癸")
const concat = xs =>
xs.length > 0 ? )(() => {
constwords("jiă unit =bĭng typeofdīng xs[0] === 'string'gēng ?xīn ''rén : [];gŭi")
return unit.concat.apply(unit, xs);
})() : [];
 
// intercalate :: String -> [a] -> String
const intercalate = (s, xs) => xs.join(s);
 
// justifyLeft :: Int -> Char -> Text -> Text
const justifyLeft = (n, cFiller, strText) =>
n > strText.length ? (
(strText + cFiller.repeat(n))
.substr(0, n)
) : strText;
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
 
// quot :: Int -> Int -> Int
const quot = (n, m) => Math.floor(n / m);
 
// show :: Int -> a -> Indented String
// show :: a -> String
const show = (...x) =>
JSON.stringify.apply(
null, x.length > 1 ? [x[1], null, x[0]] : x
);
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// wordsads :: StringArray ->Int (String, [String])
const wordsads = s() => s.split(/\s+/);
// 地支 dizhi – 12 terrestrial branches
 
// zip :: [a] -> [b] -> [zip(a,b)]
chars("子丑寅卯辰巳午未申酉戌亥")
const zip = (xs, ys) =>
)(
xs.slice(0, Math.min(xs.length, ys.length))
.map((x, i) => [x, ys[i]]);words(
"zĭ chŏu yín măo chén sì " + (
 
"wŭ wèi shēn yŏu xū hài"
// zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
const zip3 = (xs, ys, zs) => )
)
xs.slice(0, Math.min(xs.length, ys.length, zs.length))
.map((x, i) => [x, ys[i], zs[i]]);
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) =>
Array.from({
length: Math.min(xs.length, ys.length)
}, (_, i) => f(xs[i], ys[i]));
 
// TRADITIONAL STRINGS ---------------------------------------------------
// ats :: Array Int (String, String)
const ats = zip(
chars("甲乙丙丁戊己庚辛壬癸"), // 天干 tiangan – 10 heavenly stems
words("jiă yĭ bĭng dīng wù jĭ gēng xīn rén gŭi")
);
 
// ads :: Array Int (String, String)
const ads = zip(
chars("子丑寅卯辰巳午未申酉戌亥"), // 地支 dizhi – 12 terrestrial branches
words("zĭ chŏu yín măo chén sì wŭ wèi shēn yŏu xū hài")
);
 
// aws :: Array Int (String, String, String)
const aws = zip3() =>
chars("木火土金水"), // 五行 wuxing – 5 elements
wordszip3("mù huǒ tǔ jīn shuǐ"),
words("wood fire earth metal waterchars("木火土金水")
);(
words("mù huǒ tǔ jīn shuǐ")
)(
words("wood fire earth metal water")
);
 
 
// axs :: Array Int (String, String, String)
const axs = zip3() =>
chars("鼠牛虎兔龍蛇馬羊猴鸡狗豬"), // 十二生肖 shengxiao – 12 symbolic animals
zip3(
words("shǔ niú hǔ tù lóng shé mǎ yáng hóu jī gǒu zhū"),
chars("鼠牛虎兔龍蛇馬羊猴鸡狗豬")
words("rat ox tiger rabbit dragon snake horse goat monkey rooster dog pig")
);(
words(
"shǔ niú hǔ tù lóng shé " + (
"mǎ yáng hóu jī gǒu zhū"
)
)
)(
words(
"rat ox tiger rabbit dragon snake " + (
"horse goat monkey rooster dog pig"
)
)
);
 
 
// ays :: Array Int (String, String)
const ays = zip() =>
chars("阳阴"), // 阴阳 yinyang
wordszip("yáng yīn")
chars("阳阴")
);
)(
words("yáng yīn")
);
 
 
// TRADITIONAL CYCLES ------------------------------------ TRADITIONAL CYCLES ----------------
const zodiac = y => {
const
Line 2,267 ⟶ 2,245:
iStem = iYear % 10,
iBranch = iYear % 12,
[hStem, pStem] = ats()[iStem],
[hBranch, pBranch] = ads()[iBranch],
[hElem, pElem, eElem] = aws()[quot(iStem, )(2)],
[hAnimal, pAnimal, eAnimal] = axs()[iBranch],
[hYinyang, pYinyang] = ays()[iYear % 2];
 
return [
[
[show(y), hStem + hBranch, hElem, hAnimal, hYinyang],
['', pStem + pBranch, pElemshow(y), pAnimalhStem + hBranch, pYinyang]hElem,
['', show((iYear % 60) + 1) + '/60', eElem, eAnimalhAnimal, '']hYinyang
],
["", pStem + pBranch, pElem, pAnimal, pYinyang],
[
"", `${show((iYear % 60) + 1)}/60`,
eElem, eAnimal, ""
]
];
};
 
// FORMATTING ------------------------------------- TEST -----------------------
const main = () => [
1935, 1938, 1968, 1972, 1976, 1984,
new Date().getFullYear()
]
.map(showYear)
.join("\n\n");
 
 
// ------------------- FORMATTING --------------------
// fieldWidths :: [[Int]]
const fieldWidths = [
Line 2,289 ⟶ 2,283:
// showYear :: Int -> String
const showYear = y =>
unlineszipWith(mapzip)(fieldWidths)(zodiac(y))
.map(
row => concat(map(([n, s]) => justifyLeft(n, ' ', s), row)),
zipWith(zip,row fieldWidths,=> zodiacrow.map(y))
([n, s]) => justifyLeft(n)(" ")(s)
));
)
.join("")
)
.join("\n");
 
 
// TEST OUTPUT -----------------------------------------------------------
// ---------------- GENERIC FUNCTIONS ----------------
return intercalate(
 
'\n\n',
// chars :: String map(-> [Char]
const chars = s => [...s];
showYear, [1935, 1938, 1968, 1972, 1976, 1984, new Date()
 
.getFullYear()
 
]
// justifyLeft :: Int -> Char -> String -> String
const justifyLeft = n =>
// The string s, followed by enough padding (with
// the character c) to reach the string length n.
c => s => n > s.length ? (
s.padEnd(n, c)
) : s;
 
 
// quot :: Integral a => a -> a -> a
const quot = n =>
m => Math.trunc(n / m);
 
 
// show :: Int -> a -> Indented String
// show :: a -> String
const show = (...x) =>
JSON.stringify.apply(
null, x.length > 1 ? [
x[1], null, x[0]
] : x
);
 
 
// words :: String -> [String]
const words = s =>
// List of space-delimited sub-strings.
s.split(/\s+/u);
 
 
// zip :: [a] -> [b] -> [(a, b)]
const zip = xs =>
// The paired members of xs and ys, up to
// the length of the shorter of the two lists.
ys => Array.from({
length: Math.min(xs.length, ys.length)
}, (_, i) => [xs[i], ys[i]]);
 
 
// zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
const zip3 = xs =>
ys => zs => xs.slice(
0,
Math.min(...[xs, ys, zs].map(x => x.length))
)
.map((x, i) => [x, ys[i], zs[i]]);
);
 
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = f =>
// A list constructed by zipping with a
// custom function, rather than with the
// default tuple constructor.
xs => ys => xs.map(
(x, i) => f(x)(ys[i])
).slice(
0, Math.min(xs.length, ys.length)
);
 
 
// MAIN ---
return main();
})();</lang>
{{Out}}
Line 2,329 ⟶ 2,387:
1/60 wood rat
 
20172022 丁酉壬寅
dīngyŏurényín huǒ shuǐ yīn yáng
3439/60 firewater rooster tiger </pre>
 
=={{header|Julia}}==
9,655

edits