Arithmetic Progressions

11

Your task is to analyse the input and output the formula for the n-th term if it is an arithmetic sequence, otherwise it should print "NAAP".


Input

Input (from STDIN) will consist of few numbers, between 4 to 10 numbers where each number will be in the range between -1000 and 1000 inclusive, separated by a delimiter (a space or a comma or a semi-colon [whichever is to your preference]). Here are some example inputs.

12,14,16,18       //valid
-3 4 5 1 -2 -4    //valid
45;35;-35         //invalid (only three numbers are present instead of the minimum of 4 numbers)
2,32;21,321       //invalid (it uses two different delimiters: `,` and `;`)

Output

The program should first check whether the input is an arithmetic progression or not.

Arithmetic Progressions (AP) in a nutshell: Every AP will have a common difference. This is the difference between the $n$ and ${n-1}$ th terms (basically $a(n+1) - a(n)$ where a is the function for the sequnce). This difference stays the same for any value of $n$ in an AP. If there is no common difference, then it is not an arithmetic sequence. To calculate the value of the n-th term, use this formula $a(n) = a(1) + (n-1)d$ where $a(1)$ is the first term and $d$ is the common difference.

If it is not an arithmetic progression, then the program should print the error message "NAAP" (short for "Not An Arithmetic Progression").

If it is an arithmetic progression, then the program should print the simplified n-th term of the sequence to STDOUT.

Example:

> 1,3,5,7,9
2n-1

Explanation: This is an AP because there is a common difference ($3 - 1 = 2$). Then you use the formula $a(n) = a(1) + (n-1)d$

$$a_n = a_1 + (n-1)d$$

$$a_n = 1 + (n-1)2$$

$$a_n = 1 + 2n - 2$$

$$a_n = 2n - 1$$

Therefore output is 2n-1 (notice the absence of spaces)


Standard loopholes are disallowed by default.

You are allowed to create a function if you want (with the array of numbers as your parameter). If not, then you must create a full program that takes input as a string or an array and outputs accordingly.

Test cases:

1.

1,3,5,7,9
2n-1

2.

1 3 12312 7 9
NAAP

3.

-6;8;22;36;50
14n-20

4.

5,1,-3,-7,-11,-15
-4n+9

5.

-5,-7,-9,-11,-13,-15
-2n-3

6.

3,3,3,3,3,3,3,3,3
0n+3

7.

-4,-5,-6,-7
-1n-3

This is so the shortest code in bytes wins! (sorry for bad math-jax)

Any suggestions are welcome!

user41805

Posted 2015-12-03T18:26:43.940

Reputation: 16 320

4You should probably keep your post in the sandbox for more than an hour... – Mego – 2015-12-03T18:30:39.843

@Mego It has been more than one hour. – user41805 – 2015-12-03T18:32:18.343

3One hour is a really short time. Not everybody checks the sandbox constantly. 24 hours is a good minimum. – Mego – 2015-12-03T18:32:58.683

http://i.imgur.com/yS4JpMM.png – Mego – 2015-12-03T18:33:01.540

@Mego Sorry, I am new to the "Sandbox" concept... – user41805 – 2015-12-03T18:34:03.910

8Sorry, but although MathJax works on Meta, it doesn't work on the main PPCG site... – ETHproductions – 2015-12-03T18:35:31.607

1You should add test cases with decreasing sequences. – lirtosiast – 2015-12-04T00:44:16.887

2Are 0,0,0,0 and 3,1,-1,-3,-5 arithmetic progressions? If so, I think they'd be good test cases, since they broke a method I was trying. – xnor – 2015-12-04T02:50:19.250

@ThomasKwa Done. – user41805 – 2015-12-04T04:58:37.180

@xnor Yes, they are AP. – user41805 – 2015-12-04T04:59:11.257

Answers

5

Pyth, 30 bytes

?tJ{-VtQQ"NAAP"+hJ%"n%+d"-hQhJ

Test suite

To check whether it's a arithmetic procession, this uses a vectorized subtraction between each element and the previous, -VtQQ. A ternary checks if there are multiple values in the result (?tJ{) and prints NAAP if so. Then, to get the + or - right, the mod-formating %+d is used.

isaacg

Posted 2015-12-03T18:26:43.940

Reputation: 39 268

3

Haskell, 103 bytes

z=(tail>>=).zipWith
f l@(a:b:_:_:_)|and$z(==)$z(-)l=show(b-a)++'n':['+'|b-a<=a]++show(a+a-b)
f _="NAAP"

Usage example:

f [-6,8,22,36,50]   ->   "14n-20"
f [60,70,80,90]     ->   "10n+50"
f [2,3,4,6,7,8]     ->   "NAAP"

As always in Haskell, fancy output formatting (e.g. mixing numbers with strings) eats a lot of bytes (around 40). The program logic is quite compact:

f l@(a:b:_:_:_)           -- pattern match an input list with at least 4 elements,
                          -- call the whole list l, the first two elements a and b
z=(tail>>=).zipWith       -- the helper function z takes a function f and a list l
                          -- and applies f element wise to the tail of l and l

           z(-)l          -- make a list of neighbor differences
     z(==)                -- then compare these differences for equality
 and                      -- and see if only True values occur

       show ...           -- if so format output string

f _="NAAP"                -- in all other cases ( < 4 elements or False values)
                          -- return "NAAP"

nimi

Posted 2015-12-03T18:26:43.940

Reputation: 34 639

2

Japt, 60 52 51 bytes

V=N¤£X-NgY+1};W=Vg;Ve_¥W} ?W+'n+'+sU<W +(U-W :"NAAP

Try it online!

Input can be given with whichever separator you like, as that's how the interpreter is designed ;)

Ungolfed and explanation

V=N¤  £    X-NgY+1};W=Vg;Ve_  ¥ W} ?W+'n+'+sU<W +(U-W :"NAAP
V=Ns2 mXYZ{X-NgY+1};W=Vg;VeZ{Z==W} ?W+'n+'+sU<W +(U-W :"NAAP

            // Implicit: N = list of inputs, U = first input
V=Ns2       // Set variable V to N, with the first 2 items sliced off,
mXYZ{       // with each item X and index Y mapped to:
X-NgY+1}    //  X minus the item at index Y+1 in N.
            // This results in a list of the differences (but the first item is NaN).
W=Vg;       // Set W to the first item in V (the multiplication part).
VeZ{Z==W}   // Check if every item in V is equal to W.
?W+'n+      // If true, return W + "n" +
'+sU<W      //  "+".slice(U<W) (this is "+" if U >= W, and "" otherwise)
+(U-W       //  + (U minus W [the addition part]).
:"NAAP      // Otherwise, return "NAAP".
            // Implicit: output last expression

ETHproductions

Posted 2015-12-03T18:26:43.940

Reputation: 47 880

2

TI-BASIC, 70 bytes

Input X
ΔList(∟X->Y
If variance(Ans
Then
∟X(1)-min(Ans
Text(0,0,min(∟Y),"n",sub("+-",(Ans<0)+1,1),abs(Ans
Else
"NAAP

To remedy TI-BASIC's lack of number-to-string conversion, this uses output on the graphscreen (Text() if the progression is arithmetic, which automatically concatenates the arguments together.

This assumes that negative numbers are entered using TI-BASIC's high-minus character (which looks a little like ), not the binary minus sign. However, output uses the binary minus sign.

lirtosiast

Posted 2015-12-03T18:26:43.940

Reputation: 20 331

1

Matlab, 103 bytes

x=str2num(input('','s'));y=diff(x);if range(y) disp('NAAP'),else fprintf('%gn%+g\n',y(1),x(1)-y(1)),end

Luis Mendo

Posted 2015-12-03T18:26:43.940

Reputation: 87 464

1

CJam, 38 bytes

{:T2ew::-):U-"NAAP"UW*"n%+d"T0=U+e%+?}

This is an anonymous function that takes an array on the stack as input, and leaves a string on the stack as output. Try it online with additional I/O code for testing.

Explanation:

:T      Save a copy of input in variable T for output generation.
2ew     Generate list of pairs of sequential elements.
::-     Reduce all pairs with subtraction operator.
)       Pop last value from list of differences.
:U      Save difference value in variable U for output generation.
-       Set difference. This will leave an empty list (falsy) if all values are the same.
"NAAP"  First value for ternary operator, for case where not all values are the same.
UW*     Start generating output for success case. Need to flip sign of difference saved
        in variable U, since it was 1st value minus 2nd, and we need the opposite.
"n%+d"  Push format string for printf operator. The + sign in the format specifies that
        the sign is always generated, saving us from needing different cases for the
        value being negative or positive.
T0=     Extract first value from original input saved in variable T.
U+      Add the difference (with the "wrong" sign) to it.
e%      "printf" operator.
+       Concatenate two parts of result.
?       Ternary operator for picking one of the two output cases.

Reto Koradi

Posted 2015-12-03T18:26:43.940

Reputation: 4 870

1

JavaScript (ES6), 91 bytes

x=>(s=x.split`,`,m=s[1]-s[0],a=s[0]-m,s.some((n,i)=>n!=m*i+m+a)?"NAAP":m+"n"+(a<0?a:"+"+a))

Explanation

x=>(
  s=x.split`,`,       // s = array of input numbers
  m=s[1]-s[0],        // m = the multiplication part of the formula
  a=s[0]-m,           // a = the addition part of the formula
  s.some((n,i)=>      // check if the rest of the numbers follow this sequence
    n!=m*i+m+a
  )?"NAAP":
  m+"n"+(a<0?a:"+"+a) // output the formula
)

Test

<input type="text" id="input" value="5,1,-3,-7,-11,-15" /><button onclick='result.innerHTML=(

x=>(s=x.split`,`,m=s[1]-s[0],a=s[0]-m,s.some((n,i)=>n!=m*i+m+a)?"NAAP":m+"n"+(a<0?a:"+"+a))

)(input.value)'>Go</button><pre id="result"></pre>

user81655

Posted 2015-12-03T18:26:43.940

Reputation: 10 181

1

Perl 6, 123 102 101 bytes

EDIT: Don't negate difference

EDIT: use anonymous sub, logical operators and string interpolation. Thanks Brad Gilbert b2gills

sub{my@b=@_.rotor(2=>-1).map({[-] $_}).squish;$_=@_[0]+@b[0];@b.end&&"NAAP"||"@b[0]n{'+'x($_>=0)}$_"}

Test program (reads from stdin):

my $f = <the code above>
$f(split(/<[;,]>/, slurp)).say

Explanation:

my @b =
  @_.rotor(2=>-1)  # sliding window of 2: (1,2,3,4) => ((1,2),(2,3),(3,4))
  .map({[-] $_})  # calculate difference (subtract all elements and negate)
  .squish;         # remove adjacent elements that are equal

@b.end        # @b.end is last index, @b.end = 0 means @b has only 1 element
&& "NAAP"     # true branch
|| "@b[0]n{'+'x($_>=0)}$_" # string for an+b, 
        # {'+'x($_>=0)} inserts a plus sign using the repetition operator x

Ming-Tang

Posted 2015-12-03T18:26:43.940

Reputation: 5 383

Typically you would use one of the lambda expression forms so that you can remove the sub f. Also if you used @_ instead of @a you would save several bytes. {my@b=@_.rotor.... Also you shouldn't put parens around the condition of an if statement, this isn't Perl 5. If you changed that if to @b.end&&"NAAP"||$_=... you would save a few more bytes. You can also do away with that last if statement if you used "@b[0]n{'+'x($_>=0)}$_" instead, saving 4 bytes. – Brad Gilbert b2gills – 2015-12-04T16:26:25.237

You don't need sub at the beginning, without that it becomes an anonymous block. Also just so you know, I wouldn't have thought of using .map({[-] $_}) I would have probably used ».map(*-*).flat which is longer, now I have to go through my own entries to see if I can shorten it with your trick. – Brad Gilbert b2gills – 2015-12-05T17:04:41.167

1

Ruby, 95 78 76 bytes

->s{i,j=s;puts s.reduce(:+)==s.size*(s[-1]+i)/2?"%dn%+d"%[v=j-i,i-v]:"NAAP"}

78 bytes

->s{puts s.reduce(:+)==s.size*(s[-1]+i=s[0])/2?"%dn%+d"%[v=s[1]-i,i-v]:"NAAP"}

95 bytes

->s{puts s.reduce(:+)==s.size*(s[0]+s[-1])/2?"#{v=s[1]-s[0]}n#{"+"if (i=s[0]-v)>0}#{i}":"NAAP"}

Ungolfed:

-> s {
  i,j=s
  puts s.reduce(:+)==s.size*(s[-1]+i)/2?"%dn%+d"%[v=j-i,i-v]:"NAAP"
}

Usage:

->s{i,j=s;puts s.reduce(:+)==s.size*(s[-1]+i)/2?"%dn%+d"%[v=j-i,i-v]:"NAAP"}[[-6,8,22,36,50]]

=> 14n-20

Vasu Adari

Posted 2015-12-03T18:26:43.940

Reputation: 941

0

Python 3, 92 bytes
Based on my answer from Find the Sequence

def m(t):s=str;a=t[0];b=t[1];q=b-a;return((s(q)+'n'+'+'*(0<a-q)+s(a-q)),'NAAP')[t[2]/b==b/a]

george

Posted 2015-12-03T18:26:43.940

Reputation: 1 495