| Bytes | Lang | Time | Link |
|---|---|---|---|
| 122 | JavaScript Node.js | 240808T061927Z | Andrew B |
| 134 | Haskell | 220625T143014Z | matteo_c |
| 010 | Husk | 210823T113708Z | Dominic |
| 147 | BBC BASIC | 220617T124522Z | Alice F |
| 097 | C gcc | 210711T105300Z | Noodle9 |
| 014 | 05AB1E | 210711T080444Z | hyper-ne |
| 009 | 05AB1E | 210823T095349Z | Kevin Cr |
| 223 | brainfuck | 210713T201233Z | Nitrodon |
| 019 | APL Dyalog Extended | 210711T072344Z | Adá |
| 014 | Vyxal j | 210712T071049Z | emanresu |
| 011 | Japt R | 210711T152135Z | Shaggy |
| 070 | Python 2 | 210711T065054Z | dingledo |
| 110 | Excel | 210711T170636Z | Axuary |
| nan | J | 210711T064944Z | Jonah |
| 008 | Jelly | 210711T150403Z | lynn |
| 011 | Jelly | 210711T062406Z | hyper-ne |
| 078 | JavaScript ES7 | 210711T101345Z | Arnauld |
| 073 | Perl 5 | 210711T111447Z | Kjetil S |
| 076 | Julia 1.0 | 210711T114932Z | MarcMush |
| 025 | Charcoal | 210711T101630Z | Neil |
| 060 | Retina 0.8.2 | 210711T095538Z | Neil |
| 075 | Factor | 210711T090740Z | chunes |
| 016 | Vyxal j | 210711T062520Z | Wasif |
| 098 | Python 3.8 prerelease | 210711T063719Z | Wasif |
| 1249 | brainfuck | 210711T065834Z | hyper-ne |
| 019 | Pyth | 210711T065134Z | Leaky Nu |
| 105 | Python 3 | 210711T064516Z | hyper-ne |
| 013 | Jelly | 210711T062750Z | Leaky Nu |
JavaScript (Node.js), 122 bytes
_=>{q=(x,p=x-1)=>x-1?(p>1)?((x%p)&&q(x,p-1)):1:0
for(s='',k=i=1;i<41;i++,s+=`
`)for(j=1;j<=i;j++)s+='-|'[q(k++)]
return s}
Haskell, 134 bytes
[]#n=[]
a#n=take n a:drop n a#(n+1)
main=putStrLn$foldl(\a b->a++'\n':b)"-"$["|-"!!fromEnum(0`elem`map(x`mod`)[2..x-1])|x<-[2..820]]#2
Husk, 10 bytes
Cḣ40mȯc¬ṗN
Try it online! (but you won't be able to easily view the output of non-printable characters) or Try this online instead to see the output switched to 0 and 1 characters.
Derived independently to Kevin Cruijssen's 05AB1E answer, but it turns-out to use almost exactly the same approach... Unfortunately Husk's prime-checker ṗ returns the index in the list of primes, rather than 1 or 0, costing one extra byte.
mȯ # map over
N # the infinite list of integers:
c # character corresponding to
¬ # logical NOT of
ṗ # index in list of primes;
C # now cut into substrings
ḣ40 # with lengths of 1..40
BBC BASIC, 147 bytes
L=820
T=1
C=0
F.N=1TOL
IFFNF(N-1)^2MODN=0TH.P."-";:EL.P."|";:ENDIF
C+=1
IFC=T TH.
T+=1
C=0
P.';
ENDIF
N.N
END
DEF FNF(A)IFA=1ORA=0TH.=1
=A*FNF(A-1)
I won't lie, this is definitely not the best algorithm, but I did at least golf it down as much as I could.
C (gcc), 101 \$\cdots\$ 98 97 bytes
p;r;d;f(n){for(n=r=0;++r<41;puts(""))for(;r*-~r>2*n;printf(L"-|"+p))for(p=d=n++;d>1;p=n%d--&&p);}
Saved a byte (and got below \$100\$!) thanks to ceilingcat!!!
Saved another byte thanks to Shaggy!!!
Saved yet another byte from Juan Ignacio Díaz!!!
05AB1E, 14 bytes
A820ÅTüŸ€¦pèJ»
-1 byte thanks to ovs
A820ÅT>üŸ€¦pèJ» Full Program
A Push "abc...xyz"
820 Push 820
ÅT Pop 820; Push [0, 1, 3, 6, 10, ...] (triangular numbers)
üŸ Pairwise range; get [[0, 1], [1, 2, 3], [3, 4, 5, 6], ...]
€¦ For each sublist, remove the first element
p Primality; get the 2D list of 1s and 0s
è Index into "abc...xyz"
J Join each row into a string
» Join the result into a multiline string
05AB1E, 9 bytes
∞40L£pçJ»
Uses unprintables \0 and \1 instead of - and |.
Explanation:
∞ # Push an infinite positive list: [1,2,3,...]
40L # Push list [1,2,3,...,38,39,40]
£ # Split the first list into parts with the lengths of the second list
# (removes any unused trailing items): [[1],[2,3],[4,5,6],...]
p # Check for each integer whether it's a prime (1 if it's a prime; 0 otherwise)
ç # Convert it to a character with this codepoint: \0 and \1
J # Join each inner list together to a single string
» # And join those strings by newlines
# (after which the result is output implicitly)
brainfuck, 223 bytes
-[>-<-----]>[>++++[<[[->>>+<<<]>]<+>>>-]<-]>>-[--->+<]>[<<<<<[>+[[>]>]>>[->+>]>[[-<+>]<<[-<<<[[<]<]>>[-]-[[>]>]>]+>>>>]<<<<<<<[[<]<]<]>+[->>>]<[-<+>]<-]<<<+<+<--[>[[[-<<<+>>>]>]<<-[---<+>]<.[-]<+<-]++++++++++.[-]>[-<+>]+<<]
Uses trial division up to 86 to determine every prime up to 820. Outputs T for - and V for |.
Populate list of 820 numbers not yet considered composite
-[>-<-----]>[>++++[<[[->>>+<<<]>]<+>>>-]<-]
tape is 1 0 0 1 0 0 1 etc 1 0 0 1 0 (0)
Create 85 to test visibility by up to N=86 (which is high enough and short to create)
>>-[--->+<]>
working tape will be 1 0 0 1 0 0 1 etc 1 1 0 1 1 0 (0 or 1) x y 0 0
with x plus y = 85 in first iteration
For all numbers from 85 down to 1: (N is this number plus one)
[
For all numbers to sieve:
<<<<<[
Mark number seen
>+
Decrement x and increment y if x is nonzero
[[>]>]>>[->+>]
Otherwise, the last number was divisible by N
>[
Move y back to x
[-<+>]
If this isn't the first time we've seen a multiple of N:
<<[
Mark number composite
-<<<[[<]<]>>[-]-[[>]>]>
Mark that we've seen a multiple of N
]+>>>>
]
Go to next number (for loop termination condition)
<<<<<<<[[<]<]<
Repeat until all 820 numbers checked
]
Remove all "seen" markings and "seen multiple of N"
>+[->>>]
Copy whatever was left of y back to x and decrement
<[-<+>]<-
]
Now all numbers have been checked and marked composite if applicable
We are 5 cells right of first number (1) now
Set up counters for triangle shape (x=1 for first row; and y=1 so y is always nonzero)
<<<+<+
Mark 1 as nonprime
<--
For each number
[
While x is nonzero
>[
Move x and y left three cells
[[-<<<+>>>]>]
Add 85 to primality indicator to output ASCII
<<-[---<+>]
Output and remove number
<.[-]
Increment y and decrement x
<+<-
]
Output newline
++++++++++.[-]
Copy y to x (now one more than it was; restore y=1)
>[-<+>]+
<<]
APL (Dyalog Extended), 23 19 bytes
‒1 thanks to Razetime.
Full program.
↑⎕UCS{1⍭⍳≢⍵}⍢∊,\⍳40
⍳40 indices 1 through 40
,\ prefixes of that; [1,[1,2],[1,2,3],…,39,40]]
{…}⍢∊ apply the following anonymous lambda to the enlisted (flattened) data:
⍵ the argument; [1,1,2,1,2,3,…,39,40]
≢ the length of that; 820
1⍭indicate which elements are prime;[0,1,1,0,1,0,…,0,0]
⎕UCS convert to characters in the Universal Character Set; [\x00,\x01,\x01,\x00,\x01,\x00,…,\x00,\x00]
↑ mix the list of strings into a matrix, padding with spaces as necessary to make it rectangular; ["\x00 …","\x01\x01 …",…\x00\x00\x00\x00\x00\x00…\x00\x00"]
Vyxal j, 11 14 bytes
40ƛɽ÷Ṡnɾ+æ₁+Cṅ
I'm posting this because it's significantly shorter than the other one. I didn't realise the non-number rule, but still fairly short.
40ƛ # Map 1...40 to...
ɽ÷Ṡ # Sum of 1...n-1
nɾ+ # Added to each of 1...n, this produces the correct indices
æ # Is prime (vectorised)
₁+C # Add 100 and get the corresponding character (d or e)
ṅ # Joined
# (j flag) join by newlines
Japt -R, 13 11 bytes
Uses f for composites and t for primes.
#(õ_ç Ëî°Tj
#(õ_ç Ëî°Tj
#( :40
õ :Range [1,40]
_ :Map each Z
ç : Z spaces (could be any character)
Ë : Map each character
î : Slice the following to length (always 1)
°T : Prefix increment T (initially 0)
j : Is prime? (Returns a Boolean which gets coerced to a string by î)
:Implicit output joined with newlines
Japt -R, 13 bytes
Preserving this version as I quite liked the ú trick. Uses q for qomposites(!) and p for primes.
40õ_ç¬Ëú²g°Tj
40õ_ç¬Ëú²g°Tj
40õ_ :Map each Z in the range [1,40]
ç : Repeat to that length
¬ : "q"
Ë : Map each character
ú : Left pad
² : With "p" to length 2
g : Get the character at index
°Tj : As above, with the Boolean this time coerced to 0 or 1
:Implicit output joined with newlines
Python 2, 70 bytes
p=n=i=1
while i<41:s='';exec"s+='-|'[p%n];p*=n*n;n+=1;"*i;i+=1;print s
The
|s mark the position of primes.
The idea here, as with many prime-related tasks in Python, is to use Wilson's theorem. Essentially, \$ (n - 1)!^2 \bmod n \$ will equal 1 if \$ n \$ is prime, and 0 if it is not. @xnor gives a more in-depth explanation here if you're interested.
Excel, 110 bytes
=LET(a,SEQUENCE(820),CONCAT(IF(MMULT((MOD(a,TRANSPOSE(a))=0)*1,a^0)=2,"|","-")&IF(MOD(SQRT(8*a+1),1),"","
")))
=LET(a,SEQUENCE(820), a = (1..820)
CONCAT( concatenate the following
IF(MMULT((MOD(a,TRANSPOSE(a))=0)*1,a^0)=2,"|","-")& if a is prime (has 2 factors) then "|" else "-"
IF(MOD(SQRT(8*a+1),1),""," if a is triangular (8a+1 is a perfect square) then add a line feed
")))
Jelly, 8 bytes
ØYxJĠẒỌY
ØY The string "BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz"
xJ Repeat "B" once, "C" twice, "D" thrice... "z" 40 times.
Ġ Group indices by values: [[1], [2,3], [4,5,6], …, […820]]
↑B ↑C ↑D ↑z
Ẓ Is prime?
Ọ Translate 0,1 into "\x00","\x01"
Y Join lines
Jelly, 11 bytes
40RRȷR¤ṁẒỌY
The
|s are at prime indexes
I figured out the pattern by smash-printing the rows into one flat string and realizing that the distribution looked familiar :P I had another idea to use base conversion but I decided to flatten the string first and then noticed.
Leaky Nun has two tricks in their answer - firstly, that you can take the range up to 1000 (which is shorter) since mold will discard extras, and secondly, I didn't notice other characters were allowed, so the digraph nilad ØA is shorter. Jonathan Allan also noticed that we can just use chr and output the unprintables 0x00 and 0x01, so thanks to both of them for the byte saves. Please go upvote Leaky Nun's answer as well.
40RRȷR¤ṁẒỌY Main Link (Niladic)
40 Start at 40
R Range; [1, 2, ..., 40]
R Range; [[1], [1, 2], [1, 2, 3], ...]
ṁ Mold; to the shape of [[1], [1, 2], [1, 2, 3], ...], reshape
ȷR¤ Range of 1000 ([1, 2, 3, ..., 1000]) - extra elements are discarded
Ẓ x => isprime(x)
Ọ chr
Y Join on newlines
There are a couple of ways to go about this idea - you can swap which list you generate first, you can index into a multitude of other strings, you can prime-check before or after molding since it vectorizes and thus doesn't really care what shape it is, etc.
JavaScript (ES7), 78 bytes
A recursive function going from \$k=820\$ to \$k=1\$ and testing whether \$\sqrt{8k+1}\$ is an integer to detect triangular numbers and figure out where line-feeds have to be inserted.
f=(k=820)=>k?f(k-1)+'-|'[(g=n=>n%--d?g(n):+!~-d)(d=k)]+[`
`[(1+8*k)**.5%1]]:''
Perl 5, 73 bytes
say join($/,map$"x$_,1..40)=~s/./!$n++|(grep$n%$_==0,2..$n-1)?"-":"|"/ger
say # print triangle string, say adds a \n at the end
join($/,map$"x$_,1..40) =~ # make multi-line triangle
# of $" (spaces) and $/ (newlines)
s/ / # replace spaces
!$p++ # count position, ! prevent first from becoming "|"
| # bit-or instead of || or 'or'
(grep $p%$_==0, 2..$p-1) # check if $p position is a prime
? "-" # replace non-prime $p with -
: "|" # replace prime $p with |
/ger # g=replace all, e=eval, r=return triangle to say
Julia 1.0, 76 bytes
f(y=1)=1:40 .|>i->print.(y:(y+=i).|>j->"
-|"[j==y||2+(2==sum(j.%(1:j).<1))])
Charcoal, 25 bytes
G↓→⁴⁰ψ¤⭆⁸²⁰§-|﹪ΠE⊕ι∨λ±¹⊕ι
Try it online! Link is to verbose version of code. Explanation:
G↓→⁴⁰ψ
Draw an empty triangle of side 40. (Unfortunately Charcoal doesn't have a 1-byte shortcut for a triangle in this orientation.) The y variable is the null byte, which has a special meaning for the Fill function, in that it counts as a fillable area.
¤⭆⁸²⁰§-|﹪ΠE⊕ι∨λ±¹⊕ι
Calculate the first 820 factorials, negate them, reduce them modulo the incremented index, and index the results into the string -|. Use this to fill the triangle drawn above. (Charcoal's Fill works by painting the string across the region to be filled, rather than repeating it horizontally and vertically. See @ASCII-only's answer to Bake a slice of Pi for another example of how it works.)
Retina 0.8.2, 60 bytes
820$*|
.(?<=^\1+(..+))
-
^.
-¶
+`(.)+¶(?=.+$)(?<-1>.)+.
$&¶
Try it online! Explanation:
820$*|
Insert 820 |s. (820 = 40 × 41 ÷ 2)
.(?<=^\1+(..+))
-
Change most of them to -s appropriately.
^.
-¶
Change the first one too, and start building the triangle.
+`(.)+¶(?=.+$)(?<-1>.)+.
$&¶
Build up each row of the triangle to be one character longer than the previous.
Factor, 75 bytes
820 [1,b] [ prime? 43 45 ? ] ""map-as 40 [1,b] [ cut swap print ] each drop
820 [1,b]Create a range from 1 to 820 inclusive. 820 is the number of elements in the triangle sans newlines.[ prime? 43 45 ? ] ""map-asCreate a flat version of the triangle as a string, where43is the code point for+and45is the code point for-.|'s code point has 3 digits so I changed this (as it is allowed by the rules).40 [1,b] [ cut swap print ] each dropCut the sequence in two at ever-increasing indices, printing each line after it is cut off from the main sequence.
Vyxal j, 16 bytes
40ɾƛʁƛkA¥›:£æi;ṅ
-1 byte thanks to @hyper-neutrino
Replace all those characters with numbers from 1, 2 and so on. The |'s are at prime indices. So then it's easy.
(pxeger spoiled it, though I came to it independently)
Python 3.8 (pre-release), 98 bytes
r=range
for _ in r(n:=1,41):s="";exec("s+='-|'[all(n%y for y in r(2,n))and n>1];n+=1;"*_);print(s)
-6 bytes thanks to @hyper-neutrino and @pxeger
brainfuck, 1249 bytes
++++++++++[>+>++++>++++++<<<-]>>.<.>>..<<.>.>.<.<.>>.<...<.>>.<.>.<..<.>.>.<.>.<..<.>.>.<.....<.>>.<.>.<.....<.>>.<...>.<.>.<..<.>.>.<.....>.<..<.>...>.<.>.<.....<.>>.<...>.<.>.<.....<.>>.<...>.<.....>.<..<.>.....>.<...>.<.>.<..<.>.>.<.>.<...>.<.......<.>......>.<...>.<.....<.>>.<.>.<.........>.<.>.<..<.>...>.<.....>.<...>.<....<.>.>.<.....>.<.>.<.........<.>>.<.>.<...>.<.>.<...........<.>>.<...........>.<...>.<.>.<..<.>.>.<.....>.<.>.<.........>.<..<.>...>.<.....>.<.....>.<.>.<.....<.>>.<...>.<.>.<.........>.<.......<.>......>.<...>.<.>.<...>.<........<.>.....>.<.....>.<.........>.<.>.<..<.>.>.<.....>.<.......>.<.....>.<.....<.>>.<...>.<.....>.<.......>.<...>.<.....<.>..>.<.........>.<.>.<.........>.<.>.<..<.>...>.<...>.<.....>.<.......>.<...>.<.>.<..<.>.>.<...........>.<.......>.<...>.<.....<.>..>.<...>.<.....>.<...........>.<.>.<.....<.>............>.<.....>.<.........>.<....<.>.>.<.....>.<.>.<.....>.<.........>.<.....>.<..<.>...>.<.>.<.....>.<.....>.<...>.<.>.<...........<.>>.<.........>.<.>.<...>.<.....>.<.....>.<.>.<.....<.>......>.<...>.<.....>.<.......>.<.........>.<..<.>.....>.<.........>.<.......>.<.....>.<.....>.<..<.>.>.<.......>.<.....>.<...>.<.......>.<...>.<.......<.>......>.<.........>.<...........>.<.>.<.........
Kind of boring; just a hardcoded solution. I'm trying to create a solution that computes it with the prime relation, but I'm not that experienced in brainfuck and also I'll need to find an interpreter that goes up to 820 if I don't want excessive pain and suffering.
Python 3, 105 bytes
r=range
for i in r(1,41):
for j in r(i):n=i*~-i//2-~j;print(end="-|"[all(n%y for y in r(2,n))])
print()
One byte longer than wasif's, but no exec trick used here.
Jelly, 13 bytes
ȷRẒṁ40RR¤ịØAY
Uses Z and A instead of - and |.
This is basically the same answer as @hyper-neutrino's answer, which was published 3 minutes before mine, but our answers arose independently.