JavaScript (ES6), 159 154 140 bytes
Saved lots of bytes thanks to @Hedi and @Arnauld
n=>[..."ఀ刀Ā邀⏠Ϡῼῼ㿾㿞ᾼ߰ǀ"].map(x=>(f=q=>q>1?f(q>>1)+(q&1?"##":" "):"")(65536+x.charCodeAt()).repeat(n)).join`
`
That's 112 chars, but 140 UTF-8 bytes. The string was generated with this snippet:
console.log([
0b0000110000000000,
0b0101001000000000,
0b0000000100000000,
0b1001000010000000,
0b0010001111100000,
0b0000001111100000,
0b0000111111111000,
0b0001111111111100,
0b0001111111111100,
0b0011111111111110,
0b0011111111011110,
0b0001111111011100,
0b0001111110111100,
0b0000111111111000,
0b0000011111110000,
0b0000000111000000
].map(x=>String.fromCharCode(x)).join``)
Using .replace
instead of [...string].map
is equally long:
n=>"ఀ刀Ā邀⏠Ϡῼῼ㿾㿞ᾼ߰ǀ".replace(/./g,x=>(f=q=>q>1?f(q>>1)+(q&1?"##":" "):"")(65536+x.charCodeAt()).repeat(n)+`
`)
How it works
Since each row of the raw data can be represented as a 16-bit number, we can store the entire file in a 16-char string. The compression algorithm simply takes each 16-bit char-code, turns it into a char, and concatenates the resulting characters.
To decompress it, we need to extract the charcode and turn its binary representation into a string of hashes and spaces. This can be done with a recursive function, like so:
(f=q=>q?f(q>>1)+(q&1?"##":" "):"")(x.charCodeAt())
However, the result is not padded, which causes a problem. A basic way to do this would be to pad the beginning with a bunch of spaces, then take the last 32 chars:
(" ".repeat(32)+(f=q=>q?f(q>>1)+(q&1?"##":" "):"")(x.charCodeAt())).slice(-32)
Obviously, that's a little long. ES7 actually has a built-in for this; let's try using that:
(f=q=>q>1?f(q>>1)+(q&1?"##":" "):"")(x.charCodeAt()).padStart(32," ")
Better, but not good enough. Another way to do it would be to pad the number itself with zeroes before stringifying it:
(f=q=>q?f(q>>1)+(q&1?"##":" "):"")(65536+x.charCodeAt()).slice(2)
That's even better, but the .slice(2)
still seems like a little bit of a waste. It turns out that there's an easy way around this: since there's always a final unnecessary 1
, we can just ignore the result when it gets down to 1. This saves a few more bytes:
(f=q=>q>1?f(q>>1)+(q&1?"##":" "):"")(65536+x.charCodeAt())
After that, we can just repeat the string n
times and add a newline. This is the shortest decompression method I have found, but feel free to suggest any possibly shorter methods.