9
\$\begingroup\$

Introduction

Alice is a 2-d language by Martin Ender which has two different execution modes, cardinal and ordinal. When the instruction pointer passes through a mirror (either / or \), it switches from one mode to the other one.

In this challenge we will focus on ordinal mode, where commands operate on strings and the instruction pointer moves diagonally, bouncing against the edges of the code.

Simple programs operating only in ordinal mode can be written in a quite compact style, like in the following example:

/fbd/
@aec\

Here the IP starts in cardinal mode from the first cell going east, passes through the first mirror and starts moving diagonally and bouncing, executing commands a, b, and c. It then encounters the north-east mirror which makes it go south towards the other mirror and then start bouncing back towards the west, encountering commands d,e,f, and finally @, which terminates the program.

This kind of structure is quite compact, but it's not easy to write and maintain (adding a single command might force us to reorder most of the code!), so I'd like you to help me with formatting.

The task

Given a sequence of commands, where each command is a single printable ASCII character, reorder them on two lines so that the first half of the sequence can be read starting from the first character of the second line and then moving always diagonally towards the right, while the second half can be read taking the remaining characters from right to left. Don't worry about mirrors and the termination symbol, I'll add them myself.

So, for example, given input abcdef you should output

fbd
aec

In case the input is of odd length, you should add a single space (which is a noop in Alice) anywhere, as long as the sequence of commands encountered remains the same. You can also choose to output two lines differing in length by one character, in which case the shorter one is considered as having a single space at the end.

Rules

This is , the shortest answer, in bytes, wins!

  • You may input/output via any of the default input/output methods
  • Input consists of a single line of printable ASCII characters
  • A single trailing newline is permitted in the output
  • Some outputs of your program may not have a completely correct behavior when run as Alice programs (e.g. if the padding space is inserted inside a string literal). You don't have to concern yourself with these situations
  • Standard loopholes are forbidden

Test cases

--Input
abcdef
--Output
fbd
aec

--Input
123
--Output
 2
13
OR
31
 2
OR
3
12
OR
32
1

--Input
O
--Output
O

OR

O

--Input
"Hello, World!"o
--Output
oH!lloo 
""edlr,W

--Input
i.szR.szno
--Output
o.zz.
inssR

--Input
"  ^^} .~[}.~~[}{~~{}[^^^^.""!}"r.h~;a*y'~i.*So
--Output
o *^i}'.*[;.h~r}}~"{.[^
"S .^~ y~a}~~.["{!~"}^^^
(Odd length, your solution may be different)
\$\endgroup\$
0

4 Answers 4

12
\$\begingroup\$

Alice, 28 bytes

/mY. zm~wZ.k;
\I;'!*?RR.OY@/

Try it online!

If the input length is odd, this puts the padding space at the end of the linearised program, which ends up being the first character of the output.

Leo wrote an Ordinal formatter in Alice a few days ago. After adding support for odd-length inputs and then removing some stuff that wasn't necessary for this challenge, we ended up at 28 bytes. I wanted to try a slightly different approach, which is this answer. Unfortunately, it just ended up tying 28 bytes, but at least this way I can post my own solution and let Leo post his original algorithm.

This does use Leo's really clever idea to split a string in half with ..Y;m;.!z?~.

Explanation

Let's assume that the input has even length (because we'll just pad it with a space if it doesn't). The pattern is a bit easier to see if we use 0123456789 as the code. The required output would be:

91735
08264

So the first line contains all odd positions of the input and the second line all the even inputs. Furthermore, if we reverse the odd positions, then the lines itself are both the first half (possibly longer) interleaved with the reverse of second half.

So the basic idea is:

  • Separate input into odd and even positions.
  • Pad the odd positions with a space if necessary.
  • Reverse the odd positions.
  • Then twice: halve the current string, reverse the second half, interleave both halves, print with trailing linefeed.

As for the code, this looks a lot like the kind of layout we're producing in this challenge, but it's subtly different: when the IP hits the / at the end of the code it gets reflected east, not south. Then, while in Cardinal mode, the IP will wrap around to the first column. The \ there re-enters Ordinal mode, so that the second half of the code doesn't go from right to left here, but from left to right as well. This is beneficial when working with the return address stack, because it doesn't store information about the IP's direction. This lets us save a few bytes because the IP will move in the same (horizontal) direction on both w and k.

The linearised code is this:

IY' *mRw..Y;m;.!z?~RZOk@

Let's go through it:

I       Read one line of input.
Y       Unzip. Separates the string into even and odd positions.
' *     Append a space to the odd half.
m       Truncate: discards characters from the longer of the two
        strings until they're the same length. So if the input
        length was even, appending a space will make the odd half
        longer and this discards the space again. Otherwise, the
        space just padded the odd half to the same length as the
        even half and this does nothing.
R       Reverse the odd half.
w       Push the current IP address to the return address stack.
        The purpose of this is to run the following section
        exactly twice.

          This first part splits the current line in half, based
          on an idea of Leo's:
  ..        Make two copies of the current half.
  Y         Unzip one of the copies. The actual strings are irrelevant
            but the important part is that the first string's length
            will be exactly half the original string's length (rounded up).
  ;         Discard the potentially shorter half.
  m         Truncate on the original string and its even half. This shortens
            the original string to the first half of its characters.
  ;         Discard the even half, because we only needed its length.
  .!        Store a copy of the first half on the tape.
  z         Drop. Use the first half to discard it from the original string.
            This gives us the the second (potentially shorter half).
  ?         Retrieve the first half from the tape.
  ~         Swap it so that the second half is on top.
          The string has now been split in half.
  R       Reverse the second half.
  Z       Zip. Interleave the two halves.
  O       Print the result with a trailing linefeed.

k       Pop an address from the return address stack and jump back there.
        The second time we reach this, the return address stack is empty,
        and this does nothing.
@       Terminate the program.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I'll have to post another challenge for this new layout you came up with! :D Very nice, I think I'll start using it even when I don't use the return stack, it's easier to read both halves of the code from left to right \$\endgroup\$
    – Leo
    Commented May 24, 2017 at 10:02
4
\$\begingroup\$

Jelly, 23 22 bytes

-1 byte thanks to Leo (bottom-left may be the padding)

LḂ⁶ẋ;µṚ,µm2œs2U0¦ż/µ€Y

A full program printing the result (the monadic link returns a list of lists of lists of characters).

Try it online! or see a test suite.

How?

LḂ⁶ẋ;µṚ,µm2œs2U0¦ż/µ€Y - Main link: list of characters
L                      - length
 Ḃ                     - modulo 2
  ⁶                    - literal space character
   ẋ                   - repeat
    ;@                 - concatenate (swap @rguments) (appends a space if the input's length is odd)
      µ                - monadic chain separation, call that s
       Ṛ               - reverse s
        ,              - pair with s
         µ         µ€  - for €ach:
          m2           -   modulo 2 slice (take every other character)
            œs2        -   split into two "equal" chunks (first half longer if odd)
               U0¦     -   upend index 0 (reverse the second chunk)
                   /   -   reduce by:
                  ż    -     zip
                     Y - join with newlines (well just the one in this case)
                       - implicit print (mushes the sublists together)
\$\endgroup\$
0
1
\$\begingroup\$

Jelly, 15 bytes

œs2U2¦ṚZUJḤ$¦ZY

Try it online!

Takes quoted input.

Explanation:

œs2U2¦ṚZUJḤ$¦ZY Main link, monadic
œs2             Split into 2 chunks of similar lengths, last might be shorter
   U2¦          Reverse the 2nd chunk
      Ṛ         Swap the chunks
       Z        Transpose into chunks of length 2
        UJḤ$¦   Reverse the chunks at even indices (1-indexed)
             Z  Transpose into 2 chunks again
              Y Join by a newline
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 104 bytes

f=
s=>s.replace(/./g,(c,i)=>a[1&~i][i+i>l?l-i:i]=c,a=[[` `],[]],l=s.length-1|1)&&a.map(a=>a.join``).join`
`
<input oninput=o.textContent=f(this.value)><pre id=o>

Works by emulating the execution path and filling the commands in as it goes.

\$\endgroup\$
2
  • \$\begingroup\$ Seems like a nice idea, but I don't know enough about javascript to understand the algorithm you used... Could you add some explanation? \$\endgroup\$
    – Leo
    Commented May 24, 2017 at 21:55
  • \$\begingroup\$ @Leo I'm not sure how much more I can explain. As you know, the commands follow a zig-zag line from left to right and back left again. The 1&~i achieves the vertical zig-zag, while the i+i>l?l-i:i achieves the halfway mirror. Once all the commands have been entered into the desired execution positions, the array is then collected together to produce the desired result. \$\endgroup\$
    – Neil
    Commented May 24, 2017 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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