a few solutions
Perform ball drop simulation for each kth ball.  Each ball is tracked by its row and column, ie. i and j correspondingly in the input grid A.  If we can reach t
Perform ball `drop` simulation for each `k`<sup>th</sup> ball.  Each ball is tracked by its row and column, ie. `i` and `j` correspondingly in the input grid `A`.  If we can reach the `M`<sup>th</sup> row, ie. `i == M`, then the ball exits at the `j`<sup>th</sup> column, otherwise the ball got stuck.  The ball is allowed to go left/right if and only if the current cell `i`,`j` and the adjacent cell `i`,`j + A[i][j]` are "pointing" in the same direction.  This is expressed as `A[i][j] == A[i][j + A[i][j]]`, ie. we consider each current cell `A[i][j]` as a relative offset from the current `j`<sup>th</sup> column to it\'s adjacent neighbor which is to-the-left if `A[i][j] == -1` (and thus we update `j = j - 1` for the expression `j += A[i][j]`)  xor is to-the-right if `A[i][j] == 1` (and thus we update `j = j + 1` for the expression `j += A[i][j]`).  An astute observer will notice the iterative solutions update `i` **after** the update to `j` during the simulation because the next `j`<sup>th</sup> column is dependent upon the current `i`<sup>th</sup> row\'s `j`<sup>th</sup> relative offset `A[i][j]`.\n\n**Note:** the most complex and verbose part of this code is the bounds check from `0..N - 1` inclusive for the `j`<sup>th</sup> column and it\'s adjacent neighbor the `j + A[i][j]`<sup>th</sup> column, which is concisely expressed in Python3 and Kotlin correspondingly as follows:\n\n*Python3:* `0 <= j < N and 0 <= j + A[i][j] < N`\n*Kotlin:* `j in 0..N - 1 && j + A[i][j] in 0..N - 1`\n\n\n`\uD83D\uDC46 \uD83D\uDC40 `  Notice how redundant this bounds check is in the other 2 languages (Javascript and C++) \xAF\\\\_(\u30C4)_/\xAF as follows:\n\n*Javascript and C++:* `0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N`\n\n---\n\n**`\uD83D\uDE80 ` "Concise" Recursive solutions:** using the first class concept `drop(i = 0, j)` to simulate dropping the `j`<sup>th</sup> ball for each `j` from `0..N - 1` inclusive, ie. if we can drop the `j`<sup>th</sup> ball successfully through the input grid `A`, then return it\'s corresponding exit column (`-1` if the `j`<sup>th</sup> ball got stuck).\n\n*Kotlin*\n```\nclass Solution {\n    fun findBall(A: Array<IntArray>): IntArray {\n        var M = A.size\n        var N = A[0].size\n        fun drop(i: Int, j: Int): Int {\n            return if (i == M) j else if (j in 0..N - 1 && j + A[i][j] in 0..N - 1 && A[i][j] == A[i][j + A[i][j]]) drop(i + 1, j + A[i][j]) else -1\n        }\n        return IntArray(N) { drop(0, it) }\n    }\n}\n```\n\n*Javascript*\n```\nlet findBall = (A, M = A.length, N = A[0].length, drop = (i, j) => i == M ? j : 0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]] ? drop(i + 1, j + A[i][j]) : -1) => [...Array(N).keys()].map(j => drop(0, j));\n```\n\n*Python3*\n```\nclass Solution:\n    def findBall(self, A: List[List[int]]) -> List[int]:\n        ans = []\n        M = len(A)\n        N = len(A[0])\n        drop = lambda i, j: j if i == M else drop(i + 1, j + A[i][j]) if 0 <= j < N and 0 <= j + A[i][j] < N and A[i][j] == A[i][j + A[i][j]] else -1\n        return [drop(0, j) for j in range(N)]\n```\n\n*C++*\n```\nclass Solution {\npublic:\n    using VI = vector<int>;\n    using VVI = vector<VI>;\n    using fun = function<int(int, int)>;\n    VI findBall(VVI& A, VI ans = {}) {\n        int M = A.size(),\n            N = A[0].size();\n        fun drop = [&](auto i, auto j) {\n            return i == M ? j : 0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]] ? drop(i + 1, j + A[i][j]) : -1;\n        };\n        for (auto j{ 0 }; j < N; ans.push_back(drop(0, j++)));\n        return ans;\n    }\n};\n```\n\n---\n\n**`\uD83D\uDE80 ` "Verbose" Recursive solutions:** same idea as above, written verbosely for optimized readability.\n\n*Kotlin*\n```\nclass Solution {\n    fun findBall(A: Array<IntArray>): IntArray {\n        var M = A.size\n        var N = A[0].size\n        fun drop(i: Int, j: Int): Int {\n            if (i == M)\n                return j\n            if (j in 0..N - 1 && j + A[i][j] in 0..N - 1 && A[i][j] == A[i][j + A[i][j]])\n                return drop(i + 1, j + A[i][j])\n            return -1\n        }\n        return IntArray(N) { j -> drop(0, j) }\n    }\n}\n```\n\n*Javascript*\n```\nlet findBall = A => {\n    let M = A.length,\n        N = A[0].length;\n    let drop = (i, j) => {\n        if (i == M)\n            return j;\n        if (0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]])\n            return drop(i + 1, j + A[i][j]);\n        return -1;\n    };\n    return [...Array(N).keys()].map(j => drop(0, j));\n};\n```\n\n*Python3*\n```\nclass Solution:\n    def findBall(self, A: List[List[int]]) -> List[int]:\n        ans = []\n        M = len(A)\n        N = len(A[0])\n        def drop(i, j):\n            if i == M:\n                return j\n            return drop(i + 1, j + A[i][j]) if 0 <= j < N and 0 <= j + A[i][j] < N and A[i][j] == A[i][j + A[i][j]] else -1\n        return [drop(0, j) for j in range(N)]\n```\n\n*C++*\n```\nclass Solution {\npublic:\n    using VI = vector<int>;\n    using VVI = vector<VI>;\n    using fun = function<int(int, int)>;\n    VI findBall(VVI& A, VI ans = {}) {\n        int M = A.size(),\n            N = A[0].size();\n        fun drop = [&](auto i, auto j) {\n            if (i == M)\n                return j;\n            if (0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]])\n                return drop(i + 1, j + A[i][j]);\n            return -1;\n        };\n        for (auto j{ 0 }; j < N; ans.push_back(drop(0, j++)));\n        return ans;\n    }\n};\n```\n\n---\n\n**`\uD83D\uDE8C ` Iterative solutions:**  same general idea as above simulations, but in the solutions below, we drop each `k`<sup>th</sup> ball for each `k` from `0..N - 1` inclusive.  Each `k`<sup>th</sup> ball starts it\'s "drop" into `A` at cell `i = 0`,`j = k`.\n\n*Kotlin*\n```\nclass Solution {\n    fun findBall(A: Array<IntArray>): IntArray {\n        var ans = mutableListOf<Int>()\n        var M = A.size\n        var N = A[0].size\n        for (k in 0..N - 1) {\n            var i = 0\n            var j = k\n            while (i < M && j in 0..N - 1 && j + A[i][j] in 0..N - 1 && A[i][j] == A[i][j + A[i][j]]) {\n                j += A[i][j]; ++i\n            }\n            ans.add(if (i == M) j else -1)\n        }\n        return ans.toIntArray()\n    }\n}\n```\n\n*Javascript*\n```\nlet findBall = (A, ans = []) => {\n    let M = A.length,\n        N = A[0].length;\n    for (let k = 0; k < N; ++k) {\n        let i = 0,\n            j = k;\n        while (i < M && 0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]])\n            j += A[i][j], ++i;\n        ans.push(i == M ? j : -1);\n    }\n    return ans;\n};\n```\n\n*Python3*\n```\nclass Solution:\n    def findBall(self, A: List[List[int]]) -> List[int]:\n        ans = []\n        M = len(A)\n        N = len(A[0])\n        for k in range(N):\n            i = 0\n            j = k\n            while i < M and 0 <= j < N and 0 <= j + A[i][j] < N and A[i][j] == A[i][j + A[i][j]]:\n                j += A[i][j]; i += 1\n            ans.append(j if i == M else -1)\n        return ans\n```\n\t\t\n\n*C++*\n```\nclass Solution {\npublic:\n    using VI = vector<int>;\n    using VVI = vector<VI>;\n    VI findBall(VVI& A, VI ans = {}) {\n        int M = A.size(),\n            N = A[0].size();\n        for (auto k{ 0 }; k < N; ++k) {\n            auto i = 0,\n                 j = k;\n            while (i < M && 0 <= j && j < N && 0 <= j + A[i][j] && j + A[i][j] < N && A[i][j] == A[i][j + A[i][j]])\n                j += A[i][j], ++i;\n            ans.push_back(i == M ? j : -1);\n        }\n        return ans;\n    }\n};\n```
[]