-
Notifications
You must be signed in to change notification settings - Fork 1
/
10_syntax_scoring.rb
50 lines (44 loc) · 1.14 KB
/
10_syntax_scoring.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
OPEN_MATCHING_CLOSE = {
?) => ?(,
?] => ?[,
?} => ?{,
?> => ?<,
}.each_value(&:freeze).freeze
ERR_SCORE = {
?) => 3,
?] => 57,
?} => 1197,
?> => 25137,
}.freeze
COMP_SCORE = {
?( => 1,
?[ => 2,
?{ => 3,
?< => 4,
}.freeze
def completion(opens)
opens.reverse_each.reduce(0) { |a, c| a * 5 + COMP_SCORE.fetch(c) }
end
err = ERR_SCORE.transform_values { 0 }
comp = []
verbose2 = ARGV.delete('-vv')
verbose = verbose2 || ARGV.delete('-v')
ARGF.each_line(chomp: true).with_index { |line, i|
opens = []
next unless line.each_char.with_index { |c, j|
if COMP_SCORE.has_key?(c)
opens << c
elsif opens.pop != OPEN_MATCHING_CLOSE.fetch(c)
puts "#{i}: \e[1;31mcorrupt\e[0m @ #{j} #{c} #{line[0...j]}\e[1;31m#{c}\e[0m#{line[(j + 1)..-1]}" if verbose2
err[c] += 1
break
end
}
comp << score = completion(opens)
puts "#{i}: \e[1;32mincomplete\e[0m #{opens.join} = #{score}" if verbose2
}
puts err if verbose
puts err.sum { |c, freq| ERR_SCORE.fetch(c) * freq }
raise "even-sized comp #{comp.size} #{comp}" if comp.size.even?
puts "#{comp.size / 2} of #{comp.sort}" if verbose
puts comp.sort[comp.size / 2]