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 ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in shadchan.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/lib/shadchan.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Shadchan
2
+ libdir = File.join(File.dirname(File.expand_path(__FILE__)), self.name.downcase, '')
3
+ require libdir + 'shadchan.rb' # Your code goes here...
4
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Shadchan
2
+ VERSION = "0.0.1"
3
+ 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
+