primetable 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|