programming challenge: fewest characters
kazzmir

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.

spellcaster
Quote:

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.

Kris Allen
Quote:

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!

Matthew Leverton

I tried it out in my secret compiler, and it worked. :o

But really, there should be a limitation on language used, or else there's no fair way to compare entries.

Rick

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?

Billybob

I dunno, i guess I'll try:

1#include <map>
2#include <string>
3#include <vector>
4using namespace std;
5map<string,vector<string>> a;
6void main()
7{
8FILE *f = fopen("file.txt","rb");
9while(!feof(f))
10{
11char t[9],h[9];
12fscanf(f, "%s %s\n",t,h);
13a[h].push_back(t);
14}
15 
16for(map<string,vector<string>>::iterator q = a.begin(); q != a.end(); ++q)
17{
18printf("%s\n", q->second.c_str());
19for(vector<string>::iterator o = q->second.begin(); o != q->second.end(); ++o)
20printf("\t%s\n", o->c_str());
21}
22}

ReyBrujo

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 :P).

X-G

Obfuscated Haskell for everyone!

1s b (q:r) = s (z q b) r
2s a [] = a
3z (f:l:_) ((a,c):b)
4 | a == l = ((a,f:c):b)
5 | True = (a,c):(z (f:[l]) b)
6z (f:l:_) [] = [(l,[f])]
7 
8o ((l,f):r) = (l++(y f)++"\n")++(o r)
9o [] = []
10y (a:[]) = ' ':a
11y (a:b) = m (a:b)
12m (a:b) = ("\n\t"++a)++(m b)
13m [] = []
14 
15g = o . (s []) . (map words) . lines
16 
17main = do
18 x <- readFile "foo.txt"
19 putStr (g x)

EDIT: Made it somewhat shorter.
EDIT2: Made it even shorter...

Matthew Leverton
<?
        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

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>
4uS1N9 NAm35P@C3 5tD;
5m4P<StR1NG,V3C+0r<S+R1N9>> 4;
6v0ID m@1N()
7{
8F1lE *f = PhOpEN("PHiLe.TXT","RB");
9wH1lE(!Ph3oPh(ph))
10{
11Ch4r t[9],h[9];
12Ph$C@nF(ph, "%5 %S\N",T,h);
134[H].pU5H_BaCK(+);
14}
15 
16PH0R(m4p<STrING,vEc+0r<$+riN9>>::1+3R4T0R Q = A.B3gIn(); Q != A.3nd(); ++Q)
17{
18Pr1N+f("%S\n", q->5eC0nd.c_$+R());
19fOR(veC+0r<$Tr1N9>::1T3R4tor 0 = Q->53C0nd.b391n(); o != Q->5Ec0ND.3nD(); ++o)
20pRInTf("\+%5\n", O->C_5TR());
21}
22}

remember, you have to use the elite g++ port...

LSd016
#/bin/bash
cat file.txt|decapitalise|sort|dostuff|playwith > /dev/tty1

Wetimer

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>
4using namespace std;
5#define f(t,x,y) for(t::iterator x = y.begin();x != y.end();x++) {
6#define l typedef;
7l vector<string> v;
8l map<string,v> z;
9z a;
10int main()
11{
12FILE *f = fopen("f","r");
13while(!feof(f))
14{
15char t[9],h[9];
16fscanf(f, "%s %s\n",t,h);
17a[h].push_back(t);
18}
19 
20f(z,q,a)
21printf("%s\n", q->first.c_str());
22f(v,o,q->second)
23printf("\t%s\n", o->c_str());
24}
25}
26}

Goodbytes
Wetimer

Except while Whitespace can deal with input, it cannot read from files, which is a requirement.

Oscar Giner

Willam: your code doesn't compile :P I made it compile but the output generated is not the one the problem defines (same would apply to derivative work :P).

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 
7using 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 
16M m;
17main()
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.

Joel Davis

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

Matthew Leverton

Bah, C++ is so primitive compared to PHP. 8-)

I would think a Perl nerd could get the shortest working code.

Joel: I get invalid syntax on yours...

spellcaster
Quote:

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.

Krzysztof Kluczek

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) ;)

Joel Davis

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.

LSd016

You lie.

"Tytwggfdtyuqfef" == "barman, pour me another!"

Rick
Quote:

The idea is to solve the given question with the fewest number of characters

Quote:

#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.

Matthew Leverton

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.

Oscar Giner
Quote:

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.

Rick

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.

Joel Davis

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)

Oscar Giner

Rick: look better. I use string three times.

Rick

Sorry, missed it in those #defines.

BAF

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(())

Kitty Cat

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. :P
#include <allegro/allegro5.h>*thinks*

Rick

Had to find the right .NET class that simulated a stl map

1Imports System.IO
2Imports System.Collections.Specialized
3 
4Module 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
28End Module

Billybob

BAH, My code is perfect!
Kay, I fixed the typos:

1#include <map>
2#include <string>
3#include <vector>
4using namespace std;
5map<string,vector<string> > a;
6int main()
7{
8FILE *f = fopen("file.txt","rb");
9while(!feof(f))
10{
11char t[9],h[9];
12fscanf(f, "%s %s\n",t,h);
13a[h].push_back(t);
14}
15 
16for(map<string,vector<string> >::iterator q = a.begin(); q != a.end(); ++q)
17{
18printf("%s\n", q->first.c_str());
19for(int i = 0; i < q->second.size(); ++i)
20printf("\t%s\n", q->second<i>.c_str());
21}
22}

Quote:

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:

Quote:

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

ReyBrujo

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) :P I use a hash to prevent repeating surnames too.

1my %h;
2my @f;
3 
4open(F, "<test.txt") or die $!;
5@f = <F>;
6close(F);
7 
8while ($_ = 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}

Matthew Leverton
Quote:

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!

ReyBrujo

Awww... that is why I still don't understand PHP :P

X-G

Quote:

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? :P

Dustin Dettmer

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>
6using namespace std;
7 
8main ( ) {
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... ;D

Its also attatched to preserve the tabs if someone wants to compile it

kazzmir

meh, another losing entry.. ill try again in a different language.

1open( FILE, "<n" );
2while (<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}
11while ( ($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}
22close( FILE );

X-G

Fear not! Me and Jolle are working on a compacted version of my Haskell entry above. So far we're down to 173 characters.

Oscar Giner
Quote:

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 :P

Quote:

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) :P

Mars

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. ;D

Matthew, your Python interpreter is outdated.

Matthew Leverton

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()]

Marcello
Quote:

It also doesn't have the shortcut stuff like [...]

... Which is a good thing.

Marcello

X-G

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.

Matthew Leverton

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?

ReyBrujo

If you turn warnings off, this version of Perl would work as well, and has only 205 characters:

1open(F, "t");
2@f = <F>;
3 
4while ($_ = shift(@f)) {
5 @s = split;
6 $f = " ";
7 @i = @f;
8 shift @i;
9 
10 if (! exists(%h->{$s[1]})) {
11 print $s[1];
12 for (@i) {
13 @c = split;
14 if ($s[1] eq $c[1]) {
15 $f = "\n ";
16 print "$f$c[0]";
17 }
18 }
19 
20 print "$f$s[0]\n";
21 %h->{$s[1]} = 1;
22 }
23}

X-G

Quote:

X-G: Does yours output a tab character?

I'd tell you, but I'm running out of posts. :P

(Yes.)

Matthew Leverton
<?
        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. 8-) 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. :P

23yrold3yrold
Quote:

Splended!

I didn't know there was a splending contest ...

Matthew Leverton

Eh? Where's your C++ STL is teh foo code?

ReyBrujo

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 :D Much better than my 240 original one, nevertheless :)

I don't like the code, but works (don't try enabling warnings ;))

1open(F, "t");
2@_ = <F>;
3 
4while ($_ = 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).

Oscar Giner

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
  ]

Dustin Dettmer

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

ReyBrujo said:

(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>
6using namespace std;
7 
8main ( ) {
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}

Oscar Giner said:

Neither yours does (and it crashes) :P

The rules didnt say how the program had to exit, i chose to use a segfault;D

Rash
Quote:

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.

Oscar Giner

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]
  ]

Wetimer

Okay here it is in lua

1s = string
2p = s.sub
3n = {}
4t = table
5r = t.foreach
6o = print
7 
8for 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;
15end
16 
17for l,t in n do
18o(l)
19for a in t do
20 o("",a)
21end
22end

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

Karadoc ~~
Quote:

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.

Matthew Leverton

You would be missing the entire point of the thing, failing to impress anyone.

ReyBrujo

kazzmir entry is also in Perl. I tried doing it in Ruby, but didn't work too well. Trying to fix it now :P 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 :/)

Matthew Leverton
Quote:

Can the text file be "included"?

Anything should be OK, assuming it's part of the standard libs/langauge.

Karadoc ~~
Quote:

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.

ReyBrujo

It is just something to spend time, nothing serious. This is what Allegro programmers do when they are too tired :P We are not getting rewards (at least, I had not been notified :D).

Wetimer

Lua again. By changing the way I was doing things I saved about ten characters.

1n = {}
2s = string
3t = table
4z = print
5y = s.sub
6 
7for a in io.lines("f") do
8 l = s.find(a," ")
9 t.insert(n,{y(a,1,l),y(a,l+1)})
10end
11 
12t.sort(n, function (a,b) return a[2] < b[2] end)
13 
14for 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])
21end

Dustin Dettmer

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

Mars

You should remove the entries that don't get the formatting right...

Oscar Giner
Quote:

By the way its looking i think Matt with php is gonna take it.

Not too fast 8-). 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
    ]
  ]

Matthew Leverton
<?
        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

Kanzure

.. 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. :)

Oscar Giner

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 ;D

ReyBrujo

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.

1open F, "t";
2 
3while (<F>) {
4 split;
5 @f{@_[1]} .= " @_[0]"
6}
7 
8for (%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).

Colin O'Leary

More Perl:

1open F, "n";
2 
3map {
4 split;
5 push @{$h{$_[1]}}, $_[0];
6} <F>;
7 
8$"="
9 ";
10
11print @$a < 2 ? "$k @$a[0]
12" : "$k
13 @$a
14"
15 while ($k, $a) = each %h

109 :P

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.

ReyBrujo

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!

Rash
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'
9using namespace std;
10 
11int 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}

Elias

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

Oscar Giner

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 :o

Derezo

It's official: I now hate perl.
What the heck is up with Colin's code? That's crazy.

kazzmir
Quote:

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.

ReyBrujo

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):

1open F, "t";
2 
3map {
4 split;
5 @f{@_[1]} .= " @_[0]"
6} <F>;
7 
8for (%f) {
9 ++$c;
10 if (split == 1) {
11 print $c % 2? "
12$_" : $_;
13 next
14 }
15 
16 print "
17 $_" for @_
18}

107.

Billybob

/me looks at perl.
/me looks at Derezo's avatar.
Yep, that's what I look like now.

23yrold3yrold

It's true; Perl really does look like a cartoon character swearing. :)

Anyway, good job getting it down to 107. Holy crap.

Colin O'Leary

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 :))

1open FILE, '<', "names.txt";
2 
3while($line = <FILE>)
4{
5 ($first, $last) = split / /, $line;
6 push @{$names{$last}}, $first;
7}
8 
9foreach $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):

1open F, 0;
2 
3map {
4 split;
5 push @{$h{$_[1]}}, $_[0]
6} <F>;
7 
8$"="
9 ";
10
11print @$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.

Dustin Dettmer

#1

Quote:

\\\\\\\\\\\\\\\\\\\\\\\\\\\` \\\\\\\\\\\\\\\
\||||||||||||||||||||||||||| \|||||||||||||||
\|||@@@@||@@@@||@@@@||@||||| \|||@@@@||@@@@||
\|||@||@||@|||||@||@||@||||| \|||@||@||@||@||
\|||@@@@||@@@|||@@@@||@||||| \|||@@@@||@@@@||
\|||@|||||@|||||@|@|||@||||| \||||||@|||||@||
\|||@|||||@@@@||@||@||@@@@|| \||||||@|||||@||
\||||||||||||||||||||||||||| \|||||||||||||||

- - - - 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

Thomas Fjellstrom

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 :P

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 :)

ReyBrujo

But it forces you to have cat...

Thomas Fjellstrom

I don't see a problem with that. If you have perl on windows, you're going to know how to fix it ;)

CascoOscuro
Quote:

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).

Rash

Only Oscar Giner and I have posted correct C++ code.

Dustin Dettmer
Quote:

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?

ReyBrujo

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.

Dustin Dettmer

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\`\"`"

ReyBrujo

:D 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 ;)

Dustin Dettmer

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;}" > " "`

Wetimer

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.

Thomas Fjellstrom

Oh come on, cat in perl is not a weird cheat :P

Quote:

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.

Thread #427371. Printed from Allegro.cc