danbaron
30-04-2011, 08:29
I'm posting this in the science sub-forum. That way, I may be less vulnerable to attacks for writing the code of this topic in Racket.
This topic is about factoring composite integers. I became interested in it from Johannes' work on big integers, factoring composites, and primes.
Does this topic qualify as science? I think it does. Factoring is part of mathematics, and mathematics is the basis of science. And certainly, factoring done by computer, is part of computer science - and, computer science is part of science.
The code and output below use Racket, which is a descendant of Scheme, which is a dialect of Lisp.
I'm calling this topic, "Factoring 1", because, the algorithm I used is the most basic factoring algorithm.
Every positive integer, n, can be factored into k primes, for some value of k (k >= 1), such that the product of the k primes, equals n.
The algorithm works by dividing the integer (n) to factor, by members of a list containing the first y primes. If the y-th prime is at least as big as sqrt(n), then, the list is guaranteed to be able to factor n.
I arbitrarily decided to make a list of all of the primes less than or equal to the first prime greater than 10,000,000. That list is saved to file, and can be used again and again. Being able to read and write the list to file quickly, depended upon the ability of Racket to "serialize" and "deserialize" lists. The list is read and written as one unit, and the actions are very fast.
(When you use a computer to make a list of the first y primes, for some value of y, you soon realize that each succeeding prime takes longer to calculate than the previous one. The rate of growth of the list is always decreasing. At first, the list seems to grow very fast. But soon you notice that it is growing more slowly. Actually, as y approaches infinity, so does the time to calculate the y-th prime. But, theoretically, it is always possible to find the y+1-th prime, if you have a list of the first y primes. So, every prime that has ever been found, or ever will be found, could be found by constructing a list that begins with 2, and then repeatedly calculates the next prime and appends it to the list.)
So, the first thing I had to do was to make the list of primes. There is a procedure below, "set-initial-primes-file". It serialized and saved to a file called, "prime-list.txt", just the first four primes, 2, 3, 5, 7. I needed that little file, so I had something I could append to.
After that, the procedure, "append-primes-file", was used to increase the size of the list (file). It takes a parameter, "total-time", which determines how long the procedure runs. As written, the units of, "total-time", are hours. I ran the procedure numerous times, and each time it ran, the list (file) grew, until it reached its finished size. I think it took approximately 16 total hours to complete the file.
It turns out that the first prime greater than 10,000,000, is, 10,000,019. The complete list contains the first 664,580 primes, and its associated file size is 6.25 MB.
Once I had the completed file, "primes-list.txt", I could use it to factor composite integers, or to verify that an integer is prime.
The procedure that factors a number is called, "list-factor". I called it that, because, it factors a number by using a list of primes.
Since the list's largest prime, is 10,000,019, "list-factor" can factor any number that contains no factor larger than, (10,000,019)^2, or, 100,000,380,000,361. It means that the procedure can factor any number containing no factor larger than 14 digits.
******************************************************************************************************************************************************
What happens if the procedure encounters a number (or a quotient of factors) that is bigger than the 15 digit number (10000019)^2, i.e., 100000380000361?
For instance, the 15 digit number, 688846502588399 is greater than 100000380000361, and it happens to be prime.
However, what happens if we multiply together the next two primes after, 10000019, i.e., 10000079 * 10000103?
We get another 15 digit number, 100001820008137, which is also greater than 100000380000361, but, it is composite.
Can the procedure determine that 688846502588399 is prime, and that 100001820008137 is composite?
It cannot make the determination.
The procedure works by taking floor(sqrt(n)), where n is the number (or quotient of a partial factorization) being factored.
So, for 688846502588399, it finds, floor(sqrt(688846502588399)), equals 26245885.
And for, 100001820008137, it finds, floor(sqrt(100001820008137)), equals 10000090.
Both "roots" are bigger than the the biggest prime in the list, 10000019.
So, in both cases, the procedure starts at the beginning of the primes list with 2, and divides each number by each prime in the list. If the remainder of a division is 0, then, that prime divisor is one of the number's factors.
The procedure will stop before reaching the end of the primes list if it hasn't found a factor, and a candidate divisor is greater than the number's "root" (floor(sqrt(n))). (It is impossible for the smaller/smallest factor of an integer, n, to be larger than floor(sqrt(n)). For instance, consider n to be 21. floor(sqrt(21)) = 4. Therefore, if 21 is not prime, then, it must have a factor <= 4. And it does, 3. 3 * 7 = 21. You could look at it like this. If n = r * r, where r is the square root of n, and if n = a * b, where a and b are factors of n, then, if b is greater than r, a must be less than r.)
If the procedure tries every prime in the list up to its "root", and doesn't find a factor, then, the number must be prime.
(Incidentally, sqrt(21) = 4.58257569495584.. floor(sqrt(21)) = 4. ceiling(sqrt(21)) = 5. We are working with integers, so we have to use either 4 or 5 as potential factors. And, 5 * 5 = 25, would be greater than 21, so we use 4 as the maximum, i.e., floor(sqrt(n)).)
In the cases of the two numbers above, in both cases, floor(sqrt(n)) is larger than the last prime in the list, 1000019. So, unless the procedure finds a factor, it will try dividing the numbers by every prime in the list. And in both cases, it will never find a factor. For 688846502588399, there are no factors (besides 1 and itself), because it is prime. For 100001820008137, neither of its factors (10000079 and 10000103) is in the list, because they are the next two primes after the list's largest prime, 100000019.
In summary, when the procedure encounters a number (or a quotient of factors) that is larger than (10000019)^2, which it is unable to factor, it cannot say whether it is prime or composite. At that point, the procedure must stop.
----------------------------------------------------------------
What do I mean by a "quotient of factors", or, a "quotient of a partial factorization"?
Consider the integer, 2815417672486545963.
If the procedure factors it, the first factor found will be 3.
So, the procedure will divide the number by 3, getting the "quotient of the first factor", 938472557495515321.
Then, the procedure will attempt to factor 938472557495515321, and it will find the second factor, 29.
The procedure will divide 938472557495515321 by 29, getting the "quotient of the second factor", 32361122672259149.
Now, the procedure will try to factor the "quotient of factors", 32361122672259149.
But here, it has reached a dead end. 32361122672259149 is greater than (10000019)^2, and, it has no factors in the primes list.
So, the procedure can only say that it has partially factored 2815417672486545963. It cannot say whether 32361122672259149 is prime or composite.
******************************************************************************************************************************************************
In order to factor numbers, I run the code from within the DrRacket IDE. Doing that, compiles and loads the procedures. Then, I execute the procedure, "read-primes-file", from DrRacket's REPL (read-eval-print loop). That loads the list of primes. After that, I can factor numbers by executing the procedure, "list-factor".
I made two more procedures, "time-read-primes-file", and, "time-list-factor". They time the "read-primes-file" and the "list-factor" procedures. The displayed times are in seconds.
Below is shown the code, and example interactions using the REPL.
(To factor bigger numbers, I will have to use another method.)
(One more thing. If you want to instantaneously become at least a billionaire, all you need to do is to develop a procedure that will factor an arbitrary 1000 digit decimal integer, on an average computer, in one second.)
:oops: :x :twisted:
; code -------------------------------------------------------------------------------
#lang racket
(require racket/serialize)
(define pl (list))
(define start-time 0)
(define (set-start-time)
(set! start-time (current-milliseconds)))
(define (elapsed-time)
(/ (- (current-milliseconds) start-time) 3600000.0))
(define (set-initial-primes-file)
(define out (open-output-file "primes-list.txt" #:exists 'replace))
(define l (list 2 3 5 7))
(write (serialize l) out)
(close-output-port out))
(define (append-primes-file total-time)
(read-primes-file)
(set-start-time)
(displayln (length pl))
(define last-prime (last pl))
(define (test-next-number n)
(cond
((> (last pl) 10000000) void)
((even? n) (test-next-number (+ n 1)))
((> (elapsed-time) total-time) void)
(else
(define n-root (floor (sqrt n)))
(define result (check-list n n-root pl))
(when result (set! pl (append pl (list n))))
(test-next-number (+ n 1)))))
(define (check-list test test-root l)
(define check (car l))
(cond
((null? l) #t)
((> check test-root) #t)
((= (modulo test check) 0) #f)
(else (check-list test test-root (cdr l)))))
(test-next-number (+ last-prime 1))
(write-primes-file))
(define (write-primes-file)
(define out (open-output-file "primes-list.txt" #:exists 'replace))
(write (serialize pl) out)
(close-output-port out))
(define (read-primes-file)
(define in (open-input-file "primes-list.txt"))
(set! pl (deserialize (read in)))
(close-input-port in))
(define (list-factor n)
(define factors (list))
(define (test-factors n1 l)
(cond
((and (null? l) (null? factors))
(displayln "The procedure cannot factor this number.")
(displayln "Either it is a prime greater than 100,000,380,000,361,")
(displayln "or it is a composite containing factors, all of which are greater than 10,000,019."))
((and (null? l) (not (null? factors)))
(set! factors (append factors (list n1)))
(displayln "The procedure cannot fully factor this number.")
(displayln "The last factor is either a prime greater than 100,000,380,000,361,")
(displayln "or it is a composite containing sub-factors, all of which are greater than 10,000,019.")
factors)
(else
(define test (car l))
(define sr (floor (sqrt n1)))
(cond
((= (modulo n1 test) 0)
(set! factors (append factors (list test)))
(check-duplicates n1 test l))
((> test sr)
(set! factors (append factors (list n1)))
factors)
(else (test-factors n1 (cdr l)))))))
(define (check-duplicates n2 t l1)
(define n3 (/ n2 t))
(cond
((= n3 1) factors)
((= (modulo n3 t) 0)
(set! factors (append factors (list t)))
(check-duplicates n3 t l1))
(else (test-factors n3 (cdr l1)))))
(cond
((= n 0)
(list 0))
((= n 1)
(list 1))
(else (test-factors n pl))))
(define (time-read-primes-file)
(let ((t1 (current-milliseconds)))
(read-primes-file)
(let ((t2 (current-milliseconds)))
(let ((tt (/ (- t2 t1) 1000.0)))
tt))))
(define (time-list-factor n)
(let ((t1 (current-milliseconds)))
(let ((factor-list (list-factor n)))
(let ((t2 (current-milliseconds)))
(let ((tt (/ (- t2 t1) 1000.0)))
(values factor-list tt))))))
; REPL interactions ------------------------------------------------------------------
Welcome to DrRacket, version 5.1 [3m].
Language: racket.
> (time-read-primes-file)
4.009
> (list-factor 0)
'(0)
> (list-factor 1)
'(1)
> (list-factor 2)
'(2)
> (list-factor 3)
'(3)
> (list-factor 4)
'(2 2)
> (list-factor 5)
'(5)
> (list-factor 6)
'(2 3)
> (list-factor 1024)
'(2 2 2 2 2 2 2 2 2 2)
> (time-list-factor 111111111)
'(3 3 37 333667)
0.001
> (time-list-factor 1111111111)
'(11 41 271 9091)
0.001
> (time-list-factor 11111111111)
'(21649 513239)
0.319
> (time-list-factor 111111111111)
'(3 7 11 13 37 101 9901)
0.001
> (time-list-factor 1111111111111)
'(53 79 265371653)
0.002
> (time-list-factor 11111111111111)
'(11 239 4649 909091)
0.001
> (time-list-factor 111111111111111)
'(3 31 37 41 271 2906161)
0.001
> (time-list-factor 1111111111111111)
'(11 17 73 101 137 5882353)
0.001
> (time-list-factor 11111111111111111)
'(2071723 5363222357)
24.243
> (time-list-factor 111111111111111111)
'(3 3 7 11 13 19 37 52579 333667)
0.536
> (time-list-factor 1111111111111111111)
The procedure cannot factor this number.
Either it is a prime greater than 100,000,380,000,361,
or it is a composite containing factors, all of which are greater than 10,000,019.
97.527
> (time-list-factor 11111111111111111111)
'(11 41 101 271 3541 9091 27961)
1.628
> (time-list-factor 111111111111111111111)
'(3 37 43 239 1933 4649 10838689)
1.636
> (time-list-factor 1111111111111111111111)
'(11 11 23 4093 8779 21649 513239)
0.21
> (time-list-factor 11111111111111111111111)
The procedure cannot factor this number.
Either it is a prime greater than 100,000,380,000,361,
or it is a composite containing factors, all of which are greater than 10,000,019.
107.971
> (time-list-factor 111111111111111111111111)
'(3 7 11 13 37 73 101 137 9901 99990001)
0.125
> (time-list-factor 1111111111111111111111111)
'(41 271 21401 25601 182521213001)
6.208
> (time-list-factor 11111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 53 79 859 280846283204599997)
91.478
> (time-list-factor 111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 3 3 37 757 333667 440334654777631)
87.828
> (time-list-factor 1111111111111111111111111111)
'(11 29 101 239 281 4649 909091 121499449)
10.889
> (time-list-factor 11111111111111111111111111111)
'(3191 16763 43037 62003 77843839397)
2.168
> (time-list-factor 111111111111111111111111111111)
'(3 7 11 13 31 37 41 211 241 271 2161 9091 2906161)
0.14
> (time-list-factor 1111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(2791 6943319 57336415063790604359)
94.458
> (time-list-factor 11111111111111111111111111111111)
'(11 17 73 101 137 353 449 641 1409 69857 5882353)
0.593
> (time-list-factor 111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 37 67 21649 513239 1344628210313298373)
91.104
> (time-list-factor 1111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 103 4013 2071723 117957818840753430733)
92.212
> (time-list-factor 11111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(41 71 239 271 4649 123551 102598800232111471)
94.068
> (time-list-factor 111111111111111111111111111111111111)
'(3 3 7 11 13 19 37 101 9901 52579 333667 999999000001)
12.855
> (time-list-factor 1111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(2028119 547853016076034547830334961169)
88.655
> (time-list-factor 11111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 1010101010101010101010101010101010101)
93.319
> (time-list-factor 111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 37 53 79 239073561261285168617387389778123)
94.863
> (time-list-factor 1111111111111111111111111111111111111111)
'(11 41 73 101 137 271 3541 9091 27961 1676321 5964848081)
15.662
> (time-list-factor 11111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(83 1231 538987 201763709900322803748657942361)
94.13
> (time-list-factor 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 41 101 251 271 3541 5051 9091 21401 25601 27961 60101 7019801 341233306557836423189042926585457900151074303303755301)
90.121
> (time-list-factor 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11
41
73
101
137
251
271
401
1201
1601
3541
5051
9091
21401
25601
27961
60101
1676321
7019801
263980647407951828155827620420447036038246324232161580581998828957153987896442603868348285938940685117797680817907519399405310559008181)
97.999
>
This topic is about factoring composite integers. I became interested in it from Johannes' work on big integers, factoring composites, and primes.
Does this topic qualify as science? I think it does. Factoring is part of mathematics, and mathematics is the basis of science. And certainly, factoring done by computer, is part of computer science - and, computer science is part of science.
The code and output below use Racket, which is a descendant of Scheme, which is a dialect of Lisp.
I'm calling this topic, "Factoring 1", because, the algorithm I used is the most basic factoring algorithm.
Every positive integer, n, can be factored into k primes, for some value of k (k >= 1), such that the product of the k primes, equals n.
The algorithm works by dividing the integer (n) to factor, by members of a list containing the first y primes. If the y-th prime is at least as big as sqrt(n), then, the list is guaranteed to be able to factor n.
I arbitrarily decided to make a list of all of the primes less than or equal to the first prime greater than 10,000,000. That list is saved to file, and can be used again and again. Being able to read and write the list to file quickly, depended upon the ability of Racket to "serialize" and "deserialize" lists. The list is read and written as one unit, and the actions are very fast.
(When you use a computer to make a list of the first y primes, for some value of y, you soon realize that each succeeding prime takes longer to calculate than the previous one. The rate of growth of the list is always decreasing. At first, the list seems to grow very fast. But soon you notice that it is growing more slowly. Actually, as y approaches infinity, so does the time to calculate the y-th prime. But, theoretically, it is always possible to find the y+1-th prime, if you have a list of the first y primes. So, every prime that has ever been found, or ever will be found, could be found by constructing a list that begins with 2, and then repeatedly calculates the next prime and appends it to the list.)
So, the first thing I had to do was to make the list of primes. There is a procedure below, "set-initial-primes-file". It serialized and saved to a file called, "prime-list.txt", just the first four primes, 2, 3, 5, 7. I needed that little file, so I had something I could append to.
After that, the procedure, "append-primes-file", was used to increase the size of the list (file). It takes a parameter, "total-time", which determines how long the procedure runs. As written, the units of, "total-time", are hours. I ran the procedure numerous times, and each time it ran, the list (file) grew, until it reached its finished size. I think it took approximately 16 total hours to complete the file.
It turns out that the first prime greater than 10,000,000, is, 10,000,019. The complete list contains the first 664,580 primes, and its associated file size is 6.25 MB.
Once I had the completed file, "primes-list.txt", I could use it to factor composite integers, or to verify that an integer is prime.
The procedure that factors a number is called, "list-factor". I called it that, because, it factors a number by using a list of primes.
Since the list's largest prime, is 10,000,019, "list-factor" can factor any number that contains no factor larger than, (10,000,019)^2, or, 100,000,380,000,361. It means that the procedure can factor any number containing no factor larger than 14 digits.
******************************************************************************************************************************************************
What happens if the procedure encounters a number (or a quotient of factors) that is bigger than the 15 digit number (10000019)^2, i.e., 100000380000361?
For instance, the 15 digit number, 688846502588399 is greater than 100000380000361, and it happens to be prime.
However, what happens if we multiply together the next two primes after, 10000019, i.e., 10000079 * 10000103?
We get another 15 digit number, 100001820008137, which is also greater than 100000380000361, but, it is composite.
Can the procedure determine that 688846502588399 is prime, and that 100001820008137 is composite?
It cannot make the determination.
The procedure works by taking floor(sqrt(n)), where n is the number (or quotient of a partial factorization) being factored.
So, for 688846502588399, it finds, floor(sqrt(688846502588399)), equals 26245885.
And for, 100001820008137, it finds, floor(sqrt(100001820008137)), equals 10000090.
Both "roots" are bigger than the the biggest prime in the list, 10000019.
So, in both cases, the procedure starts at the beginning of the primes list with 2, and divides each number by each prime in the list. If the remainder of a division is 0, then, that prime divisor is one of the number's factors.
The procedure will stop before reaching the end of the primes list if it hasn't found a factor, and a candidate divisor is greater than the number's "root" (floor(sqrt(n))). (It is impossible for the smaller/smallest factor of an integer, n, to be larger than floor(sqrt(n)). For instance, consider n to be 21. floor(sqrt(21)) = 4. Therefore, if 21 is not prime, then, it must have a factor <= 4. And it does, 3. 3 * 7 = 21. You could look at it like this. If n = r * r, where r is the square root of n, and if n = a * b, where a and b are factors of n, then, if b is greater than r, a must be less than r.)
If the procedure tries every prime in the list up to its "root", and doesn't find a factor, then, the number must be prime.
(Incidentally, sqrt(21) = 4.58257569495584.. floor(sqrt(21)) = 4. ceiling(sqrt(21)) = 5. We are working with integers, so we have to use either 4 or 5 as potential factors. And, 5 * 5 = 25, would be greater than 21, so we use 4 as the maximum, i.e., floor(sqrt(n)).)
In the cases of the two numbers above, in both cases, floor(sqrt(n)) is larger than the last prime in the list, 1000019. So, unless the procedure finds a factor, it will try dividing the numbers by every prime in the list. And in both cases, it will never find a factor. For 688846502588399, there are no factors (besides 1 and itself), because it is prime. For 100001820008137, neither of its factors (10000079 and 10000103) is in the list, because they are the next two primes after the list's largest prime, 100000019.
In summary, when the procedure encounters a number (or a quotient of factors) that is larger than (10000019)^2, which it is unable to factor, it cannot say whether it is prime or composite. At that point, the procedure must stop.
----------------------------------------------------------------
What do I mean by a "quotient of factors", or, a "quotient of a partial factorization"?
Consider the integer, 2815417672486545963.
If the procedure factors it, the first factor found will be 3.
So, the procedure will divide the number by 3, getting the "quotient of the first factor", 938472557495515321.
Then, the procedure will attempt to factor 938472557495515321, and it will find the second factor, 29.
The procedure will divide 938472557495515321 by 29, getting the "quotient of the second factor", 32361122672259149.
Now, the procedure will try to factor the "quotient of factors", 32361122672259149.
But here, it has reached a dead end. 32361122672259149 is greater than (10000019)^2, and, it has no factors in the primes list.
So, the procedure can only say that it has partially factored 2815417672486545963. It cannot say whether 32361122672259149 is prime or composite.
******************************************************************************************************************************************************
In order to factor numbers, I run the code from within the DrRacket IDE. Doing that, compiles and loads the procedures. Then, I execute the procedure, "read-primes-file", from DrRacket's REPL (read-eval-print loop). That loads the list of primes. After that, I can factor numbers by executing the procedure, "list-factor".
I made two more procedures, "time-read-primes-file", and, "time-list-factor". They time the "read-primes-file" and the "list-factor" procedures. The displayed times are in seconds.
Below is shown the code, and example interactions using the REPL.
(To factor bigger numbers, I will have to use another method.)
(One more thing. If you want to instantaneously become at least a billionaire, all you need to do is to develop a procedure that will factor an arbitrary 1000 digit decimal integer, on an average computer, in one second.)
:oops: :x :twisted:
; code -------------------------------------------------------------------------------
#lang racket
(require racket/serialize)
(define pl (list))
(define start-time 0)
(define (set-start-time)
(set! start-time (current-milliseconds)))
(define (elapsed-time)
(/ (- (current-milliseconds) start-time) 3600000.0))
(define (set-initial-primes-file)
(define out (open-output-file "primes-list.txt" #:exists 'replace))
(define l (list 2 3 5 7))
(write (serialize l) out)
(close-output-port out))
(define (append-primes-file total-time)
(read-primes-file)
(set-start-time)
(displayln (length pl))
(define last-prime (last pl))
(define (test-next-number n)
(cond
((> (last pl) 10000000) void)
((even? n) (test-next-number (+ n 1)))
((> (elapsed-time) total-time) void)
(else
(define n-root (floor (sqrt n)))
(define result (check-list n n-root pl))
(when result (set! pl (append pl (list n))))
(test-next-number (+ n 1)))))
(define (check-list test test-root l)
(define check (car l))
(cond
((null? l) #t)
((> check test-root) #t)
((= (modulo test check) 0) #f)
(else (check-list test test-root (cdr l)))))
(test-next-number (+ last-prime 1))
(write-primes-file))
(define (write-primes-file)
(define out (open-output-file "primes-list.txt" #:exists 'replace))
(write (serialize pl) out)
(close-output-port out))
(define (read-primes-file)
(define in (open-input-file "primes-list.txt"))
(set! pl (deserialize (read in)))
(close-input-port in))
(define (list-factor n)
(define factors (list))
(define (test-factors n1 l)
(cond
((and (null? l) (null? factors))
(displayln "The procedure cannot factor this number.")
(displayln "Either it is a prime greater than 100,000,380,000,361,")
(displayln "or it is a composite containing factors, all of which are greater than 10,000,019."))
((and (null? l) (not (null? factors)))
(set! factors (append factors (list n1)))
(displayln "The procedure cannot fully factor this number.")
(displayln "The last factor is either a prime greater than 100,000,380,000,361,")
(displayln "or it is a composite containing sub-factors, all of which are greater than 10,000,019.")
factors)
(else
(define test (car l))
(define sr (floor (sqrt n1)))
(cond
((= (modulo n1 test) 0)
(set! factors (append factors (list test)))
(check-duplicates n1 test l))
((> test sr)
(set! factors (append factors (list n1)))
factors)
(else (test-factors n1 (cdr l)))))))
(define (check-duplicates n2 t l1)
(define n3 (/ n2 t))
(cond
((= n3 1) factors)
((= (modulo n3 t) 0)
(set! factors (append factors (list t)))
(check-duplicates n3 t l1))
(else (test-factors n3 (cdr l1)))))
(cond
((= n 0)
(list 0))
((= n 1)
(list 1))
(else (test-factors n pl))))
(define (time-read-primes-file)
(let ((t1 (current-milliseconds)))
(read-primes-file)
(let ((t2 (current-milliseconds)))
(let ((tt (/ (- t2 t1) 1000.0)))
tt))))
(define (time-list-factor n)
(let ((t1 (current-milliseconds)))
(let ((factor-list (list-factor n)))
(let ((t2 (current-milliseconds)))
(let ((tt (/ (- t2 t1) 1000.0)))
(values factor-list tt))))))
; REPL interactions ------------------------------------------------------------------
Welcome to DrRacket, version 5.1 [3m].
Language: racket.
> (time-read-primes-file)
4.009
> (list-factor 0)
'(0)
> (list-factor 1)
'(1)
> (list-factor 2)
'(2)
> (list-factor 3)
'(3)
> (list-factor 4)
'(2 2)
> (list-factor 5)
'(5)
> (list-factor 6)
'(2 3)
> (list-factor 1024)
'(2 2 2 2 2 2 2 2 2 2)
> (time-list-factor 111111111)
'(3 3 37 333667)
0.001
> (time-list-factor 1111111111)
'(11 41 271 9091)
0.001
> (time-list-factor 11111111111)
'(21649 513239)
0.319
> (time-list-factor 111111111111)
'(3 7 11 13 37 101 9901)
0.001
> (time-list-factor 1111111111111)
'(53 79 265371653)
0.002
> (time-list-factor 11111111111111)
'(11 239 4649 909091)
0.001
> (time-list-factor 111111111111111)
'(3 31 37 41 271 2906161)
0.001
> (time-list-factor 1111111111111111)
'(11 17 73 101 137 5882353)
0.001
> (time-list-factor 11111111111111111)
'(2071723 5363222357)
24.243
> (time-list-factor 111111111111111111)
'(3 3 7 11 13 19 37 52579 333667)
0.536
> (time-list-factor 1111111111111111111)
The procedure cannot factor this number.
Either it is a prime greater than 100,000,380,000,361,
or it is a composite containing factors, all of which are greater than 10,000,019.
97.527
> (time-list-factor 11111111111111111111)
'(11 41 101 271 3541 9091 27961)
1.628
> (time-list-factor 111111111111111111111)
'(3 37 43 239 1933 4649 10838689)
1.636
> (time-list-factor 1111111111111111111111)
'(11 11 23 4093 8779 21649 513239)
0.21
> (time-list-factor 11111111111111111111111)
The procedure cannot factor this number.
Either it is a prime greater than 100,000,380,000,361,
or it is a composite containing factors, all of which are greater than 10,000,019.
107.971
> (time-list-factor 111111111111111111111111)
'(3 7 11 13 37 73 101 137 9901 99990001)
0.125
> (time-list-factor 1111111111111111111111111)
'(41 271 21401 25601 182521213001)
6.208
> (time-list-factor 11111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 53 79 859 280846283204599997)
91.478
> (time-list-factor 111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 3 3 37 757 333667 440334654777631)
87.828
> (time-list-factor 1111111111111111111111111111)
'(11 29 101 239 281 4649 909091 121499449)
10.889
> (time-list-factor 11111111111111111111111111111)
'(3191 16763 43037 62003 77843839397)
2.168
> (time-list-factor 111111111111111111111111111111)
'(3 7 11 13 31 37 41 211 241 271 2161 9091 2906161)
0.14
> (time-list-factor 1111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(2791 6943319 57336415063790604359)
94.458
> (time-list-factor 11111111111111111111111111111111)
'(11 17 73 101 137 353 449 641 1409 69857 5882353)
0.593
> (time-list-factor 111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 37 67 21649 513239 1344628210313298373)
91.104
> (time-list-factor 1111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 103 4013 2071723 117957818840753430733)
92.212
> (time-list-factor 11111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(41 71 239 271 4649 123551 102598800232111471)
94.068
> (time-list-factor 111111111111111111111111111111111111)
'(3 3 7 11 13 19 37 101 9901 52579 333667 999999000001)
12.855
> (time-list-factor 1111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(2028119 547853016076034547830334961169)
88.655
> (time-list-factor 11111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 1010101010101010101010101010101010101)
93.319
> (time-list-factor 111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(3 37 53 79 239073561261285168617387389778123)
94.863
> (time-list-factor 1111111111111111111111111111111111111111)
'(11 41 73 101 137 271 3541 9091 27961 1676321 5964848081)
15.662
> (time-list-factor 11111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(83 1231 538987 201763709900322803748657942361)
94.13
> (time-list-factor 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11 41 101 251 271 3541 5051 9091 21401 25601 27961 60101 7019801 341233306557836423189042926585457900151074303303755301)
90.121
> (time-list-factor 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
The procedure cannot fully factor this number.
The last factor is either a prime greater than 100,000,380,000,361,
or it is a composite containing sub-factors, all of which are greater than 10,000,019.
'(11
41
73
101
137
251
271
401
1201
1601
3541
5051
9091
21401
25601
27961
60101
1676321
7019801
263980647407951828155827620420447036038246324232161580581998828957153987896442603868348285938940685117797680817907519399405310559008181)
97.999
>