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.
6 Answers 6
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.
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
Perl 5, 87 bytes
perl -E'while(<STDIN>){@f=(0,split);@i=0..$#f,@i[@ARGV]=0;say"@f[grep$_,@i] $_ $f[$_]"for@ARGV}'
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)
-
\$\begingroup\$
p>>=return.f
should generally be writtenf<$>p
. In this case, though, you can golf more by just usings<-getArgs
and applying the parsing inline. Since you usemap
three times, you should writem=map
on its own line and use that. \$\endgroup\$dfeuer– dfeuer2019年07月03日 04:02:10 +00:00Commented Jul 3, 2019 at 4:02
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.
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.
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}
{
...}
"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" ]]
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\$