fortune 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/fortune.gemspec +26 -0
- data/lib/fortune.rb +71 -0
- data/lib/fortune/a.rb +14 -0
- data/lib/fortune/c.rb +14 -0
- data/lib/fortune/c_repetition.rb +11 -0
- data/lib/fortune/event.rb +30 -0
- data/lib/fortune/event_list.rb +45 -0
- data/lib/fortune/odds.rb +140 -0
- data/lib/fortune/p.rb +58 -0
- data/lib/fortune/p_abstract.rb +19 -0
- data/lib/fortune/pn.rb +16 -0
- data/lib/fortune/pn_repetition.rb +13 -0
- data/lib/fortune/version.rb +3 -0
- data/spec/fortune/a_spec.rb +13 -0
- data/spec/fortune/c_repetition_spec.rb +13 -0
- data/spec/fortune/c_spec.rb +13 -0
- data/spec/fortune/event_spec.rb +17 -0
- data/spec/fortune/odds_spec.rb +32 -0
- data/spec/fortune/p_spec.rb +54 -0
- data/spec/fortune/pn_repetition_spec.rb +13 -0
- data/spec/fortune/pn_spec.rb +16 -0
- data/spec/fortune_spec.rb +11 -0
- data/spec/hash_spec.rb +29 -0
- data/spec/math_spec.rb +12 -0
- data/spec/spec_helper.rb +12 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9fc004785ef01cd70f23583a76c0d36cfd7d3607
|
4
|
+
data.tar.gz: eb71d50d976e4d0a78f582e2db63dc5a6947f9c3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: df3008f56c4471c58cad733994baec963df15e064c80c8ddc0a46700417a571031c874e42e1220e4d75e1f396a962ac50cd75283d1cb30b20c3e990a9a0f4e32
|
7
|
+
data.tar.gz: 19695ff2b954f96f74ef008954690d18088d1116d13811db7dae5b54ffc634bc4fa3c05ffff2c515e9eb15c67fb082291db4d2a05185bc0e6663f819be84d10c
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format documentation
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Fotom
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Fortune
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'fortune'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install fortune
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/fortune.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fortune/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fortune"
|
8
|
+
spec.version = Fortune::VERSION
|
9
|
+
spec.authors = ["Malykh Oleg"]
|
10
|
+
spec.email = ["malykholeg@gmail.com"]
|
11
|
+
spec.description = %q{Ruby gem for calculate probability, odds and combinations. Mostly helpfull for gambling, e.g. Poker.}
|
12
|
+
spec.summary = %q{Lib for get changes, odds, probability and combinations for given values}
|
13
|
+
spec.homepage = "https://github.com/Fotom/Fortune"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
data/lib/fortune.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require "fortune/version"
|
2
|
+
|
3
|
+
require 'fortune/p_abstract'
|
4
|
+
require 'fortune/a'
|
5
|
+
require 'fortune/c'
|
6
|
+
require 'fortune/p'
|
7
|
+
require 'fortune/c_repetition'
|
8
|
+
require 'fortune/event_list'
|
9
|
+
require 'fortune/event'
|
10
|
+
require 'fortune/odds'
|
11
|
+
require 'fortune/pn'
|
12
|
+
require 'fortune/pn_repetition'
|
13
|
+
|
14
|
+
module Fortune
|
15
|
+
|
16
|
+
factorial = %q{
|
17
|
+
def self.factorial(n)
|
18
|
+
return 1 if n.zero?
|
19
|
+
1.upto(n).inject(:*)
|
20
|
+
end
|
21
|
+
}
|
22
|
+
Math.module_eval(factorial)
|
23
|
+
|
24
|
+
# alias
|
25
|
+
Pnr = Pn_repetition
|
26
|
+
|
27
|
+
# Fortune::Pnr(h) || Fortune.Pnr(h)
|
28
|
+
[:Cr, :C_repetition, :C, :A, :Pnr, :Pn_repetition, :Pn].each{|c|
|
29
|
+
Fortune.module_eval(%|
|
30
|
+
def self.#{c}(h)
|
31
|
+
#{c}.calc(h)
|
32
|
+
end
|
33
|
+
|)
|
34
|
+
}
|
35
|
+
|
36
|
+
# alias
|
37
|
+
Cr = C_repetition
|
38
|
+
|
39
|
+
def self.P(*args)
|
40
|
+
P.new(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Hash
|
46
|
+
|
47
|
+
def to_P
|
48
|
+
n = 0
|
49
|
+
self.each{|k,v| n += v.to_i}
|
50
|
+
self.each{|k,v| self[k] = Fortune::P(:m => v.to_i, :n => n)}
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_p
|
55
|
+
self.to_P.each{|k,v| self[k] = v.value}
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# {:a => 1, :b => 2, ...}
|
60
|
+
def choose
|
61
|
+
Fortune::Event.select(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
# {[:a, :b] => 1, [:c] => 2, ...} ||
|
65
|
+
# {10 => 1, 15 => 2, ...}
|
66
|
+
def choose_set
|
67
|
+
Fortune::P.n_select(self)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
data/lib/fortune/a.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# Permutation without repetition with select k elements (accommodation)
|
4
|
+
# example: 20 different elements and you need select 5 of them (how many ways of selection exists?)
|
5
|
+
# elements is ordered ([a,b,c] != [b,c,a])
|
6
|
+
# A.calc(:elements => 10, :select => 5)
|
7
|
+
class A < P_abstract
|
8
|
+
def initialize(h)
|
9
|
+
super(h)
|
10
|
+
self.value = Math.factorial(self.n)/Math.factorial(self.n - self.k)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/lib/fortune/c.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# Combinations without repetition
|
4
|
+
# example: 10 different elements (students) and you need select 5 of them (how many ways of selection exists?)
|
5
|
+
# elements does not ordered ([a,b,c] == [b,c,a])
|
6
|
+
# C.calc(:elements => 10, :select => 5)
|
7
|
+
class C < P_abstract
|
8
|
+
def initialize(h)
|
9
|
+
super(h)
|
10
|
+
self.value = Math.factorial(self.n)/(Math.factorial(self.k)*Math.factorial(self.n - self.k))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
class Event
|
4
|
+
attr_accessor :has_come, :name, :m, :n
|
5
|
+
def initialize(h = {})
|
6
|
+
@has_come = false
|
7
|
+
[:name, :n, :m].each{|k| instance_variable_set("@#{k}", h[k])}
|
8
|
+
end
|
9
|
+
def p(h = {})
|
10
|
+
P.new(:m => self.m, :n => h[:n] || self.n).value
|
11
|
+
end
|
12
|
+
def try(h = {})
|
13
|
+
@has_come = P.is(self.m, h[:n] || self.n)
|
14
|
+
self
|
15
|
+
end
|
16
|
+
def has_come?
|
17
|
+
@has_come
|
18
|
+
end
|
19
|
+
def set_come
|
20
|
+
@has_come = true
|
21
|
+
end
|
22
|
+
def self.list(h = {})
|
23
|
+
EventList.new(h).calc
|
24
|
+
end
|
25
|
+
def self.select(h = {})
|
26
|
+
Event.list(h).active.name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
class EventList < Array
|
4
|
+
attr_accessor :sum_m, :intervals, :n
|
5
|
+
def initialize(h = {})
|
6
|
+
h.each{|name, m| self.push(Event.new({:name => name, :m => m}))}
|
7
|
+
@sum_m = 0
|
8
|
+
@intervals = {}
|
9
|
+
end
|
10
|
+
def calc
|
11
|
+
self.calc_sum_m
|
12
|
+
self.calc_intervals
|
13
|
+
self.get_n
|
14
|
+
self.set_active
|
15
|
+
self
|
16
|
+
end
|
17
|
+
def set_active
|
18
|
+
self.map{|event|
|
19
|
+
next if event.m <= 0
|
20
|
+
event.set_come if self.n >= intervals[event.name][0] && self.n <= intervals[event.name][1]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
def get_n
|
24
|
+
@n = P.n(self.sum_m)
|
25
|
+
end
|
26
|
+
def calc_sum_m
|
27
|
+
self.map{|event|
|
28
|
+
next if event.m <= 0
|
29
|
+
self.sum_m += event.m
|
30
|
+
}
|
31
|
+
end
|
32
|
+
def calc_intervals
|
33
|
+
x = 0
|
34
|
+
self.map{|event|
|
35
|
+
next if event.m <= 0
|
36
|
+
self.intervals[event.name] = [x + 1, x + event.m]
|
37
|
+
x = x + event.m
|
38
|
+
}
|
39
|
+
end
|
40
|
+
def active
|
41
|
+
self.select{|event| event.has_come?}.first
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/fortune/odds.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# win
|
4
|
+
class Odds
|
5
|
+
include Comparable
|
6
|
+
attr_accessor :p, :s, :k, :type
|
7
|
+
|
8
|
+
def initialize(h = {})
|
9
|
+
# TODO: check p or (s and k) exists
|
10
|
+
h[:s] ||= h[:win]
|
11
|
+
h[:k] ||= h[:lose]
|
12
|
+
[:win, :lose].each{|k| h.delete(k)}
|
13
|
+
|
14
|
+
h.each{|k,v| instance_variable_set("@#{k}", v)}
|
15
|
+
self.p = P.new(s, s + k).value unless self.p
|
16
|
+
self.calc_s_k if !self.k || !self.s
|
17
|
+
|
18
|
+
self.to_win
|
19
|
+
end
|
20
|
+
|
21
|
+
def <=>(other)
|
22
|
+
if self.p < other.p
|
23
|
+
-1
|
24
|
+
elsif self.p > other.p
|
25
|
+
1
|
26
|
+
else
|
27
|
+
0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_i
|
32
|
+
self.s, self.k = self.s.to_i, self.k.to_i
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def n_all
|
37
|
+
s + k
|
38
|
+
end
|
39
|
+
alias :variants :n_all
|
40
|
+
|
41
|
+
# h = {:k => int, [:fractions => true]}
|
42
|
+
def to_human(h = {:k => 7})
|
43
|
+
min_delta = nil
|
44
|
+
closest_odd = nil
|
45
|
+
|
46
|
+
Odds.human(h).each{|odd|
|
47
|
+
delta = (self.p - odd.p).abs
|
48
|
+
if !min_delta || delta < min_delta
|
49
|
+
min_delta = delta
|
50
|
+
closest_odd = odd
|
51
|
+
end
|
52
|
+
}
|
53
|
+
|
54
|
+
closest_odd
|
55
|
+
end
|
56
|
+
|
57
|
+
def is_on_win?
|
58
|
+
self.type == :on_win
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_on_lose?
|
62
|
+
self.type == :on_lose
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_win
|
66
|
+
self.s_to_k if self.is_on_lose?
|
67
|
+
self.type = :on_win
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def s_to_k
|
72
|
+
self.s, self.k = self.k, self.s
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_lose
|
76
|
+
self.s_to_k if self.is_on_win?
|
77
|
+
self.type = :on_lose
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def revert
|
82
|
+
self.s_to_k
|
83
|
+
self.p = 1 - self.p
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.equal
|
88
|
+
Odds.new({:s => 1, :k => 1})
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.human(h)
|
92
|
+
Odds.p_human(h).values
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_s
|
96
|
+
"#{self.s}:#{self.k} #{self.type} (p: #{p_obj.to_percent_string})"
|
97
|
+
end
|
98
|
+
|
99
|
+
def p_obj
|
100
|
+
P.new(self.p)
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def calc_s_k
|
106
|
+
self.s = 1
|
107
|
+
self.k = s.to_f/p.to_f - s.to_f
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def self.p_human(h)
|
113
|
+
p_odds = {Odds.equal.p => Odds.equal}
|
114
|
+
(1..h[:k]).each{|k|
|
115
|
+
(0..k-1).each{|s|
|
116
|
+
Odds.fillup_p_human(p_odds, s, k)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
h[:fractions] ? Odds.add_fractions(p_odds, h) : p_odds
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.fillup_p_human(p_odds, s, k)
|
124
|
+
odd = Odds.new({:s => s, :k => k})
|
125
|
+
odd_dup = odd.dup.revert
|
126
|
+
p_odds[odd.p] = odd if not p_odds.has_key?(odd.p)
|
127
|
+
p_odds[odd_dup.p] = odd_dup if not p_odds.has_key?(odd_dup.p)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.add_fractions(p_odds, h)
|
131
|
+
p_odds_addons = {}
|
132
|
+
p_odds.each{|key, odd|
|
133
|
+
next if odd.k == h[:k]
|
134
|
+
Odds.fillup_p_human(p_odds_addons, odd.s, odd.k + 0.5)
|
135
|
+
}
|
136
|
+
p_odds_addons.merge(p_odds)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
data/lib/fortune/p.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
class P
|
4
|
+
attr_accessor :p, :m, :n
|
5
|
+
|
6
|
+
# P.new(:m => 1, :n => 10), P.new(1, 10), P.new(0.1)
|
7
|
+
def initialize(m, n_all = nil)
|
8
|
+
m, n_all = m[:m], m[:n] if m.is_a?(Hash)
|
9
|
+
raise ArgumentError.new("Error: p should be less or equal 1") if (!n_all && m > 1) || (n_all && m > n_all)
|
10
|
+
@p = m unless n_all
|
11
|
+
@p = m.to_f/n_all.to_f if n_all
|
12
|
+
@m, @n = m, n_all if n_all
|
13
|
+
end
|
14
|
+
|
15
|
+
def +(other)
|
16
|
+
P.new(self.p + other.p)
|
17
|
+
end
|
18
|
+
|
19
|
+
def *(other)
|
20
|
+
P.new(self.p * other.p)
|
21
|
+
end
|
22
|
+
|
23
|
+
def odds
|
24
|
+
Odds.new(:p => self.p)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_percent_human
|
28
|
+
self.to_percent.round(2)
|
29
|
+
end
|
30
|
+
alias :to_human :to_percent_human
|
31
|
+
|
32
|
+
def to_percent
|
33
|
+
self.p*100
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_percent_string
|
37
|
+
'%5.2f' % [self.to_percent] + '%'
|
38
|
+
end
|
39
|
+
|
40
|
+
def value
|
41
|
+
self.p
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.is(chance, n_all)
|
45
|
+
P.n(n_all) <= chance
|
46
|
+
end
|
47
|
+
def self.n(n_all)
|
48
|
+
n_all.is_a?(Array) ? n_all.sample : rand(n_all) + 1
|
49
|
+
end
|
50
|
+
# P.n_select([1..10] => 5, [3..15] => 20, ...)
|
51
|
+
# || P.n_select(10 => 90, 5 => 10)
|
52
|
+
# || P.n_select([:a, :b] => 1, [:c] => 2)
|
53
|
+
def self.n_select(h = {})
|
54
|
+
P.n(Event.select(h))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# Permutations
|
4
|
+
class P_abstract
|
5
|
+
attr_accessor :value, :n, :k
|
6
|
+
|
7
|
+
def initialize(h, format = {:n => :elements, :k => :select})
|
8
|
+
raise ArgumentError.new("Error: arguments should be hash") unless h.is_a?(Hash)
|
9
|
+
self.n = h[:n] || h[format[:n]]
|
10
|
+
self.k = h[:k] || h[format[:k]]
|
11
|
+
self.value = h
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.calc(n)
|
15
|
+
self.new(n).value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/fortune/pn.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# Permutation without repetition
|
4
|
+
# example: the amount of distributions of the four teams in four places (Pn.calc(4))
|
5
|
+
# Pn.calc(5), Pn.calc(:elements => 5), Pn.calc(:elements => 5, :select => 2)
|
6
|
+
class Pn < P_abstract
|
7
|
+
|
8
|
+
def initialize(h)
|
9
|
+
h = {:n => h} unless h.is_a?(Hash)
|
10
|
+
super(h)
|
11
|
+
self.value = self.k ? A.calc(h) : Math.factorial(self.n)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fortune
|
2
|
+
|
3
|
+
# Permutation with repetition
|
4
|
+
# example: how many different options you can dress up if there are three sweaters two skirts and two hats (3*2*2, if all thing is equal 3, then: Pn_repetition(:n => 3, :k => 3), k - element groups, n - elements count in group)
|
5
|
+
# Pnr.calc(:groups => 10, :elements => 5)
|
6
|
+
class Pn_repetition < P_abstract
|
7
|
+
def initialize(h)
|
8
|
+
super(h, {:n => :groups, :k => :elements})
|
9
|
+
self.value = self.n**self.k
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fortune::Event do
|
4
|
+
|
5
|
+
it "should have p" do
|
6
|
+
Fortune::Event.new(:name => :get_prize, :m => 1, :n => 5).p.should eq 0.2
|
7
|
+
end
|
8
|
+
it "certain event should be" do
|
9
|
+
Fortune::Event.new(:name => :get_prize, :m => 1, :n => 1).try.has_come?.should eq true
|
10
|
+
end
|
11
|
+
it "impossible event should not be" do
|
12
|
+
Fortune::Event.new(:name => :get_prize, :m => 0, :n => 1).try.has_come?.should eq false
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fortune::Odds do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@odd = Fortune::Odds.new(:win => 1, :lose => 9)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "correct comparison" do
|
10
|
+
@odd.should > Fortune::Odds.new(:win => 1, :lose => 99)
|
11
|
+
end
|
12
|
+
it "calculate variants" do
|
13
|
+
@odd.n_all.should eq 10
|
14
|
+
@odd.variants.should eq 10
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "to_human" do
|
18
|
+
it "convert for 1:7 max" do
|
19
|
+
Fortune::Odds.new(:win => 400, :lose => 891).to_human.should eq Fortune::Odds.new(:win => 3, :lose => 7)
|
20
|
+
end
|
21
|
+
it "convert for 1:10 max" do
|
22
|
+
Fortune::Odds.new(:win => 400, :lose => 891).to_human(:k => 10).should eq Fortune::Odds.new(:win => 4, :lose => 9)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "revertion" do
|
27
|
+
@odd.revert.should eq Fortune::Odds.new(:win => 9, :lose => 1)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fortune::P do
|
4
|
+
|
5
|
+
describe "new" do
|
6
|
+
it "create by n, m params" do
|
7
|
+
Fortune::P.new(:m => 1, :n => 10).value.should eq 0.1
|
8
|
+
end
|
9
|
+
it "create by list params" do
|
10
|
+
Fortune::P.new(1, 10).value.should eq 0.1
|
11
|
+
end
|
12
|
+
it "create by probability params" do
|
13
|
+
Fortune::P.new(0.1).value.should eq 0.1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "addition" do
|
18
|
+
it "p + p = 2p" do
|
19
|
+
(Fortune.P(0.1) + Fortune.P(0.2)).p.round(5).should eq Fortune.P(0.3).p.round(5)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "multiplication" do
|
24
|
+
it "p*p = p^2" do
|
25
|
+
(Fortune.P(0.1) * Fortune.P(0.2)).p.round(5).should eq Fortune.P(0.02).p.round(5)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "odds" do
|
30
|
+
it "calc odds for probability" do
|
31
|
+
Fortune.P(0.1).odds.should eq Fortune::Odds.new(:win => 1, :lose => 9)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "to_percent conversation" do
|
36
|
+
Fortune.P(0.1).to_percent.should eq 10
|
37
|
+
end
|
38
|
+
it "check event is happen" do
|
39
|
+
Fortune::P.is(1,10**10).should eq false
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "n" do
|
43
|
+
it "get random element from array" do
|
44
|
+
Fortune::P.n([1,1,1]).should eq 1
|
45
|
+
end
|
46
|
+
it "get random element from range" do
|
47
|
+
Fortune::P.n(100).should < 101
|
48
|
+
Fortune::P.n(100).should > 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fortune::Pn_repetition do
|
4
|
+
|
5
|
+
describe "calc" do
|
6
|
+
it "get Permutation with repetition value for 5 elements and 10 groups" do
|
7
|
+
Fortune::Pn_repetition.calc(:elements => 5, :groups => 10).should eq 100000
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fortune::Pn do
|
4
|
+
|
5
|
+
describe "calc" do
|
6
|
+
it "get Permutation value for 5 from 10" do
|
7
|
+
Fortune::Pn.calc(:elements => 10, :select => 5).should eq 30240
|
8
|
+
end
|
9
|
+
it "get Permutation value for 5" do
|
10
|
+
Fortune::Pn.calc(:elements => 5).should eq 120
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
data/spec/hash_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
|
5
|
+
describe "to_p" do
|
6
|
+
it "convert values to percent" do
|
7
|
+
{:a => 1, :b => 3}.to_p.should == {:a => 0.25, :b => 0.75}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "choose" do
|
12
|
+
it "select one element" do
|
13
|
+
[:a, :b].include?({:a => 1, :b => 3}.choose).should be_true
|
14
|
+
end
|
15
|
+
it "select by element weight" do
|
16
|
+
{:a => 1.0/10**5, :b => 1*10**10, :c => 1.0/10**10}.choose.should == :b
|
17
|
+
end
|
18
|
+
it "select one element by weight" do
|
19
|
+
{:a => 1, :b => 0, :c => 0}.choose.should == :a
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "choose_set" do
|
24
|
+
it "get one from set" do
|
25
|
+
[:a, :b, :c].include?({[:a, :b, :c] => 1, [:d] => 0}.choose_set).should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/math_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'fortune'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fortune
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Malykh Oleg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-13 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.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '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: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Ruby gem for calculate probability, odds and combinations. Mostly helpfull
|
56
|
+
for gambling, e.g. Poker.
|
57
|
+
email:
|
58
|
+
- malykholeg@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- .rspec
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- fortune.gemspec
|
71
|
+
- lib/fortune.rb
|
72
|
+
- lib/fortune/a.rb
|
73
|
+
- lib/fortune/c.rb
|
74
|
+
- lib/fortune/c_repetition.rb
|
75
|
+
- lib/fortune/event.rb
|
76
|
+
- lib/fortune/event_list.rb
|
77
|
+
- lib/fortune/odds.rb
|
78
|
+
- lib/fortune/p.rb
|
79
|
+
- lib/fortune/p_abstract.rb
|
80
|
+
- lib/fortune/pn.rb
|
81
|
+
- lib/fortune/pn_repetition.rb
|
82
|
+
- lib/fortune/version.rb
|
83
|
+
- spec/fortune/a_spec.rb
|
84
|
+
- spec/fortune/c_repetition_spec.rb
|
85
|
+
- spec/fortune/c_spec.rb
|
86
|
+
- spec/fortune/event_spec.rb
|
87
|
+
- spec/fortune/odds_spec.rb
|
88
|
+
- spec/fortune/p_spec.rb
|
89
|
+
- spec/fortune/pn_repetition_spec.rb
|
90
|
+
- spec/fortune/pn_spec.rb
|
91
|
+
- spec/fortune_spec.rb
|
92
|
+
- spec/hash_spec.rb
|
93
|
+
- spec/math_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
homepage: https://github.com/Fotom/Fortune
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 2.1.11
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: Lib for get changes, odds, probability and combinations for given values
|
119
|
+
test_files:
|
120
|
+
- spec/fortune/a_spec.rb
|
121
|
+
- spec/fortune/c_repetition_spec.rb
|
122
|
+
- spec/fortune/c_spec.rb
|
123
|
+
- spec/fortune/event_spec.rb
|
124
|
+
- spec/fortune/odds_spec.rb
|
125
|
+
- spec/fortune/p_spec.rb
|
126
|
+
- spec/fortune/pn_repetition_spec.rb
|
127
|
+
- spec/fortune/pn_spec.rb
|
128
|
+
- spec/fortune_spec.rb
|
129
|
+
- spec/hash_spec.rb
|
130
|
+
- spec/math_spec.rb
|
131
|
+
- spec/spec_helper.rb
|