# Javascript (ES6), 453 bytes The first and most obvious solution that came to my mind is one that looks around the slides and then merges or replaces. a=>{b=(d,e,f)=>d.substr(0,e)+f+d.substr(e+(''+f).length);g=0;a=a.split` `.map(h=>h.replace(/o/g,'1'));j=i=>i.match(/[0-9]/);k=' ';while(!g){g=1;for(r=a.length-2;r>0;r--){for(c=1;c<a[r].length-1;c++){nr=r+1;l=b(a[r],c,k);nc=a[nr][c]=='\\'?c+1:a[nr][c]=='/'?c-1:a[nr][c]==k||j(a[nr][c])?c:null;j(a[r][c])&&nc!=null?j(a[nr][nc])?(a[nr]=b(a[nr],nc,+a[nr][nc]+ +a[r][c]),a[r]=l,g=0):a[nr][nc]==k?(a[nr]=b(a[nr],nc,a[r][c]),a[r]=l,g=0):0:0}}}return a.join` `} Ungolfed: state => { replaceAt = (str, index, char) => str.substr(0, index) + char + str.substr(index + ('' + char).length); complete = 0; state = state.split `\n`.map(line => line.replace(/o/g, '1')); isNumber = inp => inp.match(/[0-9]/); space = ' '; while (!complete) { complete = 1; for (r = state.length - 2; r > 0; r--) { for (c = 1; c < state[r].length - 1; c++) { nr = r + 1; nc = state[nr][c] == '\\' ? c + 1 : state[nr][c] == '/' ? c - 1 : state[nr][c] == space || isNumber(state[nr][c]) ? c : null; replacedLine = replaceAt(state[r], c, space); isNumber(state[r][c]) && nc != null ? isNumber(state[nr][nc]) ? ( state[nr] = replaceAt(state[nr], nc, +state[nr][nc] + +state[r][c]), state[r] = replacedLine, complete = 0 ) : state[nr][nc] == space ? ( state[nr] = replaceAt(state[nr], nc, state[r][c]), state[r] = replacedLine, complete = 0 ) : 0 : 0 } } } return state.join `\n`; } Lookaround and string manipulation are not cheap. Interested in your _389b_ Python code.