prime_multiplication_table 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be3fd8276121c35cd3bf8f27e68e130902b7fee2
4
+ data.tar.gz: 71e1a2188bc8f8f0ab2335eac253825a54c1a11a
5
+ SHA512:
6
+ metadata.gz: 82b0212d5ef41ddd16ce8a9912ade4f4a3f2e25532f717aa7054b96028b6b2f8f8af0581268b82e3f675554f13e8267399e2e2a6e543ab4dd660fbdc1ea667f5
7
+ data.tar.gz: 2a7ee9b6966c7dcbdd127b771abe79b6ee80d523a38e3edb955d8c1c83779183da21d537667cb48baa092ef9102848f8572af8ce96f051d64744de0778c65677
@@ -0,0 +1,3 @@
1
+ # Created by .ignore support plugin (hsz.mobi)
2
+ .idea
3
+ .ruby-*
@@ -0,0 +1,19 @@
1
+ # See full list of defaults here: https://github.com/bbatsov/rubocop/blob/master/config/default.yml
2
+ # To see all cops used see here: https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.3
6
+ DisplayCopNames: true
7
+
8
+ LineLength:
9
+ Max: 120
10
+
11
+ Style/OpMethod:
12
+ Enabled: false
13
+
14
+ Style/FrozenStringLiteralComment:
15
+ Enabled: false
16
+
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - '**/*_spec.rb'
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in prime_multiplication_table.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec', require: false
8
+ end
9
+
10
+ group :development do
11
+ gem 'rubocop'
12
+ end
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ prime_multiplication_table (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.3.0)
10
+ diff-lcs (1.3)
11
+ parser (2.4.0.0)
12
+ ast (~> 2.2)
13
+ powerpack (0.1.1)
14
+ rainbow (2.2.2)
15
+ rake
16
+ rake (12.0.0)
17
+ rspec (3.5.0)
18
+ rspec-core (~> 3.5.0)
19
+ rspec-expectations (~> 3.5.0)
20
+ rspec-mocks (~> 3.5.0)
21
+ rspec-core (3.5.4)
22
+ rspec-support (~> 3.5.0)
23
+ rspec-expectations (3.5.0)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.5.0)
26
+ rspec-mocks (3.5.0)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.5.0)
29
+ rspec-support (3.5.0)
30
+ rubocop (0.48.1)
31
+ parser (>= 2.3.3.1, < 3.0)
32
+ powerpack (~> 0.1)
33
+ rainbow (>= 1.99.1, < 3.0)
34
+ ruby-progressbar (~> 1.7)
35
+ unicode-display_width (~> 1.0, >= 1.0.1)
36
+ ruby-progressbar (1.8.1)
37
+ unicode-display_width (1.2.1)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ prime_multiplication_table!
44
+ rspec
45
+ rubocop
46
+
47
+ BUNDLED WITH
48
+ 1.13.6
@@ -0,0 +1,36 @@
1
+ ### Installation
2
+
3
+ ```bash
4
+ gem install prime_multiplication_table
5
+ ```
6
+
7
+ ### Usage
8
+
9
+ ```bash
10
+ $ prime_multiplication_table
11
+ prime_multiplication_table (version: 0.1.0)
12
+ 2 3 5 7 11 13 17 19 23 29
13
+ 2 4 6 10 14 22 26 34 38 46 58
14
+ 3 6 9 15 21 33 39 51 57 69 87
15
+ 5 10 15 25 35 55 65 85 95 115 145
16
+ 7 14 21 35 49 77 91 119 133 161 203
17
+ 11 22 33 55 77 121 143 187 209 253 319
18
+ 13 26 39 65 91 143 169 221 247 299 377
19
+ 17 34 51 85 119 187 221 289 323 391 493
20
+ 19 38 57 95 133 209 247 323 361 437 551
21
+ 23 46 69 115 161 253 299 391 437 529 667
22
+ 29 58 87 145 203 319 377 493 551 667 841
23
+
24
+
25
+ $ prime_multiplication_table 1
26
+ prime_multiplication_table (version: 0.1.0)
27
+ 2
28
+ 2 4
29
+
30
+
31
+ $ prime_multiplication_table 2
32
+ prime_multiplication_table (version: 0.1.0)
33
+ 2 3
34
+ 2 4 6
35
+ 3 6 9
36
+ ```
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'prime_multiplication_table'
3
+ require 'prime_multiplication_table_cli'
4
+
5
+ PrimeMultiplicationTableCLI.run(ARGV)
@@ -0,0 +1,11 @@
1
+ require 'forwardable'
2
+
3
+ # This is main namespace for the library.
4
+ module PrimeMultiplicationTable
5
+ end
6
+
7
+ require 'prime_multiplication_table/version'
8
+ require 'prime_multiplication_table/cache'
9
+ require 'prime_multiplication_table/atkin_sieve'
10
+ require 'prime_multiplication_table/prime'
11
+ require 'prime_multiplication_table/renderer'
@@ -0,0 +1,85 @@
1
+ module PrimeMultiplicationTable
2
+ # AtkinSieve contains implementation of atkin algorithm to find prime numbers.
3
+ module AtkinSieve
4
+ def nth_prime(n)
5
+ return Cache[n] if Cache[n]
6
+ Cache.primes = compute_primes(n)
7
+ Cache[n]
8
+ end
9
+
10
+ private
11
+
12
+ def compute_primes(count)
13
+ return Cache.primes if Cache.size > count
14
+ sieve_size = compute_sieve_size(count)
15
+ atkin_sieve(sieve_size).each_with_index.map { |v, p| p if v }.compact
16
+ end
17
+
18
+ # TODO: 52 should be replaced with algorithm to find range which cover expected count of prime numbers
19
+ #
20
+ # As we know the range 1..10**23 contains 1_925_320_391_606_803_968_923 prime numbers
21
+ # (so, the range contains 1.92 % on prime numbers)
22
+ # to find 100 prime numbers we need to create sieve 100 * (100 / 1.92) or 100 * 52
23
+ def compute_sieve_size(count)
24
+ count * 52
25
+ end
26
+
27
+ def atkin_sieve(sieve_size)
28
+ sieve = init_sieve
29
+ filter_sieve(sieve, sieve_size)
30
+ finalize_sieve(sieve, sieve_size)
31
+ sieve
32
+ end
33
+
34
+ def init_sieve
35
+ # 0, 1, 2, 3
36
+ [nil, nil, true, true]
37
+ end
38
+
39
+ def filter_sieve(sieve, sieve_size)
40
+ sieve_size_sqrt = Math.sqrt(sieve_size).floor
41
+
42
+ (1..sieve_size_sqrt).each do |x|
43
+ (1..sieve_size_sqrt).each do |y|
44
+ filter_sieve_iteration(sieve, sieve_size, x, y)
45
+ end
46
+ end
47
+ end
48
+
49
+ def finalize_sieve(sieve, sieve_size)
50
+ sieve_size_sqrt = Math.sqrt(sieve_size).floor
51
+
52
+ (5..sieve_size_sqrt).each do |n|
53
+ next if Cache[n] || !sieve[n]
54
+ step = n**2
55
+ (step..sieve_size).step(step) do |not_prime|
56
+ sieve[not_prime] = false
57
+ end
58
+ end
59
+ end
60
+
61
+ def filter_sieve_iteration(sieve, sieve_size, x, y)
62
+ x2 = x**2
63
+ y2 = y**2
64
+
65
+ apply_first_filter(sieve, sieve_size, x2, y2)
66
+ apply_second_filter(sieve, sieve_size, x2, y2)
67
+ apply_third_filter(sieve, sieve_size, x2, y2) if x > y
68
+ end
69
+
70
+ def apply_first_filter(sieve, sieve_size, x2, y2)
71
+ n = x2 * 4 + y2
72
+ sieve[n] = !sieve[n] if n <= sieve_size && (n % 12 == 1 || n % 12 == 5)
73
+ end
74
+
75
+ def apply_second_filter(sieve, sieve_size, x2, y2)
76
+ n = x2 * 4 + y2 - x2
77
+ sieve[n] = !sieve[n] if n <= sieve_size && n % 12 == 7
78
+ end
79
+
80
+ def apply_third_filter(sieve, sieve_size, x2, y2)
81
+ n = x2 * 4 + y2 - x2 - 2 * y2
82
+ sieve[n] = !sieve[n] if n <= sieve_size && n % 12 == 11
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,15 @@
1
+ module PrimeMultiplicationTable
2
+ # Cache contains already calculated prime numbers.
3
+ module Cache
4
+ class << self
5
+ extend Forwardable
6
+ attr_writer :primes
7
+
8
+ def_delegators :primes, :[], :[]=, :last, :size
9
+
10
+ def primes
11
+ @primes ||= [2, 3]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module PrimeMultiplicationTable
2
+ # Prime contains implementation of comparable prime number.
3
+ class Prime
4
+ include Comparable
5
+ include AtkinSieve
6
+
7
+ attr_reader :value
8
+
9
+ def initialize(position)
10
+ @position = position
11
+ @value = nth_prime(@position)
12
+ end
13
+
14
+ def succ
15
+ self.class.new(@position + 1)
16
+ end
17
+
18
+ def <=>(other)
19
+ @value <=> other.value
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ module PrimeMultiplicationTable
2
+ # Renderer contains implementation of table renderer functionality.
3
+ class Renderer
4
+ def initialize(primes_array)
5
+ @primes_array = primes_array
6
+ end
7
+
8
+ def render
9
+ matrix.map { |r| render_row(r) }.join("\n")
10
+ end
11
+
12
+ private
13
+
14
+ def render_row(row_array)
15
+ row_array.each_with_index.map { |c, i| c.to_s.rjust(cell_size(i)) }.join(' ')
16
+ end
17
+
18
+ def matrix
19
+ @matrix ||= [[nil] + @primes_array] + @primes_array.map do |prime_x|
20
+ @primes_array.each_with_index.each_with_object([]) do |(prime_y, index), result|
21
+ result << prime_x if index.to_i.zero?
22
+ result << prime_x * prime_y
23
+ end
24
+ end
25
+ end
26
+
27
+ def cell_size(cell_index)
28
+ matrix.last[cell_index].to_s.size
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module PrimeMultiplicationTable
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,19 @@
1
+ # Command line interface of prime_multiplication_table gem.
2
+ module PrimeMultiplicationTableCLI
3
+ DEFAULT_TABLE_SIZE = 10
4
+
5
+ class << self
6
+ def run(args)
7
+ puts "prime_multiplication_table (version: #{PrimeMultiplicationTable::VERSION})"
8
+ size = parse_table_size_argument(args)
9
+ prime_class = PrimeMultiplicationTable::Prime
10
+ array = (prime_class.new(0)...prime_class.new(size)).map(&:value)
11
+ puts PrimeMultiplicationTable::Renderer.new(array).render
12
+ end
13
+
14
+ def parse_table_size_argument(args)
15
+ size = args.first.to_i
16
+ size.positive? ? size : DEFAULT_TABLE_SIZE
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../lib/prime_multiplication_table/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'prime_multiplication_table'
5
+ gem.version = PrimeMultiplicationTable::VERSION
6
+ gem.date = '2017-05-08'
7
+ gem.summary = 'Prime multiplication table printer'
8
+ gem.description = 'Ruby gem for printing prime multiplication tables'
9
+ gem.authors = ['Konstantin Lynda']
10
+ gem.email = 'knlynda@gmail.com'
11
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
12
+ gem.test_files = gem.files.grep(%r{^spec/})
13
+ gem.require_paths = ['lib']
14
+ gem.bindir = 'bin'
15
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
16
+ gem.homepage = 'http://rubygems.org/gems/prime_multiplication_table'
17
+ gem.license = 'MIT'
18
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PrimeMultiplicationTable::Cache do
4
+ it { is_expected.to respond_to :primes, :primes=, :[], :[]=, :last, :size }
5
+
6
+ describe '.primes' do
7
+ subject { described_class.primes }
8
+
9
+ it { is_expected.to eql [2, 3] }
10
+ end
11
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PrimeMultiplicationTable::Prime do
4
+ describe '#succ' do
5
+ subject { described_class.new(position) }
6
+
7
+ context 'when position is zero' do
8
+ let(:position) { 0 }
9
+ it { expect(subject.value).to eql 2 }
10
+ end
11
+
12
+ context 'when position is 1' do
13
+ let(:position) { 1 }
14
+ it { expect(subject.value).to eql 3 }
15
+ end
16
+
17
+ context 'when position is 499' do
18
+ let(:position) { 499 }
19
+ it { expect(subject.value).to eql 3571 }
20
+ end
21
+
22
+ context 'when position is -1' do
23
+ let(:position) { -1 }
24
+ it { expect(subject.value).to eql PrimeMultiplicationTable::Cache[-1] }
25
+ end
26
+
27
+ context 'when position is -500_000' do
28
+ let(:position) { -500_000 }
29
+ it { expect(subject.value).to be_nil }
30
+ end
31
+ end
32
+
33
+ describe '#nth_prime' do
34
+ subject { described_class.new(position).nth_prime(new_position) }
35
+
36
+ context 'when position is zero and new_position is 1' do
37
+ let(:position) { 0 }
38
+ let(:new_position) { 1 }
39
+
40
+ it { is_expected.to eql 3 }
41
+ end
42
+
43
+ context 'when position is zero and new_position is zero' do
44
+ let(:position) { 0 }
45
+ let(:new_position) { 0 }
46
+
47
+ it { is_expected.to eql 2 }
48
+ end
49
+
50
+ context 'when position is zero and new_position is 499' do
51
+ let(:position) { 0 }
52
+ let(:new_position) { 499 }
53
+
54
+ it { is_expected.to eql 3571 }
55
+ end
56
+
57
+ context 'when position is zero and new_position is -1' do
58
+ let(:position) { 0 }
59
+ let(:new_position) { -1 }
60
+
61
+ it { is_expected.to eql PrimeMultiplicationTable::Cache[-1] }
62
+ end
63
+
64
+ context 'when position is zero and new_position is -500_000' do
65
+ let(:position) { 0 }
66
+ let(:new_position) { -500_000 }
67
+
68
+ it { is_expected.to be_nil }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PrimeMultiplicationTable::Renderer do
4
+ describe '#render' do
5
+ subject { described_class.new(table_basis).render }
6
+
7
+ context 'when table_basis is empty' do
8
+ let(:table_basis) { [] }
9
+ it { is_expected.to be_empty }
10
+ end
11
+
12
+ context 'when table_basis is not empty' do
13
+ let(:table_basis) { [1, 2, 3] }
14
+ it { is_expected.to eql " 1 2 3\n1 1 2 3\n2 2 4 6\n3 3 6 9" }
15
+ end
16
+
17
+ context 'when table_basis includes big and small numbers' do
18
+ let(:table_basis) { [11, 2, 33] }
19
+ it { is_expected.to eql " 11 2 33\n11 121 22 363\n 2 22 4 66\n33 363 66 1089" }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PrimeMultiplicationTableCLI do
4
+ describe '.run' do
5
+ subject(:run) { described_class.run(args) }
6
+ let(:renderer) { double }
7
+
8
+ before do
9
+ expect(PrimeMultiplicationTable::Renderer).to receive(:new).with(renderer_args).and_return(renderer)
10
+ expect(renderer).to receive(:render)
11
+ end
12
+
13
+ context 'when args is [0]' do
14
+ let(:args) { [0] }
15
+ let(:renderer_args) { [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }
16
+
17
+ it { run }
18
+ end
19
+
20
+ context 'when args is [1]' do
21
+ let(:args) { [1] }
22
+ let(:renderer_args) { [2] }
23
+
24
+ it { run }
25
+ end
26
+
27
+ context 'when args is [1]' do
28
+ let(:args) { [1] }
29
+ let(:renderer_args) { [2] }
30
+
31
+ it { run }
32
+ end
33
+
34
+ context 'when args is [5]' do
35
+ let(:args) { [5] }
36
+ let(:renderer_args) { [2, 3, 5, 7, 11] }
37
+
38
+ it { run }
39
+ end
40
+
41
+ context 'when args is [-1]' do
42
+ let(:args) { [-1] }
43
+ let(:renderer_args) { [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }
44
+
45
+ it { run }
46
+ end
47
+
48
+ context 'when args is ["one"]' do
49
+ let(:args) { ['one'] }
50
+ let(:renderer_args) { [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }
51
+
52
+ it { run }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'prime_multiplication_table'
5
+ require 'prime_multiplication_table_cli'
6
+
7
+ RSpec.configure(&:disable_monkey_patching!)
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prime_multiplication_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Konstantin Lynda
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby gem for printing prime multiplication tables
14
+ email: knlynda@gmail.com
15
+ executables:
16
+ - prime_multiplication_table
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rubocop.yml"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - README.md
25
+ - bin/prime_multiplication_table
26
+ - lib/prime_multiplication_table.rb
27
+ - lib/prime_multiplication_table/atkin_sieve.rb
28
+ - lib/prime_multiplication_table/cache.rb
29
+ - lib/prime_multiplication_table/prime.rb
30
+ - lib/prime_multiplication_table/renderer.rb
31
+ - lib/prime_multiplication_table/version.rb
32
+ - lib/prime_multiplication_table_cli.rb
33
+ - prime_multiplication_table.gemspec
34
+ - spec/lib/prime_multiplication_table/cache_spec.rb
35
+ - spec/lib/prime_multiplication_table/prime_spec.rb
36
+ - spec/lib/prime_multiplication_table/renderer_spec.rb
37
+ - spec/prime_multiplication_table_cli_spec.rb
38
+ - spec/spec_helper.rb
39
+ homepage: http://rubygems.org/gems/prime_multiplication_table
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.5.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Prime multiplication table printer
63
+ test_files:
64
+ - spec/lib/prime_multiplication_table/cache_spec.rb
65
+ - spec/lib/prime_multiplication_table/prime_spec.rb
66
+ - spec/lib/prime_multiplication_table/renderer_spec.rb
67
+ - spec/prime_multiplication_table_cli_spec.rb
68
+ - spec/spec_helper.rb