Module: AtCoderFriends::Parser::Modulo

Defined in:
lib/at_coder_friends/parser/modulo.rb

Overview

parses problem page and extract modulo values

Constant Summary collapse

SECTIONS =

rubocop:disable Style/AsciiComments

[
  Problem::SECTION_OUT_FMT,
  Problem::SECTION_STATEMENT,
  Problem::SECTION_TASK,
  Problem::SECTION_INTRO
].freeze
VALUE_PATTERN =

(998244353) 十億九

%r{
  (?:
    <var>([^<>]+)</var>
    |\\\(([^()]+)\\\)
    |\$([^$]+)\$
    |\{([^{}]+)\}
    |([\d,^+]+)
    |([一二三四五六七八九十百千万億]+)
  )
}x.freeze
MOD_PATTERN =

<var>1,000,000,007</var> (素数)で割った余り

/
  (?:
    #{VALUE_PATTERN}\s*(?:\([^()]+\)\s*)?で割った(?:剰余|余り|あまり)
    |(?:modulo|mod|divided\s*by|dividing\s*by)\s*#{VALUE_PATTERN}
  )
/xi.freeze

Class Method Summary collapse

Class Method Details

.normalize_content(s) ⇒ Object



58
59
60
61
62
63
64
65
66
67
# File 'lib/at_coder_friends/parser/modulo.rb', line 58

def normalize_content(s)
  s
    .tr('0-9A-Za-z', '0-9A-Za-z')
    .gsub(/[[:space:]]/, ' ')
    .gsub(%r{[^一-龠_ぁ-ん_ァ-ヶーa-zA-Z0-9 -/:-@\[-`\{-~]}, '')
    .gsub(/{\\rm\s*mod\s*}\\?/i, 'mod') # {\rm mod} -> mod
    .gsub(/\\rm\s*{\s*mod\s*}\\?/i, 'mod') # \rm{mod}\ -> mod
    .gsub(/\\mbox\s*{\s*mod\s*}/i, 'mod') # \mbox{mod} -> mod
    .gsub(%r{<var>\s*mod\s*</var>}i, 'mod') # <var>mod</var> -> mod
end

.normalize_value(s) ⇒ Object



69
70
71
72
73
# File 'lib/at_coder_friends/parser/modulo.rb', line 69

def normalize_value(s)
  s
    .gsub(/\A([^(=]+)[(=].*\z/, '\1') # 1000000007 (10^9+7), ... =10^9+7
    .gsub(/[{}()=\\ ]/, '')
end

.parse(str) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/at_coder_friends/parser/modulo.rb', line 47

def parse(str)
  str = normalize_content(str)
  str
    .scan(MOD_PATTERN)
    .map(&:compact)
    .map { |(v)| normalize_value(v) }
    .reject(&:empty?)
    .uniq
    .map { |v| Problem::Constant.new('mod', :mod, v) }
end

.process(pbm) ⇒ Object

rubocop:enable Style/AsciiComments



37
38
39
40
41
42
43
44
45
# File 'lib/at_coder_friends/parser/modulo.rb', line 37

def process(pbm)
  mods = []
  SECTIONS.any? do |section|
    next unless (html = pbm.sections[section]&.html)

    !(mods = parse(html)).empty?
  end
  pbm.constants += mods
end