primetable 0.2.2 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +10 -4
- data/data/prime.dat +1 -1
- data/js/prime.js +87 -0
- data/lib/primetable.rb +27 -17
- data/lib/primetable/version.rb +1 -1
- data/primetable.gemspec +1 -0
- data/spec/primetable_spec.rb +14 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 299f5fbd29ce75cf104d0f2be372821a59d2d776
|
4
|
+
data.tar.gz: 9c18c6aef7dc6c7c500b8902399502a7527712db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcb03e51222e85965ad491a05d4accc773cea77882692ead9f166e800222451f2a7a8f679a6fd31dc0acfe43ddf94dc0d1c2a91b081d5a4048d4860ff11de730
|
7
|
+
data.tar.gz: c59603ca941d2cf1fca3f141e25f19165318572cfd95231d2edf44ba909a992dfe16dcb1d1a3eee1e4c17ab4387e765c4c3f477df111c1a6b9b3bafcfead4642
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
primetable (0.2.
|
4
|
+
primetable (0.2.3)
|
5
|
+
awesome_print (~> 1.6, >= 1.6.1)
|
6
|
+
therubyracer (~> 0.12.2)
|
5
7
|
|
6
8
|
GEM
|
7
9
|
remote: https://rubygems.org/
|
8
10
|
specs:
|
9
11
|
awesome_print (1.6.1)
|
10
12
|
diff-lcs (1.2.5)
|
13
|
+
libv8 (3.16.14.13)
|
11
14
|
rake (10.4.2)
|
15
|
+
ref (2.0.0)
|
12
16
|
rspec (3.4.0)
|
13
17
|
rspec-core (~> 3.4.0)
|
14
18
|
rspec-expectations (~> 3.4.0)
|
@@ -22,16 +26,18 @@ GEM
|
|
22
26
|
diff-lcs (>= 1.2.0, < 2.0)
|
23
27
|
rspec-support (~> 3.4.0)
|
24
28
|
rspec-support (3.4.0)
|
29
|
+
therubyracer (0.12.2)
|
30
|
+
libv8 (~> 3.16.14.0)
|
31
|
+
ref
|
25
32
|
|
26
33
|
PLATFORMS
|
27
34
|
ruby
|
28
35
|
|
29
36
|
DEPENDENCIES
|
30
|
-
awesome_print
|
31
37
|
bundler (~> 1.6)
|
32
38
|
primetable!
|
33
|
-
rake
|
34
|
-
rspec
|
39
|
+
rake (~> 10.4, >= 10.4.2)
|
40
|
+
rspec (~> 3.4, >= 3.4.0)
|
35
41
|
|
36
42
|
BUNDLED WITH
|
37
43
|
1.10.6
|
data/data/prime.dat
CHANGED
@@ -13410,4 +13410,4 @@
|
|
13410
13410
|
[1999121,1999163,1999177,1999187,1999211,1999219,1999223,1999243,1999247,1999273]
|
13411
13411
|
[1999297,1999301,1999303,1999307,1999331,1999339,1999343,1999363,1999379,1999681]
|
13412
13412
|
[1999691,1999703,1999721,1999733,1999771,1999799,1999817,1999819,1999853,1999859]
|
13413
|
-
[1999867,1999871,1999889,1999891,1999957,1999969,1999979,1999993]
|
13413
|
+
[1999867,1999871,1999889,1999891,1999957,1999969,1999979,1999993,2000003,2000029]
|
data/js/prime.js
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
var factors = [];
|
2
|
+
var primes = [];
|
3
|
+
|
4
|
+
function libPrime(method, n) {
|
5
|
+
if (method === "isPrime" && n === 1) {
|
6
|
+
return false;
|
7
|
+
}
|
8
|
+
if (method === "generatePrimes") {
|
9
|
+
var count = 10;
|
10
|
+
// console.log("primes.length:"+primes.length);
|
11
|
+
while (primes.length<count) {
|
12
|
+
if (isPrime(n) && (primes.indexOf(n) === -1)) {
|
13
|
+
// console.log("isPrime(n):true:"+n);
|
14
|
+
primes.push(n);
|
15
|
+
// console.log("primes:"+primes+", primes.length:"+primes.length);
|
16
|
+
} else {
|
17
|
+
// console.log("isPrime(n):false:"+n);
|
18
|
+
n++;
|
19
|
+
generatePrimes(n);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
return primes;
|
23
|
+
}
|
24
|
+
// console.log("* n:"+n);
|
25
|
+
// We don't care about divisibility by 1, so we begin at 2
|
26
|
+
var divisor = 2;
|
27
|
+
|
28
|
+
// If a suitable divisor exists it will be less than or equal to the square root of n
|
29
|
+
// Due to the commutative property of multiplication
|
30
|
+
while ((divisor <= Math.floor(Math.sqrt(n)))) {
|
31
|
+
// console.log("** n:"+n+", divisor:"+divisor+", n % divisor:"+(n % divisor));
|
32
|
+
if (!(n % divisor)) {
|
33
|
+
// console.log("*** n:"+n+", divisor:"+divisor);
|
34
|
+
// If n is divisible with remainder zero, then it's non-prime
|
35
|
+
switch (method) {
|
36
|
+
case "isPrime":
|
37
|
+
return false;
|
38
|
+
case "primeFactors":
|
39
|
+
// The divisor will always be a prime factor
|
40
|
+
factors.push(divisor);
|
41
|
+
// The quotient may or may not be prime, so we recurse here
|
42
|
+
// console.log("**** n:"+n+", divisor:"+divisor+", n/divisor:"+n/divisor);
|
43
|
+
primeFactors(n/divisor);
|
44
|
+
return factors;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
// If n is not evenly divisible then we increment the divisor and continue
|
49
|
+
if (divisor >= 3) {
|
50
|
+
divisor += 2; // Because all even numbers > 2 are non-prime
|
51
|
+
} else {
|
52
|
+
divisor += 1; // Just once, from 2 to 3
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
switch (method) {
|
57
|
+
case "isPrime":
|
58
|
+
return true;
|
59
|
+
case "primeFactors":
|
60
|
+
factors.push(n);
|
61
|
+
return factors;
|
62
|
+
case "generatePrimes":
|
63
|
+
primes.push(n);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
// Returns true if n is prime
|
68
|
+
function isPrime(n) {
|
69
|
+
return libPrime("isPrime",n);
|
70
|
+
}
|
71
|
+
|
72
|
+
// Returns n if prime, or the prime factors of n if composite
|
73
|
+
function primeFactors(n) {
|
74
|
+
return libPrime("primeFactors",n);
|
75
|
+
}
|
76
|
+
|
77
|
+
// Generate an array of prime numbers greater than or equal to n with length count
|
78
|
+
function generatePrimes(n) {
|
79
|
+
return libPrime("generatePrimes",n);
|
80
|
+
}
|
81
|
+
// Try it out
|
82
|
+
// // console.log(isPrime(1));
|
83
|
+
// console.log(generatePrimes(1999867));
|
84
|
+
// Try it out
|
85
|
+
// for (var i = 1; i < 1002; i++) {
|
86
|
+
// // console.log(i + " is " + (isPrime(i) ? "PRIME" : "COMPOSITE") + (!(isPrime(i)) ? (": " + primeFactors(i)) : ""));
|
87
|
+
// }
|
data/lib/primetable.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# Require modules from the lib/primetable directory...right now it's just our VERSION constant
|
2
|
+
Dir["#{File.dirname(__FILE__)}/primetable/**/*.rb"].each { |f| require(f) }
|
3
3
|
|
4
4
|
# This is needed for load_primes method, which loads data from a file.
|
5
5
|
require "yaml"
|
@@ -7,13 +7,18 @@ require "yaml"
|
|
7
7
|
# I'll probably remove this later, but it's my interim table display solution.
|
8
8
|
require "awesome_print"
|
9
9
|
|
10
|
+
# So, just for fun, I'm going to write my Ruby prime generation method and a few others as
|
11
|
+
# wrappers for some JS functionality I've already written. We'll test as usual. Perhaps, if
|
12
|
+
# I ever get around to writing Ruby native versions, we can have them race eachother.
|
13
|
+
require "v8"
|
14
|
+
|
10
15
|
# It's a pretty simple program. I considered making multiple classes, but it's not necessary.
|
11
16
|
class PrimeTable
|
12
17
|
|
13
18
|
# We're going to want to get and set things from inside multiple methods, so...
|
14
19
|
attr_accessor :primes, :table
|
15
20
|
|
16
|
-
def initialize(first=1, count=10, prime_method=:
|
21
|
+
def initialize(first=1, count=10, prime_method=:fast, suppress_output=false)
|
17
22
|
|
18
23
|
# This is only for testing, I'm unlikely to implement a command-line flag for this
|
19
24
|
unless suppress_output
|
@@ -22,7 +27,7 @@ class PrimeTable
|
|
22
27
|
end
|
23
28
|
|
24
29
|
# Ye olde instance variables
|
25
|
-
@primes = init_primes(
|
30
|
+
@primes = init_primes(prime_method,first,count)
|
26
31
|
@table = build_data(@primes)
|
27
32
|
|
28
33
|
# I added this suppress_output so I could run certain tests without a huge, admittly
|
@@ -39,12 +44,11 @@ class PrimeTable
|
|
39
44
|
# Of course, we calculate the primes by default. But having three methods is not only
|
40
45
|
# fancy; it's also comes in handy for testing that our calculated values are correct.
|
41
46
|
case prime_method
|
42
|
-
when :fast #
|
43
|
-
|
44
|
-
|
45
|
-
when :load # Using precalculated values saves us a lot of time vs. the :calc method
|
47
|
+
when :fast # Using precalculated values from code. 3-8ms on benchmark run.
|
48
|
+
PrimeTable::PRIMES.slice(first-1,count)
|
49
|
+
when :load # Using precalculated values from file. 13-23ms on benchmark run.
|
46
50
|
load_primes(first,count)
|
47
|
-
when :calc #
|
51
|
+
when :calc # Using JS generated values. 8-16ms on benchmark run.
|
48
52
|
calc_primes(first,count)
|
49
53
|
end # case prime_method
|
50
54
|
|
@@ -55,21 +59,29 @@ class PrimeTable
|
|
55
59
|
# TODO: Include note on average run time using this method.
|
56
60
|
def calc_primes(first, count)
|
57
61
|
|
62
|
+
# One nice thing about this is that I can easily set a timeout, so I someone asks us to run
|
63
|
+
# some astronomical prime, we won't seize up the CPU forever. 700ms is arbitrary.
|
64
|
+
calc_primes_js = V8::Context.new timeout: 700
|
65
|
+
File.open("js/prime.js") do |file|
|
66
|
+
calc_primes_js.eval(file, "js/prime.js")
|
67
|
+
end
|
68
|
+
primes_js = calc_primes_js.eval("generatePrimes(#{first})")
|
69
|
+
primes = YAML::load("[#{primes_js}]")
|
70
|
+
return primes
|
71
|
+
|
58
72
|
end
|
59
73
|
|
60
74
|
# Loads precalculated primes from a data file. The file is formatted with 10 primes per line.
|
61
75
|
# Each line is enclosed in square brackets, and the primes are comma-delimited. Thus, it's
|
62
76
|
# trivial to read each line in as an array of ten primes. Please note that this file is 995K
|
63
|
-
|
64
77
|
# and contains 13413 lines. You don't want to just slurp this file. That would be rude. Instead
|
65
|
-
|
66
78
|
# we read lines one at a time and only keep what we need. Also note the highest prime in this
|
67
|
-
# file is currently
|
79
|
+
# file is currently 2000029, although conceivably we could use the :calc method and extend it.
|
68
80
|
def load_primes(first, count)
|
69
81
|
|
70
|
-
# Again, we only have the first
|
71
|
-
if (first + count) >
|
72
|
-
throw "We only have the first
|
82
|
+
# Again, we only have the first 134130 primes in here right now
|
83
|
+
if (first + count) > 134130
|
84
|
+
throw "We only have the first 134130 primes in the data file right now. Please pass -c to use calculated primes."
|
73
85
|
end
|
74
86
|
|
75
87
|
# An array to keep our prime numbers in, right?
|
@@ -77,10 +89,8 @@ class PrimeTable
|
|
77
89
|
|
78
90
|
# Because there are ten primes on each line, we can get the line number we're looking for by
|
79
91
|
# dividing the indices we want by 10 and rounding down for the bottom of our range and up for
|
80
|
-
|
81
92
|
# the top. It's not immediately intuitive why we might want to do this, but it's because:
|
82
93
|
# 1) We don't want to slurp the whole file...what if the file was even larger? Not cool.
|
83
|
-
|
84
94
|
# 2) IO.readlines gets the file one line at a time, so we need a line number, not an index.
|
85
95
|
|
86
96
|
first_line = (first/10).floor
|
data/lib/primetable/version.rb
CHANGED
data/primetable.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "awesome_print", '~> 1.6', '>= 1.6.1'
|
22
|
+
spec.add_runtime_dependency 'therubyracer', '~> 0.12.2'
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.6"
|
24
25
|
spec.add_development_dependency "rake", '~> 10.4', '>= 10.4.2'
|
data/spec/primetable_spec.rb
CHANGED
@@ -22,9 +22,11 @@ describe PrimeTable do
|
|
22
22
|
[23,46,69,115,161,253,299,391,437,529,667],
|
23
23
|
[29,58,87,145,203,319,377,493,551,667,841]]
|
24
24
|
end
|
25
|
+
|
25
26
|
it 'has a version number' do
|
26
27
|
expect(PrimeTable::VERSION).not_to be nil
|
27
28
|
end
|
29
|
+
|
28
30
|
it 'executes when called on the command line' do
|
29
31
|
expect(`primetable`).to include("PrimeTable is running...\n")
|
30
32
|
end
|
@@ -46,7 +48,7 @@ describe PrimeTable do
|
|
46
48
|
expect(execution_output).to include(@expected_version_output)
|
47
49
|
end
|
48
50
|
it 'executes *and* prints out a run time *and* prints out the version number when passed both --time and --version arguments' do
|
49
|
-
execution_output = `primetable
|
51
|
+
execution_output = `primetable --time --version`
|
50
52
|
expect(execution_output).to include(@expected_execution_output)
|
51
53
|
expect(execution_output).to include(@expected_time_output)
|
52
54
|
expect(execution_output).to include(@expected_version_output)
|
@@ -57,9 +59,20 @@ describe PrimeTable do
|
|
57
59
|
execution_output = `primetable --help`
|
58
60
|
expect(execution_output).to include(@expected_help_output)
|
59
61
|
end
|
62
|
+
|
60
63
|
it "has the right data when we run it with :load" do
|
61
64
|
test_instance = PrimeTable.new(1,10,:load,true)
|
62
65
|
expect(test_instance.primes).to eq(@expected_first_ten_primes)
|
63
66
|
expect(test_instance.table).to eq(@expected_table_with_first_ten_primes)
|
64
67
|
end
|
68
|
+
it "has the right data when we run it with :fast" do
|
69
|
+
test_instance = PrimeTable.new(1,10,:fast,true)
|
70
|
+
expect(test_instance.primes).to eq(@expected_first_ten_primes)
|
71
|
+
expect(test_instance.table).to eq(@expected_table_with_first_ten_primes)
|
72
|
+
end
|
73
|
+
it "has the right data when we run it with :calc" do
|
74
|
+
test_instance = PrimeTable.new(1,10,:calc,true)
|
75
|
+
expect(test_instance.primes).to eq(@expected_first_ten_primes)
|
76
|
+
expect(test_instance.table).to eq(@expected_table_with_first_ten_primes)
|
77
|
+
end
|
65
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: primetable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Day Davis Waterbury
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.6.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: therubyracer
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.12.2
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.12.2
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,6 +116,7 @@ files:
|
|
102
116
|
- Rakefile
|
103
117
|
- bin/primetable
|
104
118
|
- data/prime.dat
|
119
|
+
- js/prime.js
|
105
120
|
- lib/primetable.rb
|
106
121
|
- lib/primetable/version.rb
|
107
122
|
- lib/timer.rb
|