emacs org mode: how to remove the trailing dot in a mean of hms values - org-mode

so i'm using vmean on a series of HMS values. because I don't care about fractions of seconds i convert the hms value to seconds, floor that value and then cast back to HMS. Which works fine, however, I have been unable to figure out how to remove the trailing dot from the seconds field.
what I have:
#II .. #III = (0# 15' 36", 0# 16' 7", 0# 16' 36", 0# 17' 05")
0# 16' 21." = #7$4 = hms(0,0,floor(deg(vmean(#II..#III))*3600))
what I want:
0# 16' 21" = #7$4

Define a calc function that converts the seconds of an hms value to an integer:
(defmath hmsIntSecs (v)
(let ((x v))
(setq x (nreverse x))
(setcar x (calcFunc-round (car x)))
(setq x (nreverse x))
)
)
Be sure to evaluate the function definition before proceeding.
What I get with just vmean:
| 0# 16' 21." | 0# 15' 36" | 0# 16' 7" | 0# 16' 36" | 0# 17' 05" |
#+TBLFM: $1=vmean($2..$5)
Now what I get using hmsIntSecs:
| 0# 16' 21" | 0# 15' 36" | 0# 16' 7" | 0# 16' 36" | 0# 17' 05" |
#+TBLFM: $1=hmsIntSecs(vmean($2..$5))

Related

format output in Perl [duplicate]

I want to output a table containing four variables, an example of the desired format is:
A confusion matrix
H | P |
-----------------------
$var1 | $var2 | H
$var3 | $var4 | P
The problem I am having is that depending on the number of digits in the variables, the format changes and the various lines are offset. I know this is a complete noobie question, but I have never had to pay too much attention to the format of output before, its just one of those little things I want to get right this time. Any help at all would be great, thanks.
Text::Table, Text::SimpleTable::AutoWidth
In addition to daxim's suggestions, there is also Text::TabularDisplay.
You want "format" construct (somewhat inherited from Fortran(!))
http://perldoc.perl.org/functions/format.html
A real example with code with Text::SimpleTable::AutoWidth:
use strict; use warnings;
use Text::SimpleTable::AutoWidth;
print Text::SimpleTable::AutoWidth
->new( max_width => 55, captions => [qw/ Name Age /] )
->row( 'Mother', 59 )
->row( 'Dad', 58 )
->row( 'me', 32 )
->draw();
.--------+-----.
| Name | Age |
+--------+-----+
| Mother | 59 |
| Dad | 58 |
| me | 32 |
'--------+-----'
If you prefer to not install another CPAN module, using format:
#!/usr/bin/env perl
use strict; use warnings;
my ($name, $age, $salary);
format Emp =
#<#<<<<<<<<<#|||||||||||#<#<<#<<#<
'|', $name, '|', $salary, '|', $age, '|'
.
$~ = 'Emp';
# header
print <<EOF;
+----------------+--------+-----+
| Employee name | salary | age |
+----------------+--------+-----+
EOF
my #n = ("Ali", "Raza", "Jaffer");
my #a = (20, 30, 40);
my #s = (2000, 2500, 4000);
my $i = 0;
foreach (#n) {
$name = $_;
$salary = $s[$i];
$age = $a[$i];
write;
}
# footer
print "+-------------------------+-----+\n";
+----------------+--------+-----+
| Employee name | salary | age |
+----------------+--------+-----+
| Ali | 20| 20 |
| Raza | 20| 20 |
| Jaffer | 20| 20 |
+-------------------------+-----+
This syntax is very old and confusing. Up to you.

Perl: Perl6::Form format

I have file something like this,
SR Name Rollno Class
1 Sanjay 01 B
2 Rahul_Kumar_Khanna 09 A
Now I need to add "|" between each. So it should look like
SR | Name |Rollno | Class|
1 | Sanjay |01 | B |
2 | Rahul_Kumar_Khanna|09 | A |
I am using Perl6::form
my $text;
foreach my $line (#arr) {
my ($SR, $Name, $Rollno, $Class) = split (" ", $line);
my $len = length $Name;
$text = form
'| {||||||||} | {||||||||} | {||||||||} | {||||||||}|',
$SR, $Name, $Rollno, $Class;
print $text;
}
Here till now I have done but the name is not comming out properly. I have add extra "|" in name for that. Is there any way we can add "|" by calculating length like(below). I tried but getting error.
'| {||||||||} | {||||||||}x$len | {||||||||} | {||||||||}|',
Problem #1
'| {||||||||} | {||||||||}x$len | {||||||||} | {||||||||}|'
produces
| {||||||||} | {||||||||}x20 | {||||||||} | {||||||||}|
but you're trying to get
| {||||||||} | {||||||||||||||||||||} | {||||||||} | {||||||||}|
For that, you'd want
'| {||||||||} | {'.( "|" x $len ).'} | {||||||||} | {||||||||}|'
Problem #2
$len is the length of the name field of the current row. It's different for every row. This is wrong, cause you want the output to be the same width for every row. $len needs to be the length of the longest name field.
You will need to find the correct value for $len before even starting the loop.
# Read in the data as an array of rows.
# Each row is an array of values.
my #rows = map { [ split ] } <>;
# Find the maximum width of each column.
my #col_lens = (0) x #{rows[0]};
for my $row (#rows) {
# Skip the blank line after the header.
next if !#$row;
for my $col_idx (0..$#$row) {
my $col_len = $row->[$col_idx];
if ($col_lens->[$col_idx] < $col_len) {
$col_lens->[$col_idx] = $col_len;
}
}
}
my $form =
join "",
"| ",
"{".( "|"x($col_lens[0]-2) )."}",
" | ",
"{".( "|"x($col_lens[1]-2) )."}",
" | ",
"{".( "|"x($col_lens[2]-2) )."}",
" | ",
"{".( "|"x($col_lens[3]-2) )."}",
" |";
for my $row (#rows) {
if (#$row) {
print form($form, #$row);
} else {
print "\n";
}
}

Using Tree::DAG_Node to print list heap into tree-format

To make it simple, I am trying to get this heap to print in a tree like format. It's close but I know I am missing stuff, but I just can't wrap my head around this module. I know there is tree::simple and I think just Tree? But I can't really find any tutorials on how to actually use with a list or a array. The heap sort is right, cause it's sorting the list after the tree has been posted but I can't figure how to draw the tree correctly, then again outputting has never been my strong suit on any language. I think it's not grabbing the data from the file? least that is my idea but i'm not confident enough to be sure. here is my code so far.
#!/usr/bin/perl
use 5.006;
use strict;
use warnings;
use Tree::DAG_Node;
process_data(read_file('data.txt'));
process_data((3,1,4,1,5,9,2,6,5,3,6));
sub read_file{
my($filename)=#_;
my #data=();
my #words;
open(my $fh, "<", $filename)
or die "Could not open file: $!\n";
while(<$fh>){
chomp;
#words = split(' ');
foreach my $word(#words) {
push #data, $word;
}
}
close $fh;
return #data;
}
sub heap_sort {
my ($a) = #_;
my $n = #$a;
for (my $i = ($n - 2) / 2; $i >= 0; $i--) {
down_heap($a, $n, $i);
}
for (my $i = 0; $i < $n; $i++) {
my $t = $a->[$n - $i - 1];
$a->[$n - $i - 1] = $a->[0];
$a->[0] = $t;
down_heap($a, $n - $i - 1, 0);
}
}
sub down_heap {
my ($a, $n, $i) = #_;
while (1) {
my $j = max($a, $n, $i, 2 * $i + 1, 2 * $i + 2);
last if $j == $i;
my $t = $a->[$i];
$a->[$i] = $a->[$j];
$a->[$j] = $t;
$i = $j;
}
sub max {
my ($a, $n, $i, $j, $k) = #_;
my $m = $i;
$m = $j if $j < $n && $a->[$j] > $a->[$m];
$m = $k if $k < $n && $a->[$k] > $a->[$m];
return $m;
}
}
sub draw_tree{
my(#data)=#_;
my $root = Tree::DAG_Node->new;
$root->name($_[0]);
$root->new_daughter->name($_) for ('1'..'10');
my #names = #data;
my $count =0;
for my $n ($root->daughters) {
for (split //, $names[$count++]) {
$n->new_daughter->name($_)
}
}
print map "$_\n", #{$root->draw_ascii_tree};
}
sub process_data{
my(#data)=#_;
my #a = #data;
print "#a\n";
print "\n";
heap_sort(\#a);
print "\n";
print "#a\n";
print "\n";
draw_tree(#a);
}
and here is the output I am getting so far.
10,4,5,2,1,7
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
Use of uninitialized value in split at HEAPSORTtree.pl line 77.
|
<10,4,5,2,1,7>
/---------------------------------------+--
-+---+---+---+---+---+---+---\
| |
| | | | | | | |
<1> <2>
<3> <4> <5> <6> <7> <8> <9> <10>
/-----------------+-----------------+---+---+---+---+---+---+---+---+---\
| | | | | | | | | | | |
<1> <Tree::DAG_Node=HASH(0x4b32dc)> <,> <4> <,> <5> <,> <2> <,> <1> <,> <7>
10,4,5,2,1,7
3 1 4 1 5 9 2 6 5 3 6
|
<1>
/---+---+---+---+---+---+---+---+---\
| | | | | | | | | |
<1> <2> <3> <4> <5> <6> <7> <8> <9> <10>
| | | | | | | | | |
<1> <1> <2> <3> <3> <4> <5> <5> <6> <9>
1 1 2 3 3 4 5 5 6 9 6
Press any key to continue . . .
the output I want is similar to this
|
<root>
/-------+-------+-------\
| | | |
<1> <d> <e> <f>
/---+---\ |
| | | <3>
<a> <b> <c> /---+---\
| | |
<g> <h> <i>

Merging of columns in text file

Input of the text file
A | 1 | def | 1432
A | 1 | ffr | 1234
A | 1 | dfs | 3241
A | 2 | asf | 2213
Desired Output
A | 1 | def 1432,ffr 1234,dfs 3241
A | 2 | asf 2213
Merging values related to 2nd column in a single row
And here is a Perl attempt:
perl -F'\s+\|\s+' -alne '
$a{$F[1]} .= "$F[2] $F[3],";
END {
$_ = "A | $_ | $a{$_}", s/,$//, print for sort keys %a;
}' FILE
Your problem is not well specified, but here's a step towards a solution:
awk -F\| '{ a[$1 "|" $2] = a[$1 "|" $2 ] "," $3 $4 }
END { for( x in a ) print x a[x]}' input |
sed 's/,/|/' # Trim leading comma
This will incorrectly delete the first comma in either of the first 2 columns instead of the incorrectly inserted leading comma in the 3rd column of output, and sorts on both of the first 2 columns rather than just the 2nd. Also, the order of the output will be different than the input. There are probably other issues, but this may help.
awk '
BEGIN { FS = " \\| "; OFS = SUBSEP = " | " }
{
val[$1,$2] = val[$1,$2] sep[$1,$2] $3 " " $4
sep[$1,$2] = ","
}
END { for (key in val) print key, val[key] }
'
This will likely not preserve the order of the input. Also, it uses both the 1st and 2nd columns as the key, but as you say the 1st column does not change it is irrelevant.

splitting a complex line into an array

I have an array where the elements look like this (whitespaces included)
#array = (
" 795 0| 1",
" 5 135| 17",
" 12 161| 17",
" 244 22| 17",
" 11 25| 17",
" 249 389| 17",
" 22383 443| 17"
);
I need to take an element out
" 795 0| 1"
and split it into 3 numbers getting rid of the white spaces and "|" in each line.
#new_array =("795","0","1");
The problem I'm having is that the whitespace and size of the numbers varies.
I would use a regexp matching only the numbers:
#!/usr/bin/perl
use strict ;
use warnings ;
use Data::Dumper ;
my #array = (
" 795 0| 1",
" 5 135| 17",
" 12 161| 17",
" 244 22| 17",
" 11 25| 17",
" 249 389| 17",
" 22383 443| 17"
);
foreach my $item ( #array ) {
my #tmp = $item =~ m/(\d+)/g ;
printf "'%s' => %s\n" , $item , Dumper( \#tmp ) ;
}
This will also work if the string has no whitespace in the beginning.
One way:
my ($empty, #array) = split(/\|?\s+/, " 795 0| 1");
Perhaps something easier and readable like this could help:
#!/usr/bin/perl
use strict;
use warnings;
my #array = (
" 795 0| 1",
" 5 135| 17",
" 12 161| 17",
" 244 22| 17",
" 11 25| 17",
" 249 389| 17",
" 22383 443| 17"
);
my $eggs;
for my $spam (#array) {
chomp $spam;
$spam =~ s/^\s*//;
push #$eggs, [ split ( /\|?\s+/, $spam ) ];
}
for my $egg (#$eggs) {
print join (", ", #$egg);
print "\n";
}
and the result is:
795, 0, 1
5, 135, 17
12, 161, 17
244, 22, 17
11, 25, 17
249, 389, 17
22383, 443, 17
If you're spacing is truly uniform, you could use Perl's unpack to get at the data. See http://perldoc.perl.org/perlpacktut.html#Packing-Text