4
\$\begingroup\$

Let's say you've got a table of data:

meter_id date 0000 0600 1200 1800
0 030915 10 20 30 40
1 030915 15 7 49 2

where the last four columns are meter readings at different times. You want to output

meter_id date time reading
0 030915 0000 10
0 030915 0600 20

etc.

Your input and output will not have headers, unlike in this example. The set of columns you'll transpose will be provided as numeric arguments to your program, from 1 onwards. Input is stdin and output is stdout.

So here's an example of it actually being used.

$ ./tpose 3 4 5 6

Stdin:

0 030915 10 20 30 40
1 030915 15 7 49 2

Stdout:

0 030915 3 10
0 030915 4 20
0 030915 5 30
0 030915 6 40
1 030915 3 15
1 030915 4 7
1 030915 5 49
1 030915 6 2

The third column contains values from 3 to 6. This is because the reading is from columns 3 to 6 from the input table.

Happy golfing.

asked Oct 9, 2015 at 14:17
\$\endgroup\$
20
  • 4
    \$\begingroup\$ Can you post some example inputs and outputs? \$\endgroup\$ Commented Oct 9, 2015 at 14:18
  • \$\begingroup\$ Is 0600 30 in the example just wrong (1200 is 30), or are you trying to do cumulative readings (so adding the current 20 to the previous 10)? \$\endgroup\$ Commented Oct 9, 2015 at 14:20
  • \$\begingroup\$ @Geobits Fixed. \$\endgroup\$ Commented Oct 9, 2015 at 14:21
  • \$\begingroup\$ You say in the text that the values in the third column of the output are 3 to 6, but they are actually 2 to 5. Which one is right? Right now, it looks like you're using 1-based column indices in the input, and 0-based in the output. \$\endgroup\$ Commented Oct 9, 2015 at 15:16
  • 1
    \$\begingroup\$ Do the columns to be transposed always form a contiguous range? Can other columns appear after them? If yes, where should the transposed columns appear in the output? Are the columns to be transposed always given in ascending order, and can they contain the same column twice? And if so, can we reorder them in the output, or collapse duplicates? \$\endgroup\$ Commented Oct 10, 2015 at 17:00

6 Answers 6

3
\$\begingroup\$

kdb k, 101 bytes

1@"\n"/:{"\n"/:{" "/:(r@&{~#&x=a}'!#r),(,1ドル+a@x),,c@x}'!#c::(r::" "\:x)@a::-1+.:'.z.x}'-1_"\n"\:0::0;

Me: (reads the word "transpose" in the title) K will be perfect for this! It'll kick everything else's hind!

20 minutes and 101 bytes later

Me: Idiot.

answered Oct 9, 2015 at 22:37
\$\endgroup\$
2
\$\begingroup\$

Ruby, (削除) 88 (削除ここまで) 84 bytes

Input is tab-separated. Annoyingly, Ruby gets pulls from files whose names match those from ARGV, but those don't exist so the program errors out. To work around this, I have to use STDIN.gets to get the actual correct input.

-4 bytes by remembering that I don't actually need to use scan since I'm only matching the pattern once per line anyways, so =~ for a single regex match saves bytes.

($_=~/(\d+	\w+	)(.*)/;i=-1;puts2ドル.split.map{|s|"#1ドル#{$*[i+=1]}	"+s})while STDIN.gets

Try it online!

answered Jun 25, 2019 at 22:09
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 87 bytes

perl -E'while(<STDIN>){@f=(0,split);@i=0..$#f,@i[@ARGV]=0;say"@f[grep$_,@i] $_ $f[$_]"for@ARGV}'
answered Oct 9, 2015 at 20:57
\$\endgroup\$
1
\$\begingroup\$

Haskell (195 bytes)

import System.Environment
main=do s<-getArgs>>=return.map(\a->read a-1);interact$unlines.map unwords.t s.map words.lines
t g r=[[a!!j|j<-[0..length a-1],not$j`elem`g]++show(j+1):[a!!j]|a<-r,j<-g]

Ungolfed Haskell (398 bytes):

import System.Environment
import Prelude
main = do js <- getArgs >>= return . map (\a -> read a - 1)
 interact $ unbr . (`tpose` js) . br
br = map words . lines
xs `excludingFrom` es = [xs !! j | j <- [0..length xs - 1], not $ j `elem` es]
tpose rows js = [row `excludingFrom` js ++ [show (j+1)] ++ [row !! j] | row <- rows, j <- js]
unbr = unlines . map (foldr1 $ \t a -> t++"\t"++a)
answered Oct 9, 2015 at 14:48
\$\endgroup\$
1
  • \$\begingroup\$ p>>=return.f should generally be written f<$>p. In this case, though, you can golf more by just using s<-getArgs and applying the parsing inline. Since you use map three times, you should write m=map on its own line and use that. \$\endgroup\$ Commented Jul 3, 2019 at 4:02
1
\$\begingroup\$

PHP, 90 bytes

while($r=fgetcsv(STDIN,0,' '))foreach($argv as$a)if($a|0)echo"$r[0] $r[1] $a {$r[$a-1]}
";

Input and output with single space delimiter.

Try it online!

PHP, 109 bytes

while($r=preg_split("/\s+/",fgets(STDIN),0,1))foreach($argv as$a)if($a|0)echo"$r[0]\t$r[1]\t$a\t{$r[$a-1]}
";

Or with I/O exactly as shown above, using fixed width columns.

Try it online!

answered Jun 25, 2019 at 15:16
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog Unicode), 56 bytes SBCS

Anonymous prefix lambda. Takes column numbers for "transposition" as right argument and prompts via stdin for filename of table.

{(t[;⍵~⍨⍳≢⍉t]⌿⍨≢⍵),(⍪,⍨⍵⍴⍨≢),t[;⍵]⊣t←↑(∊∘⎕D⊆⊢) ̈⊃⎕NGET⍞1}

Try it online!

{...} "dfn"; right argument (column numbers) is :

⍞1 prompt for file name from stdin and juxtapose with 1 (indicating that we want a list of strings)
["tpose",1]

⎕NGET get the native file's (content,encoding,newline)
[["0 030915 10 20 30 40","1 030915 15 7 49 2"],"UTF-8-NOBOM",[10]]

pick the first of those (content)
["0 030915 10 20 30 40","1 030915 15 7 49 2"]

(...) ̈ apply the following tacit function to each line:

the characters that are members
of
⎕D the set of digits
[[1,0,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1],[1,0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1]]

indicate the sub-partitions of

the line
[["0","030915","10","20","30","40"],["1","030915","15","7","49","2"]]

up the rank by mixing the list (rank 1) of lists into a matrix (rank 2)
[["0","030915","10","20","30","40"],
["1","030915","15","7" ,"49","2" ]]

t← assign that to t (for table)

discard that in favour of

t[;⍵] all rows of the subset of columns of t enumerated in the argument
[["10","20","30","40"],
["15","7" ,"49","2" ]]

, ravel (flatten that)
["10","20","30","40","15","7","49","2"]

(...) apply the following tacit function to that:

the tally of elements
8

⍵⍴⍨ use that to reshape the number of columns to be "transposed"
[3,4,5,6,3,4,5,6]

,⍨ to that, append

the table-fied (made into single-column table) argument (the "transposed" columns)
[[3,"10"],
[4,"20"],
[5,"30"],
[6,"40"],
[3,"15"],
[4,"7" ],
[5,"49"],
[6,"2" ]]

(...), prepend the following:

≢⍵ the tally of columns to be "transposed"
4

...⌿⍨ use that to vertically replicate the rows of...

t[;...] all rows of the following columns of the table:

⍉t transpose the table
[["0" ,"1" ],
["030915","030915"],
["10" ,"15" ],
["20" ,"7" ],
["30" ,"49" ],
["40" ,"2" ]]

the tally of rows
6

ɩndices until that
[1,2,3,4,5,6]

⍵~⍨ except the "transposed" column numbers
[1,2]

[["0","030915"],
["1","030915"]]

[["0","030915"],
["0","030915"],
["0","030915"],
["0","030915"],
["1","030915"],
["1","030915"],
["1","030915"],
["1","030915"]]

[["0","030915",3,"10"],
["0","030915",4,"20"],
["0","030915",5,"30"],
["0","030915",6,"40"],
["1","030915",3,"15"],
["1","030915",4,"7" ],
["1","030915",5,"49"],
["1","030915",6,"2" ]]

answered Jul 2, 2019 at 23:55
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.