ada_truthy 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f60c11c32eb2f78bf12f596577d76cf7800f9f4a555c0bd68ab9ea2d9f5ddea
4
- data.tar.gz: 86a813a004e5c51817a5bd7ab31d96bc8cfbed92e081d418b80f30d2dd06329a
3
+ metadata.gz: 9410ea5b7b775f817f02da291cfc63c9af895d2b2599c42eed5f5eb7100fcfaa
4
+ data.tar.gz: a10674f3776820c10bd7dd4e1d5002bb78006db2ef52a072f7df888b44b158c5
5
5
  SHA512:
6
- metadata.gz: 1e3f39e7f20a550147c303383d4c4f1f6ab7c2066c53cfa914ec168acd5e0ff466e77f218e0b947a5f2a6a6a9b1e687abc550d645062dbd8bbbffe651a3b6245
7
- data.tar.gz: 30065c106ffe083fa2e8f285d831a8bb97eaa586a57aa5e63fce4848ad8f32b61b8132a8534b565b765e09b0e3b81c83a1591bc21906496f4b9e482f476ffc39
6
+ metadata.gz: 911ec53c15825ca5821f229e8f86813a0437dcf390d3c3a0dad80f2003b934baddff5787ff66d80b234833db2741e449077542d43687dc3a2c4b6061a7c8eefa
7
+ data.tar.gz: ca1a86932ee59d704a64eae301504df72680dd104daea056fe1ec7824e642696f95e66f29607e7ee73be1cc52471a2c0105b9db09275eec869cbc661039e480d
data/.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
data/.idea/modules.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/truthy.iml" filepath="$PROJECT_DIR$/.idea/truthy.iml" />
6
+ <module fileurl="file://$PROJECT_DIR$/../.idea/truthy_gem.iml" filepath="$PROJECT_DIR$/../.idea/truthy_gem.iml" />
7
+ </modules>
8
+ </component>
9
+ </project>
data/.idea/truthy.iml ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
6
+ <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
7
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
8
+ </content>
9
+ <orderEntry type="jdk" jdkName="rbenv: 2.7.7" jdkType="RUBY_SDK" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.18.0, rbenv: 2.7.7) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.1, rbenv: 2.7.7) [gem]" level="application" />
13
+ </component>
14
+ <component name="RakeTasksCache">
15
+ <option name="myRootTask">
16
+ <RakeTaskImpl id="rake">
17
+ <subtasks>
18
+ <RakeTaskImpl description="Run tests" fullCommand="default" id="default" />
19
+ <RakeTaskImpl description="Run tests" fullCommand="test" id="test" />
20
+ </subtasks>
21
+ </RakeTaskImpl>
22
+ </option>
23
+ </component>
24
+ </module>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
+ </component>
6
+ </project>
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ada_numbers.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ #t.pattern = "test/*_test.rb"
9
+ end
10
+
11
+ desc "Run tests"
12
+ task :default => :test
@@ -0,0 +1,26 @@
1
+ require_relative 'lib/ada_truthy/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "ada_truthy"
5
+ spec.version = AdaTruthy::VERSION
6
+ spec.summary = "Create truth tables and operate with logical gates."
7
+ spec.description = "Create truth tables and let truthy handle the annoying part. Also, operate with logical gates like AND and OR."
8
+ spec.authors = ["Roberto W. P. Ribeiro"]
9
+ spec.email = ["rober.will@hotmail.com"]
10
+
11
+ # Specify which files should be added to the gem when it is released.
12
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
14
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ end
16
+
17
+ spec.homepage = "https://github.com/roberwil/truthy_gem"
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/roberwil/truthy_gem"
20
+ spec.metadata["changelog_uri"] = "https://github.com/roberwil/truthy_gem/blob/main/CHANGELOG.md"
21
+ spec.licenses = ["MIT"]
22
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.7")
23
+
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ada_truthy"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,62 @@
1
+ module AdaTruthy
2
+ class LogicalGate
3
+ def self.not(a)
4
+ return inot(a) if a.is_a? Integer
5
+ return !a
6
+ end
7
+
8
+ def self.and(a, b, *others)
9
+ return self.iand(a, b, others) if a.is_a? Integer
10
+ return false if (others.include?(false) || !a || !b)
11
+ return true
12
+ end
13
+
14
+ def self.nand(a, b, *others)
15
+ self.not self.and(a, b, others)
16
+ end
17
+
18
+ def self.or(a, b, *others)
19
+ return self.ior(a, b, others) if a.is_a? Integer
20
+ return true if others.include?(true) || a || b
21
+ return false
22
+ end
23
+
24
+ def self.nor(a, b, *others)
25
+ self.not self.or(a, b, others)
26
+ end
27
+
28
+ def self.xor(a, b, *others)
29
+ result = self.base_xor a, b
30
+
31
+ others.each do |term|
32
+ result = base_xor(result, term)
33
+ end
34
+
35
+ return result
36
+ end
37
+
38
+ def self.xnor(a, b, *others)
39
+ return !self.xor(a, b, others)
40
+ end
41
+
42
+ private
43
+
44
+ def self.base_xor(a, b)
45
+ a != b
46
+ end
47
+
48
+ def self.inot(a)
49
+ a == 1 ? 0 : 1
50
+ end
51
+
52
+ def self.iand(a, b, *others)
53
+ return 0 if others.include?(0) || a == 0 || b == 0
54
+ return 1
55
+ end
56
+
57
+ def self.ior(a, b, *others)
58
+ return 1 if others.include?(1) || a == 1 || b == 1
59
+ return 0
60
+ end
61
+ end
62
+ end
@@ -1,6 +1,7 @@
1
1
  require_relative 'logical_gate'
2
2
 
3
3
  class TrueClass
4
+ LogicalGate = AdaTruthy::LogicalGate
4
5
  def not
5
6
  LogicalGate.not self
6
7
  end
@@ -31,6 +32,7 @@ class TrueClass
31
32
  end
32
33
 
33
34
  class FalseClass
35
+ LogicalGate = AdaTruthy::LogicalGate
34
36
  def not
35
37
  LogicalGate.not self
36
38
  end
@@ -0,0 +1,219 @@
1
+ require_relative 'truthy_exception'
2
+ require_relative '../logical_gates/logical_gate_extension'
3
+
4
+ module AdaTruthy
5
+ class TruthTable
6
+ @@letters = %w[A B C D E F G H I J]
7
+
8
+ @@combinations = {
9
+ 2 => 04, 3 => 8, 4 => 16,
10
+ 5 => 32, 6 => 64, 7 => 128,
11
+ 8 => 256, 9 => 512, 10 => 1024
12
+ }
13
+
14
+ MAX_LIMIT = 6
15
+ MIN_LIMIT = 2
16
+ SELF = 'S'
17
+ COMPLEMENT = 'C'
18
+ TRUE_VALUE = 'T'
19
+ FALSE_VALUE = 'F'
20
+
21
+ def initialize(number_of_terms)
22
+ case number_of_terms
23
+ when number_of_terms > MAX_LIMIT
24
+ raise TruthyException, "The maximum number of terms is #{MAX_LIMIT}"
25
+ when number_of_terms < MIN_LIMIT
26
+ raise TruthyException, "The minimum number of terms is #{MIN_LIMIT}"
27
+ end
28
+
29
+ @number_of_terms = number_of_terms
30
+ @number_of_combinations = @@combinations[number_of_terms]
31
+
32
+ @cache = Hash.new
33
+ @formula = Array.new
34
+ @rows = Array.new
35
+
36
+ @using_sum_of_products = true
37
+ @using_product_of_sums = false
38
+
39
+ @number_of_zeros = 0
40
+ @number_of_ones = 0
41
+ end
42
+
43
+ def add_row(*terms)
44
+ table_has_enough_rows = @rows.size == @number_of_combinations
45
+
46
+ if table_has_enough_rows
47
+ raise TruthyException, "There should be only #{@number_of_combinations} rows."
48
+ end
49
+
50
+ right_number_of_terms = terms.size == @number_of_terms + 1
51
+
52
+ unless right_number_of_terms
53
+ raise TruthyException, "There should be only #{@number_of_terms} terms."
54
+ end
55
+
56
+ row = terms
57
+
58
+ unless row_is_valid? row
59
+ raise TruthyException, "The combination #{row} has been used already."
60
+ end
61
+
62
+ @cache = {}
63
+
64
+ row_output = row[-1]
65
+ change_algorithm = (@rows.size == 0).and(row_output == 0)
66
+
67
+ use_product_of_sums if change_algorithm
68
+
69
+ @rows << row
70
+ (row_output == 1) ? @number_of_ones += 1 : @number_of_zeros += 1
71
+
72
+ compute row
73
+ end
74
+
75
+ def check(*terms)
76
+ has_right_number_of_terms = terms.size == @number_of_terms
77
+
78
+ unless has_right_number_of_terms
79
+ raise TruthyException, "There should be only #{@number_of_terms} terms."
80
+ end
81
+
82
+ change_algorithm_if_needed
83
+
84
+ cache_code = TruthTable.get_row_cache_code terms
85
+ cache_result = @cache[cache_code]
86
+
87
+ return cache_result unless cache_result.nil?
88
+
89
+ terms_cursor = 0
90
+ partial_result = true
91
+ result = false
92
+
93
+ if @using_product_of_sums
94
+ partial_result = false
95
+ result = true
96
+ end
97
+
98
+ @formula.each do |t|
99
+ if @using_sum_of_products
100
+ partial_result = (t == SELF ? partial_result.and(terms[terms_cursor]) :
101
+ partial_result.and(!terms[terms_cursor]))
102
+ else
103
+ partial_result = (t == SELF ? partial_result.or(terms[terms_cursor]) :
104
+ partial_result.or(!terms[terms_cursor]))
105
+ end
106
+
107
+ terms_cursor += 1
108
+ next if terms_cursor != @number_of_terms
109
+ terms_cursor = 0
110
+
111
+ if (@using_sum_of_products)
112
+ return true if partial_result
113
+ result = result.or(partial_result)
114
+ partial_result = true
115
+ else
116
+ return false if not partial_result
117
+ result = result.and(partial_result)
118
+ partial_result = false
119
+ end
120
+ end
121
+
122
+ @cache[cache_code] = result
123
+ return result
124
+ end
125
+
126
+ def to_s
127
+ terms_cursor = 0
128
+ partial_result = ''
129
+ result = ''
130
+
131
+ @formula.each do |t|
132
+ if @using_sum_of_products
133
+ partial_result += (t == SELF ? "#{@@letters[terms_cursor]}." : "~#{@@letters[terms_cursor]}.")
134
+ else
135
+ partial_result += (t == SELF ? "#{@@letters[terms_cursor]}+" : "~#{@@letters[terms_cursor]}+")
136
+ end
137
+
138
+ terms_cursor += 1
139
+ next if terms_cursor != @number_of_terms
140
+ terms_cursor = 0
141
+
142
+ result += (@using_sum_of_products ? "(#{partial_result[0...-1]})+" : "(#{partial_result[0...-1]}).")
143
+ partial_result = ''
144
+ end
145
+
146
+ result[0...-1]
147
+ end
148
+
149
+ private
150
+
151
+ def row_is_valid?(row)
152
+ @rows.each do |existing_row|
153
+ is_equal = true
154
+
155
+ (0..existing_row.size - 1).each do |i|
156
+ is_equal = is_equal.and(row[i] == existing_row[i])
157
+ end
158
+
159
+ return false if is_equal
160
+ end
161
+
162
+ return true
163
+ end
164
+
165
+ def compute(row)
166
+ row_output = row[-1]
167
+
168
+ return if @using_sum_of_products.and(row_output != 1)
169
+ return if @using_product_of_sums.and(row_output != 0)
170
+
171
+ (0...row.size - 1).each do |i|
172
+ if @using_sum_of_products
173
+ @formula << (row[i] == 1 ? SELF : COMPLEMENT)
174
+ else
175
+ @formula << (row[i] == 1 ? COMPLEMENT : SELF)
176
+ end
177
+ end
178
+ end
179
+
180
+ def change_algorithm_if_needed
181
+ no_need_to_change = @using_sum_of_products.and(@number_of_zeros == 0).
182
+ or(@using_product_of_sums.and(@number_of_ones == 0))
183
+
184
+ return if no_need_to_change
185
+
186
+ more_zeros = @number_of_zeros > @number_of_ones
187
+
188
+ no_need_to_change = @using_sum_of_products.and(more_zeros).
189
+ or(@using_product_of_sums.and(!more_zeros))
190
+
191
+ return if no_need_to_change
192
+
193
+ more_zeros ? use_sum_of_products : use_product_of_sums
194
+
195
+ @formula = []
196
+ @cache = {}
197
+
198
+ @rows.each do |row|
199
+ compute row
200
+ end
201
+ end
202
+
203
+ def use_sum_of_products
204
+ @using_sum_of_products = true
205
+ @using_product_of_sums = false
206
+ end
207
+
208
+ def use_product_of_sums
209
+ @using_sum_of_products = false
210
+ @using_product_of_sums = true
211
+ end
212
+
213
+ def self.get_row_cache_code(terms)
214
+ code = ''
215
+ terms.each { |term| code += (term ? TRUE_VALUE : FALSE_VALUE) }
216
+ return code
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,4 @@
1
+ module AdaTruthy
2
+ class TruthyException < StandardError
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module AdaTruthy
2
+ VERSION = "1.2.0"
3
+ end
data/lib/ada_truthy.rb CHANGED
@@ -1,4 +1,5 @@
1
- require_relative 'logical_gates/logical_gate_extension'
2
- require_relative 'truth_table/truth_table'
1
+ require_relative 'ada_truthy/version'
2
+ require_relative 'ada_truthy/logical_gates/logical_gate_extension'
3
+ require_relative 'ada_truthy/truth_table/truth_table'
3
4
 
4
5
 
metadata CHANGED
@@ -1,33 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ada_truthy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto W. P. Ribeiro
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-22 00:00:00.000000000 Z
11
+ date: 2023-03-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Create truth tables and let truthy handle the annoying part. Also, operate
14
- with logical gates.
15
- email: rober.will@hotmail.com
14
+ with logical gates like AND and OR.
15
+ email:
16
+ - rober.will@hotmail.com
16
17
  executables: []
17
18
  extensions: []
18
- extra_rdoc_files:
19
- - GEM_README.md
19
+ extra_rdoc_files: []
20
20
  files:
21
- - GEM_README.md
21
+ - ".idea/.gitignore"
22
+ - ".idea/modules.xml"
23
+ - ".idea/truthy.iml"
24
+ - ".idea/vcs.xml"
25
+ - Gemfile
26
+ - Rakefile
27
+ - ada_truthy.gemspec
28
+ - bin/console
29
+ - bin/setup
22
30
  - lib/ada_truthy.rb
23
- - lib/logical_gates/logical_gate.rb
24
- - lib/logical_gates/logical_gate_extension.rb
25
- - lib/truth_table/truth_table.rb
26
- - lib/truth_table/truthy_exception.rb
31
+ - lib/ada_truthy/logical_gates/logical_gate.rb
32
+ - lib/ada_truthy/logical_gates/logical_gate_extension.rb
33
+ - lib/ada_truthy/truth_table/truth_table.rb
34
+ - lib/ada_truthy/truth_table/truthy_exception.rb
35
+ - lib/ada_truthy/version.rb
27
36
  homepage: https://github.com/roberwil/truthy_gem
28
37
  licenses:
29
38
  - MIT
30
- metadata: {}
39
+ metadata:
40
+ homepage_uri: https://github.com/roberwil/truthy_gem
41
+ source_code_uri: https://github.com/roberwil/truthy_gem
42
+ changelog_uri: https://github.com/roberwil/truthy_gem/blob/main/CHANGELOG.md
31
43
  post_install_message:
32
44
  rdoc_options: []
33
45
  require_paths:
data/GEM_README.md DELETED
@@ -1,30 +0,0 @@
1
- # Truthy Gem
2
-
3
- ### What is truthy anyway?
4
-
5
- Well, think of a truth table you just invented, you put your 1s and 0s and **Truthy** figures out which formula works
6
- for the table.
7
-
8
- | A | B | C |
9
- |-----|-----|-----|
10
- | 0 | 0 | 1 |
11
- | 1 | 0 | 1 |
12
- | 1 | 1 | 0 |
13
- | 0 | 1 | 0 |
14
-
15
- If you create the above table with **Truthy**, it will know what to do so that your table makes sense.
16
- Also, **Truthy** has implementations for the following logical gates: `and`, `or`, `not`,
17
- `xor`, `nand`, `nor`, and `xnor`.
18
-
19
- ### Where can I use it?
20
-
21
- - Access matrices are a good example;
22
- - Other examples are just day-to-day comparisons you do with booleans in your code.
23
-
24
- Let your imagination make good use of Truthy.
25
-
26
- ### Where do I learn how to use it?
27
-
28
- Check the documentation [here](https://github.com/roberwil/truthy_gem/blob/main/README.md).
29
- Remember, **Truthy** is the way.
30
-
@@ -1,59 +0,0 @@
1
- class LogicalGate
2
- def self.not(a)
3
- return inot(a) if a.is_a? Integer
4
- return !a
5
- end
6
-
7
- def self.and(a, b, *others)
8
- return self.iand(a, b, others) if a.is_a? Integer
9
- return false if (others.include?(false) || !a || !b)
10
- return true
11
- end
12
-
13
- def self.nand(a, b, *others)
14
- self.not self.and(a, b, others)
15
- end
16
-
17
- def self.or(a, b, *others)
18
- return self.ior(a, b, others) if a.is_a? Integer
19
- return true if others.include?(true) || a || b
20
- return false
21
- end
22
-
23
- def self.nor(a, b, *others)
24
- self.not self.or(a, b, others)
25
- end
26
-
27
- def self.xor(a, b, *others)
28
- result = self.base_xor a, b
29
-
30
- others.each do |term|
31
- result = base_xor(result, term)
32
- end
33
-
34
- return result
35
- end
36
-
37
- def self.xnor(a, b, *others)
38
- return !self.xor(a, b, others)
39
- end
40
-
41
- private
42
- def self.base_xor(a, b)
43
- a != b
44
- end
45
-
46
- def self.inot(a)
47
- a == 1? 0 : 1
48
- end
49
-
50
- def self.iand(a, b, *others)
51
- return 0 if others.include?(0) || a == 0 || b == 0
52
- return 1
53
- end
54
-
55
- def self.ior(a, b, *others)
56
- return 1 if others.include?(1) || a == 1 || b == 1
57
- return 0
58
- end
59
- end
@@ -1,216 +0,0 @@
1
- require_relative 'truthy_exception'
2
- require_relative '../logical_gates/logical_gate_extension'
3
-
4
- class TruthTable
5
- @@letters = %w[A B C D E F G H I J]
6
-
7
- @@combinations = {
8
- 2 => 04, 3 => 8, 4 => 16,
9
- 5 => 32, 6 => 64, 7 => 128,
10
- 8 => 256, 9 => 512, 10 => 1024
11
- }
12
-
13
- MAX_LIMIT = 6
14
- MIN_LIMIT = 2
15
- SELF = 'S'
16
- COMPLEMENT = 'C'
17
- TRUE_VALUE = 'T'
18
- FALSE_VALUE = 'F'
19
-
20
- def initialize(number_of_terms)
21
- case number_of_terms
22
- when number_of_terms > MAX_LIMIT
23
- raise TruthyException, "The maximum number of terms is #{MAX_LIMIT}"
24
- when number_of_terms < MIN_LIMIT
25
- raise TruthyException, "The minimum number of terms is #{MIN_LIMIT}"
26
- end
27
-
28
- @number_of_terms = number_of_terms
29
- @number_of_combinations = @@combinations[number_of_terms]
30
-
31
- @cache = Hash.new
32
- @formula = Array.new
33
- @rows = Array.new
34
-
35
- @using_sum_of_products = true
36
- @using_product_of_sums = false
37
-
38
- @number_of_zeros = 0
39
- @number_of_ones = 0
40
- end
41
-
42
- def add_row(*terms)
43
- table_has_enough_rows = @rows.size == @number_of_combinations
44
-
45
- if table_has_enough_rows
46
- raise TruthyException, "There should be only #{@number_of_combinations} rows."
47
- end
48
-
49
- right_number_of_terms = terms.size == @number_of_terms + 1
50
-
51
- unless right_number_of_terms
52
- raise TruthyException, "There should be only #{@number_of_terms} terms."
53
- end
54
-
55
- row = terms
56
-
57
- unless row_is_valid? row
58
- raise TruthyException, "The combination #{row} has been used already."
59
- end
60
-
61
- @cache = {}
62
-
63
- row_output = row[-1]
64
- change_algorithm = (@rows.size == 0).and(row_output == 0)
65
-
66
- use_product_of_sums if change_algorithm
67
-
68
- @rows << row
69
- (row_output == 1)? @number_of_ones += 1 : @number_of_zeros += 1
70
-
71
- compute row
72
- end
73
-
74
- def check(*terms)
75
- has_right_number_of_terms = terms.size == @number_of_terms
76
-
77
- unless has_right_number_of_terms
78
- raise TruthyException, "There should be only #{@number_of_terms} terms."
79
- end
80
-
81
- change_algorithm_if_needed
82
-
83
- cache_code = TruthTable.get_row_cache_code terms
84
- cache_result = @cache[cache_code]
85
-
86
- return cache_result unless cache_result.nil?
87
-
88
- terms_cursor = 0
89
- partial_result = true
90
- result = false
91
-
92
- if @using_product_of_sums
93
- partial_result = false
94
- result = true
95
- end
96
-
97
- @formula.each do |t|
98
- if @using_sum_of_products
99
- partial_result = (t == SELF ? partial_result.and(terms[terms_cursor]) :
100
- partial_result.and(!terms[terms_cursor]))
101
- else
102
- partial_result = (t == SELF ? partial_result.or(terms[terms_cursor]) :
103
- partial_result.or(!terms[terms_cursor]))
104
- end
105
-
106
- terms_cursor += 1
107
- next if terms_cursor != @number_of_terms
108
- terms_cursor = 0
109
-
110
- if (@using_sum_of_products)
111
- return true if partial_result
112
- result = result.or(partial_result)
113
- partial_result = true
114
- else
115
- return false if not partial_result
116
- result = result.and(partial_result)
117
- partial_result = false
118
- end
119
- end
120
-
121
- @cache[cache_code] = result
122
- return result
123
- end
124
-
125
- def to_s
126
- terms_cursor = 0
127
- partial_result = ''
128
- result = ''
129
-
130
- @formula.each do |t|
131
- if @using_sum_of_products
132
- partial_result += (t == SELF ? "#{@@letters[terms_cursor]}." : "~#{@@letters[terms_cursor]}.")
133
- else
134
- partial_result += (t == SELF ? "#{@@letters[terms_cursor]}+" : "~#{@@letters[terms_cursor]}+")
135
- end
136
-
137
- terms_cursor += 1
138
- next if terms_cursor != @number_of_terms
139
- terms_cursor = 0
140
-
141
- result += (@using_sum_of_products? "(#{partial_result[0...-1]})+" : "(#{partial_result[0...-1]}).")
142
- partial_result = ''
143
- end
144
-
145
- result[0...-1]
146
- end
147
-
148
- private
149
- def row_is_valid?(row)
150
- @rows.each do |existing_row|
151
- is_equal = true
152
-
153
- (0..existing_row.size - 1).each do |i|
154
- is_equal = is_equal.and(row[i] == existing_row[i])
155
- end
156
-
157
- return false if is_equal
158
- end
159
-
160
- return true
161
- end
162
-
163
- def compute(row)
164
- row_output = row[-1]
165
-
166
- return if @using_sum_of_products.and(row_output != 1)
167
- return if @using_product_of_sums.and(row_output != 0)
168
-
169
- (0...row.size - 1).each do |i|
170
- if @using_sum_of_products
171
- @formula << (row[i] == 1 ? SELF : COMPLEMENT)
172
- else
173
- @formula << (row[i] == 1 ? COMPLEMENT : SELF)
174
- end
175
- end
176
- end
177
-
178
- def change_algorithm_if_needed
179
- no_need_to_change = @using_sum_of_products.and(@number_of_zeros == 0).
180
- or(@using_product_of_sums.and(@number_of_ones == 0))
181
-
182
- return if no_need_to_change
183
-
184
- more_zeros = @number_of_zeros > @number_of_ones
185
-
186
- no_need_to_change = @using_sum_of_products.and(more_zeros).
187
- or(@using_product_of_sums.and(!more_zeros))
188
-
189
- return if no_need_to_change
190
-
191
- more_zeros ? use_sum_of_products : use_product_of_sums
192
-
193
- @formula = []
194
- @cache = {}
195
-
196
- @rows.each do |row|
197
- compute row
198
- end
199
- end
200
-
201
- def use_sum_of_products
202
- @using_sum_of_products = true
203
- @using_product_of_sums = false
204
- end
205
-
206
- def use_product_of_sums
207
- @using_sum_of_products = false
208
- @using_product_of_sums = true
209
- end
210
-
211
- def self.get_row_cache_code(terms)
212
- code = ''
213
- terms.each { |term| code += (term ? TRUE_VALUE : FALSE_VALUE) }
214
- return code
215
- end
216
- end
@@ -1,2 +0,0 @@
1
- class TruthyException < StandardError
2
- end