-
Notifications
You must be signed in to change notification settings - Fork 0
/
sync-word-tool.rb
79 lines (66 loc) · 2.14 KB
/
sync-word-tool.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
require 'io/console'
def right_multiline(width, left, rights)
left_width = left.size
lines = [left]
rights.each do |right|
lines << " " * left_width if lines.last.size + right.size + 1 >= width
lines[-1] += " " + right
end
lines.join "\n"
end
alphabet = [*"A" .. "Z"]
edges = [gets.chomp, gets.chomp]
.map{|line| line.chars.map{|c|alphabet.index c}}
.transpose
out = []
keymap = "." + "-" * (edges.count - 1)
collisions = []
loop.with_index do |_, i|
out << right_multiline(IO.console.winsize[1],
"%2d %s /" % [i, keymap],
collisions.map{|c|c.join("-")})
break if /^\.*$/ === keymap
prev_keymap = keymap
prev_collisions = collisions
key_pairs = edges.map{|es| es.map{|e| keymap[e]}}
#assign keys to pairs of previous keys
pair_keys = Hash.new{|h,k| h[k] = ""}
keymap = key_pairs.zip(alphabet).map{|pair, a|
case
when pair == ["-", "-"]
"-"
else
pair_keys[pair] += a; a
end
}.join
#determine which pairs of new keys collide
collisions = pair_keys.keys.combination(2).map{|pair_pair|
pair_pair.map(&pair_keys) if pair_pair.transpose.all?{|nk1, nk2|
nk1 == "-" || nk2 == "-" || prev_collisions.any?{|pc1, pc2|
(pc1.include?(nk1) && pc2.include?(nk2)) || (pc1.include?(nk2) && pc2.include?(nk1))
}
}
}.compact
# combine keys with the same collision sets
# pair_keys.values.combination(2).each do |nk1, nk2|
# k1c = collisions.select{|c| c.include? nk1}.map{|c| c - [nk1]}
# k2c = collisions.select{|c| c.include? nk2}.map{|c| c - [nk2]}
# next unless k1c == k2c
# keymap.tr!(nk2, nk1)
# collisions.reject! {|c| c.include? nk2}
# end
pair_keys.values.each do |nk|
keymap.tr!(nk, ".") unless collisions.any?{|c| c.include? nk}
end
# compress the list of collisions
loop do
c1, c2 = collisions.combination(2).find {|c1, c2| (c1 & c2).one?}
break unless c1
collisions.delete c1
collisions.delete c2
new_keys = (c1 - c2)[0] + (c2 - c1)[0]
collisions.push [(c1 & c2)[0], new_keys.chars.sort.join].sort
end
collisions.sort!
end
puts "", out