23
\$\begingroup\$

An Abjad is a writing system where each symbol stands for a consonant, and where vowels are omitted. An impure Abjad is an abjad in which there are additionals symbols for vowels, usually diacritics.

Write a program or function that, given a string of lowercase text (i.e. nothing but ASCII letters from a to z, commas and spaces), outputs a corresponding impure abjad English transcript with the following rules:

Representation of vowels

Each vowel (i.e. a e i o u) is represented as an accent on the immediately preceding consonant. For instance, assuming the accent representing the vowel e is ́, the word wet will be transcribed as ẃt.

If a vowel is not preceded by a consonant (two or more vowels in a row, or a word starting with a vowel), the symbol o is used as a "blank consonant". For example, the word peep will be transcribed as ṕóp

Accent placement

Consonants that have ascenders are unpleasant to read when accentuated. Therefore, for those consonants, the symmetric accent will be displayed below the symbol instead of above. For instance, the letter combination te will be written rather than ́t

Those consonants are b d f h k l t.

Accents for vowels

We are using Unicode combining characters to display accents on every consonant possible. The combining characters used can be found here. Combining accents are placed directly after the symbol they are to be put on.

The accents are presented on arbitrary consonants in this list.

  • a

    Above accent: U+0x0304, example:

    Below accent: U+0x0320, example:

  • e

    Above accent: U+0x0301, example:

    Below accent: U+0x0316, example:

  • i

    Above accent: U+0x0307, example:

    Below accent: U+0x0323, example:

  • o

    Above accent: U+0x030c, example:

    Below accent: U+0x032d, example:

  • u

    Above accent: U+0x0311, example:

    Below accent: U+0x032e, example:

Here is the list of all possible characters:

b̠ b̖ ḅ b̭ b̮
c̄ ć ċ č c̑
d̠ d̖ ḍ ḓ d̮
f̠ f̖ f̣ f̭ f̮
ḡ ǵ ġ ǧ g̑
h̠ h̖ ḥ h̭ ḫ
j̄ j́ j̇ ǰ j̑
k̠ k̖ ḳ k̭ k̮
l̠ l̖ ḷ ḽ l̮
m̄ ḿ ṁ m̌ m̑
n̄ ń ṅ ň n̑
p̄ ṕ ṗ p̌ p̑
q̄ q́ q̇ q̌ q̑
r̄ ŕ ṙ ř ȓ
s̄ ś ṡ š s̑
t̠ t̖ ṭ ṱ t̮
v̄ v́ v̇ v̌ v̑
w̄ ẃ ẇ w̌ w̑
x̄ x́ ẋ x̌ x̑
ȳ ý ẏ y̌ y̑
z̄ ź ż ž z̑
ō ó ȯ ǒ ȏ

Test cases

  • Input: programming puzzles and code golf

Output: přgr̄mṁng p̑zzl̖s ōnd čd̖ ǧlf

  • Input: the quick brown fox jumps over the lazy dog

Output: th̖ q̑ȯck břwn f̭x j̑mps ǒv́r th̖ l̠zy ḓg

  • Input: beautiful

Outpu: b̖ōȏṭf̮l

  • Input: one ring to rule them all, one ring to find them, one ring to bring them all and in the darkness bind them

Output: ǒń ṙng ṱ ȓl̖ th̖m ōll, ǒń ṙng ṱ f̣nd th̖m, ǒń ṙng ṱ bṙng th̖m ōll ōnd ȯn th̖ d̠rkńss ḅnd th̖m

Scoring

This is , so the shortest program or function in bytes wins.

\$\endgroup\$
  • 7
    \$\begingroup\$ And suddenly reminded of why I chose not to try to learn Arabic. \$\endgroup\$ – Alex A. Jul 16 '15 at 15:27
  • \$\begingroup\$ I think the hard part is using the Unicode.. \$\endgroup\$ – DeadChex Jul 16 '15 at 20:57
  • \$\begingroup\$ Just to make it clear, you simply want a letter-to-accent-sign conversion, ignoring the actual pronunciation of the English words? \$\endgroup\$ – Paŭlo Ebermann Sep 13 '15 at 12:56
  • 1
    \$\begingroup\$ @PaŭloEbermann Yes. There are no real consistent rules to english pronunciation anyway. \$\endgroup\$ – Fatalize Sep 13 '15 at 12:59
  • \$\begingroup\$ @Fatalize: It can be understood through tough thorough thought, though. \$\endgroup\$ – Per Alexandersson Jan 13 '17 at 0:32
3
\$\begingroup\$

CJam, 63 62 bytes

Qq{_"aeiou"#:I){;___eu='o*\"bdfhklt"&"F<IST""*'-27"?I=730+}&}/

Try it online in the CJam interpreter.

How it works

Qq             e# Push an empty string and read from STDIN.
{              e# For each character in the input:
               e#   Push a copy of the character.
  "aeiou"#     e#   Find its index in "aeiou" (-1 for not found).
  :I)          e#   Save in I and add 1.
  {            e#   If I + 1 != 0:
    ;          e#     Discard the character.
    ___        e#     Copy the previous character (or the empty array) three times.
    eu=        e#     Convert the last copy to uppercase and check for equality.
               e#     This pushes 1 for non-letters and 0 for letters.
    'o*        e#     Push a string of that many o's.
    \          e#     Swap the last copy with the string of o's.
    "bdfhklt"& e#     Intersect with that string.
    "F<IST"    e#     Push that string.
    "*'-27"    e#     Push that string.
    ?          e#     Select the first iff the intersection is non-empty.
    I=         e#     Retrieve the character at index I.
    730+       e#     Add 730 to its code point.
  }&           e#
}/             e#
\$\endgroup\$
  • \$\begingroup\$ A full 206 bytes shorter than my solution. Nice. :) \$\endgroup\$ – Alex A. Jul 17 '15 at 20:09
8
\$\begingroup\$

GNU sed, 168 158 134 105 98 85 byt̖s

ǒr 75 ch̠rs (b̭th ȯncl̮ḍng +1 f̭r th̖ -r fl̠g).

s/([bdfhklt])([aeiou])/\1\u\2/g;y/aeiouAEIOU/̠̖̣̭̮̄́̇̌̑/;s/\B[^ ,a-z]/o&/g

óxpl̠n̄ṭǒn

Wó s̄v́ ō ḅt ȏṡng th̖ čnstr̄ȯnt th̠t ȯnp̑t ȯs ōll ḽẃr-c̄ś. Wó ȏpc̄ś ōny v̌ẃl f̭lḽẇng ō čnšn̄nt, b̖f̭ŕ čnv́rṭng ōll v̌ẃls ṱ ōcćnts.

#!/bin/sed -rf

s/([bdfhklt])([aeiou])/\1\u\2/g  # upcase vowel following ascender
y/aeiouAEIOU/̠̖̣̭̮̄́̇̌̑/
s/\B[^ ,a-z]/o&/g                # precede with 'o' if needed

Th̖ ǒdd-ḽǒḳng ch̠r̄ct̖rs ōŕ // čnt̠ȯṅng ōll t̖n ōcćnts (/̠̖̣̭̮̄́̇̌̑/). óxp̄nd̖d ǒȏt ẇth sp̄ćs, th̖y w̌ȏld ḽǒk ḷk̖ / ̄ ́ ̇ ̌ ̑ ̠ ̖ ̣ ̭ ̮ /.

ǒȏtp̑t

přgr̄mṁng p̑zzl̖s ōnd čd̖ ǧlf
th̖ q̑ȯck břwn f̭x j̑mps ǒv́r th̖ l̠zy ḓg
b̖ōȏṭf̮l
ǒń ṙng ṱ ȓl̖ th̖m ōll, ǒń ṙng ṱ f̣nd th̖m, ǒń ṙng ṱ bṙng th̖m ōll ōnd ȯn th̖ d̠rkńss ḅnd th̖m
\$\endgroup\$
  • \$\begingroup\$ 1. The output of the first test case is wrong. Looping is not the same as appending g to each s since the last five commands may replace digits after underscores. If you loop only over the first five and use y for the rest, you shorten and correct the code at the same time. 2. You can save more bytes by doing s/([ ,aeiou])([aeiou])/\1~\2/g at the beginning and replacing ~ with o in the transliteration. \$\endgroup\$ – Dennis Jul 18 '15 at 3:15
  • \$\begingroup\$ Thanks for your observation (1) - fix pending. I didn't think that y would work with multi-byte characters, but I've now tried it and it does - I should have tested to begin with. Your suggestion (2) fails with the last example which would need (^|[ ,aeiou]) instead of ([ ,aeiou]) - I tried something like that and lost (actually it was (^|[ ,1-5]) after the first y). \$\endgroup\$ – Toby Speight Jul 21 '15 at 7:54
  • \$\begingroup\$ I've now updated - and now I know that y works by character rather than by byte, I replace with accents immediately. Thanks @Dennis for prompting my improvements. I now remember why inserting o with a single step didn't work (e.g. suggestion to use s/([ ,aeiou])([aeiou])/\1~\2/g) - this only makes one replacement when there's two consecutive vowels, leading to b̖ō̑ṭf̮l for testcase 3. So I've stuck with inserting too many o and removing the unnecessary ones afterward. \$\endgroup\$ – Toby Speight Jul 21 '15 at 8:14
  • \$\begingroup\$ 1. I cannot copy and paste your golfed code. A lot of characters are missing. Copying the ungolfed code works just fine, but I count only 104 bytes. Not sure if I'm still missing one. 2. [^ ,a-z] is shorter and should work fine in the last substitution. \$\endgroup\$ – Dennis Jul 21 '15 at 14:42
  • \$\begingroup\$ @Dennis - 1. I printed the reduced code to xterm and then pasted that; perhaps xterm converted to precomposed or something? I'll try doing it directly within emacs. And did you count 1 for -r? 2. I still don't see how [^ ,a-z] will create the initial o in the last testcase. Edit: I see what you mean - shorter than the ten accents in the second group. Even better, [^ -~] will work, to save a further 2. \$\endgroup\$ – Toby Speight Jul 21 '15 at 15:34
2
\$\begingroup\$

Julia, 269 bytes

This is really long and can probably be golfed further, but I'm just psyched that I was able to come up with a working solution at all!

s->(u=700+[72,69,75,80,85];l=800+[0,-10,3,13,14];R=replace;r(m)=(i=findin("aeiou",m[2])[1];j=m[1]∈"bdfhklt"?l[i]:u[i];string(m[1],char(j)));t(m)=string("o",char(u[findin("aeiou",m)[1]]));R(R(R(s,r"(?![eiou])[b-z][aeiou]",r),r"(?<=^| )[aeiou]",t),r"(?<=\S)[aeiou]",r))

This creates an unnamed function that accepts a string and returns a string.

Ungolfed + explanation:

function f(s)
    # Construct arrays of integers representing the unicode accents
    # u is for the upper accents and l is for the lower
    u = 700 + [72,69,75,80,85]
    l = 800 + [0,-10,3,13,14]

    # Define a function to accent consonants followed by vowels
    r(m) = begin
        # m is the consonant-vowel pair from the regex match
        i = findin("aeiou", m[2])[1]
        j = m[1] ∈ "bdfhklt" ? l[i] : u[i]
        string(m[1], char(j))
    end

    # Define a function to accent vowels
    t(m) = string("o", char(u[findin("aeiou", m)[1]]))

    # Accent consonants
    rep1 = replace(s, r"(?![eiou])[b-z][aeiou]", r)

    # Accent vowels at the start of a string or before a space
    rep2 = replace(rep1, r"(?<=^| )[aeiou]", t)

    # Accent remaining unaccented vowels
    rep3 = replace(rep2, r"(?<=\S)[aeiou]", t)

    # Return
    rep3
end

Examples:

julia> println(f("beautiful"))
b̖ōȏṭf̮l

julia> println(f("programming puzzles and code golf"))
přgr̄mṁng p̑zzl̖s ōnd čd̖ ǧlf

Note that if you look at the raw text in the post, the "t" in the first example is accented correctly but for some reason it doesn't display that way in the rendered markdown, at least for me.

\$\endgroup\$
  • \$\begingroup\$ As long as it displays correctly in your examples for me (and it does), it's good \$\endgroup\$ – Fatalize Jul 17 '15 at 18:44
  • 1
    \$\begingroup\$ @Fatalize Oh I'm glad it displays correctly for you. I wonder why it doesn't for me. Regardless, nice challenge, glad I could participate! \$\endgroup\$ – Alex A. Jul 17 '15 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.