HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Matrix Diagonal Difference

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
differencematrixdiagonal

Problem

Problem

Given a square matrix of size N×N, calculate the absolute difference between the sums of its diagonals.

Input Format

The first line contains a single integer, N. The next N lines denote the matrix's rows, with each line containing N space-separated integers describing the columns.

Output Format

Print the absolute difference between the two sums of the matrix's diagonals as a single integer.

Sample Input

3
11 2 4
4 5 6
10 8 -12


Sample Output

15


Code

(ns hackerrank.core
  [:require [clojure.string :as s]])

(defn get-diagonal-sums-reducer
  [n]
  (fn
    [sums [line-number line]]
    (let
      [primary (nth line line-number)
       secondary (nth line (- n (+ 1 line-number)))]
      (assoc
        sums
        :primary (+ primary (:primary sums))
        :secondary (+ secondary (:secondary sums))))))

(let
  [n (Integer/parseInt (read-line))
   matrix (for
            [_ (range n)]
            (mapv #(Integer/parseInt %) (s/split (read-line) #"\s+")))
   matrix-enumerated (map-indexed vector matrix)
   sums (reduce
          (get-diagonal-sums-reducer n)
          {:primary 0 :secondary 0}
          matrix-enumerated)
   difference (- (:primary sums) (:secondary sums))]
  (println (max difference (- difference))))


Couple questions in particular:

-
can I avoid the get-diagonal-sums-reducer somehow? I'm only using it so that it closes over n.

-
am I doing this as lazily as possible or is there any place I'm using vectors when seqs would have worked?

-
is there a much less verbose way to do this? Doesn't feel like this would be as complicated in Python.

Solution

Could you have avoided get-diagonal-sums-reducer?

You probably could have used partial if you wanted, though I'm not sure it ends up that much better:

(defn diagnoal-sums-reducer [n sums [line-number line]]
...)

(reduce (partial diagonal-sums-reducer n) ...)


Is there a much less verbose way to do this.

I think there is. I can see why you've tried to use reduce, but your reducer is doing way more than it should be. Essentially, there's 3 things it's doing:

  • Calculating the coordinates of the diagonals for the line.



  • Getting the values of those coordinates.



  • Summing the values together with the previous values.



There might be some situations where you'd need to do all of those things in a single reduce, but I don't think this is one of those cases. It's also complicated by having to do this for both the primary and the secondary cases.

It ends up much simpler if you split the whole process out into the individual steps:

(defn sum [x] (apply + x))

(let [n 3
matrix [[11 2 4]
[4 5 6]
[10 8 -12]]

;; Build up a list of coordinates for the diagonals.
primary-coords (for [i (range n)] [i i])
secondary-coords (for [i (range n)] [(- n i 1) i])

;; Extract the values of those coordinates
primaries (map #(get-in matrix %) primary-coords)
secondaries (map #(get-in matrix %) secondary-coords)]

;; Sum them, take the absolute difference
(Math/abs (- (sum primaries) (sum secondaries))))

Context

StackExchange Code Review Q#124846, answer score: 4

Revisions (0)

No revisions yet.