10
\$\begingroup\$

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.

\$\endgroup\$
  • 7
    \$\begingroup\$ Shortest code in each language win and Shortest Brainfuck solution will be accepted are two different winning criteria. \$\endgroup\$ – Mego Jul 17 '18 at 3:58
  • 2
    \$\begingroup\$ @Mego I meant if you answer in brainfuck and you win, you're accepted \$\endgroup\$ – l4m2 Jul 17 '18 at 6:22
  • 1
    \$\begingroup\$ Also. 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. \$\endgroup\$ – Sylwester Jul 21 '18 at 21:42
  • 1
    \$\begingroup\$ The 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. \$\endgroup\$ – Mitch Schwartz Jul 21 '18 at 22:13
  • 1
    \$\begingroup\$ Maybe I'm completely misunderstanding the challenge, but test cases #3 and #4 seem to clash. \$\endgroup\$ – DJMcMayhem Jul 27 '18 at 16:53
7
\$\begingroup\$

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 ,[,]>,<<[<<]<[[>]>>[>>]<+<[<<]<[<]>-]>[>]>>[>>]+<*

\$\endgroup\$
  • \$\begingroup\$ ,[>,]<[.<]?,[...,] input 12345 returns 111, even with enough > before? \$\endgroup\$ – l4m2 Jul 20 '18 at 10:07
  • \$\begingroup\$ @l4m2 Hmm, it's working for me on TIO. (,[>,]<[.<] is not valid but >,[>,]<[.<] is.) \$\endgroup\$ – Mitch Schwartz Jul 20 '18 at 10:14
  • \$\begingroup\$ So what's your "it allows going to the left of the start cell"? \$\endgroup\$ – l4m2 Jul 20 '18 at 10:35
  • 1
    \$\begingroup\$ So 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? \$\endgroup\$ – Sylwester Jul 20 '18 at 13:36
  • 1
    \$\begingroup\$ For 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. \$\endgroup\$ – Mitch Schwartz Jul 20 '18 at 15:08
5
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – Dorian Jul 18 '18 at 6:10
5
\$\begingroup\$

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
]
\$\endgroup\$
  • 1
    \$\begingroup\$ Why no output? \$\endgroup\$ – l4m2 Jul 19 '18 at 12:42
  • \$\begingroup\$ @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. \$\endgroup\$ – Dorian Jul 19 '18 at 12:52
4
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ 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? \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 21:53
  • \$\begingroup\$ 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.) \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 22:24
  • \$\begingroup\$ @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. \$\endgroup\$ – Sylwester Jul 19 '18 at 22:36
  • \$\begingroup\$ 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. \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 23:16
  • \$\begingroup\$ 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... \$\endgroup\$ – Mitch Schwartz Jul 20 '18 at 6:43
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ This looks great. Unfortunately it fails on the first test. Program A ,[..,] and program B ,[...,]. \$\endgroup\$ – Dorian Jul 19 '18 at 18:12
  • \$\begingroup\$ Oh, this is a silly oversight on my part, I hurried too much. It is fixable but I should delete it for now. \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 18:28
  • \$\begingroup\$ @Dorian It should be fixed now. (I'll keep looking it over.) Thanks for pointing out the mistake, and sorry for the inconvenience. \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 18:37
  • \$\begingroup\$ 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. \$\endgroup\$ – Mitch Schwartz Jul 19 '18 at 18:43

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.