euler 1.0.8 → 1.1.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.
- data/.gitignore +2 -1
- data/README.rdoc +28 -9
- data/Rakefile +8 -2
- data/VERSION +1 -1
- data/euler.gemspec +55 -0
- data/lib/euler.rb +19 -1
- data/lib/rudoku.rb +178 -0
- data/test/tc_integer_methods.rb +2 -2
- data/test/tc_module.rb +2 -2
- data/test/tc_rudoku.rb +28 -0
- data/test/test_euler.rb +2 -1
- metadata +7 -4
- data/README.txt +0 -55
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
= euler
|
2
2
|
|
3
|
-
|
3
|
+
== DESCRIPTION
|
4
4
|
|
5
|
-
|
5
|
+
libeuler is a simple library you can include in your code to take away some of the boring repetitive parts of solving Project Euler problems.
|
6
|
+
|
7
|
+
== FEATURES
|
8
|
+
|
9
|
+
* Adds various methods to the Integer class, such as factorial, prime?, is_fibonacci?, etc.
|
10
|
+
* Provides various module methods, such as generate_sieve, get_primes, etc.
|
11
|
+
|
12
|
+
== SYNOPSIS
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'euler'
|
16
|
+
|
17
|
+
5.factorial # => 120
|
18
|
+
|
19
|
+
== REQUIREMENTS
|
20
|
+
|
21
|
+
* none
|
22
|
+
|
23
|
+
== INSTALL
|
24
|
+
|
25
|
+
* sudo gem install euler
|
26
|
+
|
27
|
+
== COLLABORATION
|
6
28
|
|
7
29
|
* Fork the project.
|
8
30
|
* Make your feature addition or bug fix.
|
9
|
-
* Add tests for it. This is important so I don't break it in a
|
10
|
-
|
11
|
-
* Commit, do not mess with rakefile, version, or history.
|
12
|
-
(if you want to have your own version, that is fine but
|
13
|
-
bump version in a commit by itself I can ignore when I pull)
|
31
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
32
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
14
33
|
* Send me a pull request. Bonus points for topic branches.
|
15
34
|
|
16
|
-
==
|
35
|
+
== COPYRIGHT
|
17
36
|
|
18
|
-
Copyright (c) 2009 Mike Skalnik. See LICENSE for details.
|
37
|
+
Copyright (c) 2009 Mike Skalnik, Nick Kezhaya. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -9,8 +9,14 @@ begin
|
|
9
9
|
gem.description = %Q{A gem that provides a small library to help in removing the repetativeness of solving Project Euler problems.}
|
10
10
|
gem.email = "mike.skalnik@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/skalnik/euler"
|
12
|
-
gem.authors = ["Mike Skalnik"]
|
12
|
+
gem.authors = ["Mike Skalnik", "Nick Kezhaya"]
|
13
|
+
gem.rubyforge_project = 'euler'
|
13
14
|
end
|
15
|
+
|
16
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
17
|
+
rubyforge.doc_task = 'rdoc'
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
14
20
|
rescue LoadError
|
15
21
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
16
22
|
end
|
@@ -51,4 +57,4 @@ Rake::RDocTask.new do |rdoc|
|
|
51
57
|
rdoc.title = "euler #{version}"
|
52
58
|
rdoc.rdoc_files.include('README*')
|
53
59
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
-
end
|
60
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/euler.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{euler}
|
8
|
+
s.version = "1.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Mike Skalnik", "Nick Kezhaya"]
|
12
|
+
s.date = %q{2009-10-11}
|
13
|
+
s.description = %q{A gem that provides a small library to help in removing the repetativeness of solving Project Euler problems.}
|
14
|
+
s.email = %q{mike.skalnik@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"euler.gemspec",
|
26
|
+
"lib/euler.rb",
|
27
|
+
"lib/rudoku.rb",
|
28
|
+
"test/tc_integer_methods.rb",
|
29
|
+
"test/tc_module.rb",
|
30
|
+
"test/tc_rudoku.rb",
|
31
|
+
"test/test_euler.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/skalnik/euler}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubyforge_project = %q{euler}
|
37
|
+
s.rubygems_version = %q{1.3.5}
|
38
|
+
s.summary = %q{A small library to help solve Projet Euler problems.}
|
39
|
+
s.test_files = [
|
40
|
+
"test/tc_integer_methods.rb",
|
41
|
+
"test/tc_module.rb",
|
42
|
+
"test/tc_rudoku.rb",
|
43
|
+
"test/test_euler.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
+
else
|
52
|
+
end
|
53
|
+
else
|
54
|
+
end
|
55
|
+
end
|
data/lib/euler.rb
CHANGED
@@ -173,7 +173,25 @@ module Euler
|
|
173
173
|
return Math.sqrt(c**2 - a**2) if b.nil?
|
174
174
|
return Math.sqrt(a**2 + b**2) if c.nil?
|
175
175
|
end
|
176
|
-
|
176
|
+
|
177
|
+
# Solves a Sudoku puzzle passed in as a 2D array.
|
178
|
+
# Euler.solve_sudoku(
|
179
|
+
# [[0, 0, 3, 0, 2, 0, 6, 0, 0],
|
180
|
+
# [9, 0, 0, 3, 0, 5, 0, 0, 1],
|
181
|
+
# [0, 0, 1, 8, 0, 6, 4, 0, 0],
|
182
|
+
# [0, 0, 8, 1, 0, 2, 9, 0, 0],
|
183
|
+
# [7, 0, 0, 0, 0, 0, 0, 0, 8],
|
184
|
+
# [0, 0, 6, 7, 0, 8, 2, 0, 0],
|
185
|
+
# [0, 0, 2, 6, 0, 9, 5, 0, 0],
|
186
|
+
# [8, 0, 0, 2, 0, 3, 0, 0, 9],
|
187
|
+
# [0, 0, 5, 0, 1, 0, 3, 0, 0]]
|
188
|
+
# ) # => [[4, 8, 3, 9, 2, 1, 6, 5, 7], [9, 6, 7, 3, 4, 5, 8, 2, 1], [2, 5, 1, 8, 7, 6, 4, 9, 3], [5, 4, 8, 1, 3, 2, 9, 7, 6], [7, 2, 9, 5, 6, 4, 1, 3, 8], [1, 3, 6, 7, 9, 8, 2, 4, 5], [3, 7, 2, 6, 8, 9, 5, 1, 4], [8, 1, 4, 2, 5, 3, 7, 6, 9], [6, 9, 5, 4, 1, 7, 3, 8, 2]]
|
189
|
+
def solve_sudoku(puzzle)
|
190
|
+
require File.dirname(__FILE__) + "/rudoku"
|
191
|
+
rudoku = Rudoku.new(puzzle)
|
192
|
+
rudoku.backtrack_solve
|
193
|
+
rudoku.to_a
|
194
|
+
end
|
177
195
|
end
|
178
196
|
|
179
197
|
# Just adds Euler::IntegerMethods to the Integer class.
|
data/lib/rudoku.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
class Rudoku
|
2
|
+
def initialize(sudoku)
|
3
|
+
@n = sudoku.size
|
4
|
+
@sqrt_n = Math.sqrt(@n).to_i
|
5
|
+
raise "wrong sudoku size" unless @sqrt_n * @sqrt_n == @n
|
6
|
+
|
7
|
+
@arr = sudoku.collect { |row|
|
8
|
+
(0...@n).collect { |i|
|
9
|
+
((1..@n) === row[i]) ? [row[i]] : (1..@n).to_a
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
@rfix = Array.new(@n) { [] }
|
14
|
+
@cfix = Array.new(@n) { [] }
|
15
|
+
@bfix = Array.new(@n) { [] }
|
16
|
+
@n.times { |r| @n.times { |c| update_fix(r, c) } }
|
17
|
+
|
18
|
+
[@rfix, @cfix, @bfix].each { |fix| fix.each { |x|
|
19
|
+
unless x.size == x.uniq.size
|
20
|
+
raise "non-unique numbers in row, col or box"
|
21
|
+
end
|
22
|
+
} }
|
23
|
+
end
|
24
|
+
|
25
|
+
def solve
|
26
|
+
begin
|
27
|
+
until finished?
|
28
|
+
progress = false
|
29
|
+
while reduce
|
30
|
+
progress = true
|
31
|
+
end
|
32
|
+
progress = true if deduce
|
33
|
+
return :unknown unless progress
|
34
|
+
end
|
35
|
+
:solved
|
36
|
+
rescue
|
37
|
+
:impossible
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def backtrack_solve
|
42
|
+
if (res = solve) == :unknown
|
43
|
+
r, c = 0, 0
|
44
|
+
@rfix.each_with_index { |rf, r|
|
45
|
+
break if rf.size < @n
|
46
|
+
}
|
47
|
+
@arr[r].each_with_index { |x, c|
|
48
|
+
break if x.size > 1
|
49
|
+
}
|
50
|
+
partial = to_a
|
51
|
+
solutions = []
|
52
|
+
@arr[r][c].each { |guess|
|
53
|
+
partial[r][c] = guess
|
54
|
+
rsolver = Rudoku.new(partial)
|
55
|
+
case rsolver.backtrack_solve
|
56
|
+
when :multiple_solutions
|
57
|
+
initialize(rsolver.to_a)
|
58
|
+
return :multiple_solutions
|
59
|
+
when :solved
|
60
|
+
solutions << rsolver
|
61
|
+
end
|
62
|
+
}
|
63
|
+
if solutions.empty?
|
64
|
+
return :impossible
|
65
|
+
else
|
66
|
+
initialize(solutions[0].to_a)
|
67
|
+
return solutions.size > 1 ? :multiple_solutions : :solved
|
68
|
+
end
|
69
|
+
end
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_a
|
74
|
+
@arr.collect { |row| row.collect { |x|
|
75
|
+
(x.size == 1) ? x[0] : nil
|
76
|
+
} }
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
fw = @n.to_s.size
|
81
|
+
to_a.collect { |row| row.collect { |x|
|
82
|
+
(x ? x.to_s : "_").rjust(fw)
|
83
|
+
}.join " " }.join "\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
def finished?
|
87
|
+
@arr.each { |row| row.each { |x| return false if x.size > 1 } }
|
88
|
+
true
|
89
|
+
end
|
90
|
+
|
91
|
+
def reduce
|
92
|
+
success = false
|
93
|
+
@n.times { |r| @n.times { |c|
|
94
|
+
if (sz = @arr[r][c].size) > 1
|
95
|
+
@arr[r][c] = @arr[r][c] -
|
96
|
+
(@rfix[r] | @cfix[c] | @bfix[rc2box(r, c)])
|
97
|
+
raise "impossible to solve" if @arr[r][c].empty?
|
98
|
+
if @arr[r][c].size < sz
|
99
|
+
success = true
|
100
|
+
update_fix(r, c)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
} }
|
104
|
+
success
|
105
|
+
end
|
106
|
+
|
107
|
+
def deduce
|
108
|
+
success = false
|
109
|
+
[:col_each, :row_each, :box_each].each { |meth|
|
110
|
+
@n.times { |i|
|
111
|
+
u = uniqs_in(meth, i)
|
112
|
+
unless u.empty?
|
113
|
+
send(meth, i) { |x|
|
114
|
+
if x.size > 1 && ((u2 = u & x).size == 1)
|
115
|
+
success = true
|
116
|
+
u2
|
117
|
+
else
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
}
|
121
|
+
return success if success
|
122
|
+
end
|
123
|
+
}
|
124
|
+
}
|
125
|
+
success
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
def rc2box(r, c)
|
130
|
+
(r - (r % @sqrt_n)) + (c / @sqrt_n)
|
131
|
+
end
|
132
|
+
|
133
|
+
def update_fix(r, c)
|
134
|
+
if @arr[r][c].size == 1
|
135
|
+
@rfix[r] << @arr[r][c][0]
|
136
|
+
@cfix[c] << @arr[r][c][0]
|
137
|
+
@bfix[rc2box(r, c)] << @arr[r][c][0]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def row_each(r)
|
142
|
+
@n.times { |c|
|
143
|
+
if (res = yield(@arr[r][c]))
|
144
|
+
@arr[r][c] = res
|
145
|
+
update_fix(r, c)
|
146
|
+
end
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def col_each(c)
|
151
|
+
@n.times { |r|
|
152
|
+
if (res = yield(@arr[r][c]))
|
153
|
+
@arr[r][c] = res
|
154
|
+
update_fix(r, c)
|
155
|
+
end
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def box_each(b)
|
160
|
+
off_r, off_c = (b - (b % @sqrt_n)), (b % @sqrt_n) * @sqrt_n
|
161
|
+
@n.times { |i|
|
162
|
+
r, c = off_r + (i / @sqrt_n), off_c + (i % @sqrt_n)
|
163
|
+
if (res = yield(@arr[r][c]))
|
164
|
+
@arr[r][c] = res
|
165
|
+
update_fix(r, c)
|
166
|
+
end
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
def uniqs_in(each_meth, index)
|
171
|
+
h = Hash.new(0)
|
172
|
+
send(each_meth, index) { |x|
|
173
|
+
x.each { |n| h[n] += 1 } if x.size > 1
|
174
|
+
nil
|
175
|
+
}
|
176
|
+
h.select { |k, v| v == 1 }.collect { |k, v| k }
|
177
|
+
end
|
178
|
+
end
|
data/test/tc_integer_methods.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test/unit"
|
2
2
|
|
3
|
-
require "euler"
|
3
|
+
require File.dirname(__FILE__) + "/../lib/euler"
|
4
4
|
|
5
5
|
class TestIntegerMethods < Test::Unit::TestCase
|
6
6
|
def test_factorial
|
@@ -42,4 +42,4 @@ class TestIntegerMethods < Test::Unit::TestCase
|
|
42
42
|
assert_equal(2, 10.length, "10 has a length of 2")
|
43
43
|
assert_equal(4, 4563.length, "4563 has a length of 4")
|
44
44
|
end
|
45
|
-
end
|
45
|
+
end
|
data/test/tc_module.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test/unit"
|
2
2
|
|
3
|
-
require "euler"
|
3
|
+
require File.dirname(__FILE__) + "/../lib/euler"
|
4
4
|
|
5
5
|
class TestModule < Test::Unit::TestCase
|
6
6
|
def test_sieve
|
@@ -37,4 +37,4 @@ class TestModule < Test::Unit::TestCase
|
|
37
37
|
assert_equal(4, Euler.find_missing_pyth_value(3, nil, 5))
|
38
38
|
assert_equal(5, Euler.find_missing_pyth_value(3, 4, nil))
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
data/test/tc_rudoku.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/../lib/euler"
|
4
|
+
|
5
|
+
class TestRudoku < Test::Unit::TestCase
|
6
|
+
def test_rudoku
|
7
|
+
assert_equal([[4, 8, 3, 9, 2, 1, 6, 5, 7],
|
8
|
+
[9, 6, 7, 3, 4, 5, 8, 2, 1],
|
9
|
+
[2, 5, 1, 8, 7, 6, 4, 9, 3],
|
10
|
+
[5, 4, 8, 1, 3, 2, 9, 7, 6],
|
11
|
+
[7, 2, 9, 5, 6, 4, 1, 3, 8],
|
12
|
+
[1, 3, 6, 7, 9, 8, 2, 4, 5],
|
13
|
+
[3, 7, 2, 6, 8, 9, 5, 1, 4],
|
14
|
+
[8, 1, 4, 2, 5, 3, 7, 6, 9],
|
15
|
+
[6, 9, 5, 4, 1, 7, 3, 8, 2]],
|
16
|
+
Euler.solve_sudoku([[0, 0, 3, 0, 2, 0, 6, 0, 0],
|
17
|
+
[9, 0, 0, 3, 0, 5, 0, 0, 1],
|
18
|
+
[0, 0, 1, 8, 0, 6, 4, 0, 0],
|
19
|
+
[0, 0, 8, 1, 0, 2, 9, 0, 0],
|
20
|
+
[7, 0, 0, 0, 0, 0, 0, 0, 8],
|
21
|
+
[0, 0, 6, 7, 0, 8, 2, 0, 0],
|
22
|
+
[0, 0, 2, 6, 0, 9, 5, 0, 0],
|
23
|
+
[8, 0, 0, 2, 0, 3, 0, 0, 9],
|
24
|
+
[0, 0, 5, 0, 1, 0, 3, 0, 0]]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
data/test/test_euler.rb
CHANGED
metadata
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: euler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Skalnik
|
8
|
+
- Nick Kezhaya
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
@@ -22,17 +23,18 @@ extensions: []
|
|
22
23
|
extra_rdoc_files:
|
23
24
|
- LICENSE
|
24
25
|
- README.rdoc
|
25
|
-
- README.txt
|
26
26
|
files:
|
27
27
|
- .gitignore
|
28
28
|
- LICENSE
|
29
29
|
- README.rdoc
|
30
|
-
- README.txt
|
31
30
|
- Rakefile
|
32
31
|
- VERSION
|
32
|
+
- euler.gemspec
|
33
33
|
- lib/euler.rb
|
34
|
+
- lib/rudoku.rb
|
34
35
|
- test/tc_integer_methods.rb
|
35
36
|
- test/tc_module.rb
|
37
|
+
- test/tc_rudoku.rb
|
36
38
|
- test/test_euler.rb
|
37
39
|
has_rdoc: true
|
38
40
|
homepage: http://github.com/skalnik/euler
|
@@ -57,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
59
|
version:
|
58
60
|
requirements: []
|
59
61
|
|
60
|
-
rubyforge_project:
|
62
|
+
rubyforge_project: euler
|
61
63
|
rubygems_version: 1.3.5
|
62
64
|
signing_key:
|
63
65
|
specification_version: 3
|
@@ -65,4 +67,5 @@ summary: A small library to help solve Projet Euler problems.
|
|
65
67
|
test_files:
|
66
68
|
- test/tc_integer_methods.rb
|
67
69
|
- test/tc_module.rb
|
70
|
+
- test/tc_rudoku.rb
|
68
71
|
- test/test_euler.rb
|
data/README.txt
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
= euler
|
2
|
-
|
3
|
-
== DESCRIPTION:
|
4
|
-
|
5
|
-
libeuler is a simple library you can include in your code to take away some of the boring repetitive parts of solving Project Euler problems.
|
6
|
-
|
7
|
-
== FEATURES:
|
8
|
-
|
9
|
-
* Adds various methods to the Integer class, such as factorial, prime?, is_fibonacci?, etc.
|
10
|
-
* Provides various module methods, such as generate_sieve, get_primes, etc.
|
11
|
-
|
12
|
-
== SYNOPSIS:
|
13
|
-
|
14
|
-
require 'rubygems'
|
15
|
-
require 'euler'
|
16
|
-
|
17
|
-
5.factorial # => 120
|
18
|
-
|
19
|
-
== REQUIREMENTS:
|
20
|
-
|
21
|
-
* none
|
22
|
-
|
23
|
-
== INSTALL:
|
24
|
-
|
25
|
-
* sudo gem install euler
|
26
|
-
|
27
|
-
== LICENSE:
|
28
|
-
|
29
|
-
(BSD License)
|
30
|
-
|
31
|
-
Copyright (c) 2008, Mike "Oompa" Skalnik ("THE AUTHOR")
|
32
|
-
All rights reserved. mike.skalnik@gmail.com
|
33
|
-
|
34
|
-
Redistribution and use in source and binary forms, with or without
|
35
|
-
modification, are permitted provided that the following conditions are met:
|
36
|
-
* Redistributions of source code must retain the above copyright
|
37
|
-
notice, this list of conditions and the following disclaimer.
|
38
|
-
* Redistributions in binary form must reproduce the above copyright
|
39
|
-
notice, this list of conditions and the following disclaimer in the
|
40
|
-
documentation and/or other materials provided with the distribution.
|
41
|
-
* Neither the name of the author nor the
|
42
|
-
names of its contributors may be used to endorse or promote products
|
43
|
-
derived from this software without specific prior written permission.
|
44
|
-
|
45
|
-
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY
|
46
|
-
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
47
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
48
|
-
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
49
|
-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
50
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
51
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
52
|
-
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
53
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
54
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
55
|
-
|