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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 06b99246be7a2bfd75f92c7fc00da6244f58e47f
4
- data.tar.gz: 4150b339ac4d875941fae7b3bc09777e431f28ee
3
+ metadata.gz: 299f5fbd29ce75cf104d0f2be372821a59d2d776
4
+ data.tar.gz: 9c18c6aef7dc6c7c500b8902399502a7527712db
5
5
  SHA512:
6
- metadata.gz: c9d32659b42c562551f8fe7365c990aa91a67e8a6eca00f99311010d8ce01b2f50b648bbc174bf9ec25886122346b491d8ddb40411888252c6c0d2eca8040716
7
- data.tar.gz: f67ba3a6d0d7de34e50eace6719ee3efde83e0c4279a19e0b7192b26598eda02207899e0406a2ece6801080dfbf036c5c2ce03b45e13a853521dba100073dff4
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.0)
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
- # Not sure why this is here. I'll have to experiment with taking it out.
2
- require "primetable/version"
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=:calc, suppress_output=false)
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(:load,first,count)
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 # Shaves off about between 10 and 40 milliseconds vs. the :load method
43
- [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
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 # The slowest, but presumably preferred, method in our arsenal
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 1999993, although conceivably we could use the :calc method and extend it.
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 134128 primes in here right now
71
- if (first + count) > 134128
72
- throw "We only have the first 134128 primes in the data file right now. Please pass -c to use calculated primes."
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
@@ -1,3 +1,3 @@
1
1
  class PrimeTable
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.4"
3
3
  end
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'
@@ -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 -tv`
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.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-21 00:00:00.000000000 Z
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