Meta Golf Challenge

On that challenge you have to solve that challenge.

Contest is over! Check the end of the question

Specs:

1. Write the smallest code (Any language*).
2. The score of an answer is the sum of:
• Code length without whitespace.
• Number of answers using that same language squared.
• Length of the name of the biggest language on the contest minus the length of your language.
3. Write the position of the users and the score.
4. Each user can write only one answer.
5. The lowest score wins.

Testing:

So, at the end of the contest, a possible input could be (STDIN):

UserA Python 100 1
UserB Perl 30 2
UserC Java 500 3
UserD Brainfuck 499 4
UserE Perl 29 5

If your user name has spaces like "My User Name" it'll become "MyUserName" so the input will always have exactly 4 columns.

The output will be (STDOUT):

1 UserE 33
2 UserB 37
3 UserA 103
4 UserD 496
5 UserC 503

Explanation:

User  P  N^2  L   V
A   100  1   3  -1
B    30  4   5  -2
C   500  1   5  -3
D   499  1   0  -4
E    29  4   5  -5

Brainfuck is the largest name with 9 chars (9 - 9 = 0).

Perl and Java have 4 chars (9 - 4 = 5).

Python has 6 chars (9 - 6 = 3).

Perl has 2 entries so each get 4 extra points.

The name of the language must contain only English letters (i.e. [A-Za-z]) and those which don't fit that must be "translated" to something else.

By the end of the contest, every language must have it's representation (You may propose better representations)

Examples:

Python3      -> Python
Ruby1.9      -> Ruby
Shell Script -> Shell
C++          -> Cpp
C#           -> CSharp
><>          -> Fish

Deadline: August 20, 2011 00:00 UTC

At the end of the contest, the winner must use his/her program to find the winner. It's allowed to non winners to use their programs to find the winner and tell him/her to use his/her program to find the winner. :)

The winner (see above) gets the answer accepted!

*The Whitespace language has the unfair advantage of being able to introduce unlimited complexity without a penalty on the character count. Answers written in Whitespace may be on the contest but can't win.

If you can make the logic of your program in whitespaces, you also can't win. That's a subjective topic, but if your program can increase considerably in size without being penalized, it falls in that condition.

Final Input

Alphabetical order of names (as of Aug 20th 2011 UTC 00:00)

boothby Sage 41 9
Harpyon Python 203 4
JBernardo Python 184 7
jpjacobs AWK 269 4
Lowjacker Ruby 146 2
PeterTaylor Golfscript 82 4
rmackenzie CommonLisp 542 2
shesek Javascript 243 3
userunknown Scala 252 1

As both mine and boothby's answers are not allowed to win, the winner should proclaim himself the winner by editing this question and posting the final output below.

Final Output

1 boothby 39
2 PeterTaylor 79
3 Lowjacker 151
4 JBernardo 185
5 Harpyon 207
7 shesek 241
8 userunknown 257
9 jpjacobs 273
10 rmackenzie 541
• Does that mean a solution in Whitespace will automatically win? Jul 18 '11 at 6:35
• Where does the information about other answers come from? Are our programs supposed to connect to StackExchange and mine the answers to this question? Jul 18 '11 at 16:46
• @Justin At the end of the contest, I'll make the real program input with the answers. I gave the format Jul 18 '11 at 21:55
• @Harpyon <>< ti dexif I !sknahT Jul 18 '11 at 21:58
• Must we sort the output by scores? If so, what should we do in case of tie? Jul 19 '11 at 0:13

Sage: 48 42 41 non-whitespace (60246 bytes total)

Just to be a prick:

s = '   '
for c in '<lots of whitespace>'.split(s):
s+=chr(len(c))
exec s

Note that the first line should be equivalent to s='\t', but the SE code block translates the tab to 4 spaces.

The whitespace unpacks to:

exec preparse("""
import sys
instances = {}
maxlen = 0
inputs = [line.split() for line in sys.stdin.readlines()]
for i in [0..len(inputs)-1]:
user, language, length, votes = inputs[i]
if language in instances:
instances[language]+=1
else:
instances[language]=1
if len(language) > maxlen:
maxlen = len(language)

scoresheet = []
for i in [0..len(inputs)-1]:
user, language, length, votes = inputs[i]
length = int(length)
score = length + (maxlen - len(language)) + instances[language]*instances[language] - votes
scoresheet.append((score,user))

scoresheet.sort(reverse=False)
for user, score in scoresheet:
print user, score""")

Note that my use of [0..len(inputs)-1] ensures that this isn't a Python script, since Sage is a superpython*. Unfortunately, exec falls back on Python... so I've gotta preparse it.

edit 1: splitting on tabs, not newlines -- what was I thinking? edit 2: made the code easier on the eyes, and recycled the splitting tab by pushing another 'newline' to the whitespace

*ok, not quite: we break xor

Golfscript, 83 chars (82 not counting whitespace)

n/{},{' ':s/}%.{1=}%\{~~\~\-\.{=}+4$\,,.*\,-+2${,}%$)\;+[\]}%$\;.,,]zip{~)s@~s@n}%

Explanation:

# Split the string containing all the input on newlines
n/
# Remove empty lines
{},
# Split each line on spaces (storing the space character in variable s)
{' ':s/}%
# We now have an array of arrays of words. Duplicate it, filter the copy to contain
# only the second word of each array, and reorder with the array of second words first
.{1=}%\
# Map each line
{
# Unpack the array ["user" "lang" "length" "votes"] and evaluate the integers
~~\~\
# Subtract votes from length and bring "lang" to the top
-\
# Create a function to match the string "lang"
.{=}+
# Stack is currently [array of langs] "user" (length-votes) "lang" {"lang"=}
# Duplicate the array of langs and apply the match function as a filter
4$\, # Get the length of the array of matches and square it ,.* # Stack is [array of langs] "user" (length-votes) "lang" (num with lang)^2 # Bring the "lang" to the top, get its length, subtract and add \,-+ # Stack is [array of langs] "user" (score-length of longest lang) # Get an array of length of language names and sort it 2${,}%$# Drop it apart from the largest value, and add that to the score )\;+ # Package the "user" score from the top of the stack as [score "user"] [\] }% # Sort. Since each element is a [score "user"] value, this will sort by score.$
# Discard the [array of langs].
\;
# Stack is an array of [score "user"] arrays. Get its length and create an array of the
# same length which counts from 0.
.,,
# Group and zip, so we go from [[score0 "user0"] ... [scoren "usern"]] [0 ... n] to
# [[[score0 "user0"] 0] ... [[scoren "usern"] n]]
]zip
# Map each [[scorei "useri"] i]
{
# Expand, increment i (so we count from 1 rather than 0), add a space
~)s
# Bring the [scorei "useri"] to the top, unpack, add a space
@~s
# Bring the scorei to the top, add a newline
@n
}%
# We now have an array [[1 " " "userA" " " scoreA "\n"] ... [n " " "userZ" " " scoreZ "\n"]
# so Golfscript's standard output formatting does the rest
• That's pretty neat, I should take a look at GolfScript... I have no idea how that's parsed into something meaningful Aug 18 '11 at 6:52
• @shesek, added a heavily commented version Aug 18 '11 at 7:26
• wow, very cool! thanks :-) Aug 18 '11 at 9:50

Python, 184

That's why I love spaces.

import          sys
).split()
z = x [  1 : : 4  ]
for i , ( j , k
) in enumerate (
sorted (
zip (
[
int(i)
- int(j) +
z.count(k) ** 2
+ max(map(len, z)) -
len(k)
for i, j, k in
zip (
x[2 : : 4],
x[3 : : 4],
z
)
],
x[ : : 4]
)
),
1
):
print i, k, j

• is this supposed to be some kind of ascii art picturing something? if yes, what should it look like? Aug 17 '11 at 8:04
• @oenone you tell me. Aug 17 '11 at 10:30
• it looks like it should, but i can't recognize anything Aug 17 '11 at 10:37
• @oneone neither do I... Aug 19 '11 at 2:04

PostgreSQL - 225 non-space characters

242 → 225: Replaced subqueries with windowing clauses.

\set QUIET 1
\t
\a
\f ' '
CREATE TEMPORARY TABLE t (u TEXT, l TEXT, c INT, v INT);
\copy t FROM PSTDIN WITH DELIMITER ' ';
SELECT row_number() OVER (ORDER BY score), *
FROM (SELECT u,
c
+ count(*) OVER (PARTITION BY l)^2
+ max(length(l)) OVER ()
- length(l)
- v AS score
FROM t) AS q

tested on 9.2devel

$psql -f meta.sql < meta.in 1 UserE 33 2 UserB 37 3 UserA 103 4 UserD 496 5 UserC 503 Python 2 - 210 203 non-space characters import sys e=enumerate n=len l=[x.split()for x in sys.stdin.readlines()] for i,(x,y)in e(sorted((int(x)-int(x)+n(list(y for y in l if y==x))**2+max(n(x)for x in l)-n(x),i)for i, x in e(l))):print i+1,l[y],x Usage and output:$ cat meta.txt | python meta.py
1 UserE 33
2 UserB 37
3 UserA 103
4 UserD 496
5 UserC 503
• you could use only x.split() (that will also remove \n) Jul 18 '11 at 22:53
• @JBernardo Cheers! Saved 7 characters.
– user1158
Jul 18 '11 at 22:58
• You could ditch the .readlines() on sys.stdin.... for any reasonable length of input the function call won't make a difference and costs some characters. Just figured that out in another golf and thought I'd share. Aug 18 '11 at 20:03

AWK, 277 269 non-space characters

Used in to cut 8 chars.

Spaced version and commented version:

{
u[NR]=$0 # count number of times language has been used l[$2]+=1
}

END{
# get maximum language length
M=0
X=NR
for (g in l){
f=length(g)
if(f>M)
M=f
}
# get score for user i
for(i in u){
split(u[i],c)
s[i]=c+l[c]^2+M-length(c)-c
}
# sort scores and users
for(i=2;i<=X;++i){
for(j=i;s[j-1]>s[j];--j){
t=s[j]
x=u[j]
s[j]=s[j-1]
u[j]=u[j-1]
s[j-1]=t
u[j-1]=x
}
}
# output
for(i=1;i<=X;++i){
split(u[i],c)
print i,c,s[i]
}
}

usage:

awk -f meta.awk data.txt
• used sed '/#/ d' meta.awk|sed ':a;$!N;s/\n//;ta;s/\s//g;'|wc -c for counting characters. Jul 20 '11 at 8:56 Common Lisp - 546 (when golfed boy consolidating parenthesis, not counting spaces) ;;;; This is an answer to Code-Golf question ;;;; 3203/meta-golf-challenge ;;;; By using Common Lisp I plan to have the longest ;;;; Language-name while I cannot hope to have the ;;;; lowest character count due to Lisp's ;;;; linguistic tradition I can avoid the 16 or 25-pt ;;;; penalty atached to being the 4th or 5th PY ;;;; based answer. (defun f (i) (loop for e in y do (if (eq i (nth 0 e)) (return (nth 1 e)) ) ) ) (setf x (loop for l = (read-line () () () ()) while l collect (loop for i = 0 then (1+ j) as j = (position #\Space l :start i) collect (subseq l i j) while j) ) ) (setf y (loop for a in x collect (list (+ (read-from-string (nth 2 a)) (expt (reduce #'+ (loop for b in x collect (if (string= (nth 1 a) (nth 1 b)) 1 0) ) ) 2 ) (+ 5 (- (reduce #'min (loop for b in x collect (length (nth 1 b)))) (length (nth 1 a)))) (* -1 (read-from-string (nth 3 a))) ) (car a) ) ) ) (setf g (sort (loop for c in y collect (nth 0 c)) #'<) ) (loop for i = 0 then (1+ i) while (< i (length g)) do (setf a (nth i g)) (format t "~A ~A ~A~%" (1+ i) (f a) a) ) Heavily golfed, my common lisp solution was and is the longest on the board. So I decided to cheat a bit by writing a significantly shorter bootloader and claiming that as my submission. (I consider @Boothby's submission to be a precedent in favor of this behavior) Major thanks to Peter Taylor for his help squeezing every last char out of this bootstrapper. BASH - 35 wget -q goo.gl/R4R54 cat -|clisp l.lsp Usage: cat ./test0 | bash ./btstrp.sh Joey Adams pointed out that this is not a fair solution because I can "arbitrarily increase the complexity of your solution without a corresponding increase in code size", a point not clearly expressed in the spec. • Wouldn't a for-loop be shorter than the until? Aug 18 '11 at 14:26 • not sure... but found a shorter while! Aug 18 '11 at 14:34 • Also, if you specify the variable to read into you don't have to use$REPLY. Try while read x;do a=$x"\n"$a;done. And you should be able to remove the spaces after the |s on the last line. On another note, I'm not sure that using an internal IP address is very useful: it won't work for anyone else. Aug 18 '11 at 14:43
• Or even wget -q http://url/l.lsp ;cat - |clisp l.lsp Aug 18 '11 at 14:45
• Okay, you lost me on the cat - Aug 18 '11 at 14:48

Ruby, 146 characters + 4 spaces

b=\$<.map &:split
puts b.map{|u,l,c,v|[b.map{|_,n|n.size}.max-l.size+b.count{|_,n|n==l}**2+eval(c+?-+v),u]}.sort.map.with_index{|(s,u),i|[i+1,u,s]*' '}

JavaScript, 243 chars

for(g=0,H="length",i=J.split("\n"),p=[],l={};i[H]&&p.push(a=i.pop().split(" "));)
X=a,X[H]>g&&(g=X[H]),l[X]=l[X]+1||1
for(i=-1;m=p[++i];)p[i]=[m,+m+Math.pow(l[m],2)+(g-m[H])-m]
p.sort(function(a,b){return a<b?-1:1}).join("\n")

Longer than most of the other solutions... but the best I could come up with in JavaScript.

Usage

Input should be in a J variable. For example, open a console and write:

J="UserA Python 100 1\nUserB Perl 30 2\nUserC Java 500 3\nUserD Brainfuck 499 4\nUserE Perl 29 5";
for(g=0,H="length",i=J.split("\n"),p=[],l={};i[H]&&p.push(a=i.pop().split(" "));)
X=a,X[H]>g&&(g=X[H]),l[X]=l[X]+1||1
for(i=-1;m=p[++i];)p[i]=[m,+m+Math.pow(l[m],2)+(g-m[H])-m]
p.sort(function(a,b){return a<b?-1:1}).join("\n")

CoffeScript, 177 chars

About the same logic, in CoffeScript:

g=0;H="length";l={};([A,+C+Math.pow(l[B],2)+(g-B[H])-D] for [A,B,C,D] in for a in J.split "\n" then [_,X]=a=a.split " ";X[H]>g&&g=X[H];l[X]=l[X]+1||1;a).sort((a,b)->a<b?-1:1).join "\n"
• I like how you abbreviate the length attribute by using a variable and subscripts. Aug 18 '11 at 5:26

Scala 269 266 252 without blanks and newlines.

val b = io.Source.stdin.getLines.toList.map (_.split (" "))
b.map (a => {
val l = b.filter (_(1) .equals ( a(1))).size
a(0) -> (a (2).toInt + l * l + (b.map (x => x(1).length).max - a(1).length) - a(3).toInt)
}).sortBy (_._2).zipWithIndex .map (m => m._2 + " " + m._1._1 + " "+ m._1._2).mkString ("\n")

Invocation:

cat user.lst | scala -i metagolf.scala

• simplified (l => l.foo) -> (_.foo)
• invocation
• Gareths hint of stdin

my solution:

* 0 boothby 39
1 PeterTaylor 79
2 Lowjacker 151
* 3 JBernardo 185
4 Harpyon 207