25
\$\begingroup\$

As a celebration of good old Notepad, we are going to treat carriage returns and line feeds as what they originally meant, rather than what they are (ab-)used for today.

Given a string consisting of printable ASCII plus line feeds (␊; LF; esc \n; hex 0A; dec 10) and carriage returns (␍; CR; esc \r; hex 0D; dec 13), cause Try It Online to show how the printable characters would be positioned if printed on a printer which takes those two control characters literally:

  1. upon a line feed, continue printing one line further down
  2. upon a carriage return continue printing from the left edge
  3. multiple consecutive carriage returns behave like a single carriage return

Due to modern devices having problems with overstriking, a run of one or more of carriage returns will, except for at the beginning of the input, never occur without at least one preceding and/or following line feed. However, two runs of carriage returns may be separated by a single line feed.

Any amount of additional trailing white space is acceptable, both on the right-hand side of any lines and below the entire text, as long as at least the amount of white space given in the input is preserved.

Examples (using \n and \r for line feed and carriage return)

Lorem ipsum dolor sit amet,

Lorem ipsum dolor sit amet,

consectetur adipiscing\nelit, sed

consectetur adipiscing
                      elit, sed

do eiusmod\r\ntempor incididunt\n\n ut labore

do eiusmod
tempor incididunt

                  ut labore

et dolore\n\rmagna \r\r\naliqua. Ut (notice the trailing spaces)

et dolore
magna          
aliqua. Ut

\nenim ad minim veniam,\n\r quis nostrud


enim ad minim veniam,
     quis nostrud

\rexercitation\r\n\rullamco laboris\n\r\nnisi ut aliquip ex\n\n\rea commodo consequat.\n\n

exercitation
ullamco laboris

nisi ut aliquip ex

ea commodo consequat.


\$\endgroup\$
9
  • 28
    \$\begingroup\$ Suggested answer: Notepad, 179712 bytes \$\endgroup\$
    – Etheryte
    May 9, 2018 at 8:57
  • 3
    \$\begingroup\$ @Nit :| notepad isn't TC \$\endgroup\$
    – ASCII-only
    May 9, 2018 at 8:58
  • 3
    \$\begingroup\$ Shame that TIO doesn't use a proper terminal, otherwise a nice shell winner would be stty -onlcr;cat. \$\endgroup\$ May 9, 2018 at 11:28
  • 1
    \$\begingroup\$ I'm having trouble entering the carriage-return characters into the "input" field of TIO. They just seem to get swallowed up (or converted into newlines) when pasting - is that my browser at fault, or is it TIO? \$\endgroup\$ May 9, 2018 at 13:09
  • 3
    \$\begingroup\$ @Adám Don't prohibit all outputs than TIO. Instead restrict programs to using certain terminal types, or to file output. Or require that output have the necessary spaces preceding text on new lines. \$\endgroup\$
    – mbomb007
    May 9, 2018 at 21:46

9 Answers 9

6
\$\begingroup\$

Charcoal, 10 bytes

UTFθ«ι≡ι⸿↑

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

UT

Disable right padding.

Fθ«

Loop over the input.

ι

Print the current character. This automatically handles \n (which Charcoal treats as \v in this context) but Charcoal translates \r into \r\n, so...

≡ι⸿

... check for an \r...

... and if so then move back up a line.

\$\endgroup\$
13
  • \$\begingroup\$ Shouldn't you remove the l flag from your TIO link? \$\endgroup\$
    – Adám
    May 9, 2018 at 14:14
  • \$\begingroup\$ @Adám What's to stop me pasting any gibberish into my answer and then linking to a suboptimal program? \$\endgroup\$
    – Neil
    May 9, 2018 at 14:15
  • \$\begingroup\$ I see. Maybe Charcoal should output the TIO link to stderr (Debug)? \$\endgroup\$
    – Adám
    May 9, 2018 at 14:23
  • \$\begingroup\$ @Adám I'll suggest that to@ASCII-only. \$\endgroup\$
    – Neil
    May 9, 2018 at 14:37
  • \$\begingroup\$ @Neil fixed, I think? \$\endgroup\$
    – ASCII-only
    May 9, 2018 at 22:30
5
\$\begingroup\$

Ruby, 24 17 bytes

->s{s.tr $/,"\v"}

Try it online!

It does not work on TIO, but works on the Linux console.

\$\endgroup\$
7
  • \$\begingroup\$ You can drop the space between tr " I think. \$\endgroup\$ May 9, 2018 at 9:35
  • \$\begingroup\$ Uh, I didn't think of this solution, it may just work for any language to change all \ns into \v when run in a Linux console. \$\endgroup\$
    – Adám
    May 9, 2018 at 9:37
  • \$\begingroup\$ @Adám What about some languages change nothing and works in a DOS console? \$\endgroup\$
    – tsh
    May 9, 2018 at 9:44
  • \$\begingroup\$ I'm sorry for changing the spec mid-challenge, but to make the challenge more interesting and less subject to trivial answers, I now require proper output on TIO. \$\endgroup\$
    – Adám
    May 9, 2018 at 9:54
  • 5
    \$\begingroup\$ Changing the spec: I don't think it's fair. but I will delete my answer if I have to. \$\endgroup\$
    – G B
    May 9, 2018 at 13:50
4
\$\begingroup\$

Java 10, 211 207 206 bytes

s->{var a=s.replace("\r\n","\n\r").split("(?<=\n)");int i=0,p=0,j;for(var x:a){for(j=x.charAt(0)<14?0:p;j-->0;x=" "+x);j=(a[i++]=x.replace("\r","")).length()-1;p=x.matches("\\s+")?p:j;}return"".join("",a);}

Try it online.

Explanation:

s->{                      // Method with String as both parameter and return-type
  var a=s.replace("\r\n","\n\r")
                          //  Replace all "\r\n" with "\n\r"
        .split("(?<=\n)");//  Create String-array split by "\n",
                          //  without removing the trailing "\n" delimiter
  int i=0,                //  Index integer
      p=0,                //  Previous line-length, starting at 0
      j;                  //  Temp integer
  for(var x:a){           //  Loop over the String-array
    for(j=x.charAt(0)<14?0//   If the current line starts with either '\r' or '\n':
        0                 //    Prepend no spaces
       :                  //   Else:
        p;j-->0;x=" "+x); //    Prepand `p` amount of spaces for the current item
    j=(a[i++]=x.replace("\r",""))
                          //   Remove all "\r" from the current line
       .length()-1;       //   Set `j` to the current line-length (minus the trailing '\n')
    p=x.matches("\\s+")?  //   If the current line only contains '\r', '\n' and/or spaces:
       p                  //    Leave `p` unchanged
      :                   //   Else:
       j;}                //    Change `p` to this line-length minus 1
  return"".join("",a);}   //  Return the String-array joined together

Old answer before the challenge was changed 151 148 bytes:

s->{String a[]=s.replace("\r\n","\n\r").split("(?<=\n)"),r="";int p=0,i;for(var x:a){for(i=p;i-->0;r+=" ");i=x.length()-1;p=i<1?p:i;r+=x;}return r;}

Explanation:

s->{                            // Method with String as both parameter and return-type
  String a[]=s.replace("\r\n","\n\r") 
                                //  Replace all "\r\n" with "\n\r"
              .split("(?<=\n)"),//  Create String-array split by "\n",
                                //  without removing the trailing "\n" delimiter
         r="";                  //  Result-String, starting empty
  int p=0,                      //  Previous line-length, starting at 0
      i;                        //  Index (and temp) integer
  for(var x:a){                 //  Loop over the String-array
    for(i=p;i-->0;r+=" ");      //   Append `p` amount of spaces to the result
    i=x.length()-1;p=i<1?p:j;   //   If the current line is not empty:
                                //    Replace `p` with the length of this current line
    r+=x;}                      //   Append the current item
  return r;}                    //  Return the result-String

Doesn't work on TIO, does work on Windows Command Prompt:

enter image description here

\$\endgroup\$
0
3
\$\begingroup\$

JavaScript (Node.js), 85 bytes

s=>s[R='replace'](/(.*)([\n\r]+)/g,(_,t,b)=>t+b[R](/\r/g,_=>s='',s=t[R](/./g,' '))+s)

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Python 2, 150 128 122 104 103 bytes

def f(s):
 i=n=0;l=''
 for c in s:l,n,i=[l,l+c,l+' '*i*n+c,n,1,0,0,i,i+1]['\r\n'.find(c)%3::3]
 print l

Try it online!


Saved:

  • -1 byte, thanks to Lynn
\$\endgroup\$
1
  • \$\begingroup\$ It seems l,n,i=[l,l+c,l+' '*i*n+c,n,1,0,0,i,i+1]['\r\n'.find(c)%3::3] is just barely shorter. \$\endgroup\$
    – Lynn
    May 9, 2018 at 10:44
3
\$\begingroup\$

C (gcc), 100 94 bytes

b,c,d;f(char*s){for(b=13;b;b=*s++)b==13?c=d=0:b-10?d=!printf("%*c",++d,b),++c:putchar(b,d=c);}

Assumes ASCII coding ('\r'==13, '\n'==10); adjust to suit on other systems.

Try it online! (requires Javascript)

Readable version

int c = 0;
int d = 0;

f(char*s)
{
    for (;*s;++s) {
        switch (*s) {
        case'\r':
            c = d = 0;
            break;
        case'\n':
            d = c;
            putchar(*s);
            break;
        default:
            printf("%*s%c", d, "", *s);
            d = 0;
            ++c;
        }
    }
}

c is the current column position; d is the number of spaces that must be inserted before a printable character. Both are assumed to be zero on entry to the function.

Test program

int main(int argc, char **argv)
{
    char s[1024];
    if (argc <= 1)
        while (fgets(s, sizeof s, stdin))
               f(s);
    else
        for (int i = 1;  i < argc;  ++i)
            f(argv[i]);
}
\$\endgroup\$
5
  • \$\begingroup\$ chars are just small ints, they should be interchangeable (in theory). Maybe gcc will do an implicit cast \$\endgroup\$
    – Stan Strum
    May 9, 2018 at 18:51
  • \$\begingroup\$ 91 bytes. \$\endgroup\$ May 11, 2018 at 14:37
  • \$\begingroup\$ By the way, I do not think that per our consensus you are allowed to reset your global variables c,d. Your function should -- without other cleanup code -- be able to run multiple times. Thus you most likely need to add a c=d=0. \$\endgroup\$ May 11, 2018 at 14:40
  • \$\begingroup\$ For your interest, the relevant meta post. \$\endgroup\$ May 14, 2018 at 11:01
  • \$\begingroup\$ It's now a reusable function. \$\endgroup\$ May 14, 2018 at 11:35
2
\$\begingroup\$

Python 3, 101 94 bytes

Based on TFeld's answer.

def f(s):
 i=n=0
 for c in s:k='\r\n'.find(c);a=k&1;print(end=-k*' '*i*n+c*a);n=k>0;i=i*a-k//2

Try it online!


Ungolfed

def f(s):
  i=0  # position of the cursor
  n=0  # was the last character LF?
  for c in s:        # iterate over the input
    k='\r\n'.find(c) # k := 0 for CR, 1 for LF and -1 for every other character
    a=k&1            # as (-1)&1 == (1)&1 == 1, this is a := abs(k)
    print(end=-k*' '*i*n+c*a) # If c is a normal character (k == -1) and the last character was LF, 
                              # print leading spaces. If c is not CR, print it
    n=k>0            # n := True if c is LF, False otherwise
    i=i*a-k//2       # If c is either a newline or a printable character (a == 1),
                     # keep the cursor's position and increment it for a printable character ((-1)//2 == -1)
\$\endgroup\$
2
\$\begingroup\$

Clean, 92 91 bytes

-1 thanks to Laikoni!

Note: \ in \r is omitted from bytecount as Linux CG handles literal \r and \ns.
Note: Windows CG requires \n and \r be escaped, so +3 if it has to run on Windows.

import StdEnv
?n['\r':t]= ?0t
?n['
':t]=['
':spaces n]++ ?n t
?n[h:t]=[h: ?(n+1)t]
?_ e=e

?0

Try it online!

A partial application of ? :: Int [Char] -> [Char] with 0 as the initial first argument. This descends through each character keeping track of how many traversed, the count resets when it encounters a carriage return and when it encounters a newline it adds spaces equal to the number of characters traversed at that point.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think ?_[]=[] can be ?_ e=e. \$\endgroup\$
    – Laikoni
    May 11, 2018 at 7:02
  • \$\begingroup\$ @Laikoni You're right. I swear I've missed exactly that same thing a dozen times by now. \$\endgroup\$
    – Οurous
    May 11, 2018 at 7:03
1
\$\begingroup\$

Haskell, 93 87 bytes

l=0#0
(n#x)(t:r)|t=='\n'=t:(n#1)r|t=='\r'=l$r|m<-n+1=(' '<$[1..n*x])++t:(m#0)r
(_#_)e=e

Try it online!


Pretty straightforward solution. # is an infix function that recursively creates the output one character at a time while keeping a character position counter (n) and flag for when to add spaces after a newline (x).

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can define an infix function instead of c, use l$r instead of c 0 0r and c _ _ e=e (or rather (_#_)e=e). \$\endgroup\$
    – Laikoni
    May 11, 2018 at 7:15
  • \$\begingroup\$ All together 87 bytes: Try it online! \$\endgroup\$
    – Laikoni
    May 11, 2018 at 7:15
  • \$\begingroup\$ @Laikoni Thank you, I didn't realize you could use that infix trick with that many parameters. \$\endgroup\$
    – aoemica
    May 11, 2018 at 14:02

Your Answer

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

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