FizzBuzz 問題
はやりものらしいのでやってみましたょ。
まず次の ruby のスクリプトを用意しまして。
#! /usr/bin/ruby
#
# Tape class
#
class Tape
def initialize()
@position = 0 # Current head position.
@tape = " "
end
# Move right.
def right()
@position += 1
if @position >= @tape.length then
@tape += " "
end
end
# Move left.
def left()
@position -= 1
if @position < 0 then
@tape = " " + @tape
@position = 0
end
end
# Read the symbol of current position.
def read()
@tape[@position, 1]
end
# Write a symbol to the current position.
def write(symbol)
@tape[@position] = symbol
end
# Print current tape and head status while running.
def print(state)
printf("{%s<%s)%s}\n",
@tape[0..@position],
state,
@tape[@position + 1..-1])
end
# Print the rusult.
def printResult()
puts "Result:"
puts @tape.strip()
end
end # class Tape
#
# Head class
#
class Head
#
# State class
#
class State
#
# Transaction class
#
class Transaction
def initialize(symbols, newSymbols, direction, newStateName)
@symbols = symbols
@newSymbols = newSymbols
@direction = direction
@newStateName = newStateName
end
def getSymbols()
@symbols
end
def newSymbol(symbol)
if @newSymbols.empty? then
# Empty new symbol means 'unchanged'.
return symbol
elsif @symbols.empty? then
# Empty symbols means 'don't care'.
return @newSymbols
else
return @newSymbols[@symbols.index(symbol), 1]
end
end
def direction()
@direction
end
def newStateName()
@newStateName
end
end # class Transaction
@@state = Hash.new(0)
def initialize(name)
# States of same name is not allowed.
if @@state[name] != 0 then
raise
end
@transaction = []
@@state[name] = self
end
def addTransaction(symbols, newSymbols, direction, newStateName)
@transaction.push(Transaction.new(symbols, newSymbols,
direction, newStateName))
end
def getTransaction(symbol)
for transaction in @transaction do
if transaction.getSymbols()[symbol] == symbol ||
transaction.getSymbols().empty? then
return transaction
end
end
raise "halt"
end
def direction(symbol)
getTransaction(symbol).direction()
end
def newSymbol(symbol)
getTransaction(symbol).newSymbol(symbol)
end
def newStateName(symbol)
getTransaction(symbol).newStateName()
end
def State.get(name)
@@state[name]
end
end # class State
def initialize()
@tape = Tape.new
@stateName = nil
load()
end
def load()
state = nil # Current state.
line = 0 # Line number.
while (gets)
line += 1
gsub!(/#.*$/, "") # Ignore remarks.
next if $_.strip!.empty? # Ignore empty line.
# New state.
gsub(/^\S+$/) { |name|
begin
state = State.new(name)
@stateName = name if @stateName == nil
rescue
raise "duplicate state at line " + line.to_s
end
""
}
# New transaction.
gsub(/^\[(.*)\]\s+\[(.*)\]\s+([LR])\s+(\S+)$/) { |m|
if state == nil then
raise "transaction before first state at line " + line.to_s
end
symbols = $1
newSymbols = $2
direction = $3
newStateName = $4
if symbols.empty? then
if newSymbols.length > 1
raise "when symbols is 'don't care', " +
"new symbols must be 'unchanged' or a single symbol" +
" at line " + line.to_s
end
elsif !newSymbols.empty? then
if symbols.length != newSymbols.length then
raise "symbol to new symbol map is unmatched at line " +
line.to_s
end
end
state.addTransaction(symbols, newSymbols, direction, newStateName)
""
}
raise "syntax error at line " + line.to_s unless $_.empty?
end
raise "no program" if @stateName == nil
end
def run()
begin
loop {
@tape.print(@stateName)
state = State.get(@stateName)
raise "halt" if state == 0
symbol = @tape.read()
newSymbol = state.newSymbol(symbol)
@tape.write(newSymbol)
direction = state.direction(symbol)
if direction == "L"
@tape.left()
elsif direction == "R"
@tape.right()
end
@stateName = state.newStateName(symbol)
sleep(0.2)
}
rescue RuntimeError
puts "HALT"
end
@tape.printResult()
end
end # class Head
begin
Head.new().run()
rescue => evar then
p $!
end
このスクリプトに、 次のデータを食わせますのです。
# Initialization.
INIT
[] [0] R INIT_1
INIT_1
[] [0] R INIT_2
INIT_2
[] [0] R INIT_3
INIT_3
[] [_] L DUPLAST
# Duplicate Last Number.
DUPLAST
[0123456789] [] L DUPLAST
[ ] [] R DUPLAST_COPY
DUPLAST_COPY
[ABCDEFGHIJ] [] R DUPLAST_COPY
[0] [A] R DUPLAST_H0
[1] [B] R DUPLAST_H1
[2] [C] R DUPLAST_H2
[3] [D] R DUPLAST_H3
[4] [E] R DUPLAST_H4
[5] [F] R DUPLAST_H5
[6] [G] R DUPLAST_H6
[7] [H] R DUPLAST_H7
[8] [I] R DUPLAST_H8
[9] [J] R DUPLAST_H9
[_] [] L DUPLAST_CLEAN_0
[a] [] L FIZZ
[b] [] L BUZZ
[c] [] L FIZZBUZZ
DUPLAST_CLEAN_0
[ ] [] R DUPLAST_CLEAN_1
[] [] L DUPLAST_CLEAN_0
DUPLAST_CLEAN_1
[ABCDEFGHIJ] [0123456789] R DUPLAST_CLEAN_1
[_] [ ] R DUPLAST_CLEAN_2
[] [] R DUPLAST_CLEAN_1
DUPLAST_CLEAN_2
[ ] [] L INCLAST
[] [] R DUPLAST_CLEAN_2
DUPLAST_H0
[ ] [0] R DUPLAST_NEXT
[] [] R DUPLAST_H0
DUPLAST_H1
[ ] [1] R DUPLAST_NEXT
[] [] R DUPLAST_H1
DUPLAST_H2
[ ] [2] R DUPLAST_NEXT
[] [] R DUPLAST_H2
DUPLAST_H3
[ ] [3] R DUPLAST_NEXT
[] [] R DUPLAST_H3
DUPLAST_H4
[ ] [4] R DUPLAST_NEXT
[] [] R DUPLAST_H4
DUPLAST_H5
[ ] [5] R DUPLAST_NEXT
[] [] R DUPLAST_H5
DUPLAST_H6
[ ] [6] R DUPLAST_NEXT
[] [] R DUPLAST_H6
DUPLAST_H7
[ ] [7] R DUPLAST_NEXT
[] [] R DUPLAST_H7
DUPLAST_H8
[ ] [8] R DUPLAST_NEXT
[] [] R DUPLAST_H8
DUPLAST_H9
[ ] [9] R DUPLAST_NEXT
[] [] R DUPLAST_H9
DUPLAST_NEXT
[ABCDEFGHIJ] [] R DUPLAST_COPY
[] [] L DUPLAST_NEXT
# Increment Last Number.
INCLAST
[012345678] [123456789] R INCLAST_FIN
[9] [0] L INCLAST
INCLAST_FIN
[ ] [] L CHECKTERM
[] [] R INCLAST_FIN
# Check Termination.
CHECKTERM
[1] [] L CHECKTERM_1
[] [] R CHECKTERM_FAIL
CHECKTERM_1
[0] [] L CHECKTERM_2
[] [] R CHECKTERM_FAIL
CHECKTERM_2
[1] [] R TERM
[] [] R CHECKTERM_FAIL
CHECKTERM_FAIL
[ ] [] L CHECKMUL3
[] [] R CHECKTERM_FAIL
# Check Multiply of 3.
CHECKMUL3
[0369] [] L CHECKMUL3
[147] [] L CHECKMUL3_1
[258] [] L CHECKMUL3_2
[ ] [] R MUL3_SUCC
CHECKMUL3_1
[0369] [] L CHECKMUL3_1
[147] [] L CHECKMUL3_2
[258] [] L CHECKMUL3
[ ] [] R MUL3_FAIL
CHECKMUL3_2
[0369] [] L CHECKMUL3_2
[147] [] L CHECKMUL3
[258] [] L CHECKMUL3_1
[ ] [] R MUL3_FAIL
MUL3_SUCC
[ ] [] L CHECKMUL35
[] [] R MUL3_SUCC
MUL3_FAIL
[ ] [] L CHECKMUL5
[] [] R MUL3_FAIL
# Check Multiply of 3 and 5.
CHECKMUL35
[05] [] R MUL35_SUCC
[] [] R MUL35_FAIL
MUL35_FAIL
[ ] [a] R MUL35_FAIL_1
MUL35_FAIL_1
[] [a] L MUL35_FAIL_2
MUL35_FAIL_2
[] [] L DUPLAST
MUL35_SUCC
[ ] [c] R MUL35_SUCC_1
MUL35_SUCC_1
[] [c] R MUL35_SUCC_2
MUL35_SUCC_2
[] [c] R MUL35_SUCC_3
MUL35_SUCC_3
[] [c] R MUL35_SUCC_4
MUL35_SUCC_4
[] [c] R MUL35_SUCC_5
MUL35_SUCC_5
[] [c] L MUL35_SUCC_6
MUL35_SUCC_6
[c] [] L MUL35_SUCC_6
[] [] L DUPLAST
# Fizz.
FIZZ
[ ] [] R FIZZ_0
[] [] L FIZZ
FIZZ_0
[] [F] R FIZZ_1
FIZZ_1
[] [i] R FIZZ_2
FIZZ_2
[] [z] R FIZZ_3
FIZZ_3
[] [z] R FIZZ_FIN
FIZZ_FIN
[ ] [] L INCLAST
[a] [ ] R FIZZ_FIN
[] [] R FIZZ_FIN
# Check Multiply of 5.
CHECKMUL5
[05] [] R MUL5_SUCC
[] [] R MUL5_FAIL
MUL5_FAIL
[ ] [_] L DUPLAST
MUL5_SUCC
[ ] [b] R MUL5_SUCC_1
MUL5_SUCC_1
[] [b] L MUL5_SUCC_2
MUL5_SUCC_2
[] [] L DUPLAST
# Buzz.
BUZZ
[ ] [] R BUZZ_0
[] [] L BUZZ
BUZZ_0
[] [B] R BUZZ_1
BUZZ_1
[] [u] R BUZZ_2
BUZZ_2
[] [z] R BUZZ_3
BUZZ_3
[] [z] R BUZZ_FIN
BUZZ_FIN
[ ] [] L INCLAST
[b] [ ] R BUZZ_FIN
[] [] R BUZZ_FIN
# FizzBuzz.
FIZZBUZZ
[ ] [] R FIZZBUZZ_0
[] [] L FIZZBUZZ
FIZZBUZZ_0
[] [F] R FIZZBUZZ_1
FIZZBUZZ_1
[] [i] R FIZZBUZZ_2
FIZZBUZZ_2
[] [z] R FIZZBUZZ_3
FIZZBUZZ_3
[] [z] R FIZZBUZZ_4
FIZZBUZZ_4
[] [B] R FIZZBUZZ_5
FIZZBUZZ_5
[] [u] R FIZZBUZZ_6
FIZZBUZZ_6
[] [z] R FIZZBUZZ_7
FIZZBUZZ_7
[] [z] R FIZZBUZZ_FIN
FIZZBUZZ_FIN
[ ] [] L INCLAST
[c] [ ] R FIZZBUZZ_FIN
[] [] R FIZZBUZZ_FIN
# Terminating...
TERM
[ ] [] L ERASE101
[] [] R TERM
# Erase 101.
ERASE101
[ ] [] L SEEK_TOP
[] [ ] L ERASE101
# Seek Top.
SEEK_TOP
[ ] [] L SEEK_TOP_1
[] [] L SEEK_TOP
SEEK_TOP_1
[ ] [] R ERASE_LEAD0
[] [] L SEEK_TOP
# Erase Leading 0
ERASE_LEAD0
[0] [ ] R ERASE_LEAD0
[ ] [] R ERASE_LEAD0_TERM
[] [] R ERASE_LEAD0_SKIP
ERASE_LEAD0_SKIP
[ ] [] R ERASE_LEAD0
[] [] R ERASE_LEAD0_SKIP
ERASE_LEAD0_TERM
[ ] [] R HALT
[0] [ ] R ERASE_LEAD0
[] [] R ERASE_LEAD0
# Halt.
HALT
いぢょ。
FizzBuzz 問題 More ログイン