28
\$\begingroup\$

EDIT I modified the wording of the rules to make some things which were implicit more explicit. I also added some emphasis to clear up some points of apparent confusion, and explicitly defined the option of making a standalone program instead of a function.

The goal here is to make a function that takes a text file (or string) and transposes it so that lines become columns and vice versa.

Example:

I am a text.
Transpose me.
Can you do it?

Results in:

ITC
 ra
aan
mn
 sy
apo
 ou
ts
eed
x o
tm
.ei
 .t
  ?

The rules:

  • You are allowed to assume that the only whitespace characters used are " " and "\n" and that there is no trailing whitespace on any line.
  • You may assume that the file is ASCII. Which endline marker you want to use is up to you.(CRLF or LF). It must work correctly on the example, but it should also work on any input that satisfies the above assumptions.
  • You might have to insert spaces (as in the example) where there were none in order to keep the columns in line.
  • Your result must not have trailing whitespace on any line.
  • The final newline character(for the last line) is optional.
  • It should be either a function or a complete program. If your function accepts a string, then it should return the results as a string. If it accepts a filename, then you return the name of the file where you saved the result. You are additionally allowed to write a complete program that accepts input from STDIN and outputs the correct result to STDOUT; if you do this, you must not output anything to STDERR.
  • Shortest procedure wins, but I will upvote any answer I like.

Based on the rules, the output on the example is either 53 or 52 bytes long (for LF newlines) depending on whether the final newline is included or not.

Note: It is not a specific requirement, but if your function, when run twice successively is not identical to the original(the final newline might be differ, and any empty lines at the end of the file will be deleted), then you are probably breaking one of the rules.

\$\endgroup\$
  • \$\begingroup\$ I decided to remove the prohibition on language built-ins. \$\endgroup\$ – Tim Seguine Jan 3 '14 at 13:27
  • \$\begingroup\$ I edited to clarify the trailing whitespace condition. \$\endgroup\$ – Tim Seguine Jan 3 '14 at 14:16
  • \$\begingroup\$ Are you asking for a function? Is it acceptable to accept a string from STDIN and print the correct output to STDOUT? \$\endgroup\$ – Justin Jan 3 '14 at 22:56
  • \$\begingroup\$ @Quincunx Yes, I am accepting that as a "function".I will alter the rules to be explicit on that point. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:30
  • \$\begingroup\$ The text transpose function cannot be an involution unless you allow for trailing ws. Example: "a*c\ndef\n" ->TT-> "a*\ncd\nef\n" ~ "a\ncd\nef\n" ->TT-> "acd\nef\n", where *=ws \$\endgroup\$ – Emanuel Landeholm Mar 19 '14 at 5:28

47 Answers 47

2
\$\begingroup\$

Japt, 6 bytes

y mx1R

Try it
Run it twice - returns original string


Explanation

y

Transpose the input

m  R

Map over each line

x1

Trim right

\$\endgroup\$
4
\$\begingroup\$

J (31 40)

f=:3 :';(,&LF@dlb&.|.)&.><"1|:>LF cut y'

This is a function that takes a string, and returns a string (i.e. a character vector with linefeeds inserted in the right places, and not a matrix.)

Edit: no trailing whitespace on any line.

Test:

   f=:3 :';(,&LF@dlb&.|.)&.><"1|:>LF cut y'

   string=:stdin''
I am a text.
Transpose me.
Can you do it?
^D

   $string
42
   $f string
53
   f string
ITC
 ra
aan
mn
 sy
apo
 ou
ts
eed
x o
tm
.ei
 .t
  ?
\$\endgroup\$
  • \$\begingroup\$ I hope you noticed I removed the prohibition for built-ins. \$\endgroup\$ – Tim Seguine Jan 3 '14 at 13:43
  • \$\begingroup\$ @Tim: Yes, otherwise I wouldn't have posted this. \$\endgroup\$ – marinus Jan 3 '14 at 13:44
  • \$\begingroup\$ Is the trailing whitespace rule written unclearly? You seem to have more characters than I expected. \$\endgroup\$ – Tim Seguine Jan 3 '14 at 13:55
  • \$\begingroup\$ How many characters should I have? The last characters on the string are ?\n. \$\endgroup\$ – marinus Jan 3 '14 at 14:02
  • 1
    \$\begingroup\$ @Tim: I could only get it to 44 in APL. Main reason is that APL doesn't provide either cut or dlb by default and writing them myself takes a bunch of characters even in APL. \$\endgroup\$ – marinus Jan 5 '14 at 0:29
4
\$\begingroup\$

Ruby 111

Golfed:

def f t;s=t.lines;s.map{|l|l.chomp.ljust(s.map(&:size).max).chars}.transpose.map{|l|l.join.rstrip+?\n}.join;end

Ungolfed:

def transpose_text(text)
  max_length = text.lines.map(&:size).max
  text.lines.map do |line|
    line.chomp.ljust(max_length).chars
  end.transpose.map do |chars|
    chars.join.rstrip + "\n"
  end.join
end

Ruby has an array transpose function, so this simply pads the lines out, turns them into an array of characters, uses Ruby's Array#transpose function, then turns the array of characters back into lines.

Golfing it was simply using single-character identifiers, removing spaces, using a temporary for text.lines, and putting the calculation for max_length inline (there are no points for efficiency).

\$\endgroup\$
  • \$\begingroup\$ Nice. You can strip out one more character by replacing "\n" with ?\n. \$\endgroup\$ – O-I Jan 3 '14 at 21:04
  • \$\begingroup\$ Also, the .to_a is superfluous. You can gain another 5 characters there. \$\endgroup\$ – O-I Jan 3 '14 at 21:43
  • \$\begingroup\$ @O-I Thanks, I owe you six characters. I dashed this off at work, which uses 1.9.3. The to_a is required in 1.9.3, but not in 2.0. \$\endgroup\$ – Wayne Conrad Jan 3 '14 at 22:29
  • \$\begingroup\$ I see. Good to know. Consider us even for showing me a few String methods in Ruby I should be using more often. Cheers! \$\endgroup\$ – O-I Jan 4 '14 at 0:19
  • 2
    \$\begingroup\$ Some of the code golf challenges have renewed my interest in learning ruby. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 13:29
4
\$\begingroup\$

R, 171

function(e){p=strsplit
x=t(plyr::rbind.fill.matrix(lapply(p(p(e,"\n")[[1]],""),t)))
x[is.na(x)]=" "
cat(apply(x,1,function(y)sub(" *$","",paste(y,collapse=""))),sep="\n")}

Usage example:

text <- "I am a text.
Transpose me.
Can you do it?"


(function(e){p=strsplit
x=t(plyr::rbind.fill.matrix(lapply(p(p(e,"\n")[[1]],""),t)))
x[is.na(x)]=" "
cat(apply(x,1,function(y)sub(" *$","",paste(y,collapse=""))),sep="\n")})(text)

ITC
 ra
aan
mn
 sy
apo
 ou
ts
eed
x o
tm
.ei
 .t
  ?

Trailing whitespace is removed.

\$\endgroup\$
4
\$\begingroup\$

Python 2.7 (97 79 94 90)

EDIT: Missed the function requirement;

I'm fairly sure this will be improved on since I'm sort of a beginner here, but to start with;

c=lambda a:'\n'.join(''.join(y or' 'for y in x).rstrip()for x in map(None,*a.split('\n')))

The code uses a simple split to split the string into a vector of rows. It then uses map with a function value as None (the unity function) and the splat operator to transpose and pad the vector (similar functionality to zip_longest in Python3)

The rest of the code just maps None to space, trims and reassembles the matrix to a single string again.

>>> a = 'I am a text.\nTranspose me.\nCan you do it?'
>>> c(a)                                                                            
'ITC\n ra\naan\nmn\n sy\napo\n ou\nts\need\nx o\ntm\n.ei\n .t\n  ?'
>>> len("""c=lambda a:'\n'.join(''.join(y or' 'for y in x).rstrip()for x in map(None,*a.split('\n')))""")
88
# (+2 since `\n` is considered by `len` to be a single char)
\$\endgroup\$
  • \$\begingroup\$ Not exactly compliant. It should be a function take takes a string and returns a string. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:50
  • \$\begingroup\$ @Tim Yes, missed that. Fixed now, thanks. \$\endgroup\$ – Joachim Isaksson Jan 4 '14 at 13:16
  • \$\begingroup\$ +1 you appear to be the shortest compliant python entry at the moment. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 13:23
  • \$\begingroup\$ Nice use of map. I keep looking for a place to use that... and you just beat me to it. ;) \$\endgroup\$ – boothby Jan 4 '14 at 19:26
4
\$\begingroup\$

Bash+coreutils+sed, 83

eval paste `sed 's/.*/<(fold -w1<<<"&")/'`|expand -t2|sed 's/\(.\) /\1/g;s/ \+$//'

fold and paste do the important work. The rest is just formatting.

Accepts input from stdin and outputs to stdout:

$ < tr.txt ./transposefile.sh
ITC
 ra
aan
mn
 sy
apo
 ou
ts
eed
x o
tm
.ei
 .t
  ?
$ < tr.txt ./transposefile.sh | ./transposefile.sh
I am a text.
Transpose me.?
Can you do it
$ 
\$\endgroup\$
  • \$\begingroup\$ You appear to be breaking the rule "Your result must not have trailing whitespace on any line." \$\endgroup\$ – Tim Seguine Mar 19 '14 at 9:56
  • \$\begingroup\$ @TimSeguine Oops I missed that one. I just fixed it in the latest edit. \$\endgroup\$ – Digital Trauma Mar 19 '14 at 16:56
3
\$\begingroup\$

C (278 bytes)

Edit: This actually breaks the rules, since it takes a filename in as an argument but writes to stdout. I'll edit it later to write to a file and then print the filename to stdout.

This is my first code golf ever, so have mercy. Some plain old C. Place the input in test.txt and let it run!

clang transpose.c -o transpose && ./transpose test.txt

#import <stdio.h>
#import <stdlib.h>
#import <string.h>

#define BUFFER_SIZE 1024

#define MAX(A,B) ((A)>(B)?(A):(B))

int main(int argc, char **argv) {
    char line[BUFFER_SIZE];

    FILE *f; int nLines, maxLen;

    f = fopen(argv[1], "r");
    while(!feof(f) && fgets(line, BUFFER_SIZE, f)) {
        nLines++;
        maxLen = MAX(maxLen, strlen(line));
    }
    fclose(f);

    for (int charPos = 0; charPos < maxLen; charPos++) {
        f = fopen(argv[1], "r");
        for (int linePos = 0; linePos < nLines; linePos++) {
            fgets(line, BUFFER_SIZE, f);
            printf("%c", charPos < strlen(line) && line[charPos] != '\xA' ? line[charPos] : ' ');
        }
        printf("\n");
        fclose(f);
    }

    return 0;
}

By using short variable names, removing gratuitous formatting, and allowing file handles to leak, and disabling all warnings this is reduced to 278 bytes. (Since this uses implicit imports, it may not link properly on all systems. Works on my machine!)

#import <stdio.h>
int main(int C,char**V){char L[1024];int A,B,D,I,J,*F=fopen(V[1],"r");while(!feof(F)&&fgets(L,1024,F)){A++;D=strlen(L);B=B>D?B:D;}for(I=0;I<B;I++){F=fopen(V[1],"r");for(J=0;J<A;J++)fgets(L,1024,F)&&printf("%c",I<strlen(L)&&L[I]!='\n'?L[I]:' ');printf("\n");}}
\$\endgroup\$
  • \$\begingroup\$ I think you can take advantage of implicit int to shorten some of your declarations, or is that illegal now? \$\endgroup\$ – Tim Seguine Jan 3 '14 at 15:51
  • \$\begingroup\$ Yeah, I'm using that in a later edit to not import stdlib.h or string.h. If I don't import stdio.h it segfaults on run. \$\endgroup\$ – wjl Jan 3 '14 at 15:59
  • \$\begingroup\$ To your edit comment on the rules: your other alternative is to accept input from stdin. I would consider that conforming as well. And also, I can't tell from a cursory glance: does it strip whitespace from the ends of lines in the transpose version? \$\endgroup\$ – Tim Seguine Jan 3 '14 at 16:09
  • \$\begingroup\$ Since I re-read the file multiple times to avoid storing in RAM, reading from stdio would probably be harder. :) I'm not sure what whitespace should be stripped. Right now I don't think it does any stripping at all, unfortunately. I'll have to work on that too. \$\endgroup\$ – wjl Jan 3 '14 at 16:18
  • \$\begingroup\$ You can declare A,B,D,I,J,*F as global variables, in order to avoid int keyword. Similarly, you can remove int from main declaration, and C argument. In C, int is optional in many places. \$\endgroup\$ – Konrad Borowski Jan 3 '14 at 16:44
3
\$\begingroup\$

AutoHotkey 210

f(i){
StringSplit,o,i,`n
m:=0
loop % o0 {
a:=A_index
if (t:=Strlen(p:=o%a%))>m
m:=t
StringSplit,l%a%,o%a%
}
loop % m {
a:=A_index,n:=""
loop % o0
n.=(j:=l%A_index%%a%)=""?" ":j
s.=Rtrim(n," ") "`n"
}
return s
}

Test

text=
(
I am a text.
Transpose me.
Can you do it?
)
msgbox % f(text)
\$\endgroup\$
  • \$\begingroup\$ I can't test this one, but it looks compliant \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:56
3
\$\begingroup\$

Ruby: 88 characters

(Posted because it's shorter then the other Ruby solutions. Not checked whether my code introduces anything new compared to those. If you already posted a Ruby solution and you feel this is mostly a copy of yours, please comment and I will retire my answer.)

f=->t{l=t.split$/;r=[""]*m=l.map(&:size).max;l.map{|l|m.times{|i|r[i]+=l[i]||" "}};r*$/}

Sample run:

irb(main):001:0> f=->t{l=t.split$/;r=[""]*m=l.map(&:size).max;l.map{|l|m.times{|i|r[i]+=l[i]||" "}};r*$/}
=> #<Proc:0x99a9e68@(irb):1 (lambda)>

irb(main):002:0> sample='I am a text.
irb(main):003:0' Transpose me.
irb(main):004:0' Can you do it?'
=> "I am a text.\nTranspose me.\nCan you do it?"

irb(main):005:0> puts f[sample]
ITC
 ra
aan
mn
 sy
apo
 ou
ts
eed
x o
tm
.ei
 .t
  ?
=> nil

irb(main):006:0> puts f[f[sample]]
I am a text.
Transpose me.
Can you do it?
=> nil
\$\endgroup\$
  • \$\begingroup\$ +1 You golfed it better in any case. \$\endgroup\$ – Tim Seguine Jan 17 '14 at 10:54
3
\$\begingroup\$

Bash, 124 bytes

D=`mktemp -d`;split -l1 - $D/;for F in $D/*;do grep -o . $F>$F+
done;paste $D/*+|sed -e's/\([^\t]\)\t/\1/g;s/\t/ /g;s/ *$//'

It reads standard input and writes standard output. Try it:

echo $'I am a text.\nTranspose me.\nCan you do it?' | script.sh

How it works:

  • split input into single lines (files in temporary directory $D)
  • split lines into single characters using grep (files *+)
  • layout characters side-by-side using paste (TAB-separated columns)
  • remove alignment TABs, replace filler TABs with BLANKs, trim using sed

Edit:

  • -9: Removed tidy-up code ;rm -r $D (thanks Tim)
  • -2: use + instead of _ as suffix and shorten ${F}_ to $F+
  • -3: remove prefix L from split result files
\$\endgroup\$
  • \$\begingroup\$ For the purposes of code golf, you don't necessarily have to be nice and clean up after yourself. You can leave off the rm bit from your character count. \$\endgroup\$ – Tim Seguine Jan 5 '14 at 20:15
2
\$\begingroup\$

Ruby — 144 characters

Here's my first attempt, golfed:

def f t
t.split(?\n).each{|l|l<<' 'until l.size==t.split(?\n).map(&:size).max}.map{|x|x.split('')}.transpose.map{|l|l.join.rstrip}.join(?/n)
end

For output, run puts f text where text is any multi-line string adhering to the rules above. The ungolfed version is below:

def text_transpose(text)
  lines = text.split(?\n)
  maxlen = lines.map(&:size).max
  lines.each { |line| line << ' ' until line.size == maxlen }
       .map  { |line| line.split('') }.transpose
       .map  { |char| char.join.rstrip }.join(?\n)
end

For a similar, but ultimately better solution in Ruby, check out Wayne Conrad's code above.

\$\endgroup\$
  • \$\begingroup\$ I didn't notice the transpose in your answer before I wrote mine. It doesn't seem quite kosher for me to have essentially rewritten your answer, only a little better. :( \$\endgroup\$ – Wayne Conrad Jan 4 '14 at 17:07
  • 2
    \$\begingroup\$ I don't mind at all. You came up with your code independently and it's not a race. I definitely learned something from your solution. Had you held back because I used transpose, it's possible a better Ruby solution wouldn't have surfaced. One of things I love most about programming is the willingness to collaborate and cross-pollinate ideas. Till we meet again, kind sir. Cheers! \$\endgroup\$ – O-I Jan 4 '14 at 23:45
2
\$\begingroup\$

PHP 194

function x($a){$a.="\n";$s=strlen($a);$i=0;while($c<$s)if($a{$c}!="\n")$b[$i++].=$a{$c++};else{$c++;for(;$i<$s;$i++)$b[$i].=" ";$i=0;}ksort($b);return rtrim(implode("\n",array_map("trim",$b)));}

Non-golfed:

function x($a) {
    $a.="\n";
    $s=strlen($a);
    $i=0;
    while($c<$s)
        if($a{$c}!="\n")
            $b[$i++].=$a{$c++};
        else{
            $c++;
            for(;$i<$s;$i++)
                $b[$i].=" ";$i=0;
        }
    ksort($b);
    return rtrim(implode("\n",array_map("trim",$b)));
}

This is my first golfing attempt, so please be kind! Also, tips/suggestions would be greatly appreciated!

\$\endgroup\$
  • \$\begingroup\$ It's shorter than my php attempt. You can save two characters by gitting rid of the "s around "trim". php will give a warning, but it works just fine. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:39
  • \$\begingroup\$ @TimSeguine Warnings output on screen though right? You'll have to use @ to suppress warnings. \$\endgroup\$ – ericw31415 May 5 '16 at 13:42
  • \$\begingroup\$ @eric I haven't been active in a while so the opinions might have changed, but in the past it was deemed acceptable to output irrelevant data to standard error. \$\endgroup\$ – Tim Seguine May 5 '16 at 15:09
  • \$\begingroup\$ It's allowed? If that is true, then I didn't know that. \$\endgroup\$ – ericw31415 May 5 '16 at 16:41
2
\$\begingroup\$

MATHEMATICA 117 chars

t = "I am a text.\nTranspose me.\nCan you do it?";

f=(m=Length/@(f=Flatten[Characters/@StringSplit[#,"\n"],{{2},{1}}])//Max;
StringJoin@@@(PadLeft[#,m," "]&/@f)//Column)&
\$\endgroup\$
  • \$\begingroup\$ I can't test this one, so can you verify that it removes traling whitespace on the ends of lines? Also this doesn't appear(at first glance) to define a function, which the rules require. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:54
  • \$\begingroup\$ hi @Tim, now it is a function f!.. tks \$\endgroup\$ – Murta Jan 4 '14 at 13:03
2
\$\begingroup\$

Perl (92+1)

reads stdin and writes to stdout. adding 1 to the score for say

@L=map[grep!/\n/,split//],<>;do{$_=join'',map shift@$_||$",@L;s/ +$//;say}while grep@$_>0,@L
\$\endgroup\$
2
\$\begingroup\$

CJam, 32 25 bytes

CJam is newer than this challenge, so this answer is not eligible for being accepted.

Considerably shortened by user23013.

qN/_z,f{Se]}z{S+e`);e~N}%

Test it here.

qN/                       "Read input, split into lines.";
   _z,                    "Transpose, get length (find maximum line length).";
      f{Se]}              "Pad each line to that length with spaces.";
            z             "Transpose.";
             {         }% "Map this block onto each line in the result.";
              S+          "Add a space to ensure there's at least one.";
                e`        "Run-length encode.";
                  );      "Discard the trailing run of spaces.";
                    e~    "Run-length decode";
                      N   "Push a newline.";
\$\endgroup\$
  • \$\begingroup\$ Eligible or not, it is a great late answer. Seems like the hardest part for this answer was dealing with the trailing spaces. \$\endgroup\$ – Tim Seguine Apr 25 '15 at 10:35
  • \$\begingroup\$ @TimSeguine Indeed. Without a built-in trimming operator, doing this manually in CJam is surprisingly cumbersome (user23013's suggestion already improved it considerably). \$\endgroup\$ – Martin Ender Apr 25 '15 at 13:00
2
\$\begingroup\$

Javascript, 103

s=>[...s].map((_,i)=>s.split`
`.map(b=>r+=b[q=b[i]||q,i]||' ',r=q='')&&r.replace(/ *$/,q?`
`:q)).join``

Less golfed

s=>[...s].map(
     // we need 'i' ranging from 0 to the length of the longest input line
     // so we scan all the input string, that is surely longer
     // but we need to check that after some point the output must be empty
     (_, i) => ( 
       r = '', // the current output row, starts empty
       q = '', // flag to check if we are beyond the longest line
       s.split('\n') // split in rows
       .map( 
         b => ( // for each input row in b
           q = b[i] || q, // if there is a char at position i in b, i goes to q
           r += b[i] || ' ' // add to output the char at position i or a fill space
         )
       ),
       q // if q is still '', we are beyond the longest input line 
       ? r.replace(/ *$/,`\n`) // trim leading space and add newline
       : '' // no output 
     )
   ).join('')

Test

F=
s=>[...s].map((_,i)=>s.split`
`.map(b=>r+=b[q=b[i]||q,i]||' ',r=q='')&&r.replace(/ *$/,q?`
`:q)).join``

function go() {
  var text=I.value
  var output = F(text)
  O.textContent = output
}

go()
#I { width:50%; height:5em }
<textarea id=I>I am a text.
Transpose me.
Can you do it?</textarea><br>
<button onclick='go()'>Transpose</button>
<pre id=O></pre>

\$\endgroup\$
2
\$\begingroup\$

Retina, 40 bytes

P`.+
~L0$`.
L,$.%'vs,$.(x$%=),`.+
m` *$

Try it online!

Based on this program that I created to transpose any size of rectangle, which uses Leo's suggestion for transposing a rectangle of a known size.

Edit: Golfed more and no longer has trailing spaces on lines.

\$\endgroup\$
2
\$\begingroup\$

Perl 5, 25 bytes

Note that this uses ANSI escape sequences and as such does not work on TIO, you can however see it in action here.

$"="";$_="[1;$.H@F"

Explanation

This code first changes the list separator ($") value to be a vertical tab, followed by the ANSI escape sequence for 'go backwards 1 column' (\x1b[1D), then we set the implicitly printed variable $_ to be a string that starts with the ANSI escape sequence for 'start printing at line 1 column $. (where $. is the current line of text)' (\x1b1;$.H) and interpolates the list @F (which is a list of all the characters on that line, populated by autosplit (-a) with an empty split pattern (-F)) which places the contents of $" in between each item, moving the cursor vertically down instead of continuing output after the previous character.

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Oh my god, the sheer horror! I love it! \$\endgroup\$ – Tim Seguine Aug 6 '18 at 12:37
1
\$\begingroup\$

C++ (243 characters)

Here's a function that takes and returns a string.

I could've shaved a couple dozen chars, but decided to keep it as not-stupid code (runs fast, reads okay). Maybe I only decided to do that because this is my first code golf... I'm not hardcore enough yet :)

string f(string s){stringstream ss(s);vector<string> v;for(size_t i=0;getline(ss,s);++i){if(v.size() < s.size())v.resize(s.size());for(size_t j=0;j<s.size();++j){v[j].resize(i,' ');v[j].push_back(s[j]);}}s="";for(auto& i:v)s+=i+'\n';return s;}

With formatting:

string f(string s)
{
    stringstream ss(s);
    vector<string> v;

    for(size_t i = 0; getline(ss, s); ++i)
    {
        if(v.size() < s.size())
            v.resize(s.size());

        for(size_t j = 0; j < s.size(); ++j)
        {
            v[j].resize(i, ' ');
            v[j].push_back(s[j]);
        }
    }

    s = "";
    for(auto& i : v)
        s += i + '\n';

    return s;
}
\$\endgroup\$
  • \$\begingroup\$ I assume you use using namespace std;. \$\endgroup\$ – Konrad Borowski Jan 3 '14 at 18:59
  • \$\begingroup\$ @xfix Not normally, but I did for this \$\endgroup\$ – David Jan 3 '14 at 19:06
  • 1
    \$\begingroup\$ If I am being picky, I would say using namespace std; should be added to the character count. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:45
1
\$\begingroup\$

Python 2.7 - 115 chars:

oneliner:

>>> a
'I am a text.\nTranspose me.\nCan you do it?'

>>> "".join(["".join(i)+'\n' for i in zip(*[x+" "*(len(max(a.splitlines(), key=len))-len(x)) for x in a.splitlines()])])
'ITC\n ra\naan\nmn \n sy\napo\n ou\nts \need\nx o\ntm \n.ei\n .t\n  ?\n'

and in a cleaner printing:

>>> print "".join(["".join(i)+'\n' for i in zip(*[x+" "*(len(max(a.splitlines(), key=len))-len(x)) for x in a.splitlines()])])
ITC
 ra
aan
mn 
 sy
apo
 ou
ts 
eed
x o
tm 
.ei
 .t
  ?

in 115 chars:

>>> len(""""".join(["".join(i)+'\n' for i in zip(*[x+" "*(len(max(a.splitlines(), key=len))-len(x)) for x in a.splitlines()])])""")
115
\$\endgroup\$
  • \$\begingroup\$ You are not stripping the trailing whitespace on your lines like the rules require. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:35
  • \$\begingroup\$ Also, it's actually 116 bytes, \n is considered by len to be a single char, but it's two :) \$\endgroup\$ – Joachim Isaksson Jan 4 '14 at 13:22
  • 1
    \$\begingroup\$ @JoachimIsaksson on unix \n is one. So I say one is fine. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 15:44
  • \$\begingroup\$ @Tim len("\n") will show 1, although it's certainly 2 separate characters in the source code. Saving the source to a file will make ls display 116. Just saying that len isn't the best way to measure code size due to escape characters being processed before measuring :) \$\endgroup\$ – Joachim Isaksson Jan 4 '14 at 15:51
  • \$\begingroup\$ @JoachimIsaksson oh, sorry I misunderstood your point. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 21:58
1
\$\begingroup\$

GolfScript, 51 chars

n%.{,}%$-1=" "*:y;{y+y,<}%zip{n\+0{;).32=}do}%((;\+

This is a first attempt; I suspect it can be improved. Most of the code is to comply with the padding and trailing space removal requirements — without them, just n%zip n* would suffice.

Ps. The following 46-character version will do the job for the given sample input, but will crash if any input column consists entirely of spaces:

n%.{,}%$-1=" "*:y;{y+y,<}%zip{0{;).32=}do]}%n*

I assume that's enough to disqualify it, even if the challenge doesn't explicitly say so.

\$\endgroup\$
  • \$\begingroup\$ Your assumption is correct. It should work on any ASCII text under the assumptions allowed in the rules. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 13:03
1
\$\begingroup\$

Scheme/Racket 113

The text:

(define t (list 
    (string->list "I am a text.") 
    (string->list "Transpose me.")
    (string->list "Can you do it?")
))

Without new lines and extra white spaces:

(define s(λ(v x)(if(= x 0)'()(cons(list->string(car v))(s(cdr v)(- x 1))))))(s(apply map list t)(length(car t)))

The user-friendly version

(define text (list 
    (string->list "I am a text.") 
    (string->list "Transpose me.")
    (string->list "Can you do it?")
))

(define transpose
    (λ(text length)
        (if (= length 0)
            '()
            (cons (list->string (car text)) (transpose (cdr text) (- length 1)))
)))

(transpose (apply map list text) (length (car text)))
\$\endgroup\$
1
\$\begingroup\$

Haskell

import Data.List
main = interact (unlines . transpose . lines)

It was so short, I needed to add in white space...

\$\endgroup\$
  • \$\begingroup\$ I'm almost sure you can remove some of the whitespace here. But otherwise, great solution. \$\endgroup\$ – Konrad Borowski Jan 4 '14 at 9:05
  • 3
    \$\begingroup\$ This doesn't quite work on my system. It's a bit hard to show in a comment, but if you run it twice you get I am a text..? Transpose met Can you do i. \$\endgroup\$ – marinus Jan 4 '14 at 10:42
  • \$\begingroup\$ Yeah, I am thinking maybe you are not padding the lines to keep the columns intact like the example does. Theorectally, the result of running the function twice should be the original string(with possibly the addition or removal of the final newline.) \$\endgroup\$ – Tim Seguine Jan 4 '14 at 12:33
1
\$\begingroup\$

Python 89 103 chars

def f(a):return'\n'.join([''.join(i).rstrip()for i in zip(*[j+' '*99 for j in a.split('\n')])]).rstrip()

I feel dirty. 90 104 chars for industrial strength version. :^)

\$\endgroup\$
  • \$\begingroup\$ not a function. \$\endgroup\$ – Tim Seguine Jan 4 '14 at 13:24
  • \$\begingroup\$ @Tim My bad, fixed. Anyway my solution is inferior to Joachim Isaksson's. I wonder if there's any short way to solve this problem with recursion. \$\endgroup\$ – TrevorM Jan 4 '14 at 21:08
1
\$\begingroup\$

Mathematica, 95 chars

f=""<>Riffle[Thread@PadRight@Characters@StringSplit[#,"\n"]//.{0->" ",{x___," "..}:>{x}},"\n"]&
\$\endgroup\$
1
\$\begingroup\$

K, 56

This should meet the spec now.

Accepts a string, returns a string.

{`/:{$[" "=*|x;|(+/&\" "=|x)_|x;x]}'x@'/:!max@#:'x:`\:x}

.

k)f:{`/:{$[" "=*|x;|(+/&\" "=|x)_|x;x]}'x@'/:!max@#:'x:`\:x}
k)f"I am a text.\nTranspose me.\nCan you do it?"
"ITC\n ra\naan\nmn\n sy\napo\n ou\nts\need\nx o\ntm\n.ei\n .t\n  ?\n"
k)f f"I am a text.\nTranspose me.\nCan you do it?"
"I am a text.\nTranspose me.\nCan you do it?\n"
\$\endgroup\$
  • \$\begingroup\$ The output appears to be an array of strings? \$\endgroup\$ – Tim Seguine Mar 19 '14 at 17:02
  • \$\begingroup\$ @Tim It is. If you want a single string then add three chars. {`/:x@'/:!max@#:'x:`\:x} for 26. \$\endgroup\$ – tmartin Mar 19 '14 at 17:39
  • \$\begingroup\$ You also have a problem with trailing whitespace. And "If it accepts a filename, then you return the name of the file where you saved the result." You need to return output in the same manner you accept input. \$\endgroup\$ – Tim Seguine Mar 20 '14 at 10:18
  • \$\begingroup\$ @Tim should be fixed now. Kills my bytecount though \$\endgroup\$ – tmartin Mar 20 '14 at 12:09
  • \$\begingroup\$ I suspected it might :( , but a spec is a spec. \$\endgroup\$ – Tim Seguine Mar 20 '14 at 12:13
1
\$\begingroup\$

Groovy, 98 chars

{i->o=[].withDefault{''};i.readLines().each{it.toList().eachWithIndex{c,d->o[d]+=c}};o.join('\n')}

online

ungolfed:

{i->
o=[].withDefault{''};//create list with empty string as default value 
i.readLines()
.each{
    it.toList() //split every line to characters
    .eachWithIndex{ 
        c,d->o[d]+=c //append to string from list with right index
    }
};
o.join('\n')}//join list with newlines
}
\$\endgroup\$
1
\$\begingroup\$

Pyth, 11 bytes

# aYcw1;.tY

Try it online!

Takes input as a string, outputs a list of lists

Pyth, 25 bytes

# aYcw1=+Z1;jbcj"".n.tY)Z

Takes input as a string, outputs a string.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

J, 28 26 Bytes

Saved 2 bytes thanks to frownyfrog

t=.,@:(,&LF"1)@|:@:>@cutLF

Takes a string, returns a string. I'm not sure if there's a shorter version of the 'cutopen' function verb that I could use.

There's also the shorter

t=.|:@:>@cutLF

But I'm not sure it falls within the OP's guidelines, as it returns an array of characters.

How it works:

                     cutLF   | Splits the input on new lines and boxes them
                    @        | Composes verbs (as does @:, but they're not equal)
                   >         | Unboxes this, forming an array of the lines
                 @:          |
               |:            | Transposes the array
      (      )@              |
       ,&LF                  | Appends a new line...
           "1                | To each row of the array
    @:                       |
   ,                         | Flatten the result
t=.                          | Assign this verb to t

The other version works the same, but doesn't convert the transposed array to a properly formatted string.

Examples:

NB. Define a multi-line string

    text =: 0 : 0
I am a text.
Transpose me.
Can you do it?
)

    t text
ITC
 ra
aan
mn    NB. There's whitespace after the 'n' here, but I assume it doesn't count as trailing since it's part of the original string
 sy
apo
 ou
ts 
eed
x o
tm 
.ei
 .t
  ?

    t t text
I am a text.     NB. Again, whitespace here, but it's part of the argument of the second 't' (added by the first 't' to keep columns straight)
Transpose me. 
Can you do it?
\$\endgroup\$
  • \$\begingroup\$ I would use cutLF. \$\endgroup\$ – FrownyFrog Dec 6 '17 at 3:56
  • 1
    \$\begingroup\$ Save 1 character with 0|:>@cutLF \$\endgroup\$ – FrownyFrog Dec 6 '17 at 4:10
1
\$\begingroup\$

Lua, 203 189 bytes

t={{}}i=1m=0(...):gsub(".",function(c)n=#t[i]if c=="\n"then i=i+1t[i]={}else t[i][n+1]=c end m=m<=n and n+1or m end)
for x=1,m do for p=1,i do io.write(t[p][x]or" ")end _=m<=x or print()end

Try it online!

I saw another Lua solution here, but I don't think there's a problem with posting 2 solutions on the same language. If there is, tell me :)

\$\endgroup\$
  • 1
    \$\begingroup\$ There's nothing wrong with multiple answers in the same language. Even identical answers are allowed to an extent (though it's encouraged to at least check if you're posting the a similar solution) \$\endgroup\$ – Jo King Jul 25 '18 at 6:56
  • \$\begingroup\$ Unfortunately Your result must not have trailing whitespace on any line. \$\endgroup\$ – Jo King Jul 30 '18 at 7:33
  • \$\begingroup\$ But I can't see trailing whitespaces on the output of my code. There's no spaces after the line ends and no blank line at the end. \$\endgroup\$ – Visckmart Jul 30 '18 at 7:35
  • \$\begingroup\$ The part that seems to catch people out is on any line. e.g. This has extra whitespace on the second line \$\endgroup\$ – Jo King Jul 30 '18 at 7:40
  • \$\begingroup\$ Ohhh now I got it! Sorry. I'll try to make it work as soon as I have time. I think the problem was that there's only 1 example test and I thought that would be the "stress" test hahah But ok, thanks for telling me :) \$\endgroup\$ – Visckmart Jul 30 '18 at 7:44

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.