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 +4 -4
- data/.idea/.gitignore +8 -0
- data/.idea/modules.xml +9 -0
- data/.idea/truthy.iml +24 -0
- data/.idea/vcs.xml +6 -0
- data/Gemfile +7 -0
- data/Rakefile +12 -0
- data/ada_truthy.gemspec +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/ada_truthy/logical_gates/logical_gate.rb +62 -0
- data/lib/{logical_gates → ada_truthy/logical_gates}/logical_gate_extension.rb +2 -0
- data/lib/ada_truthy/truth_table/truth_table.rb +219 -0
- data/lib/ada_truthy/truth_table/truthy_exception.rb +4 -0
- data/lib/ada_truthy/version.rb +3 -0
- data/lib/ada_truthy.rb +3 -2
- metadata +25 -13
- data/GEM_README.md +0 -30
- data/lib/logical_gates/logical_gate.rb +0 -59
- data/lib/truth_table/truth_table.rb +0 -216
- data/lib/truth_table/truthy_exception.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9410ea5b7b775f817f02da291cfc63c9af895d2b2599c42eed5f5eb7100fcfaa
|
4
|
+
data.tar.gz: a10674f3776820c10bd7dd4e1d5002bb78006db2ef52a072f7df888b44b158c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 911ec53c15825ca5821f229e8f86813a0437dcf390d3c3a0dad80f2003b934baddff5787ff66d80b234833db2741e449077542d43687dc3a2c4b6061a7c8eefa
|
7
|
+
data.tar.gz: ca1a86932ee59d704a64eae301504df72680dd104daea056fe1ec7824e642696f95e66f29607e7ee73be1cc52471a2c0105b9db09275eec869cbc661039e480d
|
data/.idea/.gitignore
ADDED
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
data/Gemfile
ADDED
data/Rakefile
ADDED
data/ada_truthy.gemspec
ADDED
@@ -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,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
|
data/lib/ada_truthy.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require_relative '
|
2
|
-
require_relative '
|
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.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roberto W. P. Ribeiro
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
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:
|
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
|
-
-
|
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
|