I'm just trying to get my head around a multidimensional array creation from a perl script i'm currently converting to Ruby, I have 0 experience in Perl, as in i opened my first Perl script this morning.
Here is the original loop:
my $tl = {};
for my $zoom ($zoommin..$zoommax) {
my $txmin = lon2tilex($lonmin, $zoom);
my $txmax = lon2tilex($lonmax, $zoom);
# Note that y=0 is near lat=+85.0511 and y=max is near
# lat=-85.0511, so lat2tiley is monotonically decreasing.
my $tymin = lat2tiley($latmax, $zoom);
my $tymax = lat2tiley($latmin, $zoom);
my $ntx = $txmax - $txmin + 1;
my $nty = $tymax - $tymin + 1;
printf "Schedule %d (%d x %d) tiles for zoom level %d for download ...\n",
$ntx*$nty, $ntx, $nty, $zoom
unless $opt{quiet};
$tl->{$zoom} = [];
for my $tx ($txmin..$txmax) {
for my $ty ($tymin..$tymax) {
push #{$tl->{$zoom}},
{ xyz => [ $tx, $ty, $zoom ] };
}
}
}
and what i have so far in Ruby:
tl = []
for zoom in zoommin..zoommax
txmin = cm.tiles.xtile(lonmin,zoom)
txmax = cm.tiles.xtile(lonmax,zoom)
tymin = cm.tiles.ytile(latmax,zoom)
tymax = cm.tiles.ytile(latmin,zoom)
ntx = txmax - txmin + 1
nty = tymax - tymin + 1
tl[zoom] = []
for tx in txmin..txmax
for ty in tymin..tymax
tl[zoom] << xyz = [tx,ty,zoom]
puts tl
end
end
end
The part i'm unsure of is nested right at the root of the loops, push #{$tl->{$zoom}},{ xyz => [ $tx, $ty, $zoom ] };
I'm sure this will be very simple for a seasoned Perl programmer, thanks! `
The Perl code is building up a complex data structure in $tl -- hash, array, hash, array:
$tl{$zoom}[i]{xyz}[j] = $tx # j = 0
$tl{$zoom}[i]{xyz}[j] = $ty # j = 1
$tl{$zoom}[i]{xyz}[j] = $zoom # j = 2
So I think the key line in your Ruby code should be like this:
tl[zoom] << { 'xzy' => [tx,ty,zoom] }
Note also that the root item ($tl) refers to a hash in the Perl code, while your Ruby code initializes it to be an array. That difference might cause problems for you, depending on the values that $zoom takes.
Related
How to read by the number at each iteration of the loop? Dynamic work is important, (not once to read the entire line and convert to an array), at each iteration, take one number from the file string and work with it. How to do it right?
input.txt :
5
1 7 5 2 3
Work with 2nd line of the file.
fin = File.open("input.txt", "r")
fout = File.open("output.txt", "w")
n = fin.readline.to_i
heap_min = Heap.new(:min)
heap_max = Heap.new(:max)
for i in 1..n
a = fin.read.to_i #code here <--
heap_max.push(a)
if heap_max.size > heap_min.size
tmp = heap_max.top
heap_max.pop
heap_min.push(tmp)
end
if heap_min.size > heap_max.size
tmp = heap_min.top
heap_min.pop
heap_max.push(tmp)
end
if heap_max.size == heap_min.size
heap_max.top > heap_min.top ? median = heap_min.top : median = heap_max.top
else
median = heap_max.top
end
fout.print(median, " ")
end
If you're 100% sure that your file separate numbers by space you can try this :
a = fin.gets(' ', -1).to_i
Read the 2nd line of a file:
line2 = File.readlines('input.txt')[1]
Convert it to an array of integers:
array = line2.split(' ').map(&:to_i).compact
I have this structure:
$ArrayX = [8349310431,8349314513,......]
$ArrayY = [667984788,667987788,......]
$ArrayZ = [148507632380,153294624079,.....]
$range_map = $ArrayX.zip([$ArrayY.map(&:to_i),
$ArrayZ.map(&:to_i)].transpose).sort
puts $range_map ={[8349310431=>[667984788, 148507632380],
8349314513=>[667987788, 153294624079]}
I need the key to be compared with the rest of the keys and if the subtraction between keys is lower than 100, that key to print
I corrected your code also as per your need, and solved further,
$ArrayX = [8349310431,8349314513]
$ArrayY = [667984788,667987788]
$ArrayZ = [148507632380,153294624079]
$range_map = $ArrayX.zip([$ArrayY.map(&:to_i), $ArrayZ.map(&:to_i)].transpose).sort
$ArrayX = [8349310431,8349314513]
=> [8349310431, 8349314513]
$ArrayY = [667984788,667987788]
=> [667984788, 667987788]
$ArrayZ = [148507632380,153294624079]
=> [148507632380, 153294624079]
$range_map = Hash[$ArrayX.zip([$ArrayY.map(&:to_i), $ArrayZ.map(&:to_i)].transpose).sort]
=> {8349310431=>[667984788, 148507632380], 8349314513=>[667987788, 153294624079]}
keys = $range_map.keys
valid_keys = keys.select { |k| keys.detect { |x| (x-k).abs > 100 } }
$range_map.slice(*valid_keys)
If particular key is having difference more than 100 with one of rest of keys then it will be valid for filtering.
I am using powerbuilder 11.2 and I have a pbl that creates a main screen. The user enters an order number in the textbox and hit enter and it fills in data in the bottom of the screen. I am trying to get debugging to hit a breakpoint in my function but it seems to ignore the breakpoint. Is there a way to break into the function? I have a variable I need to evaluate and I can't seem to get into the function while running. Here is the code:
Decimal{2} ld_total_hrs,ld_load_hrs,ld_unload_hrs
long ll_stops_rowcount, ll_row, ll_type, ll_ord_number, ll_rd_rowcount
datetime ldt_1st_stop, ldt_last_stop, ldt_start_time, ldt_end_time, ldt_deliver_time
string ls_dest_id, ls_type, ls_pay_id, ls_ref_number, ls_pay_leg_config
boolean lb_first_drop = TRUE
ld_load_hrs = 0
ld_unload_hrs = 0
SetNull(ldt_deliver_time)
ll_stops_rowcount = dw_trip.RowCount()
If ll_stops_rowcount < 1 then Return 0
For ll_row = 1 to ll_stops_rowcount
If ll_row = 1 then
ldt_1st_stop = dw_trip.GetItemDateTime ( 1, "stops_stp_arrivaldate" )
End if
If dw_trip.GetItemString(ll_row,"stops_stp_type") = "PUP" then
ldt_start_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_arrivaldate")
ldt_end_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_departuredate")
ld_load_hrs = ld_load_hrs + (f_datetimediff(ldt_start_time,ldt_end_time)/60)/60
End if
If dw_trip.GetItemString(ll_row,"stops_stp_type") = "DRP" then
ldt_start_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_arrivaldate")
ldt_end_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_departuredate")
ld_unload_hrs = ld_unload_hrs + (f_datetimediff(ldt_start_time,ldt_end_time)/60)/60
// get the first drops info for the report if paylegaslane is true else get last drop
ls_pay_leg_config = is_PayLegConfig
If is_CompanyOverride=true then
ls_pay_leg_config = "ByLeg"
End if
//TGRIFFIT - PayLegConfig = 'ByLeg' in TMW is equivalent to 'PayLegAsLane = 'Y' in FSS
if Upper(ls_pay_leg_config) = 'BYLEG' then
If lb_first_drop Then
ldt_deliver_time = ldt_end_time
ls_dest_id = dw_trip.GetItemString(ll_row,"stops_cmp_id")
ls_ref_number = dw_trip.GetItemString(ll_row,"stops_stp_refnum")
lb_first_drop = FALSE
End if
else
ldt_deliver_time = ldt_end_time
ls_dest_id = dw_trip.GetItemString(ll_row,"stops_cmp_id")
ls_ref_number = dw_trip.GetItemString(ll_row,"stops_stp_refnum")
end if
End if
Next
ldt_last_stop = dw_trip.GetItemDateTime ( ll_stops_rowcount, "stops_stp_departuredate" )
ld_total_hrs = (f_datetimediff(ldt_1st_stop,ldt_last_stop)/60)/60
ll_ord_number = long(dw_triptab.GetItemString(1,"ord_number"))
//If g_messlevel% < 1 Then
if gnv_app.ii_MessLevel < 1 Then
ids_revdist.Reset()
End if
//Load the datastore that stores all the revenue distribution values
ll_rd_rowcount = ids_revdist.RowCount()
ids_revdist.InsertRow(0)
ll_rd_rowcount ++
ids_revdist.SetItem(ll_rd_rowcount,"mov_number",i_movenum%)
ids_revdist.SetItem(ll_rd_rowcount,"lgh_number",dw_trip.GetItemNumber(1,"stops_lgh_number"))
ids_revdist.SetItem(ll_rd_rowcount,"total_hours",ld_total_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"load_hours",ld_load_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"unload_hours",ld_unload_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"deliver_date",ldt_deliver_time)
ids_revdist.SetItem(ll_rd_rowcount,"dest_code",ls_dest_id)
ids_revdist.SetItem(ll_rd_rowcount,"ref_number",ls_ref_number)
Return ids_revdist.RowCount()
I need to evaluate this line specifically and I set a breakpoint at this line:
ls_pay_leg_config = "ByLeg"
as well as the following lines. It does not break. I am rusty at PowerBuilder and can figure this out.
Put the breakpoint at the start of the loop.
positions = {
--table 1
[1] = {pos = {fromPosition = {x=1809, y=317, z=8},toPosition = {x=1818, y=331, z=8}}, m = {"100 monster"}},
--table 2
[2] = {pos = {fromPosition = {x=1809, y=317, z=8},toPosition = {x=1818, y=331, z=8}}, m = {"100 monster"}},
-- table3
[3] = {pos = {fromPosition = {x=1809, y=317, z=8},toPosition = {x=1818, y=331, z=8}}, m = {"100 monster"}}
}
tb = positions[?]--what need place here?
for _,x in pairs(tb.m) do --function
for s = 1, tonumber(x:match("%d+")) do
pos = {x = math.random(tb.pos.fromPosition.x, tb.pos.toPosition.x), y = math.random(tb.pos.fromPosition.y, tb1.pos.toPosition.y), z = tb.pos.fromPosition.z}
doCreateMonster(x:match("%s(.+)"), pos)
end
end
Here the problem, i use tb = positions[1], and it only for one table in "positions" table. But how apply this function for all tables in this table?
I don't know Lua very well but you could loop over the table:
for i = 0, table.getn(positions), 1 do
tb = positions[i]
...
end
Sources :
http://lua.gts-stolberg.de/en/schleifen.php and http://www.lua.org/pil/19.1.html
You need to iterate over positions with a numerical for.
Note that, unlike Antoine Lassauzay's answer, the loop starts at 1 and not 0, and uses the # operator instead of table.getn (deprecated function in Lua 5.1, removed in Lua 5.2).
for i=1,#positions do
tb = positions[i]
...
end
use the pairs() built-in. there isn't any reason to do a numeric for loop here.
for index, position in pairs(positions) do
tb = positions[index]
-- tb is now exactly the same value as variable 'position'
end
Firstly I should mention I've not been coding very long at all, although that much is probably obvious from my code :P
I'm having two problems, firstly the sort isn't functioning correctly but does sort the numbers by their length. Any help here would be appreciated.
Secondly it's changing both the table it grabs and the table it returns (not sure why). How do I prevent it changing the table it grabs?
I'd prefer if people didn't post a fully optisimised premade code as I'm not going to learn or understand anything that way.
function radix_sort(x)
pass, bucket, maxstring = 0, x, 2
while true do
pass = pass + 1
queue = {}
for n=#bucket,1,-1 do
key_length = string.len(bucket[n])
key = bucket[n]
if pass == 1 and key_length > maxstring then
maxstring = key_length
end
if key_length == pass then
pool = string.sub(key, 1,1)
if queue[pool + 1] == nil then
queue[pool + 1] = {}
end
table.insert(queue[pool + 1], key)
table.remove(bucket, n)
end
end
for k,v in pairs(queue) do
for n=1,#v do
table.insert(bucket, v[n])
end
end
if pass == maxstring then
break
end
end
return bucket
end
There's a lot of changes I made to get this working, so hopefully you can look through and pickup on them. I tried to comment as best I could.
function radix_sort(x)
pass, maxstring = 0, 0
-- to avoid overwriting x, copy into bucket like this
-- it also gives the chance to init maxstring
bucket={}
for n=1,#x,1 do
-- since we can, convert all entries to strings for string functions below
bucket[n]=tostring(x[n])
key_length = string.len(bucket[n])
if key_length > maxstring then
maxstring = key_length
end
end
-- not a fan of "while true ... break" when we can set a condition here
while pass <= maxstring do
pass = pass + 1
-- init both queue and all queue entries so ipairs doesn't skip anything below
queue = {}
for n=1,10,1 do
queue[n] = {}
end
-- go through bucket entries in order for an LSD radix sort
for n=1,#bucket,1 do
key_length = string.len(bucket[n])
key = bucket[n]
-- for string.sub, start at end of string (LSD sort) with -pass
if key_length >= pass then
pool = tonumber(string.sub(key, pass*-1, pass*-1))
else
pool = 0
end
-- add to appropriate queue, but no need to remove from bucket, reset it below
table.insert(queue[pool + 1], key)
end
-- empty out the bucket and reset, use ipairs to call queues in order
bucket={}
for k,v in ipairs(queue) do
for n=1,#v do
table.insert(bucket, v[n])
end
end
end
return bucket
end
Here's a test run:
> input={55,2,123,1,42,9999,6,666,999,543,13}
> output=radix_sort(input)
> for k,v in pairs(output) do
> print (k , " = " , v)
> end
1 = 1
2 = 2
3 = 6
4 = 13
5 = 42
6 = 55
7 = 123
8 = 543
9 = 666
10 = 999
11 = 9999
pool = string.sub(key, 1,1)
always looks at the first character; perhaps you meant string.sub(key, pass, 1)