congruence_solver 0.2.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b8cdf5634b888651240db1d379330c26e0915815
4
+ data.tar.gz: cb6e241768d62d727196d40600aed3da6c8d8cbd
5
+ SHA512:
6
+ metadata.gz: c656aba94e133852ff5a6cb03cb4e4d35e7df80bc60205254caf6ffb1b8bb486121c939a2f8c63dce9dc3881b7ad48840d7a63619b1839faa18acca2148a72bb
7
+ data.tar.gz: 84930366fe58c6f75167c673b180b5d1dcc89e38540160f0281b1c10ba100eb7603d23f63ea6346d8ea7117030ae2274d27f82433cc9c5542aa9496d3ee4f146
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ Gemfile
2
+ Gemfile.lock
3
+ tmp/
4
+ todo
5
+ lib/congruence_solver/congruence_solver.so
6
+ *.gem
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "ext/congruence_solver"]
2
+ path = ext/congruence_solver
3
+ url = https://github.com/laneb/congruence_solver_ext.git
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.4
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # CongruenceSolver
2
+
3
+ CongruenceSolver is a gem for solving polynomial congruences. Should you ever need to solve polynomial congruences and have Ruby installed, this is the gem for you!
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'congruence_solver'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install congruence_solver
20
+
21
+ ## Usage
22
+
23
+ To solve a polynomial congruence at the command line, simply invoke `csolve` and then enter the congruence at the prompt.
24
+
25
+ ```
26
+ csolve
27
+ Congruence to solve:
28
+ x^2 + 2x + 1 = x^3 + 3x^5 mod 49
29
+ (0) 1
30
+ (1) 8
31
+ (2) 15
32
+ (3) 22
33
+ (4) 26
34
+ (5) 29
35
+ (6) 36
36
+ (7) 43
37
+ ```
38
+
39
+ To use the CongruenceSolver in a Ruby program, use CongruenceSolve::solve_congruence(coeffs, mod), where coeffs is the ascending list of coefficients of the polynomial (congruent to 0) and mod is the modulus of the congruence.
40
+
41
+ ```
42
+ #solve -3x^5 - x^3 + x^2 + 2x + 1 = 0 mod 49
43
+ coeffs = [1, 2, 1, 1, 0, 3]
44
+ mod = 49
45
+ CongruenceSolver.solve_congruence(coeffs, mod).sort #=> [1, 8, 15, 22, 26, 29, 36, 43]
46
+ ```
47
+
48
+ ## Development
49
+
50
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests, or rake bench to run the benchmark.
51
+
52
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at https://github.com/laneb/congruence_solver.
57
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ #require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require 'rake/extensiontask'
4
+
5
+
6
+
7
+
8
+ =begin
9
+ namespace :test do
10
+ desc "Compile and unit test C extensions"
11
+ Rspec::Core::RakeTask.new :c => :compile_c do |t|
12
+ t.rspec_opts = C_SPEC_FILE
13
+ end
14
+ end
15
+ =end
16
+
17
+ #exe runs the csolve binary
18
+ task :exe do
19
+ $LOAD_PATH << "#{Dir.pwd}/lib/"
20
+ require_relative "bin/csolve.rb"
21
+ end
22
+
23
+ #spec runs all RSpec examples
24
+ RSpec::Core::RakeTask.new :spec
25
+
26
+ #uses task template provided by rake-compiler to run the extension compilation
27
+ #workflow. Task name: compile (do not use task name: ext)
28
+ Rake::ExtensionTask.new 'congruence_solver' do |ext|
29
+ ext.lib_dir = "lib/congruence_solver"
30
+ end
31
+
32
+ task :bench do
33
+ $LOAD_PATH << "#{Dir.pwd}/lib/"
34
+ Dir.foreach("bench") do |bm_file|
35
+ path = "bench/#{bm_file}"
36
+ if File.file? path and path =~ "_bm.rb^"
37
+ require_relative path
38
+ end
39
+ end
40
+ end
41
+
42
+ #executes compile task defined above, then cleans up the tmp directory that
43
+ #rake-compiler leaves behind for some reason
44
+ task :compile_c => :compile do
45
+ CLEAN_CMD = "rmdir /s /q tmp"
46
+ system CLEAN_CMD
47
+ end
48
+
49
+
50
+
51
+
52
+
53
+
@@ -0,0 +1,33 @@
1
+
2
+ def polynomial_to_s(coeffs)
3
+ polynomial = ""
4
+ is_first_term = true
5
+
6
+ coeffs.reverse.each_with_index do |coe, idx|
7
+ exp = coeffs.length - idx - 1
8
+ if coe != 0
9
+ if is_first_term
10
+ is_first_term = false
11
+ else
12
+ if coe < 0
13
+ polynomial << " - "
14
+ else
15
+ polynomial << " + "
16
+ end
17
+ end
18
+
19
+ if coe.abs > 1 or (coe.abs == 1 and exp < 2)
20
+ polynomial << coe.abs.to_s
21
+ end
22
+
23
+ if exp > 0
24
+ polynomial << "x"
25
+ if exp > 1
26
+ polynomial << "^#{exp}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ polynomial
33
+ end
@@ -0,0 +1,71 @@
1
+ require "congruence_solver"
2
+ require "benchmark"
3
+ require_relative "./bench_tools.rb"
4
+
5
+
6
+ SMALL_DEG_POLYNOMIAL_COEFFS = [1, -4, 4]
7
+ LARGE_DEG_POLYNOMIAL_COEFFS = [-11, 0, 0, 3, 0, 0, 0, 0, 0, 10]
8
+ SMALL_MOD = 49
9
+ MED_MOD = 5104
10
+ LARGE_MOD = 94122
11
+ XTRA_LARGE_MOD = 401249
12
+ XTRA_LARGE_PRIME_MOD = 306893
13
+ SMALL_FACTORED_LARGE_MOD = 510510
14
+
15
+
16
+ def solve_congruence_brute_force(coeffs, mod)
17
+ solutions = []
18
+
19
+ 0.upto(mod) do |x|
20
+ sum = 0
21
+
22
+ coeffs.each_with_index do |coe, exp|
23
+ sum = (sum + coe*x**exp) % mod
24
+ end
25
+
26
+ if sum == 0 then solutions << x end
27
+ end
28
+
29
+ solutions
30
+ end
31
+
32
+
33
+ def bm_solve_congruence(coeffs, mod)
34
+ puts "Solving #{polynomial_to_s(coeffs)} = 0 mod #{mod}"
35
+
36
+ rb_bf_solutions = solve_congruence_brute_force(coeffs, mod).sort
37
+ #c_bf_solutions = CongruenceSolver.brute_force(coeffs, mod).sort
38
+ c_lifting_solutions = CongruenceSolver.lift(coeffs, mod).sort
39
+
40
+ unless rb_bf_solutions == c_lifting_solutions #and c_bf_solutions c_lift_solutions
41
+ puts "Solutions do not match:"
42
+ puts "Ruby/force solutions #{rb_bf_solutions.inspect}"
43
+ #puts "C/force solutions #{c_bf_solutions}"
44
+ puts "C/lifting solutions: #{c_lifting_solutions.inspect}"
45
+ end
46
+
47
+ puts "Time measurements:"
48
+
49
+ Benchmark.bmbm do |bm|
50
+ bm.report("Ruby/force") do
51
+ solve_congruence_brute_force(coeffs, mod)
52
+ end
53
+ =begin
54
+ bm.report("C/force") do
55
+ CongruenceSolver.brute_force(coeffs, mod)
56
+ end
57
+ =end
58
+ bm.report("C/lifting") do
59
+ CongruenceSolver.lift(coeffs, mod)
60
+ end
61
+ end
62
+
63
+ print "\n\n"
64
+ end
65
+
66
+
67
+ [SMALL_DEG_POLYNOMIAL_COEFFS, LARGE_DEG_POLYNOMIAL_COEFFS].each do |coeffs|
68
+ [SMALL_MOD, MED_MOD, LARGE_MOD, XTRA_LARGE_MOD, XTRA_LARGE_PRIME_MOD, SMALL_FACTORED_LARGE_MOD].each do |mod|
69
+ bm_solve_congruence(coeffs, mod)
70
+ end
71
+ end
data/bin/csolve.rb ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ require 'congruence_solver'
3
+ require "polynomial_interpreter"
4
+
5
+
6
+ SOLVE_CONGRUENCE_BENCH_FILE = "../bench/solve_congruence_bm.rb"
7
+
8
+
9
+ if ARGV.pop == "bench"
10
+ require_relative SOLVE_CONGRUENCE_BENCH_FILE
11
+ exit(0)
12
+ end
13
+
14
+ CONGRUENCE_FORMAT = "(lhs polynomial) = (rhs polynomial) mod (modulus)"
15
+ CONGRUENCE_INVALID_MSG = "Congruence invalid: congruences must be of form:\n#{CONGRUENCE_FORMAT}"
16
+ POLYNOMIAL_FORMAT = "ax^b+cx^d...\n(integer coefficients, positive integer exponents, order irrelevant)"
17
+ LHS_INVALID_MSG = "Left hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
18
+ RHS_INVALID_MSG = "Right hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
19
+ MOD_INVALID_MSG = "Mod invalid: modulus must be an integer greater than 2"
20
+
21
+ puts "Congruence to solve:"
22
+
23
+ begin
24
+ coeffs, mod = PolynomialInterpreter.read_congruence(STDIN.gets)
25
+ rescue ArgumentError => e
26
+ if(e == PolynomialInterpreter::Errors::CONGRUENCE_INVALID)
27
+ STDERR.puts CONGRUENCE_INVALID_MSG
28
+ exit(1)
29
+
30
+ elsif(e == PolynomialInterpreter::Errors::LHS_POLYNOMIAL_INVALID)
31
+ STDERR.puts LHS_INVALID_MSG
32
+ exit(1)
33
+
34
+ elsif(e == PolynomialInterpreter::Errors::RHS_POLYNOMIAL_INVALID)
35
+ STDERR.puts RHS_INVALID_MSG
36
+ exit(1)
37
+
38
+ elsif(e == PolynomialInterpreter::Errors::MOD_INVALID)
39
+ STDERR.puts MOD_INVALID_MSG
40
+ exit(1)
41
+
42
+ else
43
+ raise e
44
+ end
45
+ end
46
+
47
+ solutions = CongruenceSolver.lift(coeffs, mod).sort
48
+
49
+ if solutions.empty?
50
+ puts "No solution."
51
+ else
52
+ puts "Solutions:"
53
+ solutions.each_with_index {|sol, i| puts "(#{i}) #{sol}"}
54
+ end
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'congruence_solver/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "congruence_solver"
8
+ spec.version = CongruenceSolver::VERSION
9
+ spec.authors = ["lane"]
10
+ spec.email = ["lane.barlow@gmail.com"]
11
+
12
+ spec.summary = "A gem for solving polynomial congruences."
13
+ spec.description = "Provides a class (CongruenceSolver) for finding the modular zeros of a
14
+ polynomial (given the coefficients and modulus) and a binary (csolve) to
15
+ to solve your congruences at the command line."
16
+ spec.homepage = "https://github.com/laneb/congruence_solver"
17
+
18
+ spec.files = `git ls-files`.split("\n")
19
+ spec.files += `git submodule --quiet foreach pwd`.split("\n").map do |abs_dir|
20
+ rel_dir = abs_dir.gsub(Dir::pwd, "")
21
+ Dir::entries(rel_dir).select {|f| File::file? f}
22
+ end.flatten
23
+ spec.bindir = "bin"
24
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.extensions << "ext/congruence_solver/extconf.rb"
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec", "~> 2.4"
32
+ spec.add_development_dependency "rake-compiler", "~>0.9"
33
+ end
@@ -0,0 +1,4 @@
1
+ require "mkmf"
2
+
3
+
4
+ create_makefile "congruence_solver"
@@ -0,0 +1,3 @@
1
+ module CongruenceSolver
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "congruence_solver/version"
2
+ require "congruence_solver/congruence_solver"
3
+
4
+ module CongruenceSolver
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,116 @@
1
+ class PolynomialInterpreter
2
+ module Errors
3
+ POLYNOMIAL_INVALID = ArgumentError.new "polynomial invalid"
4
+ CONGRUENCE_INVALID = ArgumentError.new "congruence invalid"
5
+ LHS_POLYNOMIAL_INVALID = ArgumentError.new "lhs polynomial invalid"
6
+ RHS_POLYNOMIAL_INVALID = ArgumentError.new "rhs polynomial invalid"
7
+ MOD_INVALID = ArgumentError.new "mod invalid"
8
+ end
9
+
10
+
11
+ def self.read_congruence(input_congruence)
12
+ match_data = input_congruence.match(/^(.*)=(.*) +(?:mod +(.*)|\(mod +(.*)\))$/)
13
+
14
+ if match_data.nil?
15
+ raise Errors::CONGRUENCE_INVALID
16
+ end
17
+
18
+ lhs = match_data[1]
19
+ rhs = match_data[2]
20
+ mod = match_data[3] || match_data[4]
21
+
22
+ begin
23
+ lh_coeffs = read_coeffs(lhs.gsub(" ", ""))
24
+ rescue ArgumentError => e
25
+ if(e == Errors::POLYNOMIAL_INVALID)
26
+ raise Errors::LHS_POLYNOMIAL_INVALID
27
+ else
28
+ raise e
29
+ end
30
+ end
31
+
32
+ begin
33
+ rh_coeffs = read_coeffs(rhs.gsub(" ", ""))
34
+ rescue ArgumentError => e
35
+ if e == Errors::POLYNOMIAL_INVALID
36
+ raise Errors::RHS_POLYNOMIAL_INVALID
37
+ else
38
+ raise e
39
+ end
40
+ end
41
+
42
+ if mod !~ /\d+/ or mod.to_i < 2
43
+ raise Errors::MOD_INVALID
44
+ end
45
+
46
+ 0.upto rh_coeffs.length-1 do |idx|
47
+ unless rh_coeffs[idx].nil?
48
+ lh_coeffs[idx] ||= 0
49
+ lh_coeffs[idx] -= rh_coeffs[idx]
50
+ end
51
+ end
52
+
53
+ [lh_coeffs, mod.to_i]
54
+ end
55
+
56
+ def self.read_coeffs(input_polynomial)
57
+ if input_polynomial == ""
58
+ raise Errors::POLYNOMIAL_INVALID
59
+ end
60
+
61
+ last_var = nil
62
+ coeffs = Array.new
63
+
64
+ loop do
65
+ input_polynomial.slice!(/^(\d+)\*?/)
66
+ match_data_coe = Regexp.last_match
67
+
68
+ input_polynomial.slice!(/^([a-zA-Z])(?:\^(\d+))?/)
69
+ match_data_exp = Regexp.last_match
70
+
71
+ if match_data_coe.nil? and match_data_exp.nil?
72
+ raise ArgumentError, INVALID_POLYNOMIAL_MSG
73
+ else
74
+ if match_data_exp.nil?
75
+ coe = match_data_coe[1].to_i
76
+ exp = 0
77
+ else
78
+ unless last_var.nil? or last_var == match_data_exp[1]
79
+ raise Errors::POLYNOMIAL_INVALID
80
+ end
81
+
82
+ last_var = match_data_exp[1]
83
+
84
+ if match_data_coe.nil?
85
+ coe = 1
86
+ else
87
+ coe = match_data_coe[1].to_i
88
+ end
89
+
90
+ if match_data_exp[2].nil?
91
+ exp = 1
92
+ else
93
+ exp = match_data_exp[2].to_i
94
+ end
95
+ end
96
+ end
97
+
98
+ coeffs[exp] ||= 0
99
+ coeffs[exp] += coe.to_i
100
+
101
+ break if input_polynomial.length == 0
102
+
103
+ op = input_polynomial.slice!(0)
104
+
105
+ unless op.match /[-+]/
106
+ raise Errors::POLYNOMIAL_INVALID
107
+ end
108
+ end
109
+
110
+ 0.upto(coeffs.length-1) do |idx|
111
+ coeffs[idx] ||= 0
112
+ end
113
+
114
+ coeffs
115
+ end
116
+ end
@@ -0,0 +1,38 @@
1
+ require "congruence_solver"
2
+
3
+ RSpec.describe CongruenceSolver do
4
+ describe "::lift" do
5
+ it "expects 3 arguments" do
6
+ expect {CongruenceSolver.lift()}.to raise_error ArgumentError
7
+ expect {CongruenceSolver.lift(0)}.to raise_error ArgumentError
8
+ expect {CongruenceSolver.lift([1,2], 3)}.not_to raise_error
9
+ expect {CongruenceSolver.lift([1], [1], nil)}.to raise_error ArgumentError
10
+ end
11
+
12
+
13
+ it "solves individual polynomial congruences defined by their coefficients and mod" do
14
+ coeffs = [-1, 0, 4]
15
+ mod = 5
16
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 3]
17
+
18
+ coeffs = [-3, 4, 9]
19
+ mod = 49
20
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
21
+
22
+ coeffs = [1, -4, 4]
23
+ mod = 5104
24
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
25
+
26
+ coeffs = [4, -4, 1]
27
+ mod = 5104
28
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 1278, 2554, 3830]
29
+
30
+ coeffs = Array.new(500, 0)
31
+ coeffs[0] = -1
32
+ coeffs[500] = 1
33
+ mod = 15
34
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [1, 2, 4, 7, 8, 11, 13, 14]
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,89 @@
1
+ require "polynomial_interpreter"
2
+
3
+ RSpec.describe PolynomialInterpreter do
4
+ describe "::read_congruence" do
5
+ context "when input contains no '\='" do
6
+ it "raises an ArgumentError" do
7
+ not_congruence = "x^2 (mod 5)"
8
+ expect {PolynomialInterpreter.read_congruence not_congruence}.to raise_error ArgumentError, "congruence invalid"
9
+ end
10
+ end
11
+
12
+ context "when input contains no mod" do
13
+ it "raises an ArgumentError" do
14
+ not_congruence = "x^2 = 3"
15
+ expect {PolynomialInterpreter.read_congruence not_congruence}.to raise_error ArgumentError, "congruence invalid"
16
+ end
17
+ end
18
+
19
+ context "when input contains an invalid mod" do
20
+ it "raises an ArgumentError" do
21
+ not_congruence = "x = 5 (mod)"
22
+ expect {PolynomialInterpreter.read_congruence not_congruence}.to raise_error ArgumentError, "congruence invalid"
23
+ end
24
+ end
25
+
26
+ context "when lhs is empty" do
27
+ it "raises an ArgumentError" do
28
+ congruence = "= 3 (mod 4)"
29
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "lhs polynomial invalid"
30
+ end
31
+ end
32
+
33
+ context "when lhs contains invalid characters" do
34
+ it "raises an ArgumentError" do
35
+ congruence = "x! = 3 (mod 5)"
36
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "lhs polynomial invalid"
37
+ end
38
+ end
39
+
40
+ context "when lhs contains more than one distinct variables" do
41
+ it "raises an ArgumentError" do
42
+ congruence = "x^2 + y = 0 (mod 6)"
43
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "lhs polynomial invalid"
44
+ end
45
+ end
46
+
47
+ context "when lhs contains negative power" do
48
+ it "raises an ArgumentError" do
49
+ congruence = "x^-1 = 2 (mod 35)"
50
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "lhs polynomial invalid"
51
+ end
52
+ end
53
+
54
+ context "when rhs is empty" do
55
+ it "raises an ArgumentError" do
56
+ congruence = "x^3 = (mod 4)"
57
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "rhs polynomial invalid"
58
+ end
59
+ end
60
+
61
+ context "when rhs contains invalid characters" do
62
+ it "raises an ArgumentError" do
63
+ congruence = "3 = x! (mod 5)"
64
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "rhs polynomial invalid"
65
+ end
66
+ end
67
+
68
+ context "when rhs contains more than one distinct variables" do
69
+ it "raises an ArgumentError" do
70
+ congruence = "0 = x^2 + y (mod 6)"
71
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "rhs polynomial invalid"
72
+ end
73
+ end
74
+
75
+ context "when rhs contains negative power" do
76
+ it "raises an ArgumentError" do
77
+ congruence = "2 = x^-1 (mod 35)"
78
+ expect {PolynomialInterpreter.read_congruence congruence}.to raise_error ArgumentError, "rhs polynomial invalid"
79
+ end
80
+ end
81
+
82
+ context "when input is a valid polynomial congruence" do
83
+ it "formats congruence as a single polynomial congruent to 0" do
84
+ congruence = "45x^5 + 5 + 3x ^6 + 5x^2 + x + 3x^5=x^9 + 9 x (mod 16)"
85
+ expect( PolynomialInterpreter.read_congruence(congruence)).to eq [[-1, 0, 0, 3, 48, 0, 0, 5, -8, 5].reverse, 16]
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,96 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ =begin
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Allows RSpec to persist some state between runs in order to support
54
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
55
+ # you configure your source control system to ignore this file.
56
+ config.example_status_persistence_file_path = "spec/examples.txt"
57
+
58
+ # Limits the available syntax to the non-monkey patched syntax that is
59
+ # recommended. For more details, see:
60
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
61
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
62
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
63
+ config.disable_monkey_patching!
64
+
65
+ # This setting enables warnings. It's recommended, but in some cases may
66
+ # be too noisy due to issues in dependencies.
67
+ config.warnings = true
68
+
69
+ # Many RSpec users commonly either run the entire suite or an individual
70
+ # file, and it's useful to allow more verbose output when running an
71
+ # individual spec file.
72
+ if config.files_to_run.one?
73
+ # Use the documentation formatter for detailed output,
74
+ # unless a formatter has already been configured
75
+ # (e.g. via a command-line flag).
76
+ config.default_formatter = 'doc'
77
+ end
78
+
79
+ # Print the 10 slowest examples and example groups at the
80
+ # end of the spec run, to help surface which specs are running
81
+ # particularly slow.
82
+ config.profile_examples = 10
83
+
84
+ # Run specs in random order to surface order dependencies. If you find an
85
+ # order dependency and want to debug it, you can fix the order by providing
86
+ # the seed, which is printed after each run.
87
+ # --seed 1234
88
+ config.order = :random
89
+
90
+ # Seed global randomization in this process using the `--seed` CLI option.
91
+ # Setting this allows you to use `--seed` to deterministically reproduce
92
+ # test failures related to randomization by passing the same `--seed` value
93
+ # as the one that triggered the failure.
94
+ Kernel.srand config.seed
95
+ =end
96
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: congruence_solver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - lane
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-31 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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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: '2.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ description: "Provides a class (CongruenceSolver) for finding the modular zeros of
70
+ a \n polynomial (given the coefficients and modulus) and
71
+ a binary (csolve) to \n to solve your congruences at the
72
+ command line."
73
+ email:
74
+ - lane.barlow@gmail.com
75
+ executables:
76
+ - csolve.rb
77
+ - setup
78
+ extensions:
79
+ - ext/congruence_solver/extconf.rb
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - ".gitmodules"
84
+ - ".rspec"
85
+ - ".travis.yml"
86
+ - README.md
87
+ - Rakefile
88
+ - bench/bench_tools.rb
89
+ - bench/solve_congruence_bm.rb
90
+ - bin/csolve.rb
91
+ - bin/setup
92
+ - congruence_solver.gemspec
93
+ - ext/congruence_solver/extconf.rb
94
+ - lib/congruence_solver.rb
95
+ - lib/congruence_solver/version.rb
96
+ - lib/polynomial_interpreter.rb
97
+ - spec/congruence_solver_spec.rb
98
+ - spec/csolve_spec.rb
99
+ - spec/spec_helper.rb
100
+ homepage: https://github.com/laneb/congruence_solver
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.4.5
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: A gem for solving polynomial congruences.
123
+ test_files: []