Skip to content
July 20, 2011

Spotify AutoHotkeys Script

The following code can be used in conjunction with AutoHotkey to control Spotify without needing it to be in focus.

#left::Media_Prev
#right::Media_Next
#space::Media_Play_Pause
#down::Volume_Down
#up::Volume_Up

#s::Run C:\Program Files (x86)\Spotify\spotify.exe

Keys:

  • WinKey+Space to play/pause Spotify
  • WinKey+Left goes to previous song
  • WinKey+Right goes to next song
  • WinKey+Up increases volume
  • WinKey+Down decreases volume
  • WinKey+S runs Spotify
July 18, 2011

Fine-Tuned Universe

via SMBC

July 7, 2011

IS TROPICAL – THE GREEKS Music Video

Absolutely fantastic video. Great editing, and the song is catchy as well

July 7, 2011

Sitecore Money Field

Sitecore doesn’t haven’t a built in field for rendering currency fields (they’re stored as plain text entries). I created this field control to remedy this with an implementation of a Money field control. You can specify how you want it formatted, but if you don’t specify anything, then it defaults to the format string "C" which essentially results in $#,###.## for output.

Setup

In either Web.config or another config file that is set up, add the following to the pages -> controls node

Source

Put the following code in a file in the assembly defined above, with the same namespace.

public class Money : FieldControl
{
	public string Format { get; set; }

	public Money()
	{
		Format = "C";
	}

	protected override void Render(HtmlTextWriter output)
	{
		decimal val;
		if (!decimal.TryParse(GetFieldValue(Field), out val))
		{
			output.Write("");
			return;
		}
		output.Write(val.ToString(Format));

	}
}

Usage

Put the following server tag where you need to output money. The default Format is “C” (which defaults to $#,###.##)

This outputs $#,### based on the format string specified

At the top of the page, add the line

July 6, 2011

Real Life L.A. Noire

I do enjoy the game, but this video certainly captures some of the oddities you experience

March 25, 2011

Car Audio Installation

I have finally gotten my audio system installed in my car fully. I don’t believe there is much else needed to do, aside from maybe upgrading equipment to higher end components or outfitting my car with Dynamat or the like.

Over the progression, I took a few pictures. It was interesting to see how the system evolved over time (I wish I had taken MORE pictures though since that would show how much work went into it as a whole)

Sony Radio

Getting the radio installed took place over the course of a few hours, including some quick trips to the hardware store. I ordered this Sony deck from Crutchfield, and it came with absolutely incredible directions that helped me take apart my dash, as well as the necessary wiring harnesses and other components needed for the install.  The hardware store trips were mostly for additional tools that I thought I needed, but apparently didn’t.  Subaru’s of my type have two difficult to reach screws that reside right about the ash tray (after you remove it).  I got an angled screwdriver, and eventually worked them out, and left them out since they were such a pain.

I actually got quite good at taking the dashboard apart due to this upgrade since I needed to put additional wires in the wiring harness when I added my amplifier.

Along with installing the deck came the installation of four new 6 1/2″ Sony speakers.  I ordered them from Crutchfield as well, and again, the directions were excellent, and I was able to take apart each door, remove the stock speakers and install my new ones without much hassle.  Thankfully as well, everything went back together and I didn’t lose any functionality (like power windows or the like :D )

Single Sony X-Plod Subwoofer

Towards the end of summer, I started researching subwoofers and amplifiers.  I found both through Amazon for a really cheap deal, and also free shipping.  I threw in an Atrend sealed enclosure and had that shipped out.  I also tried to order a wiring kit through Amazon, but the shipping took way too long, and seeing as I was on break between a co-op and college, I wanted to get everything set up before trekking back to Rochester, NY. I picked up a fairly cheap wiring kit from Walmart, 6 gauge wire for the power and ground. I figured I would upgrade at a later time, but just wanted to get things working.

Getting the wiring kit hooked up proved to be a very difficult task. I was at my friend’s house, having him help me as best he could, but the major issue I was having was with running the power wire from the battery to the interior of my car.  I eventually discovered an area where we could drill through the body (under the hood) and down into the wheel well, and then run the wire through a grommet to the interior.  After that, it was relatively smooth sailing getting everything hooked up.  I attached the amp to the back of the sub box, and grounded the amp to a bolt near the lid of the car.  Hearing the sub come to life was quite a rush after working on everything for so long.

Dual Sony X-Plod Subwoofers

I was pretty happy with the single sub for a short time, but I saw that the Sony Xplod subs were still relatively cheap through Amazon, so I ordered another one, and ordered a Bass Bunker ported dual enclosure from Crutchfield as well as some additional speaker wire.

Installing these was quite easy.  After attaching the subs to the enclosure and wiring them up, it was simply a matter of lugging them to my and figuring out where to put my amp.  For that time, I just left it sitting freely next to the enclosure.  Eventually, I tried attaching it to the floor mat in the trunk, and that worked out for a while, except that I lost almost all of my trunk space.

Over spring break, my friend from earlier presented me with a 2 farad capacitor that he was giving to me as a belated Christmas present.  I worked on acquiring the various components I would need to set that up, namely additional wire and ring terminals.  I ordered 4 gauge Kicker wire and some 5mm ring terminals from Crutchfield, without thinking too hard about it.  I later found out that the ring terminals were too small for almost the posts on the capacitor, as well as the bolts in my car. I did manage to use them for attaching my wires to my amp, despite the fact they were too wide to fit, so I had to file them down and force them in.  I ordered four additional 8mm ring terminals this time, and when they arrived I started the fun.

I originally wanted to mount my amp to the back of my rear seats, as well as my capacitor, but it was insanely difficult to just fit them there, let alone work a power drill in the cramped space.  After some thought, I discovered that my amp fit quite nicely in my spare tire area (basically in the wheel).  I removed the foam tool holder and attached the amp to a board upside down so that it hung in the center of the wheel.

2 Farad Capacitor

I attached the capacitor to a little carpet doorway that provides access to my jack since it put it in close range of the amp as well as my ground point.  Once attached, I hooked a few things up and went about charging the capacitor before linking it with the main electrical system.  I bought a 12v LED from Radioshack with leads and put one side on the positive post of the cap and then linked the other lead to the main power wire.  I wasn’t really sure what to expect, except that the LED display on the cap was going to read the voltage. I let it charge for a while, but it kept blinking “Lo” and occasionally “10.0″.  I let the cap “charge” overnight, though apparently that didn’t change anything, so I decided to just go for it. I removed the main fuse from my power line, hooked the power line directly to the positive post of the cap, along with the amp’s positive line, and then popped the fuse in.

Apparently I had been doing it right all along (just wait until the LED goes almost completely out), since the cap’s display jumped right to 12.7v.  I double checked everything, and I must say, it’s fantastic to have a powerful sound system.  I find that I look for excuses to drive, just so I can feel my music while I drive. I also appreciate the knowledge I gained while doing this install, especially when it comes to electrical systems, since I am sorely uninformed in that arena.

If you happen to see a black Subaru Outback and can hear a methodic thumping emanating from it, that could very well be me!

March 22, 2011

Finding Element Index in Haskell

The Haskell method index searches a list for the supplied element, and returns its position if found, otherwise, returns Nothing

index :: (Eq a) => a -> [a] -> Maybe Integer
index x lst = 	indexA x lst 0
			where
				indexA :: (Eq a) => a -> [a] -> Integer -> Maybe Integer
				indexA x [] i				= Nothing
				indexA x (y:xs) i	| x == y	= Just i
							| otherwise	= indexA x xs (i + 1)

January 26, 2011

All the King’s Horses

This script plays a game using a minimax algorithm where each player's AI evaluates all potential moves, or all moves up to a limit, and determines which move to make next. The idea of the game is to move your knight in such a way as to always have an available move. Knights must move towards the upper left of the grid, so they can move two left and one up or down, or move two up and one right or left. You lose the game when you run out of available moves. The evaluation function for the depth limited algorithm uses an area evaluation because it assumes that more squares means more moves overall.

max_x = 0
max_y = 0

def print_board(pieces):
	for y in range(0, max_y):
		line = ""
		for x in range(0, max_x):
			written = False
			for p in pieces:
				if p[1][0] == x and p[1][1] == y and p[0] == 0:
					line = line + "W"
					written = True
				elif p[1][0] == x and p[1][1] == y and p[0] == 1:
					line = line + "B"
					written = True
			if not written:
				line = line + "."

		print(line)

def generate_moves(position):
	return [[position[0] - 2, position[1] + 1], [position[0] - 2, position[1] - 1], [position[0] - 1, position[1] - 2], [position[0] + 1, position[1] - 2]]

def valid_move(pieces, new_position):
	if new_position[0] >= 0 and new_position[1] >= 0:
		for p in pieces:
			if p[1][0] == new_position[0] and p[1][1] == new_position[1]:
				return False

		return True
	else:
		return False

def has_valid_move(player, pieces):
	valid = False
	for p in pieces:
		if player == p[0]:
			moves = generate_moves(p[1])
			for move in moves:
				if move[0] >= 0 and move[1] >= 0:
					for pi in pieces:
						if pi[1][0] != move[0] or pi[1][1] != move[1]:
							valid = True
							break
	return valid

def min_value(player, pieces, limit):
	if not has_valid_move(player, pieces):
		return [1, -1, []]

	min = [1000, -1, [0, 0]]

	if limit == 0:
		mx = 0
		my = 0
		for p in pieces:
			if p[1][0] > mx and p[0] == player:
				mx = p[1][0]
			if p[1][1] > my and p[0] == player:
				my = p[1][1]

		return [mx * my, -1, []]


	for p in range(0, len(pieces)):
		if player == pieces[p][0]:
			for move in generate_moves(pieces[p][1]):
				if valid_move(pieces, move):
					new_pieces = pieces[:]
					piece = [player, move]
					new_pieces[p] = piece

					value = max_value((player + 1) % 2, new_pieces, limit - 1)

					if value[0] < min[0]:
						min= [value[0], p, move]
	return min

def max_value(player, pieces, limit):
	global max_x
	global max_y
	if not has_valid_move(player, pieces):
		return [-1, -1, []]

	max = [-1000, -1, [0, 0]]

	if limit == 0:
		mx = max_x
		my = max_y

		for p in pieces:
			if p[1][0] < mx and p[0] == player:
				mx = p[1][0]
			if p[1][1]  max[0]:
						max = [value[0], p, move]
	return max


def best_move(player, pieces):
	print(pieces)
	print_board(pieces)
	input()
	return max_value(player, pieces , -1)

def best_move_limited(player, pieces, limit):
	print (pieces)
	print_board(pieces)
	input()

	return max_value(player, pieces, limit)

def play(pieces):
	player = 0

	while has_valid_move(player, pieces):
		print("Current Player: " + str(player))

		move = best_move(player, pieces)

		print("MOVE: " + str(move))

		pieces[move[1]][1] = move[2]

		player = (player + 1) % 2

	print_board(pieces)

	if player == 0:
		print("Black wins!")
	else:
		print("White wins!")

def play_limited(pieces, limit):
	player = 0

	while has_valid_move(player, pieces):
		print("Current Player: " + str(player))

		move = best_move_limited(player, pieces, limit)

		print("MOVE: " + str(move))

		pieces[move[1]][1] = move[2]

		player = (player + 1) % 2

	print_board(pieces)

	if player == 0:
		print("Black wins!")
	else:
		print("White wins!")

def main():
	global max_x
	global max_y

	print("All The King's Horses")
	print("Andrew Burgess (acb5016@rit.edu)")
	print("")
	print("Top Left corner of the board is (0, 0)")
	print("")
	pieces = []
	x = int(input("White Knight 1 X position: "))
	y = int(input("White Knight 1 Y position: "))
	pieces.append([0, [x, y]])
	x = int(input("White Knight 2 X position: "))
	y = int(input("White Knight 2 Y position: "))
	pieces.append([0, [x, y]])
	x = int(input("Black Knight 1 X position: "))
	y = int(input("Black Knight 1 Y position: "))
	pieces.append([1, [x, y]])
	x = int(input("Black Knight 2 X position: "))
	y = int(input("Black Knight 2 Y position: "))
	pieces.append([1, [x, y]])

	for p in pieces:
		if p[1][0] > max_x:
			max_x = p[1][0]
		if p[1][1] > max_y:
			max_y = p[1][1]

	max_x = max_x + 5
	max_y = max_y + 5

	game_type = int(input("1 = Deep search\n2 = Limited search\n\nChoice: "))

	if game_type == 1:
		play(pieces)
	elif game_type == 2:
		limit = int(input("Limit: " ))
		play_limited(pieces, limit)
	else:
		return

if __name__ == "__main__":
	main()

December 10, 2010

Breadth First Search for Knuth’s Toy Problem

Donald Knuth conjectured that any positive integer can be reached from the number 4 by applying the operations square root, factorial, and floor. This script is a Breadth First Search that figures out the necessary steps to reach that value

"""
BFS Problem
Author: Andrew Burgess (andrew@deceptacle.com)

1 = Factorial
2 = Floor
3 = Square Root
"""

import math, sys

#Generates successors for supplied value
def successors(val):
	ret = []

	if (val <= 200):
		try:
			ret.append([math.factorial(val), 1])
		except:
			pass

	#Exception when values are not kosher I guess
	try:
		ret.append([math.floor(val), 2])
	except:
		ret.append([int(val), 2])

	if (val  0 and queue[0][0] != goal:
		current = queue.pop(0)

		for x in successors(current[0]):
			if not x[0] in seen:
				queue.append(x)
				seen[x[0]] = current

	#For some reason, 12 doesn't work...
	if (len(queue) == 0):
		print "Failed to find steps..."
		return None

	#Converts the data structures to the series of steps that the algorithm found
	print "Generating steps..."
	done = False
	steps = [queue[0]]
	step = queue[0][0]
	while not done:
		if step != 4:
			steps.append(seen[step])
			step = seen[step][0]
		else:
			done = True

	steps.reverse()
	return steps

s = bfs(int(sys.argv[1]))
if not s == None:
	for x in s:
		if x[1] == None:
			print "Start: " + str(x[0])
		elif x[1] == 1:
			print "Factorial: " + str(x[0])
		elif x[1] == 2:
			print "Floor: " + str(x[0])
		elif x[1] == 3:
			print "Square Root: " + str(x[0])

November 3, 2010

Linear Cryptanalysis of SPN

No idea if this works correctly. My highest bias ended up not being what I calculated, so who knows. I’m beat and it’s late

 

import random, math, operator, pprint

substitutions = [[0, 8], [1, 4], [2, 2], [3, 1], [4, 12], [5, 6], [6, 3], [7, 13], [8, 10], [9, 5], [10, 14], [11, 7], [12, 15], [13, 11], [14, 9], [15, 0]]

keys = ["0010100010101001", "0111010001111011", "0011110110100011", "1100100101101110", "0100110110101101"]

## {{{ http://code.activestate.com/recipes/113799/ (r1)
#
# bitfield manipulation
#
class bf(object):
    def __init__(self,value=0):
        self._d = value

    def __getitem__(self, index):
        return (self._d >> index) & 1

    def __setitem__(self,index,value):
        value    = (value&1L)<<index -="" -1="" :="" def="" mask="(1L)<> start) & mask

    def __setslice__(self, start, end, value):
        mask = 2L**(end - start) -1
        value = (value & mask) << start
        mask = mask <> start) & mask

    def __int__(self):
        return self._d
## end of http://code.activestate.com/recipes/113799/ }}}

def sbox(inp):
	out = ""
	for i in range(0, 4):
		s = ""
		for j in range(0, 4):
			s = s + str(inp[i * 4 + j])
		x = int(s, 2)
		o = bin(substitutions[x][1])[2:]
		while len(o) != 4:
			o = "0" + o
		out = out + o
	ret = [None] * 16

	for i in range(16):
		ret[i] = int(out[i])

	return ret

# Reverses a singular sbox instead of an entire string
def reverse_sbox(inp):
	s = ""
	for i in range(4):
		s = s + str(inp[i])
	x = int(s, 2)

	for i in range(16):
		if substitutions[i][1] == x:
			ret = [None] * 4
			temp = bf(substitutions[i][0])
			ret[0] = temp[3]
			ret[1] = temp[2]
			ret[2] = temp[1]
			ret[3] = temp[0]
			return ret

def permutation(inp):
	out = [None] * 16
	out[0] = inp[0]
	out[1] = inp[4]
	out[2] = inp[8]
	out[3] = inp[12]
	out[4] = inp[1]
	out[5] = inp[5]
	out[6] = inp[9]
	out[7] = inp[13]
	out[8] = inp[2]
	out[9] = inp[6]
	out[10] = inp[10]
	out[11] = inp[14]
	out[12] = inp[3]
	out[13] = inp[7]
	out[14] = inp[11]
	out[15] = inp[15]

	return out

def keymix(cipher, key_i):
	for j in range(16):
		cipher[j] = (int(cipher[j]) + int(keys[key_i][j])) % 2
	return cipher

def encrypt(plaintext):
	print "Encrypting plaintext: " + str(plaintext)
	print

	cipher = [None] * 16

	for i in range(16):
		cipher[i] = int(plaintext[i])

	for i in range(3):
		print "Round " + str(i + 1)
		print "Cipher: " + str(cipher)
		#Key mixing
		cipher = keymix(cipher, i)
		print "Keymix: " + str(cipher)

		#S-Box
		cipher = sbox(cipher)
		print "S-Box: " + str(cipher)

		#Permutation
		cipher = permutation(cipher)
		print "Permutation: " + str(cipher)
		print

	#Last round
	print "Round 4"
	print "Cipher: " + str(cipher)
	cipher = keymix(cipher, 3)
	print "Keymix: " + str(cipher)

	cipher = sbox(cipher)
	print "S-Box: " + str(cipher)

	print
	print "Final Keymix..."
	cipher = keymix(cipher, 4)
	print "Keymix: " + str(cipher)

	return cipher

def plaintext_generator():
	plaintext = [None] * 16
	for x in range(16):
		plaintext[x] = random.randint(0, 1)
	return plaintext


def generator(amount):
	f = open("pairs.txt", "w")
	for x in range(amount):
		plaintext = plaintext_generator()
		cipher = encrypt(plaintext)
		for y in range(16):
			f.write(str(plaintext[y]))
		f.write(" : ")
		for y in range(16):
			f.write(str(cipher[y]))
		f.write("\n")
	f.close()

def cryptanalyze(amount):
	pairs = []
	key_counter = {}
	for x in range(256):
		key_counter[x] = 0

	print "Reading data file..."
	f = open("pairs.txt", "r")
	for line in f:
		p = line.split(" : ")[0]
		c = line.split(" : ")[1].replace("\n", "")
		pairs.append([p, c])
	f.close()

	print "Extracting key bits..."
	for i in range(amount):
		for j in range(256):
			plain = pairs[i][0]
			cipher = pairs[i][1]
			field = bf(j)

			#XOR with "key"
			c1 = [None] * 4		#Key result 1
			c2 = [None] * 4		#Key result 2

			#bf class reverses bit order
			c1[0] = (int(cipher[0]) + field[3]) % 2
			c1[1] = (int(cipher[1]) + field[2]) % 2
			c1[2] = (int(cipher[2]) + field[1]) % 2
			c1[3] = (int(cipher[3]) + field[0]) % 2
			c2[0] = (int(cipher[8]) + field[7]) % 2
			c2[1] = (int(cipher[9]) + field[6]) % 2
			c2[2] = (int(cipher[10]) + field[5]) % 2
			c2[3] = (int(cipher[11]) + field[4]) % 2

			c1 = reverse_sbox(c1)
			c2 = reverse_sbox(c2)

			if (c1[0] + c2[1] + int(plain[15])) % 2 == 0:
				key_counter[j] = key_counter[j] + 1

	print "Calculating biases..."
	for i in range(256):
		key_counter[i] = math.fabs(key_counter[i] - 1024.0) / 2048.0

	pp = pprint.PrettyPrinter()
	sorted_keys = sorted(key_counter.items(), key = operator.itemgetter(1))
	field = bf(sorted_keys[255][0])		#Highest bias

	print "Bias: " + str(sorted_keys[255][1]) + " (key value: " + str(sorted_keys[255][0]) + ")"
	print "Keybits: [" + str(field[7]) + ", " + str(field[6]) + ", " + str(field[5]) + ", " + str(field[4]) + "] ... [" + str(field[3]) + ", " + str(field[2]) + ", " + str(field[1]) + ", " + str(field[0]) + "]"


# Generate 8 * (1/16) ^ -2 plaintext/ciphertexts (2048 plaintext/ciphertext pairs)

print "Commands:"
print "generate"
print "analyze"
print

while True:
	cmd = raw_input("Enter command: ")
	if cmd == "generate":
		generator(2048)
	elif cmd == "analyze":
		cryptanalyze(2048)
	elif cmd == "exit" or cmd == "quit":
		break

 

Follow

Get every new post delivered to your Inbox.