結果
| 問題 | No.677 10^Nの約数 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2018-09-26 00:17:57 |
| 言語 | Ruby (3.4.1) |
| 結果 |
AC
|
| 実行時間 | 317 ms / 2,000 ms |
| コード長 | 12,155 bytes |
| 記録 | |
| コンパイル時間 | 366 ms |
| コンパイル使用メモリ | 7,680 KB |
| 実行使用メモリ | 15,488 KB |
| 最終ジャッジ日時 | 2024-10-07 05:59:37 |
| 合計ジャッジ時間 | 4,136 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 17 |
コンパイルメッセージ
Syntax OK
ソースコード
require 'stringio'
module WhitespaceCompiler
class WhitespaceParseError < RuntimeError
def initialize(io)
end
end
def readchar(io, eof = false)
loop do
if io.eof?
return :eof if eof
raise WhitespaceParseError.new(io)
end
c = io.readbyte
return :sp if c == 32 # 83
return :tb if c == 9 # 84
return :lf if c == 10 # 76
end
end
def parse_int(io)
sign = 0
val = 0
loop do
c = readchar(io)
if c == :lf
raise WhitespaceParseError.new(io) if sign == 0
return sign*val
end
if sign == 0
sign = c == :tb ? -1 : 1
else
val = (val << 1)
val |= 1 if c == :tb
end
end
end
def parse_instruction(io)
c1 = readchar(io, true)
return nil if c1 == :eof
if c1 == :sp
c2 = readchar(io)
return [:stk_push, parse_int(io)] if c2 == :sp
if c2 == :lf
c3 = readchar(io)
return [:stk_dup] if c3 == :sp
return [:stk_swap] if c3 == :tb
return [:stk_del] if c3 == :lf
end
elsif c1 == :lf
c2 = readchar(io)
c3 = readchar(io)
return [:flw_label, parse_int(io)] if c2 == :sp && c3 == :sp
return [:flw_call, parse_int(io)] if c2 == :sp && c3 == :tb
return [:flw_jump, parse_int(io)] if c2 == :sp && c3 == :lf
return [:flw_jumpz, parse_int(io)] if c2 == :tb && c3 == :sp
return [:flw_jumpn, parse_int(io)] if c2 == :tb && c3 == :tb
return [:flw_ret] if c2 == :tb && c3 == :lf
return [:flw_exit] if c2 == :lf && c3 == :lf
elsif c1 == :tb
c2 = readchar(io)
if c2 == :sp
c3 = readchar(io)
c4 = readchar(io)
return [:art_add] if c3 == :sp && c4 == :sp
return [:art_sub] if c3 == :sp && c4 == :tb
return [:art_mul] if c3 == :sp && c4 == :lf
return [:art_div] if c3 == :tb && c4 == :sp
return [:art_mod] if c3 == :tb && c4 == :tb
elsif c2 == :tb
c3 = readchar(io)
return [:hep_store] if c3 == :sp
return [:hep_ret] if c3 == :tb
elsif c2 == :lf
c3 = readchar(io)
c4 = readchar(io)
return [:iop_outc] if c3 == :sp && c4 == :sp
return [:iop_outn] if c3 == :sp && c4 == :tb
return [:iop_readc] if c3 == :tb && c4 == :sp
return [:iop_readn] if c3 == :tb && c4 == :tb
end
end
raise WhitespaceParseError.new(io)
end
def parse(io)
extend WhitespaceCompiler
io = StringIO.new(io, 'r') if io.is_a? String
label = {}
code = []
loop do
inst = parse_instruction(io)
break if inst.nil?
code += inst
label[inst[1]] = code.size-2 if inst[0] == :flw_label
end
return [code, label]
end
module_function :parse
end
class WhitespaceInterpreter
class WhitespaceRuntimeError < RuntimeError
def initialize(wip = '')
if wip.is_a? WhitespaceInterpreter
@wip = wip
msg = "[pc=%d, stack.size=%d, callstack.size=%d]"%[wip.pc, wip.stack.size, wip.callstack.size]
super msg
else
super
end
end
end
def initialize(code, label, stdinio)
@code = code
@label = label
self.stdin = stdinio
reset()
end
attr_reader :stdin, :stdout, :pc, :halt, :stack, :heap, :callstack
def stdin=(s)
s = StringIO.new(s, 'r') if s.is_a? String
@stdin = s
end
def reset
@pc = 0
@halt = false
@stack = []
@heap = []
@callstack = []
@stdout = ''
self
end
def step
return false if @halt
unless 0 <= @pc && @pc < @code.size
raise WhitespaceRuntimeError.new(self)
end
#p [@code[@pc], @code[@pc+1], @stack, @callstack]
#abort if @callstack.size >= 4
self.send(@code[@pc], @code[@pc+1])
@pc += 1
true
end
def run
while step
end
self
end
def getchar
@stdin.eof? ? -1 : @stdin.readbyte
end
def getint
a = @stdin.gets
a ? a.to_i : 0
end
def stk_push(val)
@stack.push(val)
@pc += 1
end
def stk_dup(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@stack.push(@stack[-1])
end
def stk_swap(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
@stack[-1], @stack[-2] = @stack[-2], @stack[-1]
end
def stk_del(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@stack.pop()
end
def flw_label(label)
# ignore
@pc += 1
end
def flw_call(label)
pc = @label[label]
raise WhitespaceRuntimeError.new(self) if pc.nil?
@callstack.push(@pc+1)
@pc = pc+1
end
def flw_jump(label)
pc = @label[label]
raise WhitespaceRuntimeError.new(self) if pc.nil?
@pc = pc+1
end
def flw_jumpz(label)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@pc += 1
flw_jump(label) if @stack.pop() == 0
end
def flw_jumpn(label)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@pc += 1
flw_jump(label) if @stack.pop() < 0
end
def flw_ret(_)
raise WhitespaceRuntimeError.new(self) if @callstack.size < 1
@pc = @callstack.pop
end
def flw_exit(_)
@halt = true
end
def art_add(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
a, b = @stack.pop(2)
@stack.push(a + b)
end
def art_sub(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
a, b = @stack.pop(2)
@stack.push(a - b)
end
def art_mul(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
a, b = @stack.pop(2)
@stack.push(a * b)
end
def art_div(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
a, b = @stack.pop(2)
@stack.push(a / b)
end
def art_mod(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
a, b = @stack.pop(2)
@stack.push(a % b)
end
def hep_store(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 2
adr, val = @stack.pop(2)
@heap[adr] = val
end
def hep_ret(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
adr = @stack.pop
raise WhitespaceRuntimeError.new(self) if @heap[adr].nil?
@stack.push(@heap[adr])
end
def iop_outc(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@stdout << ("%c"%(@stack.pop))
end
def iop_outn(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
@stdout << @stack.pop.to_s
end
def iop_readc(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
adr = @stack.pop
@heap[adr] = getchar()
end
def iop_readn(_)
raise WhitespaceRuntimeError.new(self) if @stack.size < 1
adr = @stack.pop
@heap[adr] = getint()
end
end
code, label = WhitespaceCompiler.parse("
")
ip = WhitespaceInterpreter.new(code, label, STDIN.read)
ip.run
print ip.stdout