Help the library sort books
code-golf natural-language
A library needs to sort its books, located in separate sections by language. Of course, each language has its own rule for collating strings, so your method should handle that ability.
Most languages will want to treat titles case-insensitively, but unfortunately, the library has a section of Klingon books. And Klingon's romanisation, in case you don't already know, is case-sensitive. As a result, you need to give a way to have the sorter treat two given characters as the same.
Some of the titles also contain numbers, and you need to deal with those as well. Fortunately, the friendly people at the library have written some functions for you to deal with that, so all you have to do is take in a handle to a function as one of your inputs.
Your challenge: Sort a list of book titles, given a collating sequence and a function handle that converts a number to its string representation in the respective language.
- The collating sequence is a list of lists of strings. Given two strings A and B that appear respectively in the entries at indices i and j, respectively:
- if i > j, then A should sort after B
- if i = j, then A should sort the same as B
- In case some elements of the sequence have multiple characters, use the max-munch rule to tokenise the string: e.g. if both
l
and ll
appear in the collating sequence, then lll
should be tokenised to ll l
.
- Any string of digits should be parsed as a number and passed to the callback. Each such string should be replaced by the result.
- Any characters not appearing in the collating sequence should be ignored. If two strings differ only by such characters, then sort them however you like.
Test cases
Assuming
english_letters = [["A", "a"], ["B", "b"], ["C", "c"], ["D", "d"], ["E", "e"], ["F", "f"], ["G", "g"], ["H", "h"], ["I", "i"], ["J", "j"], ["K", "k"], ["L", "l"], ["M", "m"], ["N", "n"], ["O", "o"], ["P", "p"], ["Q", "q"], ["R", "r"], ["S", "s"], ["T", "t"], ["U", "u"], ["V", "v"], ["W", "w"], ["X", "x"], ["Y", "y"], ["Z", "z"]]
arka_letters = [["t"], ["k"], ["x"], ["s"], ["n"], ["v"], ["f"], ["m"], ["d"], ["g"], ["p"], ["b"], ["h"], ["y"], ["c"], ["r"], ["z"], ["j"], ["w"], ["l"]]
function english_num_callback(num) {
// convert a number to its representation in English
}
function arka_num_callback(num) { // handles nonnegative integers up to 9999
if (num == 0) return "yuu";
let kot = 0 | (num / 1000);
let gal = 0 | (num / 100 % 10);
let on = 0 | (num / 10 % 10);
let ko = num % 10;
let digits = ["yuu", "ko", "ta", "vi", "val", "lin", "kis", "nol", "ten", "los"];
return (kot == 0 ? "" : digits[kot] + "kot") +
(gal == 0 ? "" : digits[gal] + "gal") +
(on == 0 ? "" : digits[on] + "on") +
(ko == 0 ? "" : digits[ko]);
}
["Stack Exchange", "BB94 Channel!", "BB guns: all you wanted to know about them",
"carrots", "A Grammar of Jbl", "69"], english_letters, english_num_callback =>
["A Grammar of Jbl", "BB guns: all you wanted to know about them", "BB94 Channel!",
"carrots", "69", "Stack Exchange"]
["melidia", "diaklel", "44 miiko", "I Mess With the Librarians", "an isk ris tu lei",
"lei e xion", "xagrisren et xep!", "on melkadren"], arka_letters, arka_num_callback =>
["xagrisren et xep!", "44 miiko", "melidia", "diaklel", "lei e xion",
"an isk ris tu lei", "on melkadren", "I Mess With the Librarians"]