Understanding how Ruby stdout works - ruby

i'm trying to understand how Ruby's stdout actually works, since i'm struggling with the output of some code.
Actually, within my script i'm using a unix sort, which works fine from termina, but this is what i get from ruby, suppose you have this in your file (tsv)
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
My ruby code is this:
#raw_file=File.open(ARGV[0],"r") unless File.open(ARGV[0],"r").nil?
tmp_raw=File.new("#{#pwd}/tmp_raw","w")
`cut -f1,6,3,4,2,5,9,12 #{#raw_file.path} | sort -k1,1 -k8,8 > #{tmp_raw.path}`
This is what i get (misplaced separators):
a b c d e f i
1a b c d e f g h i l m
1
Whats happening here?
When running from terminal i get no separators misplacement
enter code here

Instead of writing to a temporary file, passing the file via argument etc, you can use Ruby's open3 module to create the pipeline in a more Ruby-friendly manner (instead of relying on the underlying shell):
require 'open3'
raw_file = File.open(ARGV[0], "r")
commands = [
["cut", "-f1,6,3,4,2,5,9,12"],
["sort", "-k1,1", "-k8,8"],
]
result = Open3.pipeline_r(*commands, in: raw_file) do |out|
break out.read
end
puts result
Shell escaping problems, for example, become a thing from the past, and no temporary files are necessary, since pipes are used.
I would, however, advise doing this kind of processing in Ruby itself, instead of calling external utilities; you're getting no benefit from using Ruby here, you're just doing shell stuff.

As Linuxios says, your code never uses STDOUT, so your question doesn't make a lot of sense.
Here's a simple example showing how to do this all in Ruby.
Starting with an input file called "test.txt":
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
a b c d e f g h i l m
This code:
File.open('test_out.txt', 'w') do |test_out|
File.foreach('test.txt') do |line_in|
chars = line_in.split
test_out.puts chars.values_at(0, 5, 2, 3, 1, 4, 8, 10).sort_by{ |*c| [c[0], c[7]] }.join("\t")
end
end
Creates this output in 'test_out.txt':
a b c d e f i m
a b c d e f i m
a b c d e f i m
a b c d e f i m
a b c d e f i m
a b c d e f i m
a b c d e f i m
a b c d e f i m
Read about values_at and sort_by.

Related

Output list items as ls does

I'm trying to output something that resembles as ls output. The ls command outputs like this:
file1.txt file3.txt file5.txt
file2.txt file4.txt
But I this sample list:
a b c d e f g h i j k l m n o p q r s t u v w x y z
to appear as:
a e i m q u y
b f j n r v z
c g k o s w
d h l p t x
In that case, it gave 7 columns which is fine, but I wanted up to 8 columns max. Next the following list:
a b c d e f g h i j k l m n o p q r s t u v w
will have to show as:
a d g j m p s v
b e h k n q t w
c f i l o r u
And "a b c d e f g h" will have to show as is because it is already 8 columns in 1 line, but:
a b c d e f g h i
will show as:
a c e g i
b d f h
And:
a b c d e f g h i j
a c e g i
b d f h j
One way:
#!/usr/bin/env tclsh
proc columnize {lst {columns 8}} {
set len [llength $lst]
set nrows [expr {int(ceil($len / (0.0 + $columns)))}]
set cols [list]
for {set n 0} {$n < $len} {incr n $nrows} {
lappend cols [lrange $lst $n [expr {$n + $nrows - 1}]]
}
for {set n 0} {$n < $nrows} {incr n} {
set row [list]
foreach col $cols {
lappend row [lindex $col $n]
}
puts [join $row " "]
}
}
columnize {a b c d e f g h i j k l m n o p q r s t u v w x y z}
puts ----
columnize {a b c d e f g h i j k l m n o p q r s t u v w}
puts ----
columnize {a b c d e f g h}
puts ----
columnize {a b c d e f g h i}
puts ----
columnize {a b c d e f g h i j}
The columnize function first figures out how many rows are needed with a simple division of the length of the list by the number of columns requested, then splits the list up into chunks of that length, one per column, and finally iterates through those sublists extracting the current row's element for each column, and prints the row out as a space-separated list.

What are the inorder and postorder traversals of the following tree?

With respect to the following tree:
What is the correct inorder traversal?
U S T X C P Y R B A I G J F N H V T E D L
U S T X C P Y R B A D E I G J F N H V T L
What is the correct postorder traversal?
U T S X P R Y C B D I J G N V T H F E L A
U T S X P R Y C B I J G N V T H F E D L A
I evaluated both pairs. But some are saying 1-1 and 2-1 are correct, while others say 1-2 and 2-2 are correct. I'm confused. Which ones are actually correct?
inorder:
B U S T X C P Y R A D E I G J F N H V T L
postorder (2.2 is correct):
U T S X P R Y C B I J G N V T H F E D L A

Exponents are not getting add

I am a beginner in Mathematica and learning from Google.
I was trying to find the determinant of a 4*4 matrix.
TT = {{ap, b, c, d}, {e, fp, g, h}, {i, j, kp, l}, {m, n, o, pq}}
TT // MatrixForm
After it, I applied determinant command.
Det[TT]
I am getting result as follow,
d g j m - c h j m - d fp kp m + b h kp m + c fp l m - b g l m - d g i n + c h i n + d e kp n - ap h kp n - c e l n + ap g l n + d fp i o - b h i o - d e j o + ap h j o + b e l o - ap fp l o - c fp i pq + b g i pq + c e j pq - ap g j pq - b e kp pq + ap fp kp pq
I want above expression as a polynomial in p, want to collect coefficients separately. I have tried various command such as Collect, Factor etc. But each time I get the answer as the same polynomial as above.
I assume you have a*p, f*p, k*p, p*q, instead of ap, fp, kp and pq.
Mathematica needs either space or multiple sign to treat them as a separate multiplier and not as a variable.
t = {{a p, b, c, d}, {e, f p, g, h}, {i, j, k p, l}, {m, n, o,
p q}};
Collect[Det[t], p]
(* d g j m - c h j m - b g l m - d g i n + c h i n - c e l n -
b h i o - d e j o + b e l o + a f k p^4 q +
p (b h k m + c f l m + d e k n + a g l n + d f i o + a h j o +
b g i q + c e j q) +
p^2 (-d f k m - a h k n - a f l o - c f i q - a g j q - b e k q) *)

Getting 3 string before and after of each characters using awk

What I have expected is the output like below:
[before character h is null and assign with '#". After character h
are "e","l","l".]
[before character e is "h". After character e are
"l","l","o".]
[before character l are "h" and "e". After character l
are "l" and "o".]
[before character l are "h" and "e". After character
l are "l" and "o".]
[before character l are "h","e","l". After
character l is "o".]
[before character o are "e","l","l". After
character o is null and assign with '#".]
# # # h e l l
# # h e l l o
# h e l l o #
h e l l o # #
e l l o # # #
# # # w o n d
# # w o n d e
# w o n d e r
w o n d e r f
o n d e r f u
n d e r f u l
d e r f u l #
e r f u l # #
r f u l # # #
Input file:
h e l l o
w o n d e r f u l
Code:
awk -v s1="# # #"
'BEGIN{v=length(s1)}
{$0=s1 $0 s1;num=split($0, A,"");
for(i=v+1;i<=num-v;i++){
q=i-v;p=i+v;
while(q<=p){
Q=Q?Q OFS A[q]:A[q];q++
};
print Q;Q=""
}
}' InputFile
But the result I got is:
# # # h e l
# # h e l l
# # h e l l
# h e l l o
# h e l l o #
h e l l o #
e l l o # #
e l l o # #
l l o # # #
# # # w o n
# # w o n d
# # w o n d
# w o n d e
# w o n d e
w o n d e r
o n d e r
o n d e r f
n d e r f
n d e r f u
d e r f u
d e r f u l
e r f u l #
e r f u l #
r f u l # #
r f u l # #
f u l # # #
How to solve it? Please guide me. Thanks
Add gsub(/ /,"") to the top of #fedorqui's answer to your previous question, change ## to ### and change 5 to 7 and you get:
$ cat tst.awk
{
gsub(/ /,"")
n=length($0)
$0 = "###" $0 "###"
gsub(/./, "& ")
for (i=1; i<=2*n; i+=2)
print substr($0, i, 7*2-1)
print ""
}
$ awk -f tst.awk file
# # # h e l l
# # h e l l o
# h e l l o #
h e l l o # #
e l l o # # #
# # # w o n d
# # w o n d e
# w o n d e r
w o n d e r f
o n d e r f u
n d e r f u l
d e r f u l #
e r f u l # #
r f u l # # #

Passing return value into another method

I am starting with an array of letters:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
Passing them, finding all combinations that return an array like this ["cstp", "cstb", "cstl"], this is a shortened example.
def combinations(letters)
combos = letters.combination(4)
combos.collect do |letter_set|
letter_set.join(",").gsub("," ,"")
end
end
I am trying to figure out how to pass the return value of combinations into start_wtih_letter_c. Do I have to pass a block like &block? I tried various things that keep saying wrong number of arguments.
def start_with_letter_c(pass the return value)
combinations.select {|word| word.match(/^ca/) }
end
Here you go, no errors:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
def combinations(letters)
combos = letters.combination(4)
combos.collect do |letter_set|
letter_set.join(",").gsub("," ,"")
end
end
def start_with_letter_c(combinations)
combinations.select {|word| word.match(/^ca/) }
end
start_with_letter_c(combinations(letters))
# => ["cael", "caeo", "caet", "cael", "ca ...and so on
I would write something like this:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
def combinations(letters)
letters.combination(4).map(&:join)
end
def start_with_letter_c(combinations)
combinations.select { |word| word.start_with?('ca') }
end
start_with_letter_c(combinations(letters))

Resources