[Question]
  [
I recently stumbled across [this image](https://commons.wikimedia.org/wiki/File:Tesseract_Hasse_diagram_with_nibble_shorthands.svg) on wikimedia commons. It's a little bit of an information overload at first, but after examining it a bit it shows an interesting number system for writing nibbles.
[![Tesseract Hasse diagram with nibble shorthands](https://i.stack.imgur.com/Urze2.png)](https://i.stack.imgur.com/Urze2.png)
*Image created by user [Watchduck](https://commons.wikimedia.org/wiki/User:Watchduck).*
First off a "nibble" is a 4 bit number which is really a number ranging from 0 to 15, with a particular emphasis on binary. This diagram shows a shorthand for writing such numbers with each number being one symbol. Ok, who cares? Plenty of people make up new symbols for numbers all the time. Well the interesting thing about these numbers is their symmetry.
If you take one of the symbols and mirror it horizontally you get the symbol of the number with the same bits in reverse order. For example the symbol that sort of looks like a 3 represents the bits 0011, it's horizontal mirror represents the bits 1100. Numbers which are symmetric along this mirror represent nibbles which are palindromes.
Similarly if you take a symbol and rotate it a half turn (180 degrees) you get the symbol for the bitwise compliment of that number, for example if you take the symbol that looks like a 7, it represents 0111, if you rotate it a half turn you get a symbol representing 1000.
## Task
You will write a program or function which takes as input a nibble and outputs an image of a symbol. Your symbols are not required to be anything in specific but they are required to have the symmetry properties.
1. Distinct nibbles should give distinct symbols
2. The symbol for a nibble \$r\$ should be the mirror image of the symbol for the reverse of \$r\$.
3. The symbol for a nibble \$r\$ should be the symbol for the bitwise compliment of \$r\$ rotated 180 degrees.
You may take input in any reasonable format and output in any image or graphical format. There are no additional requirements on resolution, aside from those implied by the rules. You can make your symbols as small as you wish as long as you satisfy the rules.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") the goal is to minimize the size of your source code as measured in bytes.
  
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~12~~ 7 bytes
```
t~Pv1YG
```
Input is a 4-digit binary vector.
**Example outputs** (or try it at [**MATL Online**](https://matl.io/?code=t%7EPv1YG&inputs=%5B0+1+0+0%5D&version=22.7.4)!):
* Input `[0 1 0 0]`:
[![enter image description here](https://i.stack.imgur.com/PN9ypm.png)](https://i.stack.imgur.com/PN9ypm.png)
* Input `[1 0 1 1]`:
[![enter image description here](https://i.stack.imgur.com/ODR4Jm.png)](https://i.stack.imgur.com/ODR4Jm.png)
* Input `[1 1 0 1]`:
[![enter image description here](https://i.stack.imgur.com/hdivwm.png)](https://i.stack.imgur.com/hdivwm.png)
* Input `[1 0 0 1]`:
[![enter image description here](https://i.stack.imgur.com/Q2kQdm.png)](https://i.stack.imgur.com/Q2kQdm.png)
* Input `[0 1 1 0]`:
[![enter image description here](https://i.stack.imgur.com/aNQ6Tm.png)](https://i.stack.imgur.com/aNQ6Tm.png)
### How it works
The output is a 2-row, 4-column image where the first row corresponds to the input binary digits, and the second row is the first element-wise negated and reversed.
```
t     % Implicit input. Duplicate
      % STACK: [0 1 0 0], [0 1 0 0]
~     % Negate, element-wise
      % STACK: [0 1 0 0], [1 0 1 1]
P     % Reverse
      % STACK: [0 1 0 0], [1 1 0 1]
v     % Vertically concatenate
      % STACK: [0 1 0 0; 1 1 0 1]
1YG   % Display image with scaled colors. 0 is shown as black, 1 as white
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), 106 bytes
Takes an integer as input and returns a PBM image.
```
->i{t="'/%[g|eS	
s
m
R\rzrt"
"P1
5 3
"+("%08b"%t[t.index(i.chr)+1].ord).gsub(/./,'\&0')[1..]}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m72kqDSpcsGiNNulpSVpuhY3s3TtMqtLbJUYxBnVmfSZVVmiWdPZathTOYI55bmKuXN5gmKKqviK-EuUuJQCDLlMFYy5lLQ1lFQNLJKUVEuiS_Qy81JSKzQy9ZIzijS1DWP18otSNPXSi0uTNPT19HXUY9QM1DWjDfX0YmuhNsZoGOjpGZpq6qUmJmcopOQr1OTVcCkoZOYmpqcq2CqkRefFArkFpSXFCkrWCqnJGfkKMUrK1WD52hglBTsF5Wqg_SZA-_Nq9QqScpWgyrlS81IgdixYAKEB)
The code has unprintable characters that make it copy-and-paste-unfriendly; expand the below snippet for an xxd dump if you want to try it on your own machine.
```
00000000: 2d3e 697b 743d 2200 1701 2702 2f03 2504  ->i{t="...'./.%.
00000010: 5b05 6706 7c07 6508 5309 1f0a 730b 6d0c  [.g.|.e.S...s.m.
00000020: 525c 727a 0e72 0f74 220a 2250 310a 3520  R\rz.r.t"."P1.5 
00000030: 330a 222b 2822 2530 3862 2225 745b 742e  3."+("%08b"%t[t.
00000040: 696e 6465 7828 692e 6368 7229 2b31 5d2e  index(i.chr)+1].
00000050: 6f72 6429 2e67 7375 6228 2f2e 2f2c 2726  ord).gsub(/./,'&
00000060: 3027 295b 312e 2e5d 7d0a                 0')[1..]}.
```
## The shorthand
[![](https://i.stack.imgur.com/f9HxX.png)](https://i.stack.imgur.com/f9HxX.png)
## How it works
The images are 5×3 but there are only 7 "real" pixels, in a hex pattern:
```
 1 1
1 1 1
 1 1
```
This makes each image's data fit in a byte. `t` is a lookup table where the ASCII character corresponding to each nibble is followed by the character corresponding to its image representation. The code looks up the image data in the table, formats it as a string of `1`s and `0`s, interleaves the extra `0`s, and returns it in PBM format.
## Ungolfed
```
->input{
  table = "\x00\x17\x01\x27\x02\x2f\x03\x25\x04\x5b\x05\x67\x06\x7c\x07\x65\x08\x53\x09\x1f\x0a\x73\x0b\x6d\x0c\x52\x0d\x7a\x0e\x72\x0f\x74"
  image_byte = table[table.index(input.chr) + 1].ord
  image_data = ("%08b" % image_byte).gsub(/./,'\&0')[1..]
  "P1
5 3
" + image_data
}
```
[Answer]
# [Python 3](https://docs.python.org/3) + [NumPy](https://numpy.org/) and [Pillow](https://pillow.readthedocs.io/en/stable/), ~~101~~ ~~92~~ ~~91~~ ~~82~~ 77 bytes
```
import numpy as n,PIL.Image as p
lambda x:p.fromarray(n.array([x,1-x[::-1]]))
```
Takes in a NumPy array of ones and zeros and returns the resulting 4x2 image. Basically a copy of [Luis Mendo's answer](https://codegolf.stackexchange.com/a/252262/114332) in Python.
Ungolfed:
```
import numpy as np
from PIL import Image
def represent(nibble: np.array) -> None:
    representation = np.array([nibble, 1 - nibble[::-1])
    image = Image.fromarray(representation)
    return image
```
Thanks to Louis Mendo, who figured this out (and then saved me 9 bytes)!
Examples:
* `[1, 0, 0, 1]`
[![first example](https://i.stack.imgur.com/zBQlW.png)](https://i.stack.imgur.com/zBQlW.png)
* `[1, 1, 1, 1]`
[![second example](https://i.stack.imgur.com/uY4Zn.png)](https://i.stack.imgur.com/uY4Zn.png)
* `[0, 1, 1, 0]`
[![third example](https://i.stack.imgur.com/TAIU7.png)](https://i.stack.imgur.com/TAIU7.png)
I have no idea where the blurring comes from. However, it still satisfies the criteria. Note that in these images, the colors are RGB (0, 0, 0) and (255, 255, 255), for human readability. However, in the image generated by the program, the colors are (0, 0, 0) and (1, 1, 1), which, while distinct, cannot be told appart using a human eye.
* -9 thanks to Luis Mendo
* -1 thanks to Jonathan Allen
* -9 because I figured out I could return the image instead of displaying it, and not assign this to a variable
* -5 again thanks to Jonathan Allen
[Answer]
## JavaScript (browser), ~~187~~ 182 bytes
```
f=
(n,c)=>c.getContext`2d`.putImageData(new ImageData(new Uint8ClampedArray(Int32Array.from([...s=n.toString(2).padStart(4,0),...[...s].reverse()],(c,i)=>-1<<(c^i/4)*24).buffer),4),0,0)
```
```
canvas{width:256px;height:128px;image-rendering:pixelated;}
```
```
<input type=number size=2 min=0 max=15 oninput=f(+this.value,c)><div><canvas id=c height=2 width=4>
```
Uses @LuisMendo's method. Draws the output on a `2×4` canvas passed as the second parameter, but the snippet scales the output up 64 times for convenience.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 23 bytes
A port of [@Luis Mendo's MATL answer](https://codegolf.stackexchange.com/a/252262/9288).
```
Image@{#,Reverse[1-#]}&
```
[![enter image description here](https://i.stack.imgur.com/LcOk9.png)](https://i.stack.imgur.com/LcOk9.png)
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 12 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
142D;Ṛ;¬K”P;
```
A full program that outputs a PBM file on STD OUT.
**[Try it online!](https://tio.run/##AUAAv/9qZWxsef//MTQyRDvhuZo7wqxL4oCdUDv/MuG4tuG5lzTCtcOH4oG@IiJqLEDFkuG5mGrigJwgLT4g4oCdKVn/ "Jelly – Try It Online")**
### How?
Jelly cannot produce images on screen, so this places an image file content on STD OUT ready to be directed to a file.
The PBM format idea came from [Jordan](https://codegolf.stackexchange.com/users/11261/jordan)'s [Goruby](https://codegolf.stackexchange.com/a/252279/53748) and [Ruby](https://codegolf.stackexchange.com/a/252278/53748) posts. Go upvote!
The method is similar to [Luis Meno](https://codegolf.stackexchange.com/users/36398/luis-mendo)'s [MATL](https://codegolf.stackexchange.com/a/252262/53748) post, because there is nothing simpler. Go upvote!
The only difference is that rather than the number on top of the reversed negated number we have the reverse of the number on top of the negated number.
```
142D;Ṛ;¬K”P; - Main Link: list of four bits, N     e.g. [0,0,1,0]
142          - 142
   D         - to decimal digits -> [1, 4, 2]
     Ṛ       - reverse (N)                              [0,1,0,0]
    ;        - concatenate                              [1,4,2,0,1,0,0]
       ¬     - logical NOT (N)                          [1,1,0,1]
      ;      - concatenate                              [1,4,2,0,1,0,0,1,1,0,1]
        K    - join with spaces                         [1,' ',4,' ',2,' ',0,' ',1,' ',0,' ',0,' ',1,' ',1,' ',0,' ',1]
         ”P  - 'P'
           ; - concatenate                              ['P',1,' ',4,' ',2,' ',0,' ',1,' ',0,' ',0,' ',1,' ',1,' ',0,' ',1]
             - implicit, smashing print                 P1 4 2 0 1 0 0 1 1 0 1
                                                        i.e. the pixels:
                                                        0100
                                                        1101
```
[Answer]
## HTML + Javascript 70 + ~~159~~ ~~154~~ 151 = 221 bytes
The output is topologically like [Jordan's](https://codegolf.stackexchange.com/a/252258/252278), with the output rotated by 90° and lines instead of dots. This achieves a classical seven part display. The symbols also loosely resemble those used by Watchduck in his original grafic in shape and order.
The order of the elements is
```
  0            M1,1h3
1   2      M1,1v3  M4,1v3
  3             M1,4h3
4   5      M1,4v3  M4,4v3
  6            M1,7h3
```
After experimenting with multiple other variants, I find it interesting that this intuitive ordering still gives the shortest path production.
The Bigint holds the shown elements for each symbol as bits ordered right to left. Since the symbol for 1111, the last symbol, has no shown elements in the lower half, the last (leftmost) hex digit is 0, and the number can be written in hex with 27 digits instead of the expected 16\*7/4 = 28.
*-5 bytes thanks to Steffan.*
*-3 bytes for bitwise operation on `BigInt` and symbol reordering.*
```
f=n=>{for(d='',i=0;i<7;i++)0xe5cfdb4f4dbf24fdb2f2dbf3a70n>>BigInt(n*7+i)&1n?d+=`M${(i+1)%3?1:4},${(i/3&3)*3+1}${i%3?'v':'h'}3`:0;p.setAttribute('d',d)}
```
```
<input oninput=f(value)><svg viewBox=0,0,5,8><path id=p stroke=#000 />
```
### Ungolfed and a bit more pretty
```
f = n => {
    t = 0xe5cfdb4f4dbf24fdb2f2dbf3a70n
    for (d='',i=0; i<7; i++) {
        if (t>>BigInt(n*7+i)&1n) {
            d += `M${(i+1)%3?1:4},${(i/3&3)*3+1}${i%3?'v':'h'}3`
        }
    }
    p.setAttribute('d', d)
}
f(0)
```
```
<input type=number size=2 value=0 min=0 max=15 oninput=f(value)>
<div>
  <svg viewBox=0,0,5,8 width=80>
    <path id=p stroke=#000 />
  </svg>
</div>
```
[Answer]
# [Goruby](https://codegolf.stackexchange.com/questions/363/tips-for-golfing-in-ruby/9289#9289), 37 bytes
Takes an array of `0`s and `1`s and returns a PBM image.
Same technique as [Luis Mendo's answer](https://codegolf.stackexchange.com/a/252262/11261).
```
->a{"P1
4 2
#{a+a.rv.m{_1>0?0:1}}"}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=pVbdbts2FL73U5w4aSw5imJvHTAEddN2SLfdrEML7GKGJ1ASbbOVKJWk3NiS8iK7ycX2AHuc7Wl2SEryT92iw3IR0uf_5zuH-v0PUYTrh39670_h-0zfIRc0KeJelBAp4VX4lkaqB_Ds2SJL5sGSyCVMoKx7SFtREWaSenD2y-3rF6_e3CKnvXrAWYIyMZ1DStUyi4OUScn4AlIPhsSD8xDZAAqVdoxPYYp8SZO5byKYwQyqagIpUdEStQNrTDqpOx3NjAU2RyPn52DtAQSBpDwOAkdpRy6U1ZCIhawaNkDoh4zHaMynK5I4_VxkUVmZEIybmChSwdk9RrZPhLrv-hFJEufs3tV-z-53jBqGceU21NqcNJG0ISi4OQhP18GFa5BFToUV53Gv_b9T2KbYvbamh_WQKDMYeJDiqSMhYUJbpo1HIOfqt9NS-ioLpL-QRehc-Vdu2Xf84Y3bhwt4TRf0LvepjEhOnbNzt66vjG7qLwTNHeH6MhMqQJjEGVSsrSmzJk1QWgjVVSGopuTO-bVkG-rCkyfADjJskrHtzrhUHUiiT4Aj8r4AG5EHxhrhSnYwUUB4DIJiYNyygwVVjmqKQ5ik8BNJ6a0QmfCgX3DGmWIkweDjzh6cllHd90yJqXDG7kEmSywPRdMkDAVdMaJYxr-gN1rC9sX8zAoRRAQDmoBz89z3b351YTJBkR3Mpz6CmN45Vm2dtqAb-0WuMiSbqpfVpkLL2FBumo1lThH9Nq6NqxtUVkpgmtv54PROQcETigvA2fNvBDEG_asLstMzXBjqXDtaU2_LYkdwazhYGt0nk4k2LdsB-miC7FY5gqHDutqydljRVu0ywxFsRBDwuWArojolHMStemO8EWn9LB2iu_kDtjPUlw94ifTlZGA7kBdKQv-0JDVNksxDwIR1JpLYAGc_5rmjETEejaxm07kUm8YrbWbwkm02L4rNpjeYsgkfDh8_uhx_47GL8dezquL11hqilEiQZG3ct_bjLPiwZImt3QjMHdaMJge1Q7mCq6ayIzD3PTkja-v4XAiy7jxmSRyYpjXQtVRDeZsxvqv4kmAXv9PXT2rrWLoZ6Pc_dv4jV7ihRGeAkmgJiqVUqzAe4cNF4ZYXKRUaC7uqbxBofNFpXoHME6Z6W6_EIkZTncFgZ64dkzJOm14A0RYrl3CE9IhNtS2xRsgTLnNc2TBPiFKUt-cJLpM0J4jE5jwBDDCLcAfpY-b6Oq2y0kbtUOpnCvrmqoM9LTWrtm-NfkCSLHrXjr9GZ5eNnj9ZJHqNEv-zarjdExJRh_i6by0VB9Ya2A5R23_71zTELAcriWOME9ZoYXbvnEE0HOgnrqEZXFhtnOsjHpr-qUzsbBEjYl8TE6BeFRQFt5bogXTLMYvCnLqC9S4m9jwdh-R_av70uinjDFfL9Fqb-J_d1J38XOO6rHbjx8hyveias-O19DbHvfFYp2HWfrBtv2T2vekPJfPwCxqtqg450crvPmr0xtXfNcci3Z3n-eTPQs0vv_379PIpKfs_j3uP4asebs0L4ouVn5bB-OnoZnQ9rut-bUX_Mpt1Pp2OvLE38kazmaU_PNjzXw)
[Answer]
# [Desmos](https://www.desmos.com/calculator), 44 bytes
```
L=[0...3]
f(l)=join((L[l>0],1),(3-L[l=0],0))
```
I have no idea what this question is asking about; I'm just porting most of the other answers here.
[Try It On Desmos!](https://www.desmos.com/calculator/4ojzplhamn)
[Try It On Desmos! - Prettified](https://www.desmos.com/calculator/yvcbqz6yus)
[Answer]
# [Fig](https://github.com/Seggan/Fig), \$16\log\_{256}(96)\approx\$ 13.17 bytes
```
J/Pj/ JJf142$xe!
```
[Try it online!](https://fig.fly.dev/#WyJKL1BqLyBKSmYxNDIkeGUhIiwiWzAsMCwxLDBdIl0=)
Outputs as a PBM image. Port of Jelly, so go upvote that (and the posts that inspired it)!
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), ~~35~~ 33 bytes
```
{`0:"P1\n4 2\n",*',/$x,"\n",$|~x}
```
[Try it online!](https://ngn.codeberg.page/k#eJxLs6pOMLBSCjCMyTNRMIrJU9LRUtfRV6nQUQKxVWrqKmq5uNKiDRUMFAwVDGPBTDAnFioKZYKlFQxiAS1AEuY=)
Took me quite some time, but I finally got it. Output PBM image data, as that seems to be what everyone's doing.
Forgive me if the explanation doesn't make sense. Neither do I understand it well.
Explanation:
```
{`0:"P1\n4 2\n",*',/$x,"\n",$|~x}    Main program. Takes x as input
                               x     x itself
                             |~      Not, then reverse
                            $        Convert each number to string
                       "\n",         Concat with newline
                      ,              Concat with
                    $x               x, with each number converted to string
                  ,/                 Joined everything together
                *'                   Get the first element of each string.
                                     This is to remove the sub-arrays of the negate-then-reverse x
               ,                     Concat the entire result with
    "P1\n4 2\n"                      PBM hardcoded image data. Defined an image of 2x4 pixels
 `0:                                 Print everything to stdout
```
]