I have a Perl script that compares two sets of data loaded into two arrays, and I'm trying to make the comparison more efficient. Currently the code is as follows:
foreach(#{FILE_DATA}) {
if((++$file_current_linenum % 200) == 0) {
$progress = int($file_current_linenum / $file_total_lines * 10000) / 100;
logg("Processed $file_current_linenum file rows, $progress%, $mismatches mismatches.");
}
$file_current_line = $_;
$match_found = 0;
foreach(#{DB_DATA}) {
$db_current_line = $_;
if($file_current_line->{"channel"} == $db_current_line->{"channel"} ) {
if ($file_current_line->{"checksum"} == $db_current_line->{"checksum"} &&
$file_current_line->{"time"} > ($db_current_line->{"date_part"} - $TIME_MATCH_TOLERANCE) &&
$file_current_line->{"time"} < ($db_current_line->{"date_part"} + $TIME_MATCH_TOLERANCE) ){
$match_found = 1;
last; # break;
}
}
}
if($match_found != 1) {
push(#results, $file_current_line);
$mismatches++;
}
}
My first thought would be to remove matches from both arrays to reduce the pool size, would that affect the iterators position?
Both sets of data can have up to a couple of million elements and the comparison can take a few hours to complete.
Your solution is O(DB * FILE).
The following is O(DB + FILE) if and only if there never more than a few lines with the same channel and checksum:
my %DB_DATA;
for my $db_line (#DB_DATA) {
push #{ $DB_DATA{ $db_line->{channel} }{ $db_line->{checksum} } }, $db_line;
}
for my $file_line_idx (0..$#FILE_DATA) {
my $file_line = $FILE_DATA[$file_line_idx];
my $found = 0;
if (my $r1 = $DB_DATA{ $file_line->{channel} } ) {
if (my $r2 = $r1->{ $file_line->{checksum} } ) {
my $file_time = $file_line->{time};
for my $db_line (#$r2) {
my $db_time = $db_line->{date_part};
if (abs($file_time - $db_time) < $TIME_MATCH_TOLERANCE) {
$found = 1;
last;
}
}
}
}
push #mismatches, $file_line if !$found;
if ((($file_line_idx+1) % 200) == 0) {
logg(sprintf("Processed %d file rows, %d%, %d mismatches.",
$file_line_idx+1,
int(($file_line_idx+1)/#FILE_DATA) * 100,
0+#mismatches,
));
}
}
The following is O(DB + FILE) even if there are many lines with the same channel and checksum, but uses a lot of memory if $TIME_MATCH_TOLERANCE is big:
my %DB_DATA;
for my $db_line (#DB_DATA) {
for my $db_time (
$db_line->{date_part} - $TIME_MATCH_TOLERANCE + 1
..
$db_line->{date_part} + $TIME_MATCH_TOLERANCE - 1
) {
++$DB_DATA{ $db_line->{channel} }{ $db_line->{checksum} }{$db_time};
}
}
for my $file_line_idx (0..$#FILE_DATA) {
my $file_line = $FILE_DATA[$file_line_idx];
my $found = 0;
if (my $r1 = $DB_DATA{ $file_line->{channel} } ) {
if (my $r2 = $r1->{ $file_line->{checksum} } ) {
if ($r2->{ $file_line->{time} } {
$found = 1;
last;
}
}
}
push #mismatches, $file_line if !$found;
if ((($file_line_idx+1) % 200) == 0) {
logg(sprintf("Processed %d file rows, %d%, %d mismatches.",
$file_line_idx+1,
int(($file_line_idx+1)/#FILE_DATA) * 100,
0+#mismatches,
));
}
}
Note: Assumes the timestamps are integers. If they're not, convert them to integers before using them as keys.
The following is O((DB + FILE) log DB) [ which is very close to O(DB + FILE) ] even if there are many lines with the same channel and checksum, and uses minimal memory:
sub binsearch(&\#) {
my ($compare, $array) = #_;
my $i = 0;
my $j = $#$array;
return 0 if $j == -1;
while (1) {
my $k = int(($i+$j)/2);
for ($array->[$k]) {
my $cmp = $compare->()
or return 1;
if ($cmp < 0) {
$j = $k-1;
return 0 if $i > $j;
} else {
$i = $k+1;
return 0 if $i > $j;
}
}
}
}
my %DB_DATA;
for my $db_line (#DB_DATA) {
push #{ $DB_DATA{ $db_line->{channel} }{ $db_line->{checksum} } }, $db_line;
}
for my $r1 (values(%DB_DATA)) {
for my $r2 (values(%$r1)) {
#$r2 = sort { $a->{date_part} <=> $b->{date_part} } #$r2;
}
}
for my $file_line_idx (0..$#FILE_DATA) {
my $file_line = $FILE_DATA[$file_line_idx];
my $found = 0;
if (my $r1 = $DB_DATA{ $file_line->{channel} } ) {
if (my $r2 = $r1->{ $file_line->{checksum} } ) {
my $file_time = $file_line->{time};
my $min_db_time = $file_time - $TIME_MATCH_TOLERANCE;
my $max_db_time = $file_time + $TIME_MATCH_TOLERANCE;
if ( binsearch {
$_->{date_part} >= $max_db_time ? -1
: $_->{date_part} <= $min_db_time ? +1
: 0
} #$r2 ) {
$found = 1;
last;
}
}
}
push #mismatches, $file_line if !$found;
if ((($file_line_idx+1) % 200) == 0) {
logg(sprintf("Processed %d file rows, %d%, %d mismatches.",
$file_line_idx+1,
int(($file_line_idx+1)/#FILE_DATA) * 100,
0+#mismatches,
));
}
}
You could probably reduce the time significantly by pre-building a hash from DB_DATA, using the concatenation of the "channel" and "checksum" values as the key, and each value being a list of all of the DB_DATA entries with that channel and checksum. That way, for each FILE_DATA entry, you only need to check that list.
If there are a lot of entries with a given channel and checksum, you try to improve even more by sorting them by date_part, and then trying to binary search to find a valid entry.
If there are very few entries with a given channel and checksum, this should reduce your run time by a factor of a million or so, since it reduces the run time from O($#FILE_DATA * $#DB_DATA) to O($#FILE_DATA + $#DB_DATA).
Related
Answer "the script used too much memory".
I start a few start to read text file line by line, and convert the text to blob, then send it to socket:
use experimental :pack;
sub heart-msg(Str $msg, Str $device-id --> Blob) {
my $heart-msg = $msg.substr(0, $msg.chars - 8);
my $header-buf = pack("H*", $heart-msg);
my $device-id-buf = pack("L*", $device-id);
$header-buf ~ $device-id-buf
}
sub deal-message(Str $msg, Str $device-id --> Blob) {
my $now = DateTime.now();
my $year = $now.year;
my $month = $now.month;
my $day = $now.day;
my $hour = $now.hour;
my $minute = $now.minute;
my $second = $now.second.Int;
my $check-number = 0;
my $head-msg = $msg.substr(0,4);
my $device-id-length = $msg.substr(4,2);
my $pf-code = $msg.substr(14, 2);
my $msg-length = $msg.substr(16, 4);
my $rel-time = $msg.substr(20, 4);
my $end-msg = $msg.substr(38, $msg.chars - 38 - 2);
my $head-msg-buf = pack("H*", $head-msg);
my $device-id-len-buf = pack("H*", $device-id-length);
my $device-id-buf = pack("L*", $device-id);
my $pf-code-buf = pack("H*", $pf-code);
my $msg-length-buf = pack("H*", $msg-length);
my $rel-time-buf = pack("H*", $rel-time);
my $year-buf = pack("S*", $year);
my $month-buf = pack("C*", $month);
my $day-buf = pack("C*", $day);
my $hour-buf = pack("C*", $hour);
my $minute-buf = pack("C*", $minute);
my $second-buf = pack("C*", $second);
my $end-msg-buf = pack("H*", $end-msg);
my #bufs = [$device-id-len-buf, $device-id-buf, $pf-code-buf, $msg-length-buf,
$rel-time-buf, $year-buf, $month-buf, $day-buf, $hour-buf, $minute-buf, $second-buf,
$end-msg-buf];
for #bufs -> $byte {
my $byte_sum = [+] $byte.contents;
$check-number += $byte_sum;
}
$check-number = $check-number % 256;
my $checked-msg-buf = pack("C*", $check-number);
[~] $head-msg-buf, |#bufs, $checked-msg-buf
}
sub deal-data(Str $msg, Str $device-id --> Blob) {
my $header = $msg.substr(0, 4);
given $header {
when '6868' {
return deal-message($msg, $device-id);
}
when '7468' {
return heart-msg($msg, $device-id);
}
default { return Buf.new }
}
}
sub MAIN(
:$host = '10.0.0.77',
Int() :$port = 4444,
Rat() :$interval = 0.001,
:$file = 'data.txt',
Int() :$device-num = 169) {
my $conn = IO::Socket::INET.new(:$host, :$port);
my #devices = "modelId.txt".IO.lines;
my #promises = gather for #devices[159..$device-num] -> $device-id {
take start {
my $f = lazy $file.IO.lines;
my $iterator = $f.iterator;
react {
whenever Supply.interval($interval) {
try {
my $line := $iterator.pull-one;
if $line =:= IterationEnd {
done;
} else {
my $blob = deal-data($line.chomp.split(/\s+/).tail, $device-id.Str);
#say $blob;
$conn.write($blob);
}
}
QUIT {
$conn.close;
say 'connecting closed';
default {
say .^name, '→ ', .Str;
say "handled in line $?LINE";
}
}
LAST {
say "Connection closed";
done;
}
}
}
}
}
await #promises;
}
When running on CentOS 7.4(12 core, 32G RAM), after a few seconds, my script was killed by system. When running on Win11(12 core, 16G RAM), it's OK.
So how to debug this script?
Here is the little script I created to do HTTP transactions from a file with a list of URLs. The problem is that it's not able to do HTTP transactions as fast as I would like. More precisely, I set the rate to be 200/seconds, but it was able to send only at about 50/second. The server is powerful enough to handle 100/second.
This was run on a powerful PC with E5-1650 CPU and 64GB of RAM running Ubuntu 14.04 desktop. When the script runs, the CPU usage is only about 12%. The command I used was perl httpStresser.pl urlList rate 200.
Any idea why?
use AnyEvent;
use EV;
use AnyEvent::HTTP;
use AnyEvent::Handle;
use Time::HiRes qw( gettimeofday );
my $expectedRespCode = 200;
my $rate = 1;
my #urls = ();
readUrls(shift);
my $numOfUrls = $#urls;
my $start = time();
my $printed = 0; #have we printed the completion msg.
my $gId = 0;
my $spawned;
my #ctx = ();
my $i;
for ($i=0; $i<=$#ARGV; $i++) {
if ($ARGV[$i] =~ /^expect/) {
$expectedRespCode = $ARGV[$i+1];
$i++;
} elsif ($ARGV[$i] =~ /^rate/) {
$rate = $ARGV[$i+1];
print "rate is now $rate\n";
$i++;
} elsif ($ARGV[$i] =~ /^skip/) {
$gId = $ARGV[$i+1];
$i++;
} else {
die "only max, stayup are supported\n";
}
}
my $spawned = 0;
my $w = AnyEvent->condvar;
$| = 1;
my $start = getTS();
my $_timer;
$_timer = AnyEvent->timer(after => 0, interval => 0.001, cb => ::timeoutHandler);
$w->recv;
sub kickoff {
my $id = $gId ++;
if ($id > $numOfUrls) {
if ($printed == 0) {
print "done!!\n"; $printed = 1;
}
return;
}
#print "$id\n";
http_get $urls[$id], headers => { }, sub {
my $statusCode = $_[1]->{Status};
#printf "status $statusCode %d\n", time() - $start;
if (($id % 100) == 0) {
print "$id\n";
}
if ($statusCode != $expectedRespCode) {
print "unexpected resp code $id:$statusCode $urls[$id]\n";
}
};
}
sub timeoutHandler {
#print time(), "|\n";
if (! defined $start) {
$start = getTS(); kickoff(); $spawned = 1; return;
}
my $delta = getTS() - $start;
my $target = $delta * $rate;
#printf "%.4f %4d $spawned\n", $delta, $target;
for (; $spawned <= $target; $spawned++) {
kickoff();
}
if ($delta >= 1.0 ) {
$start += 1.0; $spawned = 0;
}
}
sub readUrls {
my $fname = shift;
my $line;
open FD, $fname || die "Failed to open $fname $!\n";
while (<FD>) {
chomp($line = $_);
push #urls, $line;
}
close FD;
}
sub getTS {
my ($seconds, $microseconds) = gettimeofday;
return $seconds + (0.0+ $microseconds)/1000000.0;
}
I am trying to make this calendar start on Sunday instead of Monday. I've looked through all the help files I can Google on this topic & cannot find any that have any lines of code that I can reference. Am I missing some? Or can some one point me to the point I need to change in order to make it start on Sunday instead of Monday?
<?php
/**
* Copyright (C) 2006-2014 Center Stage Software
* 1191 Luxton Street, Seaside, California 93955
* All Rights Reserved
*/
// ensure that this file is called up by another file
defined('_VALID_ACCESS') or die('Direct access of this file is prohibited.');
/**
* renderEventCalendar - Creates a calendar display of events for one month.
*
* #global (Array) $cstage
*/
function renderEventCalendar() {
global $cstage, $path;
// Result variable.
$calendar = '';
// Calculate first and last day of the month.
$firstDayTimestamp = strtotime($_SESSION[SYS_USER]['search']['Month'].'-01 07:00:00');
list($year,$month) = explode("-",$_SESSION[SYS_USER]['search']['Month']);
if( $month == 12 ) {
$month = 00;
$year += 1;
}
$lastDayTimestamp = strtotime("$year-".($month+1).'-01 08:00:00') - 86400; // minus 24 hours and add 1-day-light-savings-hour
// TODO: Remove the following calendar debugging code.
// print "<h1>first=$firstDayTimestamp; last=$lastDayTimestamp</h1>";
// Build query to retrieve entries for that month.
$aryEvents = array();
$extraSqlFields = '';
$extraSqlJoins = '';
$extraSqlConditions = '';
if( !empty($_SESSION[SYS_USER]['domain']) ) {
$extraSqlJoins .= 'LEFT JOIN "domainlist" AS "domain2" ON "domain2"."master_id" = "master"."master_id" ';
$extraSqlConditions .= sprintf('AND "domain2"."domain"=\'%s\' '
,$_SESSION[SYS_USER]['domain']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Theatre']) ) {
$extraSqlConditions .= sprintf('AND "master"."theatre"=\'%s\' '
,$_SESSION[SYS_USER]['search']['Theatre']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Location']) ) {
$extraSqlConditions .= sprintf('AND "master"."location"=\'%s\' '
,$_SESSION[SYS_USER]['search']['Location']
);
}
if( !empty($_SESSION[SYS_USER]['search']['EventType']) ) {
$extraSqlConditions .= sprintf('AND "master"."event_types_id"=\'%s\' '
,$_SESSION[SYS_USER]['search']['EventType']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Month']) ) {
$extraSqlConditions .= sprintf('AND "shows"."show_date" >= \'%s\' AND "shows"."show_date" <= \'%s\' '
,date('Y-m-d',$firstDayTimestamp)
,date('Y-m-d',$lastDayTimestamp)
);
}
if( $cstage['rttEnable'] ) {
$extraSqlFields .= ', "rtt"."label" AS "rtt_label"';
$extraSqlJoins .= 'LEFT JOIN "rtt" ON "master"."rtt_id" = "rtt"."rtt_id" ';
} else {
$extraSqlConditions .= 'AND "master"."rtt_id"=0 ';
}
if( $cstage['enableEventPriceListTest'] ) {
$aryGroups = array($cstage['tixDomain']);
if( !empty($_SESSION[SYS_USER]['info']) && count($_SESSION[SYS_USER]['info']['groupDomains']) > 0 ) {
$aryGroups = array_merge($aryGroups, $_SESSION[SYS_USER]['info']['groupDomains']);
}
$extraSqlFields .= ', GROUP_CONCAT(DISTINCT "prices"."prices_id" SEPARATOR \';\') AS "priceidlist"';
$extraSqlFields .= ', GROUP_CONCAT(DISTINCT CONCAT("price_category"."label",\' \', "prices"."printed_as") SEPARATOR \', \') AS "pricelist"';
$extraSqlJoins .= ' INNER JOIN "price_category" ON "price_category"."master_id" = "master"."master_id" OR "price_category"."master_id"=0 INNER JOIN "prices" ON "price_category"."price_category_id" = "prices"."price_category_id" INNER JOIN "price_category_domain" ON "price_category_domain"."price_category_id" = "price_category"."price_category_id"';
$extraSqlConditions .= sprintf('AND ("price_category"."master_id"="shows"."master_id" OR "price_category"."master_id"=0) AND ("prices"."shows_id"="shows"."shows_id" OR "prices"."shows_id"=0) AND "prices"."onsale"<=CONCAT("shows"."show_date", \' 00:00:00\') AND ("prices"."offsale">=CONCAT("shows"."show_date", \' 23:59:59\') OR "prices"."offsale" IS NULL) AND "price_category_domain"."domain" IN (\'%s\') '
,implode('\',\'', $aryGroups)
);
}
$now = date('Y-m-d H:i:s');
$query = sprintf('SELECT "master".*, "shows"."show_date", "shows"."show_time", "shows"."onsale" AS "min_onsale"%s FROM "shows" INNER JOIN "master" ON "master"."master_id" = "shows"."master_id" INNER JOIN "domainlist" ON "domainlist"."master_id" = "master"."master_id" %s WHERE "shows"."offsale" >= \'%s\' AND ("shows"."wt_offsale"=\'\' OR "shows"."wt_offsale"=0) AND "domainlist"."domain"=\'%s\' %s GROUP BY "shows"."shows_id"'
,$extraSqlFields
,$extraSqlJoins
,$now
,$cstage['tixDomain']
,$extraSqlConditions
);
$keyEventCalendar = 'eventCalendar_'.$cstage['dbDatabase'].sha1($query);
if( !empty($cstage['cache']) ) {
// Is the record cached to save on slow database connections?
$calendar = $cstage['cache']->load($keyEventCalendar);
}
if( !$calendar ) {
$result = $cstage['pdo']->query( $query );
while( $show = $result->fetch( PDO::FETCH_ASSOC ) ) {
$show['domainlist'] = $cstage['tixDomain'].';'.$_SESSION[SYS_USER]['domain'];
$show['comingSoon'] = false;
if( $now < $show['min_onsale'] ) {
$show['comingSoon'] = true;
}
if( $show['rtt_id'] > 0 ) {
$show['master_id'] = trim($show['rtt_label']).trim($show[]);
if( !$cstage['rttEnable'] ) {
$show = array();
}
}
$path->inc_once('_includes/libf_okEvent.php');
if( okEvent($show) ) {
// Save data into array for usage later
$extraSort = $cstage['useEventSortOrder'] === true ? sprintf('%05d',$show['sortorder']) : '';
$aryEvents[$show['show_date']][date('H:i',strtotime($show['show_time'])).$extraSort.$show['showname'].$show['master_id']] = $show;
}
}
// Start rendering calendar.
$calendar = "\r\n".'<table class="EventCalendar ui-widget-content ui-corner-all"><thead '._HEAD.'><tr><th colspan="7">'.lang('Calendar of events for').' '.date('Y F',strtotime($_SESSION[SYS_USER]['search']['Month'].'-02')).'</th></tr>'
. "\r\n".'<tr><th>'.lang('Sunday').'</th><th>'.lang('Monday').'</th><th>'.lang('Tuesday').'</th><th>'.lang('Wednesday').'</th><th>'.lang('Thursday').'</th><th>'.lang('Friday').'</th><th>'.lang('Saturday').'</th></tr></thead>'
. '<tbody>';
$dayOfWeekPadding = date('w',$firstDayTimestamp);
if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 6;
} else {
$dayOfWeekPadding -= 0;
}
if( $dayOfWeekPadding > 0 ) {
$calendar .= "\r\n<tr>";
}
for($day=7; $day < $dayOfWeekPadding; $day++) {
$calendar .= "\r\n<td class='EventCalendar_EmptyDate'> </td>";
}
$timeStamp = $firstDayTimestamp;
while( $timeStamp <= $lastDayTimestamp ) {
if( date('w',$timeStamp) == 0 ) {
$calendar .= "\r\n<tr>";
}
$dateKey = date('Y-m-d',$timeStamp);
$calendar .= "\r\n".'<td class="EventCalendar_Date" id="date'.$dateKey.'" onmouseover="tbl_colorchange(\'date'.$dateKey.'\', \'highlight\');" onmouseout="tbl_colorchange(\'date'.$dateKey.'\', \'normal\');"><span>'.date('d',$timeStamp).'</span>';
if( !empty($aryEvents[$dateKey]) ) {
ksort($aryEvents[$dateKey]);
$count = 0;
foreach( $aryEvents[$dateKey] as $key=>$show ) {
$cssClass = $count++ % 2 ? _ODD : _EVEN;
$rttUrl = ( $show['rtt_id'] > 0 ) ? '&rtt='.$show['rtt_id'] : '';
$strPriceList = (empty($show['pricelist']) ? '' : ' title="'.lang('Prices available').': '.$show['pricelist'].'"');
$calendar .= "\r\n<div {$cssClass}{$strPriceList}><a href='event-details.php?e={$show['master_id']}&date={$dateKey}{$rttUrl}'>{$show['']} # {$show['show_time']}</a></div>";
}
}
$calendar .= '</td>';
if( date('w',$timeStamp) == 0 ) {
$calendar .= "\r\n</tr>";
}
$timeStamp += 86400; // Get the next day (in seconds).
}
$dayOfWeekPadding = date('w',$timeStamp);
if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 6;
} else if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 0; // do not have an empty week of padding
} else {
$dayOfWeekPadding = 6 - $dayOfWeekPadding;
}
for($day=0; $day < $dayOfWeekPadding; $day++) {
$calendar .= "\r\n<td class='EventCalendar_EmptyDate'> </td>";
}
if( $dayOfWeekPadding > 0 ) {
$calendar .= "\r\n</tr>";
}
$calendar .= "\r\n</tbody></table>";
if( !empty($cstage['cache']) ) {
$cstage['cache']->save($calendar, $keyEventCalendar);
}
}
return $calendar;
}
This question already has an answer here:
Why does my file content/user input not match? (missing chomp canonical) [duplicate]
(1 answer)
Closed 8 years ago.
I have a symbol download from a database that produces this populates the symbol hash just fine. WHen I sort the keys I get this
foreach $symbol ( sort keys %symbol_hash ) {
print "$symbol\n ";
}
A AA AAL AAPL ABBV ABT ABT_SPIN ABX ACI ACN ACT ADBE ADI ADM ADSK AEIS AEO AES AET AFAM AGN AGU AIG AKAM AKS ALL ALNY ALR ALU AMAT AMGN AMP AMZN ANF ANN ANR APA APC ARCC
I have a unix config file which contains alot of information for many processes.
This is the config file
# Tick Size
# tr -d \ | sort -u
TickSizePostOpen = 1.00
TickSize = {
penny1 = {
TickSize = 0.00
members = {
IWM
QQQ
SPY
SPY_TEST
}
}
penny = {
TickSize = </0.000/0.00/0.00
members = {
A
AA
AAL
AAPL
ABT
ABT_SPIN
ZNGA
}
}
notpenny = {
TickSize = </9/9.99/9.99
}
}
BIPP.QuoterOx = {
Cup1and2 = {
BIPP.QuoterOx = BIPP-ox-1
members = {
Cup_1
Cup_2
}
}
TRAP.PxByGroup = 1
TRAP.Px = {
group1 = {
TRAP.Px = OPTxxxxxx
members = {
px.TRAP.1
}
}
group2 = {
TRAP.Px = OPTxxxxxx
members = {
px.TRAP.2
}
}
TRAP.QuoterOx = {
Cup0 = {
TRAP.QuoterOx = QESxxxxx
members = {
Cup_0
Cup_99
}
}
Cup1and4and10 = {
TRAP.QuoterOx = ise-ox-1-4-10-dti
members = {
Cup_1
Cup_4
Cup_10
}
}
Cup56 = {
TRAP.AuctionOx = ise-ox-56-ecl
members = {
Cup_56
}
}
}
TRAP.RotateQuote = {
rotatenames = {
TRAP.RotateQuote = 1
members = {
AAPL
ADY
AEIS
AFAM
AGP
ALNY
ZINC
}
}
}
Underlying = {
Cup0 = {
Underlying = MHR
members = {
Cup_0
}
}
g1 = {
Underlying = CEL
members = {
Cup_1
}
}
}
BIPP.Px = {
group1 = {
BIPP.Px = BOXPXMHR1
members = {
px.BIPP.1
}
}
group2 = {
BIPP.Px = BOXPXMHR2
members = {
px.BIPP.2
}
}
}
TWIG.Px = {
AB = {
TWIG.Px = TWIGPXMHR1
members = {
A
B
}
}
CD = {
TWIG.Px = TWIGPXMHR2
members = {
C
D
}
}
NOPQR = {
TWIG.Px = TWIGPXMHR6
members = {
N
O
P
Q
R
}
}
STUV = {
TWIG.Px = TWIGPXMHR7
members = {
S
T
U
V
}
}
WXYZ = {
TWIG.Px = TWIGPXMHR8
members = {
W
X
Y
Z
}
}
}
What I am trying to do is download symbols from a database, populate a symbol hash(which works), then load in the config file file, parse it down to its barest elements and using the symbol hash as a filter, populate the penny hash. So if an element from the stripped down config file is in the symbol hash, put it in the penny hash.
#!/perl/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
my $dbUser = 'yeah';
my $dbPass = 'boy'; # <--- was missing closing single quote
my $dbSid = 'yeah.boy';
my $dbh = DBI->connect( "dbi:Oracle:$dbSid", "$dbUser", "$dbPass" ) or die("Couldn't connect: $!");
my $penny_file = "/data/wowmom.cfg";
my %penny_hash = ();
my %symbol_hash = ();
my $query = "select alotof stuff from yeah.boy ";
if ( !$dbh ) {
print "Error connecting to Database: $DBI::errstr\n";
}
my $cur_msg = $dbh->prepare($query) or die "\n\nCould not prepare statement: " . dbh->errstr;
$cur_msg->execute();
while ( my #row = $cur_msg->fetchrow_array ) {
$symbol_hash{ $row[0] } = 1;
}
open( my $penny_fh, '<', "$penny_file" ) or die "Can't open $penny_file for reading: $!";
while (<$penny_fh>) {
next unless /\S/;
#print unless /[#{}=]/ ; # try this - the parse works!
if ( !/[#{}=]/ ) {
if ( $symbol_hash{$_} ) {
$penny_hash{$_} = 1; # does not populate
}
}
}
#foreach my $symbol ( sort keys %symbol_hash ) {
# print "$symbol\n ";
#} # works
print Dumper( \%penny_hash ); #does not work
#print Dumper(\%symbol_hash) ; # works
#foreach my $penny ( sort keys %penny_hash ) {
# print "$penny\n ";
#}
the Dumper(\%penny_hash) prints nothing.
Don't forget to chomp your input:
while (<$penny_fh>) {
chomp; # <-- remove line endings before string comparison
I wrote this code using C++ example from net to rotate my set of points in 3D.
##matrix is points and their 3D coordinates.
#rotated_matrix = rotate_l(\#matrix, 0);
sub rotate_l {
my $ref = $_[0];
my $x = 0;
my $step = 1;
#if rotx
if ($_[1] == 0) {
while ($$ref[$x][0]) {
$$ref[$x][1] += ($$ref[$x][1]*cos($step) - $$ref[$x][2]*sin($step));
$$ref[$x][2] += ($$ref[$x][1]*sin($step) + $$ref[$x][2]*cos($step));
$x++;
}
}
#if roty
if ($_[1] == 1) {
while ($$ref[$x][0]) {
$$ref[$x][0] += ( $$ref[$x][0]*cos($step) + $$ref[$x][2]*sin($step));
$$ref[$x][2] += (-$$ref[$x][0]*sin($step) + $$ref[$x][2]*cos($step));
$x++;
}
}
#if rotz
if ($_[1] == 2) {
while ($$ref[$x][0]) {
$$ref[$x][0] += ($$ref[$x][0]*cos($step) - $$ref[$x][1]*sin($step));
$$ref[$x][1] += ($$ref[$x][0]*sin($step) + $$ref[$x][1]*cos($step));
$x++;
}
}
return #$ref;
}
But something is wrong. Object size/form fails to stay same. And my math is not that good to realize why. I even not sure I need += or =?
Thx amon. As suggested this works:
##matrix is points and their 3D coordinates.
#rotated_matrix = rotate_l(\#matrix, 0);
sub rotate_l {
my $ref = $_[0];
my $x = 0;
my $step = pi;
#if rotx
if ($_[1] == 0) {
while ($$ref[$x][0]) {
$$ref[$x][1] = ($$ref[$x][1]*cos($step) - $$ref[$x][2]*sin($step));
$$ref[$x][2] = ($$ref[$x][1]*sin($step) + $$ref[$x][2]*cos($step));
$x++;
}
}
#if roty
if ($_[1] == 1) {
while ($$ref[$x][0]) {
$$ref[$x][0] = ( $$ref[$x][0]*cos($step) + $$ref[$x][2]*sin($step));
$$ref[$x][2] = (-$$ref[$x][0]*sin($step) + $$ref[$x][2]*cos($step));
$x++;
}
}
#if rotz
if ($_[1] == 2) {
while ($$ref[$x][0]) {
$$ref[$x][0] = ($$ref[$x][0]*cos($step) - $$ref[$x][1]*sin($step));
$$ref[$x][1] = ($$ref[$x][0]*sin($step) + $$ref[$x][1]*cos($step));
$x++;
}
}
return #$ref;
}
If I need to rotate not around (0,0,0), but against other point the best way is to translate to 0 point rotate and then translate back?
Just as an example of what I meant by what I recommend you do:
#! /usr/bin/env perl
use common::sense;
use YAML 'Dump';
sub translate {
my ($deltaX, $deltaY) = #{pop()}; # <-- don't mind this.
for (#_) { # <--- this is the important part
$_->[0] += $deltaX;
$_->[1] += $deltaY;
}
#_
}
my #points = ([0, 1], [0, -1], [-1, 0], [1, 0]);
print Dump([translate #points, [2, 2]]);
my $box = \#points;
print Dump([translate #$box, [5, 0]]);