DEV Community

Andy Zhao (he/him)
Andy Zhao (he/him)

Posted on

Challenge: Get Closest Number in an Array

Given an array of numbers nums, and a given number given_num:

nums = [100, 200, 400, 800, 1600, 3200, 6400, 128000]
given_num = 900
Enter fullscreen mode Exit fullscreen mode

Get the number closest to the given_num from the array nums.

In this example, the returned value should be 800.

Go!

A black checkered flag signals go!

Oldest comments (36)

Collapse
 
andy profile image
Andy Zhao (he/him) • Edited

Ruby:

nums.min_by { |num| (given_num - num).abs }
#=> 800

Shamelessly taken from Stack Overflow πŸ™ƒ I was in a much more of a "just give me the answer" mood than "let's figure it out" mood.

Collapse
 
dmfay profile image
Dian Fay

Window functions!

SELECT unnest
FROM unnest(ARRAY[100,200,400,800,1600,3200,6400,128000])
ORDER BY row_number() OVER (ORDER BY abs(900 - unnest))
LIMIT 1;
Collapse
 
rhymes profile image
rhymes

hahaha thinking outside the box :D

Collapse
 
dmfay profile image
Dian Fay

I looked at it again just now and the row_number is redundant anyway...

SELECT unnest
FROM unnest(ARRAY[100,200,400,800,1600,3200,6400,128000])
ORDER BY abs(900 - unnest)
LIMIT 1;
Collapse
 
maeganwilson_ profile image
Maegan Wilson

I probably over complicated it, but here's a CodePen link with how I did it in JS and outputted it to the HTML side.

Collapse
 
andy profile image
Andy Zhao (he/him)

Long as you solved it! πŸ‘

Collapse
 
hpj1992 profile image
Harshit • Edited

Java:

        int[] nums = {100, 200, 400, 800, 1600, 3200, 6400, 128000};
        int ans = 0;
        int given_num = 900;
        int minDistance = Integer.MAX_VALUE;
        for (int i =0; i < nums.length; i++) {
            int curDistance = Math.abs(nums[i] - given_num);
            if (curDistance < minDistance) {
                ans = nums[i];
                minDistance = curDistance;
            }
        }
        System.out.println(ans);

Trying to optimize no of lines with Java 8 Streams and Lambda.

Collapse
 
andreyvladikin profile image
Andrey Vladikin

JS:

const nums = [100, 200, 400, 800, 1600, 3200, 6400, 128000];
const givenNum = 900;

nums
.map(n => ({n, d: Math.abs(n-givenNum)}))
.sort((n1, n2) => Math.sign(n1.d - n2.d))[0].n

Collapse
 
kip13 profile image
kip

Rust πŸ¦€

numbers.iter().min_by_key(|&num| (num - given_num).abs()).unwrap()
Collapse
 
andy profile image
Andy Zhao (he/him)

Nice, didn't know Rust had similar syntax to Ruby!

Collapse
 
highcenburg profile image
Vicente G. Reyes • Edited

With the help of google, I was able to find the answer to this πŸ˜…

import numpy as np
def find_nearest(array, value):
array = np.array(array)
z=np.abs(array-value)
y= np.where(z == z.min())
m=np.array(y)
x=m[0,0]
y=m[1,0]
near_value=array[x,y]

return near_value

array =np.array([[100, 200, 400, 800, 1600, 3200, 6400, 128000]])
print(array)
value = 900
print(find_nearest(array, value))

Answer:

Thanks for this challenge! 🍺

Collapse
 
mkrl profile image
Mikhail Korolev

Wolfram Language!

Nearest[nums, given_num]
Enter fullscreen mode Exit fullscreen mode

I knew that one day my subscription will come in handy...

Collapse
 
joelnet profile image
JavaScript Joel • Edited

This is a job for Reduce!

JavaScript:

const nums = [100, 200, 400, 800, 1600, 3200, 6400, 128000]
const given_num = 900

const closestReducer = g => (a, b) =>
  Math.abs(g - a) < Math.abs(g - b) ? a : b

nums.reduce(closestReducer(given_num))
//=> 800
Collapse
 
pbouillon profile image
Pierre Bouillon • Edited

Here goes Python !

min(nums, key=lambda x: abs(x - given_num))
Collapse
 
link2twenty profile image
Andrew Bone • Edited

Javascript:

Let's go for a JS one liner πŸ˜‰

nums.sort((a, b) => Math.abs(given_num - a) - Math.abs(given_num - b))[0]

This causes the original array to have its order changed but I don't think that's against the rules πŸ˜…

Collapse
 
bugb profile image
bugb • Edited

I dont think use sort is good idea:
Let see:

[2,3,4,11].sort()
Collapse
 
link2twenty profile image
Andrew Bone

By including a function to sort by I'm no longer doing an alphabetical sort, which means this problem no longer exists.

  console.log([2,3,4,11].sort((a,b)=>a-b));
Output:
  (4)Β [2, 3, 4, 11]

The sort() method sorts the elements of an array in place and returns the array. The default sort order is built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

developer.mozilla.org/en-US/docs/W...

Thread Thread
 
bugb profile image
bugb

yes, by including compareFunction callback, we can solve this problem.

Collapse
 
andy profile image
Andy Zhao (he/him)

If it outputs the closest number, it works! :)

Collapse
 
bugb profile image
bugb • Edited

nums = [100, 200, 400, 800, 1600, 3200, 6400, 128000];
given_num = 900

Here is my solution:

f = a => (m=Math.min(...nums.map(v=>Math.abs(v-given_num))),nums.find(v=>v==given_num - m || v== m-given_num))

Usage:

f(nums)

Result:

800
Collapse
 
lucifer1004 profile image
Gabriel Wu • Edited

Be careful that ... can cause a range error:

RangeError: Maximum call stack size exceeded

when the nums array is very large.

Collapse
 
detunized profile image
Dmitry Yakimenko • Edited

C++, O(n), no sorting, no extra memory allocation beyond storing the input:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v{100, 200, 400, 800, 1600, 3200, 6400, 128000};
    int given_num = 900;

    cout << *min_element(
        v.begin(), 
        v.end(), 
        [=](int a, int b){ return abs(a - given_num) < abs(b - given_num); }
    );

    return 0;
}
Collapse
 
modaf profile image
Modaf

OCaml with list instead of array

let rec closest num list = match list with
[] -> failwith "Empty list"
|[n] -> n
|h :: q ->
    let closest_q = closest num q in
    let val_h = abs (num - h) in
    let val_q = abs (num - closest_q) in
    if (val_h < val_q) then h else closest_q;;
Collapse
 
jamesmh profile image
James Hickey

Here's some C# for everyone:

var nums = new int[] { 100, 200, 400, 800, 1600, 3200, 6400, 128000 };
var given_num = 900;

var result = 
    (
        from num in nums
        let diff = Math.Abs(given_num - num)
        orderby diff
        select num
    )
    .First();