79 lines
2.3 KiB
Factor
79 lines
2.3 KiB
Factor
! Copyright (c) 2012 Anonymous
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: accessors arrays formatting kernel literals math
|
|
math.functions math.matrices math.ranges sequences ;
|
|
IN: rosetta-code.pythagorean-triples
|
|
|
|
! http://rosettacode.org/wiki/Pythagorean_triples
|
|
|
|
! A Pythagorean triple is defined as three positive integers
|
|
! (a,b,c) where a < b < c, and a2 + b2 = c2. They are called
|
|
! primitive triples if a,b,c are coprime, that is, if their
|
|
! pairwise greatest common divisors gcd(a,b) = gcd(a,c) = gcd(b,c)
|
|
! = 1. Because of their relationship through the Pythagorean
|
|
! theorem, a, b, and c are coprime if a and b are coprime
|
|
! (gcd(a,b) = 1). Each triple forms the length of the sides of a
|
|
! right triangle, whose perimeter is P = a + b + c.
|
|
|
|
! Task
|
|
|
|
! The task is to determine how many Pythagorean triples there
|
|
! are with a perimeter no larger than 100 and the number of these
|
|
! that are primitive.
|
|
|
|
! Extra credit: Deal with large values. Can your program handle
|
|
! a max perimeter of 1,000,000? What about 10,000,000?
|
|
! 100,000,000?
|
|
|
|
! Note: the extra credit is not for you to demonstrate how fast
|
|
! your language is compared to others; you need a proper algorithm
|
|
! to solve them in a timely manner.
|
|
|
|
CONSTANT: T1 {
|
|
{ 1 2 2 }
|
|
{ -2 -1 -2 }
|
|
{ 2 2 3 }
|
|
}
|
|
CONSTANT: T2 {
|
|
{ 1 2 2 }
|
|
{ 2 1 2 }
|
|
{ 2 2 3 }
|
|
}
|
|
CONSTANT: T3 {
|
|
{ -1 -2 -2 }
|
|
{ 2 1 2 }
|
|
{ 2 2 3 }
|
|
}
|
|
|
|
CONSTANT: base { 3 4 5 }
|
|
|
|
TUPLE: triplets-count primitives total ;
|
|
|
|
: <0-triplets-count> ( -- a ) 0 0 \ triplets-count boa ;
|
|
|
|
: next-triplet ( triplet T -- triplet' ) [ 1array ] [ m. ] bi* first ;
|
|
|
|
: candidates-triplets ( seed -- candidates )
|
|
${ T1 T2 T3 } [ next-triplet ] with map ;
|
|
|
|
: add-triplets ( current-triples limit triplet -- stop )
|
|
sum 2dup > [
|
|
/i [ + ] curry change-total
|
|
[ 1 + ] change-primitives drop t
|
|
] [ 3drop f ] if ;
|
|
|
|
: all-triplets ( current-triples limit seed -- triplets )
|
|
3dup add-triplets [
|
|
candidates-triplets [ all-triplets ] with swapd reduce
|
|
] [ 2drop ] if ;
|
|
|
|
: count-triplets ( limit -- count )
|
|
<0-triplets-count> swap base all-triplets ;
|
|
|
|
: pprint-triplet-count ( limit count -- )
|
|
[ total>> ] [ primitives>> ] bi
|
|
"Up to %d: %d triples, %d primitives.\n" printf ;
|
|
|
|
: pyth ( -- )
|
|
8 [1,b] [ 10^ dup count-triplets pprint-triplet-count ] each ;
|