Its time for another programming challenge. The idea is to solve the given question with the fewest number of characters, in any language. Whitespace will be removed for counting, so dont bother to make your code look clean in the thread.
The problem:
Given an ascii text file with a list of names( first, last ), generate a table where anyone with the same last name is assumed to be related and the first names put underneath the last name, indented by one tab. Order doesnt matter
If the text file is this:
jane fonda chuck norris ted fonda kyle boop
The result should look like
fonda jane ted boop kyle norris chuck
Ordering of last names is arbitrary. Ill post an answer later on.
Remember, any language and fewest number of characters. Or feel free to come up with a better problem.
Whitespace will be removed for counting, so dont bother to make your code look clean in the thread.
Here's my whitespace version of the code:
Since whitespace are not counted, I think I won.
Since whitespace are not counted, I think I won.
Not if your whitespace program doesn't do what it needs to, which I don't think it does!
I tried it out in my secret compiler, and it worked. 
But really, there should be a limitation on language used, or else there's no fair way to compare entries.
I agree. You could use VB.NET and it would kill most C/C++ programs due to the fact VB.NET does most of the work for you. It's not really fair. When you say table, what do you mean? You want this in a database, or just back into another file?
I dunno, i guess I'll try:
| 1 | #include <map> |
| 2 | #include <string> |
| 3 | #include <vector> |
| 4 | using namespace std; |
| 5 | map<string,vector<string>> a; |
| 6 | void main() |
| 7 | { |
| 8 | FILE *f = fopen("file.txt","rb"); |
| 9 | while(!feof(f)) |
| 10 | { |
| 11 | char t[9],h[9]; |
| 12 | fscanf(f, "%s %s\n",t,h); |
| 13 | a[h].push_back(t); |
| 14 | } |
| 15 | |
| 16 | for(map<string,vector<string>>::iterator q = a.begin(); q != a.end(); ++q) |
| 17 | { |
| 18 | printf("%s\n", q->second.c_str()); |
| 19 | for(vector<string>::iterator o = q->second.begin(); o != q->second.end(); ++o) |
| 20 | printf("\t%s\n", o->c_str()); |
| 21 | } |
| 22 | } |
I can do it in Ruby, Perl or VB. In C or C++ would take too much. Off home right now, will post those solutions in around 3 hours (remember, I voted the over 4 hours of travelling to work in a poll here time ago
).
Obfuscated Haskell for everyone!
| 1 | s b (q:r) = s (z q b) r |
| 2 | s a [] = a |
| 3 | z (f:l:_) ((a,c):b) |
| 4 | | a == l = ((a,f:c):b) |
| 5 | | True = (a,c):(z (f:[l]) b) |
| 6 | z (f:l:_) [] = [(l,[f])] |
| 7 | |
| 8 | o ((l,f):r) = (l++(y f)++"\n")++(o r) |
| 9 | o [] = [] |
| 10 | y (a:[]) = ' ':a |
| 11 | y (a:b) = m (a:b) |
| 12 | m (a:b) = ("\n\t"++a)++(m b) |
| 13 | m [] = [] |
| 14 | |
| 15 | g = o . (s []) . (map words) . lines |
| 16 | |
| 17 | main = do |
| 18 | x <- readFile "foo.txt" |
| 19 | putStr (g x) |
EDIT: Made it somewhat shorter.
EDIT2: Made it even shorter...
<? foreach (file("n") as $l) { $p = split(" |\n", $l); $n[$p[1]][] = $p[0]; } foreach ($n as $a=>$z) foreach ($z as $i=>$p) echo ($z[1] ? $i?"\t":"$a\n\t" : "$a ") ."$p\n"; ?>
Note: disable debug "notices" when running.
baf langauge
(*%)#*)R(#*()#F*I()R#)T#*%()#*)%&(#*&(*)R#^T#@^#T)"|::|:}|:}{|#58927389u*(&*(#%&(*35
and in elite c++: (care of l33t-sp34k g3n3r4t0r)
| 1 | #INCluDe <m4P> |
| 2 | #1nClUD3 <S+RiN9> |
| 3 | #iNCLuDE <veCtOr> |
| 4 | uS1N9 NAm35P@C3 5tD; |
| 5 | m4P<StR1NG,V3C+0r<S+R1N9>> 4; |
| 6 | v0ID m@1N() |
| 7 | { |
| 8 | F1lE *f = PhOpEN("PHiLe.TXT","RB"); |
| 9 | wH1lE(!Ph3oPh(ph)) |
| 10 | { |
| 11 | Ch4r t[9],h[9]; |
| 12 | Ph$C@nF(ph, "%5 %S\N",T,h); |
| 13 | 4[H].pU5H_BaCK(+); |
| 14 | } |
| 15 | |
| 16 | PH0R(m4p<STrING,vEc+0r<$+riN9>>::1+3R4T0R Q = A.B3gIn(); Q != A.3nd(); ++Q) |
| 17 | { |
| 18 | Pr1N+f("%S\n", q->5eC0nd.c_$+R()); |
| 19 | fOR(veC+0r<$Tr1N9>::1T3R4tor 0 = Q->53C0nd.b391n(); o != Q->5Ec0ND.3nD(); ++o) |
| 20 | pRInTf("\+%5\n", O->C_5TR()); |
| 21 | } |
| 22 | } |
remember, you have to use the elite g++ port...
#/bin/bash cat file.txt|decapitalise|sort|dostuff|playwith > /dev/tty1
Well, I thought about doing it in C++, but William Heatley already did so, I took his code and chopped it down a little.
Wacko C++
| 1 | #include <map> |
| 2 | #include <string> |
| 3 | #include <vector> |
| 4 | using namespace std; |
| 5 | #define f(t,x,y) for(t::iterator x = y.begin();x != y.end();x++) { |
| 6 | #define l typedef; |
| 7 | l vector<string> v; |
| 8 | l map<string,v> z; |
| 9 | z a; |
| 10 | int main() |
| 11 | { |
| 12 | FILE *f = fopen("f","r"); |
| 13 | while(!feof(f)) |
| 14 | { |
| 15 | char t[9],h[9]; |
| 16 | fscanf(f, "%s %s\n",t,h); |
| 17 | a[h].push_back(t); |
| 18 | } |
| 19 | |
| 20 | f(z,q,a) |
| 21 | printf("%s\n", q->first.c_str()); |
| 22 | f(v,o,q->second) |
| 23 | printf("\t%s\n", o->c_str()); |
| 24 | } |
| 25 | } |
| 26 | } |
Except while Whitespace can deal with input, it cannot read from files, which is a requirement.
Willam: your code doesn't compile
I made it compile but the output generated is not the one the problem defines (same would apply to derivative work
).
Here's mine. Base on William's, but it compiles and generates correct output:
| 1 | #include <map> |
| 2 | #include <string> |
| 3 | #include <vector> |
| 4 | #include <fstream> |
| 5 | #include <iostream> |
| 6 | |
| 7 | using namespace std; |
| 8 | |
| 9 | #define F(a, b, c) for(a::iterator b = c.begin(); b != c.end(); ++b) |
| 10 | #define M map<S,V > |
| 11 | #define V vector<S> |
| 12 | #define S string |
| 13 | #define C cout << |
| 14 | #define D ->second |
| 15 | |
| 16 | M m; |
| 17 | main() |
| 18 | { |
| 19 | ifstream f("file.txt"); |
| 20 | while(!f.eof()) |
| 21 | { |
| 22 | S a,b; |
| 23 | f >> a >> b; |
| 24 | m<b>.push_back(a); |
| 25 | } |
| 26 | |
| 27 | F(M, q, m) |
| 28 | { |
| 29 | C q->first; |
| 30 | if (q D.size() > 1) |
| 31 | { |
| 32 | C endl; |
| 33 | F(V, o, q D) |
| 34 | C "\t" + *o << endl; |
| 35 | } |
| 36 | else |
| 37 | C " " + q D[0] << endl; |
| 38 | } |
| 39 | } |
[edit]
#define I ::iterator wasn't good anymore.
Python's list comprehensions rock!
import string n = dict([string.split(i) for i in open('names.txt').readlines()]) for x,y in dict([(v,string.join( ['']+[k for k in n.keys() if v==n[k] ],"\n "))for v in n.values() ]).iteritems(): print x,y
And so clear and readable.. heh
--Joel
Bah, C++ is so primitive compared to PHP. 
I would think a Perl nerd could get the shortest working code.
Joel: I get invalid syntax on yours...
Except while Whitespace can deal with input, it cannot read from files, which is a requirement.
Why? There's no requirement that you have to load that file, so a
type foo.txt > parse
does the trick of reading the names from that file.
Solution to this problem in Tytwggfdtyuqfef++++-- programming language:
Nobody said that inventing new high level language is forbidden - specification isn't complete yet, but it already can solve this problem. 
(and no, language name is not a polish word)
Hmm.. i'm using python 2.3.4, I think list comprehensions are pretty recent, anything above python 2.1 should work tho...
And perl could probably do way less characters, it's just sooo distasteful.
edit: oops, i'm using iteritem() so you need python 2.1 for that
edit2: attached the py file as an attachment so you don't have to worry about formatting cut/paste errors.
You lie.
"Tytwggfdtyuqfef" == "barman, pour me another!"
The idea is to solve the given question with the fewest number of characters
#define F(a, b, c) for(a::iterator b = c.begin(); b != c.end(); ++b)
#define M map<S,V >
#define V vector<S>
#define S string
#define C cout <<
#define D ->second
I'm assuming he didn't think about this as being whitespace. If that was the case you could do everything with 1 call. 
[EDIT]
Anyone ever highlight the smiley face? It turns into an angry chinese person.
Yeah, yeah, yeah. Enough of the funnies.
Ok,
File "test.py", line 2
n = dict([string.split(i) for i in open('names.txt').readlines()])
^
SyntaxError: invalid syntax
Disclaimer: I'm not familiar with Python.
I'm assuming he didn't think about this as being whitespace. If that was the case you could do everything with 1 call.
No, that part also counts. But it's smaller doing that.
I would take out #define S string since you only use string once in your code, you are wasting 8 characters. That's why I thought you didn't think it counted. Trying to help.
I'd love to see someone solve this in J (link) or APL, the most concise programming language in existance. (J is like APL without the need for a special font)
Rick: look better. I use string three times.
Sorry, missed it in those #defines.
oh yeah? I just invented baf++. The compiler is still under development, but it has built in support for everything 
Its syntax is similar to c, but is as highlevel as anything can get. I have alraedy ported allegro 5 to it.
#include <allegro5.h> read_mind(do_first_last_name_sorting_stuff()); END_OF_PROGRAM(())
Bah. I stole an advanced copy of Allegro 5 from Bob when he moved from Canada. It works in plain C. BTW, you're not taking advantage of hardware acceleration that way. 
#include <allegro/allegro5.h>*thinks*
Had to find the right .NET class that simulated a stl map
| 1 | Imports System.IO |
| 2 | Imports System.Collections.Specialized |
| 3 | |
| 4 | Module Module1 |
| 5 | Sub Main() |
| 6 | Dim f As StreamReader = File.OpenText("File.txt") |
| 7 | Dim a As New NameValueCollection |
| 8 | Dim i, j As Integer |
| 9 | Do Until f.Peek = -1 |
| 10 | Dim str() As String = f.ReadLine().Split(" ") |
| 11 | a.Add(str(1), str(0)) |
| 12 | Loop |
| 13 | Dim s() As String |
| 14 | s = a.AllKeys |
| 15 | For i = 0 To s.Length - 1 |
| 16 | Dim str() As String = a.GetValues(s(i)) |
| 17 | If str.Length > 1 Then |
| 18 | Console.WriteLine(s(i)) |
| 19 | For j = 0 To str.Length - 1 |
| 20 | Console.WriteLine(Chr(9) & str(j)) |
| 21 | Next |
| 22 | Else |
| 23 | Console.WriteLine(s(i) & " " & str(0)) |
| 24 | End If |
| 25 | Next |
| 26 | f.Close() |
| 27 | End Sub |
| 28 | End Module |
BAH, My code is perfect!
Kay, I fixed the typos:
| 1 | #include <map> |
| 2 | #include <string> |
| 3 | #include <vector> |
| 4 | using namespace std; |
| 5 | map<string,vector<string> > a; |
| 6 | int main() |
| 7 | { |
| 8 | FILE *f = fopen("file.txt","rb"); |
| 9 | while(!feof(f)) |
| 10 | { |
| 11 | char t[9],h[9]; |
| 12 | fscanf(f, "%s %s\n",t,h); |
| 13 | a[h].push_back(t); |
| 14 | } |
| 15 | |
| 16 | for(map<string,vector<string> >::iterator q = a.begin(); q != a.end(); ++q) |
| 17 | { |
| 18 | printf("%s\n", q->first.c_str()); |
| 19 | for(int i = 0; i < q->second.size(); ++i) |
| 20 | printf("\t%s\n", q->second<i>.c_str()); |
| 21 | } |
| 22 | } |
I made it compile but the output generated is not the one the problem defines
Just because the program doesn't output like the example, doesn't mean it isn't correct. The example given by the OP is incorrect:
generate a table where anyone with the same last name is assumed to be related and the first names put underneath the last name, indented by one tab.
EDIT: Code updated as of...6:59 PM PST
Hmm... I didn't like this Perl code too much. I notice I am the only one that respect the output format (if only one name with a surname, print them in the same line, otherwise print the surname first, and then all the names below)
I use a hash to prevent repeating surnames too.
| 1 | my %h; |
| 2 | my @f; |
| 3 | |
| 4 | open(F, "<test.txt") or die $!; |
| 5 | @f = <F>; |
| 6 | close(F); |
| 7 | |
| 8 | while ($_ = shift(@f)) { |
| 9 | my @s = split; |
| 10 | my $f = " "; |
| 11 | my @i = @f; |
| 12 | shift @i; |
| 13 | next if (exists(%h->{$s[1]})); |
| 14 | |
| 15 | print $s[1]; |
| 16 | for (@i) { |
| 17 | my @c = split; |
| 18 | if ($s[1] eq $c[1]) { |
| 19 | print "\n $c[0]"; |
| 20 | $f = "\n "; |
| 21 | } |
| 22 | } |
| 23 | print "$f$s[0]\n"; |
| 24 | %h->{$s[1]} = 1; |
| 25 | } |
I notice I am the only one that respect the output format (if only one name with a surname, print them in the same line, otherwise print the surname first, and then all the names below)
Mine is right!
Awww... that is why I still don't understand PHP
I notice I am the only one that respect the output format
Mine also respects that output format. Go back and read my code. What's that you say? You can't figure it out?
154 <Php> Matthew Leverton
178 <Python> Joel Davis
219 <C++> ImLeftFooted
240 <Perl> ReyBrujo
254 <Haskell> X-G
364 <C++> Winston Ewert
377 <C++> William Heatley
400 <C++> Oscar Giner
414 <.NET> Rick
Values calculated using `cat foo | tr -d ' ' | tr -d '\t' | tr -d '\n' | wc -c`
My entry:
| 1 | #define S string |
| 2 | |
| 3 | #include <iostream> |
| 4 | #include <fstream> |
| 5 | #include <map> |
| 6 | using namespace std; |
| 7 | |
| 8 | main ( ) { |
| 9 | map < S, S > p ; |
| 10 | |
| 11 | fstream s ( "t" ) ; |
| 12 | |
| 13 | for ( S e, x ; s.good ( ) ; p [ x ] += " " + e + "\n" ) |
| 14 | s >> e >> x ; |
| 15 | |
| 16 | for ( map < S, S > :: iterator P = p.begin ( ) ; ; ++ P ) |
| 17 | cout << P -> first << P -> second ; |
| 18 | } |
I think I can safely say that mines the first thats trying to say something at the same time...
Also note that the instructions said nothing about how the program had to exit... 
Its also attatched to preserve the tabs if someone wants to compile it
meh, another losing entry.. ill try again in a different language.
| 1 | open( FILE, "<n" ); |
| 2 | while (<FILE>){ |
| 3 | s/(\w+)\s*(\w+)/$f=$1;$l=$2;/e; |
| 4 | if ( ! defined( $tr{$l} ) ){ |
| 5 | $tr{$l} = [ $f ]; |
| 6 | } else { |
| 7 | $b = $tr{$l}; |
| 8 | push @$b, $f; |
| 9 | } |
| 10 | } |
| 11 | while ( ($k,$h) = each(%tr) ){ |
| 12 | print "$k "; |
| 13 | if ( $#$h == 0 ){ |
| 14 | print $$h[0] . "\n"; |
| 15 | } else { |
| 16 | print "\n"; |
| 17 | for ( @$h ){ |
| 18 | print "\t$_\n"; |
| 19 | } |
| 20 | } |
| 21 | } |
| 22 | close( FILE ); |
Fear not! Me and Jolle are working on a compacted version of my Haskell entry above. So far we're down to 173 characters.
I notice I am the only one that respect the output format (if only one name with a surname, print them in the same line, otherwise print the surname first, and then all the names below)
And mine also respects it 
364 <C++> Winston Ewert
377 <C++> William Heatley
400 <C++> Oscar Giner
Note that Winston and Williams's code doesn't produce the correct output. Neither yours does (and it crashes)
135 characters in Python, but the formating isn't right:
i = [a.split() for a in file("n").readlines()] n = {} for a in i: try: n[a[1]] += [a[0]] except: n[a[1]] = [a[0]] for l,f in n.iteritems(): print l, "\n\t".join(f)
167 characters in Python with correct formatting:
i = [a.split() for a in file("n").readlines()] n = {} for a in i: try: n[a[1]] += [a[0]] except: n[a[1]] = [a[0]] for l,f in n.iteritems(): if len(f) < 2: print l, f[0] else: print l, "\n\t".join([""]+f)
The other Python entry doesn't get the formatting right and is unreadable and longer. 
Matthew, your Python interpreter is outdated.
Actually, my entry is 148 if you use my shorter method. It just spits out some notices if you have PHP on strict "debug" mode. My nonconforming entry (placing all first names below last names) is 128.
Surely someone do much better than that though... PHP has long names like "foreach", and I have to resort to using a trim(). It also doesn't have the shortcut stuff like: i = [a.split() for a in file("n").readlines()]
It also doesn't have the shortcut stuff like [...]
... Which is a good thing.
Marcello
Haskell is back again to save the day!
z x (n:b) | n!!0 == x!!1 = [n!!0,"\n ",x!!0 ++ "\n " ++ n!!2] : b | 0 < 1 = n : z x b z [a,b] _ = [[b," ",a]] main = readFile "f" >>= putStr . unlines . map concat . foldr (z . words) [] . lines
This little baby clocks in at 143 non-whitespace characters and gets the formatting right. Shortest so far, then. Co-produced by me and Jolle.
Mine's 144 now. If PHP just didn't require those <? ?> tags. 
However, I think essential white space (anything required for parsing or output) should count.
Mine runs like this:
<?foreach(file("n")as$l){$p=split(" |\n",$l);$n[$p[1]][]=$p[0];}foreach($n as$a=>$z)foreach($z as$i=>$p)echo($z[1]?$i?"\t":"$a\n\t":"$a ")."$p\n";?>
149 bytes short.
X-G: Does yours output a tab character?
If you turn warnings off, this version of Perl would work as well, and has only 205 characters:
X-G: Does yours output a tab character?
I'd tell you, but I'm running out of posts. 
(Yes.)
<? foreach (file("n") as $l) { $p = split(" | ", $l); $n[$p[1]][] = $p[0]; } foreach ($n as $a=>$z) foreach ($z as $i=>$p) echo ($z[1] ? $i?" ":"$a " : "$a ") ."$p "; ?>
Splendid! Mine's 134 now by the cat/wc count.
I'm using literal tabs and newlines instead of \codes now. (Although, I still say it's no fair to discard required whitespace...)
I don't know if I can make it any shorter without rethinking. I better get back to some real work.
Splended!
I didn't know there was a splending contest ...
Eh? Where's your C++ STL is teh foo code?
I first posted a 177 characters one, but after some more tweaklings, got it down to 169 (counted by hand). I agree with Matthew, though, required spaces should count as well... but well
Much better than my 240 original one, nevertheless 
I don't like the code, but works (don't try enabling warnings
)
| 1 | open(F, "t"); |
| 2 | @_ = <F>; |
| 3 | |
| 4 | while ($_ = pop @_) { |
| 5 | ($a,$b) = split; |
| 6 | $f = ' '; |
| 7 | pop; |
| 8 | |
| 9 | if (! @h{$b}) { |
| 10 | print $b; |
| 11 | for (@_) { |
| 12 | ($c,$d) = split; |
| 13 | if ($b eq $d) { |
| 14 | $f = "\n\t"; |
| 15 | print $f.$c; |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | print "$f$a\n"; |
| 20 | @h{$b} = 1; |
| 21 | } |
| 22 | } |
(Edited: Posted a new version, with only 161 characters... I still don't like all those print).
Here in Mathematica. 166 characters. It produces correct output: [edit]The only space required is the one in " ", so 167 characters using this rule[/edit]
For[p = ReadList["f", {Word, Word}], p != {}, p = DeleteCases[p, {_, a}], c = Cases[p, {_, a = p[[1]][[2]]}]; {d, e} = c[[1]]; If[Length[c] < 2, Print[e, " ", d], Print[e]; Print["\t", #1[[1]]] & /@ c ] ]
Simplified, not producing correct output, it's 133 characters: [edit]No spaces required here, so it stays at 133 characters[/edit]
For[p = ReadList["f", {Word, Word}], p != {}, p = DeleteCases[p, {_, a}], c = Cases[p, {_, a = p[[1]][[2]]}]; Print[c[[1]][[2]]]; Print["\t", #1[[1]]] & /@ c ]
134 <Php> Matthew Leverton
143 <Haskell> X-G
160 <Perl> ReyBrujo
166 <Mathematica> Oscar Giner
167 <Python> Mars
178 <Python> Joel Davis
244 <Perl?> kazzmir
252 <C++> ImLeftFooted
364 <C++> Winston Ewert
377 <C++> William Heatley
400 <C++> Oscar Giner
414 <.NET> Rick
(Edited: Posted a new version, with only 161 characters... I still don't like all those print).
Came in at 160 for me
My (fixed) entry:
| 1 | #define S string |
| 2 | |
| 3 | #include <iostream> |
| 4 | #include <fstream> |
| 5 | #include <map> |
| 6 | using namespace std; |
| 7 | |
| 8 | main ( ) { |
| 9 | map < S, S > p ; |
| 10 | |
| 11 | fstream s ( "t" ) ; |
| 12 | |
| 13 | for ( S e, x ; s.good ( ) ; p [ x ] += " " + e + "\n" ) |
| 14 | s >> e >> x; |
| 15 | |
| 16 | S y; |
| 17 | |
| 18 | for ( map < S, S > :: iterator P = p.begin ( ) ; ; cout << P -> first << ( y . rfind ( " " ) != 0 ? "\n" : "" ) << y, ++ P ) |
| 19 | y = P -> second; |
| 20 | } |
Neither yours does (and it crashes)
The rules didnt say how the program had to exit, i chose to use a segfault;D
Whitespace will be removed for counting, so dont bother to make your code look clean in the thread.
Bad choice for a rule IMO. Almost all languages force the use of at least one whitespace character to differentiate between identifiers. So it makes more sense to count a sequence of whitespace characters as at least one character for the purpose of your challenge.
I improved mine. Now 157 
I discovered that you can write v[[a]][<b>] as v[[a,b]], and the Import function does a better job than ReadList 
For[p = Import["f", "Table"], p != {}, p = DeleteCases[p, {_, a}], c = Cases[p, {_, a = p[[1, 2]]}]; {d, e} = c[[1]]; If[Length[c] < 2, Print[e, " ", d], Print[e]; Print["\t", #1[[1]]] & /@ c] ]
[edit]
Oh, if the file extension is ".dat", Import mode defaults to "Table". The rules don't say anything about the file name, so now it's only 153.
[edit]
3 characters more saved. Now it's 150.
[edit]
Namig the file just ".dat" saves 1 character. Windows (at least 98) won't let you use this filename, but renaming it with DOS does the job
149 characters.
For[p = Import[".dat"], p != {}, p = DeleteCases[p, {_, a}], c = Cases[p, {_, a = p[[1, 2]]}]; {d, e} = c[[1]]; P := Print; If[Length[c] < 2, P[e, " ", d], P[e]; P["\t", #1[[1]]] & /@ c] ]
Okay here it is in lua
| 1 | s = string |
| 2 | p = s.sub |
| 3 | n = {} |
| 4 | t = table |
| 5 | r = t.foreach |
| 6 | o = print |
| 7 | |
| 8 | for l in io.lines("f") do |
| 9 | v = s.find(l," ") |
| 10 | f = p(l,v+1) |
| 11 | |
| 12 | if(type(n[f]) == "nil") then n[f] = {} end |
| 13 | l = p(l,1,v); |
| 14 | n[f][l] = l; |
| 15 | end |
| 16 | |
| 17 | for l,t in n do |
| 18 | o(l) |
| 19 | for a in t do |
| 20 | o("",a) |
| 21 | end |
| 22 | end |
I've only used the standard lua libraries, I could make it shorter by adding a few functions, but after all, then I could add a function called a which did everthing. 
[edit] updated code, discovered that foreach syntax took more then simple for
But really, there should be a limitation on language used, or else there's no fair way to compare entries.
Agreed.
I could make a programming language which just happens to have a built in function to do the whole thing.
The code would then just be:
go;
or something like that.
You would be missing the entire point of the thing, failing to impress anyone.
kazzmir entry is also in Perl. I tried doing it in Ruby, but didn't work too well. Trying to fix it now
And thanks, WE, I was wondering where the LUA version was 
(Edited: Can the text file be "included"? I will try to do it in Prolog, the rules are very easy, but I am not sure how to open and load a file at all :/)
Can the text file be "included"?
Anything should be OK, assuming it's part of the standard libs/langauge.
You would be missing the entire point of the thing, failing to impress anyone.
Thank you for that insight. I'm just saying that in any good 'competition' there needs to be a few strong rules. I used that extreme example just to illustrate my point.
It is just something to spend time, nothing serious. This is what Allegro programmers do when they are too tired
We are not getting rewards (at least, I had not been notified
).
Lua again. By changing the way I was doing things I saved about ten characters.
| 1 | n = {} |
| 2 | s = string |
| 3 | t = table |
| 4 | z = print |
| 5 | y = s.sub |
| 6 | |
| 7 | for a in io.lines("f") do |
| 8 | l = s.find(a," ") |
| 9 | t.insert(n,{y(a,1,l),y(a,l+1)}) |
| 10 | end |
| 11 | |
| 12 | t.sort(n, function (a,b) return a[2] < b[2] end) |
| 13 | |
| 14 | for l,y in n do |
| 15 | |
| 16 | x = y[2] |
| 17 | if(p ~= x) then z(x) end |
| 18 | p = x |
| 19 | |
| 20 | z("",y[1]) |
| 21 | end |
134 <Php> Matthew Leverton
143 <Haskell> X-G
149 <Mathematica> Oscar Giner
160 <Perl> ReyBrujo
167 <Python> Mars
178 <Python> Joel Davis
195 <Lua> Winston Ewert
244 <Perl> kazzmir
252 <C++> ImLeftFooted
364 <C++> Winston Ewert
377 <C++> William Heatley
400 <C++> Oscar Giner
414 <.NET> Rick
By the way its looking i think Matt with php is gonna take it.
[Edit:]
Or by language:
Php - 134
Haskell - 143
Mathematica - 149
Perl - 160
Python - 167
Lua - 195
C++ - 252
.NET - 414
You should remove the entries that don't get the formatting right...
By the way its looking i think Matt with php is gonna take it.
Not too fast
. I improved my Mathematica entry. 133 characters:
For[p = Import[".dat"], p != {}, p = Complement[p, c], c = Cases[p, {_, p[[1, 2]]}]; {d, e} = c[[1]]; Print; If[Length[c] < 2, %[e d], %[e]; %["\t"#[[1]]] & /@ c ] ]
<? foreach (file("n") as $l) { $p = split(" | ", $l); $n[$p[1]][] = $p[0]; } foreach ($n as $a=>$z) foreach ($z as $i=>$p) echo $z[1] ? $i?" ":"$a " : "$a " ,"$p "; ?>
132
.. Perl-fu didn't come through at first yet?
Surely somebody with enough perl knowledge can do this in much less, right? There's so many different ways to do things in perl, I'd think it would always come in first.. especially for problems like this.
Oh well, good job (so far) ML.
Since you're printing spaces instead of tabs, I can do, too:
Print; For[p = Import[".dat"], p != {}, p = Complement[p, c], c = Cases[p, {_, p[[1, 2]]}]; {d, e} = c[[1]]; If[Length[c] < 2, %[e d], %[e]; %[" "#[[1]]] & /@ c ] ]
131
Make room, make room. Here comes Perl and 128 characters
Since you use the implicit enter and tab, I thought I could use them as well
Had to rewrite the code completely, the previous one could be optimized only a few characters.
| 1 | open F, "t"; |
| 2 | |
| 3 | while (<F>) { |
| 4 | split; |
| 5 | @f{@_[1]} .= " @_[0]" |
| 6 | } |
| 7 | |
| 8 | for (%f) { |
| 9 | ++$c; |
| 10 | |
| 11 | if (split == 1) { |
| 12 | print $c % 2? " |
| 13 | $_" : $_; |
| 14 | next |
| 15 | } |
| 16 | |
| 17 | print " |
| 18 | $_" for @_ |
| 19 | } |
(Edited: The 128 char version had a bug, didn't work with a long name list. Replaced it with a 116 version that works
)
(Edited 2: 115 characters, replaced " " . $a with " $a").
(Edited 3: 113 characters, () are optional in the open function).
(Edited 4: Saved 2 more characters, 111 now).
More Perl:
| 1 | open F, "n"; |
| 2 | |
| 3 | map { |
| 4 | split; |
| 5 | push @{$h{$_[1]}}, $_[0]; |
| 6 | } <F>; |
| 7 | |
| 8 | $"=" |
| 9 | "; |
| 10 | |
| 11 | print @$a < 2 ? "$k @$a[0] |
| 12 | " : "$k |
| 13 | @$a |
| 14 | " |
| 15 | while ($k, $a) = each %h |
109 
ReyBrujo's beats mine if you change his while into a map.
(Edit: down to 102)
You can get it to 91 if you're allowed to read standard input instead of a file.
There is the Perl guru you were asking for
In his and my code, the problem is reporting the data: He creates a map in 48 characters, I create mine in 47. But I didn't know about the $" variable :/
By the way, remove extra semicolon in the push statement 
Way to go!
| 1 | #include <fstream> |
| 2 | #include <map> |
| 3 | #include <iostream> |
| 4 | #define P <string,string> |
| 5 | #define M multimap P |
| 6 | #define C cout<< |
| 7 | #define S ->second |
| 8 | #define N <<'\n' |
| 9 | using namespace std; |
| 10 | |
| 11 | int main(int,char* a[]) |
| 12 | { |
| 13 | ifstream f(a[1]); |
| 14 | M m; |
| 15 | string i,l; |
| 16 | while (f>>i>>l) |
| 17 | m.insert(pair P(l,i)); |
| 18 | for (M::iterator t=m.begin();t!=m.end();) { |
| 19 | int c=m.count(i=t->first); |
| 20 | if (c>1) { |
| 21 | C i<<"\n\t"<<t S N; |
| 22 | ++t; |
| 23 | while (--c>0) |
| 24 | C"\t"<<(t++) S N; |
| 25 | } |
| 26 | else |
| 27 | C i<<' '<<(t++) S N; |
| 28 | } |
| 29 | } |
Here's a shorter python version:
a = [a.split() for a in file("f")] n = {} for i in a: n[i[1]] = 1 for i in n: f = [ l[0] for l in a if l[1] == i ] if len(f) < 2: print i, f[0] else: print "\n ".join(<i> + f)
> cat acc.py | python -c"import sys; print len([x for x in sys.stdin.read() if x != ' ' and x != '\n' ])"
says: 129
124 characters:
Print; For[p = Import[".dat"], p != {}, p = Complement[p, c], c = Cases[p, {_, p[[1, 2]]}]; If[{{d, e} = c[[1]]} == c, %[e d], %[e]; %[" "#[[1]]] & /@ c ] ]
I don't think this can get even shorter
It's official: I now hate perl.
What the heck is up with Colin's code? That's crazy.
It's official: I now hate perl.
I used to hate perl as well until I was forced to learn it a little while ago.
Dude. its. awesome.
Its such a great language to manipulating text in. I havent found an language that can manipulate text in better, including c,c++,java,python,scheme,shell.
Well, maybe because PERL was created exactly for that (Practical Extraction and Report Language). And Colin is doing a very clever thing in push @{$h{$_[1]}}, $_[0];: he is using a hashed list in which every value is an array, and then using the $" variable (which I did learn now it keeps the default separator to be used in an array when printing it whole; by default it is a space, but he changes it to "\n\t") to make Perl output it directly. In my code, I use a hashed list of strings instead, so I need an extra split to convert the string into an array.
I guess it is still possible to make it < 100 characters.
Here is my possibly last version, using his suggestion to turn the while into a map (both basically do the same, but the later needs less characters):
| 1 | open F, "t"; |
| 2 | |
| 3 | map { |
| 4 | split; |
| 5 | @f{@_[1]} .= " @_[0]" |
| 6 | } <F>; |
| 7 | |
| 8 | for (%f) { |
| 9 | ++$c; |
| 10 | if (split == 1) { |
| 11 | print $c % 2? " |
| 12 | $_" : $_; |
| 13 | next |
| 14 | } |
| 15 | |
| 16 | print " |
| 17 | $_" for @_ |
| 18 | } |
107.
/me looks at perl.
/me looks at Derezo's avatar.
Yep, that's what I look like now.
It's true; Perl really does look like a cartoon character swearing. 
Anyway, good job getting it down to 107. Holy crap.
Perl's not so bad if you're not using one character variables, (ab)using map instead of while, and using default variables everywhere.
Here's a more readable version (assuming you know Perl
)
| 1 | open FILE, '<', "names.txt"; |
| 2 | |
| 3 | while($line = <FILE>) |
| 4 | { |
| 5 | ($first, $last) = split / /, $line; |
| 6 | push @{$names{$last}}, $first; |
| 7 | } |
| 8 | |
| 9 | foreach $last (keys %names) |
| 10 | { |
| 11 | @first = @{$names{$last}}; |
| 12 | |
| 13 | if(@first == 1) |
| 14 | { |
| 15 | print "$last $first[0]\n"; |
| 16 | } |
| 17 | else |
| 18 | { |
| 19 | print "$last\n"; |
| 20 | |
| 21 | foreach $first (@first) { |
| 22 | print "\t$first\n"; |
| 23 | } |
| 24 | } |
| 25 | } |
And by the way, 99 characters (not including whitespace):
| 1 | open F, 0; |
| 2 | |
| 3 | map { |
| 4 | split; |
| 5 | push @{$h{$_[1]}}, $_[0] |
| 6 | } <F>; |
| 7 | |
| 8 | $"=" |
| 9 | "; |
| 10 | |
| 11 | print @$a < 2 ? "$k @$a[0] |
| 12 | " : "$k |
| 13 | @$a |
| 14 | " |
| 15 | while ($k, $a) = each %h |
Naming the file "0" saves a pair of quotes.
#1
\\\\\\\\\\\\\\\\\\\\\\\\\\\` \\\\\\\\\\\\\\\ \||||||||||||||||||||||||||| \||||||||||||||| \|||@@@@||@@@@||@@@@||@||||| \|||@@@@||@@@@|| \|||@||@||@|||||@||@||@||||| \|||@||@||@||@|| \|||@@@@||@@@|||@@@@||@||||| \|||@@@@||@@@@|| \|||@|||||@|||||@|@|||@||||| \||||||@|||||@|| \|||@|||||@@@@||@||@||@@@@|| \||||||@|||||@|| \||||||||||||||||||||||||||| \|||||||||||||||
- - - - Colin O'Leary
#2 107 <Perl> ReyBrujo
#3 124 <Mathematica> Oscar Giner4
#4 129 <Python> Elias
#5 132 <Php> Matthew Leverton
#6 143 <Haskell> X-G
#7 167 <Python> Mars
#8 178 <Python> Joel Davis
#9 195 <Lua> Winston Ewert
#10 244 <Perl> kazzmir
#11 252 <C++> ImLeftFooted
#12 364 <C++> Winston Ewert
#13 377 <C++> William Heatley
#14 400 <C++> Oscar Giner
#15 414 <.NET> Rick
Damn you Colin, steal my thunder >:E 
Perl:
map { split; push @{$h{$_[1]}}, $_[0] } `cat n`; for $l (keys %h) { print "$l " . shift(@{$h{$l}}) . "\n"; print "\t$_\n" for (@{$h{$l}}); }
114 chars (give or take). And thats without resorting to that evil crud 
edit: moding for that last while loop...
map { split; push @{$h{$_[1]}}, $_[0] } `cat n`; $"=" "; print @$a < 2 ? "$k @$a[0] " : "$k @$a " while ($k, $a) = each %h
Now to count...
woo hoo, 95
But it forces you to have cat...
I don't see a problem with that. If you have perl on windows, you're going to know how to fix it
jane fonda
chuck norris
ted fonda
kyle boop
In prolog:
surname(jane,fonda). surname(chuck,norris). surname(ted,fonda). surname(kyle,boop).
And then in the interpreter command line write
surname(X,fonda).
(for example).
Only Oscar Giner and I have posted correct C++ code.
map {
split;
push @{$h{$_[1]}}, $_[0]
} `cat n`;
$"="
";
print @$a < 2 ? "$k @$a[0]
" : "$k
@$a
" while ($k, $a) = each %h
Now to count...
woo hoo, 95
Curse you:P. Now i have to change the 99 to 95. By the way, did you purposely leave off the last " there, or was it a copying error?
Hmm... well, now that we are cheating 
map { split; push @{$h{$_[1]}}, $_[0] } <>; $"=" "; print @$a < 2 ? "$k @$a[0] " : "$k @$a " while ($k, $a) = each %h
Execute it like cat file.txt | perl test.pl. Here is the 91 characters entry Colins' was talking about.
I think that shouldnt be allowed...
main(int, char **v) { printf(v[1]); }
Comes in at 32
Edit:
execute it using some weird bash command
prog "`<something> \"\`cat file.txt\`\"`"
Well, I just don't agree with the idea of using external aid, like cat. He might later change `cat n` with `c n` and say you need to rename cat to c for it to work
Got it down to 11, using a custom compile command:
[code entry.cpp]
#include "c"
</code>
The compile command is:
g++ entry.cpp -o entry `echo -e "#define S string\n#include <iostream>\n#include <fstream>\n#include <map>\nusing namespace std;main ( ) {map < S, S > p ;fstream s ( \"t\" ) ;for ( S e, x ; s.good ( ) ; p [ x ] += \"\t\" + e + \"\\\\\\\\n\" )s >> e >> x;S y;for ( map < S, S > :: iterator P = p.begin ( ) ; ; cout << P -> first << ( y . rfind ( \"\t\" ) != 0 ? \"\\\\\\\\n\" : \"\" ) << y, ++ P )y = P -> second;}" > c`
Edit:
Made the compile command actually one command
Edit2: Make that 10 characters
[code entry.cpp]
#include " "
</code>
g++ entry.cpp -o entry `echo -e "#define S string\n#include <iostream>\n#include <fstream>\n#include <map>\nusing namespace std;main ( ) {map < S, S > p ;fstream s ( \"t\" ) ;for ( S e, x ; s.good ( ) ; p [ x ] += \"\t\" + e + \"\\\\\\\\n\" )s >> e >> x;S y;for ( map < S, S > :: iterator P = p.begin ( ) ; ; cout << P -> first << ( y . rfind ( \"\t\" ) != 0 ? \"\\\\\\\\n\" : \"\" ) << y, ++ P )y = P -> second;}" > " "`
Actually...
While we are doing wierd cheats. Define the entire program as a preprocessor symbol. You won't be able to include, so you'll have to provide your own prototypes and such. But you should be able to define the symbol a as your entire program, there by doing it in one letter.
Oh come on, cat in perl is not a weird cheat 
By the way, did you purposely leave off the last " there, or was it a copying error?
no error, just changed the formatting, colin's dsiplays wrong too. Has to do with that $" variable. the highligter thinks it starts a string.