10
\$\begingroup\$

Given a text, this program will output a Brainfuck program, that when executed will print the text back.

Writing Brainfuck in this style to print a sentence is pretty straightforward. Iterate over the sentence and do the following per character:

  • Calculate the difference between the current character and the previous
  • Write either as many + or - as the difference between characters. + if current character is higher than previous character, - if lower than previous character
  • Write . to print current character

Hello, World!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+++++++++++++++++++++++++++++.
+++++++.
.
+++.
-------------------------------------------------------------------.
------------.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++.
++++++++++++++++++++++++.
+++.
------.
--------.
-------------------------------------------------------------------.

The code

def brainturing_printer_generator(text)
  ords = text.chars.map(&:ord)
  ("+" * ords.first + ".\n") + ords
    .zip(ords[1..-1])
    .take(ords.size - 1)
    .map {|prev, curr| (curr > prev ? "+" : "-") * (curr - prev).abs}
    .join(".\n") + ".\n"
end

print brainturing_printer_generator("Hello, World!")
\$\endgroup\$
  • 2
    \$\begingroup\$ No need to be so bashful: You can say "brainfuck" on this turing site :) Still, I'd leave it as-is. Sounds more intriguing this way \$\endgroup\$ – Flambino Sep 6 '15 at 0:38
  • 1
    \$\begingroup\$ If you don't feel like swearing, the idiomatic terms are either "Brain****" or simply "BF." \$\endgroup\$ – porglezomp Sep 6 '15 at 2:07
6
\$\begingroup\$

It's neat, though I feel like there's a bit too much array manipulation going on.

Your friend for this, I'd argue, is the each_cons method, short for "each consecutive". Then you don't need the zip, though you do need to pad the beginning of the array.

Here's my take:

def brainturing_printer_generator(text)
  ords = [0] + text.chars.map(&:ord)
  ords.each_cons(2).map do |previous, current|
    delta = current - previous
    line = (delta < 0 ? "-" : "+") * delta.abs
    "#{line}."
  end.join("\n")
end
\$\endgroup\$
  • \$\begingroup\$ each_cons is surely a simplification over my original code, I always miss some built-in Ruby goodness :) \$\endgroup\$ – Caridorc Sep 6 '15 at 12:50
  • 2
    \$\begingroup\$ @Caridorc Yeah, in many reviews I've told people to read the docs for Array and Enumerable as much as they can stand :) There's so much good stuff, and it took me a while to learn that as well. Also you get a sixth sense that tells you "there must be a built-in way to do X" and a lot of the time you're right. It's almost always a good idea to just skim the list of methods, even if you've already got a solution in your head \$\endgroup\$ – Flambino Sep 6 '15 at 13:54
  • 1
    \$\begingroup\$ You miss the last . \$\endgroup\$ – Nakilon Sep 7 '15 at 13:04
  • \$\begingroup\$ @Nakilon Damn, you're right. I'll fix it, thanks \$\endgroup\$ – Flambino Sep 7 '15 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.