Top Banner
AKS test for primes You are encouraged to solve this task according to the task description, using any language you may know. AKS test for primes From Rosetta Code The AKS algorithm (http://www.cse.iitk.ac.in/users/manindra/algebra /primality_v6.pdf) for testing whether a number is prime is a polynomial-time algorithm based on an elementary theorem about Pascal triangles. The theorem on which the test is based can be stated as follows: a number p is prime if and only if all the coefficients of the polynomial expansion of (x − 1) p − (x p − 1) are divisible by p. For example, trying p = 3: (x − 1) 3 − (x 3 − 1) = (x 3 − 3x 2 + 3x − 1) − (x 3 − 1) = − 3x 2 + 3x And all the coefficients are divisible by 3 so 3 is prime. Note: This task is not the AKS primality test. It is an inefficient exponential time algorithm discovered in the late 1600s and used as an introductory lemma in the AKS derivation. The task Create a function/subroutine/method that given p generates the coefficients of the expanded polynomial representation of (x − 1) p . 1. Use the function to show here the polynomial expansions of (x − 1) p for p in the range 0 to at least 7, inclusive. 2. Use the previous function in creating another function that when given p returns whether p is prime using the theorem. 3. Use your test to generate a list of all primes under 35. 4. As a stretch goal, generate all primes under 50 (Needs greater than 31 bit integers). 5. References Agrawal-Kayal-Saxena (AKS) primality test (https://en.wikipedia.org/wiki/AKS_primality_test) (Wikipedia) Fool-Proof Test for Primes (http://www.youtube.com/watch?v=HvMSRWTE2mI) - Numberphile (Video). The accuracy of this video is disputed -- at best it is an oversimplification. Contents 1 ALGOL 68 2 AutoHotkey 1 of 53
53

Aks Codes

Dec 11, 2015

Download

Documents

Margit Orsós

Code Collection of the Aks algorithm
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Aks Codes

AKS testfor primesYou areencouragedto solve this

task according to thetask description, usingany language you mayknow.

AKS test for primesFrom Rosetta Code

The AKS algorithm (http://www.cse.iitk.ac.in/users/manindra/algebra/primality_v6.pdf) for testing whether a number is prime is apolynomial-time algorithm based on an elementary theorem aboutPascal triangles.

The theorem on which the test is based can be stated as follows:

a number p is prime if and only if all the coefficients of thepolynomial expansion of

(x − 1)p − (xp − 1)

are divisible by p.

For example, trying p = 3:

(x − 1)3 − (x3 − 1) = (x3 − 3x2 + 3x − 1) − (x3 − 1) = − 3x2 + 3xAnd all the coefficients are divisible by 3 so 3 is prime.

Note:This task is not the AKS primality test. It is an inefficient exponential timealgorithm discovered in the late 1600s and used as an introductory lemma

in the AKS derivation.

The task

Create a function/subroutine/method that given p generates the coefficients of the expandedpolynomial representation of (x − 1)p.

1.

Use the function to show here the polynomial expansions of (x − 1)p for p in the range 0 to atleast 7, inclusive.

2.

Use the previous function in creating another function that when given p returns whether pis prime using the theorem.

3.

Use your test to generate a list of all primes under 35.4. As a stretch goal, generate all primes under 50 (Needs greater than 31 bit integers).5.

References

Agrawal-Kayal-Saxena (AKS) primality test (https://en.wikipedia.org/wiki/AKS_primality_test)(Wikipedia)Fool-Proof Test for Primes (http://www.youtube.com/watch?v=HvMSRWTE2mI) -Numberphile (Video). The accuracy of this video is disputed -- at best it is anoversimplification.

Contents

1 ALGOL 682 AutoHotkey

1 of 53

Page 2: Aks Codes

3 Bracmat4 C5 C#6 Clojure7 CoffeeScript8 Common Lisp9 D10 EchoLisp11 Erlang12 Fortran13 Go14 FreeBASIC15 Haskell16 J17 Java18 JavaScript19 jq20 Julia21 Maple22 Mathematica / Wolfram Language23 Oforth24 PARI/GP25 Pascal26 Perl

26.1 Real AKS27 Perl 628 Phix29 PicoLisp30 Prolog

30.1 Prolog(ue)30.2 Pascal Triangle Generator30.3 Solutions

31 PureBasic32 Python

32.1 Python: Output formatted for wiki33 R34 Racket35 REXX

35.1 version 135.2 version 2

36 Ruby37 Rust38 Scala39 Scilab40 Seed741 Sidef42 Swift43 Tcl44 uBasic/4tH45 zkl

ALGOL 68

2 of 53

Page 3: Aks Codes

The code below uses Algol 68 Genie which provides arbitrary precision arithmetic for LONGLONG modes.

BEGINCOMMENT Mathematical preliminaries.

First note that the homogeneous polynomial (a+b)^n is symmetrical(to see this just swap the variables a and b). Therefore its

coefficients need be calculated only to that of (ab)^{n/2} for even n or (ab)^{(n-1)/2} for odd n.

Second, the coefficients are the binomial coefficients C(n,k) where the coefficient of a^k b^(n-k) is C(n,k) = n! / k! (k-1)!. This leads to an immediate and relatively efficient implementation for which we do not need to compute n! before dividing by k! and (k-1)! but, rather cancel common factors as we go along. Further, the well-known symmetry identity C(n,k) = C(n, n-k) allows a significant reduction in computational effort.

Third, (x-1)^n is the value of (a + b)^n when a=x and b = -1. The powers of -1 alternate between +1 and -1 so we may as well compute

(x+1)^n and negate every other coefficient when printing.COMMENT

PR precision=300 PRMODE LLI = LONG LONG INT; CO For brevity COPROC choose = (INT n, k) LLI :BEGIN

LLI result := 1;INT sym k := (k >= n%2 | n-k | k); CO Use symmetry COIF sym k > 0 THEN

FOR i FROM 0 TO sym k-1DO result TIMESAB (n-i); result OVERAB (i+1)OD

FI; result

END;PROC coefficients = (INT n) [] LLI :BEGIN

[0:n] LLI a;FOR i FROM 0 TO n%2DO a[i] := a[n-i] := choose (n, i) CO Use symmetry CO

OD; a

END;COMMENT First print the polynomials (x-1)^n, remembering to alternate signs and to tidy up the constant term, the x^1 term and the x^n term. This means we must treat (x-1)^0 and (x-1)^1 speciallyCOMMENT

FOR n FROM 0 TO 7DO

[0:n] LLI a := coefficients (n);printf (($"(x-1)^", g(0), " = "$, n));CASE n+1 IN

printf (($g(0)l$, a[0])),printf (($"x - ", g(0)l$, a[1]))

OUTprintf (($"x^", g(0)$, n));FOR i TO n-2DO printf (($xax, g(0), "x^", g(0)$, (ODD i | "-" | "+"), a[i], n-i))OD;printf (($xax, g(0), "x"$, (ODD (n-1) | "-" | "+"), a[n-1]));printf (($xaxg(0)l$, (ODD n | "-" | "+"), a[n]))

ESACOD;COMMENT Finally, for the "AKS" portion of the task, the sign of the coefficient has no effect on its divisibility by p so, once again, we may as well use the positive coefficients. Symmetry clearly

3 of 53

Page 4: Aks Codes

reduces the necessary number of tests by a factor of two.COMMENT

PROC is prime = (INT n) BOOL :BEGIN

BOOL prime := TRUE;FOR i FROM 1 TO n%2 WHILE prime DO prime := choose (n, i) MOD n = 0 OD;

primeEND;print ("Primes < 50 are ");FOR n FROM 2 TO 50 DO (is prime (n) | printf (($g(0)x$, n)) ) OD;print (newline);print ("And just to show off, the primes between 900 and 1000 are ");FOR n FROM 900 TO 1000 DO IF is prime (n) THEN printf (($g(0)x$, n)) FI OD;print (newline)

END

Output:

(x-1)^0 = 1(x-1)^1 = x - 1(x-1)^2 = x^2 - 2x + 1(x-1)^3 = x^3 - 3x^2 + 3x - 1(x-1)^4 = x^4 - 4x^3 + 6x^2 - 4x + 1(x-1)^5 = x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1(x-1)^6 = x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1(x-1)^7 = x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1Primes < 50 are 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 And just to show off, the primes between 900 and 1000 are 907 911 919 929 937 941 947 953 967 971 977 983 991 997

AutoHotkey

Works with: AutoHotkey L

; 1. Create a function/subroutine/method that given p generates the coefficients of the expanded polynomial representation of (x-1)^p. ; Function modified from http://rosettacode.org/wiki/Pascal%27s_triangle#AutoHotkeypascalstriangle(n=8) ; n rows of Pascal's triangle{

p := Object(), z:=Object()Loop, % n

Loop, % row := A_Indexcol := A_Index, p[row, col] := row = 1 and col = 1

? 1: (p[row-1, col-1] = "" ; math operations on blanks return blanks; I want to assume zero

? 0: p[row-1, col-1])

- (p[row-1, col] = ""? 0: p[row-1, col])

Return p}

; 2. Use the function to show here the polynomial expansions of p for p in the range 0 to at least 7, inclusive.For k, v in pascalstriangle(){

s .= "`n(x-1)^" k-1 . "="For k, w in v

s .= "+" w "x^" k-1}s := RegExReplace(s, "\+-", "-")s := RegExReplace(s, "x\^0", "")s := RegExReplace(s, "x\^1", "x")Msgbox % clipboard := s

; 3. Use the previous function in creating another function that when given p returns whether p is prime using the AKS test.aks(n){

isnotprime := FalseFor k, v in pascalstriangle(n+1)[n+1]

(k != 1 and k != n+1) ? isnotprime |= !(v // n = v / n) ; if any is not divisible, returns true

4 of 53

Page 5: Aks Codes

Return !isnotprime}

; 4. Use your AKS test to generate a list of all primes under 35. i := 49p := pascalstriangle(i+1)Loop, % i{

n := A_Indexisnotprime := FalseFor k, v in p[n+1]

(k != 1 and k != n+1) ? isnotprime |= !(v // n = v / n) ; if any is not divisible, returns truet .= isnotprime ? "" : A_Index " "

}Msgbox % tReturn

Output:

(x-1)^0=+1(x-1)^1=-1+1x(x-1)^2=+1-2x+1x^2(x-1)^3=-1+3x-3x^2+1x^3(x-1)^4=+1-4x+6x^2-4x^3+1x^4(x-1)^5=-1+5x-10x^2+10x^3-5x^4+1x^5(x-1)^6=+1-6x+15x^2-20x^3+15x^4-6x^5+1x^6(x-1)^7=-1+7x-21x^2+35x^3-35x^4+21x^5-7x^6+1x^7

1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Function maxes out at i = 61 as AutoHotkey supports up to 64-bit signed integers.

Bracmat

Bracmat automatically normalizes symbolic expressions with the algebraic binary operators +, *, ^and \L (logartithm). It can differentiate such expressions using the \D binary operator. (Theseoperators were implemented in Bracmat before all other operators!). Some algebraic values canexist in two evaluated forms. The equivalent x*(a+b) and x*a+x*b are both considered "normal", butx*(a+b)+-1 is not, and therefore expanded to -1+a*x+b*x. This is used in the forceExpansion function toconvert e.g. x*(a+b) to x*a+x*b.

The primality test uses a pattern that looks for a fractional factor. If such a factor is found, thetest fails. Otherwise it succeeds.

( (forceExpansion=.1+!arg+-1)& (expandx-1P=.forceExpansion$((x+-1)^!arg))& ( isPrime = . forceExpansion $ (!arg^-1*(expandx-1P$!arg+-1*(x^!arg+-1))) : ?+/*?+? & ~` | )& out$"Polynomial representations of (x-1)^p for p <= 7 :"& -1:?n& whl ' ( 1+!n:~>7:?n & out$(str$("n=" !n ":") expandx-1P$!n) )& 1:?n& :?primes& whl ' ( 1+!n:~>50:?n & ( isPrime$!n&!primes !n:?primes |

5 of 53

Page 6: Aks Codes

) )& out$"2 <= Primes <= 50:"& out$!primes);

Output:

Polynomial representations of (x-1)^p for p <= 7 :n=0: 1n=1: -1+xn=2: 1+-2*x+x^2n=3: -1+3*x+-3*x^2+x^3n=4: 1+-4*x+6*x^2+-4*x^3+x^4n=5: -1+5*x+-10*x^2+10*x^3+-5*x^4+x^5n=6: 1+-6*x+15*x^2+-20*x^3+15*x^4+-6*x^5+x^6 n=7: -1 + 7*x + -21*x^2 + 35*x^3 + -35*x^4 + 21*x^5 + -7*x^6 + x^72 <= Primes <= 50:2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

The AKS test kan be written more concisely than the task describes. This prints the primesbetween 980 and 1000:

( out$"Primes between 980 and 1000, short version:"& 980:?n& whl ' ( !n+1:<1000:?n & ( 1+!n^-1*((x+-1)^!n+-1*(x^!n+-1))+-1:?+/*?+? | out$!n ) ));

Output:

Primes between 980 and 1000, short version:983991997

C

#include <stdio.h>#include <stdlib.h>

long long c[100];

void coef(int n){

int i, j;

if (n < 0 || n > 63) abort(); // gracefully deal with range issue

for (c[i=0] = 1; i < n; c[0] = -c[0], i++)for (c[1 + (j=i)] = 1; j > 0; j--)

c[j] = c[j-1] - c[j];}

6 of 53

Page 7: Aks Codes

int is_prime(int n){

int i;

coef(n);c[0] += 1, c[i=n] -= 1;while (i-- && !(c[i] % n));

return i < 0;}

void show(int n){

do printf("%+lldx^%d", c[n], n); while (n--);}

int main(void){

int n;

for (n = 0; n < 10; n++) {coef(n);printf("(x-1)^%d = ", n);show(n);putchar('\n');

}

printf("\nprimes (never mind the 1):");for (n = 1; n <= 63; n++)

if (is_prime(n))printf(" %d", n);

putchar('\n');return 0;

}

The ugly output:

(x-1)^0 = +1x^0(x-1)^1 = +1x^1-1x^0(x-1)^2 = +1x^2-2x^1+1x^0(x-1)^3 = +1x^3-3x^2+3x^1-1x^0(x-1)^4 = +1x^4-4x^3+6x^2-4x^1+1x^0(x-1)^5 = +1x^5-5x^4+10x^3-10x^2+5x^1-1x^0(x-1)^6 = +1x^6-6x^5+15x^4-20x^3+15x^2-6x^1+1x^0(x-1)^7 = +1x^7-7x^6+21x^5-35x^4+35x^3-21x^2+7x^1-1x^0(x-1)^8 = +1x^8-8x^7+28x^6-56x^5+70x^4-56x^3+28x^2-8x^1+1x^0(x-1)^9 = +1x^9-9x^8+36x^7-84x^6+126x^5-126x^4+84x^3-36x^2+9x^1-1x^0

primes (never mind the 1): 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61

C#

Translation of: C

using System; public class AksTest { static long[] c = new long[100];

static void Main(string[] args) { for (int n = 0; n < 10; n++) {

coef(n);Console.Write("(x-1)^" + n + " = ");show(n);Console.WriteLine("");

} Console.Write("Primes:");

7 of 53

Page 8: Aks Codes

for (int n = 1; n <= 63; n++) if (is_prime(n)) Console.Write(n + " ");

Console.WriteLine('\n'); Console.ReadLine(); }

static void coef(int n) { int i, j;

if (n < 0 || n > 63) System.Environment.Exit(0);// gracefully deal with range issue

for (c[i = 0] = 1L; i < n; c[0] = -c[0], i++) for (c[1 + (j = i)] = 1L; j > 0; j--) c[j] = c[j - 1] - c[j]; }

static bool is_prime(int n) { int i;

coef(n); c[0] += 1; c[i = n] -= 1;

while (i-- != 0 && (c[i] % n) == 0) ;

return i < 0; }

static void show(int n) {

do { Console.Write("+" + c[n] + "x^" + n);

}while (n-- != 0); }

}

Clojure

The *' function is an arbitrary precision multiplication.

(defn c "kth coefficient of (x - 1)^n"[n k](/ (apply *' (range n (- n k) -1))

(apply *' (range k 0 -1))(if (and (even? k) (< k n)) -1 1)))

(defn cs "coefficient series for (x - 1)^n, k=[0..n]"[n](map #(c n %) (range (inc n))))

(defn aks? [p] (->> (cs p) rest butlast (every? #(-> % (mod p) zero?))))

(println "coefficient series n (k[0] .. k[n])")(doseq [n (range 10)] (println n (cs n)))(println)(println "primes < 50 per AKS:" (filter aks? (range 2 50)))

Output:

coefficient series n (k[0] .. k[n])0 (1)1 (-1 1)2 (-1 2 1)

8 of 53

Page 9: Aks Codes

3 (-1 3 -3 1)4 (-1 4 -6 4 1)5 (-1 5 -10 10 -5 1)6 (-1 6 -15 20 -15 6 1)7 (-1 7 -21 35 -35 21 -7 1)8 (-1 8 -28 56 -70 56 -28 8 1)9 (-1 9 -36 84 -126 126 -84 36 -9 1)

primes < 50 per AKS: (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)

CoffeeScript

pascal = () -> a = []

return () ->if a.length is 0 then a = [1]else

b = (a[i] + a[i+1] for i in [0 ... a.length - 1]) a = [1].concat(b).concat [1]

show = (a) -> show_x = (e) ->

switch ewhen 0 then ""when 1 then "x"else "x^#{e}"

degree = a.length - 1 str = "(x - 1)^#{degree} =" sgn = 1

for i in [0...a.length] str += ' ' + (if sgn > 0 then "+" else "-") + ' ' + a[i] + show_x(degree - i) sgn = -sgn

return str

primerow = (row) -> degree = row.length - 1 row[1 ... degree].every (x) -> x % degree is 0

p = pascal()console.log show p() for i in [0..7]

p = pascal()p(); p() # skip 0 and 1

primes = (i+1 for i in [1..49] when primerow p())

console.log ""console.log "The primes upto 50 are: #{primes}"

Output:

(x - 1)^0 = + 1(x - 1)^1 = + 1x - 1(x - 1)^2 = + 1x^2 - 2x + 1(x - 1)^3 = + 1x^3 - 3x^2 + 3x - 1(x - 1)^4 = + 1x^4 - 4x^3 + 6x^2 - 4x + 1(x - 1)^5 = + 1x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1(x - 1)^6 = + 1x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1(x - 1)^7 = + 1x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1

The primes upto 50 are: 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47

Common Lisp

(defun coefficients (p)

9 of 53

Page 10: Aks Codes

(cond((= p 0) #(1))

(t (loop for i from 1 upto p for result = #(1 -1) then (map 'vector #'-

(concatenate 'vector result #(0))(concatenate 'vector #(0) result))

finally (return result)))))

(defun primep (p)(cond((< p 2) nil)

(t (let ((c (coefficients p)))(decf (elt c 0))(loop for i from 0 upto (/ (length c) 2)

for x across c never (/= (mod x p) 0))))))

(defun main ()(format t "# p: (x-1)^p for small p:~%")(loop for p from 0 upto 7

do (format t "~D: " p)(loop for i from 0

for x across (reverse (coefficients p))do (when (>= x 0) (format t "+"))

(format t "~D" x)(if (> i 0)

(format t "X^~D " i)(format t " ")))

(format t "~%"))(loop for i from 0 to 50

do (when (primep i) (format t "~D " i)))(format t "~%"))

Output:

# p: (x-1)^p for small p:0: +1 1: -1 +1X^1 2: +1 -2X^1 +1X^2 3: -1 +3X^1 -3X^2 +1X^3 4: +1 -4X^1 +6X^2 -4X^3 +1X^4 5: -1 +5X^1 -10X^2 +10X^3 -5X^4 +1X^5 6: +1 -6X^1 +15X^2 -20X^3 +15X^4 -6X^5 +1X^6 7: -1 +7X^1 -21X^2 +35X^3 -35X^4 +21X^5 -7X^6 +1X^7 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

D

Translation of: Python

import std.stdio, std.range, std.algorithm, std.string, std.bigint;

BigInt[] expandX1(in uint p) pure /*nothrow*/ {if (p == 0) return [1.BigInt];typeof(return) r = [1.BigInt, BigInt(-1)];foreach (immutable _; 1 .. p)

r = zip(r~0.BigInt, 0.BigInt~r).map!(xy => xy[0]-xy[1]).array; r.reverse();

return r;}

bool aksTest(in uint p) pure /*nothrow*/ {if (p < 2) return false;auto ex = p.expandX1;

ex[0]++;return !ex[0 .. $ - 1].any!(mult => mult % p);

}

10 of 53

Page 11: Aks Codes

void main() {"# p: (x-1)^p for small p:".writeln;foreach (immutable p; 0 .. 12)

writefln("%3d: %s", p, p.expandX1.zip(iota(p + 1)).retro .map!q{"%+dx^%d ".format(a[])}.join.replace("x^0", "") .replace("^1 ", " ").replace("+", "+ ") .replace("-", "- ").replace(" 1x", " x")[2 .. $]);

"\nSmall primes using the AKS test:".writeln;101.iota.filter!aksTest.writeln;

}

Output:

# p: (x-1)^p for small p: 0: 1 1: x - 1 2: x^2 - 2x + 1 3: x^3 - 3x^2 + 3x - 1 4: x^4 - 4x^3 + 6x^2 - 4x + 1 5: x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1 6: x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1 7: x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1 8: x^8 - 8x^7 + 28x^6 - 56x^5 + 70x^4 - 56x^3 + 28x^2 - 8x + 1 9: x^9 - 9x^8 + 36x^7 - 84x^6 + 126x^5 - 126x^4 + 84x^3 - 36x^2 + 9x - 1 10: x^10 - 10x^9 + 45x^8 - 120x^7 + 210x^6 - 252x^5 + 210x^4 - 120x^3 + 45x^2 - 10x + 1 11: x^11 - 11x^10 + 55x^9 - 165x^8 + 330x^7 - 462x^6 + 462x^5 - 330x^4 + 165x^3 - 55x^2 + 11x - 1

Small primes using the AKS test:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

EchoLisp

We use the math.lib library and the poly functions to compute and display the requiredpolynomials. A polynomial P(x) = a0 +a1*x + .. an*x^n is a list of coefficients (a0 a1 .... an).

(lib 'math.lib);; 1 - x^p : P = (1 0 0 0 ... 0 -1)(define (mono p) (append (list 1) (make-list (1- p) 0) (list -1)))

;; compute (x-1)^p , p >= 1(define (aks-poly p)

(poly-pow (list -1 1) p))

;; (define (show-them n)

(for ((p (in-range 1 n)))(writeln 'p p (poly->string 'x (aks-poly p)))))

;; aks-test;; P = (x-1)^p + 1 - x^p(define (aks-test p)

(let ((P (poly-add (mono p) (aks-poly p))) (test (lambda(a) (zero? (modulo a p))))) ;; p divides a[i] ? (apply and (map test P)))) ;; returns #t if true for all a[i]

Output:

(show-them 13) →p 1 x -1p 2 x^2 -2x +1p 3 x^3 -3x^2 +3x -1p 4 x^4 -4x^3 +6x^2 -4x +1p 5 x^5 -5x^4 +10x^3 -10x^2 +5x -1

11 of 53

Page 12: Aks Codes

p 6 x^6 -6x^5 +15x^4 -20x^3 +15x^2 -6x +1p 7 x^7 -7x^6 +21x^5 -35x^4 +35x^3 -21x^2 +7x -1p 8 x^8 -8x^7 +28x^6 -56x^5 +70x^4 -56x^3 +28x^2 -8x +1p 9 x^9 -9x^8 +36x^7 -84x^6 +126x^5 -126x^4 +84x^3 -36x^2 +9x -1p 10 x^10 -10x^9 +45x^8 -120x^7 +210x^6 -252x^5 +210x^4 -120x^3 +45x^2 -10x +1p 11 x^11 -11x^10 +55x^9 -165x^8 +330x^7 -462x^6 +462x^5 -330x^4 +165x^3 -55x^2 +11x -1p 12 x^12 -12x^11 +66x^10 -220x^9 +495x^8 -792x^7 +924x^6 -792x^5 +495x^4 -220x^3 +66x^2 -12x +1

(lib 'bigint)Lib: bigint.lib loaded.

(for ((p (in-range 2 100)))(when (aks-test p) (write p))) →

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Erlang

Translation of: CoffeeScript

The Erlang io module can print out lists of characters with any level of nesting as a flat string.(e.g. ["Er", ["la", ["n"]], "g"] prints as "Erlang") which is useful when constructing the strings toprint out for the binomial expansions. The program also shows how lazy lists can be implementedin Erlang.

#! /usr/bin/escript

-import(lists, [all/2, seq/2, zip/2]).

iterate(F, X) -> fun() -> [X | iterate(F, F(X))] end.

take(0, _lazy) -> [];take(N, Lazy) ->

[Value | Next] = Lazy(),[Value | take(N-1, Next)].

pascal() -> iterate(fun (Row) -> [1 | sum_adj(Row)] end, [1]).

sum_adj([_] = L) -> L;sum_adj([A, B | _] = Row) -> [A+B | sum_adj(tl(Row))].

show_binomial(Row) ->Degree = length(Row) - 1,["(x - 1)^", integer_to_list(Degree), " =", binomial_rhs(Row, 1, Degree)].

show_x(0) -> "";show_x(1) -> "x";show_x(N) -> [$x, $^ | integer_to_list(N)].

binomial_rhs([], _, _) -> [];binomial_rhs([Coef | Coefs], Sgn, Exp) ->

SignChar = if Sgn > 0 -> $+; true -> $- end,[$ , SignChar, $ , integer_to_list(Coef), show_x(Exp) | binomial_rhs(Coefs, -Sgn, Exp-1)].

primerow(Row, N) -> all(fun (Coef) -> (Coef =:= 1) or (Coef rem N =:= 0) end, Row).

main(_) ->[io:format("~s~n", [show_binomial(Row)]) || Row <- take(8, pascal())],io:format("~nThe primes upto 50: ~p~n",

[[N || {Row, N} <- zip(tl(tl(take(51, pascal()))), seq(2, 50)),primerow(Row, N)]]).

Output:

12 of 53

Page 13: Aks Codes

(x - 1)^0 = + 1(x - 1)^1 = + 1x - 1(x - 1)^2 = + 1x^2 - 2x + 1(x - 1)^3 = + 1x^3 - 3x^2 + 3x - 1(x - 1)^4 = + 1x^4 - 4x^3 + 6x^2 - 4x + 1(x - 1)^5 = + 1x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1(x - 1)^6 = + 1x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1(x - 1)^7 = + 1x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1

The primes upto 50: [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]

Fortran

program aksimplicit none

! Coefficients of polynomial expansioninteger(kind=16), dimension(:), allocatable :: coeffsinteger(kind=16) :: n! Character variable for I/Ocharacter(len=40) :: tmp

! Point #2do n = 0, 7

write(tmp, *) ncall polynomial_expansion(n, coeffs)

write(*, fmt='(A)', advance='no') '(x - 1)^'//trim(adjustl(tmp))//' ='call print_polynom(coeffs)

end do

! Point #4do n = 2, 35if (is_prime(n)) write(*, '(I4)', advance='no') n

end do write(*, *)

! Point #5do n = 2, 124if (is_prime(n)) write(*, '(I4)', advance='no') n

end do write(*, *)

if (allocated(coeffs)) deallocate(coeffs)contains! Calculate coefficients of (x - 1)^n using binomial theoremsubroutine polynomial_expansion(n, coeffs)integer(kind=16), intent(in) :: ninteger(kind=16), dimension(:), allocatable, intent(out) :: coeffsinteger(kind=16) :: i, j

if (allocated(coeffs)) deallocate(coeffs)

allocate(coeffs(n + 1))

do i = 1, n + 1 coeffs(i) = binomial(n, i - 1)*(-1)**(n - i - 1)

end doend subroutine

! Calculate binomial coefficient using recurrent relation, as calculation! using factorial overflows too quickly.function binomial(n, k) result (res)integer(kind=16), intent(in) :: n, kinteger(kind=16) :: resinteger(kind=16) :: i

if (k == 0) then res = 1

returnend if

13 of 53

Page 14: Aks Codes

res = 1do i = 0, k - 1

res = res*(n - i)/(i + 1)end do

end function

! Outputs polynomial with given coefficientssubroutine print_polynom(coeffs)integer(kind=16), dimension(:), allocatable, intent(in) :: coeffsinteger(kind=4) :: i, pcharacter(len=40) :: cbuf, pbuflogical(kind=1) :: non_zero

if (.not. allocated(coeffs)) return

non_zero = .false.

do i = 1, size(coeffs)if (coeffs(i) .eq. 0) cycle

p = i - 1 write(cbuf, '(I40)') abs(coeffs(i)) write(pbuf, '(I40)') p

if (non_zero) thenif (coeffs(i) .gt. 0) then

write(*, fmt='(A)', advance='no') ' + 'else

write(*, fmt='(A)', advance='no') ' - 'endif

elseif (coeffs(i) .gt. 0) then

write(*, fmt='(A)', advance='no') ' 'else

write(*, fmt='(A)', advance='no') ' - 'endif

endif

if (p .eq. 0) then write(*, fmt='(A)', advance='no') trim(adjustl(cbuf))

elseif (p .eq. 1) thenif (coeffs(i) .eq. 1) then

write(*, fmt='(A)', advance='no') 'x'else

write(*, fmt='(A)', advance='no') trim(adjustl(cbuf))//'x'end if

elseif (coeffs(i) .eq. 1) then

write(*, fmt='(A)', advance='no') 'x^'//trim(adjustl(pbuf))else

write(*, fmt='(A)', advance='no') &trim(adjustl(cbuf))//'x^'//trim(adjustl(pbuf))

end ifend if

non_zero = .true.end do

write(*, *)end subroutine

! Test if n is prime using AKS test. Point #3.function is_prime(n) result (res)integer(kind=16), intent (in) :: nlogical(kind=1) :: resinteger(kind=16), dimension(:), allocatable :: coeffsinteger(kind=16) :: i

call polynomial_expansion(n, coeffs) coeffs(1) = coeffs(1) + 1 coeffs(n + 1) = coeffs(n + 1) - 1

res = .true.

do i = 1, n + 1 res = res .and. (mod(coeffs(i), n) == 0)

end do

14 of 53

Page 15: Aks Codes

if (allocated(coeffs)) deallocate(coeffs)end function

end program aks

Output:

(x - 1)^0 = 1(x - 1)^1 = - 1 + x(x - 1)^2 = 1 - 2x + x^2(x - 1)^3 = - 1 + 3x - 3x^2 + x^3(x - 1)^4 = 1 - 4x + 6x^2 - 4x^3 + x^4(x - 1)^5 = - 1 + 5x - 10x^2 + 10x^3 - 5x^4 + x^5(x - 1)^6 = 1 - 6x + 15x^2 - 20x^3 + 15x^4 - 6x^5 + x^6(x - 1)^7 = - 1 + 7x - 21x^2 + 35x^3 - 35x^4 + 21x^5 - 7x^6 + x^7 2 3 5 7 11 13 17 19 23 29 31 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113

Go

package main

import "fmt"

func bc(p int) []int64 { c := make([]int64, p+1) r := int64(1)

for i, half := 0, p/2; i <= half; i++ { c[i] = r c[p-i] = r r = r * int64(p-i) / int64(i+1)

}for i := p - 1; i >= 0; i -= 2 {

c[i] = -c[i]}return c

}

func main() {for p := 0; p <= 7; p++ {

fmt.Printf("%d: %s\n", p, pp(bc(p)))}for p := 2; p < 50; p++ {

if aks(p) { fmt.Print(p, " ")

}}

fmt.Println()}

var e = []rune("²³⁴⁵⁶⁷")

func pp(c []int64) (s string) {if len(c) == 1 {

return fmt.Sprint(c[0])}

p := len(c) - 1if c[p] != 1 {

s = fmt.Sprint(c[p])}for i := p; i > 0; i-- {

s += "x"if i != 1 {

s += string(e[i-2])}if d := c[i-1]; d < 0 {

s += fmt.Sprintf(" - %d", -d)} else {

15 of 53

Page 16: Aks Codes

s += fmt.Sprintf(" + %d", d)}

}return

}

func aks(p int) bool { c := bc(p) c[p]-- c[0]++

for _, d := range c {if d%int64(p) != 0 {

return false}

}return true

}

Output:

0: 11: x - 12: x² - 2x + 13: x³ - 3x² + 3x - 14: x⁴ - 4x³ + 6x² - 4x + 15: x⁵ - 5x⁴ + 10x³ - 10x² + 5x - 16: x⁶ - 6x⁵ + 15x⁴ - 20x³ + 15x² - 6x + 17: x⁷ - 7x⁶ + 21x⁵ - 35x⁴ + 35x³ - 21x² + 7x - 12 3 5 7 11 13 17 19 23 29 31 37 41 43 47

FreeBASIC

'METHOD -- Use the Pascal triangle to retrieve the coefficients'UPPER LIMIT OF FREEBASIC ULONGINT GETS PRIMES UP TO 70Sub string_split(s_in As String,char As String,result() As String)

Dim As String s=s_in,var1,var2Dim As Integer n,pst#macro split(stri,char,var1,var2)

pst=Instr(stri,char) var1="":var2=""

If pst<>0 Then var1=Mid(stri,1,pst-1) var2=Mid(stri,pst+1)

Else var1=stri

End IfRedim Preserve result(1 To 1+n-((Len(var1)>0)+(Len(var2)>0)))

result(n+1)=var1#endmacroDo

split(s,char,var1,var2):n=n+1:s=var2Loop Until var2=""Redim Preserve result(1 To Ubound(result)-1)

End Sub

'Get Pascal triangle componentsFunction pasc(n As Integer,flag As Integer=0) As String n+=1

Dim As Ulongint V(n):V(1)=1ulDim As String s,signFor r As Integer= 2 To n

s=""For i As Integer = r To 1 Step -1

V(i) += V(i-1)If i Mod 2=1 Then sign="" Else sign="-"

s+=sign+Str(V(i))+","Next i

Next rIf flag Then 'formatted output

Dim As String i,i2,i3,gRedim As String a(0)

16 of 53

Page 17: Aks Codes

string_split(s,",",a())For n1 As Integer=1 To Ubound(a)

If Left(a(n1),1)="-" Then sign="" Else sign="+"If n1=Ubound(a) Then i2="" Else i2=a(n1)If n1=2 Then i3="x" Else i3="x^"+Str(n1-1)If n1=1 Then i="":sign=" " Else i=i3

g+=sign+i2+i+" "Next n1

g="(x-1)^"+Str(n-1)+" = "+gReturn g

End IfReturn s

End Function

Function isprime(num As Integer) As IntegerRedim As String a(0)

string_split(pasc(num),",",a())For n As Integer=Lbound(a)+1 To Ubound(a)-1

If (Valulng(Ltrim(a(n),"-"))) Mod num<>0 Then Return 0Next nReturn -1

End Function'==================================== 'Formatted outputFor n As Integer=1 To 9

Print pasc(n,1)Next n

Print'Limit of Freebasic Ulongint sets about 70 maxPrint "Primes up to 70:"For n As Integer=2 To 70

If isprime(n) Then Print n;Next n

Sleep

Output:

(x-1)^1 = -1 +x(x-1)^2 = 1 -2x +x^2(x-1)^3 = -1 +3x -3x^2 +x^3(x-1)^4 = 1 -4x +6x^2 -4x^3 +x^4(x-1)^5 = -1 +5x -10x^2 +10x^3 -5x^4 +x^5(x-1)^6 = 1 -6x +15x^2 -20x^3 +15x^4 -6x^5 +x^6(x-1)^7 = -1 +7x -21x^2 +35x^3 -35x^4 +21x^5 -7x^6 +x^7(x-1)^8 = 1 -8x +28x^2 -56x^3 +70x^4 -56x^5 +28x^6 -8x^7 +x^8(x-1)^9 = -1 +9x -36x^2 +84x^3 -126x^4 +126x^5 -84x^6 +36x^7 -9x^8 +x^9

Primes up to 70: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67

Haskell

expand p = scanl (\z i -> z * (p-i+1) `div` i) 1 [1..p]

test p | p < 2 = False| otherwise = and [mod n p == 0 | n <- init . tail $ expand p]

printPoly [1] = "1"printPoly p = concat [ unwords [pow i, sgn (l-i), show (p!!(i-1))]

| i <- [l-1,l-2..1] ] where l = length p sgn i = if even i then "+" else "-" pow i = take i "x^" ++ if i > 1 then show i else ""

main = doputStrLn "-- p: (x-1)^p for small p"

17 of 53

Page 18: Aks Codes

putStrLn $ unlines [show i ++ ": " ++ printPoly (expand i) | i <- [0..10]]putStrLn "-- Primes up to 100:"print (filter test [1..100])

Output:

-- p: (x-1)^p for small p0: 11: x - 12: x^2 - 2x + 13: x^3 - 3x^2 + 3x - 14: x^4 - 4x^3 + 6x^2 - 4x + 15: x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 16: x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 17: x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 18: x^8 - 8x^7 + 28x^6 - 56x^5 + 70x^4 - 56x^3 + 28x^2 - 8x + 19: x^9 - 9x^8 + 36x^7 - 84x^6 + 126x^5 - 126x^4 + 84x^3 - 36x^2 + 9x - 110: x^10 - 10x^9 + 45x^8 - 120x^7 + 210x^6 - 252x^5 + 210x^4 - 120x^3 + 45x^2 - 10x + 1

-- Primes up to 100:[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

J

Solution:

binomialExpansion =: (!~ * _1 ^ 2 | ]) i.&.:<: NB. 1) Create a function that gives the coefficients of (x-1)^p. testAKS =: 0 *./ .= ] | binomialExpansion NB. 3) Use that function to create another which determines whether p is prime usin

Examples:

binomialExpansion&.> i. 8 NB. 2) show the polynomial expansions p in the range 0 to at 7 inclusive.+-++--+----+-------+-----------+---------------+------------------+|0||_2|_3 3|_4 6 _4|_5 10 _10 5|_6 15 _20 15 _6|_7 21 _35 35 _21 7|+-++--+----+-------+-----------+---------------+------------------+

(#~ testAKS&> ) 2+i. 35 NB. 4) Generate a list of all primes under 35.2 3 5 7 11 13 17 19 23 29 31

(#~ testAKS&> ) 2+i. 50 NB. 5) [stretch] Generate all primes under 502 3 5 7 11 13 17 19 23 29 31 37 41 43 47 i.&.:(_1&p:) 50 NB. Double-check our results using built-in prime filter.2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Java

Translation of: CSolution:

public class AksTest {

static Long[] c = new Long[100];

public static void main(String[] args){

for (int n = 0; n < 10; n++) {coef(n);System.out.print("(x-1)^" + n + " = ");show(n);System.out.println("");

}

System.out.print("Primes:");for (int n = 1; n <= 63; n++)

18 of 53

Page 19: Aks Codes

if (is_prime(n))System.out.printf(" %d", n);

System.out.println('\n');}

static void coef(int n){

int i, j;

if (n < 0 || n > 63) System.exit(0); // gracefully deal with range issue

for (c[i=0] = 1l; i < n; c[0] = -c[0], i++)for (c[1 + (j=i)] = 1l; j > 0; j--)

c[j] = c[j-1] - c[j];}

static boolean is_prime(int n){

int i;

coef(n);c[0] += 1;c[i=n] -= 1;

while (i-- != 0 && (c[i] % n) == 0);

return i < 0;}

static void show(int n){

do {System.out.print("+" + c[n] + "x^"+ n);

}while (n-- != 0);}

}

Output:

(x-1)^0 = +1x^0(x-1)^1 = +1x^1+-1x^0(x-1)^2 = +1x^2+-2x^1+1x^0(x-1)^3 = +1x^3+-3x^2+3x^1+-1x^0(x-1)^4 = +1x^4+-4x^3+6x^2+-4x^1+1x^0(x-1)^5 = +1x^5+-5x^4+10x^3+-10x^2+5x^1+-1x^0(x-1)^6 = +1x^6+-6x^5+15x^4+-20x^3+15x^2+-6x^1+1x^0(x-1)^7 = +1x^7+-7x^6+21x^5+-35x^4+35x^3+-21x^2+7x^1+-1x^0(x-1)^8 = +1x^8+-8x^7+28x^6+-56x^5+70x^4+-56x^3+28x^2+-8x^1+1x^0(x-1)^9 = +1x^9+-9x^8+36x^7+-84x^6+126x^5+-126x^4+84x^3+-36x^2+9x^1+-1x^0Primes: 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61

JavaScript

Translation of: CoffeeScript

var i, p, pascal, primerow, primes, show, _i;

pascal = function() {var a;

a = [];return function() {var b, i;if (a.length === 0) {return a = [1];

} else { b = (function() {

var _i, _ref, _results; _results = [];

for (i = _i = 0, _ref = a.length - 1; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {

19 of 53

Page 20: Aks Codes

_results.push(a[i] + a[i + 1]);}return _results;

})();return a = [1].concat(b).concat([1]);

}};

};

show = function(a) {var degree, i, sgn, show_x, str, _i, _ref;

show_x = function(e) {switch (e) {case 0:return "";

case 1:return "x";

default:return "x^" + e;

}};

degree = a.length - 1; str = "(x - 1)^" + degree + " ="; sgn = 1;for (i = _i = 0, _ref = a.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {

str += ' ' + (sgn > 0 ? "+" : "-") + ' ' + a[i] + show_x(degree - i); sgn = -sgn;}return str;

};

primerow = function(row) {var degree;

degree = row.length - 1;return row.slice(1, degree).every(function(x) {return x % degree === 0;

});};

p = pascal();

for (i = _i = 0; _i <= 7; i = ++_i) { console.log(show(p()));}

p = pascal();

p();

p();

primes = (function() {var _j, _results;

_results = [];for (i = _j = 1; _j <= 49; i = ++_j) {if (primerow(p())) {

_results.push(i + 1);}

}return _results;

})();

console.log("");

console.log("The primes upto 50 are: " + primes);

Output:

(x - 1)^0 = + 1(x - 1)^1 = + 1x - 1(x - 1)^2 = + 1x^2 - 2x + 1(x - 1)^3 = + 1x^3 - 3x^2 + 3x - 1(x - 1)^4 = + 1x^4 - 4x^3 + 6x^2 - 4x + 1(x - 1)^5 = + 1x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1(x - 1)^6 = + 1x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1

20 of 53

Page 21: Aks Codes

(x - 1)^7 = + 1x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1

The primes upto 50 are: 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47

Reviewed (ES6):

function pascal(n) {var cs = []; if (n) while (n--) coef(); return coeffunction coef() {

if (cs.length === 0) return cs = [1];for (var t=[1,1], i=cs.length-1; i; i-=1) t.splice( 1, 0, cs[i-1]+cs[i] ); return cs = t

}}

function show(cs) {for (var s='', sgn=true, i=0, deg=cs.length-1; i<=deg; sgn=!sgn, i+=1) {

s += ' ' + (sgn ? '+' : '-') + cs[i] + (e => e==0 ? '' : e==1 ? 'x' : 'x<sup>' + e + '</sup>')(deg-i)}return '(x-1)<sup>' + deg + '</sup> =' + s;

}

function isPrime(cs) {var deg=cs.length-1; return cs.slice(1, deg).every( function(c) { return c % deg === 0 } )

}

var coef=pascal(); for (var i=0; i<=7; i+=1) document.write(show(coef()), '<br>')

document.write('<br>Primes: ');for (var coef=pascal(2), n=2; n<=50; n+=1) if (isPrime(coef())) document.write(' ', n)

Output:

(x-1)0 = +1

(x-1)1 = +1x -1

(x-1)2 = +1x2 -2x +1

(x-1)3 = +1x3 -3x2 +3x -1

(x-1)4 = +1x4 -4x3 +6x2 -4x +1

(x-1)5 = +1x5 -5x4 +10x3 -10x2 +5x -1

(x-1)6 = +1x6 -6x5 +15x4 -20x3 +15x2 -6x +1

(x-1)7 = +1x7 -7x6 +21x5 -35x4 +35x3 -21x2 +7x -1

Primes: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47

Translation of: C

function coef(n) {for (var c=[1], i=0; i<n; c[0]=-c[0], i+=1) {

c[i+1]=1; for (var j=i; j; j-=1) c[j] = c[j-1]-c[j]}return c

}

function show(cs) {var s='', n=cs.length-1do s += (cs[n]>0 ? ' +' : ' ') + cs[n] + (n==0 ? '' : n==1 ? 'x' :'x<sup>'+n+'</sup>'); while (n--)return s

}

function isPrime(n) {var cs=coef(n), i=n-1; while (i-- && cs[i]%n == 0);return i < 1

}

for (var n=0; n<=7; n++) document.write('(x-1)<sup>',n,'</sup> = ', show(coef(n)), '<br>')

document.write('<br>Primes: ');for (var n=2; n<=50; n++) if (isPrime(n)) document.write(' ', n)

21 of 53

Page 22: Aks Codes

Output:

(x-1)0 = +1

(x-1)1 = +1x -1

(x-1)2 = +1x2 -2x +1

(x-1)3 = +1x3 -3x2 +3x -1

(x-1)4 = +1x4 -4x3 +6x2 -4x +1

(x-1)5 = +1x5 -5x4 +10x3 -10x2 +5x -1

(x-1)6 = +1x6 -6x5 +15x4 -20x3 +15x2 -6x +1

(x-1)7 = +1x7 -7x6 +21x5 -35x4 +35x3 -21x2 +7x -1

Primes: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47

jq

Works with: jq version 1.5rc1

In the #Prolog section of this page, it is shown how the symmetry of rows in a Pascal triangle canbe used to yield a more efficient test of primality than is apparently envisioned by the problemstatement. The key concept is the "OptPascal row", which is just the longest non-decreasingsequence of the corresponding Pascal row. In this article, the focus will therefore be on OptPascalrows.

NOTE: jq uses IEEE 754 64-bit numbers and thus if builtin arithmetic is used, is_prime will onlybe accurate up to 96 by this method because of loss of precision. The program below, however,can easily be adapted to use a BigInt library such as the one at https://github.com/joelpurra/jq-bigint

# add_pairs is a helper function for optpascal/0# Input: an OptPascal array# Output: the next OptPascal array (obtained by adding adjacent items, # but if the last two items are unequal, then their sum is repeated)def add_pairs: if length <= 1 then . elif length == 2 then (.[0] + .[1]) as $S | if (.[0] == .[1]) then [$S] else [$S,$S] end else [.[0] + .[1]] + (.[1:]|add_pairs) end;

# Input: an OptPascal row# Output: the next OptPascalRowdef next_optpascal: [1] + add_pairs;

# generate a stream of OptPascal arrays, beginning with []def optpascals: [] | recurse(next_optpascal);

# generate a stream of Pascal arraysdef pascals: # pascalize takes as input an OptPascal array and produces # the corresponding Pascal array; # if the input ends in a pair, then peel it off before reversing it. def pascalize: . + ((if .[-2] == .[-1] then .[0:-2] else .[0:-1] end) | reverse);

optpascals | pascalize;

# Input: integer n# Output: the n-th Pascal rowdef pascal: nth(.; pascals);

def optpascal: nth(.; optpascals);

22 of 53

Page 23: Aks Codes

Task 1: "A method to generate the coefficients of (x-1)^p"

def coefficients: def alternate_signs: . as $in | reduce range(0; length) as $i ([]; . + [$in[$i] * (if $i % 2 == 0 then 1 else -1 end )]); (.+1) | pascal | alternate_signs;

Task 2: "Show here the polynomial expansions of (x − 1)^p for p in the range 0 to at least 7,inclusive."

range(0;8) | "Coefficient for (x - 1)^\(.): \(coefficients)"

Output:

Coefficients for (x - 1)^0: [1]Coefficients for (x - 1)^1: [1,-1]Coefficients for (x - 1)^2: [1,-2,1]Coefficients for (x - 1)^3: [1,-3,3,-1]Coefficients for (x - 1)^4: [1,-4,6,-4,1]Coefficients for (x - 1)^5: [1,-5,10,-10,5,-1]Coefficients for (x - 1)^6: [1,-6,15,-20,15,-6,1]Coefficients for (x - 1)^7: [1,-7,21,-35,35,-21,7,-1]

Task 3: Prime Number Test

For brevity, we show here only the relatively efficient solution based on optpascal/0:

def is_prime: . as $N | if . < 2 then false else (1+.) | optpascal | all( .[2:][]; . % $N == 0 ) end;

Task 4: "Use your AKS test to generate a list of all primes under 35."

range(0;36) | select(is_prime)

Output:

235711131719232931

Task 5: "As a stretch goal, generate all primes under 50."

[range(0;50) | select(is_prime)]

Output:

23 of 53

Page 24: Aks Codes

[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]

Julia

Task 1

function polycoefs(n::Int64) pc = typeof(n)[] if n < 0 return pc end sgn = one(n) for k in n:-1:0 push!(pc, sgn*binomial(n, k)) sgn = -sgn end return pcend

Perhaps this should be done with a comprehension, but properly accounting for the sign is trickyin that case.

Task 2

function stringpoly(n::Int64) if n < 0 return "" end st = @sprintf "(x - 1)^{%d} & = & " n for (i, c) in enumerate(polycoefs(n)) if i == 1 op = "" ac = c elseif c < 0 op = "-" ac = abs(c) else op = "+" ac = abs(c) end p = n + 1 - i if p == 0 st *= @sprintf " %s %d\\\\" op ac elseif ac == 1 st *= @sprintf " %s x^{%d}" op p else st *= @sprintf " %s %dx^{%d}" op ac p end end return stend

Of course this could be simpler, but this produces a nice payoff in typeset equations that do oninclude extraneous characters (leading pluses and coefficients of 1).

Task 3

function isaksprime(n::Int64) if n < 2

24 of 53

Page 25: Aks Codes

return false end for c in polycoefs(n)[2:(end-1)] if c%n != 0 return false end end return trueend

Task 4

println("<math>")println("\\begin{array}{lcl}")for i in 0:10 println(stringpoly(i))endprintln("\\end{array}")println("</math>\n")

L = 50print("AKS primes less than ", L, ": ")sep = ""for i in 1:L if isaksprime(i) print(sep, i) sep = ", " endendprintln()

Output:

AKS primes less than 50: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47

Maple

Maple handles algebraic manipulation of polynomials natively.

> for xpr in seq( expand( (x-1)^p ), p = 0 .. 7 ) do print( xpr ) end: 1

x - 1

2

25 of 53

Page 26: Aks Codes

x - 2 x + 1

3 2 x - 3 x + 3 x - 1

4 3 2 x - 4 x + 6 x - 4 x + 1

5 4 3 2 x - 5 x + 10 x - 10 x + 5 x - 1

6 5 4 3 2 x - 6 x + 15 x - 20 x + 15 x - 6 x + 1

7 6 5 4 3 2 x - 7 x + 21 x - 35 x + 35 x - 21 x + 7 x - 1

To implement the primality test, we write the following procedure that uses the (built-in)polynomial expansion to generate a list of coefficients of the expanded polynomial.

polc := p -> [coeffs]( expand( (x-1)^p - (x^p-1) ) ):

Use polc to implement prime? which does the primality test.

prime? := n -> n > 1 and {op}( map( modp, polc( n ), n ) ) = {0}

Of course, rather than calling polc, we can inline it, just for the sake of making the whole thing aone-liner (while adding argument type-checking for good measure):

prime? := (n::posint) -> n > 1 and {op}( map( modp, [coeffs]( expand( (x-1)^n - (x^n-1) ) ), n ) ) = {0}

This agrees with the built-in primality test isprime:

> evalb( seq( prime?(i), i = 1 .. 1000 ) = seq( isprime( i ), i = 1 .. 1000 ) ); true

Use prime? with the built-in Maple select procedure to pick off the primes up to 50:

> select( prime?, [seq](1..50) ); [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Mathematica / Wolfram Language

Algebraic manipulation is built into Mathematica, so there's no need to create a function to do(x-1)^p

Print["powers of (x-1)"](x - 1)^( Range[0, 7]) // Expand // TableForm Print["primes under 50"]poly[p_] := (x - 1)^p - (x^p - 1) // Expand;coefflist[p_Integer] := Coefficient[poly[p], x, #] & /@ Range[0, p - 1];AKSPrimeQ[p_Integer] := (Mod[coefflist[p] , p] // Union) == {0};

26 of 53

Page 27: Aks Codes

Select[Range[1, 50], AKSPrimeQ]

Output:

powers of (x-1)1-1+x1-2 x+x^2-1+3 x-3 x^2+x^31-4 x+6 x^2-4 x^3+x^4-1+5 x-10 x^2+10 x^3-5 x^4+x^51-6 x+15 x^2-20 x^3+15 x^4-6 x^5+x^6-1+7 x-21 x^2+35 x^3-35 x^4+21 x^5-7 x^6+x^7

primes under 50{1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47}

Oforth

func: nextCoef(prev) { | i | ListBuffer new dup add(0) prev size 1 - loop: i [ dup add(prev at(i) prev at(i 1 +) - ) ] dup add(0)}func: coefs(n) { [ 0, 1, 0 ] #nextCoef times(n) extract(2, n 2 + ) }func: isPrime(n) { coefs(n) extract(2, n) conform(#[n mod 0 == ]) }

func: aks{| i | 0 10 for: i [ System.Out "(x-1)^" << i << " = " << coefs(i) << cr ] 50 seq filter(#isPrime) apply(#[ print " " print ]) printcr}

Output:

(x-1)^0 = [1](x-1)^1 = [-1, 1](x-1)^2 = [1, -2, 1](x-1)^3 = [-1, 3, -3, 1](x-1)^4 = [1, -4, 6, -4, 1](x-1)^5 = [-1, 5, -10, 10, -5, 1](x-1)^6 = [1, -6, 15, -20, 15, -6, 1](x-1)^7 = [-1, 7, -21, 35, -35, 21, -7, 1](x-1)^8 = [1, -8, 28, -56, 70, -56, 28, -8, 1](x-1)^9 = [-1, 9, -36, 84, -126, 126, -84, 36, -9, 1](x-1)^10 = [1, -10, 45, -120, 210, -252, 210, -120, 45, -10, 1]2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

PARI/GP

getPoly(n)=('x-1)^n;vector(8,n,getPoly(n-1))AKS_slow(n)=my(P=getPoly(n));for(i=1,n-1,if(polcoeff(P,i)%n,return(0))); 1;AKS(n)=my(X=('x-1)*Mod(1,n));X^n=='x^n-1;select(AKS, [1..50])

Output:

[1, x - 1, x^2 - 2*x + 1, x^3 - 3*x^2 + 3*x - 1, x^4 - 4*x^3 + 6*x^2 - 4*x + 1, x^5 - 5*x^4 + 10*x^3 - 10*x^2 + 5*x - 1, x^6 - 6*x^5 + 15*x^4

27 of 53

Page 28: Aks Codes

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Pascal

tested wth freepascal

const pasTriMax = 61;type tpasTri =array[0..pasTriMax] of UInt64;

var pasTri : tpasTri;

procedure pastriangle(n:longInt);//calculate the n'th line 0.. middlevar j,k: longWord;begin pasTri[0] := 1; j := 1;while (j<=n) dobegin

inc(j); k := j SHR 1; pasTri[k] :=pasTri[k-1];

For k := k downto 1 do inc(pasTri[k],pasTri[k-1]);end;

end;

function CheckPrime(n:longWord):boolean;var i : integer; res: boolean;Begin

IF n > pasTriMax thenbeginwriteln(n,' is out of range ');

EXIT;end;

pastriangle(n); res := true; i := n shr 1;while res AND (i >1) doBegin

res := res AND(pasTri[i] mod n = 0); dec(i);end;

CheckPrime := res;end;

procedure ExpandPoly(n:longWord);const Vz :array[boolean] of char = ('+','-');var j,k: longWord; bVz: Boolean;BeginIF n < 2 thenBeginIF n = 0 thenwriteln('(x-1)^0 = 1')

elsewriteln('(x-1)^1 = x-1');

EXIT;end;

IF n > pasTriMax thenbegin

28 of 53

Page 29: Aks Codes

writeln(n,' is out of range '); EXIT;end;

pastriangle(n);write('(x-1)^',n,' = ');

k := 0; j := n; bVz := false;repeatIF j=n thenwrite('x^',j)

elsewrite(Vz[bVz],pasTri[k],'*x^',j);

bVz := Not(bVz); inc(k); dec(j);until k>= j;

k := j;while k > 0 doBeginIF j <> 1 thenwrite(Vz[bVz],pasTri[k],'*x^',j)

elsewrite(Vz[bVz],pasTri[k],'*x');

bVz := Not(bVz); dec(k); dec(j);end;write(Vz[bVz],pasTri[0]);writeln;

end;

var n: LongWord;BeginFor n := 0 to 9 do

ExpandPoly(n);For n := 2 to pasTriMax doIF CheckPrime(n) thenwrite(n:3);

end.

output

(x-1)^0 = 1

(x-1)^1 = x-1

(x-1)^2 = x^2-2*x+1

(x-1)^3 = x^3-3*x^2+3*x-1

(x-1)^4 = x^4-4*x^3+6*x^2-4*x+1

(x-1)^5 = x^5-5*x^4+10*x^3-10*x^2+5*x-1

(x-1)^6 = x^6-6*x^5+15*x^4-20*x^3+15*x^2-6*x+1

(x-1)^7 = x^7-7*x^6+21*x^5-35*x^4+35*x^3-21*x^2+7*x-1

(x-1)^8 = x^8-8*x^7+28*x^6-56*x^5+70*x^4-56*x^3+28*x^2-8*x+1

(x-1)^9 = x^9-9*x^8+36*x^7-84*x^6+126*x^5-126*x^4+84*x^3-36*x^2+9*x-1

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61

Perl

use strict;

29 of 53

Page 30: Aks Codes

use warnings;# Select one of these lines. Math::BigInt is in core, but quite slow.use Math::BigInt; sub binomial { Math::BigInt->new(shift)->bnok(shift) }# use Math::Pari "binomial";# use ntheory "binomial";

sub binprime {my $p = shift;return 0 unless $p >= 2;# binomial is symmetric, so only test half the termsfor (1 .. ($p>>1)) { return 0 if binomial($p,$_) % $p }1;

}sub coef { # For prettier printingmy($n,$e) = @_;return $n unless $e;$n = "" if $n==1;$e==1 ? "${n}x" : "${n}x^$e";

}sub binpoly {my $p = shift;join(" ", coef(1,$p),

map { join("",("+","-")[($p-$_)&1]," ",coef(binomial($p,$_),$_)) }reverse 0..$p-1 );

}print "expansions of (x-1)^p:\n";print binpoly($_),"\n" for 0..9;print "Primes to 80: [", join(",", grep { binprime($_) } 2..80), "]\n";

Output:

expansions of (x-1)^p:1x - 1x^2 - 2x + 1x^3 - 3x^2 + 3x - 1x^4 - 4x^3 + 6x^2 - 4x + 1x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1x^8 - 8x^7 + 28x^6 - 56x^5 + 70x^4 - 56x^3 + 28x^2 - 8x + 1x^9 - 9x^8 + 36x^7 - 84x^6 + 126x^5 - 126x^4 + 84x^3 - 36x^2 + 9x - 1Primes to 80: [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79]

Real AKS

The ntheory module has implementations of the full AKS algorithm in Perl, C, and C+GMP. This isvastly faster than the method used in this task and is polynomial time, but like all current AKSimplementations is still much slower than other methods such as BPSW, APR-CL, and ECPP.

Library: ntheory

use ntheory ":all";# Uncomment next line to see the r and s values used. Set to 2 for more detail.# prime_set_config(verbose => 1);say join(" ", grep { is_aks_prime($_) } 1_000_000_000 .. 1_000_000_100);

Output:

1000000007 1000000009 1000000021 1000000033 1000000087 1000000093 1000000097

Perl 6

constant expansions = [1], [1,-1], -> @prior { [@prior,0 Z- 0,@prior] } ... *;

30 of 53

Page 31: Aks Codes

sub polyprime($p where 2..*) { so expansions[$p].[1 ..^ */2].all %% $p }

The expansions are generated similarly to how most FP languages generate sequences thatresemble Pascal's triangle, using a zipwith meta-operator (Z) with subtraction, applied betweentwo lists that add a 0 on either end to the prior list. Here we define a constant infinite sequenceusing the ... sequence operator with a "whatever" endpoint. In fact, the second term [1,-1] couldhave been generated from the first term, but we put it in there for documentation so the readercan see what direction things are going.

The polyprime function pretty much reads like the original description. Is it "so" that the p'thexpansion's coefficients are all divisible by p? The .[1 ..^ */2] slice is done simply to weed outdivisions by 1 or by factors we've already tested (since the coefficients are symmetrical in termsof divisibility). If we wanted to write polyprime even more idiomatically, we could have made itanother infinite constant list that is just a mapping of the first list, but we decided that would justbe showing off. :-)

Showing the expansions:

say ' p: (x-1)ᵖ';say '-----------';

sub super ($n) {$n.trans: '0123456789'

=> '⁰¹²³⁴⁵⁶⁷⁸⁹';}

for ^13 -> $d {say $d.fmt('%2i: '), (

expansions[$d].kv.map: -> $i, $n {my $p = $d - $i;[~] gather {

take < + - >[$n < 0] ~ ' ' unless $p == $d; take $n.abs unless $p == $d > 0; take 'x' if $p > 0; take super $p - $i if $p > 1;

}}

)}

Output:

p: (x-1)ᵖ----------- 0: 1 1: x - 1 2: x² - 2x + 1 3: x³ - 3x² + 3x - 1 4: x⁴ - 4x³ + 6x² - 4x + 1 5: x⁵ - 5x⁴ + 10x³ - 10x² + 5x - 1 6: x⁶ - 6x⁵ + 15x⁴ - 20x³ + 15x² - 6x + 1 7: x⁷ - 7x⁶ + 21x⁵ - 35x⁴ + 35x³ - 21x² + 7x - 1 8: x⁸ - 8x⁷ + 28x⁶ - 56x⁵ + 70x⁴ - 56x³ + 28x² - 8x + 1 9: x⁹ - 9x⁸ + 36x⁷ - 84x⁶ + 126x⁵ - 126x⁴ + 84x³ - 36x² + 9x - 110: x¹⁰ - 10x⁹ + 45x⁸ - 120x⁷ + 210x⁶ - 252x⁵ + 210x⁴ - 120x³ + 45x² - 10x + 111: x¹¹ - 11x¹⁰ + 55x⁹ - 165x⁸ + 330x⁷ - 462x⁶ + 462x⁵ - 330x⁴ + 165x³ - 55x² + 11x - 112: x¹² - 12x¹¹ + 66x¹⁰ - 220x⁹ + 495x⁸ - 792x⁷ + 924x⁶ - 792x⁵ + 495x⁴ - 220x³ + 66x² - 12x + 1

And testing the function:

print "\nPrimes up to 100:\n { grep &polyprime, 2..100 }\n";

31 of 53

Page 32: Aks Codes

Output:

Primes up to 100: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Phix

-- Does not work for primes above 53, which is actually beyond the original task anyway.-- Translated from the C version, just about everything is (working) out-by-1, what fun.

sequence c = repeat(0,100)

procedure coef(integer n)-- out-by-1, ie coef(1)==^0, coef(2)==^1, coef(3)==^2 etc. c[n] = 1 for i=n-1 to 2 by -1 do c[i] = c[i]+c[i-1] end forend procedure

function is_prime(integer n) coef(n+1); -- (I said it was out-by-1) for i=2 to n-1 do -- (technically "to n" is more correct) if remainder(c[i],n)!=0 then return 0 end if end for return 1end function

procedure show(integer n)-- (As per coef, this is (working) out-by-1)object ci for i=n to 1 by -1 do ci = c[i] if ci=1 then if remainder(n-i,2)=0 then if i=1 then if n=1 then ci = "1" else ci = "+1" end if else ci = "" end if else ci = "-1" end if else if remainder(n-i,2)=0 then ci = sprintf("+%d",ci) else ci = sprintf("-%d",ci) end if end if if i=1 then -- ie ^0 printf(1,"%s",{ci}) elsif i=2 then -- ie ^1 printf(1,"%sx",{ci}) else printf(1,"%sx^%d",{ci,i-1}) end if end forend procedure

procedure AKS_test_for_primes() for n=1 to 10 do -- (0 to 9 really) coef(n); printf(1,"(x-1)^%d = ", n-1); show(n);

32 of 53

Page 33: Aks Codes

puts(1,'\n'); end for

puts(1,"\nprimes (<=53):");-- coef(2); -- (needed to reset c, if we want to avoid saying 1 is prime...) c[2] = 1 -- (this manages "", which is all that call did anyway...) for n = 2 to 53 do if is_prime(n) then printf(1," %d", n); end if end for puts(1,'\n'); if getc(0) then end ifend procedure

AKS_test_for_primes()

Output:

(x-1)^0 = 1(x-1)^1 = x-1(x-1)^2 = x^2-2x+1(x-1)^3 = x^3-3x^2+3x-1(x-1)^4 = x^4-4x^3+6x^2-4x+1(x-1)^5 = x^5-5x^4+10x^3-10x^2+5x-1(x-1)^6 = x^6-6x^5+15x^4-20x^3+15x^2-6x+1(x-1)^7 = x^7-7x^6+21x^5-35x^4+35x^3-21x^2+7x-1(x-1)^8 = x^8-8x^7+28x^6-56x^5+70x^4-56x^3+28x^2-8x+1(x-1)^9 = x^9-9x^8+36x^7-84x^6+126x^5-126x^4+84x^3-36x^2+9x-1

primes (<=53): 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53

PicoLisp

(de pascal (N) (let D 1 (make (for X (inc N) (link D) (setq D (*/ D (- (inc N) X) (- X)) ) ) ) ) )

(for (X 0 (> 10 X) (inc X)) (println X '-> (pascal X) ) )

(println (filter '((X) (fully '((Y) (=0 (% Y X))) (cdr (head -1 (pascal X))) ) ) (range 2 50) ) )

(bye)

Output:

0 -> (1)1 -> (1 -1)2 -> (1 -2 1)3 -> (1 -3 3 -1)4 -> (1 -4 6 -4 1)5 -> (1 -5 10 -10 5 -1)6 -> (1 -6 15 -20 15 -6 1)7 -> (1 -7 21 -35 35 -21 7 -1)8 -> (1 -8 28 -56 70 -56 28 -8 1)

33 of 53

Page 34: Aks Codes

9 -> (1 -9 36 -84 126 -126 84 -36 9 -1)(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)

Prolog

Prolog(ue)

The theorem as stated ties together two elementary concepts in mathematics: prime numbers andthe Pascal triangle. The simplicity of the connection can be expressed directly in Prolog by thefollowing prime number generator:

prime(P) :- pascal([1,P|Xs]), append(Xs, [1], Rest), forall( member(X,Xs), 0 is X mod P).

where pascal/1 is a generator of rows of the Pascal triangle, for example as defined below; theother predicates used above are standard.

This solution to the Rosetta Code problems will accordingly focus on the Pascal triangle, but toillustrate a number of points, we shall exploit its symmetry by representing each of its rows bythe longest initial non-decreasing segment of that row, as illustrated in the third column of thefollowing table:

Row Pascal Row optpascal1 1 [1]2 1 1 [1, 1]3 1 2 1 [1, 2]4 1 3 3 1 [1, 3, 3]

We shall refer to this condensed representation of a row as an "optpascal list". Using it, we cansimplify and improve the above prime number generator by defining it as follows:

prime(N) :- optpascal([1,N|Xs]), forall( member(X,Xs), 0 is X mod N).

Using SWI-Prolog without modifying any of the memory management parameters, this primenumber generator was used to generate all primes up to and including 75,659.

Since Pascal triangles are the foundation of our approach to addressing the specific Rosetta Codeproblems, we begin by defining the generator pascal/2 that is required by the first problem, butwe do so by defining it in terms of an efficient generator, optpascal/1.

Pascal Triangle Generator

% To generate the n-th row of a Pascal triangle% pascal(+N, Row)pascal(0, [1]).pascal(N, Row) :- N > 0, optpascal( [1, N|Xs] ),!,

pascalize( [1, N|Xs], Row ).

pascalize( Opt, Row ) :-% if Opt ends in a pair, then peel off the pair:

34 of 53

Page 35: Aks Codes

( append(X, [R,R], Opt) -> true ; append(X, [R], Opt) ), reverse(X, Rs), append( Opt, Rs, Row ).

% optpascal(-X) generates optpascal lines:optpascal(X) :- optpascal_successor( [], X).

% optpascal_successor(+P, -Q) is true if Q is an optpascal list beneath the optpascal list P:optpascal_successor(P, Q) :- optpascal(P, NextP),(Q = NextP ; optpascal_successor(NextP, Q)).

% optpascal(+Row, NextRow) is true if Row and NextRow are adjacent rows in the Pascal triangle.% optpascal(+Row, NextRow) where the optpascal representation is usedoptpascal(X, [1|Y]) :- add_pairs(X, Y).

% add_pairs(+OptPascal, NextOptPascal) is a helper function for optpascal/2.% Given one OptPascal list, it generates the next by adding adjacent% items, but if the last two items are unequal, then their sum is% repeated. This is intended to be a deterministic predicate, and to% avoid a probable compiler limitation, we therefore use one cut.add_pairs([], []).add_pairs([X], [X]).add_pairs([X,Y], Ans) :- S is X + Y,(X = Y -> Ans=[S] ; Ans=[S,S]),!. % To overcome potential limitation of compiler

add_pairs( [X1, X2, X3|Xs], [S|Ys]) :- S is X1 + X2, add_pairs( [X2, X3|Xs], Ys).

Solutions

Solutions with output from SWI-Prolog:

%%% Task 1: "A method to generate the coefficients of (1-X)^p"

coefficients(N, Coefficients) :- pascal(N, X), alternate_signs(X, Coefficients).

alternate_signs( [], [] ).alternate_signs( [A], [A] ).alternate_signs( [A,B | X], [A, MB | Y] ) :- MB is -B, alternate_signs(X,Y).

%%% Task 2. "Show here the polynomial expansions of (x − 1)p for p in the range 0 to at least 7, inclusive."

coefficients(Coefficients) :- optpascal( Opt), pascalize( Opt, Row ), alternate_signs(Row, Coefficients).

% As required by the problem statement, but necessarily very inefficient::- between(0, 7, N), coefficients(N, Coefficients), writeln(Coefficients), fail ; true.

[1][1,-1][1,-2,1][1,-3,3,-1][1,-4,6,-4,1][1,-5,10,-10,5,-1][1,-6,15,-20,15,-6,1][1,-7,21,-35,35,-21,7,-1]

35 of 53

Page 36: Aks Codes

The following would be more efficient because backtracking saves recomputation:

:- coefficients(Coefficients), writeln(Coefficients), Coefficients = [_,N|_], N = -7.

%%% Task 3. Use the previous function in creating [sic]%%% another function that when given p returns whether p is prime%%% using the AKS test.

% Even for testing whether a given number, N, is prime, % this approach is inefficient, but here is a Prolog implementation:

prime_test_per_requirements(N) :- coefficients(N, [1|Coefficients]), append(Cs, [_], Coefficients), forall( member(C, Cs), 0 is C mod N).

The following is more efficient (because it relies on optpascal lists rather than the full array ofcoefficients), and more flexible (because it can be used to generate primes without requiringrecomputation):

prime(N) :- optpascal([1,N|Xs]), forall( member(X,Xs), 0 is X mod N).

%%% Task 4. Use your AKS test to generate a list of all primes under 35.

:- prime(N), (N < 35 -> write(N), write(' '), fail ; nl).

% Output: 1 2 3 5 7 11 13 17 19 23 29 31

%%% Task 5. As a stretch goal, generate all primes under 50.

:- prime(N), (N < 50 -> write(N), write(' '), fail ; nl).

% Output: 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

PureBasic

EnableExplicitDefine vzr.b = -1, vzc.b = ~vzr, nMAX.i = 10, n , k

Procedure coeff(nRow.i, Array pd.i(2))Define.i n, kFor n=1 To nRowFor k=0 To nIf k=0 Or k=n : pd(n,k)=1 : Continue : EndIf

pd(n,k)=pd(n-1,k-1)+pd(n-1,k)Next

NextEndProcedure

Procedure.b isPrime(n.i, Array pd.i(2))Define.i mFor m=1 To n-1If Not pd(n,m) % n = 0 : ProcedureReturn #False : EndIf

36 of 53

Page 37: Aks Codes

NextProcedureReturn #True

EndProcedure

Dim pd.i(nMAX,nMAX)pd(0,0)=1 : coeff(nMAX, pd())OpenConsole()

For n=0 To nMAXPrint(RSet(Str(n),3,Chr(32))+": ")If vzr : Print("+") : Else : Print("-") : EndIfFor k=0 To n If k>0 : If vzc : Print("+") : Else : Print("-") : EndIf : vzc = ~vzc : EndIfPrint(RSet(Str(pd(n,k)),3,Chr(32))+Space(3))

NextPrintN("")

vzr = ~vzr : vzc = ~vzr NextPrintN("")

nMAX=50 : Dim pd.i(nMAX,nMAX)Print("Primes n<=50 : ") : coeff(nMAX, pd())For n=2 To 50If isPrime(n,pd()) : Print(Str(n)+Space(2)) : EndIf

NextInput()

Output:

0: + 1 1: - 1 + 1 2: + 1 - 2 + 1 3: - 1 + 3 - 3 + 1 4: + 1 - 4 + 6 - 4 + 1 5: - 1 + 5 - 10 + 10 - 5 + 1 6: + 1 - 6 + 15 - 20 + 15 - 6 + 1 7: - 1 + 7 - 21 + 35 - 35 + 21 - 7 + 1 8: + 1 - 8 + 28 - 56 + 70 - 56 + 28 - 8 + 1 9: - 1 + 9 - 36 + 84 -126 +126 - 84 + 36 - 9 + 1 10: + 1 - 10 + 45 -120 +210 -252 +210 -120 + 45 - 10 + 1

Primes n<=50 : 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Python

def expand_x_1(n): # This version uses a generator and thus less computations c =1

for i in range(n/2+1): c = c*(n-i)/(i+1)

yield c

def aks(p):if p==2:

return True

for i in expand_x_1(p):if i % p:

# we stop without computing all possible solutionsreturn False

return True

def expand_x_1(p): ex = [1]

for i in range(p): ex.append(ex[-1] * -(p-i) / (i+1))

return ex[::-1]

37 of 53

Page 38: Aks Codes

def aks_test(p):if p < 2: return False

ex = expand_x_1(p) ex[0] += 1

return not any(mult % p for mult in ex[0:-1])

print('# p: (x-1)^p for small p')for p in range(12):

print('%3i: %s' % (p, ' '.join('%+i%s' % (e, ('x^%i' % n) if n else '')for n,e in enumerate(expand_x_1(p)))))

print('\n# small primes using the aks test')print([p for p in range(101) if aks_test(p)])

Output:

# p: (x-1)^p for small p 0: +1 1: -1 +1x^1 2: +1 -2x^1 +1x^2 3: -1 +3x^1 -3x^2 +1x^3 4: +1 -4x^1 +6x^2 -4x^3 +1x^4 5: -1 +5x^1 -10x^2 +10x^3 -5x^4 +1x^5 6: +1 -6x^1 +15x^2 -20x^3 +15x^4 -6x^5 +1x^6 7: -1 +7x^1 -21x^2 +35x^3 -35x^4 +21x^5 -7x^6 +1x^7 8: +1 -8x^1 +28x^2 -56x^3 +70x^4 -56x^5 +28x^6 -8x^7 +1x^8 9: -1 +9x^1 -36x^2 +84x^3 -126x^4 +126x^5 -84x^6 +36x^7 -9x^8 +1x^9 10: +1 -10x^1 +45x^2 -120x^3 +210x^4 -252x^5 +210x^6 -120x^7 +45x^8 -10x^9 +1x^10 11: -1 +11x^1 -55x^2 +165x^3 -330x^4 +462x^5 -462x^6 +330x^7 -165x^8 +55x^9 -11x^10 +1x^11

# small primes using the aks test[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Python: Output formatted for wiki

Using a wikitable and math features with the following additional code produces better formattedpolynomial output:

print('''{| class="wikitable" style="text-align:left;"|+ Polynomial Expansions and AKS prime test|-! <math>p</math>! <math>(x-1)^p</math>|-''')for p in range(12):

print('! <math>%i</math>\n| <math>%s</math>\n| %r\n|-' % (p,

' '.join('%s%s' % (('%+i' % e) if (e != 1 or not p or (p and not n) ) else '+',(('x^{%i}' % n) if n > 1 else 'x') if n else '')

for n,e in enumerate(expand_x_1(p))), aks_test(p)))print('|}')

Output:

38 of 53

Page 39: Aks Codes

Polynomial Expansions and AKS prime test

p (x − 1)p Prime(p)?

0 + 1 False

1 − 1 + x False

2 + 1 − 2x + x2 True

3 − 1 + 3x − 3x2 + x3 True

4 + 1 − 4x + 6x2 − 4x3 + x4 False

5 − 1 + 5x − 10x2 + 10x3 − 5x4 + x5 True

6 + 1 − 6x + 15x2 − 20x3 + 15x4 − 6x5 + x6 False

7 − 1 + 7x − 21x2 + 35x3 − 35x4 + 21x5 − 7x6 + x7 True

8 + 1 − 8x + 28x2 − 56x3 + 70x4 − 56x5 + 28x6 − 8x7 + x8 False

9 − 1 + 9x − 36x2 + 84x3 − 126x4 + 126x5 − 84x6 + 36x7 − 9x8 + x9 False

10 + 1 − 10x + 45x2 − 120x3 + 210x4 − 252x5 + 210x6 − 120x7 + 45x8 − 10x9 +x10 False

11 − 1 + 11x − 55x2 + 165x3 − 330x4 + 462x5 − 462x6 + 330x7 − 165x8 + 55x9

− 11x10 + x11 True

R

Borrowing heavily from Python listing. Optimized for the fact that the vector of the coefficients isa palindrome.

Is.Prime<-function(x){ expand<-function(p){ ex = 1 for (i in 0:(p/2-1)){ ex<-c(ex[1]*(p-i)/(i+1),ex) } return(rev(ex)[-1]) } return(as.logical(min(expand(x)%%x==0))) }

Racket

With copious use of the math/number-theory library...

#lang racket(require math/number-theory)

;; 1. coefficients of expanded polynomial (x-1)^p;; produces a vector because in-vector can provide a start;; and stop (of 1 and p) which allow us to drop the (-1)^p;; and the x^p terms, respectively.;;;; (vector-ref (coefficients p) e) is the coefficient for p^e(define (coefficients p) (for/vector ((e (in-range 0 (add1 p)))) (define sign (expt -1 (- p e))) (* sign (binomial p e))))

;; 2. Show the polynomial expansions from p=0 .. 7 (inclusive)

39 of 53

Page 40: Aks Codes

;; (it's possible some of these can be merged...)(define (format-coefficient c e leftmost?) (define (format-c.x^e c e) (define +c (abs c)) (match* (+c e) [(_ 0) (format "~a" +c)] [(1 _) (format "x^~a" e)] [(_ _) (format "~ax^~a" +c e)])) (define +/- (if (negative? c) "-" "+")) (define +c.x^e (format-c.x^e c e)) (match* (c e leftmost?) [(0 _ _) ""] [((? negative?) _ #t) (format "-~a" +c.x^e)] [(_ _ #t) +c.x^e] [(_ _ _) (format " ~a ~a" +/- +c.x^e)]))

(define (format-polynomial cs) (define cs-length (sequence-length cs)) (apply string-append (reverse ; convention is to display highest exponent first (for/list ((c cs) (e (in-naturals))) (format-coefficient c e (= e (sub1 cs-length)))))))

(for ((p (in-range 0 (add1 11)))) (printf "p=~a: ~a~%" p (format-polynomial (coefficients p))))

;; 3. AKS primeality test(define (prime?/AKS p) (define cs (coefficients p)) (and (or (= (vector-ref cs 0) -1) ; c_0 = -1 -> c_0 - (-1) = 0 (divides? p 2)) ; c_0 = 1 -> c_0 - (-1) = 2 -> divides? (for/and ((c (in-vector cs 1 p))) (divides? p c))))

;; there is some discussion (see Discussion) about what to do with the perennial "1";; case. This is my way of saying that I'm ignoring it(define lowest-tested-number 2)

;; 4. list of numbers < 35 that are prime (note that 1 is prime;; by the definition of the AKS test for primes):(displayln (for/list ((i (in-range lowest-tested-number 35)) #:when (prime?/AKS i)) i))

;; 5. stretch goal: all prime numbers under 50(displayln (for/list ((i (in-range lowest-tested-number 50)) #:when (prime?/AKS i)) i))(displayln (for/list ((i (in-range lowest-tested-number 100)) #:when (prime?/AKS i)) i))

Output:

p=0: 1p=1: x^1 - 1p=2: x^2 - 2x^1 + 1p=3: x^3 - 3x^2 + 3x^1 - 1p=4: x^4 - 4x^3 + 6x^2 - 4x^1 + 1p=5: x^5 - 5x^4 + 10x^3 - 10x^2 + 5x^1 - 1p=6: x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x^1 + 1p=7: x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x^1 - 1p=8: x^8 - 8x^7 + 28x^6 - 56x^5 + 70x^4 - 56x^3 + 28x^2 - 8x^1 + 1p=9: x^9 - 9x^8 + 36x^7 - 84x^6 + 126x^5 - 126x^4 + 84x^3 - 36x^2 + 9x^1 - 1p=10: x^10 - 10x^9 + 45x^8 - 120x^7 + 210x^6 - 252x^5 + 210x^4 - 120x^3 + 45x^2 - 10x^1 + 1p=11: x^11 - 11x^10 + 55x^9 - 165x^8 + 330x^7 - 462x^6 + 462x^5 - 330x^4 + 165x^3 - 55x^2 + 11x^1 - 1(2 3 5 7 11 13 17 19 23 29 31)(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)

REXX

version 1

/* REXX ---------------------------------------------------------------

40 of 53

Page 41: Aks Codes

* 09.02.2014 Walter Pachl* 22.02.2014 WP fix 'accounting' problem (courtesy GS)*--------------------------------------------------------------------*/c.=1Numeric Digits 100limit=200pl=''mmm=0Do p=3 To limit pm1=p-1 c.p.1=1 c.p.p=1Do j=2 To p-1

jm1=j-1 c.p.j=c.pm1.jm1+c.pm1.j mmm=max(mmm,c.p.j)

EndEnd

Say '(x-1)**0 = 1'do i=2 To limit im1=i-1sign='+'

ol='(x-1)^'im1 '='Do j=i to 2 by -1If j=2 Then

term='x 'Else

term='x^'||(j-1)If j=i Then

ol=ol termElse

ol=ol sign c.i.j'*'termsign=translate(sign,'+-','-+')End

If i<10 thenSay ol sign 1

Do j=2 To i-1If c.i.j//(i-1)>0 ThenLeave

EndIf j>i-1 Then

pl=pl (i-1)End

Say ' 'Say 'Primes:' subword(pl,2,27)Say ' ' subword(pl,29)Say 'Largest coefficient:' mmmSay 'This has' length(mmm) 'digits'

Output:

(x-1)**0 = 1(x-1)^1 = x - 1(x-1)^2 = x^2 - 2*x + 1(x-1)^3 = x^3 - 3*x^2 + 3*x - 1(x-1)^4 = x^4 - 4*x^3 + 6*x^2 - 4*x + 1(x-1)^5 = x^5 - 5*x^4 + 10*x^3 - 10*x^2 + 5*x - 1(x-1)^6 = x^6 - 6*x^5 + 15*x^4 - 20*x^3 + 15*x^2 - 6*x + 1(x-1)^7 = x^7 - 7*x^6 + 21*x^5 - 35*x^4 + 35*x^3 - 21*x^2 + 7*x - 1(x-1)^8 = x^8 - 8*x^7 + 28*x^6 - 56*x^5 + 70*x^4 - 56*x^3 + 28*x^2 - 8*x + 1

Primes: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199Largest coefficient: 45274257328051640582702088538742081937252294837706668420660This has 59 digits

version 2

This REXX version is an optimized version (of version 1) and modified to address each of therequirements.The program determines programmatically the required number of digits (precision) for the large

41 of 53

Page 42: Aks Codes

coefficients.

/*REXX pgm calculates primes via the Agrawal-Kayal-Saxena (AKS) primality test*/parse arg Z .; if Z=='' then Z=200 /*Z not specified? Then use default.*/OZ=Z; tell=Z<0; Z=abs(Z) /*Is Z negative? Then show expression.*/numeric digits max(9,Z%3) /*define a dynamic # of decimal digits.*/$.0='-'; $.1="+"; @.=1 /*$.x: sign char; default coefficients.*/#= /*define list of prime numbers (so far)*/do p=3 for Z; pm=p-1; pp=p+1 /*PM & PP: used as a coding convenience*/

do m=2 for pp%2-1; mm=m-1 /*calculate coefficients for a power. */ @[email protected] + @.pm.m; h=pp-m /*calculate left side of coefficients*/ @[email protected] /* " right " " " */

end /*m*/ /* [↑] The M DO loop creates both */end /*p*/ /* sides in the same loop, saving */

/* a bunch of execution time. */if tell then say '(x-1)^0: 1' /*possibly display the first expression*/

/* [↓] test for primality by division.*/do n=2 for Z; nh=n%2; d=n-1 /*create expressions; find the primes.*/

do k=3 to nh while @.n.k//d==0 /*are coefficients divisible by N-1 ? */end /*k*/ /* [↑] skip the 1st & 2nd coefficients*/

/* [↓] multiple THEN─IF faster than &s*/if d\==1 then if d\==4 then if k>nh then #=# d /*add number to prime list.*/if \tell then iterate /*Don't tell? Don't show expressions.*/

y='(x-1)^'d": " /*define first part of the expression. */ s=1 /*S: is the sign indicator (-1│+1).*/

do j=n to 2 by -1 /*create the higher powers first. */if j==2 then xp='x' /*if power=1, then don't show the power*/

else xp='x^' || (j-1) /* ··· else show power with ^ */if j==n then y=y xp /*no sign (+│-) for the 1st expression.*/

else y=y $.s @.n.j'∙'xp /*build the expression with sign (+|-).*/ s=\s /*flip the sign for the next expression*/

end /*j*/ /* [↑] the sign (now) is either 0 │ 1,*//* and is displayed either - │ + */

say y $.s 1 /*just show the first N expressions, */end /*n*/ /* [↑] ··· but only for negative Z. */

say /* [↓] Has Z a leading + ? Then show.*/is="isn't"; if Z==word(. #,words(#)+1) then is='is' /*is or isn't a prime.*/if left(OZ,1)=='+' then say Z is 'prime.' /*tell if OZ has a +. */

else say 'primes:' # /*display prime # list. */say /* [↓] size of big 'un.*/say 'Found ' words(#) ' primes and the largest coefficient has' ,

length(@.pm.h) "decimal digits." /*stick a fork in it, we're all done. */

output for requirement #2, showing twenty expressions using as input: -20

(x-1)^0: 1(x-1)^1: x - 1(x-1)^2: x^2 - 2∙x + 1(x-1)^3: x^3 - 3∙x^2 + 3∙x - 1(x-1)^4: x^4 - 4∙x^3 + 6∙x^2 - 4∙x + 1(x-1)^5: x^5 - 5∙x^4 + 10∙x^3 - 10∙x^2 + 5∙x - 1(x-1)^6: x^6 - 6∙x^5 + 15∙x^4 - 20∙x^3 + 15∙x^2 - 6∙x + 1(x-1)^7: x^7 - 7∙x^6 + 21∙x^5 - 35∙x^4 + 35∙x^3 - 21∙x^2 + 7∙x - 1(x-1)^8: x^8 - 8∙x^7 + 28∙x^6 - 56∙x^5 + 70∙x^4 - 56∙x^3 + 28∙x^2 - 8∙x + 1(x-1)^9: x^9 - 9∙x^8 + 36∙x^7 - 84∙x^6 + 126∙x^5 - 126∙x^4 + 84∙x^3 - 36∙x^2 + 9∙x - 1(x-1)^10: x^10 - 10∙x^9 + 45∙x^8 - 120∙x^7 + 210∙x^6 - 252∙x^5 + 210∙x^4 - 120∙x^3 + 45∙x^2 - 10∙x + 1(x-1)^11: x^11 - 11∙x^10 + 55∙x^9 - 165∙x^8 + 330∙x^7 - 462∙x^6 + 462∙x^5 - 330∙x^4 + 165∙x^3 - 55∙x^2 + 11∙x - 1(x-1)^12: x^12 - 12∙x^11 + 66∙x^10 - 220∙x^9 + 495∙x^8 - 792∙x^7 + 924∙x^6 - 792∙x^5 + 495∙x^4 - 220∙x^3 + 66∙x^2 - 12∙x + 1(x-1)^13: x^13 - 13∙x^12 + 78∙x^11 - 286∙x^10 + 715∙x^9 - 1287∙x^8 + 1716∙x^7 - 1716∙x^6 + 1287∙x^5 - 715∙x^4 + 286∙x^3 - 78∙x^2 + 13∙x - 1(x-1)^14: x^14 - 14∙x^13 + 91∙x^12 - 364∙x^11 + 1001∙x^10 - 2002∙x^9 + 3003∙x^8 - 3432∙x^7 + 3003∙x^6 - 2002∙x^5 + 1001∙x^4 - 364∙x^3 + 91∙x^(x-1)^15: x^15 - 15∙x^14 + 105∙x^13 - 455∙x^12 + 1365∙x^11 - 3003∙x^10 + 5005∙x^9 - 6435∙x^8 + 6435∙x^7 - 5005∙x^6 + 3003∙x^5 - 1365∙x^4 + 45(x-1)^16: x^16 - 16∙x^15 + 120∙x^14 - 560∙x^13 + 1820∙x^12 - 4368∙x^11 + 8008∙x^10 - 11440∙x^9 + 12870∙x^8 - 11440∙x^7 + 8008∙x^6 - 4368∙x^5 (x-1)^17: x^17 - 17∙x^16 + 136∙x^15 - 680∙x^14 + 2380∙x^13 - 6188∙x^12 + 12376∙x^11 - 19448∙x^10 + 24310∙x^9 - 24310∙x^8 + 19448∙x^7 - 12376∙(x-1)^18: x^18 - 18∙x^17 + 153∙x^16 - 816∙x^15 + 3060∙x^14 - 8568∙x^13 + 18564∙x^12 - 31824∙x^11 + 43758∙x^10 - 48620∙x^9 + 43758∙x^8 - 31824(x-1)^19: x^19 - 19∙x^18 + 171∙x^17 - 969∙x^16 + 3876∙x^15 - 11628∙x^14 + 27132∙x^13 - 50388∙x^12 + 75582∙x^11 - 92378∙x^10 + 92378∙x^9 - 755(x-1)^20: x^20 - 20∙x^19 + 190∙x^18 - 1140∙x^17 + 4845∙x^16 - 15504∙x^15 + 38760∙x^14 - 77520∙x^13 + 125970∙x^12 - 167960∙x^11 + 184756∙x^10

primes: 2 3 5 7 11 13 17 19

Found 8 primes and the largest coefficient has 6 decimal digits.

output for requirement #3, showing if 2221 is prime (or not) using for input: +2221

42 of 53

Page 43: Aks Codes

(Output note: this number is really pushing at the limits of REXX's use of virtual memory; theversion ofRegina REXX used herein has a limit of around 2 Gbytes.)

2221 is prime.

Found 331 primes and the largest coefficient has 668 decimal digits.

output for requirement #4, showing all primes under 35 using the input: 35

primes: 2 3 5 7 11 13 17 19 23 29 31

Found 11 primes and the largest coefficient has 10 decimal digits.

output for requirement #5 (stretch goal), showing all primes under 50 using the input: 50

primes: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Found 15 primes and the largest coefficient has 15 decimal digits.

output when using the input: 500

primes: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 17

Found 95 primes and the largest coefficient has 150 decimal digits.

Ruby

Using the `polynomial` Rubygem, this can be written directly from the definition in thedescription:

require 'polynomial'

def x_minus_1_to_the(p)return Polynomial.new(-1,1)**p

end

def prime?(p)return false if p < 2(x_minus_1_to_the(p) - Polynomial.from_string("x**#{p}-1")).coefs.all?{|n| n%p==0}

end

8.times do |n|# the default Polynomial#to_s would be OK here; the substitutions just make the# output match the other version below.puts "(x-1)^#{n} = #{x_minus_1_to_the(n).to_s.gsub(/\*\*/,'^').gsub(/\*/,'')}"

end

puts "\nPrimes below 50:", 50.times.select {|n| prime? n}.join(',')

Or without the dependency:

def x_minus_1_to_the(p)p.times.inject([1]) do |ex, _|([0] + ex).zip(ex + [0]).map { |x,y| x - y }

endend

43 of 53

Page 44: Aks Codes

def prime?(p)return false if p < 2

coeff = x_minus_1_to_the(p) coeff[0] += coeff.pop coeff.all?{|n| n%p==0}end

8.times do |n|puts "(x-1)^#{n} = " +

x_minus_1_to_the(n).each_with_index.map { |c, p|if p.zero? then c.to_selse(c<0 ? " - " : " + ") + (c.abs==1 ? "x" : "#{c.abs}x") + (p==1 ? "" : "^#{p}")

end}.join

end

puts "\nPrimes below 50:", 50.times.select {|n| prime? n}.join(',')

Output:

(x-1)^0 = 1(x-1)^1 = -1 + x(x-1)^2 = 1 - 2x + x^2(x-1)^3 = -1 + 3x - 3x^2 + x^3(x-1)^4 = 1 - 4x + 6x^2 - 4x^3 + x^4(x-1)^5 = -1 + 5x - 10x^2 + 10x^3 - 5x^4 + x^5(x-1)^6 = 1 - 6x + 15x^2 - 20x^3 + 15x^4 - 6x^5 + x^6(x-1)^7 = -1 + 7x - 21x^2 + 35x^3 - 35x^4 + 21x^5 - 7x^6 + x^7

Primes below 50:2,3,5,7,11,13,17,19,23,29,31,37,41,43,47

Rust

#![feature(core)]

use std::iter::{range_inclusive, repeat};

fn aks_coefficients(k: usize) -> Vec<i64> {let mut coefficients = repeat(0i64).take(k + 1).collect::<Vec<_>>();coefficients[0] = 1;for i in 1..(k + 1) {

coefficients[i] = -(1..i).fold(coefficients[0], |prev, j|{let old = coefficients[j];coefficients[j] = old - prev;old

});}coefficients

}

fn is_prime(p: usize) -> bool {if p < 2 {

false} else {

let c = aks_coefficients(p);range_inclusive(1, (c.len() - 1) / 2).all(|i| (c[i] % (p as i64)) == 0)

}}

fn main() { for i in 0..8 { println!("{}: {:?}", i, aks_coefficients(i)); }

for i in (1..51).filter(|&i| is_prime(i)) {print!("{} ", i);

}}

44 of 53

Page 45: Aks Codes

Output:

0: [1]1: [1, -1]2: [1, -2, 1]3: [1, -3, 3, -1]4: [1, -4, 6, -4, 1]5: [1, -5, 10, -10, 5, -1]6: [1, -6, 15, -20, 15, -6, 1]7: [1, -7, 21, -35, 35, -21, 7, -1]2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

An alternative version which computes the coefficients in a more functional but less efficient way.

fn aks_coefficients(k: usize) -> Vec<i64> {if k == 0 {

vec![1i64]} else {

let zero = Some(0i64);range(1, k).fold(vec![1i64, -1], |r, _| {

let a = r.iter().chain(zero.iter());let b = zero.iter().chain(r.iter());a.zip(b).map(|(x, &y)| x-y).collect()

})}

}

Scala

def powerMin1(n: BigInt) = if (n % 2 == 0) BigInt(1) else BigInt(-1)

val pascal = (( Vector(Vector(BigInt(1))) /: (1 to 50)) { (rows, i) =>val v = rows.headval newVector = ((1 until v.length) map (j =>

powerMin1(j+i) * (v(j-1).abs + v(j).abs))).toVector(powerMin1(i) +: newVector :+ powerMin1(i+v.length)) +: rows

}).reverse

def poly2String(poly: Vector[BigInt]) = ((0 until poly.length) map { i =>(i, poly(i)) match {

case (0, c) => c.toStringcase (_, c) =>

(if (c >= 0) "+" else "-") +(if (c == 1) "x" else c.abs + "x") +(if (i == 1) "" else "^" + i)

}}) mkString ""

def isPrime(n: Int) = {val poly = pascal(n)

poly.slice(1, poly.length - 1).forall(i => i % n == 0)}

for(i <- 0 to 7) { println( f"(x-1)^$i = ${poly2String( pascal(i) )}" ) }

val primes = (2 to 50).filter(isPrime)printlnprintln(primes mkString " ")

Output:

(x-1)^0 = 1(x-1)^1 = -1+x(x-1)^2 = 1-2x+x^2

45 of 53

Page 46: Aks Codes

(x-1)^3 = -1+3x-3x^2+x^3(x-1)^4 = 1-4x+6x^2-4x^3+x^4(x-1)^5 = -1+5x-10x^2+10x^3-5x^4+x^5(x-1)^6 = 1-6x+15x^2-20x^3+15x^4-6x^5+x^6(x-1)^7 = -1+7x-21x^2+35x^3-35x^4+21x^5-7x^6+x^7

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Scilab

clearxdel(winsid())

stacksize('max')sz=stacksize();

n=7; //For the expansion up to power of ng=50; //For test of primes up to g

function X = pascal(g) //Pascal´s triangle X(1,1)=1; //Zeroth power X(2,1)=1; //First power X(2,2)=1; for q=3:1:g+1 //From second power use this loop X(q,1)=1; X(q,q)=1; for p=2:1:q-1 X(q,p)=X(q-1,p-1)+X(q-1,p); end endendfunction

Z=pascal(g); //Generate Pascal's triangle up to g

Q(0+1)="(x-1)^0 = 1"; //For nicer displayQ(1+1)="(x-1)^1 = x^1-1"; //For nicer display

disp(Q(1))disp(Q(2))

function cf=coef(Z,q,p) //Return coeffiecents for nicer display of expansion without "ones" if Z(q,p)==1 then cf=""; else cf=string(Z(q,p)); endendfunction

for q=3:n+1 //Generate and display the expansions Q(q)=strcat(["(x-1)^",string(q-1)," = "]); sing=""; //Sign of coeff. for p=1:q-1 //Number of coefficients equals power minus 1 Q(q)=strcat([Q(q),sing,coef(Z,q,p),"x^",string(q-p)]); if sing=="-" then sing="+"; else sing="-"; end end Q(q)=strcat([Q(q),sing,string(1)]); disp(Q(q)) clear Qend

function prime=prime(Z,g) prime="true"; for p=2:g if abs(floor(Z(g+1,p)/g)-Z(g+1,p)/g)>0 then prime="false"; break; end endendfunction

R="2"; //For nicer displayfor r=3:g

46 of 53

Page 47: Aks Codes

if prime(Z,r)=="true" then R=strcat([R, ", ",string(r)]); endenddisp(R)

Output:

(x-1)^0 = 1

(x-1)^1 = x^1-1

(x-1)^2 = x^2-2x^1+1

(x-1)^3 = x^3-3x^2+3x^1-1

(x-1)^4 = x^4-4x^3+6x^2-4x^1+1

(x-1)^5 = x^5-5x^4+10x^3-10x^2+5x^1-1

(x-1)^6 = x^6-6x^5+15x^4-20x^3+15x^2-6x^1+1

(x-1)^7 = x^7-7x^6+21x^5-35x^4+35x^3-21x^2+7x^1-1

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47

Seed7

$ include "seed7_05.s7i";

const func array integer: expand_x_1 (in integer: p) is func result var array integer: ex is [] (1); local var integer: i is 0; begin for i range 0 to p - 1 do ex := [] (ex[1] * -(p - i) div (i + 1)) & ex; end for; end func;

const func boolean: aks_test (in integer: p) is func result var boolean: aks_test is FALSE; local var array integer: ex is 0 times 0; var integer: idx is 0; begin if p >= 2 then ex := expand_x_1(p); ex[1] +:= 1; for idx range 1 to pred(length(ex)) until ex[idx] rem p <> 0 do noop; end for; aks_test := idx = length(ex); end if; end func;

const proc: main is func local var integer: p is 0; var integer: n is 0; var integer: e is 0; begin writeln("# p: (x-1)^p for small p"); for p range 0 to 11 do write(p lpad 3 <& ": "); for n key e range expand_x_1(p) do write(" "); if n >= 0 then

47 of 53

Page 48: Aks Codes

write("+"); end if; write(n); if e > 1 then write("x^" <& pred(e)); end if; end for; writeln; end for; writeln; writeln("# small primes using the aks test"); for p range 0 to 61 do if aks_test(p) then write(p <& " "); end if; end for; writeln; end func;

Output:

# p: (x-1)^p for small p 0: +1 1: -1 +1x^1 2: +1 -2x^1 +1x^2 3: -1 +3x^1 -3x^2 +1x^3 4: +1 -4x^1 +6x^2 -4x^3 +1x^4 5: -1 +5x^1 -10x^2 +10x^3 -5x^4 +1x^5 6: +1 -6x^1 +15x^2 -20x^3 +15x^4 -6x^5 +1x^6 7: -1 +7x^1 -21x^2 +35x^3 -35x^4 +21x^5 -7x^6 +1x^7 8: +1 -8x^1 +28x^2 -56x^3 +70x^4 -56x^5 +28x^6 -8x^7 +1x^8 9: -1 +9x^1 -36x^2 +84x^3 -126x^4 +126x^5 -84x^6 +36x^7 -9x^8 +1x^9 10: +1 -10x^1 +45x^2 -120x^3 +210x^4 -252x^5 +210x^6 -120x^7 +45x^8 -10x^9 +1x^10 11: -1 +11x^1 -55x^2 +165x^3 -330x^4 +462x^5 -462x^6 +330x^7 -165x^8 +55x^9 -11x^10 +1x^11

# small primes using the aks test2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61

Sidef

Translation of: Perl

func binprime(p) {p >= 2 || return false;

range(1, p>>1).each { |i|(binomial(p, i) % p) && return false;

};return true;

}

func coef(n, e) {(e == 0) && return "#{n}";(n == 1) && (n = "");(e == 1) ? "#{n}x" : "#{n}x^#{e}";

}

func binpoly(p) { join(" ", coef(1, p), range(p-1).reverse.map {|i| join(" ", %w(+ -)[(p-i)&1], coef(binomial(p, i), i));

}...);}

say "expansions of (x-1)^p:";range(9).each { |i| say binpoly(i) };say "Primes to 80: [#{(2..80).grep { binprime(_) }}]";

Output:

expansions of (x-1)^p:

48 of 53

Page 49: Aks Codes

1x - 1x^2 - 2x + 1x^3 - 3x^2 + 3x - 1x^4 - 4x^3 + 6x^2 - 4x + 1x^5 - 5x^4 + 10x^3 - 10x^2 + 5x - 1x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x + 1x^7 - 7x^6 + 21x^5 - 35x^4 + 35x^3 - 21x^2 + 7x - 1x^8 - 8x^7 + 28x^6 - 56x^5 + 70x^4 - 56x^3 + 28x^2 - 8x + 1x^9 - 9x^8 + 36x^7 - 84x^6 + 126x^5 - 126x^4 + 84x^3 - 36x^2 + 9x - 1Primes to 80: [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79]

Swift

func polynomialCoeffs(n: Int) -> [Int] { var result = [Int](count : n+1, repeatedValue : 0)

result[0]=1 for i in 1 ..< n/2+1 { //Progress up, until reaching the middle value result[i] = result[i-1] * (n-i+1)/i; } for i in n/2+1 ..< n+1 { //Copy the inverse of the first part result[i] = result[n-i]; } // Take into account the sign for i in stride(from: 1, through: n, by: 2) { result[i] = -result[i] }

return result}

func isPrime(n: Int) -> Bool {

var coeffs = polynomialCoeffs(n)

coeffs[0]-- coeffs[n]++

for i in 1 ... n { if coeffs[i]%n != 0 { return false } }

return true}

for i in 0...10 {

let coeffs = polynomialCoeffs(i)

print("(x-1)^\(i) = ") if i == 0 { print("1") } else { if i == 1 { print("x") } else { print("x^\(i)") if i == 2 { print("\(coeffs[i-1])x") } else { for j in 1...(i - 2) { if j%2 == 0 { print("+\(coeffs[j])x^\(i-j)") } else { print("\(coeffs[j])x^\(i-j)") } } if (i-1)%2 == 0 { print("+\(coeffs[i-1])x") } else {

49 of 53

Page 50: Aks Codes

print("\(coeffs[i-1])x") } } } if i%2 == 0 { print("+\(coeffs[i])") } else { print("\(coeffs[i])") } } println()}

println()print("Primes under 50 : ")

for i in 1...50 { if isPrime(i) { print("\(i) ") }}

Output:

(x-1)^0 = 1(x-1)^1 = x-1(x-1)^2 = x^2-2x+1(x-1)^3 = x^3-3x^2+3x-1(x-1)^4 = x^4-4x^3+6x^2-4x+1(x-1)^5 = x^5-5x^4+10x^3-10x^2+5x-1(x-1)^6 = x^6-6x^5+15x^4-20x^3+15x^2-6x+1(x-1)^7 = x^7-7x^6+21x^5-35x^4+35x^3-21x^2+7x-1(x-1)^8 = x^8-8x^7+28x^6-56x^5+70x^4-56x^3+28x^2-8x+1(x-1)^9 = x^9-9x^8+36x^7-84x^6+126x^5-126x^4+84x^3-36x^2+9x-1(x-1)^10 = x^10-10x^9+45x^8-120x^7+210x^6-252x^5+210x^4-120x^3+45x^2-10x+1

Primes under 50 : 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Tcl

A recursive method with memorization would be more efficient, but this is sufficient forsmall-scale work.

proc coeffs {p {signs 1}} {set clist 1for {set i 0} {$i < $p} {incr i} {

set clist [lmap x [list 0 {*}$clist] y [list {*}$clist 0] { expr {$x + $y}}]

}if {$signs} {

set s -1set clist [lmap c $clist {expr {[set s [expr {-$s}]] * $c}}]

}return $clist

}proc aksprime {p} {

if {$p < 2} {return false

}foreach c [coeffs $p 0] {

if {$c == 1} continueif {$c % $p} { return false}

}return true

}

50 of 53

Page 51: Aks Codes

for {set i 0} {$i <= 7} {incr i} {puts -nonewline "(x-1)^$i ="set j $iforeach c [coeffs $i] {

puts -nonewline [format " %+dx^%d" $c $j]incr j -1

}puts ""

}

set sub35primes {}for {set i 1} {$i < 35} {incr i} {

if {[aksprime $i]} {lappend sub35primes $i

}}puts "primes under 35: [join $sub35primes ,]"

set sub50primes {}for {set i 1} {$i < 50} {incr i} {

if {[aksprime $i]} {lappend sub50primes $i

}}puts "primes under 50: [join $sub50primes ,]"

Output:

(x-1)^0 = +1x^0(x-1)^1 = +1x^1 -1x^0(x-1)^2 = +1x^2 -2x^1 +1x^0(x-1)^3 = +1x^3 -3x^2 +3x^1 -1x^0(x-1)^4 = +1x^4 -4x^3 +6x^2 -4x^1 +1x^0(x-1)^5 = +1x^5 -5x^4 +10x^3 -10x^2 +5x^1 -1x^0(x-1)^6 = +1x^6 -6x^5 +15x^4 -20x^3 +15x^2 -6x^1 +1x^0(x-1)^7 = +1x^7 -7x^6 +21x^5 -35x^4 +35x^3 -21x^2 +7x^1 -1x^0primes under 35: 2,3,5,7,11,13,17,19,23,29,31primes under 50: 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47

uBasic/4tH

For n = 0 To 9 Push n : Gosub _coef : Gosub _drop Print "(x-1)^";n;" = "; Push n : Gosub _show PrintNext

PrintPrint "primes (never mind the 1):";

For n = 1 To 34 Push n : Gosub _isprime If Pop() Then Print " ";n;Next

PrintEnd

' show polynomial expansions_show ' ( n --) Do If @(Tos()) > -1 Then Print "+"; Print @(Tos());"x^";Tos(); While (Tos()) Push Pop() - 1 Loop

Gosub _dropReturn

51 of 53

Page 52: Aks Codes

' test whether number is a prime_isprime ' ( n --) Gosub _coef

i = Tos() @(0) = @(0) + 1 @(i) = @(i) - 1

Do While (i) * ((@(i) % Tos()) = 0) i = i - 1 Loop

Gosub _drop Push (i = 0)Return

' generate coefficients_coef ' ( n -- n) If (Tos() < 0) + (Tos() > 34) Then End ' gracefully deal with range issue i = 0 @(i) = 1

Do While i < Tos() j = i @(j+1) = 1

Do While j > 0 @(j) = @(j-1) - @(j) j = j - 1 Loop

@(0) = -@(0) i = i + 1 LoopReturn

' drop a value from the stack_drop ' ( n --) If Pop() EndifReturn

Output:

(x-1)^0 = +1x^0(x-1)^1 = +1x^1-1x^0(x-1)^2 = +1x^2-2x^1+1x^0(x-1)^3 = +1x^3-3x^2+3x^1-1x^0(x-1)^4 = +1x^4-4x^3+6x^2-4x^1+1x^0(x-1)^5 = +1x^5-5x^4+10x^3-10x^2+5x^1-1x^0(x-1)^6 = +1x^6-6x^5+15x^4-20x^3+15x^2-6x^1+1x^0(x-1)^7 = +1x^7-7x^6+21x^5-35x^4+35x^3-21x^2+7x^1-1x^0(x-1)^8 = +1x^8-8x^7+28x^6-56x^5+70x^4-56x^3+28x^2-8x^1+1x^0(x-1)^9 = +1x^9-9x^8+36x^7-84x^6+126x^5-126x^4+84x^3-36x^2+9x^1-1x^0

primes (never mind the 1): 1 2 3 5 7 11 13 17 19 23 29 31

zkl

Translation of: Python

var BN=Import("zklBigNum");fcn expand_x_1(p){ ex := L(BN(1)); foreach i in (p){ ex.append(ex[-1] * -(p-i) / (i+1)) } return(ex.reverse()) }fcn aks_test(p){ if (p < 2) return(False); ex := expand_x_1(p);

52 of 53

Page 53: Aks Codes

ex[0] = ex[0] + 1; return(not ex[0,-1].filter('%.fp1(p)));}println("# p: (x-1)^p for small p");foreach p in (12){ println("%3d: ".fmt(p),expand_x_1(p).enumerate() .pump(String,fcn([(n,e)]){"%+d%s ".fmt(e,n and "x^%d".fmt(n) or "")}));}

println("\n# small primes using the aks test");println([0..110].filter(aks_test).toString(*));

Output:

# p: (x-1)^p for small p 0: +1 1: -1 +1x^1 2: +1 -2x^1 +1x^2 3: -1 +3x^1 -3x^2 +1x^3 4: +1 -4x^1 +6x^2 -4x^3 +1x^4 5: -1 +5x^1 -10x^2 +10x^3 -5x^4 +1x^5 6: +1 -6x^1 +15x^2 -20x^3 +15x^4 -6x^5 +1x^6 7: -1 +7x^1 -21x^2 +35x^3 -35x^4 +21x^5 -7x^6 +1x^7 8: +1 -8x^1 +28x^2 -56x^3 +70x^4 -56x^5 +28x^6 -8x^7 +1x^8 9: -1 +9x^1 -36x^2 +84x^3 -126x^4 +126x^5 -84x^6 +36x^7 -9x^8 +1x^9 10: +1 -10x^1 +45x^2 -120x^3 +210x^4 -252x^5 +210x^6 -120x^7 +45x^8 -10x^9 +1x^10 11: -1 +11x^1 -55x^2 +165x^3 -330x^4 +462x^5 -462x^6 +330x^7 -165x^8 +55x^9 -11x^10 +1x^11

# small primes using the aks testL(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109)

Retrieved from "http://rosettacode.org/mw/index.php?title=AKS_test_for_primes&oldid=210996"Categories: Programming Tasks Prime Numbers ALGOL 68 AutoHotkey Bracmat CC sharp Clojure CoffeeScript Common Lisp D EchoLisp Erlang Fortran Go FreeBASICHaskell J Java JavaScript Jq Julia Maple Mathematica Wolfram Language OforthPARI/GP Pascal Perl Ntheory Perl 6 Phix PicoLisp Prolog PureBasic Python R RacketREXX Ruby Rust Scala Scilab Seed7 Sidef Swift Tcl UBasic/4tH Zkl

This page was last modified on 5 September 2015, at 17:36.Content is available under GNU Free Documentation License 1.2.

53 of 53