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
Can you explain the problem further? You want to return the number that x exceeds in the set? If so something like this:
var nums = [41, 73, 113, 147, 181, 213];
for (var i = 0; i < nums.length; i++) {
if (x >nums[i]) return nums[i];
}
return nums.pop();
Copy link to clipboard
Copied
Hi Brian,
Thank you for your response.
Actually I don't want to use loop.
Basically I want to check where number falls before?
Input output ex:
5 => 1
109 => 3
113 => 4
Regards,
Copy link to clipboard
Copied
Don't see any way out of using a loop. You'll need to return the iterator (i) to achieve that output and you'll need to examine each 'less than' element of the array. Still runs in worst case O(n)
Copy link to clipboard
Copied
Thank you.
Copy link to clipboard
Copied
Try this :
alert (check(536));
//=============================
function check(y){
var number = [41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643];
number = number.sort(function(a, b){return a - b;});
if(y < number[number.length-1]){
return true;
}
return false;
}
Best
Sunil
Copy link to clipboard
Copied
Thanks Sunil but this is not my requirements.
Copy link to clipboard
Copied
> Actually I don't want to use loop.
That's like "I want to nail this to the wall but I don't want to use a hammer."
return 1+(x>41,73, . . .
Where did you find this statement?
Copy link to clipboard
Copied
Thank you Peter for your response and I like your statement
> "I want to nail this to the wall but I don't want to use a hammer.".
> Where did you find this statement?
I find it from here. Specially check this line
return Function('x', 'return '+s);
Earlier the function name "PAGE_TO_SECTION(320)" return correct value but now all the time return constant value whatever is the input no matter. I don't know what is wrong but something happened wrong during forum transition 2 years ago.
Regards,
Copy link to clipboard
Copied
I find it from here.
that is an obfuscated code in which it seems to me the author himself will get lost. and look carefully, there is a loop in it.
Earlier the function name "PAGE_TO_SECTION(320)" return correct value but now all the time return constant value whatever is the input no matter. I don't know what is wrong but something happened wrong during forum transition 2 years ago.
maybe your xml has changed
Copy link to clipboard
Copied
Hi SychevKA,
Anonymous function return below function.
function anonymous(x) {
return 1+(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)+
(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)
}
Above code should return page number to section as per @Marc Autret .
// -------------------------------------
// Return the func that converts a page number to a
// section number (1..N) depending on RANGES and no matter xml changed or not.
// E.g. PAGE_TO_SECTION(320) => 9
Regards,
Copy link to clipboard
Copied
This code is made hard to read and does not do what you expect.
The value of (a,b,c,d,e,f...,z) is just z and all of a,b,c,d... have no effect on the result.
So
1+(x>41,73,113,147,181,213,255,291,333,365,405,435,467,505,535,567,607,643)
is 1+643 is 644.
There is no clever magic or side effect, just junk to confuse the reader. And there is no such code in the page you linked.
Copy link to clipboard
Copied
Dear @Test Screen Name ,
Did you see original post?
const HREF_PATTERN = "M%1_BERK9695_07_SE_C%1.xhtml#page%2";
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 + ')');
return Function('x', 'return ' + s);
})(RANGES);
Copy link to clipboard
Copied
I saw. There is no similarity.
[a,b,c,d,e,...z] creates an array with those elements
(a,b,c,d,e,...z) returns z
Copy link to clipboard
Copied
Thankk you.
Copy link to clipboard
Copied
Sumit -- The code snippet you quoted return 11575, so clearly there's something wrong. The snippet does use a loop, by the way (for n = a.length. . .). And how you arrive at the code you proposed (your function check()) from Marc's code is not entirely clear to me.
What you're after is really very straightforward, a simple while loop returns the section number:
const RANGES = [0, 41, 73, 113, 147, 181, 213, 255, 291, 333, 365, 405, 435, 467, 505, 535, 567, 607, 643];
function check (folio) {
var n = 0;
while (n < RANGES.length && folio >= RANGES[n]) {
n += 1;
}
return n;
}
check (320);
Peter
Copy link to clipboard
Copied
Thank you Peter.
Yes there is also loop but RANGES.length times only.
At the index pages there are 12,000 page numbers appearing and if I use while loop it will loop morethan 1 lac times and it is slower.
My requirement is to add argument as page number and get the chapter number.
Chapter 1 --> 001-041
Chapter 2 --> 042-073
Chapter 3 --> 074-113
Chapter 4 --> 114-147
Chapter 5 --> 148-181
Chapter 6 --> 182-213
Chapter 7 --> 214-255
Chapter 8 --> 256-291
Chapter 9 --> 292-333
Chapter 10 --> 334-365
Chapter 11 --> 366-405
Chapter 12 --> 406-435
Chapter 13 --> 436-467
Chapter 14 --> 468-505
Chapter 15 --> 506-535
Chapter 16 --> 536-567
Chapter 17 --> 568-607
Chapter 18 --> 608-643
that's why I use below code but this function return constant value all the times.
PAGE_TO_SECTION(320) // return 9
So I just want to understand below code only.
const __ = $.global.localize;
const HREF_PATTERN = "M%1_BERK9695_07_SE_C%1.xhtml";
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){
for (n = a.length, s = '1', i = -1; ++i < n; s += '+(x>' + a + ')');
return Function('x', 'return ' + s);
})(RANGES);
var sectionNumber = PAGE_TO_SECTION(320)// => 9
result = __(HREF_PATTERN, sectionNumber);
Regards,
Copy link to clipboard
Copied
I understand what you're after. I can't help you with understanding Marc's code, you'll have to ask him.
> At the index pages there are 12,000 page numbers appearing and if I use while loop it will loop morethan 1 lac [?] times and it is slower.
No: if you check 12,000 pages, Marc's for-loop iterates through the RANGES array 12,000 times, same as my code. The difference is that Marc uses a for-loop, I use a while-loop.
By the way, in (your version of) Marc's code, PAGE_TO_SECTION(320) reurns 11575, not 9.
P.
Copy link to clipboard
Copied
Thank you.
Copy link to clipboard
Copied
If you have to find an index into an array of 10000 items which define ranges, you need a loop. Even if there is a clever trick like using "sort" it will contain many loops and be even slower.
If I had to solve this problem, which might take on average 5000 loops, I would spend a few days coding a binary search, which would reduce it to a maximum 14 loops per search. This is not simple coding.
Copy link to clipboard
Copied
Thank you @Test Screen Name
Copy link to clipboard
Copied
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 on RANGES.
// E.g. PAGE_TO_SECTION(320) => 9
{
for( n=a.length, s='1', i=-1 ; ++i < n ; s+='+(x>'+a+')' );
return Function('x', 'return '+s);
})(RANGES);
So the code basically creates an anonymous function that returns the value of the following expression
1+(x>41)+(x>73)+(x>113)+(x>147)+(x>181)+(x>213)+(x>255)+(x>291)+(x>333)+(x>365)+(x>405)+(x>435)+(x>467)+(x>505)+(x>535)+(x>567)+(x>607)+(x>643)
So what this does is, it checks if the passed in value is greater with each of the element on the base array(sorted) and keeps adding the return value, the return value will be 1 till the argument is greater and 0 afterwards. This explains why 320 would give a result as 9.
Now why do we get 11575 as the result and not 9 that is because the code is incorrect(not written incorrect but fudged up by migration to the new forum platform). The correct code would be as follows
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);
Now the code should seem quite understandable and not cryptic. So the loop has been used here as well albeit just for one pass of the array and for each search, henceforth its just a long list of comparisons that are executed. To me this looks like a good idea to speed up things. I am not sure what happens when the input array is really long like the 12000 entry you mentioned, woud like comments on that from @Test Screen Name and @Peter Kahrel, if they have ever played around with such an idea and would this, for me binary search looks more palatable.
-Manan
Copy link to clipboard
Copied
Thanks for the correction and the explanation, Manan. But the function doesn't look through a 12,000-element array. There are ~12,000 page numbers, so Marc's function executes 12,000 times. It's true though that the for-loop in Marc's function executes just once, which is very clever.
Overall, Marc's function outperforms mine. There is an interesting difference: in lower page numbers my function is quicker, whereas with higher page numbers, Marc's becomes much quicker. The reason must be that with low page numbers my function iterates the RANGES array just a couple of times and Marc's function suffers from the overhead of calling the inner function and its action (coercing the booleans to numbers and adding up the zeros and ones).
The book has somewhere between 650 and 700 pages, and there are 12,000 page references to check. The tipping point between Marc's and my function is around 250, so Marc's function wins in this job, hands-down probably. (Though we're talking milliseconds here -- either function would have done the job thousands of times while I was writing this message.)
A binary function would not work in this case I don't think.
P.
Copy link to clipboard
Copied
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 < 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
}
Now we have a chapter without compare.
#targetengine 'check chapter'
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)
Notice there are two different scripts here. Until you restart the InDesign, you can run the second script as many times as you like and get the result without compare.
Copy link to clipboard
Copied
Thank you @SychevKA ,
This is the correct way to use minimum loop, around 650 loop.
But I was thinking that should I map multiple pages with same value that's why I did not use this approach.
Regards,