Class: BrainfuckConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/brainfuck_converter.rb

Overview

Class, which includes a function to convert text into Brainfuck code. Furthermore, it is possible to change the character set used in Brainfuck.

Constant Summary collapse

DEFAULT_COMMANDS =
{
  inc_val: '+',
  dec_val: '-',
  inc_ptr: '>',
  dec_ptr: '<',
  output: '.',
  loop_begin: '[',
  loop_end: ']'
}.freeze
ASCII_MAX =
127

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bf_cmds = DEFAULT_COMMANDS) ⇒ BrainfuckConverter

Initializes a new Brainfuck Converter

Parameters:

  • bf_cmds (Hash) (defaults to: DEFAULT_COMMANDS)

    Command sign. If not specified, the default command set under BrainfuckConverter::DEFAULT_COMMANDS will be used.



23
24
25
# File 'lib/brainfuck_converter.rb', line 23

def initialize(bf_cmds = DEFAULT_COMMANDS)
  @cmds = bf_cmds
end

Instance Attribute Details

#cmdsObject

Returns the value of attribute cmds.



17
18
19
# File 'lib/brainfuck_converter.rb', line 17

def cmds
  @cmds
end

#codeObject (readonly)

Returns the value of attribute code.



16
17
18
# File 'lib/brainfuck_converter.rb', line 16

def code
  @code
end

Instance Method Details

#convert(text, cells_num = 8) ⇒ String, FalseClass

Converts an ASCII string to Brainfuck code.

Examples:

require 'brainfuck_converter'

con = BrainfuckConverter.new

con.convert 'Hello World!'  # => 'Hello World!'
con.code  # => "++++++++++++++[>+>++>+++>++++>+++++>++++++>++++++... too long"

con.convert 'Hallo Welt!', 15  # => 'Hallo Welt!'
con.code  # => "+++++++[>+>++>+++>++++>+++++>++++++>+++++++>+++++... too long"

Parameters:

  • text (String)

    The text to be converted into Brainfuck code.

  • cells_num (Integer) (defaults to: 8)

    Number of cells to be used. All values from 0 can be used. If not specified, 8 cells are used. Regardless of the number specified here, an additional cell is used.

Returns:

  • (String, FalseClass)

Raises:

  • (ArgumentError)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/brainfuck_converter.rb', line 44

def convert(text, cells_num = 8)
  # To output a string in Brainfuck, "auxiliary numbers" are written into
  # certain cells. If a letter is to be output, the letter is converted into
  # an ASCII value and the auxiliary number that is closest to it is searched for.
  # This is then adjusted so that it corresponds to the ASCII value of the letter.
  # The auxiliary number or the letter is then output.

  raise ArgumentError, 'Text must be a string' unless text.is_a? String
  raise ArgumentError, 'Number of cells must be a integer' unless cells_num.is_a? Integer
  raise ArgumentError, 'Number of cells must be larger than 0' if cells_num < 1
  raise ArgumentError, "Number of cells must be smaller than #{ASCII_MAX}" if cells_num > ASCII_MAX

  # Code is cleared. A new Brainfuck program is started.
  @code = ''

  # Calculating the auxiliary numbers
  space_cells = ASCII_MAX / (cells_num + 1)
  @cell_values = []
  @cell_values[0] = space_cells
  for i in 1...cells_num
    @cell_values[i] = @cell_values[i - 1] + space_cells
  end

  # The code to create the auxiliary numbers in the cells is created.
  # The auxiliary numbers are created by multiplication.
  # This also has the advantage that you can use a loop.
  @code += @cmds[:inc_val] * space_cells
  @code += @cmds[:loop_begin]
  for i in 1..cells_num
    @code += @cmds[:inc_ptr]
    @code += @cmds[:inc_val] * i
  end
  @code += @cmds[:dec_ptr] * cells_num
  @code += @cmds[:dec_val]
  @code += @cmds[:loop_end]
  @code += @cmds[:inc_ptr]

  # A pointer to get to the corresponding cells later.
  # To be exact, you would be at cell 1, but you can ignore the first cell 0,
  # because it was only used as a counter for the loop.
  @pointer = 0

  text.each_byte do |search|
    # Search for the next auxiliary number
    diffs = @cell_values.map do |val|
      (search - val).abs
    end
    nearest = diffs.index(diffs.min)

    # It goes to the auxiliary number. This is changed accordingly and the
    # corresponding ASCII_character is output.
    move_pointer @pointer, nearest
    change_value search
    output_cell
  end
end