Sunday, September 25, 2005

Infinite improbability

The last thing I have to do before going on vacation Tuesday is to write an algorythm that will take a list of mortgage points and find the three that are closest to 1, 0 and -1. The problem is that the list can have 1 item or it can have 15, and they can be sprinkled anywhere between 10 and -10.

In other words, I have patterns on the brain, and maybe that's why this jumped out at me this morning: Statistically Improbable Phrases. This is Amazon's latest addition to its book section, and part of its Search Inside feature that digitizes the contents of entire books. The SIP function looks for phrases in one book that don't show up in most other books. For example, in the book "Party Monster: A Fabulous But True Tale of Murder in Clubland" the two SIPs are drink tickets and club kids. Click on either of those, and you find the list of other books that feature those phrases. And damn if they're not all about similar or even identical themes.

I like it. I've already spent the morning looking up past books that I dig ("House of Leaves," "Killing Pablo," "All the President's Men," "Me Talk Pretty One Day") and seeing what connections SIP provides. Not surprisingly, the non-fiction links are much more accurate than the fiction. The two SIPs for "House of Leaves" are the fantastically unhelpful "dwarf nuns" and "neon markers."

2 comments:

Bootay said...

I wrote some code for a similar need recently:

load array with values
closest to -1,0,-1 variables all start with element 0 in array
for each value in array, if value is closer to target than current closest, closest = value
next

done

Jacob said...

As usual, Mark is 100% right. With his guidance, here's the final and completely boring algorythm:

//Truncate list of points
if ((isnumeric(pricingquote.mpa_nbr_quotes)) AND (pricingquote.mpa_nbr_quotes GT 0))

{
truncate_point_list = "";
for (g = 1; g LTE pricingquote.mpa_nbr_quotes; g = IncrementValue(g))
{
truncate_point_list = ListAppend(truncate_point_list,ListGetAt(pricingquote.mpa_point_list,g,","));
}
pricingquote.mpa_point_list = truncate_point_list;

//More than three quotes
if (pricingquote.mpa_nbr_quotes GT 3)
{
pointList = "1,0,-1";
temp_point_list = "100,100,100";
for (h = 1; h LTE 3; h = IncrementValue(h))
{
for (i = 1; i LTE pricingquote.mpa_nbr_quotes; i = IncrementValue(i))
{
iDiff = ReReplace((ListGetAt(pricingquote.mpa_point_list,i,",") - ListGetAt(pointList,h,",")),"-","","ALL");
if (iDiff LT ReReplace((ListGetAt(temp_point_list,h,",") - ListGetAt(pointList,h,",")),"-","","ALL"))
{
temp_point_list = ListSetAt(temp_point_list,h,ListGetAt(pricingquote.mpa_point_list,i,","));
}
}
ListDeleteAt(pricingquote.mpa_point_list,ListFind(temp_point_list,ListGetAt(temp_point_list,h,","),","));
}
}

//Three or fewer quotes
else
{
for (i = 1; i LTE pricingquote.mpa_nbr_quotes; i = IncrementValue(i))
{
temp_point_list = ListAppend(temp_point_list,ListGetAt(pricingquote.mpa_point_list,i,","));
}
}


//Search for original point positions
for (k = 1; k LTE ListLen(temp_point_list); k = IncrementValue(k))
{
thisPos = ListFind(pricingquote.mpa_point_list,ListGetAt(temp_point_list,k,","),",");

//Determine closing costs for this rate
if ((pricinginfo.mpa_pvpgm_loan_product eq "CEP") or (pricinginfo.mpa_pvpgm_loan_product eq "NEP"))
{
monthly_payment_temp = pricinginfo.mpa_pvlamt_loan_amount * (ListGetAt(pricingquote.mpa_rate_list,thisPos)/12/100);
}
else
{
monthly_payment_temp = pricinginfo.mpa_pvlamt_loan_amount * (ListGetAt(pricingquote.mpa_rate_list,thisPos)/12/100) * ((1 + (ListGetAt(pricingquote.mpa_rate_list,thisPos)/12/100)) ^ (pricinginfo.mpa_pvatrm_amort_term - 1)) / (((1 + (ListGetAt(pricingquote.mpa_rate_list,thisPos)/12/100)) ^ (pricinginfo.mpa_pvatrm_amort_term - 1)) - 1);
}


//Create new truncated lists
pricingquote.final_margin_list = ListAppend(pricingquote.final_margin_list, ListGetAt(pricingquote.mpa_margin_list,thisPos));
pricingquote.final_point_list = ListAppend(pricingquote.final_point_list, ListGetAt(pricingquote.mpa_point_list,thisPos));
pricingquote.final_rate_list = ListAppend(pricingquote.final_rate_list, ListGetAt(pricingquote.mpa_rate_list,thisPos));
pricingquote.final_monthly_payment = ListAppend(pricingquote.final_monthly_payment, monthly_payment_temp);
pricingquote.final_nbr_quotes = k;

if (k EQ 3) //Max number of rates
{
break;
}
}
}