diff --git a/content/blog/2023-04-14-kaktovik/index.md b/content/blog/2023-04-14-kaktovik/index.md new file mode 100644 index 0000000..4bed56c --- /dev/null +++ b/content/blog/2023-04-14-kaktovik/index.md @@ -0,0 +1,77 @@ +--- +date: 2023-04-14 +title: Kaktovik numerals +scripts: + - kaktovik.mjs +draft: true +--- + +I just saw a Scientific American article about the recent inclusion in Unicode of the +[Kaktovik Numerals](https://en.wikipedia.org/wiki/Kaktovik_numerals), +a base-20 counting system invented in 1990 by schoolchildren in northern Alaska. + +Let's do some counting! + +
+
+

Apple-inator

+ + +
+
+

Apples

+
+
+
+ +Seems pretty easy, right? +I had it group apples in rows, so it's easier to visually see how many apples you have. + +Let's use 🍊 instead of 🍏🍏🍏🍏🍏, +to make it even easier to see how many rows we have. + +
+
+

Apple-inator

+ + +
+
+

Fruit

+
+
+
+

Apples

+
+
+
+ +--- + +
+
+

Apple-inator

+ + +
+
+

Kaktovik

+
+
+
+

Fruit

+
+
+
+

Apples

+
+
+
+

Arabic

+
+
+
+ +Can you see how +the number of left-and-right lines is the number of complete rows of apples, +and the number of up-and-down lines is the number of apples left? \ No newline at end of file diff --git a/content/blog/2023-04-14-kaktovik/kaktovik.mjs b/content/blog/2023-04-14-kaktovik/kaktovik.mjs new file mode 100644 index 0000000..8705100 --- /dev/null +++ b/content/blog/2023-04-14-kaktovik/kaktovik.mjs @@ -0,0 +1,113 @@ +const FruitNumerals = [ + "", "🍏", "🍏🍏", "🍏🍏🍏", "🍏🍏🍏🍏", + "🍊", "🍊🍏", "🍊🍏🍏", "🍊🍏🍏🍏", "🍊🍏🍏🍏🍏", + "🍊🍊", "🍊🍊🍏", "🍊🍊🍏🍏", "🍊🍊🍏🍏🍏", "🍊🍊🍏🍏🍏🍏", + "🍊🍊🍊", "🍊🍊🍊🍏", "🍊🍊🍊🍏🍏", "🍊🍊🍊🍏🍏🍏", "🍊🍊🍊🍏🍏🍏🍏", +] + +const KaktovikNumerals = [ + "𝋀", "𝋁", "𝋂", "𝋃", "𝋄", + "𝋅", "𝋆", "𝋇", "𝋈", "𝋉", + "𝋊", "𝋋", "𝋌", "𝋍", "𝋎", + "𝋏", "𝋐", "𝋑", "𝋒", "𝋓", +] + +function ToNumerals(numerals, n) { + let base = numerals.length + let its = [] + if (n < base) { + return [numerals[n]] + } + while (n > 0) { + its.unshift(numerals[n % base]) + n = Math.floor(n / base) + } + return its +} + +function ToFruit(n) { + let its = ToNumerals(FruitNumerals, n) + let doc = new DocumentFragment() + for (let it of its) { + let row = doc.appendChild(document.createElement("div")) + row.classList.add("row") + row.textContent = it + } + return doc +} + +function ToKaktovik(n) { + let its = ToNumerals(KaktovikNumerals, n) + return its.join("") +} + +function ToApples(n) { + let doc = new DocumentFragment() + while (n > 0) { + let apples = Math.min(n, 5) + let row = doc.appendChild(document.createElement("div")) + row.classList.add("row") + row.textContent = "🍏".repeat(apples) + n -= apples + } + return doc +} + + +class Counter { + /** + * Initialize a counter element. + * + * This makes buttons active, + * and does an initial render. + * + * @param {HTMLElement} element + */ + constructor(element, n=1) { + this.element = element + this.n = n + this.min = Number(this.element.dataset.min) || 0 + this.max = Number(this.element.dataset.max) || Infinity + + for (let e of this.element.querySelectorAll("button.add")) { + let amount = Number(e.dataset.amount) || 1 + e.addEventListener("click", e => this.add(e, amount)) + } + this.render() + } + + add(event, amount) { + let n = this.n + amount + n = Math.min(n, this.max) + n = Math.max(n, this.min) + if (n != this.n) { + this.n = n + this.render() + } + } + + render() { + for (let e of this.element.querySelectorAll(".kaktovik")) { + e.textContent = ToKaktovik(this.n) + } + for (let e of this.element.querySelectorAll(".fruit")) { + while (e.firstChild) e.firstChild.remove() + e.appendChild(ToFruit(this.n)) + } + for (let e of this.element.querySelectorAll(".apples")) { + while (e.firstChild) e.firstChild.remove() + e.appendChild(ToApples(this.n)) + } + for (let e of this.element.querySelectorAll(".arabic")) { + e.textContent = this.n + } + } +} + +function init() { + for (let e of document.querySelectorAll(".counter")) { + new Counter(e) + } +} + +document.addEventListener("DOMContentLoaded", init) diff --git a/static/assets/css/default.css b/static/assets/css/default.css index d476eb7..caf2b58 100644 --- a/static/assets/css/default.css +++ b/static/assets/css/default.css @@ -178,6 +178,9 @@ caption { caption-side: bottom; font-size: small; } +.jistify-center { + text-align: center; +} .justify-right, input[type="number"] { text-align: right; } @@ -203,6 +206,16 @@ caption { max-width: 100%; } } + +.flex { + display: flex; + justify-content: space-around; +} + +.flex.wrap { + flex-wrap: wrap; +} + @media (prefers-color-scheme: dark) { html { background-image: url("../images/bg-dark.jpg");