'use strict';
console.time('Took: ');
const fs = require('fs'),
  BN = require('bn.js');

const taskName = 'ijones';
const inputFileName = process.argv[2] || taskName + '.in',
  outputFileName = process.argv[3] || taskName + '.out';

const alphabet = ['q','w','e','r','t','y','u','i','o','p','l','k','j','h','g','f','d','s','a','z','x','c','v','b','n','m'];

fs.readFile(inputFileName, 'utf8', (err, data) => {
  if (err) throw err;
  let contents = data.split('\n'),
    [w, h] = contents[0].split(' ').map(x => parseInt(x)),
    matrix = contents.slice(1, h+1),
    solutions = Array.apply(null, Array(h)).map(() => {
      return Array.apply(null, Array(w-1)).map(() => {
        return new BN(0)
      })
    }),
    jumps = new Map();

  /* base cases */
  for (let i = 0; i < h; i++) {
    solutions[i][0] = new BN(1);
  }
  alphabet.map((char) => {
    jumps.set(char, new BN(0))
  });
  for (let i = 0; i < h; i++) {
    jumps.set(matrix[i][0], jumps.get(matrix[i][0]).add(new BN(1)));
  }

  /* filling the table */
  for (let i = 1; i < w - 1; i++) {
    for (let j = 0; j < h; j++) {
      let char = matrix[j][i],
        leftChar = matrix[j][i-1];
      solutions[j][i] = jumps.get(char);
      if (char !== leftChar) {
        solutions[j][i] = solutions[j][i].add(new BN(1));
      }
    }
    for (let j = 0; j < h; j++) {
      let char = matrix[j][i];
      if (jumps.has(char)) {
        jumps.set(char, jumps.get(char).add(solutions[j][i]));
      }
    }
  }

  let topRChar = matrix[h-1][w-1],
    topRLChar = matrix[h-1][w-2],
    topRSolution = jumps.get(topRChar)
      .add(new BN(topRChar !== topRLChar ? 1 : 0)) ,
    bottomRChar = matrix[0][w-1],
    bottomRLChar = matrix[0][w-2],
    bottomRSolution = jumps.get(bottomRChar)
      .add(new BN(bottomRChar !== bottomRLChar ? 1 : 0)) ;

  fs.writeFile(outputFileName, topRSolution.add(bottomRSolution), err => {
    if (err) throw err;
    console.log(topRSolution.add(bottomRSolution).toString());
    console.timeEnd('Took: ');
  });
});
@@ -7,16 +7,19 @@
 trict';%0A
+// 
 console.
@@ -575,16 +575,30 @@
 utions =
+ %7B%0A      prev:
  Array.a
@@ -632,22 +632,31 @@
  =%3E 
-%7B
+new BN(0)),
 %0A      
-return
+curr:
  Arr
@@ -676,19 +676,17 @@
 , Array(
-w-1
+h
 )).map((
@@ -693,25 +693,8 @@
 ) =%3E
- %7B%0A        return
  new
@@ -703,24 +703,15 @@
 N(0)
-%0A      %7D
 )%0A    %7D
-)
 ,%0A  
@@ -755,77 +755,8 @@
  */%0A
-  for (let i = 0; i %3C h; i++) %7B%0A    solutions%5Bi%5D%5B0%5D = new BN(1);%0A  %7D%0A
   al
@@ -843,24 +843,73 @@
 %3C h; i++) %7B%0A
+    solutions.prev%5Bi%5D = new BN((w %3E 1) ? 1 : 0);%0A
     jumps.se
@@ -1076,205 +1076,56 @@
     
-let char = matrix%5Bj%5D%5Bi%5D,%0A        leftChar = matrix%5Bj%5D%5Bi-1%5D;%0A      solutions%5Bj%5D%5Bi%5D = jumps.get(char);%0A      if (char !== leftChar) %7B%0A        solutions%5Bj%5D%5Bi%5D = solutions%5Bj%5D%5Bi%5D.add(new BN(1));%0A      %7D
+solutions.curr%5Bj%5D = getSolutionForElement(j, i);
 %0A   
@@ -1274,21 +1274,23 @@
 olutions
-%5Bj%5D%5Bi
+.curr%5Bj
 %5D));%0A   
@@ -1306,345 +1306,161 @@
 %7D%0A  
-%7D%0A%0A  let topRChar = matrix%5Bh-1%5D%5Bw-1%5D,%0A    topRLChar = matrix%5Bh-1%5D%5Bw-2%5D,%0A    topRSolution = jumps.get(topRChar)%0A      .add(new BN(topRChar !== topRLChar ? 1 : 0)) ,%0A    bottomRChar = matrix%5B0%5D%5Bw-1%5D,%0A    bottomRLChar = matrix%5B0%5D%5Bw-2%5D,%0A    bottomRSolution = jumps.get(bottomRChar)%0A      .add(new BN(bottomRChar !== bottomRLChar ? 1 : 0)) ;%0A
+  solutions.prev = solutions.curr.slice();%0A  %7D%0A  let topRSolution = getSolutionForElement(h-1, w-1),%0A    bottomRSolution = getSolutionForElement(0, w-1);
 %0A  f
@@ -1496,32 +1496,40 @@
 opRSolution.add(
+h %3E 1 ? 
 bottomRSolution)
@@ -1527,16 +1527,28 @@
 Solution
+ : new BN(0)
 ), err =
@@ -1574,24 +1574,27 @@
 row err;%0A   
+ //
  console.log
@@ -1611,16 +1611,24 @@
 ion.add(
+h %3E 1 ? 
 bottomRS
@@ -1634,16 +1634,28 @@
 Solution
+ : new BN(0)
 ).toStri
@@ -1664,16 +1664,19 @@
 ());%0A   
+ //
  console
@@ -1701,11 +1701,322 @@
 ;%0A  %7D);%0A
+%0A  function getSolutionForElement(hIndex, wIndex) %7B%0A    let char = matrix%5BhIndex%5D%5BwIndex%5D,%0A      leftChar = matrix%5BhIndex%5D%5BwIndex-1%5D;%0A    if (!leftChar) %7B%0A      return new BN(1);%0A    %7D%0A    if (char === leftChar) %7B%0A      return jumps.get(char);%0A    %7D%0A    return solutions.prev%5BhIndex%5D.add(jumps.get(char));%0A  %7D%0A%0A
 %7D);

all answers correct