16
\$\begingroup\$

When code-golfing there will be times where you need a Hex Dump of your code, usually because you've used unprintable characters. So, why not make a program that Hex Dumps itself?

The Challenge

This challenge is to, given no input, output a Hex Dump of your source code in the following formatting:

0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Or, for example, if your program was print("SomeString"):rep(123)

0000: 70 72 69 6e 74 28 5c 22 53 6f 6d 65 53 74 72 69  print("SomeStrin
0010: 6e 67 5c 22 29 3a 72 65 70 28 31 32 33 29        g"):rep(123)

Specifics

The hex dump is split into rows of three parts, each row representing 16 bytes of your source code.

The first part is the memory address. It specifies where the current row starts in your code. Written as a 2 Byte Hexadecimal number, followed by a :, then a space.

The Second, is the Hex Dump itself. This is 16 bytes of your Source Code, written in Hexadecimal form separated by spaces. This should be an accurate byte representation using your code's encoding.

Lastly, after a two space gap, is the code itself. This is simply 16 characters of your code, with Non printable characters written as .

Notes

  • This is a challenge, so Standard Quine Rules apply.
  • And this is challenge too, so Standard Loopholes apply.
  • As shown in the second example, do not write bytes after EOF, instead use whitespace.
  • Trailing whitespace is fine.
  • Inbuilts to Hex dump, if you happen to have one in this specific format, are not banned but are frowned upon.
  • Non printable characters refer to any character that, represented as only a single byte, cannot be represented as a single spaced glyph. For UTF-8, this means 0-31, 128-255. For the Jelly Codepage, as all characters can be represented as a single spaced glyph, there are no Non printable characters.
\$\endgroup\$
14
  • \$\begingroup\$ related/duplicate? codegolf.stackexchange.com/q/11985/47022 \$\endgroup\$
    – Herb
    Jan 16, 2017 at 1:01
  • \$\begingroup\$ Personally I feel like this is an applied quine makes it different enough, but I'm willing to see the community's thoughts. \$\endgroup\$
    – ATaco
    Jan 16, 2017 at 1:02
  • 1
    \$\begingroup\$ So for the record, you can't read your file name and xxd it? \$\endgroup\$
    – Riker
    Jan 16, 2017 at 1:05
  • 4
    \$\begingroup\$ Of course not, standard Quine rules disallow that \$\endgroup\$
    – ATaco
    Jan 16, 2017 at 1:05
  • 1
    \$\begingroup\$ Personally, I'd leave it up to the answer. Excluding a language because of this is absolutely unnecessary in my opinion. If you insist on a fixed width, use something that should be enough for most languages. Most hexdump utilities use 7 hex-digits. \$\endgroup\$
    – Dennis
    Jan 16, 2017 at 2:01

5 Answers 5

8
\$\begingroup\$

Perl, 81 bytes

#!perl -l
$_=q($%+=print"00$%0: @{[unpack'(H2)*']}  $_"for"\$_=q($_);eval"=~/.{16}/g);eval

Counting the shebang as one. Having the code length be a multiple of 16 saves quite a bit on formatting. Using eval to reassign $_ to itself borrowed from ais523.

Output:

0000: 24 5f 3d 71 28 24 25 2b 3d 70 72 69 6e 74 22 30  $_=q($%+=print"0
0010: 30 24 25 30 3a 20 40 7b 5b 75 6e 70 61 63 6b 27  0$%0: @{[unpack'
0020: 28 48 32 29 2a 27 5d 7d 20 20 24 5f 22 66 6f 72  (H2)*']}  $_"for
0030: 22 5c 24 5f 3d 71 28 24 5f 29 3b 65 76 61 6c 22  "\$_=q($_);eval"
0040: 3d 7e 2f 2e 7b 31 36 7d 2f 67 29 3b 65 76 61 6c  =~/.{16}/g);eval

Try it online!

\$\endgroup\$
5
\$\begingroup\$

Perl + xxd + cut, 61 bytes

$_=q(open F,"|xxd -g1|cut -c5-";print F"\$_=q($_);eval");eval

Try it online!

This is a universal quine constructor in Perl + a call to xxd and cut to do the hexdumping. None of the programs in question have a builtin to do a hexdump in the format in the question; however, xxd -g1 comes very close and so it's possible to use cut to trim the output into the correct shape.

The universal quine constructor is $_=q("\$_=q($_);eval");eval, which creates a copy of its own source code in memory, and can be modified to perform arbitrary operations on it. In this case, I use open "|" and print to pipe the input into external programs, xxd which does the bulk of the hexdumping work and cut which changes it into the required format.

\$\endgroup\$
3
\$\begingroup\$

V, 39 bytes

ñi241"qp:%!xxd
Î4x
Íøø / &
f&3i ÿ

Try it online!

Note that normally V uses the latin1 encoding, where this is 36 bytes (which is what TIO says) but this submission is using UTF-8 where it is 39 bytes.

This is pretty much just a modification of the V-quine template I wrote about.

\$\endgroup\$
2
  • \$\begingroup\$ Shouldn't the newline 0a at the end of the output be removed? \$\endgroup\$
    – user41805
    Jan 16, 2017 at 19:53
  • \$\begingroup\$ @kritixilithos Ah, I forgot about that. It's easier to just add a newline to the end. \$\endgroup\$
    – DJMcMayhem
    Jan 16, 2017 at 20:04
3
\$\begingroup\$

JavaScript (ES6) 229 219 162 bytes

Thanks to @Neil for saving a lot of bytes

Note

Quite a few people think accessing the source code of a function the way I do it is cheating, but according to @Dennis, it's fine. As such, I'll leave my answer here.

Code

f=_=>([...c=`f=`+f].map(d=>d.charCodeAt()[t=`toString`](16)).join‌​` `+` `.repeat(46)).match(/.{48}/g).map((s,i)=>`00${i[t](16)}0: `+s+c.substr(i*16,16)).join`\n`

Usage

f()

Simply call the function with no arguments.

Output

0000: 66 3d 5f 3d 3e 28 5b 2e 2e 2e 63 3d 60 66 3d 60 f=_=>([...c=`f=`
0010: 2b 66 5d 2e 6d 61 70 28 63 3d 3e 63 2e 63 68 61 +f].map(c=>c.cha
0020: 72 43 6f 64 65 41 74 28 29 5b 74 3d 60 74 6f 53 rCodeAt()[t=`toS
0030: 74 72 69 6e 67 60 5d 28 31 36 29 29 2e 6a 6f 69 tring`](16)).joi
0040: 6e 60 20 60 2b 60 20 60 2e 72 65 70 65 61 74 28 n` `+` `.repeat(
0050: 34 36 29 29 2e 6d 61 74 63 68 28 2f 2e 7b 34 38 46)).match(/.{48
0060: 7d 2f 67 29 2e 6d 61 70 28 28 73 2c 69 29 3d 3e }/g).map((s,i)=>
0070: 60 30 30 24 7b 69 5b 74 5d 28 31 36 29 7d 30 3a `00${i[t](16)}0:
0080: 20 60 2b 73 2b 63 2e 73 75 62 73 74 72 28 69 2a  `+s+c.substr(i*
0090: 31 36 2c 31 36 29 29 2e 6a 6f 69 6e 60 5c 6e 60 16,16)).join`\n`                                     
\$\endgroup\$
5
  • 1
    \$\begingroup\$ (not sure that 'f='+f is allowed under standard quine rules but if it is then for 161 bytes I give you f=_=>([...c=`f=`+f].map(c=>c.charCodeAt().toString(16)).join` `+` `.repeat(46)).match(/.{48}/g).map((s,i)=>`00`+i.toString(16)+`0 `+s+c.substr(i*16,16)).join`\n`. \$\endgroup\$
    – Neil
    Jan 16, 2017 at 11:25
  • \$\begingroup\$ Clever approach. I read some questions, and is appears people generally think it's considered cheating because I'm abusing a convenient language feature. I'll add that, along with your improved code, to my answer. \$\endgroup\$
    – Luke
    Jan 16, 2017 at 13:32
  • \$\begingroup\$ I think it is allowed, Dennis said on another quine challenge that using function source inspection is fine, and I know several "Golf a quine" answers use this. \$\endgroup\$
    – FlipTack
    Jan 16, 2017 at 17:44
  • \$\begingroup\$ Change the first .toString to [t=toString] and the second to [t] to save 3 bytes. Change the <backtick>\n<backtick> to <backtick><newline><backtick> to save another one. \$\endgroup\$ Jan 17, 2017 at 10:02
  • \$\begingroup\$ Changing it the string method requires the function name to be a string, as such, it only saves one byte. As for the newline, it would result in an a in the hex dump, which needs a 0 prepended, and adding that check would only increase the bytecount. \$\endgroup\$
    – Luke
    Jan 17, 2017 at 16:46
2
\$\begingroup\$

Ruby, 128 112 bytes

eval b='7.times{|y|$><<"%04x:"%y*=16;c=("eval b="+(a=39.chr)+b+a)[y,16];c.chars{|x|$><<" %x"%x.ord};puts"  "+c}'

Without trailing newline.

Thanks primo for the idea of aligning to 16-byte boundary.

Output

0000: 65 76 61 6c 20 62 3d 27 37 2e 74 69 6d 65 73 7b  eval b='7.times{
0010: 7c 79 7c 24 3e 3c 3c 22 25 30 34 78 3a 22 25 79  |y|$><<"%04x:"%y
0020: 2a 3d 31 36 3b 63 3d 28 22 65 76 61 6c 20 62 3d  *=16;c=("eval b=
0030: 22 2b 28 61 3d 33 39 2e 63 68 72 29 2b 62 2b 61  "+(a=39.chr)+b+a
0040: 29 5b 79 2c 31 36 5d 3b 63 2e 63 68 61 72 73 7b  )[y,16];c.chars{
0050: 7c 78 7c 24 3e 3c 3c 22 20 25 78 22 25 78 2e 6f  |x|$><<" %x"%x.o
0060: 72 64 7d 3b 70 75 74 73 22 20 20 22 2b 63 7d 27  rd};puts"  "+c}'
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.