Skip to main content
added 387 characters in body
Source Link
Wheat Wizard
  • 100k
  • 22
  • 282
  • 661

  • Although I didn't think of this at the time, we could save a couple of bytes if we could use ranges in character classes. [ptkfcsxlmnr] could be [cfk-np-tx] (q isn't in the input so it doesn't matter that this matches q). These were implemented in 51806e570.

  • Although I didn't think of this at the time, we could save a couple of bytes if we could use ranges in character classes. [ptkfcsxlmnr] could be [cfk-np-tx] (q isn't in the input so it doesn't matter that this matches q). These were implemented in 51806e570.
Source Link
Wheat Wizard
  • 100k
  • 22
  • 282
  • 661

Haskell + hgl, 186 bytes

c="[^aeiou]"
v="[aeiou]"
cP$rXw(yS hdS)$fo["([mpbkgfvcsx][lr]|[cs][mnptkf]|[jz][mbdgv]|t[csr]|d[jzr])",v,c,v,"|",c,v,"([cjsz]{2}|x[kc]|[kc]x|mz|/p)!([ptkfcsxlmnr]{2}|[bdgvjzlmnr]{2})",v]

Attempt This Online!

Without regex, 189 bytes

y=jzW(p2**).*wR
v=xys W5
c=xys d
d="ptkfcsxlmnr bdgvjzlmnr"
cP$fo[asy$y"mpbkgfvcsx cs jz t d""lr mnptkf mbdgv csr jzr",v,c,v]++fo[c,v,asy$cX(y d d)$zW p2 d d<>y"cjsz x kc m""cjsz kc x z",v]

Attempt This Online!

Explanation

First we define some helpers. y=jzW(p2**).*wR is the most complex. It's a weird synthetic operation that happens to be useful in this usecase, so it doesn't really have a simple explanation. But you can break it down part by part:

  • (p2**) takes two lists of characters and creates all strings formed by taking one character from the first and one from the second, so

    >>> (p2**) "abc" "ae"
    ["aa","ae","ba","be","ca","ce"]
    
  • jzW applies it pairwise to two lists. This allows us to get a bunch of pairs made from combinations of specific sets of characters.

  • (.*wR) makes it so it takes the lists as space separated strings. This is just a denser format than lists of strings.

v is relatively simple. It's a parser that parses any vowel, aeiou. Similarly c parses any Lojban consonant (or a space). d is our list of all consonants, it contains a space and some repeats because this format is useful for other things. We can do this since xys basically treats its input as a set and we know the input will never have a space.

Specifically the string is <voiceless consonants><sonorants> <voiced consonants><sonorants>.

Now we get into the body, this has the form:

cP$fo[??,v,c,v]++fo[c,v,??,v]

with the two ??s each being replaced with the clustering rules.

Reflection

The non-regex answer is so close to beating the regex answer. I have some improvements:

  • While jzW(p2**).*wR is overly synthetic jzW(p2**) and zW p2 are both probably useful.
  • "[aeiou]" is shorter than '[':W5<>"]". If there were a function, ekQ, to enclose a string in square brackets ekQ W5 would be shorter than both.
  • There should probably be constants for consonants of the ISO alphabet as well as the ones for vowels.
  • Back-referencing would be useful in the regex answer. It's already a planned feature, there are just technical hurdles on the way to implementing it.
  • There could be more versatile ways to handle user input parsers. v and c could potentially have been user input parsers if there existed the ability to supply more than one.
  • Along the lines of that, I could make a way for the user to assign escape sequences in some sort of header string, like rwh"v[aeiou];c[^aeiou]""/c/v/c/c/v".