PDA

View Full Version : One-Liner for elections



Wizzup?
11-12-2011, 09:08 PM
Basically, the problem is given a number of candidates + voters, decide who has won an ``election''.

Input looks like this:


4
A B C D

5
A B D C
B A D C
A C B D
D C B A
C D B A


Following the format:



# number of candidates
<cand 1 name> <cand 2 name> <cand 3 name>

# number of voters
// each line following represents one voter
<voter-1 first choice> <voter-1 second choice> <voter-1 nth choice...>
<voter-nth first choice> <voter-nth second choice> <voter-nth nth choice...>


File should be named "in.txt" and should be in the same directory as the program.

This program will tell you who won:
print reduce((lambda w: (lambda x: w(lambda *args: x(x)(*args)))(lambda x: w(lambda *args: x(x)(*args))))(lambda w: lambda z, y: ('No Winner' if (len(z[1]) == 1 or isinstance(z,str)) else w((z[0], z[1][1:]),(y[0], y[1][1:]))) if z[1][0] == y[1][0] else (('No Winner' if isinstance(z, str) else False) or (z[0], f[z[0]]) if z[1][0] > y[1][0] else (y[0], f[y[0]]))), list(globals().__setitem__('f', (lambda l: dict(zip(l[0], map(lambda x: map(lambda y: y[1], x), map(lambda ll: (lambda e: [e.__setitem__(x, e[x]+1) for x in ll] and sorted(e.items()))(dict(zip(range(len(l[0])),[0]*len(l[0])))), map(lambda (char, lst): map((lambda y: lambda x: x.find(y))(char), lst), zip(l[0], [l[1:] for x in xrange(len(l[0]))])))))))(map(lambda x: x.replace(' ', ''), filter(lambda x: x and len(x) > 1, [x.strip() for x in open('in.txt')])))) or f.iteritems()))


Output:


$ python ass5.py
('A', [2, 1, 0, 2])


Why? Because it was fun and I needed some relaxation. And also because my students will have to write the same, in Java, with approximate 500 times the amount of lines. :p

Nava2
11-12-2011, 09:12 PM
You're an asshole.

Big ol' mean TA.

tls
11-12-2011, 09:26 PM
why do they have to use 500+ lines?

BraK
11-12-2011, 09:35 PM
We should write out a whole bunch of problems for Pascal that people need to solve. This would give people some programming logic experience to help them learn scripting. I've had the Idea bumping around for awhile but haven't put it into a thread yet. I really need to stop being lazy with my learning Ideas for others. :)

mastaraymond
11-12-2011, 09:46 PM
We should write out a whole bunch of problems for Pascal that people need to solve. This would give people some programming logic experience to help them learn scripting. I've had the Idea bumping around for awhile but haven't put it into a thread yet. I really need to stop being lazy with my learning Ideas for others. :)

http://villavu.com/forum/showthread.php?t=50949

bevardis
11-12-2011, 09:48 PM
We should write out a whole bunch of problems for Pascal that people need to solve. This would give people some programming logic experience to help them learn scripting. I've had the Idea bumping around for awhile but haven't put it into a thread yet. I really need to stop being lazy with my learning Ideas for others. :)

Project Euler, check it out.

Also, I saw Ben Land was doing that too.

Wizzup?
11-13-2011, 02:22 AM
why do they have to use 500+ lines?

Just the approximate size of the Java program, and then a bit exaggerated because it is Java. Hopefully they'll do it in less.

Invalid Gold
11-13-2011, 02:59 AM
Hm, intresting concept.

noidea
11-13-2011, 04:25 AM
Should have used J.

Wizzup?
11-13-2011, 12:12 PM
Should have used J.

I liked the concept of using reduce() to reduce the list of winners to only one candidate, and I just worked from that. :p

Reading the file is pretty simple. Just iterate over the lines, removing spaces. numbers and empty lines. Then use .find() to determinate the position of each letter. Use that letter as an index in an array (or in my case, dictionary) to ``count'' the amount of each position/rank. This was one hard part to do in one line. This does it:


(lambda e: [e.__setitem__(x, e[x]+1) for x in ll] and sorted(e.items()))(dict(zip(range(len(l[0])),[0]*len(l[0]))))


Then you simply turn that dictionary into a list of tuples. 'A' : 4 -> ('A', 4) and pass this to the ``reduce function''.

My first one worked like this:


# Collapse until the winner is the only item
def reducer(x, y):
if isinstance(x, str):
return x
if x[1][0] == y[1][0]:
if len(x[1]) == 1:
return 'No Winner'
return reducer((x[0], x[1][1:]),(y[0], y[1][1:]))
elif x[1][0] > y[1][0]:
return (x[0], f[x[0]])
else:
return (y[0], f[y[0]])


On one line, using lambda calculus. (Y-Combinator)


(lambda w: (lambda x: w(lambda *args: x(x)(*args)))(lambda x: w(lambda *args: x(x)(*args))))(lambda w: lambda z, y: ('No Winner' if (len(z[1]) == 1 or isinstance(z,str)) else w((z[0], z[1][1:]),(y[0], y[1][1:]))) if z[1][0] == y[1][0] else (('No Winner' if isinstance(z, str) else False) or (z[0], f[z[0]]) if z[1][0] > y[1][0] else (y[0], f[y[0]])))


Then just call reduce on the list of tuples with the above function as ``reducer'.. It'll pick two items from the list, return the winner and compare to the next candidate until only one candidate is left. So you really collapse the list until only the winner is left. :p

mastaraymond
11-13-2011, 12:19 PM
Well, not to be a bitch, but your one-liners are unreadable.

Wizzup?
11-13-2011, 12:57 PM
Well, not to be a bitch, but your one-liners are unreadable.

Well, that was the point. ;)
It's not a hard problem to solve.

You could probably make it more readable, but then I doubt you'd have it on one line.

mastaraymond
11-13-2011, 01:11 PM
Well, that was the point. ;)
It's not a hard problem to solve.

You could probably make it more readable, but then I doubt you'd have it on one line.
Or you could just run an obfuscater over readable code, one-liners for free!

Wizzup?
11-13-2011, 01:59 PM
Or you could just run an obfuscater over readable code, one-liners for free!

Not really. Note that my statement really belongs on one line. It simply is only one ``call'' with subcalls. And all the declarations are with lambda. A for loop for example can't really be a one liner. Stacking them all on one line separated by ; doesn't count. ;)