There are a number of hex dump utilities in existence, that go by the
names `hd`, `od`, `hexdump`... I'm sure there are more. Pick one you'd
like to reproduce…
Will you be accepting golfed solutions? Of course you will.
-- a,b=%Q=Z,O^NPO\r4_PV\\PI\x15^-\x0\v=,email=%\%%%c\%115%%# Mikael Hoilund, CTO
okay=%#;hmm=(0...a.size).map{|i|((a[i]-email[i]+2)%128).# of Meta.io ApS from
chr}.join;!email.gsub!'o',"%c%c"%[3+?0.<<(2),?G.~@];aha=############# Denmark
hmm.scan(/#{'(.)'*5}/);!puts(email[1..-12]+aha.shift.zip(*aha).join)# Ruby <3
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 = 0
ARGF.read.scan(/.{0,16}/m) {
puts(("%08x " % i) + $&.unpack('H4'*8).join(' '))
i += 16
}
ARGF (aliased as $<) is the file handle of all file names given in the arguments concatenated, STDIN if none exactly what we need. The regex to scan matches between 0 and 16 characters (including newline) greedily. Change it to 1,16 if you don't want the empty line at the end.
Instead of letting the block to scan take an argument, I used a trick I picked up from the last Ruby Quiz I participated in (Obfuscated Email), and use $& inside the block, which is the last regex match. Saves two characters \o/
The unpack returns an array of eight strings, each of four characters, with the hexadecimal representation of the ASCII value of two consecutive characters. Fun, fun, fun.
This week's quiz should be quick and easy for experienced Rubyists,
and a good lesson for beginners. Your task this week is to write a
utility that outputs a hex dump of the input.
I did something a little different, I made a module that can be used to extend IO objects. This means you can extend any File or socket objects to become hex writers. Since I don't think you can "un-extend" an object, it would probably be best if you dup the IO object if you need to switch between hex and normal output.
Well, sure... Though in this case, I'd somewhat prefer to see nicely
written solutions that offered up more command-line options, such as
those provided by the various utilities. Things like grouping by 1, 2
or 4 bytes; ASCII display; binary/octal; etc.
But golfed solutions are okay, as usual...
···
On Jul 25, 3:56 pm, Mikael Høilund <mik...@hoilund.org> wrote:
Will you be accepting golfed solutions? Of course you will.
On Sunday 27 July 2008 22:51:04 Mikael Høilund 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 = 0
ARGF.read.scan(/.{0,16}/m) {
puts(("%08x " % i) + $&.unpack('H4'*8).join(' '))
i += 16
}
ARGF (aliased as $<) is the file handle of all file names given in the
arguments concatenated, STDIN if none exactly what we need. The
regex to scan matches between 0 and 16 characters (including newline)
greedily. Change it to 1,16 if you don't want the empty line at the end.
Instead of letting the block to scan take an argument, I used a trick
I picked up from the last Ruby Quiz I participated in (Obfuscated
Email), and use $& inside the block, which is the last regex match.
Saves two characters \o/
The unpack returns an array of eight strings, each of four characters,
with the hexadecimal representation of the ASCII value of two
consecutive characters. Fun, fun, fun.
Well here goes my reference implementation, in good ol' RQ tradition.
Nothing fancy here just 16 bytes per line
with hexaddresses and ASCII output at the right, like the System V hd command.
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
···
On 7/28/08, Martin Boese <boesemar@gmx.de> wrote:
On Sunday 27 July 2008 22:51:04 Mikael Høilund 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
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
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