shadchan 0.0.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/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/lib/shadchan.rb +4 -0
- data/lib/shadchan/shadchan.rb +131 -0
- data/lib/shadchan/version.rb +3 -0
- data/shadchan.gemspec +21 -0
- metadata +74 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/lib/shadchan.rb
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
module Shadchan
|
|
2
|
+
class Shadchan
|
|
3
|
+
=begin rdoc
|
|
4
|
+
Create a new instance of stable marriage problem.
|
|
5
|
+
Instance will be imediately solved and object can be queried for results.
|
|
6
|
+
|
|
7
|
+
parameters - preference lists.
|
|
8
|
+
accepts arrays of preferences ('women' first), which contain integers. Length
|
|
9
|
+
of preference list must correspond with their number.
|
|
10
|
+
There must be equal number of men and women and lists must be valid.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
Shadchan.new [0, 1], [1, 0], [0, 1], [0, 1]
|
|
14
|
+
|
|
15
|
+
Woman no.0 prefers Man 0 before Man 1.
|
|
16
|
+
Woman no.1 prefers Man 1 before Man 0.
|
|
17
|
+
Man no.0 prefers Woman 0 before Woman 1.
|
|
18
|
+
Man no.1 prefers Woman 0 before Woman 1.
|
|
19
|
+
=end
|
|
20
|
+
def initialize *args
|
|
21
|
+
check_input args
|
|
22
|
+
@women = args.shift(args.size/2)
|
|
23
|
+
@men = args
|
|
24
|
+
@size = @men.size
|
|
25
|
+
stable_matching
|
|
26
|
+
raise(StandardError, 'Found solution not stable') unless check_solution
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
=begin rdoc
|
|
30
|
+
Returns matched pairs [woman, man].
|
|
31
|
+
=end
|
|
32
|
+
def match
|
|
33
|
+
result = []
|
|
34
|
+
@matches.each_with_index do |m, w|
|
|
35
|
+
result << [w, m]
|
|
36
|
+
end
|
|
37
|
+
return result
|
|
38
|
+
end
|
|
39
|
+
=begin rdoc
|
|
40
|
+
Returns matches for men
|
|
41
|
+
Match of man 0 -
|
|
42
|
+
s.match_men[0]
|
|
43
|
+
=end
|
|
44
|
+
def match_men
|
|
45
|
+
result = match
|
|
46
|
+
match.sort_by(&:last).map(&:first)
|
|
47
|
+
end
|
|
48
|
+
=begin rdoc
|
|
49
|
+
Returnes matches for women
|
|
50
|
+
Match of woman 0 -
|
|
51
|
+
s.match_men[0]
|
|
52
|
+
=end
|
|
53
|
+
def match_women
|
|
54
|
+
@matches.dup
|
|
55
|
+
end
|
|
56
|
+
private
|
|
57
|
+
def stable_matching
|
|
58
|
+
men_preferences = @men.map(&:dup)
|
|
59
|
+
matches = Array.new(@size)
|
|
60
|
+
while m = free_man_proposable(men_preferences, matches, @size)
|
|
61
|
+
w = men_preferences[m].shift
|
|
62
|
+
unless matches[w] then
|
|
63
|
+
matches[w] = m
|
|
64
|
+
next
|
|
65
|
+
end
|
|
66
|
+
if @women[w].find_index(m) < @women[w].find_index(matches[w]) then
|
|
67
|
+
# if the men is better match then current match
|
|
68
|
+
matches[w] = m
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
@matches = matches
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def free_man_proposable m, matches, size
|
|
75
|
+
@size.times do |i|
|
|
76
|
+
free = !matches.include?(i)
|
|
77
|
+
proposable = !m[i].empty?
|
|
78
|
+
if free and proposable then
|
|
79
|
+
return i
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
return nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
=begin rdoc
|
|
86
|
+
Checks argument if they are valid SM problem.
|
|
87
|
+
It should not be empty.
|
|
88
|
+
It should have equal number of men and women
|
|
89
|
+
It should state preference for all women and for all men.
|
|
90
|
+
It should not state preference twice for one men/women.
|
|
91
|
+
=end
|
|
92
|
+
def check_input args
|
|
93
|
+
raise ArgumentError, 'No arguments given' if args.empty?
|
|
94
|
+
size = args.first.size
|
|
95
|
+
|
|
96
|
+
unless args.all?{|w| w.size == size} then
|
|
97
|
+
raise ArgumentError, 'Incorrectly specified input - inconsistent preference list size. Check your input.'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
unless args.size == size*2 then
|
|
101
|
+
raise ArgumentError, 'Incorrect number of men or women. Check your input.'
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
args.each do |w|
|
|
105
|
+
size.times do |i|
|
|
106
|
+
raise ArgumentError, 'Error in input - it must be 0..number of men' unless w.include? i
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
=begin rdoc
|
|
113
|
+
Checks if the found solution is valid. It should always be, but better safe then sorry.
|
|
114
|
+
Tries to find blocking pairs (m, w), (m', w') such that
|
|
115
|
+
w' >m w AND m >w' m'
|
|
116
|
+
=end
|
|
117
|
+
def check_solution
|
|
118
|
+
@matches.each_with_index do |m, w|
|
|
119
|
+
#check woman
|
|
120
|
+
w_better_candidates = @women[w].take(@women[w].find_index(m))
|
|
121
|
+
# all these are prefered over current spouse. If they prefer her over their current spouse, matching is not stable.
|
|
122
|
+
w_better_candidates.each do |better_man|
|
|
123
|
+
spouse = @matches.find_index(better_man)
|
|
124
|
+
m_better_spouses = @men[better_man].take(@men[better_man].find_index(spouse))
|
|
125
|
+
return false if m_better_spouses.include? w
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
true
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
data/shadchan.gemspec
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "shadchan/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "shadchan"
|
|
7
|
+
s.version = Shadchan::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Vojtech Salbaba"]
|
|
10
|
+
s.email = ["darktatka@gmail.com"]
|
|
11
|
+
s.homepage = ""
|
|
12
|
+
s.summary = %q{Solves a stable marriage problem}
|
|
13
|
+
s.description = %q{Solves a stable marriage problem}
|
|
14
|
+
|
|
15
|
+
s.rubyforge_project = "shadchan"
|
|
16
|
+
|
|
17
|
+
s.files = `git ls-files`.split("\n")
|
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
+
s.require_paths = ["lib"]
|
|
21
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: shadchan
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 29
|
|
5
|
+
prerelease: false
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 0
|
|
9
|
+
- 1
|
|
10
|
+
version: 0.0.1
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Vojtech Salbaba
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-01-15 00:00:00 +01:00
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies: []
|
|
21
|
+
|
|
22
|
+
description: Solves a stable marriage problem
|
|
23
|
+
email:
|
|
24
|
+
- darktatka@gmail.com
|
|
25
|
+
executables: []
|
|
26
|
+
|
|
27
|
+
extensions: []
|
|
28
|
+
|
|
29
|
+
extra_rdoc_files: []
|
|
30
|
+
|
|
31
|
+
files:
|
|
32
|
+
- .gitignore
|
|
33
|
+
- Gemfile
|
|
34
|
+
- Rakefile
|
|
35
|
+
- lib/shadchan.rb
|
|
36
|
+
- lib/shadchan/shadchan.rb
|
|
37
|
+
- lib/shadchan/version.rb
|
|
38
|
+
- shadchan.gemspec
|
|
39
|
+
has_rdoc: true
|
|
40
|
+
homepage: ""
|
|
41
|
+
licenses: []
|
|
42
|
+
|
|
43
|
+
post_install_message:
|
|
44
|
+
rdoc_options: []
|
|
45
|
+
|
|
46
|
+
require_paths:
|
|
47
|
+
- lib
|
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
hash: 3
|
|
54
|
+
segments:
|
|
55
|
+
- 0
|
|
56
|
+
version: "0"
|
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
|
+
none: false
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
hash: 3
|
|
63
|
+
segments:
|
|
64
|
+
- 0
|
|
65
|
+
version: "0"
|
|
66
|
+
requirements: []
|
|
67
|
+
|
|
68
|
+
rubyforge_project: shadchan
|
|
69
|
+
rubygems_version: 1.3.7
|
|
70
|
+
signing_key:
|
|
71
|
+
specification_version: 3
|
|
72
|
+
summary: Solves a stable marriage problem
|
|
73
|
+
test_files: []
|
|
74
|
+
|