loading...

Daily Challenge #215 - Difference of 2

thepracticaldev profile image dev.to staff ・1 min read

The objective is to implement a function that will return all pairs of integers from a given array of integers that have a difference of 2. The result array should be sorted in ascending order of values.

Assume there are no duplicate integers in the array. The order of the integers in the input array should not matter.

Examples

[1, 2, 3, 4]      -->  [[1, 3], [2, 4]]
[4, 1, 2, 3]      -->  [[1, 3], [2, 4]]
[1, 23, 3, 4, 7]  -->  [[1, 3]]
[4, 3, 1, 5, 6]   -->  [[1, 3], [3, 5], [4, 6]]

Tests

pairDifference([1,2,3,4])
pairDifference([1,3,4,6])

Happy coding!


This challenge comes from technikhil on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Posted on by:

thepracticaldev profile

dev.to staff

@thepracticaldev

The hardworking team behind dev.to ❤️

Discussion

pic
Editor guide
 

Python solution

pairDifference = lambda lst: sorted([(num,num+2) for num in lst if (num+2) in lst])

print(pairDifference([1, 2, 3, 4])) # output [(1, 3), (2, 4)]
print(pairDifference([4, 1, 2, 3])) # output [(1, 3), (2, 4)]
print(pairDifference([1, 23, 3, 4, 7])) # output [(1, 3)]
print(pairDifference([4, 3, 1, 5, 6])) # output [(1, 3), (3, 5), (4, 6)]
print(pairDifference([1,3,4,6])) # output [(1, 3), (4, 6)]
 

Whoa, that reads almost as if it were English!

 
 

Ruby solution

def pair_difference(lst)
  lst.sort # sort array
    .combination(2) # get all posible combinations of pairs
    .select{|arr| (arr.max - arr.min) == 2 } # only combinations that have difference of 2
    .sort_by{|arr| arr[0] } # sort by the first number
end
 

There's were several Ruby solutions already, so I tried to come up with a different one:

def pair_difference(arr)
  s = Set.new(arr)
  s.filter_map { |n| m = n + 2; [n, m] if s.include?(m) }.sort_by(&:first)
end
 

C++ solution

vector<pair<int, int>> pairDifference(vector<int> arr){
    // store all the numbers in a set for ease of searching
    // cpp set stores all numbers in ascending order by default
    set<int> numbers(arr.begin(), arr.end());

    // stores the pairs which have difference of two
    vector<pair<int, int>> numPairs;

    for(int num : numbers){
        // for any number num if num+2 is also in the set
        // then include it in the vector
        if(numbers.find(num+2) != numbers.end()){
            numPairs.push_back(make_pair(num,num+2));
        }
    }
    return numPairs;
}
 

Something like this should do it in JavaScript. I'm not entirely sure if this sort is okay, though. I can never remember which way it's ascendent and which descendent.

const pairDifference = list => list
    .sort()
    .filter(x => list.includes(x + 2))
    .map(x => [ x, x + 2 ])
 

This really is Savage

 

Took some iterations to get to this solution, but here it is.
Haskell:

import Data.Maybe (catMaybes)
import Data.List (sort)

pairDifference :: [Int] -> [(Int, Int)]
pairDifference xs = catMaybes $ f <$> sorted <*> sorted
  where
    sorted = sort xs
    f x y | y - x == 2 = Just (x, y)
          | otherwise  = Nothing
 

JS solution with reduce

const pairDifference = arr =>
  arr.sort((a,b)=>a-b).reduce((acc, val, i, oa) => {
    for (let j = i + 1; j < oa.length; j++) {
      if (Math.abs(val - oa[j]) === 2) {
        acc.push([val, oa[j]]);
      }
    }
    return acc;
  }, []);
 

My Swift solution :

func pairDifference(tab: [Int]) -> [[Int]]{
    tab.sorted().reduce(into: [[Int]]()) { (result, intValue) in
        if let value = tab.first(where: { $0 == intValue + 2 }) {
            result.append([intValue, value])
        }
    }
}

pairDifference(tab: [1, 2, 3, 4]) // [[1, 3], [2, 4]]
pairDifference(tab: [4, 1, 2, 3]) // [[1, 3], [2, 4]]
pairDifference(tab: [1, 23, 3, 4, 7]) // [[1, 3]]
pairDifference(tab: [4, 3, 1, 5, 6]) // [[1, 3], [3, 5], [4, 6]]
 

JS Solution

function pairDifference(data) {
    var pairs = [];
    var added = [];

    data.sort(function(x, y) {
        return x - y;
    });

    for (let i = 0; i < data.length; i++) {
        var x = data[i];

        for (let j = 0; j < data.length; j++) {
            var y = data[j];

            if (added.indexOf(x) < 0 && added.indexOf(y) < 0
                && Math.abs(x - y) == 2
            ) {
                pairs.push([x, y]);
                added.push(x);
                added.push(y);
            }
        }
    }

    return pairs;
}

var testData = [
    [1, 2, 3, 4],
    [4, 1, 2, 3],
    [1, 23, 3, 4, 7],
    [4, 3, 1, 5, 6],
    [1,3,4,6]
];

for (let k = 0; k < testData.length; k++) {
    var data = testData[k];

    console.log(JSON.stringify(data) + ' --> ' 
        + JSON.stringify(pairDifference(data)))
}

output:

[1,2,3,4] --> [[1,3],[2,4]]
[4,1,2,3] --> [[1,3],[2,4]]
[1,23,3,4,7] --> [[1,3]]
[4,3,1,5,6] --> [[1,3],[4,6]]
[1,3,4,6] --> [[1,3],[4,6]]
 

JavaScript

Assuming the input should be an array of unsigned integers.

"use strict";

/**
 * Find the pairs that have a difference of two.
 *
 * @param {number[]} An array of unsigned integers.
 *
 * @throws {Error}      If the function is not called with one argument.
 * @throws {TypeError}  If the first argument is not an array.
 * @throws {TypeError}  If the first argument is not an array of integers.
 * @throws {TypeError}  If the first argument is not an array of unsigned integers.
 *
 * @return {number[][]} An array of array of unsigned integer pairs
 *
 * @example
 * pairDifference([1, 2, 3, 4]);        // [ [ 1, 3 ], [ 2, 4 ] ]
 * pairDifference([4, 1, 2, 3]);        // [ [ 4, 2 ], [ 1, 3 ] ]
 * pairDifference([1, 23, 3, 4, 7]);    // [ [ 1, 3 ] ]
 * pairDifference([4, 3, 1, 5, 6]);     // [ [ 4, 6 ], [ 3, 1 ], [ 3, 5 ] ]
 */
function pairDifference(numbers) {
    if (arguments.length !== 1) {
        throw new Error("expected one argument");
    }

    if (!Array.isArray(numbers)) {
        throw new TypeError("expected first argument to be an array");
    }

    const length = numbers.length;
    const pairs = [];

    for (let first = 0; first < length; first++) {
        const firstNumber = numbers[first];

        if (!Number.isInteger(firstNumber)) {
            throw new TypeError("expected first argument to be an array of integers");
        }

        if (firstNumber < 0) {
            throw new TypeError("expected first argument to be an array of unsigned integers");
        }

        for (let second = first + 1; second < length; second++) {
            const secondNumber = numbers[second];

            if (!Number.isInteger(secondNumber)) {
                throw new TypeError("expected first argument to be an array of integers");
            }

            if (secondNumber < 0) {
                throw new TypeError("expected first argument to be an array of unsigned integers");
            }

            if (Math.abs(firstNumber - secondNumber) === 2) {
                pairs.push(firstNumber, secondNumber);
            }
        }
    }

    return pairs;
}
 

JS solution

const pairDifference = (nums) => {
  const results = []
  if (!nums || nums.length < 2) return results
  nums.sort()
  for (let i = 0; i < nums.length - 1; i++) {
    // 2nd num can only be 1 or 2 positions away when sorted and no duplicates
    if (nums[i + 1] - nums[i] === 2) {
      results.push([nums[i], nums[i + 1]])
    }
    else if (i < nums.length - 2 && nums[i + 2] - nums[i] === 2) {
      results.push([nums[i], nums[i + 2]])
    }
  }
  return results
}

const pairsEqual = (p1, p2) => p1[0] === p2[0] && p1[1] === p2[1]

const test = (nums, expected) => {
  const results = pairDifference(nums)
  const passed = results.length === expected.length &&
    !results.find((p, i) => !pairsEqual(p, expected[i]))
  console.log(`${passed? 'Pass' : 'FAIL'} - input: ${JSON.stringify(nums)} ` +
  `expected: ${JSON.stringify(expected)} results: ${JSON.stringify(results)}`)
}

test([1, 2, 3, 4], [[1, 3], [2, 4]])
test([1, 3, 4, 6], [[1, 3], [4, 6]])
test([4, 1, 2, 3], [[1, 3], [2, 4]])
test([1, 23, 3, 4, 7], [[1, 3]])
test([4, 3, 1, 5, 6], [[1, 3], [3, 5], [4, 6]])
test(undefined, [])
test([], [])
test([1], [])
test([2, -1, 0, 1], [[-1, 1], [0, 2]])
test([2000, -100, -98, 1999], [[-100, -98]])
 
 <script>
      var myFunction = (list) =>
        list
          .sort((num1, num2) => num1 - num2)
          .reduce((returnList, eachVal, i, assendingArray) => {
            for (let j = i + 1; j < assendingArray.length; j++) {
              if (Math.abs(eachVal - assendingArray[j]) === 2) {
                returnList.push([eachVal, assendingArray[j]]);
              }
            }
            return returnList;
          }, []);
      console.log(myFunction([3, 4, 7, 6, 9, 8]));
      console.log(myFunction([12, 4, 6, 7, 9, 70]));
      console.log(myFunction([23, 40, 7, 16, 9, 38]));
      console.log(myFunction([23, 25, 27, 29, 30, 32]));
    </script>

 

Ruby solution

def pairDifference(arr)
  hash = arr.reduce( { } ) { |dict,value| dict[value]=true; dict }
  arr.select { |x| hash[x+2] }.sort.map{ |x| [x,x+2] }
end
 

You mentioned in a recent comment that you're liearning Ruby, so here some tips:

  1. Ruby method names idiomatically use snake case, so pair_difference
  2. Ruby has each_with_object for exactly this use case:

    hash = arr.each_with_object ( { } ) { |value, dict| dict[value] = true }
    
 

could not be grateful anymore!!!
very thankful
hope to learn more from you.
really thanks!