INCLUDE_DATA

The Family Reunion Problem

Here’s an interesting problem. I would like to call this the family reunion problem. As far as I know, this problem hasn’t been stated or generalized anywhere else. But maybe it has?

Suppose a set of people live in different cities and wish to have a reunion. They’re fairly far apart such that they’ll be flying, cost is an issue. Everyone is indifferent as to the city, but they wish to minimize the total travel cost of the trip.

The family consists of the following people:

  • Alice living in Boston
  • Bobby living in Miami
  • Cindy living in Los Angeles
  • David living in Seattle
  • Euclid living in San Francisco

Costs to fly between each city are given in this matrix:

BOS MIA LAX SEA
SFO 218 233 98 98
SEA 218 238 138
LAX 218 283
MIA 168

Which member of the family should host the reunion?

Of course this is easy with just 4 people, but family reunions usually have many times this. And family reunions don’t necessarily have to be held in a home city; it could be an entirely new venue.

My intuition tells me this is NP-Complete, but it has been a while.

For loops in SAS

When coding for loops in SAS, one neat thing to remember is that all of the parts of it are optional.

start <TO stop> <BY increment> <WHILE(expression) | UNTIL(expression)>

http://support.sas.com/documentation/cdl/en/lrdict/62618/HTML/default/a000201276.htm

So in another language, what might be

for(int i=0;i < max;i++) {

In SAS, you can leave out the "by 1", since it's the default increment. So this would be

do i=0 to max;

What's fun is in SAS you can combine a Repeat-Until/Do-While loop with a for loop. This might be useful if for some reason you don't set the var "max" until you've iterated through the loop once, such as in this case, where "metadata_getnobj" returns a negative on fail, but otherwise returns the number of objects that match the query.

do i=1 by 1 until (i >= objs);
  rc=metadata_getnobj("omsobj:SASLibrary?@Libref='MYLIBREF'",i,uri);
  if rc>=0 then objs=rc;

  rc=metadata_getnasn(uri,"LibraryConnection",1,uri);
  if rc>=0 then leave;
end;

This code loops through all the libraries in the metadata with libref='MYLIBREF', and exits with a URI for the first one it sees with at least one LibraryConnection association. This is useful when you have a remote library pointing to a local library and they both have the same name and you want a URI to the remote one.

Another cool thing with FOR loops in SAS is iteration through lists. In Java, say you have a block like this:

for(String x : new String[] { "a","b","c" }) {
  System.out.println("x="+x);
}

In SAS, this is simply

do x="a","b","c";
  put x=;
end;

NC Democrat Party refers to people as “Tea Baggers”

You keep using that word. I do not think it means what you think it means.

From: David Young, Chairman, NC Democrats <headquarters@ncdp.org>
Sent: Friday, September 18, 2009 9:46 AM
Subject: Democrats Counter Tea Baggers

Democratic strength continues to grow

Democratic leaders from across the country met last week in Austin, TX for the Democratic National Committee’s Fall Meeting.

In addition to electing a slate of organizational and caucus officers, Democrats learned about the rebirth and growth of the Democratic Party in Texas and the strength of our gubernatorial candidates in New Jersey and Virginia.

North Carolina continues to lead the way with DNC Member Susan Burgess’ pitch to host the 2012 Democratic National Convention in Charlotte, where she serves as Mayor Pro-Tem.

Joyce Brayboy and Ed Turlington were elected at-large DNC members. Turlington and Everett Ward were elected to the Resolutions and Credentials committees, respectively, with Ward elected as co-chairman of his committee.

David Parker was also elected Treasurer of the Southern Caucus. Spanning states from Virginia to Texas, the caucus discusses regional issues and concerns. DNC Chairman Tim Kaine said the organization will continue to focus its efforts on winning elections in the South.

Removing formats from all variables in a SAS Dataset

In SAS, every field/variable in a table/dataset can be given a format. This format tells SAS how to display the data. The following datastep will create a table called “formatted” having 1 row containing 3 variables: x, y, and d.

data formatted;
  x=9000;
  y=42;
  now=16761;
  format x comma6.;
  format y dollar5.;
  format now date7.;
  put x=;
  put y=;
  put now=;
run;

Additionally it prints to the log the formatted values.

x=9,000
y=$42
now=21NOV05

In SAS you can also create your own formats, and you can assign these formats to whichever datasets you like. However if that format goes away for some reason and you try to look at the data again, you will get this error:

ERROR: Informat $YOURFMT not found or couldn't be loaded for variable YOURVAR.

You can get around this by turning off this option

options nofmterr;

Then your ERROR turns into NOTE, and things work normally, except when you try to view the data you see it unformatted. This could be useful, however, if you find yourself in a situation like this:

data _null_;
  a=20.0000001;
  b=20.000001;
  format a dollar4.2;
  format b dollar4.2;
  put a= b=;
  if(a=b) then put 'matches';
   else put 'no match';
run;

Runs and outputs:

a=20.0 b=20.0
no match

At any rate, there are times in SAS when you simply want to remove all the formats from a dataset. This can be done in one line in a datastep:

data unformatted;
  set formatted;
  format _all_;
run;

Tablesaw that Won’t Cut Fingers

This is one of the greatest inventions I’ve seen in a long time. Using a charge in the saw blade, if it detects capacitance from human flesh it immediately halts and retracts the spinning blade. When pushing wood through at any reasonable speed, it’s supposed to stop before the blade cuts any deeper than 1/16th an inch. Probably does irreparable damage to the saw’s blade, but at least you keep your fingers.

Not that I have any use for a table saw, but if I did, I’d buy this one.

AT&T U-Verse DNS Loopback workaround for 3800HGV-B

AT&T’s U-Verse network just came up on my street.

So… since the gateway doubles as a router & switch, I was trying to set it up so my httpd server was accessible from the outside. Setup the port forwarding through the firewall just fine, and indeed everything works for the rest of the internet. All of you should be able to get to shatner.philihp.com.

However I can’t. From what I gather, the gateway doesn’t support DNS loopback. So when I resolve shatner.philihp.com, it resolves to my WAN IP, then I try to connect to it and I timeout. It’s similar to the problem this guy had with his FTP server.

Eric DeVaudreuil suggested that if I could get the DNS on the gateway to resolve the domain differently for LAN users, it would work. And it looks like from the manual, that there used to be a quazi-secret management console that had a “DNS Resolve” page for doing just this. However a recent firmware upgrade totally removed this in order to fix some XSS attack. So that’s out of the picture.

this guy got around it by setting up a router behind his gateway… I suppose I could do this, but it seems like overkill for something that should just work.

Someone at Experts-Exchange says it can’t be done… but over there they use a sort of “democratic truth” similar to the abomination that is Yahoo Answers; so I wouldn’t believe much I see there.

Right now, I have this working solution/workaround. Admittedly it doesn’t scale well, but this isn’t an issue when my network is under half a dozen devices. My solution is just to add in lines to my /etc/hosts file for all of my machines to make the domain resolve to the LAN IP of the HTTP server, rather than the WAN IP. The only drawback/annoyance to this is with my laptop which constantly goes in and out of the local network.

Sending HTTP Requests without Reloading and without AJAX

Supposing I have a simple HTML form that looks like this:

<form method="post" action="/SomeServlet">
  <input type="text" name="message" value="Hello Server" />
  <input type="submit" value="Send" />
</form>

And supposing I have a Servlet mapped at the path /SomeServlet, consisting of the code:

public class SomeServlet extends HttpServlet {
  protected void doPost(HttpServletRequest request,
                        HttpServletResponse response)
          throws ServletException, IOException {
    System.out.println(request.getParameter("message"));
    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
  }
}

If I goto the form, type in a message, and click the Send button, the message will print out on the Server’s console. So What? So the cool thing is the HTML Form is not reloaded. Which could be useful if you’ve got heavy data on it. Seriously! Fire up Fiddler and watch your HTTP traffic.

Of course there are many other ways of doing this, a lot of them with Javascript or IFrames. This one does not require the use of anything fancy on the client side. Just an HTML Form. And of course it works outside of Java Servlets too– so long as you can mess around with the HTTP status code.

Second best Final Fantasy game now on PS3

Final Fantasy 7 cover art

Final Fantasy 7 cover art

This popped up in my RSS reader just now. Many people would get into a heated argument with me over what the best Final Fantasy game is, so I’ll just claim seven to be the second-best Final Fantasy game. Any fan of RPGs should play through this at least once, if only to understand why any self-aware game character would fear FMV sequences.

Final Fantasy VII On PlayStation Store Today

Just about every Final Fantasy game has had environmentalist life-force hippie connotations, but I think this one does it best with the whole Mako reactor business. Almost as well as Koyaanisqatsi. I can’t wait to go home and play it!

And this time I won’t leave Yuffie behind.

Converting between Date and Datetime in SAS

In SAS, fields are either character of varying length, or numeric. No exceptions. Temporal values such as Date and Date/Time are stored as either the number of days or seconds since 1960 January 1st.

In order to convert from Date/Time to Date, and from Date to Date/Time, you could divide or multiply respectively by 86400 (the number of seconds in a day).

data _null_;
  d='29FEB1984'd;
  put d date.;
  dt=d*24*60*60;
  put dt datetime.;
  d=dt/24/60/60;
  put d date.;
run;

But unless someone deals with dates every day, it might not be obvious to them by reading this code what those magic numbers are doing.

Another method would be to use put() and input() using functions to go back and fourth.

data _null_;
  d='29FEB1984'd;
  put d date.;
  dt=input(put( d  ,date7.) || ':00:00:00', datetime.);
  put dt datetime.;
  d =input(substr(put(dt,datetime.),1,7),date7.);
  put d date.;
run;

But I don’t consider this any better. It’s wordy. Functions are nested within functions. And you still have a magic number for the call to substr. Also, since it isn’t uncommon for SAS datasets to get into the billions of rows, this probably isn’t the fastest way to do it.

SAS has built-in functions called dhms() (mnemonic: date,hour,minute,second) and datepart() that should make things a lot easier.

data _null_;
  d='29FEB1984'd;
  put d date.;
  dt=dhms(d,0,0,0);
  put dt datetime.;
  d =datepart(dt);
  put d date.;
run;

Static Java List Instantiation

I’ve been out of the loop on straight Java programming for a while, so this is probably obvious to a lot of people, and has been for a long time. But on the off chance that I’m not the only other idiot out there, I’ll post this.

The old way of instantiating a List in Java was like this:

List strings = Arrays.asList(new String[]{"foo","bar"});

In Java 5, templates were introduced, so I had to change to doing this:

List<String> strings = Arrays.asList(new String[]{"foo","bar"});

It just occurred to me that with variable-length methods, I can simply call asList like this:

List<String> strings = Arrays.asList("foo","bar");