rlsm 1.1.0 → 1.8.1
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.
- data/Manifest +26 -0
- data/README +10 -10
- data/Rakefile +9 -55
- data/data/monoids.db +0 -0
- data/examples/benchmark.rb +14 -0
- data/examples/creating_db.rb +52 -0
- data/examples/creating_lists.rb +185 -0
- data/examples/numbers.rb +41 -0
- data/examples/order8.rb +13 -0
- data/examples/presenting_monoids_in_tex.rb +373 -0
- data/examples/regular_monoids.rb +144 -0
- data/ext/array/array_c_ext.c +21 -12
- data/ext/monoid/monoid_c_ext.c +76 -85
- data/lib/rlsm.rb +1 -1
- data/lib/rlsm/dfa.rb +9 -8
- data/lib/rlsm/helper.rb +12 -6
- data/lib/rlsm/monoid.rb +627 -217
- data/lib/rlsm/regexp.rb +2 -1
- data/lib/rlsm/regexp_parser.rb +2 -1
- data/rlsm.gemspec +26 -0
- data/test/test_dfa.rb +16 -14
- data/test/test_monoid.rb +43 -43
- data/test/test_regexp.rb +2 -2
- metadata +51 -83
- data/ext/binop/binop_c_ext.c +0 -57
- data/ext/binop/extconf.rb +0 -2
- data/lib/rlsm/binary_operation.rb +0 -151
- data/test/test_binop.rb +0 -119
data/Manifest
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Rakefile
|
2
|
+
Manifest
|
3
|
+
README
|
4
|
+
rlsm.gemspec
|
5
|
+
lib/rlsm.rb
|
6
|
+
lib/rlsm/helper.rb
|
7
|
+
lib/rlsm/monoid.rb
|
8
|
+
lib/rlsm/dfa.rb
|
9
|
+
lib/rlsm/regexp.rb
|
10
|
+
lib/rlsm/regexp_parser.rb
|
11
|
+
ext/monoid/extconf.rb
|
12
|
+
ext/monoid/monoid_c_ext.c
|
13
|
+
ext/array/extconf.rb
|
14
|
+
ext/array/array_c_ext.c
|
15
|
+
test/helpers.rb
|
16
|
+
test/test_monoid.rb
|
17
|
+
test/test_dfa.rb
|
18
|
+
test/test_regexp.rb
|
19
|
+
data/monoids.db
|
20
|
+
examples/creating_db.rb
|
21
|
+
examples/creating_lists.rb
|
22
|
+
examples/presenting_monoids_in_tex.rb
|
23
|
+
examples/regular_monoids.rb
|
24
|
+
examples/order8.rb
|
25
|
+
examples/benchmark.rb
|
26
|
+
examples/numbers.rb
|
data/README
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
= rlsm
|
2
2
|
rlsm stands for *R*egular *L*anguages and *S*yntactic *M*onoids.
|
3
3
|
|
4
|
-
Source is availible from
|
5
|
-
http://github.com/asmodis/rlsm
|
6
|
-
|
7
|
-
RDoc-Documentation is availible from
|
8
|
-
http://rlsm.rubyforge.org
|
4
|
+
Source is availible from http://github.com/asmodis/rlsm.
|
9
5
|
|
10
6
|
== DESCRIPTION:
|
7
|
+
Monoids play a large role in the theory of formal languages, especially in the
|
8
|
+
theory of regular languages. If +L+ is a regular language, there exists a finite monoid,
|
9
|
+
the so called syntactic monoid of +L+, and it is possible to get more informations about
|
10
|
+
the language by investigating properties of the monoid. On the other hand one is
|
11
|
+
interessted in the question which monoids are syntactic.
|
11
12
|
|
12
|
-
|
13
|
-
- Deterministic Finite Automata
|
14
|
-
- Regular Expressions (in the sense of theoretical computer sience)
|
15
|
-
- Monoids
|
16
|
-
|
13
|
+
The rlsm gem allows the study of both questions.
|
17
14
|
|
18
15
|
== SYNOPSIS:
|
19
16
|
|
@@ -24,6 +21,9 @@ This is a ruby implementation of three concepts:
|
|
24
21
|
m.isomorph_to?(m) # => true
|
25
22
|
m.commutative? # => false
|
26
23
|
|
24
|
+
m2 = RLSM::Monoid.from_regexp("ab*")
|
25
|
+
m2.aperiodic?
|
26
|
+
|
27
27
|
== INSTALL:
|
28
28
|
|
29
29
|
gem install rlsm
|
data/Rakefile
CHANGED
@@ -5,8 +5,13 @@ require File.join(File.dirname(__FILE__), 'lib', 'rlsm')
|
|
5
5
|
task :build_ext do
|
6
6
|
Dir.chdir File.join(File.dirname(__FILE__), 'ext') do
|
7
7
|
Dir.foreach('.') do |extension|
|
8
|
+
next if ['.','..'].include? extension
|
8
9
|
Dir.chdir extension do
|
10
|
+
rm "Makefile" if File.exists? 'Makefile'
|
11
|
+
rm "#{extension}_c_ext.o" if File.exists? "#{extension}_c_ext.o"
|
12
|
+
rm "#{extension}_cext.so" if File.exists? "#{extension}_cext.so"
|
9
13
|
if File.exists? 'extconf.rb'
|
14
|
+
puts "In #{Dir.pwd}:"
|
10
15
|
ruby 'extconf.rb'
|
11
16
|
sh "make"
|
12
17
|
end
|
@@ -23,62 +28,11 @@ task :test => :build_ext do
|
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|
26
|
-
task :
|
27
|
-
|
28
|
-
File.open("Manifest", 'w') do |manifest|
|
29
|
-
FileList['lib/**/*.rb', 'ext/**/*.c','ext/**/*.rb', 'test/**/*'].to_a.each do |file|
|
30
|
-
manifest.puts file
|
31
|
-
end
|
32
|
-
|
33
|
-
manifest.puts "Rakefile"
|
34
|
-
manifest.puts "README"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
task :create_gemspec => :create_manifest do
|
40
|
-
Dir.chdir(File.dirname(__FILE__)) do
|
41
|
-
readme = File.open("README")
|
42
|
-
manifest = File.open("Manifest")
|
43
|
-
filelist = "[" + manifest.to_a.map { |line| "'#{line.chomp}'" }.join(", ") + "]"
|
44
|
-
manifest.close
|
45
|
-
|
46
|
-
readme_string = '<<DESCRIPTION' + "\n" + readme.to_a.join + "\nDESCRIPTION"
|
47
|
-
readme.close
|
48
|
-
|
49
|
-
File.open(".gemspec", 'w') do |gemspec|
|
50
|
-
gemspec.puts <<GEMSPEC
|
51
|
-
# -*- ruby -*-
|
52
|
-
|
53
|
-
require "rake"
|
54
|
-
|
55
|
-
Gem::Specification.new do |s|
|
56
|
-
s.author = "Gunther Diemant"
|
57
|
-
s.email = "g.diemant@gmx.net"
|
58
|
-
s.homepage = "http://github.com/asmodis/rlsm"
|
59
|
-
s.rubyforge_project = 'rlsm'
|
60
|
-
|
61
|
-
s.name = 'rlsm'
|
62
|
-
s.version = '#{RLSM::VERSION}'
|
63
|
-
s.add_development_dependency('minitest')
|
64
|
-
s.add_development_dependency('thoughtbot-shoulda')
|
65
|
-
s.summary = "Library for investigating regular languages and syntactic monoids."
|
66
|
-
s.description = #{readme_string}
|
67
|
-
|
68
|
-
s.files = #{filelist}
|
69
|
-
s.test_files = FileList['test/test_*.rb']
|
70
|
-
s.extensions = FileList['ext/**/extconf.rb']
|
71
|
-
|
72
|
-
s.has_rdoc = true
|
73
|
-
s.extra_rdoc_files = ['README']
|
74
|
-
s.rdoc_options << '--main' << 'README'
|
75
|
-
end
|
76
|
-
GEMSPEC
|
77
|
-
end
|
78
|
-
end
|
31
|
+
task :test_monoid => :build_ext do
|
32
|
+
ruby "test/test_monoid.rb"
|
79
33
|
end
|
80
34
|
|
81
|
-
task :create_gem
|
82
|
-
sh "gem build .gemspec"
|
35
|
+
task :create_gem do
|
36
|
+
sh "gem build rlsm.gemspec"
|
83
37
|
sh "mv *.gem gem/"
|
84
38
|
end
|
data/data/monoids.db
ADDED
Binary file
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rlsm')
|
2
|
+
|
3
|
+
#f = File.open("tempfile.txt",'w')
|
4
|
+
x=0
|
5
|
+
start = Time.now
|
6
|
+
RLSM::Monoid.each_table(6) { x += 1 }
|
7
|
+
puts "Elapsed time: #{Time.now - start}"
|
8
|
+
start = Time.now
|
9
|
+
RLSM::Monoid.each(6) { x += 1 }
|
10
|
+
puts "Elapsed time: #{Time.now - start}"
|
11
|
+
|
12
|
+
puts
|
13
|
+
|
14
|
+
#f.close
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#-*- ruby -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rlsm')
|
4
|
+
require "rubygems"
|
5
|
+
require "sqlite3"
|
6
|
+
|
7
|
+
$db = SQLite3::Database.new("monoids.db")
|
8
|
+
|
9
|
+
$db.execute <<SQL
|
10
|
+
create table if not exists monoids (
|
11
|
+
binop TEXT,
|
12
|
+
ord INTEGER,
|
13
|
+
num_gen INTEGER,
|
14
|
+
num_left_zeros INTEGER,
|
15
|
+
num_right_zeros INTEGER,
|
16
|
+
num_idempotents INTEGER,
|
17
|
+
has_zero INTEGER,
|
18
|
+
is_syntactic INTEGER,
|
19
|
+
is_commutative INTEGER,
|
20
|
+
is_idempotent INTEGER,
|
21
|
+
is_aperiodic INTEGER,
|
22
|
+
is_l_trivial INTEGER,
|
23
|
+
is_r_trivial INTEGER,
|
24
|
+
is_j_trivial INTEGER,
|
25
|
+
is_group INTEGER
|
26
|
+
);
|
27
|
+
SQL
|
28
|
+
|
29
|
+
def monoid2sql(monoid)
|
30
|
+
translate = { true => '1', false => '0' }
|
31
|
+
sql = "insert into monoids values ("
|
32
|
+
sql += "'#{monoid.to_s.chop}', "
|
33
|
+
sql += "'#{monoid.order}', "
|
34
|
+
sql += "'#{monoid.generating_subset.size.to_s}', "
|
35
|
+
sql += "'#{monoid.left_zeros.size.to_s}', "
|
36
|
+
sql += "'#{monoid.right_zeros.size.to_s}', "
|
37
|
+
sql += "'#{monoid.idempotents.size.to_s}', "
|
38
|
+
sql += "'#{translate[monoid.zero?]}', "
|
39
|
+
sql += "'#{translate[monoid.syntactic?]}', "
|
40
|
+
sql += "'#{translate[monoid.commutative?]}', "
|
41
|
+
sql += "'#{translate[monoid.idempotent?]}', "
|
42
|
+
sql += "'#{translate[monoid.aperiodic?]}', "
|
43
|
+
sql += "'#{translate[monoid.l_trivial?]}', "
|
44
|
+
sql += "'#{translate[monoid.r_trivial?]}', "
|
45
|
+
sql += "'#{translate[monoid.j_trivial?]}', "
|
46
|
+
sql + "'#{translate[monoid.group?]}');"
|
47
|
+
end
|
48
|
+
|
49
|
+
7.times do |i|
|
50
|
+
RLSM::Monoid.each(i+1) { |mon| $db.execute monoid2sql(mon) }
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rlsm')
|
2
|
+
require File.join(File.dirname(__FILE__), 'presenting_monoids_in_tex')
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "sqlite3"
|
6
|
+
|
7
|
+
File.open("monoidlist.tex", "w") do |f|
|
8
|
+
db = SQLite3::Database.new(File.join(File.dirname(__FILE__), '..', 'data', 'monoids.db'))
|
9
|
+
|
10
|
+
#Making the header
|
11
|
+
f.puts "\\documentclass[8pt]{article}"
|
12
|
+
f.puts "\\usepackage[a4paper, left=2cm, right=2cm, top=1cm, bottom=2cm]{geometry}"
|
13
|
+
f.puts "\\usepackage[utf8]{inputenc}"
|
14
|
+
f.puts "\\usepackage[T1]{fontenc}"
|
15
|
+
f.puts "\\usepackage[all]{xy}"
|
16
|
+
|
17
|
+
f.puts "\\begin{document}"
|
18
|
+
f.puts "\\title{Nichtäquivalente Monoide bis Ordnung 5}"
|
19
|
+
f.puts "\\date{}"
|
20
|
+
f.puts "\\maketitle"
|
21
|
+
f.puts "\\tableofcontents\n"
|
22
|
+
|
23
|
+
f.puts "\\section{Überblick}"
|
24
|
+
query = <<SQL
|
25
|
+
SELECT
|
26
|
+
ord AS 'Order',
|
27
|
+
count(*) AS 'Total',
|
28
|
+
total(is_syntactic) AS 'Syntactic',
|
29
|
+
total(is_group) AS 'Groups',
|
30
|
+
total(is_commutative) AS 'Commutative',
|
31
|
+
total(is_aperiodic) AS 'Aperiodic',
|
32
|
+
total(is_idempotent) AS 'Idempotent',
|
33
|
+
total(is_j_trivial) AS 'J-trivial',
|
34
|
+
total(is_r_trivial) AS 'R-trivial',
|
35
|
+
total(is_l_trivial) AS 'L-trivial',
|
36
|
+
total(has_zero) AS 'With zero element'
|
37
|
+
FROM monoids
|
38
|
+
GROUP BY ord
|
39
|
+
ORDER BY 'Order' ASC;
|
40
|
+
SQL
|
41
|
+
result = db.execute2(query)
|
42
|
+
|
43
|
+
f.puts "\\begin{center}"
|
44
|
+
f.puts "\\begin{tabular}{r|ccccccc}"
|
45
|
+
|
46
|
+
f.puts( (0..7).to_a.map { |i| "\\textbf{#{result[i][0]}}" }.join(' & ') + " \\\\ \\hline" )
|
47
|
+
|
48
|
+
1.upto 10 do |row_index|
|
49
|
+
f.puts "\\textbf{#{result[0][row_index]}} & "+
|
50
|
+
(1..7).to_a.map { |i| result[i][row_index].to_i }.join(' & ') + " \\\\"
|
51
|
+
end
|
52
|
+
|
53
|
+
f.puts "\\end{tabular}"
|
54
|
+
f.puts "\\end{center}\n\n"
|
55
|
+
|
56
|
+
1.upto 6 do |order|
|
57
|
+
num = db.execute("select count(*) from monoids where ord=#{order};").join
|
58
|
+
f.puts "\\section{Ordnung #{order} (#{num} Stück)}\n"
|
59
|
+
|
60
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=1 AND is_commutative=1 AND is_idempotent=1 ORDER BY binop;"
|
61
|
+
result = db.execute(query)
|
62
|
+
|
63
|
+
unless result.empty?
|
64
|
+
f.puts "\\subsection{Syntaktisch, Kommutativ und Idempotent (#{result.size} Stück)}\n"
|
65
|
+
|
66
|
+
result.each do |row|
|
67
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
68
|
+
f.puts "\n\n"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=1 AND is_commutative=1 AND is_aperiodic=1 AND is_idempotent=0 ORDER BY binop;"
|
74
|
+
result = db.execute(query)
|
75
|
+
|
76
|
+
unless result.empty?
|
77
|
+
f.puts "\\subsection{Syntaktisch, Kommutativ und Aperiodisch (#{result.size} Stück)}\n"
|
78
|
+
|
79
|
+
result.each do |row|
|
80
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
81
|
+
f.puts "\n\n"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=1 AND is_commutative=1 AND is_aperiodic=0 ORDER BY binop;"
|
86
|
+
result = db.execute(query)
|
87
|
+
|
88
|
+
unless result.empty?
|
89
|
+
f.puts "\\subsection{Syntaktisch und Kommutativ (#{result.size} Stück)}\n"
|
90
|
+
|
91
|
+
result.each do |row|
|
92
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
93
|
+
f.puts "\n\n"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=1 AND is_idempotent=1 AND is_commutative=0 ORDER BY binop;"
|
98
|
+
result = db.execute(query)
|
99
|
+
|
100
|
+
unless result.empty?
|
101
|
+
f.puts "\\subsection{Syntaktisch und Idempotent (#{result.size} Stück)}\n"
|
102
|
+
|
103
|
+
result.each do |row|
|
104
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
105
|
+
f.puts "\n\n"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=1 AND is_aperiodic=1 AND is_idempotent=0 AND is_commutative=0 ORDER BY binop;"
|
111
|
+
result = db.execute(query)
|
112
|
+
|
113
|
+
unless result.empty?
|
114
|
+
f.puts "\\subsection{Syntaktisch und Aperiodisch (#{result.size} Stück)}\n"
|
115
|
+
|
116
|
+
result.each do |row|
|
117
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
118
|
+
f.puts "\n\n"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=0 AND is_commutative=1 AND is_idempotent=1 ORDER BY binop;"
|
123
|
+
result = db.execute(query)
|
124
|
+
|
125
|
+
unless result.empty?
|
126
|
+
f.puts "\\subsection{Nicht Syntaktisch, Kommutativ und Idempotent (#{result.size} Stück)}\n"
|
127
|
+
|
128
|
+
result.each do |row|
|
129
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
130
|
+
f.puts "\n\n"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=0 AND is_commutative=1 AND is_aperiodic=1 AND is_idempotent=0 ORDER BY binop;"
|
136
|
+
result = db.execute(query)
|
137
|
+
|
138
|
+
unless result.empty?
|
139
|
+
f.puts "\\subsection{Nicht Syntaktisch, Kommutativ und Aperiodisch (#{result.size} Stück)}\n"
|
140
|
+
|
141
|
+
result.each do |row|
|
142
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
143
|
+
f.puts "\n\n"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=0 AND is_commutative=1 AND is_aperiodic=0 ORDER BY binop;"
|
148
|
+
result = db.execute(query)
|
149
|
+
|
150
|
+
unless result.empty?
|
151
|
+
f.puts "\\subsection{Nicht Syntaktisch und Kommutativ (#{result.size} Stück)}\n"
|
152
|
+
|
153
|
+
result.each do |row|
|
154
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
155
|
+
f.puts "\n\n"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=0 AND is_idempotent=1 AND is_commutative=0 ORDER BY binop;"
|
160
|
+
result = db.execute(query)
|
161
|
+
|
162
|
+
unless result.empty?
|
163
|
+
f.puts "\\subsection{Nicht Syntaktisch und Idempotent (#{result.size} Stück)}\n"
|
164
|
+
|
165
|
+
result.each do |row|
|
166
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
167
|
+
f.puts "\n\n"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
query = "SELECT * FROM monoids WHERE ord=#{order} AND is_syntactic=0 AND is_aperiodic=1 AND is_commutative=0 AND is_idempotent=0 ORDER BY binop;"
|
172
|
+
result = db.execute(query)
|
173
|
+
|
174
|
+
unless result.empty?
|
175
|
+
f.puts "\\subsection{Nicht Syntaktisch und Aperiodisch (#{result.size} Stück)}\n"
|
176
|
+
|
177
|
+
result.each do |row|
|
178
|
+
f.puts Presenter.db_row_to_latex(row, :lang => :de)
|
179
|
+
f.puts "\n\n"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
f.puts "\\end{document}"
|
185
|
+
end
|
data/examples/numbers.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#-*- ruby -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rlsm')
|
4
|
+
require "rubygems"
|
5
|
+
require "sqlite3"
|
6
|
+
|
7
|
+
$db = SQLite3::Database.new("../data/monoids.db")
|
8
|
+
|
9
|
+
[2,3,4,5,6,7].each do |i|
|
10
|
+
puts "Monoids of order #{i}:"
|
11
|
+
total = 0
|
12
|
+
syntactic = 0
|
13
|
+
regular = 0
|
14
|
+
reg_ns = 0
|
15
|
+
inverse = 0
|
16
|
+
inv_ns = 0
|
17
|
+
|
18
|
+
$db.execute("SELECT binop FROM monoids WHERE ord=#{i};").each do |binop|
|
19
|
+
monoid = RLSM::Monoid[*binop]
|
20
|
+
|
21
|
+
total += 1
|
22
|
+
if monoid.syntactic?
|
23
|
+
syntactic += 1
|
24
|
+
regular += 1 if monoid.regular?
|
25
|
+
inverse += 1 if monoid.inverse?
|
26
|
+
else
|
27
|
+
regular += 1; reg_ns += 1 if monoid.regular?
|
28
|
+
inverse += 1; inv_ns += 1 if monoid.inverse?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
puts " Total: #{total}"
|
33
|
+
puts " Syntactic: #{syntactic}"
|
34
|
+
puts "Not Syntactic: #{total - syntactic}"
|
35
|
+
puts " Regular: #{regular}"
|
36
|
+
puts " Inverse: #{inverse}"
|
37
|
+
puts " Regular ns: #{reg_ns}"
|
38
|
+
puts " Inverse ns: #{inv_ns}"
|
39
|
+
puts
|
40
|
+
puts
|
41
|
+
end
|