Cops and Robbers: Redacted Primality (Cops' Thread)

This challenge was originally sandboxed by Magic Octopus Urn; I adopted and posted it with his permission.

This is the cops' thread. The robbers' thread is here.

The challenge

• Step One: Write a piece of code (function or full program) which checks for primality.
• Step Two: Remove pieces of your code by replacing characters with the symbol █.
• Step Three: Post the redacted code on the cops thread.
• Step Four: Wait for your code to be cracked and try to crack other's code.

For example, the Groovy code {it.isPrime()} could become {██.is█████()}. (This one would be stupidly easy to crack; also, I know, .isPrime() is not a Groovy method.)

Scoring

You must include your program's score in its submission. The score is defined as the ratio of redacted characters to characters. So if your program had 20 characters and 5 were redacted, your score would be 0.25. The Groovy code above would have a score of 0.5.

Rules

• Your program only needs to handle positive integers. It should output a truthy value if the number is prime and a falsy value otherwise. Please specify in your answer what it outputs.
• Your code may not contain any comments or unnecessary whitespace.
• No hashing or cryptographic obfuscation.
• Your code may be no more than 50% redacted (at least 1/2 the characters must be shown). This means that the highest possible score is 0.5.
• If your answer is not cracked within a week you may mark it safe and edit in the intended crack.

Winning

The winner will be the lowest-scoring uncracked answer within two weeks of posting. In the case of a tie, whichever has the most votes will win. This thread is always open to more submissions, but the winner chosen after two weeks will be permanent.

• What is the domain of the input? (i.e. is it all n >= 1 or all integers?) – Conor O'Brien Feb 3 '18 at 4:50
• @FryAmTheEggman status-completed – MD XF Feb 3 '18 at 5:11
• Again, if a scoring method is easily exploitable, it's broken. – user202729 Feb 3 '18 at 7:33
• Related :) – DLosc Feb 3 '18 at 9:25
• Snippet please? – user202729 Feb 4 '18 at 10:21

Functoid, score = 14 / 223 ≈ 0.062780 [safe]

Y(yG(BK██)(B(S(BS(C(BC(C(BB(B(v
S(CB█)(█C█B>vK  BSBB())█K(BS(S?
>(KZ)(C(C(Bv>██        >   v██<
█)Sg3I)$; @>B(BS(b(C(BBI)Iv>(█g ())I)))I)IBB(C(b(CB(C())))<v)█C I))I))0)))(C(BC(B(BB)(C(BBv>))) ]I))))I))> >)█$;@   >I)(B


Takes input as command-line argument and outputs True (prime) or False, try it online!

Hint (added 4 days after posting):

The first and 4th █ are a red herring: The intended (and most likely every) solution's IP will follow the first line and reach the ? character.

Solution

Y(yG(BKL2)(B(S(BS(C(BC(C(BB(B(v
S(CBO)( C B>vK  BSBB())OK(BS(S?
>(KZ)(C(C(Bv>O)        >   vY <
^)Sg3I)$; @>B(BS(b(C(BBI)Iv>(yg ())I)))I)IBB(C(b(CB(C())))<v)-C I))I))0)))(C(BC(B(BB)(C(BBv>))) ]I))))I))> >)2$;@   >I)(B


Try it online!

Explanation

Due to the randomness that comes from ? it's not possible to flatten the program. Here's the flat program with a question mark where a random expression will be:

Y(yG(BKL2)(B(S(BS(C(BC(C(BB(B(?(yg(KZ)(C(C(BB(BS(b(C(BBI)I))))(C(BC(b(C(BBI)I)))I))(C-))))I))I))0)))(C(BC(B(BB)(C(BBI)(B]I))))I)))2$;@  Full program: Y{trial_division} -- fix-point of {trial_division} 2 -- apply 2 (begin division with 2)$    --  apply argument (work with the supplied input)
;   --  print result as boolean
@  --  terminate program


The {trial_division}:

y                         -- recursive function with two arguments x,y
G                        -- | base predicate: x >= y
(BKL2)                  -- | base function:  BKL2 x y
|  ->             K(L2) x y
|  ->             L2 y
|  ->             2 <= y
{recursive_call}  -- | recursive call


{recursive_call}, taking arguments f (self-reference), x and y (note 0 is the same as False)

  B (S(BS(C(BC(C(BB(B{divides}I))I))0))) (C(BC(B(BB)(C(BBI)(B]I))))I) f x y
->       (C(BC(C(BB(B{divides}I))I))0) x y (BC(B(BB)(C(BBI)(B]I)))) f I x y)
->       (C(BC(C(BB(B{divides}I))I))0) x y (BC(B(BB)(C(BBI)(B]I)))) f I x y)
->            (C(BB(B{divides}I))I) x y 0  (BC(B(BB)(C(BBI)(B]I)))) f I x y)
->            (C(BB(B{divides}I))I) x y 0  (   B(BB)(C(BBI)(B]I))   f x I y)
->                   {divides}      x y 0  (         C(BBI)(B]I)    f x y  )
->              if x divides y then 0 else         C(BBI)(B]I)    f x y
->                                                    f (B]I x)  y
->                                                    f (] x) y
->                                                    f (x+1) y


{divides} is ?(yg(KZ)(C(C(BB(BS(b(C(BBI)I))))(C(BC(b(C(BBI)I)))I))(C-))) where ? is randomly chosen (depending on the random direction) from:

• Y
• S(CBO)(CBO)
• S(SB(KO))(BBSBKO)

These are all equivalent to each other, so {divides} becomes the fix-point of:

y                       -- recursive function with two arguments x,y
g                      -- | base predicate: x > y
(KZ)                  -- | base function:  KZ x y
-- |  ->              0 == y
{recursive_call}  -- | recursive call


{recursive_call} is a pretty obfuscated expression that basically just does f x (y-x)

8086 DOS COM, 87 bytes, score 19/87 ~= 0.2183

1└╣██1█╛ü ¼<█t<< u≈¼<█t█,0|/<██+ô≈ßô☺├δδâ√█|█╞█S█Y╣██9┘t█ë╪1╥≈±○╥t█Aδ∩╞█S█N┤█║S█═!├A
$ This is a COM program; expects number as a command line argument, outputs Y or N. Limit: 65535 because 16 bit processor (sizeof(int) would be 2). Newline is 0x0D 0x0A on this platform. Yes you count 20 █ instead of 19 █. One of them's a real █ and has not been substituted. Muhahaha. The space in position 10 is actually a NUL byte. The symbol for NUL is the same as space in the old VGA font. • Will take forever to crack because there are about 0 relation between assembly (opcode) and machine code. / Is this Code page 437? – user202729 Feb 5 '18 at 5:23 • @user202729: Correct code page. DOS is CP437 unless stated otherwise. – Joshua Feb 5 '18 at 15:40 • Are you using an obscure DOS quirk to read the commandline parameters from$5881 instead of $0081, or is it a mistake? Do I need a true DOS installation? – NieDzejkob Feb 5 '18 at 22:36 • @NieDzejkob: Wait what? I'm pretty sure it reads its command line from DS:0081. I'll double-check the hexdump when I get home but I don't expect to find anything. – Joshua Feb 5 '18 at 23:14 • @Joshua well, the ╛üX at the very beginning is mov si, 0x5881. – NieDzejkob Feb 5 '18 at 23:36 Swift 4, score 26 / 170 ≈ 0.153, safe func p(n:Int)->Bool{func █(_ █:Int,_ █:Int)->Int{var h=(1...l).map{$0██m██
while(m=h.count,m██).1{h=[Int](h[█...])};return m}
return █>██&(█.███).index█j█n██0)>=█0}█=██l}


Try it online!

func p(n:Int)->Bool{func j(_ l:Int,_ k:Int)->Int{var h=(1...l).map{$0},m=l while(m=h.count,m>k).1{h=[Int](h[k...])};return m} return n>1&&(2..<n).index{j(n,$0)>=$0}==nil}  Ungolfed func p(n:Int)->Bool{ func j(_ l:Int,_ k:Int)->Int{ // Modulus function (l mod k) var h=(1...l).map{$0},m=l      //  Create an array h of size l
while(m=h.count,m>k).1{        //  While h has more than k elements:
h=[Int](h[k...])             //   Remove k elements from h
}
return m                       //  Return the length of h (equal to k if l divides k)
}
return n>1&&                     // Test if n > 1
(2..<n).index{j(n, $0)>=$0}==nil //  and no number from 2 to n-1 divides n
}


brainfuck, 37/540 bytes (score: 0.06851) (Cracked by Nitrodon)

>>>>>+>,[>++++++[-<-------->]<+>,]<[-[█<█<]++++++++++<]>[-]>>██[>█>>█>]+[<]<<[<]>█<<+>>[>]█>[>]█+[<]<<[<]>-█>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<█]>]>[>]<[[█]<]<<<<<[<]<<██>>[>]<█[->+<]<█>>[>]<[-[[<]<]++++++++++<]>███>[<<]>[[[>]>████[<]<[-[[<]<]++++++++++<]>[-]>[█<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>███████>[[█]>]<]<[[<]<]<[█]>]>>>[[>]<->>]]>[[>]>]<<[[[█]<]<]<<<[█]<<█>>>[>]█[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.


Try it online!

Prints "prime" if prime, "not prime" if composite. Technically works for arbitrary integers but times out on TIO for numbers above 6000

• Cracked after working on this for several days. – Nitrodon Feb 8 '18 at 13:54

Mathematica, 97 bytes, score 0.2989690722 (Cracked)

f[x_]:=(██ToString███████████████;StringMatchQ[████Infinity,RegularExpression@"█\█\█{█\█+, ███"])


Strings! Regex! Primes?

There is such a thing as a primality checking regex, but that's not whats happening here.

This has been cracked, but the way I intended was quite different, so I won't reveal the intended solution yet.

• – user202729 Feb 3 '18 at 8:23

Jelly, score 0.(142857) (cracked)

25██26█966836897364918299█0█1█65849159233270█02█837903312854349029387313█ị██v


Try it online!

Repost of my other answer, this time with a few more bytes revealed to avoid unintended cheats.

• I can character-wise OR your two answers to get some bytes... probably I won't. – user202729 Feb 3 '18 at 13:57
• @user202729 Uh, something weird happened, I didn't intend to cover more chars... – Erik the Outgolfer Feb 3 '18 at 14:20
• – user202729 Feb 4 '18 at 10:14

Octave, Score: 0.15 (86 bytes)

I revealed several more characters. I thought the winning criterion was highest score, not lowest.

@(x)eval([(str2num(cell2mat([cellstr(reshape('0█1███1█0█0█00',████))])')█'█')','(x)'])


Try it online!

Good luck =)

• Cracked! This was a fun one. – Giuseppe Feb 8 '18 at 20:23

Python 3, 388 bytes, .155, Cracked

Last-minute crack. Yes, this is the Miller-Rabin test.

I suppose probabilistic tests are allowed, uncertainty 2^-100

Well, a great hint in the previous sentence though

Made return value 0 as COMPOSITE and 1 as PROBABLY PRIME

*368 > 388 : Fixed the problem when z<4

import ██████
def f(z):
if z<4:return z>>1
d,s,n,e,c=██z,0,z,0,50
while not ██1:d//=2;s+=1
while n>0:n//=2;e+=1
███████████()
while c>0:
a=0
while a<2or a>z-█:
a,b=0,e
while b>0:a=a*2+██████████████(0,1);b-=█
x,r=███(█,█,z),██s
if ██x and x!=██z:
while r>0:
x,r=███(█,█,z),██r
if not ██x:return 0
elif x==██z:break
else:return 0
c-=█
else:return 1


Solution:

import random
def f(z):
if z<4:return z>>1
d,s,n,e,c=~-z,0,z,0,50
while not d&1:d//=2;s+=1
while n>0:n//=2;e+=1
random.seed()
while c>0:
a=0
while a<2or a>z-1:
a,b=0,e
while b>0:a=a*2+random.randint(0,1);b-=1
x,r=pow(a,d,z),~-s
if ~-x and x!=~-z:
while r>0:
x,r=pow(x,2,z),~-r
if not ~-x:return 0
elif x==~-z:break
else:return 0
c-=1
else:return 1

• I think having long strings like "COMPOSITE" violates the spirit of the rule "Your code may not contain any comments or unnecessary whitespace." – Pavel Feb 3 '18 at 5:29
• @Pavel Edited. Well I don't think the return values are comments or unnecessary whitespace though – Shieru Asakoto Feb 3 '18 at 5:37
• It was technically valid. It was just cheap. – Pavel Feb 3 '18 at 5:41
• I don't think this terminates when z=2. – Nitrodon Feb 3 '18 at 6:28
• @Nitrodon Oops, it didn't terminate when z=3 either. Fixed – Shieru Asakoto Feb 3 '18 at 6:44

095, score 0.20512820512 [Safe]

1id#█#=(DD#█#█{d_█%(█D0█]D}██s]D1.=[1s]


Prints 1 if prime, 0 if composite

Solution:

1id#2#=(DD#2#-{d_.%(rD0R]D}drs]D1.=[1s]


Node JavaScript, score: 0.4

Here's where it works. Full program that takes input from first command line argument, and outputs to stdout.

Hopefully, a not-so-difficult solution to start this off.

Using this snippet to calculate score.

require███████████2<<2██>n█████rin█(b████████x)█████(9211█6830)██(a,c)=>a[c[0]██████████(c)]███████);d=███+n;q=████27775██9564,[502█59,█6])[█]);a=██q>0████r(n=q█a█&█-q-██)a██n%q?██0██(137152█8270,22288)(a)


Jelly, score 0.(142857)

25██26█9668368973649182992051██5849159233270202█837903312854349029387313█████


Try it online!

Takes a command-line argument.

False = 0
True = 1

• – user202729 Feb 3 '18 at 13:28
• @user202729 Eh, I should've revealed more, I'll repost. But I can't add that it was cracked until you post on the robbers thread. :P – Erik the Outgolfer Feb 3 '18 at 13:31

JavaScript, 103 bytes, score 0.1923

x=>{if(x<4)return(!0);for(y=x>>>Math.log10(p=████;--y-1;(p=x/y%1)████if(██&&(███))break████return(███)}

Returns a boolean.

Unintended crack

Javascript, score 0.1894093686354379

let t=[2,3,3,3,3,3,3,5,7,5,7,5,7,7,11,12,13,11,13,13,1,2,17,13,2,3,17,19,23,29,19,19,41,23,23,29,23,"","",29,7,31,31,524,31,37,33,34,41]; function r(a, b) {█████████████████████████████████████████████████████████████};function l(t){let a=0;let b=[];while(true){b.push(t[a]);█████████████;if(!t[a]){return█████};function p(v) {let i=0;let a=r(2,v██);for (i in a){if(v%(█████████a█i██)==0){return false;}};return true;};function f(v){if(l(t).indexOf(v)!=-1){return true;}else{return p(v)};};


Good luck. :p

call f with the prime you want to check.

><>, score 0.096, cracked by Jo King

:1@v>~~:?1n;█$-1<█?=2:}*{█@:$@:


Intended crack:

:1@v>~~:?1n;
$-1<^?=2:}*{%@:$@:

• I don't know ><> really well, but isn't the first v an unconditional infinite loop? – NieDzejkob Feb 5 '18 at 22:31
• @NieDzejkob If you run the program as it is, yes, it will loop forever. – Esolanging Fruit Feb 5 '18 at 22:44
• oh, I see it now... – NieDzejkob Feb 5 '18 at 22:57
• Cracked – Jo King Feb 6 '18 at 2:06

Brain-Flak, Score: 35/134 = 0.2612 (cracked!)

(({████){██[████)█>(({}))<>}<>{}███{}((██({}))█████{}]██)({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})██[██()██(()█[()]██{}██}{}<>{})

Returns 1 for prime, 0 for composite.

This is a very hard language to try this challenge in, as the formatting is so restricted that it takes effort not to make it obvious what the missing character is.

This is a very hard language to solve this challenge in, as it is ridiculously hard to read.

Java 1.4+, 24/145 (0.16551724137)

class X{public static void main(String[]args){System.out.println(new String(████████[Integer.parseInt(args[0])]).matches("█████████████")?███);}}


Try it online!

Weirdest way I've seen to prime check in Java by far lol.

• cracked – ovs Feb 8 '18 at 14:33

Japt, 19 bytes, 0.315789... score, Safe

I don't know if I obscured more of this than I needed to, costing myself a better score.

█h8575¥█
█UâÊ█Ê█ █2


View solution (Explanation coming soon)

C, 34/76 = 0.447368, Safe

int p(int n){int r███████2;██r███r++)███+███n;████&███r));return███████n██;}


Having this many blanks means that I will be much more likely to get an unintended crack than the intended one.

Solution:

int p(int n){int r=1,e=n%2;for(;(r++)*(r++)<n;e=e&&(n%r));return e?n>1:n<3;}

explanation:

e holds a boolean value of whether or not the number is not prime (with a few special case exceptions). r iterates through the odd numbers less than or equal to the square root of n. return e?n>1:n<3; handles the special cases when n is 1 or 2.

M, score: 4/22 = .1818..., cracked by Dennis

███“;;█»VOḣ2S⁵++3Ọ;”Pv


This may end up with an unintended crack, we'll have to see. It did.

Dennis' solutions is

ÆPø“;;“»VOḣ2S⁵++3Ọ;”Pv


Try it online!

I will leave my solution hidden for someone to crack. My hint to Dennis on his robber submission was the word "zoo".

• @user202729 I think you may be able to crack this – dylnan Feb 20 '18 at 16:55
• Cracked. – Dennis Feb 21 '18 at 18:17

C, 66 bytes, 29 redacted, score 0.439

i;p(n){█████2███████ 0███████2;███;███)if(████)return 0;return 1;}


Just a simple C submission; I'll see how long this one takes before I post a really evil one.

• Are you sure that the last block is supposed to be 4 characters long? – NieDzejkob Feb 5 '18 at 17:02
• @NieDzejkob Yes. – MD XF Feb 5 '18 at 18:27

Pyth, score: ~0.(461538) (13 bytes) (Cracked)

█]█Q ██Q{█M█P


Try to crack it here!

• Cracked. – MD XF Feb 4 '18 at 2:49
• I knew it was easily brute forceable... – Mr. Xcoder Feb 4 '18 at 6:02

sh + coreutils, score 19 / 143 ~= 0.1328

cracked

e█ec█s█ █c "██████WyAkKHNoIC1jICJg█WNobyBabUZqZEc5eWZIUnlJQ2█2SnlBblhHNG5m██JoYVd3Z0t6SjhkMk1nTFhjSyB8YmFzZTY0IC1kYCIpIC1lcSAxIF0K█b█se6███d"


TIO

• @MDXF: Base64 is encoding, not encryption. There's no key to crack. – Joshua Feb 4 '18 at 2:21
• Can you include a TIO link? (probably bash) – user202729 Feb 4 '18 at 10:19
• Cracked (3 hours ago). – user202729 Feb 5 '18 at 15:46

Brain-Flak, score 29 / 140 = 0.207

({}██()██<>){██({}[()])██{}{}███({<({}[()])><>({})<>}{}██████{}██){(({})){({}[()])<>}{}}<>([{}()]{}<>{})<>}(<>██{}({}████)((){[()]██{}██}{})

Try it online!

Outputs 1 for prime and 0 for non-prime.

Tampio (imperative), score: 24/51 = 0.5

Luku on alkuluku,jos ████████████e███████ on █████.


This is an obvious solution, I hope no one here understands Finnish.

Tampio (imperative), score: 26/223 = 0.11659...

Luvun kokonaislukuarvot ovat riippuen siitä,onko se yksi,joko listan,jonka alkioita ovat yksi █████████████████████,alkiot tai █████ liitettynä sen alkutekijöihin.Luku on alkuluku,jos sen kokonaislukuarvojen summa on nolla.


Pyt, score: 0.288288... [Safe]

Đ2⇹█ŘĐĐŁ███⇹ʀĐ↔Đ5Ș↔⇹██=█ŕĐ↔Đ5Ș↔Đř█⇹█████↔Đ4Ș5Ș⇹██⇹3Ș°04Ș↔█3ȘĐŁ█3Ș05Ș↔█⇹04Ș0↔⇹██=█ŕ↔ŕĐĐŁ██↔██↔ŕŕŕŕ█↔████↔ŕŕŕ██¬¬


Outputs "True" if prime, "False" if not

Forgot to mention that it is a probabilistic test.

Solution:

Đ2⇹⁻ŘĐĐŁ₂⁻⇹ʀĐ↔Đ5Ș↔⇹Ǥ1=?ŕĐ↔Đ5Ș↔Đř²⇹%∈2*⁻↔Đ4Ș5Ș⇹⁻₂⇹3Ș°04Ș↔+3ȘĐŁ⁺3Ș05Ș↔+⇹04Ș0↔⇹%+=?ŕ↔ŕĐĐŁ⁺⁺↔ł:↔ŕŕŕŕ;↔⁺⁻±?↔ŕŕŕ:;¬¬


This implements the Solovay-Strassen primality test.

Try it online here!

Ruby, 27/73 = 0.369863

def p n;███████(██n.times████a[2..-1].map{|s|█.██n████s}██.█*█|██})█);end


This should be fun.

Python 3, score: 0.386363, cracked

p=lambda x,i=2:█████or(x%i and ████████)████


Going for the really low hanging fruit at first. I'll come up with a cheeky answer soon.

user71546 made it "work" with

p=lambda x,i=2:i>=x or(x%i and p(x,i+1))or 0


...but that was unintended. Original code was

p=lambda x,i=2:i>x/2or(x%i and p(x,i+1))or 0


Neither work for x<2, turns out. Oops.

• Cracked? Not working when x<2 though. – Shieru Asakoto Feb 20 '18 at 4:19

JavaScript (ES7), 297 bytes, 103 redacted, .347

M=(N,X=N,F=(n,a=█████)=>a>1e-20?█████+F(n,█████████):1,G=(n,a=█████)=>a>1e-20?█████+G(n,███████):n==2?0:G(n-1),H=(n,a=█████)=>a>1e-20?█████-H(n,███████):0,I=n=>████████I(████),J=n=>I(n)*████+H(█████████-1),K=(n,l=n|0)=>(n-l>=.5)+l,L=(a,b)=>██████████(a)+█(b)████,Z=L(--N,N)██)=>L(Z,████M(N,X)██)██


My previous Python answer was too straightforward, so here's an evil one ;)

The logic behind is straightforward though.