Compose two Brainfuck programs

10

3

Given 2 brainfuck code snippets A and B, output some brainfuck code C which has the same behavior as running B with the input of As result. Note that C must work for any input that match the following assumptions, as if it were given to A.

You can assume:

  1. Finite input.
  2. both A and B halt.
  3. EOF is consistently 0 or consistently -1.
  4. Consistently allow or disallow cells to left
  5. Unbounded tape (otherwise the requirement may be impossible)
  6. Consistently 8-bit wrapping or unbounded integer
  7. No stream(input or output for A or B) contain the byte representing EOF
  8. Code A and B can contain characters that possibly appear in your C, and +-[]<>,.

E.g. (EOF=0)

A = ,[..,]
B = ,[...,]
C = ,[......,]

A = >,[>,]<[.<]
B = ,[...,]
C = >>>>,[[-<+<+<+>>>]>>>,]<<<<[.<]

A = >,[>,]<[.<]
B = ,[...,]
C = >,[>,]<[...<]

A = ,.
B = ,.
C = ,>,[,]<.

A = ,.
B = ,.
C = ,.

are valid tests

Shortest code in each language win. Winner in Brainfuck will be accepted.

l4m2

Posted 2018-07-17T03:29:06.730

Reputation: 5 985

7Shortest code in each language win and Shortest Brainfuck solution will be accepted are two different winning criteria. – Mego – 2018-07-17T03:58:52.407

2@Mego I meant if you answer in brainfuck and you win, you're accepted – l4m2 – 2018-07-17T06:22:55.537

Can you explain what "Winner in Brainfuck will be accepted." is supposed to mean?

  1. The composer must output brainfuck code?
  2. The composer code length doesn't matter, but the shortest brainfuck code wins?
  3. If the composer is written in brainfuck, it wins?
  4. < – Dorian – 2018-07-18T06:01:25.517

@Dorian Your submission is written in BF and you win. (option 3) – user202729 – 2018-07-18T06:13:32.960

Some of the tests doesn't make sense. How can #3 ,. with ,. become eqvivalent with ,>,[,]<.. The composition will only read once, but your result reads more. – Sylwester – 2018-07-19T20:34:18.177

@dzaima What I mean is if you compose ,. and ,. you get ,. not ,>,[,]<. since that reads more than once and ends up printing the second input. It isn't a second input since ,. does only read ONCE. You even see that in the #4 example which is the exact same two programs with correct outcome – Sylwester – 2018-07-21T21:33:16.253

@dzaima ,>,[,]<. with one byte input prints whatever EOF is. That is different than the composition of ,. and ,. which only prints the first initial input once and perhaps ignore all other input if any. – Sylwester – 2018-07-21T21:38:28.690

1Also. can you elaborate on 4.Consistently allow or disallow cells to left. The leading answer requires cells on left in the answer to work but disallow A, B, and C to not move passed the first byte. My answer diallows move to left in answer, A, B, and C. If the rules for my program and C can be different from A, and B then i surely can shorten my answer a lot. – Sylwester – 2018-07-21T21:42:57.377

@Sylwester no it doesn't? The middle >,[,]< is guaranteed to always finish as input is finite (assuming an interpreter where EOF == 0) and it doesn't move the pointer and doesn't output so it's a noop

– dzaima – 2018-07-21T21:42:59.470

@dzaima Ah. I see it now. Thanks for your patience. Could you please answer about the 4th rule? – Sylwester – 2018-07-21T21:45:36.457

1The entire problem statement is about A, B, and C, and only the last two sentences make any reference to the language of the answer. Perhaps the author did intend for the answer to be in the same flavor as A, B, and C, but that would not be my fault. Solvers should not be punished for problem authors' lack of foresight. At any rate it is really trivial to add a few >s to the beginning of my answer to make it comply with a more restrictive flavor (but for golf, we should also consider alternatives). Also, it seems clear to me that A, B, and C must be in the same flavor as each other. – Mitch Schwartz – 2018-07-21T22:13:13.410

Also @dzaima "invalid" in your comment seems slightly misleading to me -- we are not talking about validity in the usual sense (whereby invalid answers should be fixed or deleted), but merely of eligibility for acceptance (and I'm not a fan of accepting answers on this site, but if such a criterion for acceptance had been clearly specified then I would have answered accordingly, because why not). If my point on validity seems unclear, consider a correct answer in e.g. self-modifying brainfuck, which would be clearly valid but not eligible.

– Mitch Schwartz – 2018-07-21T22:43:21.430

@dzaima If you really do mean "invalid" in the usual sense, that would be equivalent to the author specifying "You may answer in any language this site allows, except for flavors of brainfuck that differ from the flavor you chose for A, B, and C.", which seems rather elaborate to me... (And I feel slightly dirty even addressing this whole issue, since it is so trivial and has nothing to do with golf or problem solving.) – Mitch Schwartz – 2018-07-21T23:10:56.443

1Maybe I'm completely misunderstanding the challenge, but test cases #3 and #4 seem to clash. – James – 2018-07-27T16:53:07.707

Answers

8

brainfuck, 526 bytes

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

Formatted:

-<+++++<+<+++++<-[+++++++[<++++++++>-]<--->>]
<<--<--<+..<<<<
,
[
  [<+> >+<-]
  ----[>-<----]>
  [
    not question mark
    +
    [
      not greater than
      ++
      [
        not less than
        ++++++++++++++
        [
          not period
          ++
          [
            not comma
            [-]<
          ]
          <<<
          [
            comma B
            >-->>> -.>>>.<<<.>.>.<<.+>>--..>.<..<.>.>..<++.<.>..>.<..<.>--.>>.<<
            .>.<..<.>.>.<.<.>++.<<.>.>.>.<.<.>..>.<..<.>>>.<<--.++<<<
          ]
          >>>>[<]<
        ]
        >
        [
          period
          <<<<
          [
            B
            >
          ]
          >
          [
            A
            +>>> >>.>.<<<.>.<.>>>.<.[.<.>>>]<++[<<.<.>>.<<--.<<.>.>.++>>>-]<<<<.
            >.>>.<.<<<.>>..>>.<<<.>--.>.<++...<<.>>--..>>.<.<..<.>.>>.<<++...>.<
            ..<.>>>.<<--...++<<[.>]<<<--.<<.>>++.<.>>>.<<--.++<<<
          ]
        ]
        <
      ]
      >
      [
        less than
        <<<.>>
      ]
      <
    ]
    >
    [
      greater than
      >>.>.<<<.>.>>>.[<]
    ]
    <
  ]
  >
  [
    question mark
    >>.>.<..<.>>>.[<]
    <<<+>->>
  ]
  <<.[-]>,
]

With respect to A, B, and C: EOF = 0, cells left of start disallowed, 8-bit wrapping cells.

Expects A followed by ? followed by B.

Try it online

(This answer can be made compliant with a brainfuck interpreter that doesn't allow going left of the start at the cost of one byte by transliterating y/<>/></ and prepending a >.)

The basic idea is to use a series of string replacements in order to simulate the tapes of A and B using 2-cell nodes, with special attention given to replacing . in A and , in B so that the intermediate data stream is kept in a block of cells to the left of the simulated tape. The string replacement scheme is:

  • Insert >> before A

  • In both A and B, replace > with >[-]+> and < with <<

  • In A, replace . with >[-]-[>>]+[[>+<-]<[>+<-]<]>+[->>+]<[>>>-<<+[<<]<+>>>[>>]+<<<-]>[+<->]+</

  • Insert >[>>]+> after A and before B

  • In B, replace , with ,[,]>,<<[<<]<[[>]>>[>>]<+<[<<]<[<]>-]>[>]>>[>>]+<*

Mitch Schwartz

Posted 2018-07-17T03:29:06.730

Reputation: 4 899

,[>,]<[.<]?,[...,] input 12345 returns 111, even with enough > before? – l4m2 – 2018-07-20T10:07:29.617

@l4m2 Hmm, it's working for me on TIO. (,[>,]<[.<] is not valid but >,[>,]<[.<] is.)

– Mitch Schwartz – 2018-07-20T10:14:04.017

So what's your "it allows going to the left of the start cell"? – l4m2 – 2018-07-20T10:35:07.087

The program that takes A and B as input and produces C. See the first three bytes. – Mitch Schwartz – 2018-07-20T10:37:20.787

1So your answer needs a BF that starts in the middle of an infinite tape, but the nature of A and B is limited to the standard where one starts at first cell on an infinite tape to the right? – Sylwester – 2018-07-20T13:36:49.377

1For this solution, going to the left of the start cell is disallowed in A, B, and C, but it is allowed in the program (we may call it D for convenience) that takes A and B and then produces C. I don't think this is very remarkable, and is a natural choice given the nature of the solution. Going to the left of start has major consequences in the context of A, B, and C, but it is quite trivial for D, and subjectively makes for a more enjoyable golf experience as well as a slightly shorter score, and also should not make testing any more tedious, as it is easy to prepend >s to D as needed. – Mitch Schwartz – 2018-07-20T15:08:09.787

6

brainfuck, 1287 bytes

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

Try it online!

Here it is! The brainfuck code that composes two brainfuck codes. Use a "!" to separate the two input code snippets. For example snippet A: >,[>,]<[.<], snippet B: ,[...,]. Input for my program: >,[>,]<[.<]!,[...,]. It will not terminate if no "!" is found.

This does essentially the same as my VBA Version. The code that is generated is the same as in the VBA version (note that the examples in the VBA post were made before the latest change in the brainfuck snippets).

Explanation

This is my source code:

[ 
Tape: "+"(43) "-"(45) "<"(60) ">"(62) "["(91) "]"(93) readA(1) printInput(0) input else exitIf exitElse
]

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

<<<.....<<.>>....<<.>>.<<..>... print init routine
>>>>[                           while readA
  >+                              set printInput = true
  >,                              read character
  ->[-]++++[-<-------->]          decrease input by 33 to check for "!"
  +                               set else flag

  # A check for "!"
  <[                              if input not "!"
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <-                              set readA = false
    <<<..>.<.....>>.<<<.....>>.<<<< print routine between A and B
    .>>..>>.<<<.>>>>.<<<...>>>.<<.<
    <<..>>>>.<<<..>>.....<<<..>>>>>
    .<<<<<.>>>>.<<<.>.....<<.>>>>>.
    <<<<.>>..>>>
    >>>>>                           go to exitElse
  ]

  # A check for "dot"
  <<<----- ----- ---              decrease input by 13 (total 46) to check for dot
  [                               if input not dot
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<<..<<.>..>>.<<<.>.<<.>>>.... print list storing routine
    <<<.>>>>.<<<.>.....<<.>>>>>.<<<
    <<.>>>>.<<<..>>.....<<<..>>>>>.
    <<<<..>..<<.>>>..<<<.>>>>.<<<.>
    .....<<.>>>>>.<<<<.>.<<..>>>>.<
    <<..>>.....<<<..>>>>>.<<<<..>..
    >>>.<<<.>>.<<<.>>.<<<.>>.>>>.<<
    ....<<<.>>>>.<<<.>.....<<.>>>>>
    .<<<<<.>>>>.<<<..>>.....<<<..>>
    >>>.<<.....<<.>>>.<<<.>.....<<.
    >>>>>.<<<<.>.<<..>>>>.<<<..>>..
    ...<<<..>>>>>.<<<<.>..>>>>>
    >>>>                            go to exitElse
  ]

  # A check for "less than"
  <<<----- ----- ----             decrease input by 14 (total 60) to check for "less than"
  [                               if input not "less than"
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<<<...>>.<<<<.>>>>>.<<<<.>..>>>>> print A move left routine
    >>>>                            go to exitElse
  ]

  # A check for "greater than"
  <<<--                           decrease input by 2 (total 62) to check for "greater than"
  [                               if input not "greater than"
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<<.......>.<<<<.>>>>>.<<<<.>..>>>>> print A move right routine
    >>>>                            go to exitElse
  ]

  # print remaining character
  <<<<[                           if printInput
    +++++++[->++++++++<]>--.<     print original character
  ]

<                               go to readA
]

>>,                             read next character
[                               while input
  <+                              set printInput = true

  # B check for comma
  >>++++[-<----- ---->]+<+        decrement input by 44 to check for comma
  [                               if input not comma
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<.<<<.>>>>.<<..<<.>>.>.<..... print B list reading routine
    >>.<<<<<.>>>>.<<<.>.....<<.>>>>
    >.<<<<.>>...>.<<<.>...>>.<<....
    .>>>.<<....<<<.>>>>.<<<.>>.....
    <<<.>>>>>.<<<<.>..<<.>>>...>.<.
    ....>>.<<<<<.>>>>.<<<.>.....<<.
    >>>>>.<<<<.>>...>>.<<..<<.>>>.<
    <.....>>>.<<....<<<.>>>>.<<<.>>
    .....<<<.>>>>>.<<<..>>>>> 
    >>>>                            go to exitElse
  ]

  # B check for "less than"
  <<<----- ----- ----- -          decrease input by 16 (total 60) to check for "less than"
  [                               if input not "less than"
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<<<.....>>>>>                 print B move left routine
    >>>>                            go to exitElse
  ]

  # B check for "greater than"
  <<<--                           decrease input by 2 (total 62) to check for "greater than"
  [                               if input not "greater than"
    >>                              go to exitIf
  ]
  >[                              else
    <<-                             set printInput = false
    <<<<.....>>>>                   print B move right routine
    >>>>                            go to exitElse
  ]

  # print remaining character
  <<<<[                           if printInput
    +++++++[->++++++++<]>--.<     print original character
  ]

>,                              input next character
]

Dorian

Posted 2018-07-17T03:29:06.730

Reputation: 1 521

1Why no output? – l4m2 – 2018-07-19T12:42:18.267

@l4m2: Sorry, I made a little mistake in the test data. I wrote >[,>]<[.<]!,[...,], so snippet A doesn't output anything. Of course it must be >,[>,]<[.<]!,[...,] for a working example. – Dorian – 2018-07-19T12:52:22.917

5

VBA, 512 489 479 bytes

Sub f(A,B):Debug.?">>>>>->>>>->--<<<"&Replace(Replace(Replace(A,"<","<<<[+]-<<"),">",">>>>>>>[+]-<<"),".",">>-<<[-<+>>>>+[-<<<<<+]+[-->>>>>++]--<<+>>+[-<<<<<+]-<++[-->>>>>++]--<<]<[->+<]>>>>+[-<<<<<+]+[-->>>>>++]>>>>>-[-<<<<<+]-<++[-->>>>>++]-<<")&">>[>>>>>]<<<<<[+<<[-]<<<]>++[-->>>>>++]+[-<<<<<+]->>"&Replace(Replace(Replace(B,"<","<<<<<"),">",">>>>>"),",","[-]>>->[>>>>>]+[-<<<<<+]->>>[-<<<[<<<<<]>>>>+[->>>>>+]-<<+>>>[>>>>>]+[-<<<<<+]->>>]>>-[<<<<<]>>>>+[->>>>>+]<<"):End Sub

Explanation

The VBA code changes the brainfuck code in a way, that the output of snippet A will be stored in a list and the input of snippet B will be read from that list.

It first initializes some variables

>>>>>->>>>->--<<<

Then it reads snippet A and replaces every < by <<<[+]-<<, every > by >>>>>>>[+]-<< and every . by the storing routine

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

after that it deletes the memory of snippet A and makes changes to the stored list, so it can be read as input for snippet B:

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

Then snippet B will be read, every < will be replaced by <<<<<, every > will be replaced by >>>>> and every , will be replaced by the list reading routine:

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

Brainfuck source code

This is my source for the brainfuck portions of the code. I will explain that in detail later.

[
Tape: tempMem data out/in dataAnchors outAnchors (all repeating)
dataAnchors of Snippet A: -1 = memory has been used, -2 = active memory cell for copying to out/in
dataAnchors of Snippet B: -1 = active memory cell for copying from out/in
outAnchors of Snippet A: -1 = start of list, -2 = next output position
outAnchors of Snippet B: -1 = character has been read (or start of input)
]

### Init
>>              two blank data cells (for non wrapping pointer)
>>>-            set start of input
>> >>-          set first "used" flag
>--             set end of input
<<<             return to first usable data cell

### A move right routine
>>>>>           move to the next data cell
>>[+]-          clear and set "used" flag
<<              return to data cell

### A move left routine
<<<[+]-         clear and set "used" flag of previous data cell
<<              go to data cell

### A print routine
>>-             set flag
<<[             while value greater 0
  -               decrement value
  <+              increment tempMem
  >>>>+[-<<<<<+]  find start of input
  +[-->>>>>++]--  find end of input
  <<+             increment input
  >>+[-<<<<<+]-   find start of input
  <++[-->>>>>++]--find flag
  <<              go to active data cell
]
<[->+<]         move stored value back to data
>>>>+[-<<<<<+]  find start of input
+[-->>>>>++]    find end of input
>>>>>-          set new end of input
[-<<<<<+]-      return to start of input
<++[-->>>>>++]- return to and delete data flag
<<              go to data cell

### After snippet A: Delete memory of A and configure out/in list
>>[>>>>>]<<<<< go to last used data
[+<<[-]<<<]    delete each data
>++[-->>>>>++] find and delete end of input flag
+[-<<<<<+]-    go to start of input
>>             go to first data cell

### B move right routine
>>>>>          go to next data cell

### B move left routine
<<<<<          go to previous data cell

### B reading routine
[-]                      set cell = 0
>>-                      set flag
>[>>>>>]+[-<<<<<+]-      find start of input
>>>[                     if value greater 0
  -                        decrement value
  <<<[<<<<<]>>>>           go to initial start of input (combined with next)
  +[->>>>>+]-              find mem cell flag
  <<+                      increment mem cell
  >>>[>>>>>]+[-<<<<<+]->>> return to input cell
]
>>-                      set new start of input
[<<<<<]>>>>              go to initial start of input (combined with next)
+[->>>>>+]               find and delete mem cell flag
<<                       go to mem cell

Output for test case 1: f ",[..,]",",[...,]"

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

Try it online!

Output for test case 2: f ">,[>,]<[.<]",",[...,]"

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

Try it online!

Output for test case 3: f ",.",",."

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

Try it online!

Complex test case: Snippet A: Build alphabet triangle >+++++[<+++++>-]<+[>>[>[.>]]>++++++++++.--[<++++++++>-]<[+.<]<-]>>,>[.>]++++++++++.[<[.<]>,>[.>]<] Try it online!

Snippet B: Sort input in ascending order >>,[>>,]<<[[-<+<]>[>[>>]<[.[-]<[[>>+<<-]<]>>]>]<<] Try it online!

Result:

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

Try it online!

Dorian

Posted 2018-07-17T03:29:06.730

Reputation: 1 521

Thank you. I know this is pretty much ungolfed. I just wanted to provide the first working code. Will make changes to the brainfuck part of the code, too. – Dorian – 2018-07-18T06:10:16.950

5

Brainfuck, 785 bytes

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

Try it online!

To split A from B I opted for /.

Explaination:

The actual code that generates this is just a read-loop with a flag for A/B and a switch that reduces the input to look for >, <, /, ,, and . and otherwise just output the input. It is actually just a transpiler where the transpiled code lives within a data structure such that it don't interfere with the stored data from A or each other. The / just moves the active cell to the first unused cell. I originally cleaned it up, but that makes the program and output larger.

The program result has the following memory model:

|0|input*|cz|d0|c0|d2|c0|...

The c is crumble. cz is always 0 It points out where in my emulated BF data the pointer is. The active value is -1 while all visited cells will have 1. In operations like aprint and bread some c get special meaning.

A-code print skips all cells 1 byte to leave room for one more byte input which is copies with a backup in the next bytes crumble to copy back.

B-code read fetches input from input. Here being destructive is ok and when you "read" the last byte you get 0 as EOF regardless of the implementation.

I started out as Extended BrainFuck code making EBF result. Most of the debugging was done on the result files and then updates to the source that generated it. Then i just run the operations independent to get BF output, but I noticed Dorian's answer, which beat me in length so I continued golfing EBF source for smaller BF output. The original source is quite readable and simple compared to other stuff I've done with it:

:bck
:i
:t
:z
:r
:rc
:rz

;;; outputs a header with most of the result logic
{cinit
  |"
    ;; memory model of the result 
    ML/i/z/d/c
    PTR=1/1/2
    :iz:i:z:d:c:d2:c2

    ;; moves pointer back. Bad things will happen to 
    ;; A output if out of bounds
    {backward @d2 $c2++ $c-- $d
    }

    ;; moves pointer forward
    {forward $c++ $c2[-]- $d2 @d
    }

    ;; stores the current cell in input a the start of bf data
    {aprint
      $c2(-)+                 ; mark next cell as used even if it maybe
      $c[$c2]                 ; go to the end of used data
      $c((->+)$d(->+)@d2)     ; as long as c is something move d and c one place right
      @i$c+[->>+]@c           ; go to active cell, zero it
      $d(-                    ; copy: 
        $c2+                  ; backup in c2 
        $z[<<]@z              ; back to i
        $i+ $c[>>]@c          ; increement and back to zero carry
      )
      $c2-(- $d+)+            ; copy backup in c2 back to d
      $c-                     ; mark active cell
      $d                      ; move to d
    }

    ;; removes all the data from A. And initializes for B
    {aend
      $c[$c2]
      $c((-)<(-)<@c)@z
      $c-$d
    }

    ;; instead of read b fetched from input area
    {bread
      (-)>+@c2          ; clear d and c
      $c[$z]            ; go to z
      $i<[<] @iz        ; go to iz
      $i(-$iz+)         ; switch places between i and iz
      $iz(-             ; copy from iz to d
         $z[>]@z        ; move to z
         $c[$c2]        ; move to the current c 
         $d2+           ; increase d
         $c[$z]         ; back to z
         $i[$iz]        ; back to iz
         @i             ; but since we shave switched correct
      )
      $z[>]@z           ; go back to z
      $c[$c2]-          ; move to active cell and make it -1
      $d2 @d            ; go to d
    }

    $c-$d               ; init. Go to c t mark it active, then go to d
    "
  (-)
}

{cmain
  &cinit
  $t,(
    (-$i+$bck+) ; pour to i and bck

    ;; switch ( $i ) cases '<>,./' using $t
    $t+++++++(-$i------)+$i--; ,
    ($i--; .
      ($i-; /
        ($i-------------; <
          ($i--; >
            ((-) $t(-)  $bck.)
              $t (- |"&forward "(-) )
          ) $t (- |"&backward "(-) )
        ) $t (- |"&aend "(-) $r+ )
      ) $t (- $rc+$r[$rc-$bck.$rc]@r$rc[- |"&aprint "(-) $rz])
    ) $t (- $rc+$r[$rc-|"&bread "(-)]@r$rc[-$bck.$rz])
    $bck (-) ; clear backup
      $t,    ; read into t
  )
}

&cmain

Sylwester

Posted 2018-07-17T03:29:06.730

Reputation: 3 678

If I've understood properly, [->+] in program C causes failure for inputs like ->->,./,., and this could be fixed using [->>+] (making sure the pointer starts on a cell with the desired parity). For [-<+], I think you can change the navigation scheme to rely on all of A's output being nonzero? – Mitch Schwartz – 2018-07-19T21:53:23.217

I'm not sure what you mean. When A is ->->,. and B is ,., does your preferred interpreter produce the same C as TIO, and does C work as expected on your interpreter? Because it fails on TIO. (I wrote this in response to a comment that is now deleted.)

– Mitch Schwartz – 2018-07-19T22:24:44.370

@MitchSchwartz Thanks for your comment. I was a little cocky since I didn't expect to scan for -1 though user data, but indeed I did on the line "go to active cell, zero it". I've updated my answer and then I added a byte :-O but at least it works. BTW. If Im not using scan for -1 to when fetching input in B i will have to move the active byte with a copy >[-<+]< and thus I add more chars than i save by replacing +[-<+]- with [<]. If you don't copy you will not be able to know if the byte you compied was finished and copy all bytes. – Sylwester – 2018-07-19T22:36:15.527

Well my mention of [-<+] was actually also in regard to eliminating bugs (as opposed to saving bytes), for input such as -./,>++++++[<++++++>-]<., which should print # rather than %. :) But I do see some opportunities to save bytes as well. Good luck! I will try to optimise my doubly infinite tape solution, although seeing what you did makes me think maybe right-infinite tape is golfier in the end. – Mitch Schwartz – 2018-07-19T23:16:24.747

So, after examining your code more closely, I found that our setups are very similar, and that your use of a right-infinite tape is far better for golf than my doubly infinite tape. Please see my recent sed update for a solution that combines our ideas. I feel that golfing C is the most interesting part of this problem, but there is also some room to make the string replacement program shorter outside of that... – Mitch Schwartz – 2018-07-20T06:43:38.727

Wow, this is really great. I try to golf my version a little bit, but i don't think I can beat you. I even tried this with my Game of Life Beta and a pattern preselector. The resulting code is too long for tio.run, but works fine on the offline Interpreter of The Lost Kingdom. Enter a number between 1 and 8. Try it online!

– Dorian – 2018-07-20T07:13:44.403

(I found a test that doesn't work. -./,. Since tio.run uses 8-bit wrapping data cells, A should print ÿ and B should just read and print it, but it doesn't print anything test. Well this is a special case, I think it can be ignored.)

– Dorian – 2018-07-20T08:23:59.407

@Dorian I've updated by answer. I got a little longer but -./, should work now. Mitch check -./,>++++++[<++++++>-]<. is easier to check though :) Btw. I use my own bf interpeter and the same GoL code on that runs in 0.08 real 0.05 user 0.01 sys but I fear the composition will be crazy slow since this is not optimized for speed :)

– Sylwester – 2018-07-20T12:43:17.813

4

sed, 165 bytes

s > >[-]+> g
s < << g
1s \. >[-]-R+[[>+<-]<[>+<-]<]>+[->>+]<[>+>>-<L+>R+<<<-]>[<+>-]+< g
1s .* R&<R+> 
2s , ,[,]>,<L[[>]R<+L[<]>-]>[>]R+< g
s L <[<<]< g
s R >>[>>] g

For flavors with EOF = 0, cells left of start disallowed, 8-bit wrapping cells.

Expects program A on the first line and B on the second line.

Try it online

This uses 2-cell nodes to simulate the tapes of A and B, with A's output occupying contiguous cells to the left of the leftmost node.

Alternative 173-byte solution:

1i>>
s > >[-]+> g
s < << g
1s \. >[-]-[>>]+[[>+<-]<[>+<-]<]>+[->>+]<[>>>-<<+[<<]<+>>>[>>]+<<<-]>[<+>-]+< g
1a>[>>]+>
2s , ,[,]>,<<[<<]<[[>]>>[>>]<+<[<<]<[<]>-]>[>]>>[>>]+< g

Try it online

Originally my design was based on a doubly infinite tape, which required significantly more work to move left (moving data when passing beyond the leftmost cell previously encountered) and to transition from A to B (clearing the data instead of just traveling past the rightmost cell previously encountered).

Thanks to Sylwester and Dorian for tricks and ideas.

Mitch Schwartz

Posted 2018-07-17T03:29:06.730

Reputation: 4 899

This looks great. Unfortunately it fails on the first test. Program A ,[..,] and program B ,[...,]. – Dorian – 2018-07-19T18:12:24.540

Oh, this is a silly oversight on my part, I hurried too much. It is fixable but I should delete it for now. – Mitch Schwartz – 2018-07-19T18:28:57.093

@Dorian It should be fixed now. (I'll keep looking it over.) Thanks for pointing out the mistake, and sorry for the inconvenience. – Mitch Schwartz – 2018-07-19T18:37:56.770

I'm aware that some bytes can be saved by e.g. having s/x/>>/g at the very end, but I'm more interested in improvements that will shorten the output for now. – Mitch Schwartz – 2018-07-19T18:43:08.900