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)
-
public class c{public static void main(String x[])throws Exception{int a=0,b=1,c ,i;for(i=Integer.parseInt(x[0]);i>0;i--){System.out.print(b+(i==1?"":", "));b=b+ a;a=b-a;}}}
-
public class c{public static void main(String x[]) throws Exception{char m,s[]=x [0].replace(" ","").toLowerCase().toCharArray(),i=0;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=0;for(i=0;i<255;i++){m=f[m]>f[i ]?m:i;}if(f[m]==0)return;System.out.println(f[m]+" "+m);f[m]=0;}}}
-
public class c{public static void main(String x[]) throws Exception{long a=0,m=0 ,b,c,F=0xFFFFFFFF;int i,j=0;for(;j<2;j++){c=0;for(i=0;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>0;c/=25 6){System.out.print(((a&c)>>(b-=8))+(b==0?" /":"."));}for(b=32;(m&1)==0;m/=2)b-- ;System.out.print(b);}}
-
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[0]+",- ,"+y[1]).split(",");int m,l=x.length,n[]=new int[l],p=0,i=0,a=0;for(;i<l;i++)if( x[i].equals("-")){a=i;p=i+1;}else n[i]=Integer.parseInt(x[i]);for(i=0;(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]);}}
-
public class c{public static void main(String x[])throws Exception{int c,p,t=0,v []={1,3,3,5,10,50};while((c=System.in.read())>-1){p=("pcbtar".indexOf(c));t+=p>- 1?v[p]:0;}System.out.print(t);}}




O primeiro em perl: $”=5**.5;@a=map{int.5+(.5+$”/2)**$_/$”}(1..);$”=”,”;print”@a”
[Responder]
Ricbit Reply:
julho 25th, 2010 at 13:00
Haha, o sanitizador comeu um pedaço da solução.
[Responder]
chester Reply:
julho 25th, 2010 at 13:05
Manda por e-mail que eu edito o comentário no WordPress (supondo que editando eu consiga dar bypass nisso).
[Responder]
Nah, fica de desafio pro povo achar os 2 caracteres que faltam :)
[Responder]
chester Reply:
julho 25th, 2010 at 13:58
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… :-)
[Responder]
Agora a pergunta: você já escreveu assim, ou passou no obfuscador depois?
[Responder]
chester Reply:
julho 26th, 2010 at 14:14
Já escrevi assim. Talvez fosse melhor o ofuscador, mas o tempo era curto e não quis arriscar…
[Responder]
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
[Responder]
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;}}}
[Responder]
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.
[Responder]
chester Reply:
julho 27th, 2010 at 18:55
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! :-)
[Responder]
chester Reply:
julho 29th, 2010 at 00:36
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 :-) )
[Responder]
Legal. As soluções em Python são bem mais legíveis mesmo. E até um pouco parecidas com o equivalente em Javascript :]
[Responder]