Archive for the ‘Clojure Coding’ Category

GitHub Codespaces

Sunday, September 20th, 2020

GitHub Source Hosting

Late last week, I was accepted into the GitHub Codespaces beta program, and since I've been looking for something to do coding on my iPadPro, and was doing a little work with GitPod, it was something I was really interested in seeing and comparing with GitPod. So I started with two of the projects I've put into GitPod: Advent of Code, and CQ.

First things, Codespaces is a similar in that it's all about Docker images of the repos with enough of a system wrapped around it to enable the style of development needed. Java, Ruby, Node, Rust - if you can do it on Debian or Ubuntu, then you can do it in Codespaces. It's just that universal.

It's also possible to run other images, like Postgres, Mongo, MySQL, and then have them linked up to the repo's instance so that you can refer to the databases off of localhost and the default port. That's really nice.

It's not particularly easy - unless you really understand Dockerfiles... but if you keep at it, they have examples, and for the most part, you'll be able to get something going, and it's all in the repo, so it's simple enough to drop the image, and create another. It just takes time.

What I did find interesting is that the default user for Codespaces is root. I was not at all interested in working as root - even on a Docker image... it's just too uncomfortable. Thankfully, there is a vscode user you can use, and the USER directive in the Dockerfile will drop you into that user when things get started.

The next thing is the permissions... it's wild... everything is open to the world, and again, while this may be "fine" - it's very uncomfortable for me, so I converted the ownership of the workspace to the vscode user, and then removed the additional ACL security with:

  $ cd /home/vscode
  $ sudo chown -R vscode:vscode workspace
  $ sudo chmod -R g-w workspace
  $ sudo chmod -R o-w workspace
  $ sudo setfacl -R -bn workspace

With these done, the directory is owned by vscode and it's respecting the normal umask values on the creation of new files.

In the future, I'm going to have to figure out how to personalize the codespace by using the dotfiles repo in GitHub, and then installing my dot files and updating all these permissions, etc. as well. If I get to have several of these, it'll pay off to have it all done properly from the start...

Upgrading AdoptOpenJDK 1.8, 11, and 14

Thursday, July 16th, 2020

java-logo-thumb.png

Just saw a tweet from the AdoptOpenJDK folks, about new releases for JDK 1.8, 11, and 14, and thought I'd update what I had so that I could be assured of being able to upgrade when a serious bug shows up. It's good to be prepared. 🙂

Because I have several versions installed, I needed to upgrade each... and because they are delivered as casks, the upgrade commands are just a little different:

$ brew cask upgrade adoptopenjdk8    ;; 8u262
$ brew cask upgrade adoptopenjdk11   ;; 11.0.8
$ brew cask upgrade adoptopenjdk     ;; 14.0.8

Each one will take a bit to download, and they clean up the older version of the same package - so you only have the latest... not bad, and I can see the advantages.

All up to date now! 🙂

Odd Repl.it Editor Bug in Safari

Tuesday, July 14th, 2020

Clojure.jpg

I've been a big fan of Repl.it as it allows me to be able to fire up a nice Clojure REPL without a lot of grief or overhead, and it's fast enough for small projects, and while it's not perfect - like you can't include a real project.clj so you can't load other packages, it's still pretty nice.

A few weeks ago, I noticed an odd little bug in the editor on Repl.it - the cursur wasn't where the actual insertion point was on the editor:

Real it Editor Bug

The more you had on a line, the more of a gap there would be on the editor. And it didn't matter if I was using the Desktop browser on my iPad, or the Mobile browser... on my iPad, it was off. And I tried a lot of things... reported it to the Bugs List for Repl.it, and while others had seen it - there were no answers.

Finally, I thought about the zoom feature.

On my iPadPro, for Repl.it, I like to zoom out a few steps to get more on the screen. I don't mind the smaller fonts - I can read them just fine, and it reduces the "dead space" on the screen quite nicely, so that I have a good editor window, and a nice REPL window.

So I went back to Repl.it, pulled up a saved REPL, and rest the zoom to "Original". Boom! The cursor and the insertion point lined up, and looked just fine. I then updated my Bug Report on Repl.it, and hoped that it was going to be a lot easier to reproduce for the developers - because I had a way to make it "Good", and then "Bad", and back to "Good". Repeatable 100% of the time!

It's been a few weeks, and nothing, so today I offered to help work on this, as I'd really like to have this fixed, and I'm sure others would too... but I may have to wait for iPadOS 14, and hope that Safari on iPadOS 14 is going to fix this behavior.

I'd be happy to help... because I'd really like it fixed before the Fall.

Upgrading Postgres 11.1 to 12.1 Using Homebrew

Tuesday, February 4th, 2020

PostgreSQL.jpg

It's time to make sure that my laptop has the latest version of PostgreSQL, as I was reading that Heroku was moving to Postgres 12 as their default database. And since I don't do it that often, I decided to write it all down so that it's easier to do next time.

The process isn't bad... dump all the databases into one file, stop the server, update Homebrew, update postgres. This gets us to the point that we are ready to rebuild the new database:

  $ pg_dumpall > dump.sql
  $ brew services stop postgresql
  $ brew update
  $ brew upgrade postgres

Now we need to move out the old database data, create a new structure, and restart the service:

  $ cd /usr/local/var
  $ mv postgres postgres.old
  $ initdb -D /usr/local/var/postgres
  $ brew services start postgresql

You then need to go back to the directory of the first command - the one where you dumped the databases, and reload them all:

  $ psql -d postgres -f dump.sql

and at this point, everything should be back and running:

  $ psql --version
  psql (PostgreSQL) 12.1
  $ psql -l
                                      List of databases
      Name     | Owner | Encoding  |    Collate     |     Ctype      |  Access privileges
  -------------+-------+-----------+----------------+----------------+---------------------
   health      | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   inventory   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   northhollow | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   postgres    | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   template0   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII | =c/drbob           +
               |       |           |                |                | drbob=CTc/drbob
   template1   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII | drbob=CTc/drbob    +
               |       |           |                |                | =c/drbob           +
               |       |           |                |                | _postgres=CTc/drbob+
               |       |           |                |                | postgres=CTc/drbob
   test        | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
  (7 rows)

At this point you can remove the old data:

  $ rm -rf /usr/local/var/postgres.old
  $ rm dump.sql

and everything is updated. You can then use any of the normal tools, including the Apache/PHP/Postgres that Apple makes available, and Postico - a great GUI client.

UPDATE: a friend asked: "What's in 12?" and I had to say I really didn't know... so I looked it up. The big changes are all about under-the-hood performance, and so, as I suspected, it just "works better". Which is really the goal, right? 🙂

I know I will probably enjoy the JIT on by default, as there are plenty of times stored procedures are in my databases, and that makes them faster, which is always nice. But it's just a great database - getting greater.

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)))