Archive for the ‘Clojure Coding’ Category

Trying out a new Editor Font

Tuesday, January 21st, 2020

GeneralDev.jpg

A few days ago, I read about the new JetBrains Mono font that they had created for their IDEs, and it looks interesting with the increased hight of the lower-case letters, and the easily readable "1lI" combination... so I decided to give it a whirl on my editor, and in Xcode.

I have to say I like how Sublime Text and Xcode handles all the weights of the font, and the ligatures for common expressions makes it a lot easier to read the code - as if I'd written it on a chalkboard. Very nice indeed

JetBrains Mono for Clojure

I'm not sure how it'll play out, but it's pretty nice so far, and I'll play with it for a bit and see what I think. So far... nice. 🙂

Finished Advent of Code 2019

Tuesday, January 7th, 2020

Christmas Tree

This morning I finally finished Advent of Code 2019. Most days weren't too bad - I think the ones that really caused me to work extra were Day 18 and Day 20 - both of which were the pathing problems that I had failed to really master in years past. Good or bad, I decided not to give up on these, and figured out how to solve these this year.

Dijkstra's Algorithm is interesting, but I really didn't see how to implement it in Clojure until I was walking home one day - and it hit me: the recursion really made it all so much easier. And that really helped me as I hammered on these problems this year to really get a solid understanding of how to work with Dijkstra's. I'm very glad I stuck with this.

Then when I had that understood, I ran into Day 20 where it wasn't the right approach, but I needed to understand a simple Breadth-First Search on the maze. This is much different than Dijkstra's in that it's a simple looping construct, and only finds the one shortest path - but that's OK... that's all that was asked for. But it's fast. Very.

I'm really glad that this year I didn't stop when the problems seemed to be too tough for me. I'm a better coder because of the new knowledge. 🙂

Advent of Code Day 25 Adventure Map

Wednesday, December 25th, 2019

Christmas Tree

Today, the first part of Advent of Code was to run an Intcode program, and move a droid around the inside of Santa's ship. It was really just an Adventure Game, and after exploring the game, you needed to pick up certain items, and then bring them to the pressure plate to make sure you "pass", and get through to see Santa.

I remember doing something like this with the original Zork, on the machines back at Purdue in the early 1980s... and so I was used to the idea of making a map as I explored:

AoC Day 25 Adventure Map

Once I picked up all the things I could pick up - and there were plenty that I couldn't, I took them all to the room, and dropped what I couldn't carry. That was a lot easier than changing up the path each time to pick up only what I needed.

Now I need to go back and solve three more days to get all the stars... it's going to be challenging... but I've got a little time. 🙂

An Interesting Christmas Break

Monday, December 23rd, 2019

Path

It's been a very interesting Christmas Break - as I use up my use-it-or-loose-it vacation time at The Shop, and still... I attend the meetings on Hangouts, and I do what I can to help those that are working during the break... but it's been an interesting time - no doubt about it.

I've watched some interesting TV... I really enjoyed the first season of The Morning Show - but then I really don't like bullies... and I've really enjoyed watching the last three Mission: Impossible movies... and it's been fun to do as much Advent of Code as I can.

There are certainly problems I don't understand the background for, and while I could learn it - I'm not going to learn it now, in 20 min, for a single problem. That's not going to last. But I can come back to it any day, and dig deeper into things like inverse modulo... and some serious computational search space pruning... but in all, it's been fun.

Christmas in a few days, and then a week and it's back to The Shop and the New Year. Lots of changes ahead... lots of things to think about in the next week.

Advent of Code is Back

Sunday, December 1st, 2019

Christmas Tree

Just finished the Day 1 puzzle to Advent of Code for 2019. And as expected, it was funny, and fun to do. I've been playing with the LeetCode examples - just to stay sharp, and one of the things that Advent of Code provides that LeetCode doesn't is the data files. Sure, I get it... they test after you write the code, but if, like me, you don't choose one of their languages, then you're really out of luck.

Still... I'll keep doing these as long as the authors make them, because they are fun and keep my mind sharp. I am very grateful for these folks... 🙂

UPDATE: some days are going well - others are computationally very hard, and I clearly need to figure out how to solve those. I won't get them all in the first go, but I'll keep at it... 🙂

Frustration with Speed Coding Interviews

Wednesday, September 18th, 2019

Clojure.jpg

Yesterday I had an interesting phone screen with someone, and the seemingly common practice of asking a candidate to code on the phone - in a shared web-based environment again came up. I recognize that any employer can have any legal criteria for employment, and the "Coding Phonescreen" is a very common one. You get to see if the person can write code in a few minutes as opposed to inviting them for a day-long interview cycle that can cost considerably more. It's decent logic.

But it really doesn't tell the story, does it?

Speed Coding has about the same relationship to real development as a college classroom has to Jeopardy!... yeah, the material is the same, but the skills to be able to do well in one do not necessarily translate to the other. And the most critical skill in the speed forms is pattern recognition of the problem.

If you've seen this problem before, and written a simple solution to it, then you're in good shape. You know the flow, you know the pitfalls, and you can talk your way through it - like you're talking your way through directions to a local restaurant. No pressure, you're showing someone something you know, and it happens to take a few steps. No biggie.

But if you're at all unsure, then you're not going to get time to think about the solution before being expected to answer it. This is the problem with Speed Coding - if you know the answer, it's fine. But then it's not really seeing if you can think on your feet... if you don't know the answer, you're likely going to make one or two edge-case mistakes, and those will be clearly visible to the person that knows the solution.

The problem I ran into was a binary tree issue, and while I had been practicing my Speed Coding in Clojure, the nature of the binary tree really leaned towards a C++ solution, and that was not horrible, but it was a lot less friendly to edge-conditions.

I ended up writing something like this:

  struct Node { int value; Node *left; Node *right };
 
  bool stored(Node *me, op) {
    bool   retval = true;
    if (retval && (me->left != NULL) && (me->left op me->value)) {
      retval = stored(me->left, op);
    }
    if (retval && (me->right != NULL) && (me->value op me->right->value)) {
      retval = stored(me->right, op);
    }
    return retval;
  }

and the missed edge-case is that once you are one, or more, steps down in the tree, it's possible to have the relative position of the values be correct, but the absolute position to be false. There are two ways to solve this, in this code:

  1. Pass limits down with the call - this could be done with max and min arguments and then in the recursive calls, place the correct values there, and test them as well.
  2. Scan up the tree on each check - this could be a walk-up the tree and check to see that you aren't in violation of the location you have. This would take more time because of all the walking, but it'd work.

But what I'd wanted to do was to write it in Clojure, but the data structure didn't jump out at me. Until this morning. 🙂 This morning I spent the minute or two thinking about the data structure, and then formulated the following solution:

  ;; [val left right]
  ;;       10
  ;;    5      15
  ;;  1   7  12   20
  (def good [10 [5 [1] [7]] [15 [12] [20]]])
 
  ;;       10
  ;;    5      15
  ;;  1   17  12   20    -- the 17 is out of place
  (def bad [10 [5 [1] [17]] [15 [12] [20]]])
 
  (defn sorted?
    "Function to check a binary tree to see if it's sorted for proper
     searching."
    [[v lt rt] op]
    (let [ltv (first lt)
          rtv (first rt)]
      (and (or (nil? lt) (and (every? identity (map #(op % v) (flatten lt)))
                              (check lt op)))
           (or (nil? rt) (and (every? identity (map #(op v %) (flatten rt)))
                              (check rt op))))))

What I really like about this solution is that it checks the entire subtree with the operation. This means that the effort to do one, is really checking all of them. This is what I wanted to write, and it works perfectly.

But I didn't force the issue, and pull back and take the time to think. My mistake. I won't make it again.

UPDATE: a friend and I were talking about this same problem, and he came up with a solution that was very clever - the structure can be validated by simply assuming that the structure is a sorted binary tree, and then calculating the min and max values of the tree.

The catch being that if you get to a node where the current value isn't within the min and max, then you have to fail, and return nil. It's really quite amazingly simple in that it's very fast, very easy to understand and adds the additional benefit of returning the extremum of the tree.

  (defn bst-rx*
    "returns extent [min max] of valid bst or nil if invalid"
    [t]
    (cond
      (nil? t) nil
      (vector? t) (let [[v l r] t
                        lx (if l (bst-rx* l) [v v])
                        rx (if r (bst-rx* r) [v v])]
                    (when (and lx rx (<= (lx 1) v (rx 0)))
                      [(lx 0) (rx 1)]))
      :else [t t]))
 
  (defn bst-rx?
    [t]
    (boolean (bst-rx* t)))

Moving to Leiningen 2.9.0 and Ultra 0.6.0

Wednesday, August 21st, 2019

Clojure.jpg

This morning I decided to see about the status on one of my favorite Leiningen plugins - Ultra, the formatter, highlighter for the REPL. It makes things so much easier to see and read at a glance, and follow along quickly with the output of a function, or the values in some input. It's really what syntax highlighting did to text editors. Very nice.

Anyway... I found that Ultra 0.6.0 was up on Clojars, and so I was able to move to Leiningen 2.9.0 in Homebrew with:

  $ brew switch leiningen 2.9.0

and then I changed my ~/.lein/profiles.clj to be:

  {
   :user {:plugins [[lein-exec "0.3.7"]
                    [venantius/ultra "0.6.0"]]
          :ultra {:color-scheme {:delimiter [:bold :yellow]
                                 :tag [:bold :yellow]
                                 :nil [:cyan]
                                 :boolean [:bold :cyan]
                                 :number [:bold :green]
                                 :string [:bold :red]
                                 :character [:cyan]
                                 :keyword [:yellow]
                                 :symbol [:bold :magenta]
                                 :function-symbol [:bold :blue]
                                 :class-delimiter [:blue]
                                 :class-name [:green]
                                 :exception [:bold :red]}}
         }
  }

and then I was ready to go.

One downside of moving to Leiningen 2.9.0 is that nREPL 0.6.0 formats the output a little differently, and it places an additional newline on the end of the output, so that it now appears to have a "double spaced" output:

Leiningen Differences

where the top REPL was using the old nREPL in Leiningen 2.8.3, and the bottom one was using Leiningen 2.9.0 with nREPL 0.6.0. Now the developers may come to terms with this, and clean this up, or at least make it optional, but for now, I'm willing to live with the extra line as just "part of life"... as I really wanted to get to Ultra 0.6.0 and Leiningen 2.9.0 - due to it's significant structural changes under the hood.

Progress isn't always without a few bumps in the road...

Added a Few Things to Timeless

Saturday, April 27th, 2019

Javascript

My friend, that asked for the Timeless project, pinged me yesterday to say that he really would like to have a "clear" button on the page so that it cleared out all the data in the table. I said I'd look at it today - as soon as I got back up to speed with my new laptop. More on that later. 🙂

What I needed to do was to add a function to wipe out the HandsOnTable, and that wasn't too bad... simply get the row count, and clear out the timestamp data:

  /*
   * Function to clear out the timestamps from the table, and then refresh
   * the table to make sure that it's all cleared out and ready to go.
   */
  function wipeTable(tid) {
    var rows = $(tid).handsontable('countRows');
    for (var i = 0; i < rows; i++) {
      $(tid).handsontable('setDataAtCell', i, 0, '');
      $(tid).handsontable('setDataAtCell', i, 1, '');
    }
  }

Then I just needed to update the HandsOnTable formatter for the computed difference so that if the timestamp cell was empty, we put null in the computed column, and then that would work for both the clearing and the totally empty rows:

  /*
   * The Timeline table needs to have a computed 'diff' for the current line
   * to the previous line. These are all msec times, so it's just a difference
   * of two numbers. Shouldn't be hard. :)
   */
  var timeDiff = function(instance, td, row, col, prop, value) {
    if (instance.getDataAtCell(row, 0)) {
      var a = instance.getDataAtCell(row, 1);
      var b = instance.getDataAtCell((row - 1), 1);
      value = ($.isNumeric(a) ? a : 0) - ($.isNumeric(b) ? b : 0);
    } else {
      value = null;
    }
    Handsontable.NumericRenderer.apply(this, arguments);
  }

And then I needed to place a button in the header of the panel with the table:

  <div class="panel-heading">
    <h3 class="panel-title"><span id="timelineTitle">Timeline Evolution Worksheet</span>
      <form id="wipe_table" class="navbar-form navbar-right pullright"
            role="search" style="margin-top: -8px; display: visible;">
        <button id="wipeTable" class="btn btn-default">
          <span class="glyphicon glyphicon-trash"></span>
        </button>
      </form>
    </h3>
  </div>

Finally, I needed to disable the default function of the form, and wipe the table with:

  // set up the form components to work as we need them
  $("#wipe_table").submit( function(e) {
    e.preventDefault();
    wipeTable('#timelineTable');
  });

Now we have the "trash can" icon in the panel header, and it works like a charm!

Timeless Clear Table

HandsOnTable really is a nice tool. I can see doing a lot of cool things with it.

Finally Moving to Heroku

Wednesday, April 24th, 2019

Heroku

This morning, I realized it was about time to really shop around and see if Heroku or AWS was the right choice for my projects. Now I've heard, and mentioned, that it's likely that the best solution is Heroku, and after digging into all the capabilities and costs, it really is far easier and cheaper to use Heroku and just let it be done. The support for Clojure is first class, and the tools have gotten a lot better, and the pricing has come down, and that was all it took.

The first thing to do was to sign up at Heroku for an account, and then set up that account with the right SSH key, and 2FA with Authy on my iPhone, and then put in the credit card info to be a Validated user - and get more free hours a month for the "Free" dynes. All this was very nice, and really smooth. I liked that the 2FA with Authy is as easy as it is, because it pulls in the account information and icon, and it just plain works.

The next thing was to walk through the example Clojure project to see how it's done. What really matters is that it works, and then I can pick out things from that project - which also uses Jetty, and pull them into my project to get it going as well. As expected, that went very well, and the documentation is really first rate. Just what I've heard I could expect.

Finally, I followed their instructions to scale down the dynos to 0 on the example project, and started to work on converting my project from the old deployment model I had to using Heroku. First off, we needed to pull in the Procfile and app.json from the example project, and then update them to match what we needed for this project. The Procfile was updated to be:

  web: java $JVM_OPTS -cp target/timeless-standalone.jar timeless.main web

because the old init.d scripts I'm used to writing had this same basic line in them. We have to fix up the Uberjar file name, but we'll do that in a minute, but this will launch the Jetty server on the right port, and have everything cooking just fine.

The app.json was updated to be:

{
  "name": "Timeless: Sequencing timestamps",
  "description": "A service/app that helps sequence timestamps from log files.",
  "image": "heroku/clojure"
}

and here, it's pretty obvious what to update - just the name and description.

At this point, we can create the application at Heroku:

  $ heroku create

We need to make a few changes to the code so that it would work with the Heroku infrastructure. First, we had to update the project.clj to add these entries:

  :min-lein-version "2.7.1"
  :plugins [[environ/environ.lein "0.3.1"]]
  :hooks [environ.leiningen.hooks]
  :dependencies [[org.clojure/clojure "1.10.0"]
                 ;; ...other dependencies...
 
                 ;; Heroku environment tools
                 [environ "1.0.0"]]
  :uberjar-name "timeless-standalone.jar"
  :profiles {:uberjar {:main timeless.main, :aot :all}}

Then, in main.clj, we needed to pull the port for Jetty from Heroku's environment variables, and to do this, we updated the code to read:

(defn handle-args
  "Function to parse the arguments to the main entry point of this project and
  do what it's asking. By the time we return, it's all done and over."
  [args app]
  (let [[params [action]] (cli args
             ["-p" "--port"     "Listen on this port" :default 8080 :parse-fn #(Integer. %)]
             ["-s" "--ssl-port" "Listen on this port" :default 8443 :parse-fn #(Integer. %)]
             ["-v" "--verbose" :flag true])
        quiet? (:quiet params)
        fixed? (:fixed params)
        port (Integer. (or (env :port) (:port params) 5000))]
    (cond
      (= "web" action)
		      (try
		        (jt/run-jetty app {:port port})
		        ; finally, close down the async jobs
		        (finally
		          ))
      :else
        (do
          (info "Welcome to Timeless!")
          (println "Welcome to Timeless")))))

the key being to check the :port value with the env function, and then put that in the or before the default from the CLI args. It makes sense, they will want to set the port on the process so that they can stack a lot of them on a single box.

After this, it's as simple as deploying the app with:

  $ git push heroku master
  $ heroku ps:scale web=1

and it should all be running just fine.

When I added the CNAME records to my DNS for this domain, I get a certificate problem because we're moving from bobbeaty.com to herokuapp.com - so I still have to figure that out to make things really smooth, but this is a huge step in the right direction.

UPDATE: the key is not to add it as a CNAME - but a simply web permanent redirection. If we do that, then we can add it as: bobbeaty.com/timeless and we're all good!

Sublime Text 3.2 is Out

Wednesday, March 13th, 2019

Sublime Text 2

This morning I saw a tweet from @SublimeHQ saying that Sublime Text 3.2 was out, and the list of fixes and features was really quite nice. The git integration is very nice - you can now see the branch you're on in the status bar, and when you click that, it will bring up Sublime Merge. It's not bad... not sure how much I'll use that, but it's nice that they have it integrated, and can show the branch on the editor window.

They also added a lot of nice Mac features:

  • Mac: Added Mojave support
  • Mac: Add full support for macOS native tabs
  • Mac: Ensure context menus are shown without scrolling
  • Mac: Error message dialogs can now be closed with the escape key
  • Mac: Improved window placement
  • Mac: Improved resize performance

I wasn't really disappointed with the performance, but to see the support for native tabs and Mojave - it's just really nice.

They also updated the syntax highlighting for Clojure, D, Go, and Lua - and while I'm not a big fan of the others, the changes they made to Clojure really nice. I also noticed that they have done something with the rendering in the Clojure files - could all be part of the syntax highlighting, but I'll have to see what it turns out to be. Looks like they "thinned out" the strokes on the comments, but we'll see. In any case, it's a lot nicer now for most of the coding I do.

It's an exciting upgrade, and it makes my day a little brighter.