* i need inspiration as well, and some clever coding

For users to report plugin bugs and request plugin enhancements; and for authors to test new/new versions of plugins, and to discuss plugin development (in the Programming Technicalities sub-forum). If you want advice on choosing or using a plugin, please ask in General Usage or an appropriate sub-forum.
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

Your solution looks extremely complicated.
Yes, it needs some maths, but only a little basic binary maths involving powers of 2.

The following single statement should do it, assuming intA is Ahnentafel number then intG is the Generation.

local _ , intG = math.frexp( intA )

i.e. 2 raised to the power intG is greater than intA, and intG is smallest integer where that is true.

if necessary you can then use intG = intG - 1
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

gens.png
the numbers to the right are sort of a belongs to helper.
anbr(text) , (code) at = ahnentafel number

you will observe in my code that I take care of the current missing INDIS anbrs at line 24, however I do not take care of their future missing generations anbrs, and the accounting of anbrs is incorrect.
So, I know I need to either hold them in a separate var at 24 and consider them at line 29 or line 30A on a generation change without double counting them and include those once future but now current missing entries at generation change anbrs.

I can see the problem clearly, but cannot see the solution.

And Mike Tate, the math.frexp is the bomb, now my generations are simply and elegantly correct -- INSOFAR AS MY ALGORITHM IS CORRECT.

Code: Select all

 1 function rtvAncestors(iptr)
 2  local thisPTR = iptr:Clone()
 3	
 4  local ptrBAS  = fhNewItemPtr()
 5  local ptrFAMC = fhNewItemPtr()
 6  local ptrHUSB = fhNewItemPtr()
 7  local ptrWIFE = fhNewItemPtr()
 8		
 9  local anc        =  1
10  local at         =  1 
11  local gen        =  0  
12	
13  table.insert(ancestors, iptr:Clone())
14  table.insert(generation, gen) 
15  table.insert(ahnentafel, at)
16		
17  gen = gen + 1
18  while anc <= #ancestors do
19    ptrBAS = ancestors[anc]
20		
21    -- Loop Family as Child to derive parents and next gen
22    ptrFAMC = rtvFAMPtr(ptrBAS)
23    if ptrFAMC:IsNull() then
24      at = at + 2
**25		
26    else
27      ptrHUSB:MoveTo(fhGetValueAsLink(ptrFAMC), '~.HUSB>')
28      at = at + 1
**29	     
30      local _, gen = math.frexp(at)
**30A
31      table.insert(ahnentafel, at) 
32      table.insert(generation, gen) 
33      table.insert(ancestors, ptrHUSB:Clone())
34		
35      ptrWIFE:MoveTo(fhGetValueAsLink(ptrFAMC), '~.WIFE>')
36      at = at + 1
37      table.insert(ahnentafel, at) 
38      table.insert(generation, gen) 
39      table.insert(ancestors, ptrWIFE:Clone())
40    end
41
42    ptrBAS  = fhNewItemPtr()
43    ptrFAMC = fhNewItemPtr()
44    ptrHUSB = fhNewItemPtr()
45    ptrWIFE = fhNewItemPtr()
46    anc     = anc + 1
47  end 
48	
49  return ancestors
50 end --fn rtvAncestors 

FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

One solution is to use the built-in function.

at = fhCallBuiltInFunction( "AhnentafelNumber", iptr, ptrHUSB, 1 )

at = fhCallBuiltInFunction( "AhnentafelNumber", iptr, ptrWIFE, 1 )

The solution using your simple integer approach requires recursive function calls.
When you find a FAMC then call function with current person's Ahnentafel number and Generation.

Inside function obtain Husband whose Ahnentafel number is supplied Ahnentafel number * 2.
If he has FAMC then call same function with his Ahnentafel number and Generation+1.
Then obtain Wife whose Ahnentafel number is Husband's Ahnentafel number + 1.
If she has FAMC then call same function with her Ahnentafel number and Generation+1.
The resulting tables will probably need sorting into 'at' order.

Code: Select all

local function NextGen(ptrFAMC,at,gen)
	if ptrFAMC:IsNotNull() then
		local ptrHUSB = fhNewItemPtr()
		local ptrWIFE = fhNewItemPtr()

		ptrHUSB:MoveTo(fhGetValueAsLink(ptrFAMC), '~.HUSB>')
		at = at * 2

		table.insert(ahnentafel, at)
		table.insert(generation, gen)
		table.insert(ancestors, ptrHUSB:Clone())

		NextGen(fhGetItemPtr(ptrHUSB,'~.FAMC'),at,gen+1)

		ptrWIFE:MoveTo(fhGetValueAsLink(ptrFAMC), '~.WIFE>')
		at = at + 1

		table.insert(ahnentafel, at)
		table.insert(generation, gen)
		table.insert(ancestors, ptrWIFE:Clone())

		NextGen(fhGetItemPtr(ptrWIFE,'~.FAMC'),at,gen+1)
	end
end

function rtvAncestors(iptr)
	local ptrBAS = iptr:Clone()
	table.insert(ahnentafel, 1)
	table.insert(generation, 0)
	table.insert(ancestors, ptrBAS:Clone())

	NextGen(fhGetItemPtr(ptrBAS,'~.FAMC'),1,1)
end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

had to add the following code:


if ptrHUSB:IsNotNull() then
* x = 1
* for _, val in pairs (ancestors) do
* if ptrHUSB:IsSame(val) then
* x = x + 1
* end
* end
at = fhCallBuiltInFunction( "AhnentafelNumber", iptr, ptrHUSB, x) *
_, gen = math.frexp(at)
table.insert(ahnentafel, at)
table.insert(generation, gen)
table.insert(ancestors, ptrHUSB:Clone())
end
BECAUSE: situations don't you know, old cheese.... :lol:

I would like to understand how to calculate these things myself, but it works perfectly and is probably my longest line shot at ancestors (like 204 in the file from that root, and it comes back nearly instantly. I now have the same numbers as OXYgen, though OXYgen does have a mistake I have to deal with... you remember all that hullabaloo about Nora Valmina Risan and the fact she has a FAMC and another that is PEDI Foster? The FAMCs are in the correct order, I am sure he does it in other lines, but that was one I was watching for, He took the PEDI making a total of 6 records not correct in the line, and the at numbers off downstream because of it, correct for the pick, but not for the downstream, for a few. While my file is sorted and every effort is made to organize partners in the sequence they happened where there are no dates of marriage or whatnot, I feel better about pretending it is disorganized (for the general case) and finding the one I need from the bounty that is FAMCs and FAMSs. That is why I bothered with the sifting of FAMCs code.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

My recursive function automatically copes with cases like that where somebody is ancestor in more than one branch.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

What recursive function is that?
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

The one in my posting yesterday after the fhCallBuiltInFunction( "AhnentafelNumber",...) solution.

Did you not see the CODE: SELECT ALL with the local function NextGen(ptrFAMC,at,gen) recursive function script?
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

LOL, no-- truthfully I did not. You are an admin, are you not? Don't know if you peruse the logs much, but I was trying to customize all my settings, and was having a devil of a time with the posting display and order, the reset didnt seem to work, and it was somewhere in the virtual pixel order. I messed around in there quite a bit.

I went to check this morning and everything is where it should be. I re-read the thread to see what I might glean. I have saw it now, and tried it, its fast and about 1/10th of my code. I wrapped the writes in-- if not nulls dont really need to deal with them, upon reflection. yes the table needs sorting. no big gig there.

Thanks. Wish I had enough domain knowledge to think of code like that.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

I'm glad you like that recursive method.
It is the traditional way of navigating ancestors to build Ahnentafel numbers.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: clever coding (Maths again)

Post by Ron Melby »

I need some maths expertise again
I need a table sorted in this order, in LUA
I have it sorted just as it should be in a spreadsheet, however cannot do the same in LUA

d'Aboville dotrmv name

1.2.2.1.8.4.1.1.1.5.1 12218411151 SIBLEY, Nellie E.
1.2.2.1.8.4.1.1.1.5.2 12218411152 SIBLEY, Olive Minnesota
1.2.2.1.8.4.1.1.1.5.3 12218411153 SIBLEY, Agnes M.
1.2.2.1.8.4.1.1.1.5.4 12218411154 SIBLEY, Phebe M.
1.2.2.1.8.4.1.1.1.5.5 12218411155 SIBLEY, Mabell L.
1.2.2.1.8.4.1.1.1.5.6 12218411156 SIBLEY, Ruth
1.2.2.1.8.4.1.1.1.5.7 12218411157 SIBLEY, Alpha H.
1.2.2.1.8.4.1.1.1.5.8 12218411158 SIBLEY, Nettie E.
1.2.2.1.8.4.1.1.1.5.9 12218411159 SIBLEY, Estellie
1.2.2.1.8.4.1.1.1.6.1 12218411161 DISNEY, Emma Melissa
1.2.2.1.8.4.1.1.1.6.2 12218411162 SIBLEY, Joseph Samuel
1.2.2.1.8.4.1.1.1.6.3 12218411163 SIBLEY, Agnes M.
1.2.2.1.8.4.1.1.1.6.4 12218411164 SIBLEY, Ada Naomi
1.2.2.1.8.4.1.1.1.6.5 12218411165 SIBLEY, Frederick Frankland
1.2.2.1.8.4.1.1.1.6.6 12218411166 SIBLEY, Aulden Floyd
1.2.2.1.8.4.1.1.1.6.7 12218411167 SIBLEY, Charles Eugene
1.2.2.1.8.4.1.1.1.7.1 12218411171 SIBLEY, Ella Louise
1.2.2.1.8.4.1.1.1.7.2 12218411172 SIBLEY, Harry Laverne
1.2.2.1.8.4.1.1.1.7.3 12218411173 SIBLEY, Henry Franklin
1.2.2.1.8.4.1.1.1.7.4 12218411174 SIBLEY, Frederick Lucius
1.2.2.1.8.4.1.1.1.7.5 12218411175 SIBLEY, Hattie Rhecnado
1.2.2.1.8.4.1.1.1.7.6 12218411176 SIBLEY, Cecil Rose


what I have tried:
removing the dots from the d'A number and sorting, they wont sort integer, too large and text is hopeless other than in an infantile way.

ok:

as I go thru the recursive loop to build these,
bin = tostring(tonumber(bin + 1))
(that wont work, they are not build in d'A order, but clumped)

so I try
bin = (tostring(tonumber((bin + .0)^ 1/2)))
bin = (tostring(tonumber((bin + .0)^ -2)))
bin = (tostring(tonumber((bin + .0)^ -3)))

none of which seems to be a scalar pattern i can detect without some futher transformation, but sensibly they are scalar in some fashion that I cant sort out in my poor grasp of maths.

ideas?

the best it can sort now is:
desc.png
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

The problem is that d'Aboville codes cannot be treated as a number, and does not sort correctly if treated as a text string.
That is because "1.2.3.10.9" sorts before "1.2.3.2.9" instead of after.
Sp you have to sort each dot separated number separately, which is probably what you did in the spreadsheet.

The solution is to to treat the d'Aboville code as a string and split that into constituent numbers using such as the plugins:code_snippets:split_a_string_into_numbers_using_separators|> Split a String into Numbers using Separators (code snippet).
Then each number must be sorted in turn working from left to right similar to following:.

Code: Select all

-- Split a string into numbers using separators space or comma or x --
function string.splitnumbers(strTxt)
	local tblNum = {}
	strTxt = tostring(strTxt or "")
	strTxt:gsub("([^%.]+)", function(strNum) tblNum[#tblNum+1] = tonumber(strNum) or strNum end)
	return tblNum
end -- function string.splitnumbers

local tblSort = {}
Repeat for each d'Aboville code
	local strCode = tostring(dAboville)
	local tblNum = string.splitnumbers(strCode)
	table.insert( tblSort, { Num=tblNum; Code=strCode; Ptr=ptrIndi; } )
end
table.sort( tblSort,
 function(A,B)
  local tblA = A.Num
  local tblB = B.Num
  for i=1, math.max(#tblA,#tblB) do
   local intA = tblA[i] or 0
   local intB = tblB[i] or 0
   if intA ~= intB then return intA < intB end
  end
  return false
end )
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

drew it out on a bar napkin, and came to the same conclusion....
however that leads to a DotSort(R, HUNTINGTON, UD)
innit?
and sorting by dots is kind of 80s. cat fields are cat fields, and what really discourages me, if you convert them to floats, it cant even sort them correctly.
FH V.6.2.7 Win 10 64 bit
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

I have partially solved it, with two artifices:
anything beyond the 1st generation -- anything containing a dot is padded to two char if it is not already.
then I have right adjusted and padded leading blanks to a fixed field width.

There is another loop that needs to be made, but thats going to be a little complex, so going to put that on the back burner to cook and hope for some divine revelation or the like.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

So what was wrong with the script I gave you on Sun 19th May?
That worked perfectly for me, and is quite efficient.
No divine revelation needed :D
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

nothing really, I am trying to get the running time down, is all.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: i need inspiration as well, and some clever coding

Post by tatewise »

Does this run faster for you?

Code: Select all

local tblSort = { }
for _, strCode in ipairs ({ "1.2.3.10.7"; "1.2"; "1.2.3.2"; }) do
   -- strCode is each d'Aboville code and strPad has the numbers padded to 2 digits
   local strPad = ("<"..strCode..">"):gsub("%.","><"):gsub("<(%d)>","<0%1>")
   table.insert( tblSort, { Pad=strPad; Code=strCode; Ptr=ptrIndi; } )
end

table.sort( tblSort, function(A,B) return A.Pad < B.Pad end )
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: i need inspiration as well, and some clever coding

Post by Ron Melby »

I gotta say, Mike.... that fellow right there is pretty fast.

I have two issues left yet, and one is worth---- no, I will make two separate threads.

Thanks Mike.
FH V.6.2.7 Win 10 64 bit
Post Reply