On 7/28/08, Martin Boese <boesemar / gmx.de> wrote:
> On Sunday 27 July 2008 22:51:04 Mikael H°Úlund wrote:
> > Oh hi, I just thought I'd golf a solution. I'm sure other people can
> > do a much better job than I making a full hexdumping suite, so I just
> > had some fun. Can't seem to get it lower than 78 characters,
> > unfortunately.
> >
>
> I added an ascii column to your solution... now it's about twice the size-)
>
> i = 0
> $<.read.scan(/.{0,16}/m) {
>     puts(("%08x " % i) + $&.unpack('H4'*8).join(' ') + ' ['+
>       $&.split(//).collect { |c| c.inspect[1] == 92 ? '.' :c }.join +]' )
>     i += 16
> }
>

I can't resist golf:  I got Martin's solution down to 95 bytes (If you
take out the ascii column it's down to 71).

i=0;$<.read.scan(/.{0,16}/m){puts"%08x0 "%i+$&.unpack('H4'*8)*' '+' |
'+$&.tr('^ -~','.');i+=1}

Tricks: *' ' is a shorter version of .join(' ') for arrays,
and $&.tr('^ -~','.') says translate any character not between ' ' and
'~' (32 to 126) to a '.'   That saved a ton over the
split/collect/inspect method.  (By the way, map and dump save a few
bytes over collect and inspect)

I also did a more full-featured version that supports some command line options

-Adam
----------------------------------------------------
#hexdump utility for RubyQuiz#171
USAGE=<<USAGE

Usage:
  #{$0.split(/[\/\\]/)[-1]} [-n length] [-s skip] [-g group] [-w
width] [-a] file

Dumps <length> bytes of <file> in hex format, starting at offset <skip>.
Prints <width> bytes per line in groups of size <group>.
Prints the ascii on the right unless <-a> specified

Default is all bytes of $stdin in 16/2 format.

USAGE
begin
width=16
group=2
skip=0
length=Float::MAX
do_ascii = true
file = $stdin

while (opt=ARGV.shift)
   if opt[0]==?-
     case opt[1]
      when ?n
        length=ARGV.shift.to_i
      when ?s
        skip=ARGV.shift.to_i
      when ?g
        group = ARGV.shift.to_i
      when ?w
        width = ARGV.shift.to_i
      when ?a
        do_ascii = false
      else
        raise ArgumentError,"invalid Option #{opt}"
      end
    else
        file = File.new(opt)
    end
end

n=0
ascii=''
file.read(skip)
file.each_byte{|b|
 if n%width == 0
   print "%s\n%08x "%[ascii,n+skip]
   ascii='| ' if do_ascii
 end
 print "%02x"%b
 print ' ' if (n+=1)%group==0
 ascii << "%s"%b.chr.tr('^ -~','.') if do_ascii
 break if n>length
}
puts ' '*(((2+width-ascii.size)*(2*group+1))/group.to_f).ceil+ascii
#this is probably the most complicated line
#it pads out the line to get the remaining ascii to align:
#   (2+width-ascii.size) is the number of bytes missing (the 2 is for the ')
#  *(2*group+1) is the width of a group of bytes with the space
#   /group.to_f divides by the number of groups
#   .ceil rounds up, otherwise we misalign on partial groups

rescue =>x
  puts USAGE, "ERROR: #{x}"
end