sperm 0.1.1

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: 2ef71a04bbb2e84a9baa9d94c78c7d2f0a2d3ac3
4
+ data.tar.gz: 343595cd65a161078b48c082bdca8bf0f44c17e9
5
+ SHA512:
6
+ metadata.gz: b674a6080bf35a001cbc34064b0de3de3ac9181d2e52c6039560e03c3678d7c6b5ee2ae05f72946ac76c76d62d05d84c94f34ae66bc0396b1bf19b7d451281aa
7
+ data.tar.gz: 568b52e9c823c7ca2578133cd733813075e32951e2c0785b9e13b99a46f70e6e7a07e8cebe95b07448773fd4090ab092170b0ec7f82125d7e17d004c64fd0df3
@@ -0,0 +1,12 @@
1
+ # editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ indent_style = space
6
+ indent_size = 2
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.md]
12
+ trim_trailing_whitespace = false
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ Excludes:
3
+ - vendor/**
4
+ LineLength:
5
+ Max: 119
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Arthur Khashaev
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # Stupendous Permutations
2
+ **Sperm** is a random permutations generator based on the ideas of group
3
+ theory that allows you to generate very large permutations without extra
4
+ memory consumption.
5
+
6
+ [![Gem Version](https://badge.fury.io/rb/sperm.png)](https://badge.fury.io/rb/sperm)
7
+ [![Build Status](https://travis-ci.org/Invizory/sperm.png)](https://travis-ci.org/Invizory/sperm)
8
+ [![Code Climate](https://codeclimate.com/github/Invizory/sperm.png)](https://codeclimate.com/github/Invizory/sperm)
9
+ [![Coverage Status](https://coveralls.io/repos/Invizory/sperm/badge.png)](https://coveralls.io/r/Invizory/sperm)
10
+
11
+ ## Installation
12
+ Add this line to your application's Gemfile:
13
+ ```ruby
14
+ gem 'sperm'
15
+ ```
16
+
17
+ And then execute:
18
+ ```bash
19
+ $ bundle
20
+ ```
21
+
22
+ Or install it yourself as:
23
+ ```bash
24
+ $ gem install sperm
25
+ ```
26
+
27
+ ## Usage
28
+ ```ruby
29
+ Sperm.rand(5).each { |element| puts element }
30
+ ```
31
+
32
+ This is a shorthand for:
33
+ ```ruby
34
+ Sperm::RandomPermutations.new(5).rand.each { |element| puts element }
35
+ ```
36
+
37
+ You can also use your own source of randomness:
38
+ ```ruby
39
+ Sperm::RandomPermutations.new(5, Random.new(42))
40
+ Sperm::RandomPermutations.new(10**8, SecureRandom)
41
+ ```
42
+
43
+ ## How it works
44
+ ### Computational complexity
45
+ Operation | Time complexity | Space complexity
46
+ ---------------------------|--------------------|------------------
47
+ Initialization | O(n/ϕ(n) · log(n)) | O(1)
48
+ Generation of next element | O(1) | O(1)
49
+
50
+ ## Copyright
51
+ Copyright © 2014 [Arthur Khashaev]. See [LICENSE.txt](LICENSE.txt) for details.
52
+
53
+ [Arthur Khashaev]: http://khashaev.ru/
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubocop/rake_task'
3
+ require 'rspec/core/rake_task'
4
+
5
+ Rubocop::RakeTask.new
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sperm'
4
+ require 'optparse'
5
+
6
+ optparse = OptionParser.new do |opts|
7
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options] order"
8
+
9
+ opts.on_tail '-p', '--permutation ORDER', Integer,
10
+ 'Generate permutation of specified order' do |order|
11
+ Sperm.rand(order).each { |element| puts element }
12
+ exit
13
+ end
14
+
15
+ opts.on_tail '-h', '--help', 'Just display this help' do
16
+ puts opts
17
+ exit
18
+ end
19
+
20
+ opts.on_tail '-v', '--version', 'Just print the version infomation' do
21
+ puts "Sperm #{Sperm::VERSION}"
22
+ exit
23
+ end
24
+ end
25
+
26
+ optparse.parse!
@@ -0,0 +1,55 @@
1
+ -
2
+ prime: 17
3
+ generator: 3
4
+ order_phi: 8
5
+ order_factors: [2, 2, 2, 2]
6
+ -
7
+ prime: 107
8
+ generator: 2
9
+ order_phi: 52
10
+ order_factors: [2, 53]
11
+ -
12
+ prime: 1019
13
+ generator: 2
14
+ order_phi: 508
15
+ order_factors: [2, 509]
16
+ -
17
+ prime: 10007
18
+ generator: 5
19
+ order_phi: 5038
20
+ order_factors: [2, 5003]
21
+ -
22
+ prime: 100043
23
+ generator: 2
24
+ order_phi: 50020
25
+ order_factors: [2, 50021]
26
+ -
27
+ prime: 1000667
28
+ generator: 2
29
+ order_phi: 500332
30
+ order_factors: [2, 500333]
31
+ -
32
+ prime: 10000223
33
+ generator: 5
34
+ order_phi: 5000110
35
+ order_factors: [2, 5000111]
36
+ -
37
+ prime: 100000127
38
+ generator: 5
39
+ order_phi: 50000062
40
+ order_factors: [2, 50000063]
41
+ -
42
+ prime: 1000000007
43
+ generator: 5
44
+ order_phi: 500000002
45
+ order_factors: [2, 500000003]
46
+ -
47
+ prime: 1000099403
48
+ generator: 2
49
+ order_phi: 500049700
50
+ order_factors: [2, 500049701]
51
+ -
52
+ prime: 4100000027
53
+ generator: 2
54
+ order_phi: 2050000012
55
+ order_factors: [2, 2050000013]
@@ -0,0 +1,11 @@
1
+ require 'sperm/version'
2
+ require 'sperm/exceptions'
3
+ require 'sperm/random_permutations'
4
+
5
+ # Sperm is an efficient random permutations generator.
6
+ #
7
+ module Sperm
8
+ def self.rand(order)
9
+ RandomPermutations.new(order).rand
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Sperm
2
+ # This runtime error appears when requested permutation order is bigger
3
+ # than maximum group order in known set of cyclic groups.
4
+ #
5
+ class NoSuitableGroup < RuntimeError
6
+ attr_reader :order
7
+
8
+ def initialize(order)
9
+ @order = order
10
+ end
11
+
12
+ def to_s
13
+ "no suitable group for permutation of order #{order} found"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ require 'sperm/groups/additive'
2
+ require 'sperm/groups/multiplicative'
3
+ require 'sperm/groups/isomorphism'
4
+ require 'sperm/groups/multiplicative_shuffler'
5
+ require 'sperm/groups/intmod'
6
+ require 'sperm/groups/collection'
@@ -0,0 +1,28 @@
1
+ require 'sperm/groups/intmod'
2
+
3
+ module Sperm::Groups
4
+ # Represents (Z/nZ, +) - an additive cyclic group of integers modulo n.
5
+ #
6
+ class ZnAdd
7
+ include Zn
8
+
9
+ attr_reader :modulo
10
+ alias_method :order, :modulo
11
+
12
+ def initialize(modulo_factors)
13
+ @modulo_factors = modulo_factors.uniq
14
+ @modulo = modulo_factors.inject(1, &:*)
15
+ end
16
+
17
+ def generator?(number)
18
+ fail ArgumentError, 'not an element' unless include?(number)
19
+ @modulo_factors.all? { |prime| coprime_with_prime?(number, prime) }
20
+ end
21
+
22
+ private
23
+
24
+ def coprime_with_prime?(number, prime)
25
+ number % prime != 0
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ require 'sperm/groups/additive'
2
+ require 'sperm/groups/multiplicative'
3
+ require 'sperm/groups/isomorphism'
4
+
5
+ require 'ostruct'
6
+ require 'yaml'
7
+
8
+ module Sperm::Groups
9
+ # Represents collection of known cyclic groups that can be used
10
+ # for generating random permutations.
11
+ #
12
+ class GroupsCollection
13
+ def initialize(isomorphisms)
14
+ @isomorphisms = isomorphisms.sort_by { |isomorphism| isomorphism.order }
15
+ end
16
+
17
+ def find_suitable_isomorphism(order)
18
+ @isomorphisms.bsearch { |isomorphism| isomorphism.order >= order }
19
+ end
20
+
21
+ def self.load_file(path)
22
+ array = YAML.load_file(path)
23
+ isomorphisms = array.map { |hash| OpenStruct.new(hash) }.map do |group|
24
+ add_group = ZnAdd.new(group.order_factors)
25
+ mul_group = ZpMul.new(group.prime, group.generator)
26
+ Isomorphism.new(add_group, mul_group)
27
+ end
28
+ new(isomorphisms)
29
+ end
30
+
31
+ DEFAULT_FILE = File.expand_path('../../../../data/groups.yml', __FILE__)
32
+ DEFAULT = load_file(DEFAULT_FILE)
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module Sperm::Groups
2
+ # Represents Z/nZ group.
3
+ #
4
+ module Zn
5
+ def include?(element)
6
+ (0...modulo).include?(element)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ require 'forwardable'
2
+ require 'openssl'
3
+
4
+ module Sperm::Groups
5
+ # Provides isomorphism from (Z/(p-1)Z, +) to (Z/pZ \ {0}, *).
6
+ #
7
+ class Isomorphism
8
+ extend Forwardable
9
+
10
+ attr_reader :add_group, :mul_group
11
+ def_delegator :add_group, :order
12
+
13
+ def initialize(add_group, mul_group)
14
+ fail ArgumentError, 'unequal orders' unless add_group.order == mul_group.order
15
+ @add_group = add_group
16
+ @mul_group = mul_group
17
+ end
18
+
19
+ def map(number)
20
+ fail ArgumentError, 'not an element' unless add_group.include?(number)
21
+ mul_group.generator.to_bn.mod_exp(number, mul_group.modulo).to_i
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ require 'sperm/groups/intmod'
2
+
3
+ module Sperm::Groups
4
+ # Represents (Z/pZ \ {0}, *) - a multiplicative cyclic group of integers
5
+ # modulo p.
6
+ #
7
+ class ZpMul
8
+ include Zn
9
+
10
+ attr_reader :prime, :generator
11
+ alias_method :modulo, :prime
12
+
13
+ def initialize(prime, generator)
14
+ @prime = prime
15
+ @generator = generator
16
+ end
17
+
18
+ def order
19
+ modulo - 1
20
+ end
21
+
22
+ def produce_cycle(first, multiplier)
23
+ fail ArgumentError, 'not an element' unless include?(first) && include?(multiplier)
24
+ Enumerator.new do |yielder|
25
+ current = first
26
+ loop do
27
+ yielder.yield current
28
+ current = (current * multiplier) % modulo
29
+ break if current == first
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ module Sperm::Groups
2
+ # Generates random cyclic representations of (Z/pZ \ {0}, *).
3
+ #
4
+ class ZpMulShuffler
5
+ def initialize(isomorphism, rand_source)
6
+ @isomorphism, @rand_source = isomorphism, rand_source
7
+ end
8
+
9
+ def rand
10
+ first = 1 + @rand_source.rand(mul_group.modulo - 1)
11
+ mul_group.produce_cycle(first, rand_mul_generator).lazy
12
+ end
13
+
14
+ private
15
+
16
+ def rand_mul_generator
17
+ add_gen = rand_add_generator
18
+ @isomorphism.map(add_gen)
19
+ end
20
+
21
+ def rand_add_generator
22
+ gen = @rand_source.rand(add_group.modulo)
23
+ gen = (gen + 1) % add_group.modulo until add_group.generator?(gen)
24
+ gen
25
+ end
26
+
27
+ def add_group
28
+ @isomorphism.add_group
29
+ end
30
+
31
+ def mul_group
32
+ @isomorphism.mul_group
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ require 'sperm/groups'
2
+ require 'sperm/exceptions'
3
+ require 'sperm/random_source'
4
+
5
+ module Sperm
6
+ # Generates random permutations of given order.
7
+ #
8
+ class RandomPermutations
9
+ attr_reader :order
10
+
11
+ def initialize(order, random = Random.new, groups = Groups::GroupsCollection::DEFAULT)
12
+ isomorphism = groups.find_suitable_isomorphism(order)
13
+ fail NoSuitableGroup, order unless isomorphism
14
+ random_source = RandomSource.new(random)
15
+ @order = order
16
+ @shuffler = Groups::ZpMulShuffler.new(isomorphism, random_source)
17
+ end
18
+
19
+ def rand
20
+ @shuffler.rand.select { |element| element.between?(1, order) }.map { |element| element - 1 }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ module Sperm
2
+ # Internal wrapper for Random instances and RandomSecure.
3
+ #
4
+ class RandomSource
5
+ include Forwardable
6
+
7
+ def initialize(adaptee)
8
+ @adaptee = adaptee
9
+
10
+ %i(rand random_number).each do |method|
11
+ next unless @adaptee.respond_to? method
12
+ def_delegator :@adaptee, method, :rand
13
+ return
14
+ end
15
+
16
+ fail ArgumentError, 'unsupported source of randomness'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # Sperm is an efficient random permutations generator.
2
+ #
3
+ module Sperm
4
+ VERSION = '0.1.1'
5
+ end
@@ -0,0 +1,28 @@
1
+ if ENV['COVERAGE'] || ENV['TRAVIS']
2
+ require 'simplecov'
3
+ require 'coveralls'
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
+ SimpleCov::Formatter::HTMLFormatter,
7
+ Coveralls::SimpleCov::Formatter
8
+ ]
9
+ SimpleCov.start do
10
+ add_filter '/vendor/'
11
+ add_filter '/spec/'
12
+ end
13
+ end
14
+
15
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
16
+ require 'sperm'
17
+
18
+ # Some helpers for Enumerable.
19
+ #
20
+ module Enumerable
21
+ def permutation?
22
+ sort.to_a == (0...count).to_a
23
+ end
24
+
25
+ def empty?
26
+ count == 0
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sperm::RandomPermutations do
4
+ subject { Sperm::RandomPermutations.new(order) }
5
+
6
+ describe '#rand' do
7
+ context 'when order is zero' do
8
+ let(:order) { 0 }
9
+ it 'generates an empty permutation' do
10
+ expect(subject.rand).to be_empty
11
+ end
12
+ end
13
+
14
+ context 'when order is small' do
15
+ let(:order) { 42 }
16
+ it 'generates a permutation' do
17
+ expect(subject.rand).to be_a_permutation
18
+ end
19
+ end
20
+
21
+ context 'when order is large' do
22
+ let(:order) { 10**8 }
23
+ it 'generates at least first element of permutation' do
24
+ expect(subject.rand.first).to be_between(0, order - 1)
25
+ end
26
+ end
27
+
28
+ context 'when order is too large' do
29
+ let(:order) { 10**100 }
30
+ it 'raises an error' do
31
+ expect { subject }.to raise_error Sperm::NoSuitableGroup
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sperm do
4
+ it 'has a version number' do
5
+ expect(Sperm::VERSION).not_to be_nil
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'sperm/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'sperm'
9
+ spec.version = Sperm::VERSION
10
+
11
+ spec.author = 'Arthur Khashaev'
12
+ spec.email = 'arthur@khashaev.ru'
13
+
14
+ spec.summary = 'Sperm is an efficient random permutations generator'
15
+ spec.description = 'Sperm is a random permutations generator ' \
16
+ 'based on the ideas of group theory ' \
17
+ 'that allows you to generate stupendous permutations ' \
18
+ 'without extra memory consumption.'
19
+
20
+ spec.homepage = 'https://github.com/Invizory/sperm'
21
+ spec.license = 'MIT'
22
+
23
+ spec.files = `git ls-files -z`.split("\x0")
24
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_development_dependency 'bundler', "~> 1.5"
29
+ spec.add_development_dependency 'rake'
30
+ spec.add_development_dependency 'rspec'
31
+ spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'simplecov'
33
+ spec.add_development_dependency 'coveralls'
34
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sperm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Arthur Khashaev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Sperm is a random permutations generator based on the ideas of group
98
+ theory that allows you to generate stupendous permutations without extra memory
99
+ consumption.
100
+ email: arthur@khashaev.ru
101
+ executables:
102
+ - sperm
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - .editorconfig
107
+ - .gitignore
108
+ - .rspec
109
+ - .rubocop.yml
110
+ - .travis.yml
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - bin/sperm
116
+ - data/groups.yml
117
+ - lib/sperm.rb
118
+ - lib/sperm/exceptions.rb
119
+ - lib/sperm/groups.rb
120
+ - lib/sperm/groups/additive.rb
121
+ - lib/sperm/groups/collection.rb
122
+ - lib/sperm/groups/intmod.rb
123
+ - lib/sperm/groups/isomorphism.rb
124
+ - lib/sperm/groups/multiplicative.rb
125
+ - lib/sperm/groups/multiplicative_shuffler.rb
126
+ - lib/sperm/random_permutations.rb
127
+ - lib/sperm/random_source.rb
128
+ - lib/sperm/version.rb
129
+ - spec/spec_helper.rb
130
+ - spec/sperm/random_permutations_spec.rb
131
+ - spec/sperm_spec.rb
132
+ - sperm.gemspec
133
+ homepage: https://github.com/Invizory/sperm
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.0.7
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Sperm is an efficient random permutations generator
157
+ test_files:
158
+ - spec/spec_helper.rb
159
+ - spec/sperm/random_permutations_spec.rb
160
+ - spec/sperm_spec.rb