Monday Mini-Golf #6: Meeesesessess upp teeexexextext

Monday Mini-Golf: A series of short challenges, posted (hopefully!) every Monday.

True story1: The other day, I was playing around on my tablet when I had the idea to visit the page I normally use on my PC for testing JavaScript. After the page loaded, I entered this simple program:

alert("Hello!")


I then proceeded to press the Execute button, and was surprised when it told me that the code I had entered was invalid. I took a second look at the textbox and saw this:

alllelelerlerlertlert("Heeelelellellelloello!")


Wha??? That's not what I entered! So what happened here? To figure it out, I entered two simple lines:

abcdefg
0123456


This turned out as:

abbbcbcbcdbcdbcdebcdebcdefbcdefbcdefgbcdefg
0112123123412345123456


By now, I still had no clue about what happened to letters, but the numbers seemed simpler, so I took a closer look. As it turned out, the webpage was simply entering the first character, then repeating all the rest in the string every time a new one was pressed:

0112123123412345123456
0
1
12
123
1234
12345
123456


But what about the sections of letters? After pondering for a minute, I realized that it's just the same, but instead of repeating each subsection once, it repeats it twice:

abbbcbcbcdbcdbcdebcdebcdefbcdefbcdefgbcdefg
a
bb
bcbc
bcdbcd
bcdebcde
bcdefbcdef
bcdefgbcdefg


A combination of the two works with a combination of these techniques:

abc123z
abbbcbcbc1bc12bc123bc123zbc123z
a
bb
bcbc
bc1
bc12
bc123
bc123zbc123z


Whatever glitch causes this seems to reset at punctuation and spaces, so abc def becomes abbbcbc deeefef.

By this point, I was so absorbed in figuring it out and turning it into an interesting challenge that I forgot why I had been on there in the first place. (I did figure out how to type normally, however: pressing space-backspace after every character. Pretty tedious, but you gotta do what you gotta do.)

Challenge

The goal of the challenge is to write a program or function that takes in the text to be processed, makes the changes listed above, and outputs/returns the result.

Details

• The input will only contain printable ASCII, and no tabs or newlines.

Test-cases

Inputs: (one per line)

Mess up text
This is some longer text.
CAPS LOCK && "Punc-tua"+'tion'
under_score_style
CaPs wItHIn loWERs
1337 numb3r5
abcdefghij 0123456789
Code-golf is the best!


Outputs:

Meeesesessess upp teeexexextext
Thhhihihishis iss sooomomomeome looononongongongeongeongeronger teeexexextext.
CAAAPAPAPSAPS LOOOCOCOCKOCK && "Puuunununcunc-tuuuaua"+'tiiioioionion'
unnndndndendendernder_scccococorcorcorecore_stttytytyltyltyletyle
CaaaPaPaPsaPs wIIItItItHItHItHIItHIItHInItHIn loooWoWoWEoWEoWERoWERoWERsoWERs
1333337 nuuumumumbumbumb3umb3rumb3rumb3r5
abbbcbcbcdbcdbcdebcdebcdefbcdefbcdefgbcdefgbcdefghbcdefghbcdefghibcdefghibcdefghijbcdefghij 0112123123412345123456123456712345678123456789
Cooodododeode-gooolololfolf iss thhhehe beeesesestest!


Scoring

This is , so shortest valid code in bytes wins. Tiebreaker goes to submission that reached its final byte count first. The winner will be chosen next Monday, Nov 2. Good luck!

Edit: And the winner is... @MartinBüttner using Retina for an incredible 43-byte solution!

1 Yes, this story is completely true, and if you need any more clarification, see footnote 1.

• That punctuation rule... ' '.join(x[0]+''.join(2*x[1:i]for i in range(1,len(x)+1)) for x in raw_input().split()) Oct 27, 2015 at 14:26
• cough Use the Chrome DevTools cough Oct 27, 2015 at 14:34
• @TheDoctor Check out my answer's edit history :P Oct 27, 2015 at 15:10
• @BetaDecay great minds think alike ;) Oct 27, 2015 at 15:50
• inb4 someone makes a language where you actually have to type like this. Nov 6, 2015 at 12:46

Retina, 43 bytes

.(?<=[^_\W]([^_\W]+))(?<=(\1)(?<=\D))?
$1$2


Run the code from a single file with the -s flag. Since this is just a single regex substitution, you can test it here (click the Context tab to see the results).

Explanation

This matches any digit and letter which is not the first in a run. While . can match any non-linefeed character, the lookbehinds ensure the other conditions:

(?<=[^_\W]([^_\W]+))


This matches backwards from the position after the .. First it matches one or more alphanumeric characters and captures them into group 1 with ([^_\W]+). This immediately ensures that the . corresponds to an alphanumeric character itself. Then the additional [^_\W] makes sure that there is one more alphanumeric character in the current run, which we don't include the match. Now group 1 is what we want to replace the match with if it is a digit - if it is a letter we want to replace it with twice this string. That's where the second lookbehind comes into play:

(?<=(\1)(?<=\D))?


This one is optional, so if it fails it won't affect the match at all. It first ensures that the . was not a digit via (?<=\D) - so this lookbehind is only relevant when we're matching letters. In that case, we match group \1 once more (this always matches, because we've captured the group from the same position), but capture it into group 2.

Hence, we simply replace the regex with the contents of both groups ($1$2). If the match was a digit, $2 will still be empty and we write back the prefix only once. If it was a letter, $2 is the same as $1 and we write it back twice. JavaScript(ES6) 82 Using the regexp optimization suggested by Mwr247 s=>s.replace(/([\W_])|./g,(x,y)=>y?(f=0,x):f?(p+=x,p+(-x-1?z:p)):(p=z,f=x),f=z='')  Test running the snippet below in any recent browser F=s=>s.replace(/([\W_])|./g,(x,y)=>y?(f=0,x):f?(p+=x,p+(-x-1?z:p)):(p=z,f=x),f=z='') // document.write(F(prompt('Insert string'))) // TEST console.log=x=>O.innerHTML+=x+'\n' function test() { O.innerHTML=F(I.value) } ;[ ['Mess up text','Meeesesessess upp teeexexextext'] ,['This is some longer text.', 'Thhhihihishis iss sooomomomeome looononongongongeongeongeronger teeexexextext.'] ,['CAPS LOCK && "Punc-tua"+\'tion\'', 'CAAAPAPAPSAPS LOOOCOCOCKOCK && "Puuunununcunc-tuuuaua"+\'tiiioioionion\''] ,['CaPs wItHIn loWERs' ,'CaaaPaPaPsaPs wIIItItItHItHItHIItHIItHInItHIn loooWoWoWEoWEoWERoWERoWERsoWERs'] ,['1337 numb3r5','1333337 nuuumumumbumbumb3umb3rumb3rumb3r5'] ,['abcdefghij 0123456789' ,'abbbcbcbcdbcdbcdebcdebcdefbcdefbcdefgbcdefgbcdefghbcdefghbcdefghibcdefghibcdefghijbcdefghij 0112123123412345123456123456712345678123456789'] ,['Code-golf is the best!' ,'Cooodododeode-gooolololfolf iss thhhehe beeesesestest!'] ].forEach(t => ( i=t[0],x=t[1],r=F(i), console.log('Test ' + (r==x?'OK':'Fail')+'\nInput: '+i+'\nResult: '+r+'\nCheck: '+x+'\n') )) #I { width: 50% } Your test<input id=I><button onclick="test()">-></button> <pre id=O></pre> • Holy cow! That's way different (and better) than I would have done it (similar to n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳'s approach). +1 Oct 27, 2015 at 13:57 JavaScript (ES6), 9288 87 f=>f.replace(/[^_\W]+/g,m=>m[0]+[...m].slice(1).reduce((a,e)=>a+=(y+=e,++e?y:y+y),y=''))  I have no idea how to golf this down... Thanks Mwir247 for the golfed down regex and ETHproductions for one byte golf in reduce function. • Use this for your regex: /[^_\W]+/g (saves 3 characters) Oct 27, 2015 at 5:57 • I believe this would work for the .reduce function: (a,e)=>a+=(y+=e,++e?y:y+y) (1 byte shorter) Oct 27, 2015 at 13:49 Gema, 57 characters \X?=?@set{s;} <D1>=@append{s;$0}$s <L1>=@append{s;$0}$s$s


Sample run:

bash-4.3$gema '\X?=?@set{s;};<D1>=@append{s;$0}$s;<L1>=@append{s;$0}$s$s' <<< '1337 numb3r5'
1333337 nuuumumumbumbumb3umb3rumb3rumb3r5


import Data.List
import Data.Char
c=concatMap
p c=[isDigit c,isAlpha c]
r(Just n)=c id.replicate(n+1)
r _=id
f(h:t)=h:(c(\s->r(findIndex id.p$last s)s).tail.inits)t m=c f.groupBy(\a b->or$p a==or$p b)  It's a mess. Have fun reading all the weird quirks, I never thought I would use id this much. Too bad the stuff that already does half the work here needs to be imported (isDigit,isAlpha,inits). • It's lang-hs not lang-haskell. By specifying lang-haskell it probably ends up using a default highlighter. Oct 27, 2015 at 17:02 Haskell, 183 181 bytes import Data.Char b(x:y)|h x=x:c[]y|2>1=x:b y b[]=[] h y=isDigit y||isAlpha y c x l@(y:z)|h y=c(y:x)z|2>1=c x[]++b l c x[]=reverse$g\$x
g[]=[]
g a@(x:y)|isDigit x=a++g y|2>1=a++a++g y


Usage:

b"Hello, world!"
>"Heeelelellellelloello, wooorororlorlorldorld!"


Don't know if it is essentially different with Leif Willerts' answer. But here's the algorithm.

1. Search for valid letter(Letter or Num)
2. If it letter, begin collecting letter. However, it is stored reversely, make the string reversed. And first item is omitted.
3. As it hit invalid letter, do the question's transform with reversed input. The question's transform is reverse.g.reverse, but since it is already reversed, then we just do reverse.g

I somehow keep redudant brackets.

T-SQL, 357 bytes

create proc x(@s varchar(99),@z int=0,@i int=0,@y varchar(99)='',@x varchar(99)='',@w varchar(99)='') as

while LEN(@s)>0
begin
select @z=patindex('%[^0-z]%',@s+' '),@i=1,@w+=LEFT(@s,1)
while @i<@z-1
begin
select @y=SUBSTRING(@s,2,@i)
,@x+=@y
,@i+=1
if @y like'%[a-z]'set @x+=@y
end
select @w+=@x+SUBSTRING(@s,@z,1)
,@x=''
,@s=REPLACE(@s,left(@s,@z),'')
end

select @w


ex: exec x(@s='1337 numb3r5') returns 1333337 nuuumumumbumbumb3umb3rumb3rumb3r5

Python 2, 131 Bytes

i=raw_input();s=r='';g=1
for c in i:
s+=c
if g:r+=c;g=0;s=''
elif c.isalpha():r+=s*2
elif '/'<c<':':r+=s
else:g=1;r+=c
print r


Loops through characters, and saves/repeats if required.

Pip, 41 bytes

aR[^_\W]+{[email protected]@{1,++y}X2-(_Q+_)MJa}


Takes the text as a command-line argument. We use a regex replacement to replace all alphanumeric runs ([^_\W]+) with a callback function. This function maps another function to each character of the word, generating progressively larger runs of characters (with the global variable y keeping track of the index) and repeating them X2 if the character is not a number. (The logic for which uses + to convert to a number and then Q to check whether this is string-equal to the original character.) This process leaves out the first character, though, so we have to add it on afterward (a@0.).

Python 3, 86 bytes

f=0
m=''
for i in input():g=i.isalnum();m=m*g*f+i*f;print(end=m*-~i.isalpha()or i);f=g


Try it online!