Copy link to clipboard
Copied
Hi,
How to check where x falls?
check(116);
function check(x) {
return 1+(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643);
}
Regards,
Sumit
Hi @SumitKumar,
I looked into the code and as @Peter Kahrel mentioneed the return value for
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643];
const PAGE_TO_SECTION = (function(/*uint[]&*/a, n,s,i)
// -------------------------------------
// Return the func that converts a page number into a
// section number (1..N) depending o
If we need more than 12k checks, then no optimization is required, but I think we can speed up the script execution.
For this we need to create an object that already has a chapter number for each page.
#targetengine 'check chapter'
var LIST_OF_PAGES = {}
main()
function main(){
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643]
function create(from,to,chapter){
for(var i = from; i < to; i++){
LIST_OF_PAGES[i] = chapter
}
}
for(var i = 0; i < R
...
Yesterday I had a lot of work, I suspected that I was wrong, but I could not understand what, today I understood))
Here one script is enough, for this we need to check the variable LIST_OF_PAGES
#targetengine 'check chapter'
if(typeof LIST_OF_PAGES == 'undefined'){
var LIST_OF_PAGES = {}
main()
get()
}
else{get()}
function main(){
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643]
function create(from,to,chapter){
for(var i = from; i < to; i++){
L
...
Hi @SumitKumar
No procedural approach can beat @SychevKA's method, since it is based on a pre-processed, full mapping of page numbers into section indices. Its object `LIST_OF_PAGES` already contains the set of all possible page numbers, so that `LIST_OF_PAGES[anyPage]` instantly returns the corresponding section number. (By instantly, I mean something like 2-3 µs on any decent system.)
Hence this is without doubt the most efficient approach. Even a highly fine-tuned binary algorithm won't run
...Copy link to clipboard
Copied
Yesterday I had a lot of work, I suspected that I was wrong, but I could not understand what, today I understood))
Here one script is enough, for this we need to check the variable LIST_OF_PAGES
#targetengine 'check chapter'
if(typeof LIST_OF_PAGES == 'undefined'){
var LIST_OF_PAGES = {}
main()
get()
}
else{get()}
function main(){
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643]
function create(from,to,chapter){
for(var i = from; i < to; i++){
LIST_OF_PAGES[i] = chapter
}
}
for(var i = 0; i < RANGES.length; i++){
var chapter = 'chapter '+(i+1)
create(RANGES[i],RANGES[i+1],chapter)
}
if(RANGES[0] > 1){create(0,RANGES[0],0)}
LIST_OF_PAGES['last'] = chapter
}
function get(){
function get_rand(min,max){
return Math.floor(Math.random()*(max-min))+min
}
var check = {}
for(var i = 0; i < 10; i++){
var page = get_rand(1,700)
// get a chapter without compare
var chapter = LIST_OF_PAGES[page]
if(typeof chapter == 'undefined'){check[page] = LIST_OF_PAGES['last']}
else{check[page] = chapter}
}
var show = []
for(var k in check){
show.push('\n'+k+'->'+check[k])
}
alert(show)
}
> map multiple pages with same value
This way we load the processor more, my way is to load more RAM. And I think my method will run faster.
Copy link to clipboard
Copied
Thank you SychevKA.
Copy link to clipboard
Copied
Nice one, Sychev. Comparing your function is a factor 10 faster than Marc's and mine.
P.
Copy link to clipboard
Copied
All brilliant suggestions here. That is why I love this community 🙂
-Manan
Copy link to clipboard
Copied
Great, Thank you Manan!
Regards,
Copy link to clipboard
Copied
Thank you Manan, this is what I was searching.
You are supurb, I would like to work with you in future if any opportunities.
I looked into the code and as @Peter Kahrel mentioneed the return value for
PAGE_TO_SECTION(320) is 11575 and not 75 as you mentioned in the other post.
Yes PAGE_TO_SECTION(320) return 11575 thats my fault, but if you see Marc post he used substr that's why getting 75.
__(HREF_PATTERN,('0'+P2S(p)).substr(-2),p)
Also, I have one question which approach is better?
Marc
===============
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643];
const PAGE_TO_SECTION = (function(/*uint[]&*/a, n,s,i)
// -------------------------------------
// Return the func that converts a page number into a
// section number (1..N) depending on RANGES.
// E.g. PAGE_TO_SECTION(320) => 9
{
for( n=a.length, s='1', i=-1 ; ++i < n ; s+='+(x>'+a[i]+')' );
return Function('x', 'return '+s);
})(RANGES);
SychevKA
===============
var LIST_OF_PAGES = {}
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643]
function create(from,to,chapter){
for(var i = from; i < to; i++){
LIST_OF_PAGES[i] = chapter
}
}
for(var i = 0; i < RANGES.length; i++){
var chapter = 'chapter '+(i+1)
create(RANGES[i],RANGES[i+1],chapter)
}
Regards,
Sumit
Copy link to clipboard
Copied
Hi @SumitKumar
No procedural approach can beat @SychevKA's method, since it is based on a pre-processed, full mapping of page numbers into section indices. Its object `LIST_OF_PAGES` already contains the set of all possible page numbers, so that `LIST_OF_PAGES[anyPage]` instantly returns the corresponding section number. (By instantly, I mean something like 2-3 µs on any decent system.)
Hence this is without doubt the most efficient approach. Even a highly fine-tuned binary algorithm won't run faster, noting that in ExtendScript the access to object members remains ultra-fast no matter the number of registered keys.
However, as Sychev noted, execution time is saved by consuming more memory. Should the document or book contain 5,000 pages, the map LIST_OF_PAGES will have to address 5,000 key/value pairs, with a lot of redundancy like { … "2492"=>"chapter 8", "2493"=>"chapter 8", "2494"=>"chapter 8" … }.
In conclusion, this is the fastest approach but not the most memory-optimal. Some improvements are possible without reducing significantly the speed of execution.
For example, instead of creating an object of 5,000 members, you may compact the whole data structure in a UTF16 string of 5,000 characters. It still sounds huge but you can be sure that a single 5K string is much lighter than a Object reference mapping 5K keys (=strings) to 5K values (=strings).
I made some tests based on this idea and the function responds in 1 or 2 microseconds longer than the map. That's a middle ground between extreme performance and saving memory.
Edit: better code display
const PageToRange = function(/*uint>0*/p, q)
//----------------------------------
// Returns the 1-based range index containing page number `p`.
// (The last range supports any `p` beyond the maximum.)
// [REM] Use PageToRange.setup() to initialize the ranges.
// ---
// => uint [1 for 1st range, 2 for 2nd range...] | false [INVALID p]
{
return p > 0 && ((q=callee.Q).charCodeAt(-1+p)||q.charCodeAt(-1+q.length));
};
PageToRange.setup = function(/*uint[]*/a, r,z,p,i,t)
//----------------------------------
// Register an ordered list of page numbers (0 < a[i] < a[i+1].)
// => undef
{
const CHR = String.fromCharCode;
for
(
r=[], p=z=0, i=-1 ;
++i < a.length ;
p < (t=a[i])
&& ( r[r.length]=Array(1+t-p).join(CHR(++z)), p=t )
);
this.Q = r.join('');
}
//----------------------------------
// TEST
//----------------------------------
// `41` means "pages 1 to 41", `73` means "pages 42 to 73", etc.
const RANGES = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643];
// Init. (required once.)
PageToRange.setup(RANGES);
var i,arr,dt,msg;
// Loading N random numbers ranging in [1..800]
const N = 10000;
arr = (function(i,K,RND,r){ for(r=[];i--;r.push(1+~~(K*RND()))); return r;})(N,800,Math.random);
// Benchmark.
for
(
dt=0, i=arr.length ; i-- ;
arr[i]=[$.hiresTimer,PageToRange(arr[i]),dt+=$.hiresTimer][1]
);
msg = ("Total processing time: " + ~~(dt/1e3) + "ms (" + N + " numbers)\r")
+ ("Average `PageToRange` time: " + ~~(dt/N) + "µs\r\r")
+ ("First results:\r" + arr.splice(0,200).join() + '...');
alert( msg );
Best,
Marc
Copy link to clipboard
Copied