41
\$\begingroup\$

You have been hired by the American embassy in the UK to act as a translator. Being a programmer, you decide to write a program to do a bit of the work for you.

You've found out that often just doing the following things can satisfy Word's spellcheck, which has been set to "English (United States)", somewhat, so you don't have to do as much work later when translating written documents:

  • All occurrences of "our" can be replaced with "or", e.g. "favourite" -> "favorite", "our" -> "or".
  • All occurrences of "ise" and "yse" can be replaced with "ize" and "yze", respectively.
  • All occurrences of "ae" and "oe" can be replaced with "e".
  • All occurrences of "ll" that have a vowel before them can be replaced with "l".
  • The ending "re" can re replaced with "er", as long as it is not preceded by a vowel, e.g. "ore" will not be replaced, but "centre" becomes "center".
  • The ending "xion" can be replaced with "ction", e.g. "connexion" -> "connection" (this is archaic, but whatever).

Write a program or function that takes a string or list of characters as input, performs the replacements mentioned above, and outputs the modified string or list of characters using the standard IO methods.

Rules

  • A sequence of alphabetical characters is considered a word ([A-Za-z]). Words may be delimited by spaces, hyphens, commas, periods, or other punctuation characters ([^A-Za-z]).
  • A vowel is one of a, e, i, o, or u.
  • This is , so shortest code wins.
  • Inputs with conflicts are undefined behavior, e.g. if a word ends with "oure", your program can make it "ouer" or "ore".
  • Your program need only take one pass over the input - it's fine if you replaced something like "rae" and end up with "re" instead of further turning that into "er".
  • Substitutions may be done on uppercase and/or lowercase letters (you can choose). You may also output the letters in any case you want.

Test cases

Note that not all words have been translated correctly, since the rules described above are not always right. Also note that the text here has mixed case to try to look like normal English, but you can use all lowercase for your input and all uppercase for your output or whatever you want.

Substitutions are bolded or italicized if they are side by side.

Input
---
Output
______
We would like you to analyse something our agencies have discovered.
---
We would like you to analyze something or agencies have discovered.
______
There have been reports of American tourists travelling here in knight's armour.
---
There have been reports of American torists traveling here in knight's armor.
______
An aerosol may be the cause of their transfixion. Their oesophagi must be studied.
---
An erosol may be the cause of their transfiction. Their esophagi must be studied.
______
OURoullisaeisere
---
ORouliseizere
______
Pardon me, I just fell on my keyboard while dodging a knight with a metre-long sword.
---
Pardon me, I just fel on my keyboard while dodging a knight with a meter-long sword.
______
My keysere n'twourkingnowneithre r myhands hellllpme
---
My keyzere n'tworkingnowneither r myhands helllpme
______
Haha, I'm just messing with you. No knights here with 3.28-foot-long swords. That's totally ridiculous.
---
Haha, I'm just messing with you. No knights here with 3.28-foot-long swords. That's totaly ridiculous.
\$\endgroup\$
8
  • \$\begingroup\$ Is the input guaranteed to be printable ASCII, or do we have to support other Unicode characters as well? \$\endgroup\$ Dec 9, 2020 at 9:49
  • 3
    \$\begingroup\$ @KevinCruijssen Sure, if you need to. No need to support Unicode \$\endgroup\$
    – user
    Dec 9, 2020 at 12:18
  • 1
    \$\begingroup\$ What should be the output for metres? No change? \$\endgroup\$
    – vrintle
    Dec 9, 2020 at 16:32
  • 1
    \$\begingroup\$ @vrintle Yes, no change. It doesn't end in re. \$\endgroup\$
    – user
    Dec 9, 2020 at 20:50
  • \$\begingroup\$ Accoring to your rules, "this is our home" shall be translated into "this is or home", correct? \$\endgroup\$ Dec 10, 2020 at 11:16

9 Answers 9

9
\$\begingroup\$

QuadR, 77 75 bytes

-2 thanks to Neil.

our
(i|y)se
ae|oe
([aeiou]l)l
([^aeiou])re\b
xion\b
or
\1ze
e
\1
\1er
ction

Try it online!

The first half of the strings are PCRE patterns while the latter half are their substitutions.

\$\endgroup\$
3
  • \$\begingroup\$ Why not (i|y)? \$\endgroup\$
    – Neil
    Dec 8, 2020 at 20:15
  • \$\begingroup\$ l)l saves another byte. \$\endgroup\$
    – Neil
    Dec 8, 2020 at 20:18
  • 7
    \$\begingroup\$ @Neil Because I didn't sleep last night. \$\endgroup\$
    – Adám
    Dec 8, 2020 at 20:20
7
\$\begingroup\$

Perl 5, -p 100 94 bytes

Saves 6 bytes since we can require all input to be lowercase, as pointed out by @NahuelFouilleul

s/our/or/g;s/[iy]\Kse/ze/g;s/ae|oe/e/g;s/[aeiou]l\Kl//g;s/[^aeiou]\Kre\b/er/g;s/xion\b/ction/g

Try it online!

\$\endgroup\$
1
  • 3
    \$\begingroup\$ /i modifiers may be removed ; from the question Substitutions may be done on uppercase and/or lowercase letters (you can choose). \$\endgroup\$ Dec 8, 2020 at 20:38
7
\$\begingroup\$

JavaScript (ES9), 126 bytes

Operates on lowercase patterns.

s=>s.replace(/(?<=o)u(?=r)|(a|o|(?<=i|y)s)(?=e)|(?<=[aeiou])l(?=l)|(?<![aeiou])re\b|x(?=ion)/g,s=>[{x:'ct',re:'er',s:'z'}[s]])

Try it online!

How?

All operations are processed within a single replace() with a callback function.

We use lookbehind and lookahead assertions so that the sub-strings that actually need to be modified are as small as possible and the replacement is just an implicit empty string whenever possible.

The non-empty replacement strings are stored in an object.

 pattern              | replacement
----------------------+------------------------------
 (?<=o)u(?=r)         | "u" -> ""
 (a|o|(?<=i|y)s)(?=e) | "a" or "o" -> "", "s" -> "z"
 (?<=[aeiou])l(?=l)   | "l" -> ""
 (?<![aeiou])re\b     | "re" -> "er"
 x(?=ion)             | "x" -> "ct"
\$\endgroup\$
6
\$\begingroup\$

Charcoal, 130 125 bytes

≔aeiouζ≔⁺ θηFiy≔⪫⪪θ⁺ιse⁺ιzeθF⌕AθreF¬∨№ζ§ηι№β§η⁺³ι≔⭆Φθ⁻μι⎇⁻μιλerθ⭆θ⎇∨№⁺⊕⌕Aθour⁺⌕Aθae⌕Aθoeκ∧№⌕Aθllκ№ζ§ηκω⎇∧№⌕Aθxionκ¬№β§η⁺⁵κctι

Try it online! Link is to verbose version of code. Expects lowercase input. Explanation:

≔aeiouζ

Get the vowels in a variable, as they're long enough for this to save a byte.

≔⁺ θη

Make a copy of the input with a space prepended. This is used for cyclic indexing, plus conveniently offsets the indices by one.

Fiy≔⪫⪪θ⁺ιse⁺ιzeθ

Replace ise and yse with ize and yze respectively.

F⌕Aθre

Find all occurrences of re...

F¬∨№ζ§ηι№β§η⁺³ι

... that are at the end of a word and do not follow a vowel...

≔⭆Φθ⁻μι⎇⁻μιλerθ

... and replace them with er.

⭆θ⎇∨№⁺⊕⌕Aθour⁺⌕Aθae⌕Aθoeκ∧№⌕Aθllκ№ζ§ηκω⎇∧№⌕Aθxionκ¬№β§η⁺⁵κctι

If the current character is:

  • the u of our
  • the a of ae
  • the o of oe
  • or the first l of ll and it follows a vowel

... then delete it, otherwise if it is the x that begins xion at the end of a word then replace it with ct, and output the final result.

\$\endgroup\$
6
\$\begingroup\$

Ruby -p, 110 101 100 bytes

A port of Arnauld's answer in Ruby.
Saved a whooping 9+1 bytes using \K, thanks to Dingus!!

gsub /o\Ku(?=r)|(a|o|[iy]\Ks)(?=e)|[aeiou]\Kl(?=l)|[^aeiou]\Kre\b|x(?=ion)/,?s=>?z,'re'=>:er,?x=>:ct

Try it online!

\$\endgroup\$
8
  • 2
    \$\begingroup\$ that moment when ruby is shorter than charcoal.. \$\endgroup\$
    – Razetime
    Dec 9, 2020 at 9:01
  • 1
    \$\begingroup\$ @Razetime It was hard enough getting Charcoal shorter than JS (regexp helping JS a lot here). \$\endgroup\$
    – Neil
    Dec 9, 2020 at 10:55
  • 1
    \$\begingroup\$ @Neil I know the feeling (just posted my 05AB1E answer). Lack of regex is annoying for this challenge.. :/ \$\endgroup\$ Dec 9, 2020 at 11:16
  • 1
    \$\begingroup\$ @KevinCruijssen At least you have a vowels builtin... \$\endgroup\$
    – Neil
    Dec 9, 2020 at 12:14
  • 1
    \$\begingroup\$ You can shorten this a bit using \K: Try it online!. (Removed test cases only because the link was too long for a comment.) \$\endgroup\$
    – Dingus
    Dec 10, 2020 at 5:30
5
\$\begingroup\$

Lexurgy, 106 bytes

Sound changes are what Lexurgy is made for!

Works in all lowercase only.

Class v {a,e,i,o,u}
o:
our=>or
{i,y} se=>{i,y} ze
{a,o}=>*/_ e
l=>*/@v _ l
re=>er/!@v _
x=>ct/_ ion

Ungolfed explanation:

# define vowels
Class vowel {a,e,i,o,u}

or:
our=>or

ize:
{i,y} se=>{i,y} ze

e:
{a,o}=>*/_ e

l:
l=>*/@vowel _ l

er:
re=>er/!@vowel _

ction:
x=>ct/_ ion
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 94 bytes

.•´iÈQ<¾Ÿ7ø₂2>“UcтλHZ•#2ä`.:žMS„ll«D€¨.:DžQAKS¡DεD"xion"Å¿i¨¨¨¨.•U®$•«}žNvDy„re«Å¿i¨¨¨y„erJ].;

Input in lowercase. Assumes the input will only contains printable ASCII characters.

Try it online or verify all test cases.

Explanation:

.•´iÈQ<¾Ÿ7ø₂2>“UcтλHZ• # Push compressed string "our ise yse ae oe or ize yze e e"
 #                     # Split it on spaces: ["our","ise","yse","ae","oe","or","ize","yze","e","e"]
  2ä                   # Split into 2 equal-sized blocks: [["our","ise","yse","ae","oe"],["or","ize","yze","e","e"]]
    `                  # Pop and push both lists separated to the stack
     .:                # Replace all
žM                     # Push builtin "aeiou"
  S                    # Convert it to a list of characters: ["a","e","i","o","u"]
   „ll«                # Append "ll" to each: ["all","ell","ill","oll","ull"]
       D۬             # Duplicate it, and remove the last character of each: ["al","el","il","ol","ul"]
          .:           # Replace all
D                      # Duplicate the current string
 žQ                    # Push a builtin with all printable ASCII characters
   AK                  # Remove the lowercase alphabet from it
     S                 # Split it to a list of characters
      ¡                # And split the duplicated string on these non-letter characters
D                      # Duplicate the list of words
 ε                     # Map over each word:
  D                    #  Duplicate the current word
   "xion"ſi       }   #  Pop, and if it ends with "xion":
            ¨¨¨¨       #   Remove the final four characters from the word
            .•U®$•«    #   And append (compressed) "ction"
  žN                   #  Push buitin "bcdfghjklmnpqrstvwxyz"
    v                  #  Loop `y` over each of its characters:
     D                 #   Duplicate the current word
      y„re«            #   Push the current consonant, and append "re"
           ſi         #   If it ends with "Cre" (where `C` is the consonant)
              ¨¨¨      #    Remove the final three characters from the word
              y„erJ    #    Push the consonant and "er" and join all three together
]                      # Close the open if-statement, loop, and map
 .:                    # And replace all
                       # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to compress strings not part of the dictionary?) to understand why .•´iÈQ<¾Ÿ7ø₂2>“UcтλHZ• is "our ise yse ae oe or ize yze e e" and .•U®$• is "ction".

\$\endgroup\$
3
\$\begingroup\$

Wolfram Language (Mathematica), 227 181 bytes

saved 46 bytes thanks to comment.

Try it online!

R:=RegularExpression
f[s_]:=StringReplace[s,{"our"->"or","ise"->"ize","yse"->"yze","ae"->"e","oe"->"e",R["(?<=[aeiou])ll"]->"l",R["(?<=[^aeiou])re\\b"]->"er",R["xion\\b"]->"ction"}]

Ungolfed version:

f[s_String] := Module[
  {replacements, result},
  replacements = {
    "our" -> "or",
    "ise" -> "ize",
    "yse" -> "yze",
    "ae" -> "e",
    "oe" -> "e",
    RegularExpression["(?<=[aeiou])ll"] -> "l",
    RegularExpression["(?<=[^aeiou])re\\b"] -> "er",
    RegularExpression["xion\\b"] -> "ction"
  };
  result = StringReplace[s, replacements];
  result
]
\$\endgroup\$
1
  • \$\begingroup\$ It seems you can save 43 bytes by assigning RegularExpression to R: Try it online! (using URL shortener since the link is too long) \$\endgroup\$
    – The Thonnu
    Apr 8 at 13:31
2
\$\begingroup\$

Python 3.8, 158 154 bytes

Saved 4 bytes thanks to user!!!

lambda s:[(s:=re.sub(*x.split(),s))for x in r'our or|ise ize|yse yze|[ao]e e|(?<=[aeiou])ll l|(?<=[^aeiou])re\b er|xion\b ction'.split('|')][-1]
import re

Try it online!

Inputs a string in lower-case and returns its translation in lower-case.

\$\endgroup\$
4
  • \$\begingroup\$ Instead of a newline + indent for return, you can just use ;, making it x.split(),s);return s on line 3, saving 1 byte. \$\endgroup\$ Dec 10, 2020 at 2:51
  • \$\begingroup\$ @JohnZhau Not on the same line as a for loop, that'll make it return at the end of the first loop. \$\endgroup\$
    – Noodle9
    Dec 10, 2020 at 8:23
  • \$\begingroup\$ You can get 154/156 bytes with import re f=lambda s:[(s:=re.sub(*x.split(),s))for x in r'our or|ise ize|yse yze|[ao]e e|(?<=[aeiou])ll l|(?<=[^aeiou])re\b er|xion\b ction'.split('|')][-1] (sorry, TIO link was too big). reduce may have been even shorter, although the import is rather long \$\endgroup\$
    – user
    Dec 10, 2020 at 16:10
  • \$\begingroup\$ @user Sweet - thanks! :D \$\endgroup\$
    – Noodle9
    Dec 10, 2020 at 22:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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