My nail maintenance by necessity

my nails would not be considered "long" by any stretch, but once they get to a certain point, like millimeters, i basically can't type anymore

https://twitter.com/jasontconnell/status/988480972722200576

Royal Family News

Is there a way to turn off Royal family news? I managed to go years without knowing anything and I'd like to keep it that way

https://twitter.com/jasontconnell/status/988394646823895040

Gulp Coffee

compiling coffee script with gulp

"i can just do gulp coffee it looks like.
which is what i do all day anyway."

https://twitter.com/jasontconnell/status/986275775916773376

Philadelphia Sports 2018

I just need the Flyers, Phillies, Villanova, and the Sixers to win Championships this year then I'll be satisfied.

https://twitter.com/jasontconnell/status/980961145271005184

Too bad the Flyers are out of it though.

Brain Bending Stuff

I work on some pretty brain bending stuff, but today I was amazed when I went downstairs and when I got down there I remembered what I went down for :)

https://twitter.com/jasontconnell/status/979879776151318528

Flurry of Posts

I will be making a series of posts. Basically, I find the stuff I write on twitter is hilarious :D And it's only available on twitter.

Also, I was working on a guitar project. I am a huge fan of The Kinks. So I recorded myself playing guitar along with the entire Kinks - We Are The Village Green Preservation Society album. It's my favorite. The project was: Record myself playing guitar, figure out the songs that same day (usually, I did know a few already), it would have to be recorded on my cell phone, and mistakes are allowed!

So generally, the quality is bad and the playing is ok. The music is still great though. Here it is, the Village Green Office Sessions

For twitter posts, I'd probably like to write something that scans twitter for my posts tagged with a certain tag and import them automatically as posts. But I'm in a transition period on this site. Basically I want to learn Google's Cloud suite of tools and rebuild it there. So updates will have to wait.

Google App Engine on Windows

For the life of me, the Google App Engine "Quick Start" wasn't working for me for starting up the development server in Go. The command listed as "dev_appserver.py app.yaml" is the one I'm referring to. Windows kept asking me which program I wanted to use to run it.

Trying to avoid installing another copy of python, since it comes with the Google Cloud SDK, and I knew the "gcloud" command used python, I decided to look for that gcloud.cmd. And I found it. And I copied it. Only to run the dev_appserver.py instead of gcloud.py :)

Here it is. Just put it alongside the dev_appserver.py and it'll run fine.

 


@echo off

SETLOCAL

SET "CLOUDSDK_ROOT_DIR=%~dp0.."
SET "PATH=%CLOUDSDK_ROOT_DIR%\bin\sdk;%PATH%"

SETLOCAL EnableDelayedExpansion

IF "%CLOUDSDK_PYTHON%"=="" (
  SET BUNDLED_PYTHON=!CLOUDSDK_ROOT_DIR!\platform\bundledpython\python.exe
  IF EXIST !BUNDLED_PYTHON! (
    SET CLOUDSDK_PYTHON=!BUNDLED_PYTHON!
  ) ELSE (
    SET CLOUDSDK_PYTHON=python.exe
  )
)
IF "%CLOUDSDK_PYTHON_SITEPACKAGES%" == "" (
  IF "!VIRTUAL_ENV!" == "" (
    SET CLOUDSDK_PYTHON_SITEPACKAGES=
  ) ELSE (
    SET CLOUDSDK_PYTHON_SITEPACKAGES=1
  )
)
SET CLOUDSDK_PYTHON_ARGS_NO_S=!CLOUDSDK_PYTHON_ARGS:-S=!
IF "%CLOUDSDK_PYTHON_SITEPACKAGES%" == "" (
  IF "!CLOUDSDK_PYTHON_ARGS!" == "" (
    SET CLOUDSDK_PYTHON_ARGS=-S
  ) ELSE (
    SET CLOUDSDK_PYTHON_ARGS=!CLOUDSDK_PYTHON_ARGS_NO_S! -S
  )
) ELSE IF "!CLOUDSDK_PYTHON_ARGS!" == "" (
  SET CLOUDSDK_PYTHON_ARGS=
) ELSE (
  SET CLOUDSDK_PYTHON_ARGS=!CLOUDSDK_PYTHON_ARGS_NO_S!
)


SETLOCAL DisableDelayedExpansion


"%COMSPEC%" /C ""%CLOUDSDK_PYTHON%" %CLOUDSDK_PYTHON_ARGS% "%~dp0\dev_appserver.py"" %*

On guns

Going on facebook or something after a tragedy like what happened in Florida, it's such a waste of time. You really see the worst of both sides. I'm not for or against guns, I see the argument on both sides (I recently did a personality test and I'm firmly INTP which is nicknamed "Logician". I think and perceive and I don't let emotions really lead to decisions I make.  So I'm also not very opinionated.)

My thoughts are, there has always been crazy, there hasn't always been guns. In order for someone to kill 17 people before guns, before assault rifles or high capacity magazines, they'd have to either be a serial killer or in some kind of armed forces, a king. Or the leader of a cult. I'm simplifying. Basically, a single person couldn't weild something that gave them so much power that they didn't spend years trying to earn. This gives so much power to anyone who manages to stay sane for a little while to pass background checks, saves up a couple hundred bucks, and buys a gun. This is a desire for power with the classic means to gain it largely nerfed.

That's all.

Advent of Code 2017 - Day 13

Day 13 reveals itself as a sort of lock picking exercise. Part one is a simple tumble (get it) through the series of inputs they give you, to figure out if you would be caught on a certain layer, and if so, do some multiplication to get your answer. Simple.

The puzzle could also be thought of as the scene in The Rock (the movie about Alcatraz with Nicholas Cage and Sean Connery), where, to get into the prison, Sean Connery has memorized the timing for the fires that blaze, and rolls through them unscathed.

Except, the timings way down the line don't match up since they themselves are on their own timers. And there's like 40+ of them.

The sample input looks like this:

0: 3
1: 2
4: 4
6: 4

So, layer 0 has a depth 3. So on "second 0" the scanner is at 0, on second 1 it's at 1, on second 2 it's at 2, on second 3 it goes back to 1, and on second 5 it's back to the start, blocking any would-be attackers.

Layer 1 only has depth 2, so it's fluctuating back and forth between 0 and 1.

Since the puzzle input may include gaps, and it's easier (probably) to complete the puzzle with no gaps, the first step is to fill them in! As usual I'm writing my answers in Go

func fill(scanners []*Scanner) []*Scanner {
	max := scanners[len(scanners)-1].Depth
	for i := 0; i < max; i++ {
		if scanners[i].Depth != i {
			s := &Scanner{Depth: i, Range: 0, Nil: true}
			scanners = append(scanners[:i], append([]*Scanner{s}, scanners[i:]...)...)
		}
	}
	return scanners
}

That line   ------    append(scanners[:i], append([]*Scanner{s}, scanners[i:]...)...)  ---- with all the dots!! What it's doing is pretty simple, though.

If we don't have a scanner at depth i, insert a scanner with depth i at the current position.   "scanners[:i]" is all scanners up to i.  "scanners[i:]" is all scanners after and including i  ( the :   (colon) syntax is very subtle). So we want to insert it between those two. That's all it's doing. The ellipsis confusion is just because "append" takes a variadic list of parameters, and you can convert an array to variadic parameter with the ellipsis. Done!

We'll need a method to move all of the scanners every step. That's pretty straightforward. I called this method "tick". The Scanner is just a struct with Depth, Range, Current, and Dir for telling which direction the thing is moving.

func tick(scanners []*Scanner) {
	for _, s := range scanners {
		if s.Nil {
			continue
		}

		if s.Current == s.Range-1 {
			s.Dir = -1
		} else if s.Current == 0 {
			s.Dir = 1
		}

		s.Current += s.Dir
	}
}

Part 1 was to just send a "packet" (or Sean Connery) through and every time you are at a security scanner (explosion, going back to the movie), multiply the depth times the range at that scanner, and add it to the previous number to get the new number. That part was fine, and you could do it with the physical motion of passing the Sean Connery through :)

So, to figure out part 2, which is "you need to get through without getting caught this time".  Getting caught is simply being at Depth "d" when the scanner at "d"'s current position is 0. You could brute force this.

For brute force, you'd start at delay 0, then try go figure out if you can make it all the way through. If not, move to delay 1 and try again. For each delay, you have to run the tick method. For delaying 100 seconds, tick would have to be run 100 times to get the puzzle into the correct state. So this becomes computationally intense!

This is a fine solution in most instances. In this instance, though, I let it run over lunch and checked in with it 44 minutes later, and it wasn't complete yet! So, back to the drawing board.

But wait!!  Math is a thing. And it's very useful!  I'm actually pretty certain that I don't even need to check the final answer by actually traversing the sequence of layers, it's just the answer. Due to math!

So, to get through safely, the position of a particular depth has to not be 0 when we're passing through it. I wrote a method to figure this out, called "possible". It's pretty much the key to the puzzle, and solving it insanely fast.

func possible(scanners []*Scanner, delay int) bool {
	p := true
	for _, s := range scanners {
		blocking := (s.Range*2 - 2)
		p = p && (s.Nil || ((delay+s.Depth)%blocking != 0))
	}
	return p
}

A "Nil" scanner is a scanner that was filled in due to gaps. This one has 0 range and can't block anything. So if it's one of these, it can pass through this depth at this time.

The (s.Range * 2) - 2.  Call this "blocking" or whatever. I called it blocking since it's at position 0 of its range every "blocking" number of steps. A scanner with range 4 is back to 0 every 6 steps (4 * 2 - 2) To determine if it's possible at this delay, a layer 7 steps in cannot be blocking on delay + 7. Otherwise it gets caught.  (delay + depth) % blocking.   (After delay, scanner at depth "depth" has to not be at the start ( mod blocking == 0) ).  "p" is kept, for each step, if we can pass through up until now and the current layer. You could possibly shave off some iterations here by checking p, and if it's false, break out of the loop. I might actually update it to do that and report back! It takes about 1 second to run currently. (CONFIRMED. it runs in about half a second now).

So, all that's left is to still brute force the numbers to find if it's possible to get through the sequence at the current delay, without getting caught, but you don't have to actually do it, which speeds it up somewhere on the order of a million percent :)

Check out the full solution here - https://github.com/jasontconnell/advent/blob/master/2017/13.go

Happy coding, and happy holidays!!

Some Plays on Words and Phrases

Sometimes hilarious things pop in my head. Actually, I'd wager that sometimes that doesn't happen. Implying it happens most of the time. Here are some new ones (for me) for you potential comedy writers out there. I don't need any public credit :P  Maybe just a comment or email.

"Do I look like somebody who " ... You know this. "Do I look like someone who checks the toilet seat before they sit down?"  Or "Who cares what color their shirt is?"  etc. Here are a few fun ones I came up with.

"Do I look like somebody who looks like somebody?"   Yeah, pretty bad.

"Do I look like somebody who asks to be compared to anybody by their looks?"  A little better.

"Do I look like somebody who looks at things?"  Might be said by a blind person, so after my original inspiration for this, the ingenuity has been lost and it has been discounted back to lacklustre.

That's all I got though. Any more would be forcing it. You might argue the first 3 are as well ;)