| Bytes | Lang | Time | Link |
|---|---|---|---|
| 047 | Retina | 180606T203209Z | Neil |
| 180 | Yabasic | 180801T124657Z | Taylor R |
| 276 | Red | 180609T154913Z | Galen Iv |
| 130 | Haskell | 180607T175957Z | amalloy |
| 059 | Perl 5 | 180606T210741Z | breadbox |
| 034 | 05AB1E | 180607T175808Z | Magic Oc |
| 593 | SWIProlog | 180608T094903Z | Jan Droz |
| 028 | Japt P | 180607T233404Z | Bubbler |
| 500 | TSQL | 180607T153241Z | Jan Droz |
| 125 | Python 3 | 180607T180127Z | ShadowRa |
| 104 | Powershell | 180607T121544Z | mazzy |
| 064 | sed 4.2.2 | 180607T083436Z | KernelPa |
| 082 | JavaScript | 180607T095209Z | MT0 |
| 119 | Python 2 | 180606T180210Z | Chas Bro |
| 223 | Standard ML | 180606T225104Z | Laikoni |
| nan | 180606T222851Z | Brad Gil | |
| 105 | JavaScript ES6 | 180606T194424Z | Rick Hit |
| 115 | JavaScript ES6 | 180606T193808Z | Downgoat |
| 125 | JavaScript Node.js | 180606T175937Z | Luis fel |
Retina, 48 47 bytes
i`(?<=([aeiou]).*?[b-z-[eiou]])(?![aeiou])
$l$1
Try it online! Explanation: The lookahead searches for a point not followed by a vowel, while the lookbehind searches for an immediately preceding consonant and a previous vowel, which is then inserted in lower case. Edit: Saved 1 byte by using character class subtraction.
Yabasic, 180 bytes
A full program which takes input from STDIN and outputs to STDOUT
Line Input""s$
x$="AEIOUaeiou"
For i=1To Len(s$)
c$=Mid$(s$,i,1)
?c$;
If InStr(x$,c$)Then
v$=c$
Else
a=Asc(Upper$(c$))
If a>64And a<91And!InStr(x$,Mid$(s$,i+1,1))Then?v$;Fi
Fi
Next
Red, 276 bytes
func[s][v: charset t:"AEIOUaeiou"c: charset
u:"BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"b:
parse s[collect[any keep[thru c opt v]keep thru end]]p:""foreach
c b[either find t e: last c: to-string c[p: e][parse c[any[copy p v
| skip]]if find u e[append c lowercase p]]prin c]]
Readable:
f: func [ s ] [
v: charset t: "AEIOUaeiou"
c: charset u: "BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"
b: parse s [
collect [ any keep [ thru c opt v ]
keep thru end ]
]
p: ""
foreach c b [
e: last c: to-string c
either find t e [ p: e ][
parse c [ any [ copy p v | skip ] ]
if find u e [ append c lowercase p ]
]
prin c
]
]
Haskell, 142 130 bytes
""&
import Data.Char
v=(`elem`"aeiouAEIOU")
s&(x:y:z)|v y=x:s&(y:z)
s&(x:y)|v x=x:[toLower x]&y|isAlpha x=x:s++s&y|1>0=x:s&y
_&x=x
The initial ""& is a partial application of the (&) function defined later on, and is placed so oddly to make TIO count the bytes in ""&, but not count the bytes that, in a full program, would be needed to assign that to any named value.
Less golfed:
import Data.Char (isAlpha, toLower)
vowel :: Char -> Bool
vowel = (`elem`"aeiouAEIOU")
replace :: String -> String
replace = go "" -- start by carrying no extra vowel
where go _ "" = ""
-- special case for "anything followed by vowel" so later cases can ignore next character
go s (x:y:more) | vowel y = x : go s (y:more)
go s (x:xs) | vowel x = x : go [toLower x] xs -- update the vowel we're carrying
| isAlpha x = x : s ++ go s xs -- non-vowel letter not followed by a vowel
| otherwise = x : go s xs -- some non-letter junk, just include it and carry on
There really ought to be a way to do this more concisely with a fold instead of recursion, but I couldn't figure it out.
Perl 5, 68 67 59 bytes
perl -pe '$v="[aeiou])";1while s/($v[^a-z]*[b-z]\K(?<!$v(?!$v/\L$1/i'
Here's a great example of the usefulness of \K, and I can't believe I didn't know about this feature before Dom Hastings pointed it out.
I haven't been able to get the right behavior with just using s///g, so an actual loop seems necessary. (It's possible that the right use of a look-behind assertion could work without an explicit while -- but I haven't found it.)
05AB1E, 34 bytes
vyžMylåil©1V}žPylåžM¹N>èå_Y&&i®«}J
I take that back I can only shave 3 bytes off this monstrosity... I think I could shave the boolean down, but there MUST be 3 cases. 1 for vowels. 1 for consonants. 1 for the case that a digit/symbol exists.
v # For each...
y # Push current element.
žM # Push lower-case vowels (aeiou).
ylå # Lower-case current element is vowel?
i©1V} # If so, put it in register, set Y to 1.
žP # Push lower-case consonants (b...z)
ylå # Is current char a consonant?
žM¹N>èå_ # Push vowels again, is input[N+1] NOT a vowel?
Y # Did we ever set Y as 1?
&& # All 3 previous conditions true?
i®«} # Concat the current vowel to the current char.
J # Join the whole stack.
# '}' isn't needed here, b/c it's implied.
# Implicit return.
SWI-Prolog, 593 bytes
a(S,D):-atom_chars(S,D).
g(_,[],_,-1).
g(E,[E|_],R,R).
g(E,[_|T],I,R):-N is I+1,g(E,T,N,R).
c(A,E):-g(E,A,0,R),R > -1.
v(X):-a('AEIOUaeiou',X).
c(X):-a('BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz',X).
d([_],_,R,R).
d([H|T],_,I,R):-v(V),c(V,H),!,d(T,H,I,[H|R]).
d([H,N|T],V,I,R):-c(C),c(C,H),v(W),c(W,N),!,d([N|T],V,I,[H|R]).
d([H,N|T],V,I,R):-c(C),c(C,H),v(W),\+c(W,N),string_lower(V,LV),!,d([N|T],V,I,[LV,H|R]).
d([H|T],V,I,R):-!,d(T,V,I,[H|R]).
r([],Z,Z).
r([H|T],Z,A):-r(T,Z,[H|A]).
r(S,D):-r(S,D,[]).
m(X,R):-a(X,O),r(O,P),r([''|P],Q),d(Q,'',I,[]),r(I,J,[]),atomic_list_concat(J,R).
Used only built-in predicates (without regex or list manipulating library).
Usage:
?- m('A pnm bnn').
'A panama banana'
true .
Japt -P, 28 bytes
ó@\ctX ©\VtYÃËè\v ?P=D:D¬qPv
Unpacked & How it works
UóXY{\ctX &&\VtY} mD{Dè\v ?P=D:Dq qPv
UóXY{ } Split the string between any two chars that don't satisfy...
\ctX &&\VtY The first char is a consonant and the second is a non-vowel
mD{ And map...
Dè\v If this item is a vowel...
?P=D Assign it to P and return as-is
:Dq qPv Otherwise, split the item into chars and join with P lowercased
(P starts with "", so beginning consonants are not affected)
-P Join with ""
The ó function wins over any kind of regexes.
TSQL, 500 bytes
CREATE TABLE i (i CHAR(999)); INSERT i VALUES ('The rain in Spain stays mainly in the plain')
DECLARE @w CHAR(999)=(SELECT i FROM i),@r VARCHAR(999)='';WITH d(n,c,i,q)AS(SELECT n,SUBSTRING(@w,n,1),CHARINDEX(SUBSTRING(@w,n,1),'AEIOUaeiou'),CHARINDEX(SUBSTRING(@w,n,1),'BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz')FROM(SELECT DISTINCT number n FROM master..[spt_values]WHERE number BETWEEN 1 AND LEN(@w))D)SELECT @r=@r+f.c+LOWER(COALESCE(CASE WHEN f.q<>0 AND COALESCE(d2.i,0)=0 THEN SUBSTRING(@w,(SELECT MAX(n)FROM d WHERE i<>0 AND n<f.n),1)END,''))FROM d f LEFT JOIN d d2 ON f.n=d2.n-1 SELECT @r
Table i is used for input
Python 3, 125 bytes
lambda s,v='[^aeiouAEIOU':sub(f'(?<={v}\W\d])(?={v}]|$)',lambda m:sub(f'{v}]','',s[:m.end()])[-1:].lower(),s)
from re import*
Python 3.6 allows us to (ab)use f-strings to reuse our set of vowels (and for four more characters saved, the beginning of an inverted regex character class) cheaply (a f prefix on each string, then {v} as needed, instead of the '+v+' you'd need with concatenation, or the [^aeiouAEIOU you'd insert literally.
The regex that matches no characters, just a position, avoids issues with the non-overlapping matches normal regexes require, and removes the need to backreference any part of the match; all we use the match object for is to get the slice index we use to find the prior vowel.
Partially de-golfed, it would be something like:
import re
def get_last_vowel(string):
'''
Returns the lowercase version of the last vowel in a string if
the string contains any vowels, otherwise, return the empty string
'''
try:
*restvowels, lastvowel = re.sub(r'[^aeiouAEIOU]', '', string)
except ValueError:
lastvowel = '' # No vowels in string
return lastvowel.lower()
def rememebere_tehe_vowelese(string):
'''Inserts the lowercased last vowel seen after any consonant not followed by a vowel'''
return re.sub(r'(?<=[^aeiouAEIOU\W\d])(?=[^aeiouAEIOU]|$)',
lambda match: get_last_vowel(string[:match.end()]),
string)
Powershell, 104 bytes
based on Neil's regular expression.
[regex]::Replace($args,'(?i)(?<=([aeiou]).*?[^\W\d_aeiou])(?![aeiou])',{"$($args.Groups[1])".ToLower()})
save it as get-rememebere.ps1. Script for testing:
$test = @"
AN EXAMPLE WITH A LOT UPPERCASE (plus some lowercase)
And here comes a **TEST** case with 10% symbols/numbers(#)!
This is an example string.
abcdefghijklmnopqrstuvwxyz
A pnm bnn
Tell me if you need more test cases!
"@
$expected = @"
ANa EXAMaPaLE WITiHi A LOTo UPuPEReCASE (pelusu some lowerecase)
Anada here comese a **TESeTe** case witihi 10% siyimiboloso/numuberese(#)!
Thisi isi ana examapale seterinigi.
abacadefegehijikiliminopoqorosotuvuwuxuyuzu
A panama banana
Telele me ifi you neede more tesete casese!
"@
$result = .\get-rememebere.ps1 $test
$result -eq $expected
$result
JavaScript, 88 82 Bytes
Done with a single regular expression:
Original Version (88 Bytes):
s=>s.replace(/(?<=([aeiou]).*?(?![aeiou])[a-z])(?=[^aeiou]|$)/gi,(_,c)=>c.toLowerCase())
Updated Version (82 Bytes) after looking at Neil's regular expression:
s=>s.replace(/(?<=([aeiou]).*?[^\W\d_aeiou])(?![aeiou])/gi,(_,c)=>c.toLowerCase())
var tests = {
"AN EXAMPLE WITH A LOT UPPERCASE (plus some lowercase)":
"ANa EXAMaPaLE WITiHi A LOTo UPuPEReCASE (pelusu some lowerecase)",
"And here comes a **TEST** case with 10% symbols/numbers(#)!":
"Anada here comese a **TESeTe** case witihi 10% siyimiboloso/numuberese(#)!",
"This is an example string.":
"Thisi isi ana examapale seterinigi.",
"abcdefghijklmnopqrstuvwxyz":
"abacadefegehijikiliminopoqorosotuvuwuxuyuzu",
"A pnm bnn":
"A panama banana",
"Tell me if you need more test cases!":
"Telele me ifi you neede more tesete casese!"
};
for ( test in tests )
{
var result = (s=>s.replace(/(?<=([aeiou]).*?[^\W\d_aeiou])(?![aeiou])/gi,(_,c)=>c.toLowerCase()))(test);
console.log( result === tests[test], result );
}
Python 2, 134 119 bytes
def f(s,v=''):u=s[:1];return s and u+v*(u.isalpha()-g(u)-g((s+u)[1]))+f(s[1:],[v,u.lower()][g(u)])
g='aeiouAEIOU'.count
EDIT: 15 bytes thx to Lynn
Standard ML, 225 223 bytes
str o Char.toLower;fun?c=String.isSubstring(it c)"aeiou"fun g(x,l)$d=(fn l=>if Char.isAlpha$andalso not(?d)then if? $then(it$,l)else(x,l^x)else(x,l))(l^str$)fun f$(c::d::r)=f(g$c d)(d::r)|f$[c]= #2(g$c c);f("","")o explode;
Less golfed:
val lower = str o Char.toLower
fun isVowel c = String.isSubstring (lower c) "aeiou"
(* c is the current char, d is the next char, x is the last vowel and l the accumulator
for the resulting string *)
fun g (x,l) c d =
if Char.isAlpha c andalso not (isVowel d)
then if isVowel c
then (lower c, l^str c)
else (x, l^str c^x)
else (x, l^str c)
fun f t (c::d::r) = f (g t c d) (d::r)
| f t [c] = #2(g t c #"d")
val h = f ("","") o explode;
Perl 6, 75 73 71 69 bytes
{({S:i/.*(<[aeiou]>).*<-[\W\d_aeiou]><()><![aeiou]>/$0.lc()/}...*eq*).tail}
{({S:i{.*(<[aeiou]>).*<-[\W\d_aeiou]><()><![aeiou]>}=$0.lc}...*eq*).tail}
{({S:i{.*(<[aeiou]>).*<:L-[_aeiou]><()><![aeiou]>}=$0.lc}...*eq*).tail}
{({S:i{.*(<[aeiou]>).*<:L-[_aeiou]><(<![aeiou]>}=$0.lc}...*eq*).tail}
Expanded:
{ # bare block lambda with implicit parameter $_
(
# generate a sequence
{ # code block used to generate the values
S # substitute (not in-place)
:i # :ignorecase
{
.* # start at end of string
( <[aeiou]> ) # store the previous vowel in $0
.*
<:L - [_aeiou]> # letter other than a vowel
<( # ignore everything before this
# this is where `$0.lc` gets inserted
# )> # ignore everything after this
<![aeiou]> # not a vowel (zero width lookahead)
} = $0.lc # replace with lowercase of the earlier vowel
}
... # keep generating until:
* eq * # there are two equal strings (no changes)
).tail # get the last value
}
JavaScript (ES6), 108 105 bytes
(Saved 3 bytes thanks to @Shaggy.)
f=s=>(t=(s+=' ').replace(/[aeiou]|[a-z][^aeiou]/ig,r=>r[1]?r[0]+v.toLowerCase()+r[1]:v=r,v=''))!=s?f(t):s
Searches for vowels or for consonants with no following vowel:
/[aeiou]|[a-z][^aeiou]/ig
(We don't need to search for consonants explicitly, because vowels are excluded based on the /[aeiou]|....)
Vowels are stored in v, and consonants with no following vowel have v inserted:
r[1]?r[0]+v.toLowerCase()+r[1]:v=r
(If r[1] exists, we've matched on a consonant plus non-vowel.)
If nothing has been changed, we return the input. Otherwise, we recurse on the replaced string.
f=s=>(t=(s+=' ').replace(/[aeiou]|[a-z][^aeiou]/ig,r=>r[1]?r[0]+v.toLowerCase()+r[1]:v=r,v=''))!=s?f(t):s
console.log(f('A pnm bnn'));
console.log(f('abc'));
console.log(f('AN EXAMPLE WITH A LOT UPPERCASE (plus some lowercase)'));
console.log(f('And here comes a **TEST** case with 10% symbols/numbers(#)!'));
console.log(f('This is an example string.'));
console.log(f('abcdefghijklmnopqrstuvwxyz'));
console.log(f('Tell me if you need more test cases!'));
JavaScript ES6, 115 bytes
Saves 8 bytes thanks to @ETHProductions
s=>[x="",...s].map((i,j)=>(r=/[aeiou]/i).test(i)?x=i:/[a-z]/i.test(i)&&!r.test(s[j]||1)?i+x.toLowerCase():i).join``
I have managed to inflate this more in the process of golfing it O_o but it also fixes a bug
s=>[x="",...s].map( // Create a new array with x storing last vowel
// This also offsets indexes by one so rel to original str refers to next char
(i,j)=> // Going through each char...
(r=/[aeiou]/i).test(i)? // If it's vowel, store it in x
x=i:
/[a-z]/i.test(i) // If a letter (thats not a vowel excluded by above)
&&!r.test(s[j]||1)? // Test if next char is *not* vowel
i+x.toLowerCase():i // If it isn't, then add the most recent vowel after
).join`` // Combine back to string
JavaScript (Node.js), 146 143 132 127 125 bytes
(a,v="")=>[...a].map((b,i)=>(w=/[aeiou]/i).test(b)&&(v=b)?b:w.test(a[i+1]||b)||!b.match(/[a-z]/i)?b:b+v.toLowerCase()).join``