| Bytes | Lang | Time | Link |
|---|---|---|---|
| 165 | C64 Basic | 250803T181810Z | OSI8 |
| 023 | 05AB1E | 250814T080727Z | Kevin Cr |
| 132 | Python | 250803T231053Z | Lucenapo |
| 112 | C clang | 250805T134541Z | jdt |
| 053 | Pyth | 250804T220202Z | Synoli |
| 103 | Perl 5 pl | 250801T231611Z | good old |
| 118 | JavaScript ES6 | 250801T102802Z | Arnauld |
| 047 | Charcoal | 250803T125737Z | Neil |
| 083 | Retina | 250802T194431Z | Neil |
| 233 | Python3 | 250801T153528Z | Ajax1234 |
| 214 | JavaScript Node.js | 250801T084636Z | rydwolf |
| 014 | Nekomata | 250801T034829Z | alephalp |
C64 Basic, 210 165 bytes
Here's a much shorter version of the original program. A big thanks to Robin from 8-Bit Show And Tell, who took a close look at my original code and was able to shorten it considerably.
0inputa$:j=1
1l=len(a$):i=j:j=l
2s=j-i:fOx=0tos:ifl<3ori=l-1tH?a$:eN
3s=s+(mI(a$,x+i,1)=mI(a$,j-x,1)):nE:ifs<0tHa$=leF(a$,i-1)+mI(a$,j+1):j=2
4j=j-1:on1-(j-1>i)gO1,2
05AB1E, 23 bytes
¸ΔεDŒāÌù˜ʒÂQ}õªδK}˜ê}éн
Try it online or verify all test cases.
Explanation:
¸ # Wrap the (implicit) input-string into a singleton list
Δ # Loop until the result no longer changes:
ε # Map over each inner string:
D # Duplicate the current string
Œ # Pop the copy, and get all its substrings
āÌù˜ # Remove all substrings of lengths 1 and 2:
ā # Push a list in the range [1,length] (without popping the list)
Ì # Increase each value by 2: [3,length+2]
ù # Map each value to the substrings of just that length
˜ # Flatten this list of lists
ʒ # Filter the remaining strings:
ÂQ # Check that the string is a palindrome:
 # Bifurcate the string; short for Duplicate & Reverse copy
Q # Check that the two strings are the same
}õª # After the filter: append an empty string in case none are left
δ # Map over each of the valid palindromes:
K # Remove them from the duplicated current string
}˜ # After the inner map: flatten the list of lists
ê # (Sort and) uniquify this list of strings
}é # After the changes-loop: sort the resulting strings by length
н # Pop and keep the first/shortest one
# (which is output implicitly as result)
Python, 146 145 140 132 bytes
def f(s):L,*w=len(s),s;[s[a:b]==s[a:b][::-1]==(w:=w+[f(s[:a]+s[b:])])for a in range(L)for b in range(a+3,L+1)];return min(w,key=len)
C (clang), 212 199 148 140 133 121 118 112 bytes
i,j,m,n;f(*s){for(i=0;s[i];i++)for(j=wcslen(s);--j>i+1;)for(m=i,n=j;m>n?wcscpy(s+i,s-~j)<f(s):s[m++]==s[n--];);}
-14 bytes thanks to @ceilingcat!
Pyth, 53 bytes
L&>lb2qb_bL{u+G|{m|s-Fdkm,dy#df.EyMT./H]HbYh.mlbu'G]w
Explanation
Is b an eligible palindrome?
L # Declare a lambda `g(b)` …
& # … which tests if both of the following are true:
>lb2 # b is more than 2 characters long?
qb_b # b is equal to the reversed form of itself?
Remove a single palindrome
This lambda tries to find all the ways to remove a single palindrome. We accept a list of strings. For each string, we try to remove a single palindrome. If we can’t find any palindromes, then that means the string can’t be made smaller and is a potential winning candidate, so we keep it in the list. If we have a palindrome, then we remove it and keep the result. If we find more than one palindrome, we don’t know yet which one is best, so we remove each palindrome separately and keep all the results.
Y # We’re going to use reduce, so start with an empty list.
b # Our input, the list of strings. Let’s feed it into reduce.
H # Maybe the string contains no palindromes. If so, keep it around …
] # … but for interface parity, let’s wrap it in a singleton list.
H # With that out of the way, take the characters from our string …
./ # and explode it into a massive list of all possible substring partitions.
yMT # For each substring, check whether it is a valid palindrome …
.E # … and if that happens at least once in our partition, then …
f # … keep the partition around, otherwise throw it away.
y#d # In our right hand, we take the substrings that are palindromes …
m,d # … in our left hand, we take the partition itself …
-Fd # … and fold them into each other, eliminating the palindrome.
# Conveniently, folding has removed each palindrome separately,
# and multiple palindromes have automatically split into two separate
# intermediate results. This is good, because we don’t know yet
# which palindrome was the best one to remove, so let’s keep all the options.
m s # Each result is still in form of a partition, so mend it back into a string.
| k # Is our partition empty? If so, fix the mess that `s` has made with its default value 0.
{ # Our power-set shenanigans are causing abysmal performance, so let’s
# deduplicate what we have to counteract the effect at least a little.
| # If there were no palindromes at all, fall back to the singleton list we prepared earlier.
u+G # Repeat for each input string and collect results.
{ # Deduplicate the resulting list once again …
L # … and define a lambda named `'` so we can repeat all of the above over and over.
Main routine
w # Start with the input string …
] # … and wrap it inside a singleton list. That’s our initial state.
'G # From each list element, try removing a single palindrome …
# … while keeping track of intermediate solutions …
u # … over and over again, until our list no longer changes.
# The list elements are now our potential winning candidates.
lb # Look at the number of characters …
.m # … of each candidate. Those with minimal length are our solutions.
h # More than one solution? If so, pick the first one.
Perl 5 -pl, 103 bytes
@,=$s=$_;/((.)(?1)\2|(.)(.)\4?\3)?(??{$1?push@,,$`.$':length$s>y!!!c?$s=$_:1;0})/,$_=pop@,while@,;$_=$s
More readable:
@, = $s = $_;
/
( (.)(?1)\2 | (.)(.)\4?\3 )?
(??{
$1 ? push @,, $` . $'
: length $s > y!!!c ? $s = $_ : 1;
0
})
/x,
$_ = pop @, while @,;
$_ = $s
Perl 5, (non-competing) 458 bytes
$s = $_;
%seen = ();
while () {
/
(?>^.*?)
(
(
(.)(?-3)\g-1|(.)(.)\g-1?\g-2
)
(?{
$x = substr( $_, 0, $-[2] ) . substr( $_ , $+[2] );
unless ( $seen{ $x } ++ ) {
push @a, $x;
$s = $x if length( $s ) > length( $x )
}
})
)
/x;
last unless @a;
$_ = pop @a
}
$_ = $s;
Short version is terribly inefficient. Just for fun, this is a much faster version (approx. 1 sec for 16 "go"'s in linked TIO's input vs. 9 in the challenge's test case), which hopefully generates correct results.
JavaScript (ES6), 118 bytes
I/O format: arrays of characters.
f=(s,_=o=s)=>s.map((n,i)=>s.map(_=>(q=[...s],p=q.splice(i,n=-~n))[2]&&p+""==p.reverse()&&f(q,0)),s[o.length]?0:o=s)&&o
Commented
f = ( // f is a recursive function taking:
s, // s[] = input
_ = o = s // o[] = output, initialized to the input
) => //
s.map((n, i) => // for each character at index i in s[],
// with n zero'ish:
s.map(_ => // for each character in s[]:
( //
q = [...s], // q[] = copy of s[]
p = q.splice( // p[] = palindrome candidate
i, // extracted from q[] at index i
n = -~n // with a length of (at most) n
) // where n is incremented
)[2] && // if p[] is at least 3 characters long
p + "" == // and is a palindrome, i.e. it's equal
p.reverse() && // to its reversed form:
f(q, 0) // do a recursive call with q[]
// (the 2nd argument is here only
// to leave o[] unchanged)
), // end of inner map()
s[o.length] ? // if s[] is longer than o[]:
0 // do nothing
: // else:
o = s // update o[] to s[]
) && o // end of outer map(); return o[]
Charcoal, 47 bytes
⊞υSFυFLιFEι✂ικμF∧›Lλ²⁼λ⮌λ⊞υΦι÷⁻ξκLλ§υ⌕EυLι⌊EυLι
Try it online! Link is to verbose version of code. Explanation:
⊞υSFυ
Start searching for palindromic substrings starting with the input.
FLιFEι✂ικμF∧›Lλ²⁼λ⮌λ
If this substring is long enough and palindromic, then...
⊞υΦι÷⁻ξκLλ
... filter it out from the string and push the result to the list of strings to test.
§υ⌕EυLι⌊EυLι
Output the shortest resulting string.
Retina, 83 bytes
+%/(.)+(.)\2?(?<-1>\1)+(?(1)^)/&L$w`(.)+(.)\2?(?<-1>\1)+(?(1)^)
$`$'
O#$`
$.&
L`^.*
Try it online! Link includes faster¹ test cases. Explanation:
+%/(.)+(.)\2?(?<-1>\1)+(?(1)^)/&`
Repeat on those lines that contain a palindrome...
L$w`(.)+(.)\2?(?<-1>\1)+(?(1)^)
... for all overlapping matches...
$`$'
... remove the match to give the resulting line.
O#$`
$.&
Sort the lines in ascending order of length.
L`^.*
Output only the first (i.e. shortest) line.
¹gogogogogogogogogonow is too slow for the w style of overlapping match but the v style also happens to work in this case within TIO's time limit.
Python3, 233 bytes
def f(s):
q,r,S=[s],[],[s]
for s in q:
if[]==(o:=[(i,j)for i in range(len(s))for j in range(i+1,len(s)+1)if s[i:j]==s[i:j][::-1]and j-i>2]):r+=[s]
for i,j in o:
if(U:=s[:i]+s[j:])not in S:S+=[U];q+=[U]
return min(r,key=len)
JavaScript (Node.js), 214 bytes
f=s=>[...s,t=[]].map((_,i,a)=>[...Array(i).keys()].map(j=>j<i-2&&s.slice(j,(j+i)/2|0)==a.slice((j+i+1)/2|0,i).reverse().join``&&t.push(s.slice(0,j)+s.slice(i))))&&0 in t?t.map(f).sort((x,y)=>x.length-y.length)[0]:s
Explanation
f=s=>...: Define a functionf(named so recursion is possible) which solves the challenge for a strings[...s,t=[]].map((_,i,a)=>...): For every integerifrom0to the length ofs, do the following... (with the characters ofsstored in the arraya)[...Array(i).keys()].map(j=>j<i-2&&...): For every integerjfrom0toi-1, wherej < i-2, do the following...s.slice(j,(j+i)/2|0)==a.slice((j+i+1)/2|0,i).reverse().join``: Check if the slice ofsranging fromjtoiis a palindrome...&&t.push(s.slice(0,j)+s.slice(i))If so, push the section ofswithout the palindrome tot
&&0 in t?...:s: Now, iftis empty, returnsunchanged. Otherwise, one or more palindromes was foundt.map(f): For each palindrome found ins, recursively applyfto the parts ofswithout that palindrome.sort((x,y)=>x.length-y.length)[0]: Choose the shortest result possible
Nekomata, 14 bytes
ʷ{;;$ƀ=tŁ¿,}aş
Extremely slow for long inputs that contain many palindromes.
ʷ{;;$ƀ=tŁ¿,}aş
ʷ{ } Loop until failure
;; Split the input into three parts
$ƀ= Check that the second part is a palindrome
tŁ Check that the second part has length >= 3
¿, If so, join the first and third parts; otherwise fail
aş Find the shortest possible solution
If there are multiple shortest solutions, Nekomata will print all of them. You can add the -1 flag to only print the first one.
