242
\$\begingroup\$

Believe it or not, we do not yet have a code golf challenge for a simple primality test. While it may not be the most interesting challenge, particularly for "usual" languages, it can be nontrivial in many languages.

Rosetta code features lists by language of idiomatic approaches to primality testing, one using the Miller-Rabin test specifically and another using trial division. However, "most idiomatic" often does not coincide with "shortest." In an effort to make Programming Puzzles and Code Golf the go-to site for code golf, this challenge seeks to compile a catalog of the shortest approach in every language, similar to "Hello, World!" and Golf you a quine for great good!.

Furthermore, the capability of implementing a primality test is part of our definition of programming language, so this challenge will also serve as a directory of proven programming languages.

Task

Write a full program that, given a strictly positive integer n as input, determines whether n is prime and prints a truthy or falsy value accordingly.

For the purpose of this challenge, an integer is prime if it has exactly two strictly positive divisors. Note that this excludes 1, who is its only strictly positive divisor.

Your algorithm must be deterministic (i.e., produce the correct output with probability 1) and should, in theory, work for arbitrarily large integers. In practice, you may assume that the input can be stored in your data type, as long as the program works for integers from 1 to 255.

Input

  • If your language is able to read from STDIN, accept command-line arguments or any other alternative form of user input, you can read the integer as its decimal representation, unary representation (using a character of your choice), byte array (big or little endian) or single byte (if this is your languages largest data type).

  • If (and only if) your language is unable to accept any kind of user input, you may hardcode the input in your program.

    In this case, the hardcoded integer must be easily exchangeable. In particular, it may appear only in a single place in the entire program.

    For scoring purposes, submit the program that corresponds to the input 1.

Output

Output has to be written to STDOUT or closest alternative.

If possible, output should consist solely of a truthy or falsy value (or a string representation thereof), optionally followed by a single newline.

The only exception to this rule is constant output of your language's interpreter that cannot be suppressed, such as a greeting, ANSI color codes or indentation.

Additional rules

  • This is not about finding the language with the shortest approach for prime testing, this is about finding the shortest approach in every language. Therefore, no answer will be marked as accepted.

  • Submissions in most languages will be scored in bytes in an appropriate preexisting encoding, usually (but not necessarily) UTF-8.

    The language Piet, for example, will be scored in codels, which is the natural choice for this language.

    Some languages, like Folders, are a bit tricky to score. If in doubt, please ask on Meta.

  • Unlike our usual rules, feel free to use a language (or language version) even if it's newer than this challenge. If anyone wants to abuse this by creating a language where the empty program performs a primality test, then congrats for paving the way for a very boring answer.

    Note that there must be an interpreter so the submission can be tested. It is allowed (and even encouraged) to write this interpreter yourself for a previously unimplemented language.

  • If your language of choice is a trivial variant of another (potentially more popular) language which already has an answer (think BASIC or SQL dialects, Unix shells or trivial Brainfuck derivatives like Headsecks or Unary), consider adding a note to the existing answer that the same or a very similar solution is also the shortest in the other language.

  • Built-in functions for testing primality are allowed. This challenge is meant to catalog the shortest possible solution in each language, so if it's shorter to use a built-in in your language, go for it.

  • Unless they have been overruled earlier, all standard rules apply, including the http://meta.codegolf.stackexchange.com/q/1061.

As a side note, please don't downvote boring (but valid) answers in languages where there is not much to golf; these are still useful to this question as it tries to compile a catalog as complete as possible. However, do primarily upvote answers in languages where the author actually had to put effort into golfing the code.

Catalog

The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes 

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes 

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes 

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes 

<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 57617; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 12012; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>

\$\endgroup\$
8
  • 2
    \$\begingroup\$ Is there a reason for the full program requirement, rather than allowing the full range of default input types? E.g. answering with a function that takes its input as an argument, is currently disallowed? codegolf.meta.stackexchange.com/questions/2447/… \$\endgroup\$ Commented Dec 12, 2017 at 6:21
  • 3
    \$\begingroup\$ @LyndonWhite This was intended as a catalog (like “Hello, World!”) of primality tests, so a unified submission format seemed preferable. It's one of two decisions about this challenge that I regret, the other being only allowing deterministic primality tests. \$\endgroup\$ Commented Dec 12, 2017 at 12:51
  • 1
    \$\begingroup\$ Could a case be made for locking this challenge and posting a new, less restrictive one? \$\endgroup\$ Commented Jun 25, 2018 at 12:59
  • 2
    \$\begingroup\$ @Shaggy Seems like a question for meta. \$\endgroup\$ Commented Jun 25, 2018 at 13:44
  • 1
    \$\begingroup\$ Yeah, that's what I was thinking. I'll let you do the honours, seeing as it's your challenge. \$\endgroup\$ Commented Jun 25, 2018 at 13:45

382 Answers 382

1
9 10 11 12
13
0
\$\begingroup\$

reticular, 6 bytes

in@pp; 

A four-byte function:

[@p] 

Explanation

in@pp; i take input n convert to number @p check for primality p print ; terminate 
\$\endgroup\$
0
0
\$\begingroup\$

R, 19 Bytes

 ->n;sum(!n%%1:n)==2 

Starts with a right assign to n. i.e. precede the code with the desired n. then it merely checks primeness of n. Prints TRUE or FALSE implicitly

If you don't like right assign as an input method then for 24 bytes you get:

sum(!(n=scan())%%1:n)==2 or n=scan();sum(!n%%1:n)==2 

Which assigns within the operator.

If you want explicit answer printing, then for 28 bytes:

 p=function(n)sum(!n%%1:n)==2 
\$\endgroup\$
0
\$\begingroup\$

RProgN, 102 Bytes

 'i' asoc true i 1 - ] 1 > while [ 'a' asoc i a / i a // = if [ [ false else [ end a 1 - ] 1 > end [ [ 

Explanation

 'i' asoc # Associate the implicit input with i true i # Push true to the stack, push i to the stack 1 - # Subtact 1 from the top of the stack ] 1 > # Duplicate the top value of the stack, compare that it's larger than 1 while # While the top of the stack contains a truthy value [ # Pop the top of the stack (The conditional in this case) 'a' asoc # Associate the top of the stack with a i a / # Push i divided by a to the top of the stack i a // = # Push i integeral divided by a to the top of the stack, compare the top and underneith the top for equality if # if i/a = floor(i/a), essentially [ [ false # Pop the conditional, and the 'true' we slipped in earlier, push false in in place of it else # [ # Pop the conditional anyway end # a 1 - ] 1 > # Subtract 1 from a, duplicate it, and compare that it's larger than 1 end # [ [ # Pop the conditional, the value of a, which leaves only the bottom value we previously inserted, which is implicitly printed 

RProgN doesn't have any method of input as of yet, as such, Any input needs to be written in pure form at the very start of the code, such that 23 'i' asoc .... An Extra byte is added to the score, because a space is required in front of any command.

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

Pyret, 58 bytes

i=1 (i == 1) or any({(x):num-modulo(i,x) == 0},range(2,i)) 

You can try this online by copying the code into the online Pyret editor!

Pyret programs are designed to be run in the online editor, so there's no way to read from STDIN. Here, the variable i represents the input. The program returns true if i is not prime and false if i is prime.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ If there's no input from STDIN, maybe its best to do a function instead \$\endgroup\$ Commented Jun 20, 2018 at 0:14
  • 1
    \$\begingroup\$ @JoKing This challenge doesn't allow functions. \$\endgroup\$ Commented Jun 20, 2018 at 1:46
0
\$\begingroup\$

Yabasic, 43 bytes

Input""n For d=2To n p=p+!Mod(n,d)Next ?p=1 

Try it online!

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

Pepe, 53 bytes

Uses trial-and-error modulus, so gets slower in larger integers.

REeEREErEEEEErREEeEeEReeREEEEeEeEReRererrEEreEErEeree 

Try it online! Outputs 0 for truthy and none for falsy.

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

Spice, 93 bytes

;i;m;t;c;r@REA i;ADD 0 1 c;SUB i 1 m;ADD c 1 c;MOD i c t;SWI t 1 9;SWI c m 3;ADD 0 1 r;OUT r; 

This outputs [1] for a prime, and [] for a non-prime.

Un-golfed explanation:

;i;m;t;c;r@ - Declare vars (@ marks end of declarations) (line 0) REA i; - Read input into i (line 1) ADD 0 1 c; - Set counter c = 1 (line 2) SUB i 1 m; - Set store input-1 as m (line 3) ADD c 1 c; - Start of loop, c+=1 (line 4) MOD i c t; - Store mod of t=i%c (line 5) SWI t 1 8; - if t < 1 (if non-prime, leave loop) to line 8 (line 6) SWI c m 3; - if c < m continue loop (go to line 3) (line 7) ADD 0 1 r; - set result as truthy value - r = 1 (line 8) OUT r; - output result, r 
\$\endgroup\$
0
\$\begingroup\$

tq, 10 bytes

?-1!xp*p%? 

Explanation

Uses Wilson's theorem to do the prime-checking.

?-1! # Generate all numbers from 2 to input - 1 x, # Preserve this value, prevent it from being printed p*p # Generate all possible combinations of those numbers %? # Does the product of any combination equal to the input? 
\$\endgroup\$
0
0
\$\begingroup\$

C# (Visual C# Interactive Compiler), 62 bytes

int n=int.Parse(ReadLine()),i=2;while(n%i>0&i++<n);Write(n<i); 

Try it online!

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

LCGFuck inputNumeric=true, 138 bytes

(Will turn this into a GitHub repository soon)

1 1im1-1 1 1om2-1 1 1om1 1 <{>>>o+1 1m0<<om <}>>1-1om0>+om <<<++1 1 1 32 1 4 12 69 4 1 1 7 78 2 {>>>+++++c+c+++++c+++<<c<{+}}>>>c++c<c+c+c 

Try it online through this TIO JS interpreter

A brainfuck variant invented by me but uses a list of linear congruential generators (LCGs) instead of cells.

The \$N=1\$ case took too much more bytes to deal with.

Ungolfed and Explanation

1 1 im 1 -1 # Storage for the input, since the input can only be retrieved once 1 1 om 2 -1 # Used to prevent wrapping. Necessary for handling N = 1 case 1 1 om 1 1 # Counts up from 2 to N <{ # While N % counter == 0 (If N == 1 the loop is skipped) >>>o+ # Gets and increments the counter value 1 1 m 0 <<om # Use a new LCG to check N % counter <} # Loop >> 1 -1 om 0 >+om # The output of this LCG will be 2 if N is prime <<<++ # Move two states forward (2 - 2 = 0 if prime) 1 1 1 32 # LCG for space 1 4 12 69 4 # LCG for E, I, M 1 1 7 78 2 # LCG for N, O, P, R, T {>>>+++++c+c+++++c+++<<c<{+}} # Output "NOT " if this LCG is not at state 0 >>>c++c<c+c+c # Output "PRIME" 

Technical Details

(Copied from my obsolete challenge proposal on an LCGFuck interpreter)

An LCG is defined with 5 numbers, like 12345 678 90 -123 45. The last two numbers are optional and default to 0.

LCGFuck has 3 storage variables, the LCG list, the number list and the number memory. The functions are as follows:

  • LCG list: Cyclic list that stores all LCGs created. Every entry is in turn a list of 5 numbers in the order [a, b, c, d, e] as notated in the introduction. It has a pointer that controls which LCG is chosen at the moment, and moves in a cycle through the list.
  • Number list: Ordinary list that stores the numbers for LCG definition. It can store at most 5 numbers.
  • Number memory: A single variable that can be read and written with an input or an LCG output.

LCGFuck has 14 operators, namely:

  • \n (newline): Creates an LCG with the numbers in the order of [a, b, c(, d(, e))] and clears the list if the number list contains 3 or more numbers. No-op if the number list contains no more than 2 numbers.
  • <: Shifts to the previous LCG circularly (back to the last when moving from the first).
  • >: Shifts to the next LCG circularly (back to the first when moving from the last).
  • +: Moves the current LCG to the next state (calculates x' = (a * x + b) mod c)
  • c: Prints the output of the current LCG as a character (with the output as the codepoint).
  • n: Prints the output of the current LCG as a number (with a trailing space)
  • o: Writes the output of the current LCG to number memory
  • i: Reads a value from the input and writes it to number memory. There is two input mode, one reading a character one time (inputNumeric=false), and one reading a number one time (inputNumeric=true)
  • s: Reads the value from number memory and seeds the current LCG with it
  • m: Reads the value from number memory and pushes it to the number list
  • []: Output loop. Executes the loop if the current LCG is non-zero
  • {}: State loop. Executes the loop if the state of the current LCG is non-zero

An integer, optionally with a negative sign at the front, pushes the number to the number list. Any characters other than the newline \n and any of -0123456789[]{}<>+cimnos are no-ops.

The code runs linearly from the first characters, except when loop ends are encountered. Loops can be nested but must be paired accordingly from the innermost loop to the outermost loop.

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

Help, WarDoq!, 1 byte

p 

Outputs 1 if the input is prime (positive or negative, differs from the other solution), 0 otherwise.

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

Add++ -i, 9 bytes

L,dFSbL2= 

Try it online!

Using my favourite approach without any actual primality built-ins

Explained

L,dFSbL2= L, # A lambda called by the -i flag that: dF # pushes all the factors of the input and the input S # uniquify the stack - this is so that `1` is handled correctly bL2= # does the length of the TOS equal 2? 
\$\endgroup\$
0
\$\begingroup\$

flax, 1 byte

V 

What can I say here?

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

Fig, \$3\log_{256}(96)\approx\$ 2.469 bytes

{Lk 

Try it online!

Outputs with reversed boolean - 0 for truthy, any other integer for falsy.

Fig, \$2\log_{256}(96)\approx\$ 1.646 bytes

mp 

Try it online!

Builtin solution.

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

APL(Dyalog Unicode), 9 bytes SBCS

2=0+.=⍳|⊢ 

Try it on APLgolf!

A tacit function which takes a number and returns a boolean.

Explanation

2=0+.=⍳|⊢ 0+.= the count of the number of 0s in | the remainder from ⊢ the argument (divided by) ⍳ the numbers from 1..n 2= equals 2 
\$\endgroup\$
0
\$\begingroup\$

Easyfuck, 35 31 bytes

 D‘ň␗Č_-ZňÚG‰VŕPůňµ2’>Bům×É␗ţV­SHY8 

due to lack of unicode representations for c1 control characters, they have been replaced by their superscripted abbreviations

Decompressed:

"$>!>!>--<[$<%-`(>>+)J$>!>-]>$/~++' 
"$>!>!>--<[$<%-`(>>+)J$>!>-]>$/~++' "$>!>! input an 8bit integer into 1st cell and copy it into 2nd and 3rd >--< set 4th cell to 254 and go back to 3rd [ ] while loop $<%-`(>>+) modulo 2nd cell by 3rd and if 0 increment 4th J$>!>- copy 1st cell to 2nd and decrement 3rd >$/ divide 4th cell by self to get to 0 or 1 ~++' turn 1 into 0 and vice versa, then print 
\$\endgroup\$
0
\$\begingroup\$

AWK, 28 bytes

 {for(j=2;$0%j;j++);}j~$0 

Try it online!

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

Kona, 12 Bytes

{&/x!/:2_!x}

Try it online! (change n with integer)

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

Jalapeño, 1 bytes

Hex-Dump of Bytecode

 0 1 2 3 4 5 6 7 8 9 A B C D E F 0000: 71 

Try it Online!

Jalapeño, 9 bytes

%{₂1‥I₀Σₓ¬≤2 

More interesting as uses no factorising builtins, but uncompetitive.

Explained

%{₂1‥I₀Σₓ¬≤2 % # Input value modulo every element of: {₂1‥I₀ # All the numbers 1 through input Σₓ¬ # Sum, mapped by logical not. (Count factors of n) ≤2 # Is the number of factors <=2 

Hex-Dump of Bytecode

 0 1 2 3 4 5 6 7 8 9 A B C D E F 0000: 54 c6 31 2e 90 ea 58 5e 32 

Try it Online!

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

AGL, 5/14 bytes

  • a programming language i made! check out the link to my github repo.
mp#1= 

Explanation:

mp#1= mp => m: mathematical, p: for 'prime factors', external function # => length of list 1= => equals 1? (primes would only have itself as a prime factor) 

The more built-in way:

.#2>{%0>}%1+$< 

Explanation:

.#2>{%0>}%1+$< .#2> => [2..input) {%0>}% => check if each item has a remainder (item ÷ input) 1+ => append 1 to list so that '$<' won't raise any errors $< => no divisible number? (all() in python) 
\$\endgroup\$
0
\$\begingroup\$

SAKO, 127 116 85 bytes

CZYTAJ:A F=0 *1)F=F+0*MOD(ENT(A),ENT(V)) POWTORZ:V=1(1)A DRUKUJ(1,0):F-2 STOP1 KONIEC 

I used here 0 for a truthy value and any other number for a falsy one.

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

C Preprocessor (cpp), 1260 bytes

#define l()( #define r()) #define V(v...)v #define T(v...)U(v) #define U(x,y,v...)y #define A()j l V()()I #define I()j l V()()A #define Q()r V()()R #define R()r V()()Q #define u(x,v...)T(V(D(A x,K)v D(Q x,K))) #define D(x,y)B(x,y) #define B(x,y)x##y #define AK #define IK #define QK #define RK #define j(v...)a(v) #define a(f,v...)f,f(v) #define w(x,v...)T(W(D(E x,K)v D(Q x,K))) #define W(v...)v #define n(v...)b(v) #define b(f,v...)f,f(v) #define E()n l V()()J #define J()n l V()()E #define EK #define JK #define z(x,v...)T(X(D(F x,K)v D(Q x,K))) #define X(v...)v #define o(v...)d(v) #define d(f,v...)f,f(v) #define F()o l V()()L #define L()o l V()()F #define FK #define LK #define _(x,v...)T(Y(D(G x,K)v D(Q x,K))) #define Y(v...)v #define s(v...)g(v) #define g(f,v...)f,f(v) #define G()s l V()()N #define N()s l V()()G #define GK #define NK #define $(x,v...)T(Z(D(H x,K)v D(Q x,K))) #define Z(v...)v #define t(v...)h(v) #define h(f,v...)f,f(v) #define H()t l V()()O #define O()t l V()()H #define HK #define OK #define p(x,y)y,y() #define q(x)u(x,p,,) #define S(x,y)w(y,q,x) #define e(x,y)S((),S(x,y)S(y,x)) #define M(y,x,k,i)y e(x,i),x,k,k i #define m(x,y)z(x,M,,x,y,y) #define c(r,x,i)r m(x,i),x,i() #define C(x)_(x,c,,x,()) #define P(x)e(C(x),()()) P(()) 

Try it online!

This is not written by me, all I did is to shorten the program by using one-character identifier whenever possible (of course it's not always possible because of the use of the ## operator).

It originally comes from l4m2's answer as a demonstration of the power of the C Preprocessor. If l4m2 intends to post an answer, I will delete mine.

The input is hard coded in the last line P(()). The macro P takes input in unary as a sequence of ()()...()() and outputs () if the input is a prime, or empty if the input isn't.


Note: although the common implementation of loops in the C preprocessor uses something like

#define EXPAND(x) x #define EXP2(x) EXPAND(EXPAND(EXPAND(EXPAND(EXPAND(x))))) #define EXP3(x) EXP2(EXP2(EXP2(EXP2(EXP2(x))))) #define EXP4(x) EXP3(EXP3(EXP3(EXP3(EXP3(x))))) 

which would imply there's only a finite number of expansion passes the program can go through, this does not mean the primality checker program above has any limit.

It is in fact possible with the C preprocessor to do loops bounded by the input size. Consider the following example

#define f() g #define g() f f()()()() 

It results in f. In this example the number of macro expansions is equal to the number of pairs of parentheses provided by the user, not limited by anything built in the program.

With only minor modifications, you can imagine making a macro such that f()()()() expands to ()()()()()()()()f (doubles the number of pairs of parentheses) within one expansion pass. To eliminate the final f, or to implement something like multiplication, requires more complicated machinery however. For this, I recommend reading the original (ungolfed) source code by l4m2.


Background:

The link to l4m2's answer is not viewable to users with less than 10000 reputation because it was decided by a moderator that the answer is invalid. This was because because it does not contain explanation of the Turing-incompleteness of the C preprocessor as required by that question.

The explanation can be found in https://stackoverflow.com/a/37463357/5267751 which links to a paper containing Dave Prosser's algorithm which describes the precise algorithm used by actual preprocessor, the C standard leaves some parts of the operation of the preprocessor unspecified).


I used this script to automate some replacement of identifiers by single-character identifiers (others were done by hand), if someone else intend to try to write golfed programs in the C preprocessor, it could be useful.

\$\endgroup\$
1
9 10 11 12
13

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.