Retornar o número primo mais próximo


33

Desafio

É simples: dado um número inteiro positivo de até 1.000.000, retorne o número primo mais próximo.

Se o número em si é primo, você deve retornar esse número; se houver dois números primos igualmente próximos ao número fornecido, retorne o menor dos dois.

A entrada está na forma de um único número inteiro e a saída também deve estar na forma de um número inteiro.

Não me importo com o modo como você recebe a entrada (função, STDIN, etc.) ou exibe a saída (função, STDOUT, etc.), desde que funcione.

Este é um código de golfe, portanto, aplicam-se regras padrão - o programa com menos bytes vence!

Casos de teste

Input  =>  Output
------    -------
80     =>      79
100    =>     101
5      =>       5
9      =>       7
532    =>     523
1      =>       2

5
Hi and welcome to PPCG!. To avoid down voting due to lack of quality I suggest you to post it to the sandbox first and after a couple of days post it here
— Luis felipe De jesus Munoz

This is one of the outputs requested in this challenge.
— Arnauld

Very closely related but not quite identical.
— Giuseppe

@Arnauld I saw that one, but I thought that they were different enough to warrant a new question.
— Nathan Dimmer

2
See also OEIS A051697.
— Eric Towers

Respostas:


9

Gaia, 3 bytes

ṅD⌡

Try it online!

Rather slow for large inputs, but works given enough memory/time.

I'm not sure why D⌡ implicitly pushes z again, but it makes this a remarkably short answer!

ṅ	| implicit input z: push first z prime numbers, call it P
 D⌡	| take the absolute difference between P and (implicit) z,
	| returning the smallest value in P with the minimum absolute difference

13

JavaScript (ES6), 53 bytes

n=>(g=(o,d=N=n+o)=>N%--d?g(o,d):d-1?g(o<0?-o:~o):N)``

Try it online!

Commented

n => (            // n = input
  g = (           // g = recursive function taking:
    o,            //   o = offset
    d =           //   d = current divisor, initialized to N
    N = n + o     //   N = input + offset
  ) =>            //
    N % --d ?     // decrement d; if d is not a divisor of N:
      g(o, d)     //   do recursive calls until it is
    :             // else:
      d - 1 ?     //   if d is not equal to 1 (either N is composite or N = 1):
        g(        //     do a recursive call with the next offset:
          o < 0 ? //       if o is negative:
            -o    //         make it positive (e.g. -1 -> +1)
          :       //       else:
            ~o    //         use -(o + 1) (e.g. +1 -> -2)
        )         //     end of recursive call
      :           //   else (N is prime):
        N         //     stop recursion and return N
)``               // initial call to g with o = [''] (zero-ish)


7

Octave, 40 bytes

@(n)p([~,k]=min(abs(n-(p=primes(2*n)))))

Try it online!

This uses the fact that there is always a prime between n and 2*n (Bertrand–Chebyshev theorem).

How it works

@(n)p([~,k]=min(abs(n-(p=primes(2*n)))))

@(n)                                      % Define anonymous function with input n
                       p=primes(2*n)      % Vector of primes up to 2*n. Assign to p
                abs(n-(             ))    % Absolute difference between n and each prime
      [~,k]=min(                      )   % Index of first minimum (assign to k; not used)
    p(                                 )  % Apply that index to p

6

Japt, 5 bytes

_j}cU

Try it or run all test cases

_j}cU     :Implicit input of integer U
_         :Function taking an integer as an argument
 j        :  Test if integer is prime
  }       :End function
   cU     :Return the first integer in [U,U-1,U+1,U-2,...] that returns true


5

Wolfram Language (Mathematica), 31 bytes

Nearest[Prime~Array~78499,#,1]&

Try it online!

                              & (*pure function*)
        Prime~Array~78499       (*among the (ascending) first 78499 primes*)
                            1   (*select one*)
Nearest[                 ,#, ]  (*which is nearest to the argument*)

1000003 is the 78499th prime. Nearest prioritizes values which appear earlier in the list (which are lower).


5
Nearest[Prime@Range@#,#,1]& for 27
— Ben

5

Brachylog, 7 5 bytes

;I≜-ṗ

Try it online!

Saved 2 bytes thanks to @DLosc.

Explanation

;I≜      Label an unknown integer I (tries 0, then 1, then -1, then 2, etc.)
   -     Subtract I from the input
    ṗ    The result must be prime

@DLosc Mostly because I am stupid. Thanks.
— Fatalize

I think we just approached it from different directions. You were thinking about ≜ from the start, I assume, whereas I was thinking about pairing and subtracting and only later realized I'd need ≜ to make it work. :)
— DLosc

4

Pyth, 10 bytes

haDQfP_TSy

Try it online here, or verify all the test cases at once here.

haDQfP_TSyQ   Implicit: Q=eval(input())
              Trailing Q inferred
         yQ   2 * Q
        S     Range from 1 to the above
    f         Filter keep the elements of the above, as T, where:
     P_T        Is T prime?
  D           Order the above by...
 a Q          ... absolute difference between each element and Q
                This is a stable sort, so smaller primes will be sorted before larger ones if difference is the same
h             Take the first element of the above, implicit print

4

Jelly, 9 7 bytes

ḤÆRạÞµḢ

Try it online!

Slow for larger input, but works ok for the requested range. Thanks to @EriktheOutgolfer for saving 2 bytes!


Hey, that's clever! Save two by substituting _A¥ with ạ (absolute difference). Oh, and Ḥ can really be ‘.
— Erik the Outgolfer

@EriktheOutgolfer thanks. Surely using ‘ won’t always work? It means that only primes up to n+1 will be found, while the closest might be n+2.
— Nick Kennedy

Hm, that's a concern.
— Erik the Outgolfer

4

Python 2, 71 bytes

f=lambda n,k=1,p=1:k<n*3and min(k+n-p%k*2*n,f(n,k+1,p*k*k)-n,key=abs)+n

Try it online!

A recursive function that uses the Wilson's Theorem prime generator. The product p tracks (k−1)!2, and p%k is 1 for primes and 0 for non-primes. To make it easy to compare abs(k-n) for different primes k, we store k-n and compare via abs, adding back n to get the result k.

The expression k+n-p%k*2*n is designed to give k-n on primes (where p%k=1), and otherwise a "bad" value of k+n that's always bigger in absolute value and so doesn't affect the minimum, so that non-primes are passed over.



3

Tidy, 43 bytes

{x:(prime↦splice(]x,-1,-∞],[x,∞]))@0}

Try it online!

Explanation

This is a lambda with parameter x. This works by creating the following sequence:

[x - 1, x, x - 2, x + 1, x - 3, x + 2, x - 4, x + 3, ...]

This is splicing together the two sequences ]x, -1, -∞] (left-closed, right-open) and [x, ∞] (both open).

For x = 80, this looks like:

[79, 80, 78, 81, 77, 82, 76, 83, 75, 84, 74, 85, ...]

Then, we use f↦s to select all elements from s satisfying f. In this case, we filter out all composite numbers, leaving only the prime ones. For the same x, this becomes:

[79, 83, 73, 71, 89, 67, 97, 61, 59, 101, 103, 53, ...]

Then, we use (...)@0 to select the first member of this sequence. Since the lower of the two needs to be selected, the sequence which starts with x - 1 is spliced in first.

Note: Only one of x and x - 1 can be prime, so it is okay that the spliced sequence starts with x - 1. Though the sequence could be open on both sides ([x,-1,-∞]), this would needlessly include x twice in the sequence. So, for sake of "efficiency", I chose the left-closed version (also because I like to show off Tidy).



3

APL (Dyalog Extended), 20 15 bytesSBCS

Tacit prefix function inspired by Galen Ivanov's J answer.

⊢(⊃⍋⍤|⍤-⊇⊢)¯2⍭⍳

Try it online!

⍳ ɩndices one through the argument.

¯2⍭ nth primes of that

⊢(…) apply the following tacit function to that, with the original argument as left argument:

 ⊢ the primes

 ⊇ indexed by:

  ⍋ the ascending grade (indices which would sort ascending)
  ⍤ of
  | the magnitude (absolute value)
  ⍤ of
  - the differences

 ⊃ pick the first one (i.e. the one with smallest difference)


3

Perl 6, 35 bytes

{$_+=($*=-1)*$++until .is-prime;$_}

Try it online!

This uses Veitcel's technique for generating the list of 0, -1, 2, -3 but simplifies it greatly to ($*=-1)*$++ using the anonymous state variables available in P6 (I originally had -1 ** $++ * $++, but when golfed the negative loses precedence). There's a built in prime checker but unfortunately the until prevents the automagically returned value so there's an extra $_ hanging around.


I'd usually use a sequence operator approach to something like this, but comes out to one byte longer, so nice work finding a shorter method
— Jo King

@JoKing good catch. The things that happen when I golf too quickly after getting a working solution. I had a similar one but the damned lack of [-1] haha
— user0721090601

3

C, 122 121 104 bytes

p(a,i){for(i=1;++i<a;)if(a%i<1)return 0;return a>1;}c(a,b){for(b=a;;b++)if(p(--a)|p(b))return p(b)?b:a;}

Use it calling function c() and passing as argument the number; it should return the closest prime.

Thanks to Embodiment of Ignorance for 1 byte saved a big improvement.

Try it online!


But c() receives two parameters... Also, you can probably shorten the while(1) to for(;;) (untested, since I don't get how to run your code
— Embodiment of Ignorance

@EmbodimentofIgnorance I wrote it and tested it all on an online c compiler, I could call c() passing only the first parameter. And you are right, for(;;) saves me a byte, only 117 left to get first place :)
— Lince Assassino

110 bytes: #define r return p(a,i){i=1;while(++i<a)if(a%i<1)r 0;r a>1;}c(a,b){b=a;for(;;b++){if(p(--a))r a;if(p(b))r b;}}. Here is a TIO link: tio.run/…
— Embodiment of Ignorance




2

APL(NARS), 38 chars, 76 bytes

{⍵≤1:2⋄0π⍵:⍵⋄d←1π⍵⋄(d-⍵)≥⍵-s←¯1π⍵:s⋄d}

0π is the test for prime, ¯1π the prev prime, 1π is the next prime; test:

  f←{⍵≤1:2⋄0π⍵:⍵⋄d←1π⍵⋄(d-⍵)≥⍵-s←¯1π⍵:s⋄d}
  f¨80 100 5 9 532 1
79 101 5 7 523 2 


2

Perl 5, 59 bytes

$a=0;while((1x$_)=~/^.?$|^(..+?)\1+$/){$_+=(-1)**$a*($a++)}

Try it online!

/^.?$|^(..+?)\1+$/ is tricky regexp to check prime

(-1)**$a*($a++) generate sequence 0,-1, 2,-3 ...


2

MathGolf, 10 bytes

∞╒g¶áÅ-±├Þ

Try it online.

Explanation:

∞            # Double the (implicit) input-integer
 ╒           # Create a list in the range [1, 2*n]
  g         # Filter so only the prime numbers remain
    áÅ       # Sort this list using the next two character:
      -±     #  The absolute difference with the (implicit) input-integer
        ├    # Push the first item of the list
             # (unfortunately without popping the list itself, so:)
         Þ   # Discard everything from the stack except for the top
             # (which is output implicitly as result)

@JoKing Thanks! I knew Max thought about changing it, but didn't knew he actually did. The docs still state the old one.
— Kevin Cruijssen

Ah, I use the mathgolf.txt file as reference, since it seems to be more up to date
— Jo King

@JoKing Yeah, he told me yesterday about that file as well. Will use it from now on. :)
— Kevin Cruijssen


2

C# (Visual C# Interactive Compiler), 104 100 bytes

n=>{int r=0,t=0,m=n;while(r!=2){n+=(n<m)?t:-t;t++;r=0;for(int i=1;i<=n;i++)if(n%i==0)r++;}return n;}

Try it online!

Explanation:

int f(int n)
{
    int r = 0; //stores the amount of factors of "n"
    int t = 0; //increment used to cover all the integers surrounding "n"
    int m = n; //placeholder to toggle between adding or substracting "t" to "n"

    while (r != 2) //while the amount of factors found for "n" is different to 2 ("1" + itself)
    {
        n += (n < m) ? t : -t; //increment/decrement "n" by "t" (-0, -1, +2, -3, +4, -5,...)
        t++;
        r = 0;
        for (int i = 1; i <= n; i++) //foreach number between "1" and "n" increment "r" if the remainder of its division with "n" is 0 (thus being a factor)
            if (n % i == 0) r++; 
    }
    return n;
}

Console.WriteLine(f(80)); //79

2

Java 8, 88 87 bytes

n->{for(int c=0,s=0,d,N=n;c!=2;s++)for(c=d=1,n+=n<N?s:-s;d<n;)if(n%++d<1)c++;return n;}

Port of @NaturalNumberGuy's (first) C answer, so make sure to upvote him!!
-1 byte thanks to @OlivierGrégoire.

Try it online.

Explanation:

n->{               // Method with integer as both parameter and return-type
  for(int c=0,     //  Counter-integer, starting at 0
          s=0,     //  Step-integer, starting at 0 as well
          d,       //  Divisor-integer, uninitialized
          N=n;     //  Copy of the input-integer
      c!=2;        //  Loop as long as the counter is not exactly 2 yet:
      s++)         //    After every iteration: increase the step-integer by 1
    for(c=d=1,     //   (Re)set both the counter and divisor to 1
        n+=n<N?    //   If the input is smaller than the input-copy:
            s      //    Increase the input by the step-integer
           :       //   Else:
            -s;    //    Decrease the input by the step-integer
        d<n;)      //   Inner loop as long as the divisor is smaller than the input
      if(n%++d     //    Increase the divisor by 1 first with `++d`
              <1)  //    And if the input is evenly divisible by the divisor:
        c++;       //     Increase the counter-integer by 1
  return n;}       //  Return the now modified input-integer as result

2

Java (JDK), 103 bytes

n->{int p=0,x=0,z=n,d;for(;p<1;p=p>0?z:0,z=z==n+x?n-++x:z+1)for(p=z/2,d=1;++d<z;)p=z%d<1?0:p;return p;}

Try it online!


Umm.. I had already create a port of his answer.. ;) Although yours is 1 byte shorter, so something is different. EDIT: Ah, I have a result-integer outside the loop, and you modify the input inside the loop, hence the -1 byte for ;. :) Do you want me to delete my answer?.. Feel free to copy the explanation.
— Kevin Cruijssen

@KevinCruijssen Oops, rollbacked!
— Olivier Grégoire

Sorry about that (and thanks for the -1 byte). I like your version as well, though. Already upvoted before I saw NaturalNumberGuy's answer.
— Kevin Cruijssen

2

Haskell, 79 74 bytes (thanks to Laikoni)

72 bytes as annonymus function (the initial "f=" could be removed in this case).

f=(!)(-1);n!x|x>1,all((>0).mod x)[2..x-1]=x|y<-x+n=last(-n+1:[-n-1|n>0])!y

Try it online!


original code:

f=(!)(-1);n!x|x>1&&all((>0).mod x)[2..x-1]=x|1>0=(last$(-n+1):[-n-1|n>0])!(x+n)

Try it online!

Explanation:

f x = (-1)!x

isPrime x = x > 1 && all (\k -> x `mod` k /= 0)[2..x-1]
n!x | isPrime x = x            -- return the first prime found
    | n>0       = (-n-1)!(x+n) -- x is no prime, continue with x+n where n takes the 
    | otherwise = (-n+1)!(x+n) -- values -1,2,-3,4 .. in subsequent calls of (!)

1
Inside a guard you can use , instead of &&. (last$ ...) can be last(...), and the second guard 1>0 can be used for a binding to save parenthesis, e.g. y<-x+n.
— Laikoni

Anonymous functions are generally allowed, so the initial f= does not need to be counted. Also the parenthesis enclosing (-1+n) can be dropped.
— Laikoni

Thanks for the suggestions. I didn't know "," and bindings are allowed in function guards! But i don't really like the idea of an annonymous function as an answer. It doesn't feel right in my opinion.
— Sachera

You can find more tips in our collection of tips for golfing in Haskell. There is also a Guide to Golfing Rules in Haskell and dedicated chat room: Of Monads and Men.
— Laikoni

2

VDM-SL, 161 bytes

f(i)==(lambda p:set of nat1&let z in set p be st forall m in set p&abs(m-i)>=abs(z-i)in z)({x|x in set{1,...,9**7}&forall y in set{2,...,1003}&y<>x=>x mod y<>0})

A full program to run might look like this - it's worth noting that the bounds of the set of primes used should probably be changed if you actually want to run this, since it will take a long time to run for 1 million:

functions
f:nat1+>nat1
f(i)==(lambda p:set of nat1&let z in set p be st forall m in set p&abs(m-i)>=abs(z-i)in z)({x|x in set{1,...,9**7}&forall y in set{2,...,1003}&y<>x=>x mod y<>0})

Explanation:

f(i)==                                        /* f is a function which takes a nat1 (natural number not including 0)*/
(lambda p:set of nat1                         /* define a lambda which takes a set of nat1*/
&let z in set p be st                         /* which has an element z in the set such that */
forall m in set p                             /* for every element in the set*/
&abs(m-i)                                     /* the difference between the element m and the input*/
>=abs(z-i)                                    /* is greater than or equal to the difference between the element z and the input */
in z)                                         /* and return z from the lambda */
(                                             /* apply this lambda to... */
{                                             /* a set defined by comprehension as.. */
x|                                            /* all elements x such that.. */ 
x in set{1,...,9**7}                          /* x is between 1 and 9^7 */
&forall y in set{2,...,1003}                  /* and for all values between 2 and 1003*/
&y<>x=>x mod y<>0                             /* y is not x implies x is not divisible by y*/
} 
)


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.