Communistic Substring Normalization
JavaScript (ES6), 121 bytes
f=(s,j=2,o,m=s.match(`(.{${j}})(.*\\1){${(j-1)}}`))=>m?f(s,j+1,s.split(m[1]).map((e,i)=>e+(m[1][i]||'')).join``):o?f(o):s
Recursively matches the pattern:
(.{2})(.*\1){1} //2 characters, repeated 1 time
(.{3})(.*\1){2} //3 characters, repeated 2 times
(.{4})(.*\1){3} //4 characters, repeated 3 times
etc.
… until the pattern isn't found. (This guarantees that the longest string is handled first.)
It then performs the "communistic transformations" on the last-found pattern, by splitting on the match, and joining on each of the match's characters. (map
is used for this purpose. Too bad join
doesn't take a callback.)
It finally recurses on this new string until it is no longer communistic.
Test cases:
f=(s,j=2,o,m=s.match(`(.{${j}})(.*\\1){${(j-1)}}`))=>m?f(s,j+1,s.split(m[1]).map((e,i)=>e+(m[1][i]||'')).join``):o?f(o):s
console.log(f('123')); //123
console.log(f('111')); //111
console.log(f('1111')); //11
console.log(f('ABAB')); //AB
console.log(f('111111111')); //111
console.log(f('asdasdasd')); //asd
console.log(f('10/10')); //1/0
console.log(f('100/100+100')); //1/0+0
console.log(f(' + + ')); // +
console.log(f('Hello, hello, dear fellow!')); //Heo hl, dear flow!
console.log(f('11122333/11122333/11122333')); //132/23
Pyth, 22 bytes
u.xse.iLcGdf>cGTlTt#.:
To actually see what the program is doing, check out this:
Internals
In particular, the program always uses the final-occuring replacement of the longest replacements.
Explanation:
u.xse.iLcGdf>cGTlTt#.:
u.xse.iLcGdf>cGTlTt#.:G)GQ Implicit
u Q Starting with the input, repeat the following
until a fixed point is reached.
.:G) Construct all substrings of the current value
ordered smallest to largest, front to back.
t# Filter on having more than 1 element.
These are the eligible substrings.
f Filter these substrings on
cGT Chop the current value on the substring,
> lT Then remove the first len(substring) pieces.
The result is nonempty if the substring is
one we're looking for.
Chopping gives nonoverlapping occurrences.
.iL Interlace the substrings with
cGd Chop the current value on that substring
se Take the final result, make it a string.
.x G If there weren't any, the above throws an error,
So keep the current value to halt.