パスワードを忘れた? アカウント作成
494348 journal

FizzBuzz 問題

日記 by etsav

はやりものらしいのでやってみましたょ。

まず次の 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

いぢょ。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

※ただしPHPを除く -- あるAdmin

読み込み中...