What are the first 10 consecutive digits of e that form a prime number?

January 22nd, 2012

After seeing some sample Google Interview Questions that included this question, I couldn’t resist the challenge…

def bigE() {
  BigDecimal e = new BigDecimal(1.0G)
  BigDecimal temp = new BigDecimal(1.0G)
  for (int i in 1..100) {
    temp *= i
    e += new BigDecimal("1")
         .divide(temp, new java.math.MathContext(10000))
  }
  return e.toString()
}
 
def isPrime(long n) {
  if (n < 2) return false
  if (n == 2 || n == 3) return true
  if (n%2 == 0 || n%3 == 0) return false
  long sqrtN = (long)Math.sqrt(n)+1
  for (long i=6L; i < sqrtN; i += 6) {
    if (n%(i-1) == 0 || n%(i+1) == 0) return false
  }
  return true
}
 
def firstPrimeBySize(n) {
  String e = bigE()
  for (int i in 2..e.size()-n) {
    String chunk = e.substring(i,i+n)
    if (isPrime(new BigDecimal(chunk).toLong())) {
      return "$chunk at position $i"
    }
  }
}
 
assert firstPrimeBySize(10) == "7427466391 at position 100"

jsonpretty: handy when playing with web services

October 17th, 2011

I just ran into a handy little utility: jsonpretty.

$sudo gem install json jsonpretty

While

$curl -i http://localhost:8081/openmrs-standalone/ws/rest/v1/catalog

gives you something like this:

{"catalog":[{"name":"Cohort","operations":[{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort?q","description":"Fetch all non-retired that match this parameter"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}","description":"Fetch by unique uuid"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort","description":"Fetch all non-retired"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort","description":"Create with properties in request"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}","description":"Edit with given uuid, only modifying properties in request"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?!purge","description":"Delete this object from the database"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?purge","description":"Delete this object from the database"}],"url":"http://localhost:8081/openmrs/ws/rest/v1/cohort","representations":[{"name":"ref","properties":["uuid","display","links"]},{"name":"default","properties":["uuid","name","description","voided","memberIds","links"]},{"name":"full","properties":["uuid","name","description","memberIds","voided","auditInfo","links"]}]},{"name":"CohortMember","operations":[{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}","description":"Fetch by unique uuid"},{"name":"GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members","description":"Fetch all non-retired"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members","description":"Create with properties in request"},{"name":"POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}","description":"Edit with given uuid, only modifying properties in request"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}?!purge","description":"Delete this object from the database"},{"name":"DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{parentUuid}/members/{uuid}?purge","description":"Delete this object from the database"}],...

adding jsonpretty:

$curl -i http://localhost:8081/openmrs-standalone/ws/rest/v1/catalog | jsonpretty

gets you something much prettier:

{
  "catalog": [
    {
      "name": "Cohort",
      "operations": [
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort?q",
          "description": "Fetch all non-retired that match this parameter"
        },
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}",
          "description": "Fetch by unique uuid"
        },
        {
          "name": "GET http://localhost:8081/openmrs/ws/rest/v1/cohort",
          "description": "Fetch all non-retired"
        },
        {
          "name": "POST http://localhost:8081/openmrs/ws/rest/v1/cohort",
          "description": "Create with properties in request"
        },
        {
          "name": "POST http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}",
          "description": "Edit with given uuid, only modifying properties in request"
        },
        {
          "name": "DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?!purge",
          "description": "Delete this object from the database"
        },
        {
          "name": "DELETE http://localhost:8081/openmrs/ws/rest/v1/cohort/{uuid}?purge",
          "description": "Delete this object from the database"
        }
      ],
      "url": "http://localhost:8081/openmrs/ws/rest/v1/cohort",
      "representations": [
        {
          "name": "ref",
          "properties": [
            "uuid",
            "display",
            "links"
          ]
        },
        {
          "name": "default",
          "properties": [
            "uuid",
            "name",
            "description",
            "voided",
            "memberIds",
            "links"
          ]
        },
        {
          "name": "full",
          "properties": [
            "uuid",
            "name",
            "description",
            "memberIds",
            "voided",
            "auditInfo",
            "links"
          ]
        }
      ]
    },
    ...

Nice! Thank you jsonpretty! :-)

Displaying OpenMRS observations using Groovy

July 11th, 2011

I wanted to list out some observations for a patient and used the following Groovy script:

def sql(s) {admin.executeSQL(s,true) }
 
patientIdentifier = "999-3" // a test patient, of course
 
sql("""
select
date(o.obs_datetime),
(select name from concept_name where concept_id=o.concept_id limit 1) as question,
case c.datatype_id
when 1  /* numeric  */ then cast(o.value_numeric as char)
when 2  /* coded    */ then (select min(name) from concept_name where concept_id=o.value_coded)
when 3  /* text     */ then value_text
when 6  /* date     */ then cast(date(o.value_datetime) as char)
when 7  /* time     */ then cast(time(o.value_datetime) as char)
when 8  /* datetime */ then cast(o.value_datetime as char)
when 10 /* boolean  */ then if(o.value_numeric=1,'TRUE','FALSE')
else '?'
end as answer
from
obs o
left outer join
concept c
on c.concept_id=o.concept_id
where
o.person_id = (select patient_id from patient_identifier where identifier = '$patientIdentifier' limit 1)
order by
o.obs_datetime desc
""").collect{ it.join(": ") }.join("n")

which generated output like this:

2011-02-18: PATIENT HAD SEX IN LAST 6MO: TRUE
2011-02-18: PlAN FOR METHOD OF FAMILY PLANNING, DETAILED: ?
2011-02-18: QUANTITY: 5
2011-02-18: FAMILY PLANNING METHOD PLAN: INITIATION
2011-02-18: METHOD OF FAMILY PLANNING: ECPS
2011-02-18: HIV DISCLOSURE TO ANYONE, SPECIFIC: OTHER HOUSEHOLD MEMBER
2011-02-18: REASON FOR REFUSAL - FAMILY PLANNING: TRYING TO CONCEIVE NOW
2011-02-18: PlAN FOR METHOD OF FAMILY PLANNING, DETAILED: ?
2011-02-18: METHOD OF FAMILY PLANNING: MALE CONDOMS
2011-02-18: QUANTITY: 5
2011-02-18: FAMILY PLANNING METHOD PLAN: INITIATION
2011-02-18: METHOD OF FAMILY PLANNING: BTL
2011-02-18: FREETEXT, GENERAL: POSITIVE
2011-02-18: REASON FOR REFUSAL - FAMILY PLANNING: ABSTINENCE
2011-02-18: FAMILY PLANNING: TRUE
2011-02-18: REVIEW OF MEDICAL HISTORY: ICTERUS
2011-02-18: PATIENT REPORTED PROBLEM: YES
2011-02-18: CURRENT MEDICATIONS: ALUVIA
2011-02-18: REVIEW OF MEDICAL HISTORY: DEPRESSION

Sometimes you need a little web server

July 2nd, 2011

Here’s a simple jetty server using a short Groovy script:

@Grab(group='org.mortbay.jetty', module='jetty-embedded', version='6.1.14')

import org.mortbay.jetty.*
import org.mortbay.jetty.servlet.*
import groovy.servlet.*
import javax.servlet.*
import javax.servlet.http.*

class MyServlet extends HttpServlet  {
  void doPost(HttpServletRequest request, HttpServletResponse response) {
    println "--- Received ${new Date()}n" + request.getParameter('data')
  }
}

def server = new Server(8888)
def root = new Context(server, "/", Context.SESSIONS)
root.setResourceBase(".")
root.addServlet(new ServletHolder(new MyServlet()), "/")
server.start()

Running the script with groovy AtlasServer.groovy will accept HTTP POSTs at the designated port (8888) and dump posted data to the screen.  For example:

$ curl -X POST -d "data=Hello world!" http://localhost:8888/

should dump “Hello world!” to the screen.  Press Ctrl+C to abort the server.

Flowsheet Code Jam in Chennai

January 15th, 2011

Here’s a shout out to our friends at ThoughtWorks. They had a code jam on the Flowsheet Module a few weeks ago and knocked out over half a dozen key tickets in a single day as well as making progress on others. The Flowsheet Module is being installed into OpenMRS at AMPATH in Kenya to allow both data managers and providers convenient access to their patients’ data and to help improve the efficiency and quality of care for the over 300,000 patients within the system… thanks to: Khaarthigha S, Rajiv RA, Pavithra K, Geetha B, Saravana K, Arvind Kumar C, Senthil V S, Prabha P, Shanum, Ponnulingam R, Alexal, Vinoth KR, Nithyan, Gobinath T, Balaji G, Ragavan G, and Chandru. You all rock! And it looks like you had some fun in the process. I especially enjoyed the image of two laptops per lap!

Swipe down to close tab in FF4

November 16th, 2010

Just upgraded to Firefox 4 beta 7 on my MacBook Pro and the (three finger) swipe down gesture I had grown to love (thanks to Will Henderson’s MultiClutch), suddenly became a “show tab view” gesture.  This is no good!  I’ve already become accustomed to swiping down to close tabs in Firefox.

A little googling, and I was able to get back my swipe-down-to-close-tab gesture and move the show tab view gesture to SHIFT + swipe down:

  1. Open up a tab and browse to “about:config” to bring up the Firefox configuration — proceed at your own risk.
  2. Type “gesture” in the Filter field to filter down to gesture-related preferences.
  3. You should see the preference browser.gesture.swipe.down of type string set to value Browser:ShowTabView.
  4. Right-click on the preference name and select New –> String from the context menu.
  5. Enter browser.gesture.swipe.down.shift as the new preference name.
  6. Enter Browser:ShowTabView as the new preference’s value.
  7. So, now you have added a SHIFT + swipe down gesture (swiping three fingers down while holding down the shift key) to perform the default function of swipe down.  Now we take back our swipe down gesture…
  8. Double-click on the value of the browser.gesture.swipe.down preference and change it to cmd_close.
  9. You’re done!  Swipe down and the about:config tab should disappear.  Hold down shift while swiping down and you’ll see the tab view.

Now that gestures are supported on Firefox, I no longer need MultiClutch settings for Firefox.

The Fisherman

October 6th, 2010

The fish he caught…

and the story he told…

iPad Pro

April 17th, 2010

Own a MacBook Pro and an iPad?  Tired of carrying around both?  Meet the iPad Pro.

I’m looking forward to the day when the monitor of my MacBook Pro becomes an iPad.  No extra things to carry around.  If you want to run to a quick meeting or browse on the couch, just snap off your monitor and go (it’s an iPad).  Miss your keyboard, DVD drive, extra ports, extra battery life, etc.?  Just plug your iPad back onto the iPad Pro base and you’ve got a full laptop.  Keep a cloth in your bag to wipe off those fingerprints and stop freaking out when people touch your monitor — it’s a multitouch monitor, after all.

Improving OpenMRS Code Review

April 15th, 2010

Trying to figure out how we can improve the efficiency of our code reviews.  Finding some interesting stuff on the web…

Like this article: Limit the checklist to 7±2 items.  Automate the automate-able and let existing code review data drive the list of common mistakes.

Here is a list of articles, white-papers, and documentation around peer code review.  Hmmm. Several resources, but not enough time to look at them all.

Some nice pointers here, but nothing game changing.

A good summary article here.

  • Review fewer than 200-400 lines of code at a time
  • Aim for less than 300-500 LOC/hour
  • Not more than 60-90 minutes at a time
  • Authors annotate prior to review
  • Establish quantifiable goals and capture metrics to improve the process (I’m noticing a theme here)
  • Checklists are good
  • Verify that defects are fixed
  • Managers must foster a good code review culture in which finding defects is viewed positively.
  • Beware the “Big Brother” effect.
  • The Ego Effect: Do at least some code review, even if you don’t have time to review it all.
  • Lightweight-style code reviews are efficient, practical, and effective at finding bugs.

And here (and here) is an interesting take by Torvalds that Paul found.

  • There will be bugs.  Don’t aim for zero.
  • “Same goes for ‘we should all just spend time looking at each others patches and trying to find bugs in them’. That’s not a solution, that’s a drug-induced dream you’re living in.”

Plan on talking with developers to brainstorm on it…

Dad

November 11th, 2009

It appears that the folks at Shapiro’s Deli are almost as proud of Dad as I am…

Dad-Shapiros