Latest weblog entries

2016-04-28 USB speakers

Since ages, I've had these Logitech V20 speakers (serial number S-0155A) which get both their power and their audio over USB:

There are a couple of awesome things about these:

  • If you have a laptop and want something close to a docking station, then just get a USB hub, connect these speakers along with your other peripherals and save yourself the connecting/disconnecting of the 3.5 mm audio jack each morning.
  • If you have a device without a 3.5 mm audio jack, but does have USB, this is a great way to get sound. For example most Synology disk stations support these speakers.
  • If you have a PC with a terribly noisy audio jack, these speakers give you a great way to get decent quality audio without the interference.
  • They're supported on every OS that I know: Linux, OS X, Windows.

Until recently, people would ask me where to get these. But unfortunately they long since went out of stock everywhere and you'd have to rely on the second-hand market. But lately I found out that Logitech makes a new model that strictly uses USB for both audio and power: the Logitech S150.

2016-04-24 Swift solution to StoneWall

This is a 100% scoring solution to the Codility StoneWall problem. Note the bunch of print statements which I've left included for now.

  import UIKit
  public func solution1(inout H : [Int]) -> Int {
    var stack: [Int] = []
    var nBlocks = 0
    var i = 0
    var lastHeight = 0
    func append(height: Int) {
      print("append \(height)")
      lastHeight = height
      nBlocks += 1
    while i < H.count {
      let currHeight = H[i]
      print("i=\(i), currHeight=\(currHeight)")
      if i == 0 {
      } else {
        if currHeight == lastHeight {
          print("currHeight == lastHeight")
        } else if currHeight > lastHeight {
        } else { // currHeight < lastHeight
          // Keep popping
          var found = false
          while !stack.isEmpty {
            let lastAppendedHeight = stack.last!
            if lastAppendedHeight == currHeight {
              print("lastAppendedHeight == currHeight == \(currHeight)")
              lastHeight = currHeight
              found = true
            } else if lastAppendedHeight < currHeight {
          if !found {
      i += 1
    return nBlocks
  var H = [8,8,5,7,9,8,7,4,8]
  H = [1,2,3,4,5]
  H = [1,1,1,1,1,1,1,1,1]
  H = [1,2,3,3,3,2,2,2,2,2,1]
  H = [5,4,3,2,1]
  H = [1,2,1,2,1,2]

2016-04-16 Codility supports Swift

If you didn't know Codility: it's a company that devises programming tests that are used to test applicants for a job opening. Besides that, other uses are simply to exercise oneself, gaining skills in solving programming puzzles.

And now it supports Swift! I've been having fun doing some small puzzles here and there. For example, this is my solution to the Number of Intersecting Disks problem.

And for Lesson 7, the Brackets test, here is the solution I came up with:

    //: Playground - noun: a place where people can play
    import UIKit
    enum Bracket: Character {
        case squareOpen = "["
        case squareClose = "]"
        case roundOpen = "("
        case roundClose = ")"
        case curlyOpen = "{"
        case curlyClose = "}"
    public func solution(inout S : String) -> Int {
        var bracketStack: Array<Bracket> = []
        for bracketChar in S.characters {
            guard let bracket = Bracket(rawValue: bracketChar) else {
                return 0
            switch bracket {
            case .squareOpen, .roundOpen, .curlyOpen:
            case .squareClose:
                if let b = bracketStack.popLast() {
                    if b != .squareOpen {
                        return 0
                } else {
                    return 0
            case .roundClose:
                if let b = bracketStack.popLast() {
                    if b != .roundOpen {
                        return 0
                } else {
                    return 0
            case .curlyClose:
                if let b = bracketStack.popLast() {
                    if b != .curlyOpen {
                        return 0
                } else {
                    return 0
        if bracketStack.count > 0 {
            return 0
        return 1
    var validString = "{[()()]}"
    var invalidString = "([)()]"

2016-03-18 Updating Xcode

Erica Sadun about updating Xcode. The Mac App Store prompted her to update Xcode, and that's what she did. Unfortunately, the download is very big and you don't really have control over the download and update process.

I've learned long ago that it's much better to simply download the .dmg file by logging in as a developer, going to the Xcode downloads page, click on the link "Additional tools", and download the .dmg file from there.

I rename the existing installation to, for example /Applications/ so I always can go back. And from the .dmg, copy the new version to /Applications. Then if my current project nicely compiles and deploys, I remove the old Xcode installation.

As an aside, I really hope Apple will give developers a way to download that multi-gigabyte file from the commandline or perhaps in chunks of 500 megs or something. The whole root of the XcodeGhost problem was that developers were downloading Xcode from a fast 3rd party server, because the usual route wasn't feasible.

2016-03-18 Lets Encrypt

Another day, another TLS certificate from the friendly folks at Let's Encrypt! I'm running Debian 8.2 (Jessie) so I took the following steps:

Add the following lines to /etc/apt/sources.list

 # Backports repository
 deb jessie-backports main contrib non-free

Update the lot, then install the client:

 $ sudo apt-get update
 $ sudo apt-get install -t jessie-backports letsencrypt

I'm running Apache and had SSL configured already. So I ran the client:

 $ sudo letsencrypt certonly --webroot -w /var/www/vankuik/www/ -d

Then updated the domain configuration to the following lines:

 SSLCertificateFile    /etc/letsencrypt/live/
 SSLCertificateKeyFile /etc/letsencrypt/live/
 SSLCertificateChainFile /etc/letsencrypt/live/

Restart Apache:

 $ sudo service apache2 restart

And then reload in your browser. Et voilĂ , the results are in:



Weblog Archive

Weblog entries 2015

Weblog entries 2014

Weblog entries 2013

Weblog entries 2012

Weblog entries 2011

Weblog entries 2010

Weblog entries 2009

Weblog entries 2008

Weblog entries 2007

Weblog entries 2006

Weblog entries 2005

Weblog entries 2004

All weblog entries


Articles, chronologically (latest first). This is pretty old stuff.


Not yet finished. Maybe will never be finished. Maybe they'll get deleted. Who knows?


System administration: