Brainf*** Golfer

32

7

One of easiest code written by a programming language is a program printing sequence of characters (ex. "Hello, world!"). However, some esoteric programming languages like Brainfuck, even this simplest code is quite annoying to write.

Your task is to write a program (don't have to written in brainfuck), which prints a (minimum-length) Brainfuck program printing the given text.

Input

A sequence of characters (between 1 and 255) is given by any format (variable, argument, stdin, file, ...).

Output

Output is a valid (no non-matching [ and ]) brainfuck code (assume unsigned 8-bit wrapping cell and unlimited number of cells to left and right) printing exact string that was given as input.

For example, one possible output for input A is ++++++++[<++++++++>-]<+..

Your program shouldn't take long time (>2m) to run.

The BF program shouldn't take long time (>10s) to run.

Scoring

(Notice : current scoring method may change, since it is not easy to calculate...)

The length of program (generating BF code) itself doesn't matter. However, hard-coding BF codes in the program code is not OK. Only acceptable range (ex. a BF code printing a single character 0x01 : +.) of BF codes might be hard-coded.

The score is sum of length of BF codes printing these strings.

  • A string Hello, world! appended with a single 0x0A (\n) (i.e. the "Hello, world!" program)
  • Single character from 0x01 ~ 0xFF
    • Sum of length of these 255 BF codes are multiplied by 1/16, rounded, and added to the score.
  • List of first 16 strings, generated by splitting a random sequence of bytes generated on 11-11-11 by 0x00, removing all zero-length strings.
  • Lenna.png, removing all 0x00s.
  • Lyrics of the song 99 bottles of beer, starting with 99 bottles~, newlines are 0x0A, paragraphs are separated by two 0x0As, and no newline character at the end.
  • Other strings you may provide.

Your program may include calculating the score of itself.

Of-course, lowest-score code will be the winner.

JiminP

Posted 2012-04-08T16:39:54.170

Reputation: 3 264

Duplicate (although better phrased) of http://codegolf.stackexchange.com/questions/3450/how-to-encode-shortest-brainf-ck-strings

– copy – 2012-04-08T17:01:08.160

I don't think that this should be closed as a duplicate, though. This question has a scoring method and is more directly a competition, while the other one was partly asking for an explanation of some BF code and does not have any code entries. – PhiNotPi – 2012-04-08T18:24:12.587

4This seems rather hard to calculate the scores. It is a lot of different files we need to track down and run through. What is the point of 'Other strings you may provide'. Why would I add more if it will add to my score? – captncraig – 2012-04-09T03:28:59.343

1Lenna.png is going to dominate the score, as it is by far the largest input. Maybe normalize a bit by size? – Keith Randall – 2012-04-09T04:35:09.240

1OP obviously doesn't care about this challenge. Let's edit the scoring rules to something sensible? Currently, only one answer (unsuccessfully) tried to use these rules, so changing rules will not invalidate answers. – anatolyg – 2016-06-29T12:31:27.233

1Minimum-length code for 'A' is ----[---->+<]>++. – Scony – 2014-02-25T12:37:41.943

Answers

15

In Java, computes a short BF snippet which can convert any number to any other number. Each output byte is generated by either transforming the last output byte or a fresh 0 on the tape.

The snippets are generated in three ways. First by simple repetitions of + and - (e.g. ++++ converts 7 to 11), by combining known snippets (e.g. if A converts 5 to 50 and B converts 50 to 37, then AB converts 5 to 37) and simple multiplications (e.g. [--->+++++<] multiplies the current number by 5/3). The simple multiplications take advantage of wraparound to generate unusual results (e.g. --[------->++<]> generates 36 from 0, where the loop executes 146 times, with a total of 4 descending and 1 ascending wraparounds).

I'm too lazy to compute my score, but it uses about 12.3 BF operations per byte on Lenna.png.

import java.io.*;

class shortbf {
    static String repeat(String s, int n) {
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < n; i++) b.append(s);
        return b.toString();
    }

    // G[x][y]: BF code that transforms x to y.                                                     
    static String[][] G = new String[256][256];
    static {
        // initial state for G[x][y]: go from x to y using +s or -s.                                
        for (int x = 0; x < 256; x++) {
            for (int y = 0; y < 256; y++) {
                int delta = y - x;
                if (delta > 128) delta -= 256;
                if (delta < -128) delta += 256;

                if (delta >= 0) {
                    G[x][y] = repeat("+", delta);
                } else {
                    G[x][y] = repeat("-", -delta);
                }
            }
        }

        // keep applying rules until we can't find any more shortenings                             
        boolean iter = true;
        while (iter) {
            iter = false;

            // multiplication by n/d                                                                
            for (int x = 0; x < 256; x++) {
                for (int n = 1; n < 40; n++) {
                    for (int d = 1; d < 40; d++) {
                        int j = x;
                        int y = 0;
                        for (int i = 0; i < 256; i++) {
                            if (j == 0) break;
                            j = (j - d + 256) & 255;
                            y = (y + n) & 255;
                        }
                        if (j == 0) {
                            String s = "[" + repeat("-", d) + ">" + repeat("+", n) + "<]>";
                            if (s.length() < G[x][y].length()) {
                                G[x][y] = s;
                                iter = true;
                            }
                        }

                        j = x;
                        y = 0;
                        for (int i = 0; i < 256; i++) {
                            if (j == 0) break;
                            j = (j + d) & 255;
                            y = (y - n + 256) & 255;
                        }
                        if (j == 0) {
                            String s = "[" + repeat("+", d) + ">" + repeat("-", n) + "<]>";
                            if (s.length() < G[x][y].length()) {
                                G[x][y] = s;
                                iter = true;
                            }
                        }
                    }
                }
            }

            // combine number schemes                                                               
            for (int x = 0; x < 256; x++) {
                for (int y = 0; y < 256; y++) {
                    for (int z = 0; z < 256; z++) {
                        if (G[x][z].length() + G[z][y].length() < G[x][y].length()) {
                            G[x][y] = G[x][z] + G[z][y];
                            iter = true;
                        }
                    }
                }
            }
        }
    }
    static void generate(String s) {
        char lastc = 0;
        for (char c : s.toCharArray()) {
            String a = G[lastc][c];
            String b = G[0][c];
            if (a.length() <= b.length()) {
                System.out.print(a);
            } else {
                System.out.print(">" + b);
            }
            System.out.print(".");
            lastc = c;
        }
        System.out.println();
    }

    static void genFile(String file) throws IOException {
        File f = new File(file);
        int len = (int)f.length();
        byte[] b = new byte[len];
        InputStream i = new FileInputStream(f);
        StringBuilder s = new StringBuilder();
        while (true) {
            int v = i.read();
            if (v < 0) break;
            if (v == 0) continue; // no zeros                                                       
            s.append((char)v);
        }
        generate(s.toString());
    }
    public static void main(String[] args) throws IOException {
        genFile(args[0]);
    }
}

Keith Randall

Posted 2012-04-08T16:39:54.170

Reputation: 19 865

I know that I'm about two and a half years late and this isn't golf, but the repeat method could just be return new String(new char[length]).replaceAll("\0", str); – Loovjo – 2015-10-19T05:03:47.683

13

Well here's about the worst possible solution, although a rather nice looking one in Brainfuck itself:

++++++[>+++++++>+++++++++++++++>+++++++<<<-]>++++>+>+>,[[<.>-]<<<.>.>++.--<++.-->>,]

Score is probably the worst we are likely to see without intentionally making it bad.

Working on calculating actual score.

captncraig

Posted 2012-04-08T16:39:54.170

Reputation: 4 373

Could you explain what this does? Reading BF code is rather difficult. – BMac – 2015-03-04T21:55:15.963

3For each byte of input it simply prints N +'s and a . – captncraig – 2015-03-04T21:56:18.123

With I believe a [-] to clear the cell between each character. – captncraig – 2015-03-04T22:01:55.487

8

Score: 4787486 4143940 4086426 (without randomly generated data)

(4085639 of that are from Lenna.png. That's 99.98%)

I don't get the part with the random data. Don't I need an account which I have to pay for to get the data?

Pretty naive. Here's the generated code for "1Aa" (49, 65, 97) with a little documentation:

                   // field 0 and 1 are loop counters.
                   // The fields 2, 3 and 4 are for "1", "A" and "a"
++++++++++[        // do 10 times
    >
    ++++++++++[    // do 10 times
        >          // "1" (49) is below 50 so we don't need to do anything here
        >+         // When the loops are done, this part will have increased the value of field 3 by 100 (10 * 10 * 1)
        >+         // same as above
        <<<-       // decrease inner loop counter
    ]
    >+++++         // this will add 50 (10 * 5) to field 2, for a total of 50
    >----          // subtract 40 from field 3, total of 60
    >              // Nothing done, value stays at 100
    <<<<-          // decrease outer loop counter
]
>>-.               // subtract 1 from field 2, total now: 49, the value for "1"
>+++++.            // add 5 to field 3, makes a total of 65, the value for "A"
>---.              // subtract 3 from field 4, total of 97, the value for "a"

The Java code is a bit ugly but it works. The generated instruction per input byte ratio is probably better the higher the average byte value is.

If you want to run it, you have to put Lenna.png in the same directory as the .class file. It prints the score to console and writes the generated BF code into a file called "output.txt".

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;


public class BrainFuckGenerator {
    public static CharSequence generate(byte[] bytes) {
        final StringBuilder brainfuckBuilder = new StringBuilder();
        for(int j = 0; j<10; j++)
                brainfuckBuilder.append("+");

        brainfuckBuilder.append("[>");

        for(int j = 0; j<10; j++)
            brainfuckBuilder.append("+");

        brainfuckBuilder.append("[");

        final StringBuilder singles = new StringBuilder();
        final StringBuilder tens = new StringBuilder();
        final StringBuilder goBack = new StringBuilder();

        for(byte b: bytes) {
            brainfuckBuilder.append(">");
            for(int j=0; j<(b/100); j++) {
                brainfuckBuilder.append("+");
            }

            tens.append(">");
            if((b - (b/100)*100)/10 <= 5) {
                for(int j=0; j<(b - (b/100)*100)/10; j++) {
                    tens.append("+");
                }
            } else {
                brainfuckBuilder.append("+");
                for(int j=0; j<10 - (b - (b/100)*100)/10; j++) {
                    tens.append("-");
                }
            }

            singles.append(">");
            if(b%10 <= 5) {
                for(int j=0; j<b%10; j++) {
                    singles.append("+");
                }
            } else {
                tens.append("+");
                for(int j=0; j<10 - (b%10); j++) {
                    singles.append("-");
                }
            }
            singles.append(".");

            goBack.append("<");
        }
        goBack.append("-");

        brainfuckBuilder
            .append(goBack)
            .append("]")
            .append(tens)
            .append("<")
            .append(goBack)
            .append("]>")
            .append(singles);

        return brainfuckBuilder;
    }

    public static void main(String[] args) {
        /* Hello, World! */
        int score = score("Hello, world!"+((char)0xA));

        /* 255 single chars */
        int charscore = 0;
        for(char c=1; c<=0xff; c++)
            charscore += score(String.valueOf(c));

        score += Math.round(((double)charscore)/16);

        /* Lenna */
        final File lenna = new File("Res/Lenna.png");
        final byte[] data = new byte[(int)lenna.length()];
        int size = 0;
        try(FileInputStream input = new FileInputStream(lenna)) {
            int i, skipped=0;
            while((i = input.read()) != -1)
                if(i == 0)
                    skipped++;
                else
                    data[size++ - skipped] = (byte)(i&0xff);
        } catch (IOException e) {
            e.printStackTrace();
        }

        score += score(Arrays.copyOf(data, size), "Lenna");

        /* 99 Bottles */
        final StringBuilder bottleBuilder = new StringBuilder();
        for(int i=99; i>2; i--) {
            bottleBuilder
                .append(i)
                .append(" bottles of beer on the wall, ")
                .append(i)
                .append(" bottles of beer.")
                .append((char) 0xa)
                .append("Take one down and pass it around, ")
                .append(i-1)
                .append(" bottles of beer on the wall.")
                .append((char) 0xa)
                .append((char) 0xa);

        }

        bottleBuilder
            .append("2 bottles of beer on the wall, 2 bottles of beer.")
            .append((char) 0xa)
            .append("Take one down and pass it around, 1 bottle of beer on the wall.")
            .append((char) 0xa)
            .append((char) 0xa)
            .append("No more bottles of beer on the wall, no more bottles of beer. ")
            .append((char) 0xa)
            .append("Go to the store and buy some more, 99 bottles of beer on the wall.");

        score(bottleBuilder.toString(), "99 Bottles");
        System.out.println("Total score: "+score);
    }

    private static int score(String s) {
        return score(s, null);
    }

    private static int score(String s, String description) {
        final CharSequence bf = generate(s.getBytes());
        try(FileWriter writer = new FileWriter("Res/output.txt", true)) {
            writer.write((description == null ? s : description));
            writer.write(NL);
            writer.write("Code:");
            writer.write(NL);
            writer.write(bf.toString());
            writer.write(NL+NL);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bf.length();
    }

    private static int score(byte[] bytes, String description) {
        final CharSequence bf = generate(bytes);
        try(FileWriter writer = new FileWriter("Res/output.txt", true)) {
            if(description != null) {
                writer.write(description);
                writer.write(NL);
            }
            writer.write("Code:");
            writer.write(NL);
            writer.write(bf.toString());
            writer.write(NL+NL);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bf.length();
    }

    private static final String NL = System.getProperty("line.separator");
}

I'm going to make some small improvements but probably not much. Done.

IchBinKeinBaum

Posted 2012-04-08T16:39:54.170

Reputation: 253

This is broken, the generated BF outputs NUL bytes or '?' characters depending on the locale for any character not in 1..127. Plain ASCII (1-127) seems to be fine though. Noticing that (byte)s are signed and carefully choosing a locale gets a lot of them (taking the score over 5800000) but there are still several thousand NULs from the bf conversion of Lenna.png. So there's something else too. – user3710044 – 2015-09-05T22:52:44.927

8

I'm not sure how good it is, but I had fun writing this. (In Clojure...)

(ns bf.core)
(def input "Hello world!")
(defn abs [x] (if (and (< x 0) (= (type x) (type 1))) (* x -1) x)) 
(defn sqrt? [x y] (if (= (* y y) x) true false) )
(defn sqrt [x] (for [y (range x) :when (sqrt? x y)] y) )
(defn broot [x]
;  Run this using trampoline, e.g., (trampoline broot 143)
  (if (< x 2) nil)
  (let [y (sqrt x)]
    (if (not= (seq y) nil)
      (first y)
      (broot (dec x) )
      )
    )
  )
(defn factor [x]
  (if (<= x 2) x)
  (for [y (range (- x 1) 1 -1)
        :when (= ( type (/ x y) ) (type 1) )
        ]
    y)
  )

(defn smallest_factors [x]
  (let [ facts (factor x) ]
  (if (= (count facts) 2) facts)
  (if (< (count facts) 2) (flatten [facts facts])
    (let [ y (/ (dec (count facts) ) 2)
          yy (nth facts y)
          z (inc y)
          zz (nth facts z)
          ]
      (if (= (* yy zz) x ) [yy zz] [yy yy])
      )
    )
    )
  )

(defn smallestloop [x]
  (let [ facts (smallest_factors x)
        fact (apply + facts)
        sq (trampoline broot x)
        C (- x (* sq sq) )]
    (if (and (< fact (+ (* 2 sq) C) ) (not= fact 0))
      facts
      [sq sq C])
    )
  )
(def lastx nil)
;Finally!
(defn buildloop [x]
  (if (nil? lastx)
     (let [pluses (smallestloop x)]
       (apply str
              (apply str (repeat (first pluses) \+))
              "[>"
              (apply str (repeat (second pluses) \+))
              "<-]>"
              (if (and (= (count pluses) 3) (> (last pluses) 0))
                (apply str(repeat (last pluses) \+))
              )
              "."
              )
    )
    (let [diff (abs (- x lastx) )]
      (if (< diff 10)
        (if (> x lastx)
          (apply str
               (apply str (repeat diff \+))
               "."
                 )
          (apply str
                 (apply str (repeat diff \-))
                 "."
                 )
          )
        (let [signs (smallestloop diff)]
          (apply str
             "<"
             (apply str (repeat (first signs) \+))
             "[>"
             (if (> x lastx)
               (apply str (repeat (second signs) \+))
               (apply str (repeat (second signs) \-))
             )
             "<-]>"
             (if (and (= (count signs) 3) (> (last signs) 0))
               (if (> x lastx)
                 (apply str(repeat (last signs) \+))
                 (apply str(repeat (last signs) \-))
               )
             )
             "."
           )
         )
        )
      )
    )
  )
(for [x (seq input)
  :let [y (buildloop (int x))]
      ]
  (do 
   (def lastx (int x))
   y
   )
  )

There are probably more efficient solutions, and more elegant ones, but this follows my thought pattern somewhat linearly, so it was easiest.

Marty

Posted 2012-04-08T16:39:54.170

Reputation: 201

8

Python 3.x

Well, I'm not going to win any prizes for the shortest output code but maybe for the program to generate the code...

x=input();o=''
for i in x:
 a=ord(i)
 o+="+"*a+".[-]"
print(o)

'Hello, World!\n':

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++.[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++.[-]+++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+.[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++.[-]++++++++++++++++++++++++++++++++++++++++
++++.[-]++++++++++++++++++++++++++++++++.[-]++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++.[-]+++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++.[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++.[-]++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++.[-]+++++++++++++++++++++++++++++++++.[-]++++++++++.[-]

icedvariables

Posted 2012-04-08T16:39:54.170

Reputation: 453

1Accidentally answered to Madisons answer. Shorter generator: print("".join(["+"*ord(i)+".[-]"for i in input()])) – FatalError – 2017-12-08T03:25:01.590

You can golf your program by 2 chars by replacing .[-] with .> – MilkyWay90 – 2019-05-05T16:44:47.190

47 bytes – MilkyWay90 – 2019-05-05T16:55:12.853

4

BrainF**k

I'm a pretty bad BF programmer, so this answer is probably pretty inefficient. I'm unsure of the score, but it should perform slightly better than the existing answer on your average text. Rather than zeroing the cell out after every character, this one will "adjust" to a new character with subtraction if the previous character given is larger.

>>++++++[-<+++++++>]<+>>+++++[-<+++++++++>]>+++++[-<+++++++++>]<+>>,[-<+>>>>>>+<<<<<]<[-<<<.>>>]<.>>+>,[[-<<+>>>+>>+<<<]>>>>[-<<+>>]<[->+<]<<[->-[>]<<]<[->->[-<<<<<<.>>>>>>]<<]>+[-<<->>>[-<<<<<<.>>>>>>]<]<<<[>]<<.>[-]>+>,]

(Note, this is code I wrote a long time ago, and have repurposed for this competition. I sincerely hope I've done the conversion correctly, but if it fails for any input let me know.)

A version showing the state of the tape throughout the code:

>>++++++[-<+++++++>]<+>             [0 '+' 0]
                                           ^
>+++++[-<+++++++++>]                [0 '+' '-' 0]
                                               ^
>+++++[-<+++++++++>]<+>             [0 '+' '-' '.' 0]
                                                   ^
>,[-<+>>>>>>+<<<<<]                 [0 '+' '-' '.' a 0 0 0 0 0 a]
                                                     ^
<[-<<<.>>>]<.>>+>                   [0 '+' '-' '.' 0 1 0 0 0 0 a]
                                                       ^
,[[-<<+>>>+>>+<<<]                  [0 '+' '-' '.' b 1 0 b 0 b a]
                                    [b is not 0]       ^
>>>>[-<<+>>]<[->+<]                 [0 '+' '-' '.' b 1 0 b a 0 b]
                                                             ^    
<<[->-[>]<<]

<[->->[-<<<<<<.>>>>>>]<<]           

>+[-<<->>>[-<<<<<<.>>>>>>]<]        [0 '+' '-' '.' b 0 0 0 0 0 b]
                                                       ^|^
                                    [OUTPUT ONE CHARACTER BY THIS POINT]
<<<[>]<<.>[-]>                      [0 '+' '-' '.' 0 0 0 0 0 0 b]
                                                     ^
+>,]                                [End when b == 0]
                                    [GOAL: '+' '-' '.' b 1 0 b a 0 a]

Generated code for Hello, World!:

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

This is my first answer on CG.SE! If I've screwed something up, let me know!

BrainSteel

Posted 2012-04-08T16:39:54.170

Reputation: 5 132

4

><>

i:&v
.21<>i:0(?;:&:@(4g62p$:&-01-$:@0(?*l2=?~02.
>:?!v"+"o1-
"."~<.15o
+-

I wrote this in response to a question marked for a duplicate, and even though this isn't the greatest golf (for this specific question, at least) I figured it'd be kind of a waste if I didn't share it in all of its disgustingly gibberish-y glory. Really, I'm half-surprised it even works. I'll take any suggestions to golf it down since that was my main goal in its creation.

As a side note, in the second line the beginning three characters .21 could be replaced with v followed by two spaces if that makes it any easier to read. I don't like to see spaces in my ><> programs because that means there's wasted space (literally). It also is a remnant from one of many prototypes.

The way it functions is really simple, and quite frankly I'd have a difficult time thinking of a way to implement another algorithm. It prints however many "+"s need to be printed for the first character, and then prints more "+"s or "-"s as needed for each additional character, separating each section with periods. What I find cool about the program is that it modifies its own source code so that it prints "+" or "-" (it replaces the "+" on line 3 with the appropriate character after determining whether the current character is greater than or less than the previous one).

Output for Hello, World!:

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

I might score this the way it was intended to be scored, but I'm almost positive I'd lose and I don't entirely know how to read something like lenna.png in ><>.

If this answer interests you and you'd like an explanation, by all means ask, but for now I'll leave it without one just because of how twisty and turny it is.

EDIT 1: It's been a while but I was able to golf off 2 bytes with an almost complete overhaul of the way the program decides whether to print a plus or a minus. It's a somewhat disappointing return for a large overhaul but at least it works.

cole

Posted 2012-04-08T16:39:54.170

Reputation: 3 526

This gibberish program makes another gibberish program! This is the greatest program i've ever seen! – Aequitas – 2015-10-19T02:46:28.777

1

my JavaScript solution it`s quick and dirty :)

output for Hello World\n

++++++++++[>+++++++>++++++++++>+++++++++++>+++>+++++++++>+<<<<<<-]>++.>+.>--..+++.>++.>---.<<.+++.------.<-.>>+.>>.

Source:

BfGen("Hello World!\n");
// ++++++++++[>+++++++>++++++++++>+++++++++++>+++>+++++++++>+<<<<<<-]>++.>+.>--..+++.>++.>---.<<.+++.------.<-.>>+.>>.
// Length of BF code: 115
// Score: 8.846153846153847


function BfGen(input) {
    function StringBuilder() {
        var sb = {};

        sb.value = '';
        sb.append = (txt) => sb.value += txt;

        return sb;
    }

    function closest (num, arr) {
        var arr2 = arr.map((n) => Math.abs(num-n))
        var min = Math.min.apply(null, arr2);
        return arr[arr2.indexOf(min)];
    }

    function buildBaseTable(arr) {
        var out = StringBuilder();
        out.append('+'.repeat(10));
        out.append('[')
        arr.forEach(function(cc) {
            out.append('>');
            out.append('+'.repeat(cc/10));    
        });
        out.append('<'.repeat(arr.length));
        out.append('-');

        out.append(']');
        return out.value;
    }

    var output = StringBuilder();

    var charArray = input.split('').map((c) =>c.charCodeAt(0));
    var baseTable = charArray.map((c) => Math.round(c/10) * 10).filter((i, p, s) => s.indexOf(i) === p);

    output.append(buildBaseTable(baseTable));

    var pos = -1;
    charArray.forEach(function (charCode) {
        var bestNum = closest(charCode, baseTable);
        var bestPos = baseTable.indexOf(bestNum);

        var moveChar = pos < bestPos? '>' : '<';
        output.append(moveChar.repeat(Math.abs(pos - bestPos)))
        pos = bestPos;

        var opChar = baseTable[pos] < charCode? '+': '-';
        output.append(opChar.repeat(Math.abs(baseTable[pos] - charCode)));
        output.append('.');
        baseTable[pos] = charCode;
    });

    console.log(output.value)
    console.log('Length of BF code: ' + output.value.length);
    console.log('Score: ' + output.value.length / input.length);
}

Peter

Posted 2012-04-08T16:39:54.170

Reputation: 213

2Welcome to the site! You should include the score in the title of your answer. – Post Rock Garf Hunter – 2017-01-18T00:07:41.143

i just made the bf generator, original score system has image processing what is not relevant :( Hello world ratio is less then 9 (bf length / original text length) – Peter – 2017-01-18T02:00:50.373

1

Python 3

print("".join("+"*ord(i)+".[-]"for i in input()))

This is essentially just an slightly improved version of icedvariables' answer. (-1 Byte from Wheat Wizard, -5 from FatalError, -2 from jez)

Madison Silver

Posted 2012-04-08T16:39:54.170

Reputation: 139

I believe this is python 3. If so You should include so in your header. If so you can also remove the line break after your :. This could also probably be done as a list comprehension to save bytes. – Post Rock Garf Hunter – 2017-06-15T14:41:08.627

-5 bytes with print("".join(["+"*ord(i)+".[-]"for i in input()])) – FatalError – 2017-12-08T03:12:52.943

-2 bytes: lose the square brackets so you're calling join() on a generator expression rather than a list comprehension: print("".join("+"*ord(i)+".[-]"for i in input())) – jez – 2019-01-28T17:44:39.453

-2 bytes: you can simply move to the next cell (the question states you should assume an infinite band in both directions print("".join("+"*ord(i)+".>"for i in input())) (this also reduces the score since you lose 2 bytes in the output) – MegaIng – 2019-02-08T10:21:10.323

1

I built something in Java. Didn't calculate the score. Texts with 3 or less characters are encoded with a multiplication per letter e.g. "A" = ++++++++[>++++++++<-]>+.. Texts with more than 3 characters are encoded with a calculated list which is split into 3 areas. The first area is x times 49, then plus x times 7 and finally plus x. For example "A" is 1*49 + 2*7 + 2

public class BFbuilder {
    public static void main(String[] args) {
        String text = "### INSERT TEXT HERE ###";

        if (text.length()<=3){
            String result = "";
            for (char c:text.toCharArray()) {
                result += ">";
                if (c<12) {
                    for (int i=0;i<c;i++) {
                        result += "+";
                    }
                    result += ".>";
                } else {
                    int root = (int) Math.sqrt(c);
                    for (int i = 0; i<root;i++) {
                        result += "+";
                    }
                    result += "[>";
                    int quotient = c/root;
                    for (int i = 0; i<quotient;i++) {
                        result += "+";
                    }
                    result += "<-]>";
                    int remainder = c - (root*quotient);
                    for (int i = 0; i<remainder;i++) {
                        result += "+";
                    }
                    result += ".";
                }
            }
            System.out.println(result.substring(1));
        } else {
            int[][] offsets = new int[3][text.length()];
            int counter = 0;
            String result = "---";

            for(char c:text.toCharArray()) {
                offsets[0][counter] = c/49;
                int temp = c%49;
                offsets[1][counter] = temp/7;
                offsets[2][counter] = temp%7;
                counter++;
            }

            for (int o:offsets[0]) {
                switch (o) {
                case 0: result+=">--";
                break;
                case 1: result+=">-";
                break;
                case 2: result+=">";
                break;
                case 3: result+=">+";
                break;
                case 4: result+=">++";
                break;
                case 5: result+=">+++";
                break;
                }
            }
            result += ">+[-[>+++++++<-]<+++]>----";
            for (int o:offsets[1]) {
                switch (o) {
                case 0: result+=">---";
                break;
                case 1: result+=">--";
                break;
                case 2: result+=">-";
                break;
                case 3: result+=">";
                break;
                case 4: result+=">+";
                break;
                case 5: result+=">++";
                break;
                case 6: result+=">+++";
                break;
                }
            }
            result += ">+[-[>+++++++<-]<++++]>----";
            for (int o:offsets[2]) {
                switch (o) {
                case 0: result+=">---";
                break;
                case 1: result+=">--";
                break;
                case 2: result+=">-";
                break;
                case 3: result+=">";
                break;
                case 4: result+=">+";
                break;
                case 5: result+=">++";
                break;
                case 6: result+=">+++";
                break;
                }
            }
            result += ">+[-<++++]>[.>]";
            System.out.println(result);
        }
    }
}

The provided String "### INSERT TEXT HERE ###" becomes --->-->-->-->-->->->->->->->-->->->->->-->->->->->-->-->-->-->+[-[>+++++++<-]<+++]>---->++>++>++>+>>+>+>->+>++>+>++>->++>++>+>>->+>->+>++>++>++>+[-[>+++++++<-]<++++]>---->--->--->--->+>>-->+++>+++>++>--->+>--->+++>+>--->+>->+++>++>+++>+>--->--->--->+[-<++++]>[.>]

"Hello, World!" becomes --->->>>>>-->-->->>>>>-->+[-[>+++++++<-]<+++]>---->>--->-->-->-->+++>+>++>-->->-->--->+>+[-[>+++++++<-]<++++]>---->->>>>+++>->+>>+++>->>->++>+[-<++++]>[.>]

Dorian

Posted 2012-04-08T16:39:54.170

Reputation: 1 521