29
\$\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\$
11
  • \$\begingroup\$ I decided to remove the prohibition on language built-ins. \$\endgroup\$ Jan 3, 2014 at 13:27
  • \$\begingroup\$ I edited to clarify the trailing whitespace condition. \$\endgroup\$ Jan 3, 2014 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, 2014 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\$ Jan 4, 2014 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\$ Mar 19, 2014 at 5:28

46 Answers 46

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\$
10
  • \$\begingroup\$ I hope you noticed I removed the prohibition for built-ins. \$\endgroup\$ Jan 3, 2014 at 13:43
  • \$\begingroup\$ @Tim: Yes, otherwise I wouldn't have posted this. \$\endgroup\$
    – marinus
    Jan 3, 2014 at 13:44
  • \$\begingroup\$ Is the trailing whitespace rule written unclearly? You seem to have more characters than I expected. \$\endgroup\$ Jan 3, 2014 at 13:55
  • \$\begingroup\$ How many characters should I have? The last characters on the string are ?\n. \$\endgroup\$
    – marinus
    Jan 3, 2014 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, 2014 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\$
5
  • \$\begingroup\$ Nice. You can strip out one more character by replacing "\n" with ?\n. \$\endgroup\$
    – O-I
    Jan 3, 2014 at 21:04
  • \$\begingroup\$ Also, the .to_a is superfluous. You can gain another 5 characters there. \$\endgroup\$
    – O-I
    Jan 3, 2014 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\$ Jan 3, 2014 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, 2014 at 0:19
  • 2
    \$\begingroup\$ Some of the code golf challenges have renewed my interest in learning ruby. \$\endgroup\$ Jan 4, 2014 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\$
4
  • \$\begingroup\$ Not exactly compliant. It should be a function take takes a string and returns a string. \$\endgroup\$ Jan 4, 2014 at 12:50
  • \$\begingroup\$ @Tim Yes, missed that. Fixed now, thanks. \$\endgroup\$ Jan 4, 2014 at 13:16
  • \$\begingroup\$ +1 you appear to be the shortest compliant python entry at the moment. \$\endgroup\$ Jan 4, 2014 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, 2014 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\$
3
  • \$\begingroup\$ You appear to be breaking the rule "Your result must not have trailing whitespace on any line." \$\endgroup\$ Mar 19, 2014 at 9:56
  • \$\begingroup\$ @TimSeguine Oops I missed that one. I just fixed it in the latest edit. \$\endgroup\$ Mar 19, 2014 at 16:56
  • \$\begingroup\$ Great answer. Try it online! \$\endgroup\$
    – Jonah
    Mar 24, 2021 at 5:14
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\$
7
  • \$\begingroup\$ I think you can take advantage of implicit int to shorten some of your declarations, or is that illegal now? \$\endgroup\$ Jan 3, 2014 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, 2014 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\$ Jan 3, 2014 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, 2014 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\$ Jan 3, 2014 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\$
1
  • \$\begingroup\$ I can't test this one, but it looks compliant \$\endgroup\$ Jan 4, 2014 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\$
1
  • \$\begingroup\$ +1 You golfed it better in any case. \$\endgroup\$ Jan 17, 2014 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\$
1
  • \$\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\$ Jan 5, 2014 at 20:15
3
\$\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\$

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\$
0
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\$
2
  • \$\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\$ Jan 4, 2014 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, 2014 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\$
4
  • \$\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\$ Jan 4, 2014 at 12:39
  • \$\begingroup\$ @TimSeguine Warnings output on screen though right? You'll have to use @ to suppress warnings. \$\endgroup\$
    – ericw31415
    May 5, 2016 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\$ May 5, 2016 at 15:09
  • \$\begingroup\$ It's allowed? If that is true, then I didn't know that. \$\endgroup\$
    – ericw31415
    May 5, 2016 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\$
2
  • \$\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\$ Jan 4, 2014 at 12:54
  • \$\begingroup\$ hi @Tim, now it is a function f!.. tks \$\endgroup\$
    – Murta
    Jan 4, 2014 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\$
2
  • \$\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\$ Apr 25, 2015 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\$ Apr 25, 2015 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\$

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
  • 1
    \$\begingroup\$ Oh my god, the sheer horror! I love it! \$\endgroup\$ Aug 6, 2018 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\$
3
  • \$\begingroup\$ I assume you use using namespace std;. \$\endgroup\$ Jan 3, 2014 at 18:59
  • \$\begingroup\$ @xfix Not normally, but I did for this \$\endgroup\$
    – David
    Jan 3, 2014 at 19:06
  • 1
    \$\begingroup\$ If I am being picky, I would say using namespace std; should be added to the character count. \$\endgroup\$ Jan 4, 2014 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\$
5
  • \$\begingroup\$ You are not stripping the trailing whitespace on your lines like the rules require. \$\endgroup\$ Jan 4, 2014 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\$ Jan 4, 2014 at 13:22
  • 1
    \$\begingroup\$ @JoachimIsaksson on unix \n is one. So I say one is fine. \$\endgroup\$ Jan 4, 2014 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\$ Jan 4, 2014 at 15:51
  • \$\begingroup\$ @JoachimIsaksson oh, sorry I misunderstood your point. \$\endgroup\$ Jan 4, 2014 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\$
1
  • \$\begingroup\$ Your assumption is correct. It should work on any ASCII text under the assumptions allowed in the rules. \$\endgroup\$ Jan 4, 2014 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\$
3
  • \$\begingroup\$ I'm almost sure you can remove some of the whitespace here. But otherwise, great solution. \$\endgroup\$ Jan 4, 2014 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, 2014 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\$ Jan 4, 2014 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\$
2
  • \$\begingroup\$ not a function. \$\endgroup\$ Jan 4, 2014 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, 2014 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\$
5
  • \$\begingroup\$ The output appears to be an array of strings? \$\endgroup\$ Mar 19, 2014 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, 2014 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\$ Mar 20, 2014 at 10:18
  • \$\begingroup\$ @Tim should be fixed now. Kills my bytecount though \$\endgroup\$
    – tmartin
    Mar 20, 2014 at 12:09
  • \$\begingroup\$ I suspected it might :( , but a spec is a spec. \$\endgroup\$ Mar 20, 2014 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\$
0
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\$
2
  • \$\begingroup\$ I would use cutLF. \$\endgroup\$
    – FrownyFrog
    Dec 6, 2017 at 3:56
  • 1
    \$\begingroup\$ Save 1 character with 0|:>@cutLF \$\endgroup\$
    – FrownyFrog
    Dec 6, 2017 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\$
5
  • 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, 2018 at 6:56
  • \$\begingroup\$ Unfortunately Your result must not have trailing whitespace on any line. \$\endgroup\$
    – Jo King
    Jul 30, 2018 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, 2018 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, 2018 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, 2018 at 7:44

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.