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

January 22, 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 17, 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! 🙂

Sometimes you need a little web server

July 2, 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.

Improving OpenMRS Code Review

April 15, 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.

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

Plan on talking with developers to brainstorm on it…

Translating Listserv archive to mbox format

November 30, 2008

We wanted to import our old mailing list entries from the OpenMRS mailing list Listserv archives into Nabble.  No problem.  Finding the GET listname FILELIST and GET listname file1, GET listname file2, … commands was easy enough.  A quick search of Nabble support made it clear that I needed to send them mbox files.  So, I set out in search of a Listserv to mbox converter.  I found a couple scripts: one in perl and another in PHP.  But trying them out, made it clear that I was going to have to do some tweaking.  After a few near misses, I thought: “I could do this easier in Groovy.”  So, I ended up with this script.  Basically, it came down to leaving the messages and their headers alone and just adding a From_ line in front.  Otherwise, the only tricky part was getting the dates right (GMT time without timezone specified in the From_ line and a some reshuffling of the date format in the message header).

Both for future me and anyone else who might benefit, here’s the script I ended up with:

import java.text.SimpleDateFormat

delim = '=' * 73	// LISTSERV separates messages with a bar of equal signs
foundDelim = false	// we skip all content until first delimiter
inHeader = true		// true when processing header data
def header = ""		// holds current header data

dfListserv = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss z")
dfHeader = new SimpleDateFormat("E MMM dd HH:mm:ss yyyy z")
dfMbox = new SimpleDateFormat("E MMM dd HH:mm:ss yyyy")
dfMbox.timeZone = TimeZone.getTimeZone("GMT")	// for mbox, convert to GMT and drop timezone reference
cal = Calendar.instance

// Process input line by line from stdin
System.in.eachLine() { line ->
  if (!foundDelim)
    foundDelim = (line == delim)	// skip until we find first delim
  else if (inHeader) {
    // within header
    if (line =~ /^s*$/) {
      // empty line signals end of header
      
      // fetch Date from header and reformat it for output
      m1 = header =~ /(?ms)^Date:s+(.*?)s*$/
      date = dfListserv.parse(m1[0][1])
      cal.time = date
      mboxDate = dfMbox.format(cal.time)
      headerDate = dfHeader.format(cal.time)

      // fetch From from header
      m2 = header =~ /(?ms)^From:s+(.*?)s*$/
      fromHeader = m2[0][1]
      leftBracket = fromHeader.indexOf('<')
      rightBracket = fromHeader.indexOf('>')
      if (leftBracket > 0 && rightBracket > leftBracket)
        from = fromHeader.substring(leftBracket+1, rightBracket)
      else
        from = fromHeader

      // output header with mbox-required From_ line up front and reformatted date
      header = "From $from $mboxDaten" + header.replaceAll(/(?m)^Date:s+.*$/, "Date: $headerDate")
      println "$headern"

      inHeader = false	// no longer in header
      header = ""	// clear for next message
    } else {
      header += "$linen"	// accumulate full header data
    }
  } else if (line == delim) {
    // if we find a delim, begin processing next line as header
    print "nn"
    inHeader = true
  } else {
    // within a message, just send it through untouched
    println line
  }
}

ReviewBoard for OpenMRS GSoC 2008

May 5, 2008
Thanks to the generous folks at Review Board, OpenMRS has the opportunity to try out Review Board for performing code reviews for our GSoC projects.

Students can download post -review (a python script) and submit changes for review simply by issuing the command “post-review” within the root of their local copy.

Mentors can review the changes and attach comments to specific parts of the code for the student to review prior to submitting the code.

NOTE: since this feature is being generously hosted by Review Board, this feature should only be used for student projects at this time. If we decide that we want to continue using Review Board, then OpenMRS will host our own instance.

Thanks to chipx86 for his help in getting this set up. And thanks to r0bby for letting us know about the opportunity!