# A Change in Perspective

In this challenge you will write a piece of text which when viewed from two different angles will create two different programs.

Your string as viewed from above must take a string containing only characters ASCII 10, 32 - 126 and output it as viewed from above. Additionally your program when viewed from the left must take a string containing only characters ASCII 10, 32 - 126 and output it as viewed from the left.

A string viewed from above will be the first non-space character in every column of the string, or a space if no such character exists, in the order of the columns.

Here is a Haskell program that implements this:

stitchZip (' ' : b) (c : d) = c : stitchZip b d
stitchZip (a : b) (c : d)   = a : stitchZip b d
stitchZip [] x = x
stitchZip x [] = x

main = getContents >>= (putStr . foldr1 stitchZip . lines)


Try it online!

A string viewed from the left will be the first non-space character in every row of the string, or a space if no such character exists, in the reverse order of the rows. We reverse the order of the rows since our left hand would be towards the bottom of the string.

Here is a Haskell program that implements this:

stitch ' ' y = y
stitch x y = x

main = getContents >>= (putStr . reverse . map (foldl stitch ' ') . lines)


Try it online!

Your program may use characters outside of that ASCII range, but for layout purposes all characters (other than newlines) are considered to have a width of 1. As a side effect of how the views work, your programs cannot have newlines in them (although your string almost certainly will).

## Scoring

Your score will be the number of non-space characters in your submission plus the number of space characters that appear in the two programs.

For example if your program were:

sc  e ex mp e
g
a
r

d
l
o


you would score 16 since there are 14 non whitespace characters in the submission, and each program (score example and old rags) has 1 space.

Your goal is to have as low a score as possible.

• Had trouble locating what the programs were supposed to do, might want to add a header of somesort indicating the section describing the desired output of the two programs. Additionally, if a program wanted to contain a newline, how would that be represented (if even possible)? – Draco18s no longer trusts SE Oct 15 '19 at 17:33
• Maybe that could be achieved by moving "For this challenge..." up above "The first program...", making the first occurrences of each of "viewed from above" and "viewed from the left" bold (or otherwise emphasised), and titling the "The first program..." as "Viewed From Above" & similarly titling "The second program..." as "Viewed From The Left"? – Jonathan Allan Oct 15 '19 at 17:39
• @Draco18s I've reordered things as suggested by JonathanAllan. As far as newlines go "As a side effect of how the views work, your programs cannot have newlines in them". – Wheat Wizard Oct 15 '19 at 17:58

# Jelly, score 9 + 0 = 9

 Z
⁶
€
ɗ
o
Ḣ
ḟ
Ṛ
Ỵ


From the top:

ỴZḟḢoɗ€⁶


Try it online! (or see it self-operate)

From the side:

ỴṚḟḢoɗ€⁶Z


Try it online! (or see it self-operate)

### How?

Ỵ Z|Ṛ ḟḢoɗ€⁶ [Z]  - Link list of characters:
Ỵ                 - split at newline characters
Z               - | top: transpose to get columns
Ṛ             - | side: reverse the lines
⁶      - set the right argument to a literal space character
€       - for each (x = column (top) OR line (side)):
ɗ        -   last three links as a dyad - i.e. f(x, space)
ḟ           -     filter discard (spaces from x)
Ḣ          -     pop & yield the head (first remaining character or 0 if none left)
o         -     logical OR (with space character) (replace a 0 with a space)
- | top: no code remaining
Z   - | side: transpose (at this point a no-op since we have a flat list)


# Pyth, 15 score

           z
.T.
;
d
+
!
\
D
<
h
m
s
_


The two programs are:

smh<D\!d.T.z


Try it online!

_smh<D\!+d;.z


Try it online!

I attempted to make the code as similar as possible between the two programs, hence a few inefficiencies in each. Both programs filter out unwanted spaces by sorting the rows/columns by if the character is less than a !. Since the sorts are stable this preserves the rest of the line. The rest of the programs are fairly straightforward.

The main save that I think could be made for this approach would be to make the code that converts from empty lines to a space more similar. I haven't found a way to do that that isn't wastefully long.

# Charcoal, score 22 18

              κ→
Ｐ
!
Ｋ
Ｋ
‹
¿
ι
Ｆ
←
«Ｊ⁰¬¹
Ｓ
Ｗ


Note: This is designed for a pleasant input format i.e. at least one character on each line, then a completely empty line to terminate the input. Replace Ｗ with Ｆ and Ｓ with Ａ for a JSON-like input format which allows for empty lines. Additionally, the variable width characters that Charcoal uses (even in a fixed width font, sigh...) mean that the columns don't quite line up nicely. Check the output of the sample link for the expected result.

From the top: Try it online! Link is to verbose version of code. Explanation:

ＷＳ«


Ｊ⁰¬¹


Start at the top left of the canvas each time.

Ｆι


Loop through the characters on each line.

¿‹ＫＫ!κ→


Output the current character unless it would overwrite something already there in which case simply move right.

From the side: Try it online! Link is to verbose version of code. Explanation:

ＷＳ«


←


Move left for each character, thus reversing the output.

Ｆι


Loop through the characters on each line.

¿‹ＫＫ!Ｐκ


Output the current character without moving the cursor unless it would overwrite something already there.

# Wolfram Language (Mathematica), score 31 + 2 = 33

                        &
)
#
@
/
]
&
2
#
>
-
"

"
.
/
#
[
d
l
o
F
(
@
e
s
r
e
v
e
R


From the top:

Fold[#/." "->#2&]/@(#)&


Try it online!

From the side:

Reverse@(Fold[#/." "->#2&]/@#)&


Try it online!

Takes a matrix of characters as input. If the rows are not guaranteed to have equal length, add another $$\18+2\times2=22\$$ by replacing # with (PadRight@#/. 0->" ").

If input must be a list of strings, add $$\11\$$ by replacing # with Characters@#

If input must be a single string, add $$\29\$$ instead by replacing # with Characters[#~StringSplit~"\n"]

In these cases, if lines are not guaranteed to have equal length, add an additional $$\15\$$ instead of 22 by replacing Characters with Characters@StringPadRight.

# 05AB1E (legacy), score: 10 (10 non-space bytes + 0)

  ø
q
н
«
ð
Û
ð
ε
R
B
.


Outputs as a list of characters.

Top view: .BøεðÛð«нq
Try it online.

Side view: .BRεðÛð«нqø
Try it online.

EDIT: I now notice it's very similar to the Jelly answer, although I've came up with this independent.. Great minds think alike I guess.

Explanation:

Uses the legacy version of 05AB1E because the zip/transpose builtin ø works on a list of strings (whereas the new version only works on 2D lists).

.B           # Split the (implicit) input-string by newlines,
# and at the same time append spaces to make all lines of equal length
ø          # Top view: Zip/transpose the lines; swapping rows/columns
R          # Side view: Reverse the list of lines
ε         # Map each string to:
ðÛ       #  Remove all leading spaces
ð«     #  Append a space
н    #  Only leave the first character
q   #  And exit the program (although it still finishes the map first)
#  Top view: nothing more
ø  #  Side view: no-op since we've already stopped the program with q
# (after the map, the resulting character-list is output implicitly)


# APL (Dyalog Unicode), score 11 + 2 = 13

         1⍉
⍤
)
'

'
∘
~
⊃
(
⌽


Top view:

(⊃~∘' ')⍤1⍉


Left view:

⌽(⊃~∘' ')⍤1


Try it online!

### How they work

[⌽] (⊃~∘' ')⍤1 [⍉]
⍉   Top view only: Transpose the given char matrix
(      )⍤1      On each row:
⊃~∘' '         Remove all spaces and take the first char
⌽                  Left view only: Reverse the string


The lack of one-byte shortcut for a space adds 3 to the score; otherwise it'd be a tie with 05AB1E.

# Python 3, 98 + 9 + 5 = 112


)).strip()
]
-
:
:
[
)
'
n
\
'
(
t
i
l
p
s
.
s

n zip(* i+' '*len(s)for i in
i

i

r
o
f
'

'
r
o
]
1
:
[
)
(
p
i
r
t
s
.
i))
(
j(j
:
n
i
o
j
.
'
'
=
j
,
s

a
d
b
m
a
l


Top view:

lambda s,j=''.join:j(j(i).strip()[:1]or' 'for i in zip(*[i+' '*len(s)for i in s.split('\n')])).strip()


Left view:

lambda s,j=''.join:j(i.strip()[:1]or' 'for i in s.split('\n')[::-1])


Try it online!