21
\$\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
    Commented Jan 16, 2017 at 1:01
  • 1
    \$\begingroup\$ So for the record, you can't read your file name and xxd it? \$\endgroup\$
    – Riker
    Commented Jan 16, 2017 at 1:05
  • 4
    \$\begingroup\$ Of course not, standard Quine rules disallow that \$\endgroup\$
    – ATaco
    Commented Jan 16, 2017 at 1:05
  • 1
    \$\begingroup\$ 1. I'm not sure I understand the purpose of the 8-bit encoding rule. If I can replicate the bytes of the file the interpreter received, why not let me? 2. Using only 2 bytes for the line offset unnecessarily excludes languages that require more than 65536 bytes for this task. \$\endgroup\$
    – Dennis
    Commented Jan 16, 2017 at 1:52
  • 2
    \$\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
    Commented Jan 16, 2017 at 2:01

8 Answers 8

9
\$\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\$
4
\$\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
    Commented 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
    Commented Jan 16, 2017 at 20:04
4
\$\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
    Commented 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
    Commented 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
    Commented 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\$ Commented 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
    Commented Jan 17, 2017 at 16:46
3
\$\begingroup\$

Vyxal 3, 140 bytes

"ṄᵛO∥ƛ₇≥[0:;|n)fHᵛ2ẆfZ₁Ẇƛ₁m×Hʀ4Þ0':+$:ƛtʀ2Þ0}\„47»$ƛh0=['.|nhO)\“ð$+W}'"ṄᵛO∥ƛ₇≥[0:;|n)fHᵛ2ẆfZ₁Ẇƛ₁m×Hʀ4Þ0':+$:ƛtʀ2Þ0}„47»$ƛh0=['.|nhO)“ð$+W}'

Vyxal It Online!

Explanation:

"..."Ṅ                                                                     # ‎⁡Quote and prepend the source (quine cheese)
      ᵛO                                                                   # ‎⁢Convert to a list of codepoints
        ∥                                                                  # ‎⁣Duplicate that list and:
         ƛ        )                                                        # ‎⁤  For each codepoint of the first copy:
          ₇≥[                                                              # ‎⁢⁡    If it's >= 256:
             0:;   f                                                       # ‎⁢⁢      Replace it with two zeros
                |n)                                                        # ‎⁢⁣    Otherwise don't change it.
                    Hᵛ2Ẇf                                                  # ‎⁢⁤  For the second copy, convert each codepoint to hexadecimal and group those into bytes.
                         Z₁Ẇ                                               # ‎⁣⁡Zip those copies as 16-item chunks.
                            ƛ                                          }   # ‎⁣⁢For each pair of [codepoint, hex representation]:
                              m                                            # ‎⁣⁣  Take the index of the pair in the list
                             ₁ ×                                           # ‎⁣⁤  multiply by 16
                                Hʀ4Þ0                                      # ‎⁤⁡  convert to four hex digits
                                     ':+                                   # ‎⁤⁢  and append a colon.
                                        $:                                 # ‎⁤⁣  Copy the pair
                                          ƛ     }                          # ‎⁤⁤  For the first copy:
                                           tʀ2Þ0                           # ‎⁢⁡⁡    Pad the hex to two digits
                                                 „                         # ‎⁢⁡⁢    join with spaces
                                                  47»                      # ‎⁢⁡⁣    and right-pad with spaces to the width of a line.
                                                     $ƛ          )         # ‎⁢⁡⁤  For the second copy:
                                                       h0=[                # ‎⁢⁢⁡    If the codepoint is zero:
                                                           '.              # ‎⁢⁢⁢      Replace it with a period
                                                              nhO)         # ‎⁢⁢⁣    otherwise replace it with the character it represents
                                                                  “        # ‎⁢⁢⁤  and concatenate those characters.
                                                                   ð$+     # ‎⁢⁣⁡  Prepend another space to the characters.
                                                                      W '  # ‎⁢⁣⁢Join each row by spaces, and join those rows by newlines.
💎

Created with the help of Luminespire.

\$\endgroup\$
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\$
2
\$\begingroup\$

Python 3.12,  336   288   240   224   112   109  107 bytes

-48 bytes by using bytes.hex().
-48 bytes by using str.replace() instead of a list comprehension.
-16 bytes by redoing the valid half of revision 4.
±0 bytes: fixed left column.
-112 bytes by using the exec() trick.
-3 bytes by not being lazy and actually formatting the last line.
-2 bytes by redoing the last part.

I stole primo's idea of doing 21 18 15 14 7 × 16 bytes.

exec(d:="for i in range(7):c=f'exec(d:={d!r})'[i*16:][:16];print(f'00{i}0: {c.encode().hex(' '):<47} ',c)")

Try It Online doesn't support Python 3.12.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 80 bytes

000000000000"D34çý16ôε00N„0:««žĆySk₁+h€¦`õ)À}»"D34çý16ôε00N„0:««žĆySk₁+h€¦`õ)À}»

Try it online.

Slightly longer version (81 bytes) that deals with the trailing spaces format:

0"D34çý16ôε00N„0:««žĆySk₁+h€¦ðýR47jRõ)À}»"D34çý16ôε00N„0:««žĆySk₁+h€¦ðýR47jRõ)À}»

Try it online.

Explanation (of the longer version):

Uses the 05AB1E code page.

0"D34çý..."D34çý... # Default 05AB1E quine portion:
0                   #  Push 0
 "D34çý..."         #  Push the source code as string
           D        #  Duplicate this string
            34      #  Push 34
              ç     #  Pop and convert it to a character with this codepoint: '"'
               ý    #  Join the three values on the stack with '"'-delimiter


16ô                 # Split it into parts of size 16 each
   ε                # Map over each part:
                    #  (implicitly push the current part)
    00N„0:          #  Push "00", 0-based map-index, "0:"
          ««        #  Append all three together: "00N0:"
    žĆ              #  Push the 05AB1E codepage constant
      y             #  Push the current part again
       S            #  Convert it to a list of characters
        k           #  Get the 0-based index of each part in the codepage string
         ₁+         #  Add 256 to each
           h        #  Convert it to a hexadecimal value
            €¦      #  Remove the first "1" from each
    ðý              #  Join it with space delimiter
      R             #  Reverse it
       47j          #  Add trailing space to make it length 47
          R         #  Reverse it back
           õ        #  Push an empty string ""
    )               #  Wrap everything on the stack into a list
     À              #  Rotate it once so the code-part is at the end
   }                # Close the map
    »               # Join each inner list by spaces, and then each string by newlines
                    # (after which the result is output implicitly)

The ₁+ and €¦ are unfortunately necessary for the ε, which has 05AB1E codepoint 6 in hexadecimal, which should be formatted as 06.

The shorter version replaces the ðýR47jR with `, and has more leading 0s to make the length a multiple of 16.

\$\endgroup\$

Your Answer

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

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