Try it online! - 175 byte version, running at decent speed
M←∊∘morse¨D⋄C←∊(7⍴51)⊤246⊥5 17⍴¯7+⎕AV⍳'k%aÏ⍵FþfÅ⍵ìÆ⌶á≥å3¶cÒ⍺\ujü─⍳%S⊣ì⍙ÒÛ─3Ùp`Ø,hÇñ⊂┴Ö⍪l∪çi1⍵Û:-îà⌽ì≥3€ã(⍟S]ÁôXræ∇O7Uæî'
C↓⍨←≢i↓⍨←≢M⊃⍨w←(⊃C)⌷∊(⍸M⍷⍨⊂)¨⌽,\i
⍞←819⌶w⊃D
→2
Try it online! - 172 byte 🐌 version, taking about 20 times as long to finish (especially slow at beginning)
-3 bytes by packing base 51 into base 246 instead of base 64 into base 256 and losing the apostrophe
-3 bytes by ending with an error message instead of cleanly
-3 bytes by running about 20 times more slowly
So the next stage in adapting the algorithm was to translate the entire dictionary to Morse code, and at each point in the encoded song, iterate through possible words in reverse order of their length in Morse dots+dashes (with the longest being 24). Not only is this approach far, far faster in APL (and probably many other languages), and far more concise, but even the data is more lightweight – far more of the "word choice" array elements are 0
or 1
, the largest value is just 50
, and there are only 115 elements (the then
no longer needed or benefited from breaking up), meaning that in languages with arbitrary-precision base conversion, it could be packed in base 51 and take up only 82 bytes. In APL though, the overhead of implementing arbitrary-precision base conversion would override the benefit, and I stuck with packing groups of 7 elements, in base 51, into groups of 5 bytes in base 246 (as log246 517 ≈ 4.999295), taking up 85 bytes. This data set responds even better to Huffman encoding than the previous, but still wouldn't break even: 4 1 2 21 1 13 0 23 0 3 26 1 23 0 26 0 27 15 8 6 0 34 10 0 1 1 7 0 43 23 0 4 37 50 1 0 3 23(24🐌) 22 6 15 6 16 3 2 17 10 12 5 0 9 31 1 3 9 21 0 32 16 9 20 32 8 12 31 5 0 4 27 14 1 7 13 16 0 0(1🐌) 27 4 4 22 10 0 16 5 7 15 3 12 18 4 2 13 1 0 50 4 49 2 1 4 38 20 0 0 19 0 43 23 0 1 6 12 0 38 0
So as it turns out, in APL it still doesn't golf well enough to beat the existing letter-boundary solutions, even if the overhead for unpacking the "word choice" array (24 bytes) and for using Dyalog Unicode instead of Extended (7 bytes) are subtracted (yielding 144 (141🐌) bytes code+data). I still think that it might be possible to make it shorter than 131 bytes in one of the languages more specialized towards golfing, and will likely try that eventually.
On my system, this version takes about 44 or 53 (or 908🐌) seconds to finish. On TIO it doesn't quite finish within 60 seconds.
,\24↑i
- make a list of Morse sequences starting at the beginning of i
- take the current value of the input (inputwith the parts of it that have already been processed deleted)
\24↑
- truncate to 24 characters (dots+dashes). That is the length of the longest Morse encodings (rudolph
and christmas
). This step is omitted in the 🐌 version, which results in almost identical operation, but far slower; the word choice array only needs to be modified in two places (increasing the choice value by 1 at the and
in andifyoueversawit
and at christmas
), meaning that at all other words, no matches for >24 dots+dashes are found in the dictionary.
,\
- make a list of Morse subsequences starting at the beginning of this, ranging from 1 dot/dash long to 24 dots/dashes long (or maximum length, in the 🐌 version), from shortest to longest (e.g., at the very beginning, would be '-' '-.' '-.-' '-.--' '-.---' '-.----' '-.-----' '-.-----.'
...'-.-----..--.--.---.---..'
)