問題
xxxx=yyyy という形式のデータをたくさん受け取り、等しいもの同士をグルーピングするプログラムを書いてください。
Rubyで同値関係を求めるパズル - rubyco(るびこ)の日記
Set を使って書いてみました。なお、入力は in.txt なるテキストファイルからとし、出力形式は端折ってしまっています。
| in pairs sets line | in := FileStream fileNamed: 'in.txt'. pairs := OrderedCollection new. [(line := in nextLine) notNil] whileTrue: [pairs add: (line subStrings: '=')]. in close. sets := OrderedCollection new. pairs do: [:pair | | found | found := sets detect: [:set | pair anySatisfy: [:elem | set includes: elem]] ifNone: [sets add: Set new]. found addAll: pair]. World findATranscript: nil. sets do: [:each | Transcript cr; show: each asArray sort]
in.txt
b=d A=B b=a B=C c=b D=A
出力
#('a' 'b' 'c' 'd') #('A' 'B' 'C' 'D')
Ruby に直訳。
require "set" pairs = Array.new while line = ARGF.gets pairs << line.chomp!.split(/=/) end sets = Array.new pairs.each{ |pair| found = sets.detect(proc{(sets << Set.new).last}){ |set| pair.any?{ |elem| set.include?(elem) } } pair.each{ |elem| found << elem } } sets.each{ |each| p each.to_a.sort }
出力
["a", "b", "c", "d"] ["A", "B", "C", "D"]
追記
コメント欄にて id:ykoubo さんに教えて頂いたことをうけて修正いたしました。
| in pairs sets line | in := FileStream fileNamed: 'in.txt'. pairs := OrderedCollection new. [(line := in nextLine) notNil] whileTrue: [pairs add: (line subStrings: '=')]. in close. sets := OrderedCollection new. pairs do: [:pair | | founds marged | founds := sets select: [:set | pair anySatisfy: [:elem | set includes: elem]]. sets removeAll: founds. sets add: pair asSet, founds concatenation]. World findATranscript: nil. sets do: [:each | Transcript cr; show: each asArray sort]
in.txt
a=c b=d A=B b=a B=C c=b D=A
出力
#('a' 'b' 'c' 'd') #('A' 'B' 'C' 'D')
Ruby 版もあわせて修正。
require "set" pairs = Array.new while line = ARGF.gets pairs << line.chomp!.split(/=/) end sets = Array.new pairs.each{ |pair| founds = sets.select{ |set| pair.any?{ |elem| set.include?(elem) } } sets -= founds sets << founds.inject(Set[*pair]){ |r,s| r+s } } sets.each{ |each| p each.to_a.sort }