February 27, 2009 at 1:37PM Discouraging clientelism in Irish politics
Ireland is a country of just over four million people, with a parliament consisting of 226 members in total, with 166 members in the the lower house and 60 in the upper, so for a nation of our size, we’ve a disproportionally high number of public representatives for a country our size.
The constitution places upper and lower limits on the number of representatives in the lower house in article 16.2.2, specifically one representative for every 20,000 to 30,000 of the population. The use of electoral constituencies is implicit in the language of the article, but does not specify the shape of those constituencies, nor whether they can overlap--these are all matters of statute rather than basic law.
As things stand, Irish politics is riddled with clientelism, with our politicians overly focused on getting elected again the next time an election comes around, so they spend far too much time acting as delegates from their constituency rather than as trustees of the best interests of the nation as a whole, which is what they ought to be. We need some way of breaking this cycle, and I think I’ve a way.
My idea is that fully one third of the representation should be elected nationally from a single national constituency. Doing this alone would be technically feasible due to so through an act to amend our electoral law, but the one sticking point is the use of the single transferrable vote (STV)--three-, four- and five-seater constituencies are enough of a pain to do the count on, never mind a massive national constituency that can elect over fifty TDs!
The use of STV is codified into the constitution. This has been a good thing because it’s avoided the situation where Fianna Fail could change the electoral law to use first past the post (FPTP) to get a permanent majority of the seats in the Dail. For a national constituency to be practical, a constitutional amendment would be required to specify the method used for electing from that constituency. In my mind, a party list system appear be the feasible method.
Do I think this would solve our problems? No, but I do think it would be a step in the right direction towards governments that worked in the best interests of the nation rather than themselves.
[I’ve reposted this article on Irish Election, so head over there if you want to discuss it.]
February 23, 2009 at 2:13PM If programmers had to make planes
Painfully true to life:
February 8, 2009 at 9:55PM Quick notes: Changes afoot
There are a few changes that’ll be happening around these parts mighty soon. Let’s start with some site news:
- I’m killing comments on the site. Frankly, I hardly ever get any non-spam comments, so the facility’s really little more than a waste of time and energy. I may reenable them some time in the future when I’ve a better method for handling them, but until then, they’ll be kaput. [Update (Feb 12th): done - it’s no longer possible to post new comments, and all spam has been cleared.]
- I bought a server! I still have to get two harddrives and a set of rails for it, and install an OS, but I have it, and when I’ve the new software ready to power the site, I’ll be moving it onto that.
- I’m rewriting the code that powers this site from scratch. I’ve hit some paralysis caused by my new design, which I’m not at all happy with, so I might just shelve it and go with something a bit less ambitious and concentrate on the site’s code instead, like I should be.
Other bits and pieces:
- I’m abandoning awesome as my window manager. As of v3, it’s started to diverge far too much from what I liked about dwm, so I’ll likely be going back to using that instead. I don’t really feel like forking and maintaining v2. Well-named as it was, it just isn’t for me any more. Pity. For now, I’m back to using OpenBox and ROX-Session, which feels a little weird after using a tiling window manager for so long! [Note to Revence: no, I won’t be using Xmonad - it takes too long to build it, GHC, and all the other stuff it depends on. dwm is just fine.]
Update (Feb 21st): I missed a few bits of the comments code for dealing with spam, which is why some may have seen an error page on the weblog’s frontpage. My bad. It’s fixed now, and I stripped out yet more junk.
January 19, 2009 at 3:52PM QOTD: hubris experience
Every company thinks its special. So special, customers should be grateful for the mere privilege of doing business with the company. Call it egocentric design, hubris experience, entitlement architecture. The truth is, your customers don’t care as much as you wish they would. They just want to get the product or use the service and get on with other, more important things.
Ironically, if you design software by putting the emphasis on others, you end up increasing your value to other people. Funny how that works.
January 19, 2009 at 2:13PM I feel myself wanting to type ‘return new self($args)’ from as static method
I know this is a little silly, but I feel myself wanting to do something like this in a piece of code I’m writing:
abstract class Base {
protected $arg;
public function __construct($arg) {
$this->arg = $arg;
}
public abstract function stuff();
public static function wrap($arg) {
// Here be the magic.
return new Wrapper(new self($arg));
}
}
class Wrapper {
private $wrapped;
public function __construct(Base $wrapped) {
$this->wrapped = $wrapped;
}
public function nonsense() {
return sprintf("[%s]\n", $this->wrapped->stuff());
}
}
class A extends Base {
public function stuff() {
return strtoupper($this->arg);
}
}
class B extends Base {
public function stuff() {
return strtolower($this->arg);
}
}
echo A::wrap('Foo')->nonsense();
echo B::wrap('Bar')->nonsense();
Which would give:
[FOO] [bar]
Of course, PHP doesn’t allow self to be (ab)used like that, and I’m sure there’s a much better way of achieving something similar to this, but I thought I’d record this particular brainfart for posterity anyway.
January 3, 2009 at 10:19AM Minesweeper Kata
I did the minesweeper kata a few days back. It was a bit too easy, though it’s quite possible that this is more an artifact of how I approached it. Given that it’s a simple one, it might be an idea to see if I can take it in smaller steps, much smaller steps.
There’s not really much to say, so here’s the code:
#!/usr/bin/env python
import doctest
import sys
def unpack_line(s):
"""
>>> unpack_line('.....')
[0, 0, 0, 0, 0]
>>> unpack_line('')
[]
>>> unpack_line('.*.')
[0, '*', 0]
"""
line = []
for c in s:
if c == '*':
line.append('*')
else:
line.append(0)
return line
def mark_adjacents(lines):
"""
>>> mark_adjacents([[0, 0], [0, 0]])
[[0, 0], [0, 0]]
>>> mark_adjacents([['*', 0], [0, 0]])
[['*', 1], [1, 1]]
>>> mark_adjacents([['*', 0], [0, '*']])
[['*', 2], [2, '*']]
>>> mark_adjacents([[0, 0, 0], [0, '*', 0], [0, 0, 0]])
[[1, 1, 1], [1, '*', 1], [1, 1, 1]]
>>> mark_adjacents([['*', 0, 0], [0, 0, 0], [0, 0, '*']])
[['*', 1, 0], [1, 2, 1], [0, 1, '*']]
"""
for y in range(len(lines)):
for x in range(len(lines[y])):
if lines[y][x] == '*':
for oy in [y - 1, y, y + 1]:
if oy < 0 or oy == len(lines):
continue
for ox in [x - 1, x, x + 1]:
if ox < 0 or ox == len(lines[y]):
continue
if lines[oy][ox] != '*':
lines[oy][ox] += 1
return lines
def process_fields(iterable):
start = True
for line in iterable:
line = line.rstrip()
if start:
start = False
lines = []
height, width = [int(x) for x in line.split(' ')]
if width == 0 and height == 0:
break
else:
lines.append(unpack_line(line))
height -= 1
if height == 0:
start = True
yield mark_adjacents(lines)
def main():
field = 0
for f in process_fields(sys.stdin):
field += 1
if field > 1:
print
print "Field #%d:" % field
for l in f:
print ''.join([str(x) for x in l])
def _test():
doctest.testmod()
if __name__ == '__main__':
main()
I should really buckle down and finish the code that’s meant to replace the crappy one-evening hack the this blog runs on.
December 31, 2008 at 12:44AM Harry Potter Kata
I did the Harry Potter Kata earlier because I was feeling a little bored. Here’s the result. I use cents rather than euros as my unit of currency here.
I’d a start when I was thinking about how I’d solve the problem. I thought that being greedy and trying to make the biggest sets would do the trick, but the first example test case given soon managed to disabuse me of that notion.
Then I got the idea of turning things around 90 degrees by creating a set of buckets within the basket and distributing the sets between them. However, given the sample test case, I realised that the maximum discount could come from an obscure distribution of books, so I took the brute force route and decided to enumerate all the possible ways to distribute all the books of a certain volume, tracking which combination gave the greatest discount, and did this iteratively for each volume.
I already had the intuition to eliminate the larger groups of volumes sooner than the smaller ones, and I knew that the important thing was the number of books of each volume there were rather than what the particular volumes were, so sorting basket by volume made sense and avoided the need to do any backtracking later.
I looked at other implementations after I’d finished, and mine seems to be sorter and more general--though not purposely so--than most, but I’m still pretty sure there’s a much more elegant way to find an ideal distribution of volumes than the brute force method I used, though I’ve yet to think of one. Here’s the code:
#!/usr/bin/env python
import doctest
import itertools
def sum_basket(basket, unit_price, discount_pcs):
"""
Gets the sum price of the books in the basket.
basket - list of number of each book
unit_price - price of a book
discount_pcs - percentage discount to apply for each additional book in a set
>>> price = 800
>>> discount_pcs = [0, 0, 5, 10, 20, 25]
>>> sum_basket([0, 0, 0, 0, 0], price, discount_pcs)
0
>>> sum_basket([0, 1, 0, 0, 0], price, discount_pcs)
800
>>> sum_basket([0, 3, 0, 0, 0], price, discount_pcs)
2400
>>> sum_basket([1, 1, 0, 0, 0], price, discount_pcs)
1520
>>> sum_basket([2, 1, 2, 1, 0], price, discount_pcs)
4080
>>> sum_basket([2, 1, 1, 1, 1], price, discount_pcs)
3800
>>> sum_basket([2, 2, 2, 1, 1], price, discount_pcs)
5120
>>> sum_basket([1, 1, 2, 2, 2], price, discount_pcs)
5120
>>> sum_basket([5, 5, 4, 5, 4], price, discount_pcs)
14120
"""
buckets = get_basket_buckets(basket)
result = 0
for books in sorted(basket, reverse=True):
best = None
for patterns in bitmap_combinations(books, len(buckets)):
attempt = [x + y for x, y in itertools.izip(buckets, patterns)]
attempt_sum = 0
for bucket in attempt:
attempt_sum += sum_bucket(bucket, unit_price, discount_pcs)
if best is None or attempt_sum < result:
best = attempt
result = attempt_sum
buckets = best
return result
def sum_bucket(bucket, unit_price, discount_pcs):
"""
Gets the sum cost of a set of books.
bucket - number of unique books in a set.
unit_price - price of a book
discount_pcs - percentage discount to apply for each additional book in a set
>>> price = 800
>>> discount_pcs = [0, 0, 5, 10, 20, 25]
>>> sum_bucket(0, price, discount_pcs)
0
>>> sum_bucket(1, price, discount_pcs)
800
>>> sum_bucket(2, price, discount_pcs)
1520
>>> sum_bucket(3, price, discount_pcs)
2160
>>> sum_bucket(4, price, discount_pcs)
2560
>>> sum_bucket(5, price, discount_pcs)
3000
"""
return bucket * unit_price * (100 - discount_pcs[bucket]) / 100
def bitmap_combinations(ones, length):
if length == 0:
yield []
else:
if ones < length:
for tail in bitmap_combinations(ones, length - 1):
yield itertools.chain([0], tail)
if ones > 0:
for tail in bitmap_combinations(ones - 1, length - 1):
yield itertools.chain([1], tail)
def get_basket_buckets(basket):
"""
Creates enough basket buckets to hold the maximum number of unique book sets in
the basket.
>>> get_basket_buckets([0])
[]
>>> get_basket_buckets([0, 0])
[]
>>> get_basket_buckets([1, 0])
[0]
>>> get_basket_buckets([0, 1])
[0]
>>> get_basket_buckets([0, 2])
[0, 0]
>>> get_basket_buckets([1, 2])
[0, 0]
>>> get_basket_buckets([1, 2, 3, 5, 2])
[0, 0, 0, 0, 0]
"""
return [0 for i in range(max(basket))]
def _test():
doctest.testmod()
if __name__ == '__main__':
_test()