Integer triangles with perimeter less than n
Jelly, 28 27 25 23 bytes
pḶŒcÆḊÐfḅı;I$€AṢ€QS€<¹S
Try it online!
How it works
pḶŒcÆḊÐfḅı;I$€AṢ€QS€<¹S Main link. Argument: n
Ḷ Unlength; yield [0,...,n-1].
p Take the Cartesian product of [1,...,n] and [0,...,n-1].
Œc Take all combinations of the resulting pairs.
The result are of the form [[a, b], [c, d]].
ÆḊÐf Filter by determinant; keep only pairs of pairs for which
the determinant (ad - bc) is non-zero, i.e., those such
that [0, 0], [a, b], and [c, d] are not collinear.
ḅı Convert each pair [a, b] from base i (imaginary unit) to
integer, mapping it to ai + b.
€ For each pair of complex numbers [p, q]:
;I$ append their forward differences, yielding [p, q, p-q].
A Take the absolute value of each resulting complex number.
Ṣ€ Sort each resulting array of side lengths.
Q Unique; remove duplicates.
S€ Take the sum of each array, computing the perimeters.
<¹ Compare them with n.
S Take the sum of the resulting Booleans.
Jelly, 38 33 bytes
-1 thanks to Erik the Outgolfer (invert SP¬+÷/E$
by using SẠ>÷/E$
and use ÇÐf
rather than ÇÐḟ
)
-1 thanks to Mr. Xcoder (no need to flatten prior to the sort)
-2 thanks to Mr. Xcoder (S<¥Ðf³L
-> S€<³S
)
-1 stealing a trick from an earlier revision of Dennis's answer (ṗ2’Œc
-> p`⁺’
- more redundant cases but golfier!)
SẠ>÷/E$
p`⁺’ÇÐfµ_/ṭ⁸²S€Ṣµ€Q½S€<³S
A full program taking an integer and printing the result.
Try it online! (too slow to complete test cases 20+ in under 60s)
How?
SẠ>÷/E$ - Link 1, straightLineFromOrigin?: coordinates i.e. [[a,b],[c,d]]
S - sum [a+c,b+d]
Ạ - all? (0 if either of a+c or b+d are 0 otherwise 1) all([a+c,b+d])
$ - last two links as a monad:
÷/ - reduce by division [a÷c,b÷d]
E - all equal? (i.e. 1 if on a non-axial straight line) a÷c==b÷d
> - greater than? (i.e. 1 if not on any line, 0 otherwise) all([a+c,b+d])>(a÷c==b÷d)
p`⁺’ÇÐḟµ_/ṭ⁸²S€Ṣµ€Q½S€<³S - Main link: integer, n
p` - Cartesian product of implicit range(n) with itself
⁺ - repeat (Cartesian product of that result with itself)
’ - decrement (vectorises)
- - i.e. all non-negative lattice point pairs up to x,y=n-1
Ðf - filter keep only if:
Ç - call last link (1) as a monad
µ µ€ - monadic chain for €ach:
_/ - reduce with subtraction i.e. [a-c,b-d]
⁸ - chain's left argument, [[a,b],[c,d]]
ṭ - tack [[a,b],[c,d],[c-a,d-b]]
² - square (vectorises) [[a²,b²],[c²,d²],[(c-a)²,(d-b)²]]
S€ - sum €ach [[a²+b²],[c²+d²],[(c-a)²+(d-b)²]]
- - i.e. the squares of the triangle's edge lengths
Ṣ - sort
Q - de-duplicate (get one of each congruent set of triangles)
½ - square root (vectorises) - get sides from squares of sides
S€ - sum €ach
³ - program's 3rd argument, n
< - less than?
S - sum (number of such triangles)
- implicit print
JavaScript (ES7), 157 bytes
f=(n,i=n**4,o={})=>i--&&([p,P,q,Q]=[0,1,2,3].map(k=>i/n**k%n|0),!o[k=[a=(H=Math.hypot)(p,P),b=H(p-q,P-Q),c=H(q,Q)].sort()]&a+b+c<n&&(o[k]=P*q!=p*Q))+f(n,i,o)
Test cases
Only small values can be computed with the default stack size of most JS engines.
f=(n,i=n**4,o={})=>i--&&([p,P,q,Q]=[0,1,2,3].map(k=>i/n**k%n|0),!o[k=[a=(H=Math.hypot)(p,P),b=H(p-q,P-Q),c=H(q,Q)].sort()]&a+b+c<n&&(o[k]=P*q!=p*Q))+f(n,i,o)
;[
1, // 0
2, // 0
3, // 0
4, // 1
5, // 3
6, // 5
7, // 11
8, // 18
9 // 29
]
.forEach(n => console.log('a(' + n + ') = ' + f(n)))
Non-recursive version, 165 bytes
n=>[...Array(n**4)].reduce((x,_,i,o)=>x+=!o[[p,P,q,Q]=[0,1,2,3].map(k=>i/n**k%n|0),k=[a=(H=Math.hypot)(p,P),b=H(p-q,P-Q),c=H(q,Q)].sort()]&(o[k]=P*q!=p*Q)&a+b+c<n,0)
Test cases
This version also works for a(30) and a(40), but that would take too much time for the snippet.
let f =
n=>[...Array(n**4)].reduce((x,_,i,o)=>x+=!o[[p,P,q,Q]=[0,1,2,3].map(k=>i/n**k%n|0),k=[a=(H=Math.hypot)(p,P),b=H(p-q,P-Q),c=H(q,Q)].sort()]&(o[k]=P*q!=p*Q)&a+b+c<n,0)
;[
1, // 0
2, // 0
3, // 0
4, // 1
5, // 3
6, // 5
7, // 11
8, // 18
9, // 29
10, // 44
12, // 94
20 // 738
]
.forEach(n => console.log('a(' + n + ') = ' + f(n)))