Programming Comparisons: BEncoding


Problem: give the smallest possible complete subroutine/function/method definition in a language of your choice which, when called with an object, reference to a data structure, etc. returns a bencoded string representing a basic serialization of that object. Objects which are not lists, hashes, strings, or integers may be skipped. Each entry is displayed below as language: byte count followed by a commented call to the function taking as an argument a structure like: { 'foo' => 42, 'bar' => [1, 2, 3] } and returning the string: d3:barli1ei2ei3ee3:fooi42ee.

perl: 164 # b({foo => 42, bar => [1, 2, 3]}) sub b{my($o)=@_;ref($o)=~/Y/?'l'.join('',map b $_,@$o).'e':ref($o)=~/H/?'d'.join('',map{b($_).b($o->{$_})}sort keys%$o).'e':$o=~/^\d+$/?"i@{[$&+0]}e":length($o).":$o"}
ruby: 171 # b({'foo' => 42, 'bar' => [1, 2, 3]}) def b(o)case o when Array "l#{o.map{|i|b i}.join}e"when Hash "d#{o.keys.sort.map{|k|"#{k.size}:#{k+b(o[k])}"}.join}e"when Integer "i#{o}e"else "#{o.to_s.size}:#{o}"end end
python: 237 # b({ 'foo': 42, 'bar': [1, 2, 3] }) def b(o):s=lambda l:l.sort()or l;return{list:lambda:'l'+"".join(map(b,o))+'e',dict:lambda:'d'+"".join(map(lambda x:b(x)+b(o[x]),s(o.keys())))+'e',str:lambda:"%s:"%len(o)+o,int:lambda:"i%se"%o}.get(o.__class__,lambda:"%s:"%len(`o`)+`o`)()
gnu smalltalk: 244 "(Dictionary from: { 'foo' -> 42. 'bar' -> #(1 2 3) }) b" Integer extend[b[^'i%1e'%{self}]]SequenceableCollection extend[b[^'l%1e'%{(self collect:[:i|i b])join}]]String extend[b[^'%1:%2'%{self size. self}]]Dictionary extend[b[^'d%1e'%{(self keys asSortedCollection collect:[:k|k b,(self at:k)b])join}]]
haskell: 245 {- b$D$fromList[("foo",B 42),("bar",C[B 1,B 2,B 3])] -} import Data.Map data B=A String|B Integer|C[B]|D(Map String B) b(A x)=(shows.length)x$':':x b(B x)='i':shows x"e" b(C x)='l':(x>>=b)++"e" b(D x)='d':(toList x>>=(\(y,z)->b (A y)++b z))++"e"
javascript: 346 // b({foo: 42, bar: [1, 2, 3]}) function b(n){var t=typeof n,d,i,j=0,k=[],s='';if(t=='object'){for(i in n){if(d=/\D/.test(i))break;j++}if(d||j<n.length){for(i in n)k.push(i);k.sort();for(i in k)s+=(d=k[i]).length+':'+d+b(n[d]);return 'd'+s+'e'}while(j)s=b(n[--j])+s;return 'l'+s+'e'}return t=='string'||t=='number'&&Math.floor(n)!=n?(''+n).length+':'+n:t=='number'?'i'+n+'e':''}
php: 369 # b(array('foo' => 42, 'bar' => array(1, 2, 3))) function s($s){$s="$s";return(strlen($s).":$s");} function b($n){if(!isset($n))return'0:';if(is_array($n)){$i=0;$l=1;foreach($n as$k=>$v){if(!is_int($k)||$k!=$i++){$l=0;break;}}if($l)return('l'.join('',array_map('b',$n)).'e');else{$s='d';ksort($n);foreach($n as$k=>$v)$s.=s($k).b($v);return($s.'e');}}elseif(is_int($n))return"i${n}e";elseif(is_string($n))return s($n);}