Oops, I blew it up (with numbers)

Inspired by There, I fixed it (with rope), There, I fixed it (with Tape), There, I broke it (with scissors)

Given a string with characters from a-z or A-Z (whichever you prefer), turn missing letters into numbers and make them explode.

Example

Input: abcafabc

Output: a12344321c

Why?

1) Find the missing letters (only going forward in the alphabet): abca(bcde)fabc

2) Replace them with the number of missing letters: abca4fabc

3) Replace the number with

• Itself twice if it's even
• Itself + 1 if it's odd

In this case: abca44fabc

4) Explode those numbers outwards replacing any letters: a12344321c

Challenge Rules

1. Explosions can't exceed the boundaries of the string

• ae -> 343 (3 letters are missing but since 3 is odd, it's been replaced by 4)
2. Numbers can be greater than 9

• az -> 23242423 (24 letters are missing and since 24 is even, it's repeated twice)
3. You can have multiple explosions

• abcefghijmnop -> ab121fghi1221nop
4. Multiple explosions can overlap, take the sum of the number when they do

• abceghij -> abc(2)e(2)ghij -> ab12(1+1)21hij -> ab12221hij
5. It's possible that no explosions occur, in that case simply return the string

6. No explosions between ab, aa, aaa, etc.

7. You are allowed to take the input in any reasonable format. Can be a single string, string-array/list, character-array/list, etc. Output has the same flexibility.

8. You are allowed to use lowercase and/or uppercase any way you'd like. This applies both to the input, output.

General Rules

• This is , so the shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-golfing languages.
• Standard rules apply.
• Default Loopholes are forbidden.
• If possible, please add a link to a test for your code, preferably Tio.
• Also, please add an explanation if necessary.

Test cases:

Input  : 'abcdefgklmnopqrstuvwxyz'
Output : 'abcd1234321nopqrstuvwxyz'

Input  : 'abdefgjkl'
Output : 'a121ef1221kl'

Input  : 'xyzaz'
Output : '20212223242423'

Input  : 'abceghij'
Output : 'ab12221hij'

Input  : 'zrabc'
Output : 'zrabc'
• I'm sorta confused on how to decide what the ground 0 is. – NoOneIsHere Mar 10 '18 at 0:30
• @NoOneIsHere : ground zero is the place where the missing letters should have been. Example: abcefg ground zero (represented by HERE would be abcHEREefg – Dat Mar 10 '18 at 0:33
• But what about acca? – NoOneIsHere Mar 10 '18 at 0:34
• I think you should include an example where the grounds zero overlap such as aeae -> 355553 (if that is correct) – Asone Tuhid Mar 10 '18 at 8:59
• Please work e.g. this example, that should clarify a lot (overlap over multiple explosions with even steps) : abcfghabceazabcazabcefghabcfabcd – Ton Hospel Mar 10 '18 at 11:17

Perl 5, -p110 109 bytes

Handling the even/odd rules waste around 20 bytes

#!/usr/bin/perl -p
s#.#$p+=$.;$c{$p-$_}+=$-=$z-abs$_+$z%2/2for-25..($z=ord($')-ord$&);$&x($.=$z<2||$z%2+2)#eg;s##$c{+pos}||$&#eg

Try it online!

Ruby, 162 bytes

->a{b=[*a=a.reduce{|x,y|[*x,*[(n=y.ord+~x[-1].ord)+n%2]*(n<1?0:2-n%2),y]}];i=-1;b.map{|x|d=-~i+=1;a.map!{|y|(z=x.to_i-(d-=1)*s=d<=>0)<1||x==b[i-s]?y:z+y.to_i}};a}

Try it online!

Takes input as an array of chars, returns a mixed array of chars/ints. (I'm still not sure whether this is allowed after reading the comments to the original post. If not allowed, it's +3 bytes to fix).

Explanation

First, we apply a reduce operation, where we aren't actually reducing anything, but rather reconstruct the array a as [*x,*[...],y], where the middle part contains the numbers inserted at ground zero.

We also make a copy of the array: b=[*a] to serve as a reference, so that we don't get confused which numbers are at the center of the explosion, and which ones are introduced later on.

Then we iterate through b and for each element x, iterate through a to record, what effect x will have on each element y of a.

Conveniently, to_i method returns 0 for non-numeric chars, so that we don't have to worry about distinction between numbers and text.

In my initial code, arrays were indexed by i and j, but this was golfed down to use a "delta" value d=i-j.

Another helper variable is the sign of the delta: s=d<=>0. At the first occurrence it performs the same function as abs, and at the second - it helps us to block the other side of one-sided explosions as in 12344321.

Ultimately, if z is estimated to be positive, we add it up with the integer equivalent of y and store in a, otherwise, y remains intact.

Python 3, 351 348 bytes

Z=zip
R=range
E=lambda o:R(o,0,-1)
D=lambda d:[]if d<1else[[E(d),E(d+1)]]if d%2else[[E(d-1),[d]],[[],E(d)]]
def f(s):
s=sum(([c]+D(ord(n)+~ord(c))for c,n in Z(s,s[1:]+' ')),[]);l=len(s);v=*l
for i,c in enumerate(s):
if len(c)>1:
for j,d in list(Z(R(i-1,-1,-1),c))+list(Z(R(i,l),c)):v[j]+=d
print(*(d or c for c,d in Z(s,v)),sep='')

Try it online!

• −3 thanks to Kevin

The function f takes one string as input and prints the result to standard output.

Ungolfed

def range_downto_0(o):
return range(o, 0, -1)

def D(d):
return (
[]
if d >= 0 else
[[range_downto_0(d), range_downto_0(d + 1)]]
if d % 2 else
[[range_downto_0(d - 1), [d]], [[], range_downto_0(d)]]
)

def f(s):
s = sum(([c] + D(ord(n) + ord(c) - 1) for c, n in zip(s, s[1:] + ' ')), [])
v =  * len(s)
for i, c in enumerate(s):
if len(c) == 2:
for j, d in itertools.chain(
zip(range(i - 1, -1, -1), c)),
zip(range(i, len(s)), c)
):
v[j] += d
return ''.join(str(d) if d else c for c, d in zip(s, v))

Explanation

1. Expand the string s to insert number range objects as placeholders for the "outward explosions". Save the result as a list s.

2. Create a list of zeros v with the same length as s.

3. Inspect s and, for every number range, add the numerical values to the value at their respective position in v. v now contains all the numbers that are going to be in the result at their correct positions.

4. Iterate over s and v simultaneously, take the entry from v if it is greater than 0 or the entry from s otherwise and print each chosen entry in order.

The expensive repeated array concatenation in step 1 is at best in O(n2) but could be expressed in O(n) using a generator (assuming Python can construct lists from generators in O(n)). The remainder of this algorithm is in O(n ⋅ min{n, |Σ|} ⋅ log |Σ|) with Σ being the alphabet or, if you want to regard Σ as a constant, straight out O(n) (assuming that Python can join string generators in O(n)). “min{n, |Σ|}” comes from the outward range expansion and “log |Σ|” results from the conversion of numbers to strings.

• You can remove three spaces at d<1else[[E(d) (-2) and d%2else (-1). – Kevin Cruijssen Mar 15 '18 at 9:14

C (gcc), 395 bytes

#include<stdlib.h>
#include<stdio.h>
f(char*s){char*S=s;while(*S++);const int l=S-s-1;int i=1,j=0,k,d,o,t[l*3],*v;for(;i<l;i++)(d=s[i]+~(t[j++]=s[i-1]))>0&&(t[j++]=-d,d%2||(t[j++]=0));l>0&&(t[j++]=s[l-1]);v=calloc(k=j,4);for(i=0;i<k;i++){if((d=-t[i])>0){d+=o=d%2;for(j=0;j<d&&j<=i;j++)v[i-j]+=d-j;i+=!o;for(j=o;j<d&&i+j<k;j++)v[i+j]+=d-j;}}for(i=0;i<k;i++){d=v[i];printf(d?"%d":"%c",d?d:t[i]);}}

Try it online!

f takes input as a null-terminated character array and returns its result on standard output.

Explanation

This is my first C submission to Code Golf. The algorithm is the same as in my Python submission.