chester's blog

technology, travel, comics, books, math, web, software and random thoughts

FISL 11, cruzalinhas e iG Code Golf

25 Jul 2010

A edição desse ano do Fórum Internacional Software Livre foi interessante como de costume: palestrantes de renome e a troca de experiências dentro e fora do evento com as pessoas que fazem o software livre acontecer seguramente justificam passar esses dias em Porto Alegre. Esse ano fiz dois lances bacanas por lá:

O primeiro foi preparar e apresentar uma palestra-relâmpago sobre o cruzalinhas (slides aqui, vídeo em breve). Resolvi fazer isso na última hora, e me surpreendi com o interesse de pessoas de outras cidades (Manaus, Campinas, Florianópolis e da própria Porto Alegre) em fazer a mesma coisa, já que, segundo esse pessoal, a dificuldade em obter informações sobre o transporte público é a mesma.

O outro foi participar do Code Golf do iG, uma proposta inusitada, na qual são apresentados cinco problemas de programação. Eles são relativamente simples – o desafio é escrever o menor código-fonte que resolva cada um.

Claro que um código Python é bem menor que o seu equivalente Java, e por isso haviam categorias isoladas para cada linguagem suportada (Perl, Python, PHP, Java e Ruby). Fui o vencedor da categoria Java, com os códigos que estão no final do post.

Um aviso: NUNCA escreva código assim, a não ser que esteja participando de um Code Golf. O objetivo era sempre reduzir o tamanho e compensar a proibição de imports explícitos. Isso tem um custo: a performance quase sempre é horrível, a legibilidade é zero, é quase impossível modificar. Senti esse último lance na prática: tive que fazer uma gambiarra na questão 4 (o formato da entrada mudou, e o fix apropriado implicaria em reescrever tudo) – o tamanho dobrou e fui penalizado por isso.


Minhas soluções para o Code Golf (enunciados aqui)

  1. public class c{public static void main(String x[])throws Exception{int a=,b=1,c
    ,i;for(i=Integer.parseInt(x[]);i>;i--){System.out.print(b+(i==1?"":", "));b=b+
    a;a=b-a;}}}
  2. public class c{public static void main(String x[]) throws Exception{char m,s[]=x
    [].replace(" ","").toLowerCase().toCharArray(),i=;int f[]=new int[255],c,l=s.l
    ength;boolean p=true;for(;i<l;i++){p=p&&s[i]==s[l-i-1];f[s[i]]++;}System.out.pri
    ntln((p?"":"Não é ")+"Palíndrome");while(true){m=;for(i=;i<255;i++){m=f[m]>f[i
    ]?m:i;}if(f[m]==)return;System.out.println(f[m]+" "+m);f[m]=;}}}
  3. public class c{public static void main(String x[]) throws Exception{long a=,m=
    ,b,c,F=0xFFFFFFFF;int i,j=;for(;j<2;j++){c=;for(i=;i<4;i++)c=c*256+Integer.pa
    rseInt(x[j].split("\\.")[i]);a=m;m=c;}a=a|(F-m);b=32;for(c=0xFF000000l;c>;c/=25
    6){System.out.print(((a&c)>>(b-=8))+(b==?" /":"."));}for(b=32;(m&1)==;m/=2)b--
    ;System.out.print(b);}}
  4. public class c{static int h=-1;static void w(int i){if(h!=i)System.out.print(i+"
     ");h=i;}public static void main(String y[])throws Exception{String[]x=(y[]+",-
    ,"+y[1]).split(",");int m,l=x.length,n[]=new int[l],p=,i=,a=;for(;i<l;i++)if(
    x[i].equals("-")){a=i;p=i+1;}else n[i]=Integer.parseInt(x[i]);for(i=;(i<a&&p<l)
    ;){if(n[i]<n[p]){m=n[i];i++;}else{m=n[p];p++;}w(m);}for(;i<a;i++)w(n[i]);for(;p<
    l;p++)w(n[p]);}}
  5. public class c{public static void main(String x[])throws Exception{int c,p,t=,v
    []={1,3,3,5,10,50};while((c=System.in.read())>-1){p=("pcbtar".indexOf(c));t+=p>-
    1?v[p]:;}System.out.print(t);}}

Comments


Ricbit

O primeiro em perl: $"=5**.5;@a=map{int.5+(.5+$"/2)**$_/$"}(1..);$"=",";print"@a"

chester

Manda por e-mail que eu edito o comentário no WordPress (supondo que editando eu consiga dar bypass nisso).


chester

Hehe. Desafio 2: escrever um código cuja entrada é o código sem os dois caracteres, e a saída é o código com os 2 caracteres a mais que faz o que o código original deveria ter feito... :-)


chester

Já escrevi assim. Talvez fosse melhor o ofuscador, mas o tempo era curto e não quis arriscar...


@ikkebr

E em Python :)

#q1
a=[0]
exec"a+=[sum(a[:-1])+1];"*input()
print`a`[4:-1]

#q2
a=raw_input().replace(' ','').lower()
print ('',u'n\xe3o \xe9')[a!=a[::-1]]+u'pal\xedndromo'
for x,y in sorted((a.count(x),x)for x in set(a))[::-1]:print'%i: %s'%(x,y)

#q3
import struct as s,socket as o
a,b=raw_input().split()
k=lambda t:bin(s.unpack('!I',o.inet_aton(t))[0])
i=k(a)
m=k(b)
print"%s /%i"%(o.inet_ntoa(s.pack("!I",int(i,2)|~int(m,2))),32-m[:0:-1].count('0'))

#q4
a,b=raw_input().split()
exec'a,b=set([%s]),set([%s])'%(a,b)
print`sorted(a&b)`[1:-1]

#q5
import os
print sum(dict(p=1,c=3,b=3,t=5,a=10,r=50).get(x,0)for x in os.read(0,99))

ou http://pastebin.com/Et882MTV se quebrar


Lucas

public class d{public static void main(String x[])throws Exception{int a=0,b=1,i=Integer.parseInt(x[0]);for(;i>0;i--){System.out.print(b+(i==1?"":", "));b=b+a;a=b-a;}}}


Paulo Silveira

Paulo Silveira

Parabens pelo code golf. Pode parecer so brincadeira, mas esse tipo de exercício faz com que pratiquemos a sintaxe da linguagem ao extremo, que é muito importante para um total domínio da mesma.

chester

Obrigado! É verdade, além de um bom exercício, motivou discussões interessantes. Por exemplo, observei que tirando o payload da obrigatoriedade de definir uma classe/método main, o código Java em "estilo C" nem é tão verbose assim. Também percebi que "sob pressão", o Python ainda é o campeão em conservar legibilidade. Enfim, é divertido! :-)

chester

Aliás, o ricbit lembra que o SPOJ agora também tem uma modalidade de "shortest code", mas não é segregada por linguagem - ou seja, o Perl leva vantagem! (o post dele mostra uma forma alternativa de aritmética com regexps, é divertido :-) )