21
\$\begingroup\$

In this code golf, you need to get the closest number from another one in a list.

The output may be the closest number to the input.

Example:

value: (Input) 5 --- [1,2,3] --- 3

And, the program may work with negative numbers.

Example:

value: (Input) 0 --- [-1,3,5] --- -1


value: (Input) 2 --- [1, 5, 3] --- 1 (Because it gives priority to lower numbers)

RULES:

As mentioned before, it has to work with negative numbers.

If there are two answers (Example: 0 -- [5,-5]), the program gives priority to the lowest number. (-5)

This is code golf so the shortest code wins!

\$\endgroup\$
7
  • 8
    \$\begingroup\$ it gives priority to lower numbers That should be mentioned in the rules. \$\endgroup\$ – Dennis Feb 14 '16 at 17:05
  • \$\begingroup\$ If the target number is present in the list, should the output be that number or the closest other number from the list? \$\endgroup\$ – trichoplax Feb 14 '16 at 17:08
  • \$\begingroup\$ I know, the accepted answer is temporal. \$\endgroup\$ – AlexINF Feb 14 '16 at 17:16
  • 4
    \$\begingroup\$ @Alex82 Sure, you know that you'll change the accepted answer if a better one comes in, but some people are put off by challenges that already have an accepted answer, because unfortunately not every challenge author is that attentive to late answers. So it's less about whether accepting early is actually bad but whether people will get the wrong impression. \$\endgroup\$ – Martin Ender Feb 14 '16 at 17:23
  • 1
    \$\begingroup\$ Are the input numbers integers? \$\endgroup\$ – randomra Feb 14 '16 at 18:14

24 Answers 24

7
\$\begingroup\$

Pyth, 6 bytes

haDQSE

Test suite

Input in the following form on STDIN:

num
array

Explanation:

haDQSE
          Implicit: Q = eval(input()) (num)
     E    Evaluate input (array)
    S     Sort (smaller values to the front)
 aDQ      Sort by absolute difference with Q.
h         Take the first element of the sorted list, the min.
          Print implicitly.
\$\endgroup\$
6
\$\begingroup\$

Ruby, 34 bytes

->n,a{a.sort.min_by{|x|(n-x).abs}}
a.sort       min_by tiebreaks by position in array, so put smaller numbers 1st
.min_by{|x|  select the element which returns the smallest val for predicate...
(n-x).abs}   (absolute) difference between input num and element
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think you don't need #sort, since min_by will already sort it from min to max. So, it can be even shorter: ->n,a{a.min_by{|x|(n-x).abs}} \$\endgroup\$ – TiSer Feb 2 '18 at 18:20
5
\$\begingroup\$

Mathematica, 12 bytes

Min@*Nearest

Built-ins FTW! Buettner's explanation: "Mathematica has a built-in Nearest for this, but it returns a list of all tied numbers. Hence, we need to compose it with Min to break the tie."

\$\endgroup\$
4
  • 7
    \$\begingroup\$ That's what I get for writing an explanation... \$\endgroup\$ – Martin Ender Feb 14 '16 at 16:57
  • 1
    \$\begingroup\$ Could you add a "Try it online"? \$\endgroup\$ – AlexINF Feb 14 '16 at 17:04
  • 1
    \$\begingroup\$ @Alex82 Seems unlikely for Mathematica (which is proprietary). \$\endgroup\$ – Martin Ender Feb 14 '16 at 17:07
  • \$\begingroup\$ @Alex82 Test it here: lab.open.wolframcloud.com/app/view/newNotebook?ext=nb \$\endgroup\$ – thedude Feb 14 '16 at 18:25
3
\$\begingroup\$

Pyth, 8 bytes

hS.mabQE

Explanation

         - autoassign Q = eval(input())
  .m   E -   min_values([V for b in eval(input())])
    abQ  -    abs(b-Q)
 S       -  sorted(^)
h        - ^[0]

Try it online!

\$\endgroup\$
0
2
\$\begingroup\$

JavaScript ES6, 64 56 54 bytes

(i,a)=>a.sort((a,b)=>s(i-a)-s(i-b)||a-b,s=Math.abs)[0]

Try it online

Thanks to @Niel for saving two bytes

Test Snippet:

f=(i,a)=>a.sort((a,b)=>s(i-a)-s(i-b)||a-b,s=Math.abs)[0];

[
  [5, [1, 2, 3]],
  [2, [3, 5, 1]],
  [2, [1, 3, 5]],
  [0, [-1, 2, 3]],
  [5, [1, 2, 3]]
].map(v=>O.textContent+=JSON.stringify(v)+": "+f.apply(null,v)+"\n")
<pre id=O></pre>

\$\endgroup\$
3
  • \$\begingroup\$ Save 2 bytes by combining the sorts: (i,a)=>a.sort((a,b)=>s(i-a)-s(i-b)||a-b,s=Math.abs)[0] \$\endgroup\$ – Neil Feb 14 '16 at 18:55
  • \$\begingroup\$ You can save a byte by currying your function: i=>a=>... then f(i)(a) is how you call it. \$\endgroup\$ – Patrick Roberts Feb 15 '16 at 22:00
  • \$\begingroup\$ @PatrickRoberts In this case I would say no, because OP is asking for a function (or simulere) that takes to values: input and a list/array/... as integers \$\endgroup\$ – andlrc Feb 15 '16 at 22:03
2
\$\begingroup\$

Jelly, 7 6 bytes

ạżṛỤḢị

Try it online!

How it works

ạżṛỤḢị Main link. Left input: n (number). Right input: A (list)

ạ      Take the asbolute difference of n and the items of A.
  ṛ    Yield the right argument, A.
 ż     Zip the left result with the right one.
       This pairing causes ties in absolute value to be broken by initial value.
   Ụ   Grade up; sort the indices of the resulting list by their associated values.
    Ḣ  Retrieve the first index, which corresponds to the smallest value.
     ị Retrieve the item of A at that index.
\$\endgroup\$
2
\$\begingroup\$

Jelly, 4 bytes

ạÐṂṂ

Try it online!

This takes A on the left and n on the right

I'm guessing the ÐṂ builtin didn't exist when Dennis wrote his answer.

How it works

ạÐṂṂ - Main link. Takes A on the left and n on the right
 ÐṂ  - Keep elements of A with a minimal:
ạ    -   Absolute difference with n
   Ṃ - Take the minimum
\$\endgroup\$
1
  • \$\begingroup\$ @ovs Good catch, I missed that \$\endgroup\$ – caird coinheringaahing Nov 18 '20 at 12:15
2
\$\begingroup\$

R, 37 bytes

(x=scan())[order(abs(x-scan()),x)][1]

Try it online!

After 4 years, 5 bytes shorter than the previous R answer.

Uses the order() function with two arguments, to order first by the closeness to the target value, and then to break ties by the array value. Finally outputs the first element after re-ordering.

\$\endgroup\$
2
+100
\$\begingroup\$

APL (Dyalog Unicode), 17 16 bytes

⊢{⌊/⍺/⍨⍵=⌊/⍵}∘|-

Try it online!

This is a function which takes a single number as a left argument and a list of numbers as a right argument.

The general structure of this is a fork consisting of:

  • the constant right function returns the list of numbers
  • |- calculates the absolute value of each difference between a number from the list and the left argument
  • and the dfn {⌊/⍺/⍨⍵=⌊/⍵} which is called with the results of the other two functions:
            ⍝ ⍵: absolute differences (|-)
            ⍝ ⍺: the original list (⊢)
       ⌊/⍵  ⍝ the minimum of the absolute differences
     ⍵=     ⍝ element-wise equal to the absolute differences
  ⍺/⍨       ⍝ select all values from the original list where this is 1
⌊/          ⍝ take the minimum

A fully tacit function came out at 17 bytes: ⌊/∘∊((⊢=⌊/)∘|-)⊆⊢.


With some help from Adám, here is a shorter function in the extended variant:

APL (Dyalog Extended), 12 bytes

(⊃⍋⍤|⍤-⊇⊢)∘∧

Try it online!

Same arguments as before, sorts the list ascending and ⊃⍋⍤|⍤-⊇⊢ is applied with the left number and the sorted list as a right argument.

     -   ⍝ the difference between the left argument and each list entry of the sorted list
   |     ⍝ take the absolute values
 ⍋       ⍝ the indices that would sort this list (stable)
      ⊇  ⍝ index with these indices into ...
       ⊢ ⍝ ... the sorted list. This resorts the list on the absolute difference
⊃        ⍝ pick the first value
\$\endgroup\$
8
  • \$\begingroup\$ (⍋⊃¨⊂) sorts ascending as well, if that'd be of help in the tacit version. \$\endgroup\$ – Razetime Feb 17 at 8:40
  • 1
    \$\begingroup\$ @Razetime that's an interesting alternative, but in this case, where we have to ignore the left argument, the best I could do with it is 17 bytes. \$\endgroup\$ – ovs Feb 17 at 8:54
  • \$\begingroup\$ Doesn't ⌊/⊢⊃⍨∘⊃∘⍋∘|- do the trick? Or ⊃⍋⍤|⍤-⊇∧⍤⊢ in Extended? \$\endgroup\$ – Adám Feb 24 at 9:49
  • \$\begingroup\$ @Adám the non-extended version seems to fail for the last testcase on TIO. I guess ⌊/ should do the tiebreak? But doesn't ⊃∘⍋∘|- always result in a single value? \$\endgroup\$ – ovs Feb 24 at 11:08
  • 1
    \$\begingroup\$ That explains it, as I didn't look at the problem spec, only at your second solution. Shortened: ⊃⍤⍋⍤|⍤-∘∧⌷∧⍤⊢ or (⊃⍤⍋⍤|⍤-⌷⊢)∘∧ \$\endgroup\$ – Adám Feb 24 at 12:16
1
\$\begingroup\$

MATL, 10 bytes

Sti-|4#X<)

Try it online!

S       % implicitly input array, and sort. This ensures smaller numbers have priority
t       % duplicate
i       % input number
-|      % compute array of absolute differences
4#X<    % arg min. If there are several minimizers, the position of the first is returned
)       % index into original array. Implicitly display
\$\endgroup\$
1
\$\begingroup\$

Python 2, 56 bytes

a=input()
print sorted(input(),key=lambda x:abs(a-x))[0]

Gets the target number first a=input() - this has to be stored in a variable.

It then sorts the input with the function lambda x:abs(a-x) applied (think map(lambda x:abs(a-x), input()))

It then takes the minimum value in case of any duplicate values

\$\endgroup\$
0
1
\$\begingroup\$

Japt -g, 4 bytes

ÍñaV

Try it

ÍñaV     :Implicit input of array U and integer V
Í        :Sort U
 ñ       :Sort by
  aV     :  Absolute difference with V
         :Implicit output of first element
\$\endgroup\$
1
\$\begingroup\$

Python 3, 41 bytes

lambda n,a:min((abs(n-i),i)for i in a)[1]

Try it online!

No need to sort, because min captures the lowest difference and the lowest value.

Also works in Python 2.

\$\endgroup\$
1
\$\begingroup\$

Husk, 6 4 bytes

◄≠⁰O

Try it online!

◄           # element that minimizes
 ≠⁰         # difference to arg 1
   O        # applied to sorted elements
            # (implicitly) of arg 2
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 4 bytes

{I.x

Try it online or verify all test cases.

Explanation:

{     # Sort the first (implicit) input-list from lowest to highest
  .x  # Pop the list, and push the value closest
 I    # to the second input-integer
      # (after which it is output implicitly as result)

This could have been 2 bytes (.x) if we were allowed to output the first instead of the lowest value in the list, if more than one is closest: try it online or verify all test cases.

\$\endgroup\$
0
\$\begingroup\$

TeaScript, 10 bytes

T#(y-l)a)░

TeaScript doesn't support array input so in the console run: TeaScript("T#y-la)░", [[1, 2, 3], 1], {}, TEASCRIPT_PROPS) to runthis.

Explanation

T#  // Sort input by...
  (y-l)a // absolute difference with input
)░  // First item in array
\$\endgroup\$
0
\$\begingroup\$

R, 42 bytes

x=sort(scan());x[which.min(abs(x-scan()))]
\$\endgroup\$
0
\$\begingroup\$

Haskell, 38 bytes

e#l=snd$minimum$(zip=<<map(abs.(e-)))l

Usage example: 2 # [1,5,3]-> 1.

For each element in the input list l make a pair of the absolute difference of the element with the input number e and the element itself, e.g. e=2, l=[1,5,3] -> [(1,1),(3,5),(1,3)]. Find the minimum and discard the difference.

\$\endgroup\$
0
\$\begingroup\$

zsh, 75 73 71 70 67 bytes

for n in ${@:2};{echo "$[$1-n]    $n"}|tr -d -|sort -n|head -1|cut -f2

Expects input as command line arguments.

Note that the four spaces in the echo is actually supposed to be a tab, but Stack Exchange converts tabs to spaces in all posts.

Not Bash-compatible because of the for syntax.

for n in ${@:2};      for each argument except the first...
{echo "$[$1-n]\t$n"}  output the difference from the first argument
                        and then the original number
|tr -d -              poor man's abs()
|sort -n              sort by first num (difference), tiebreaking by second num
                        (original value)
|head -1              take the thing that sorted first
|cut -f2              print field 2 (aka discard the difference)

Thanks to dev-null for 2 bytes!

\$\endgroup\$
0
0
\$\begingroup\$

Perl 6, 31 bytes

{@^b.sort.sort((*-$^a).abs)[0]}

Usage:

my &code = {@^b.sort.sort((*-$^a).abs)[0]}

say code 5, [1,2,3];   # 3
say code 0, [-1,3,5];  # -1
say code 2, [1, 5, 3]; # 1
say code 0, [5,-5];    # -5
\$\endgroup\$
0
\$\begingroup\$

Stax, 7 bytes

ôXêUe>┤

Run and debug it

\$\endgroup\$
0
\$\begingroup\$

PHP, 62 bytes

foreach($a as $i){$s[$i]=abs($i-$n);}
asort($s);print key($s);

Try it online!

First PHP answer, please help!

(Define the number and array in header section)

\$\endgroup\$
0
\$\begingroup\$

T-SQL, 93 Bytes

SELECT MIN(B) FROM(SELECT B,abs(B-@v) AS C FROM @A) D WHERE C=(SELECT MIN(abs(B-@v)) FROM @A)

Example:

DECLARE @A TABLE(B  INT);
DECLARE @v INT = 5;
INSERT INTO @A SELECT * FROM (VALUES(1),(2),(3)) AS A(B);

SELECT MIN(B) -- 3. Finally, select the minimum list value from the rowset
FROM(
        SELECT B,abs(B-@v) AS C -- 1. Get list value along with absolute value of the difference.
        FROM @A
    ) D
WHERE C = (SELECT MIN(abs(B-@v)) -- 2. Filter for the smallest absolute difference.
          FROM @A
          )
\$\endgroup\$
0
\$\begingroup\$

C# 61 52 bytes

int v(int i,int[] a)=>a.Min(x=>(Math.Abs(i-x),x)).x;

Or function body only: 29 bytes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.