Skip to content

Instantly share code, notes, and snippets.

@kriskowal
Created February 2, 2019 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kriskowal/f97680b89d43d44c4f8b17d2c6a2f3d9 to your computer and use it in GitHub Desktop.
Save kriskowal/f97680b89d43d44c4f8b17d2c6a2f3d9 to your computer and use it in GitHub Desktop.
Generate tables for converting an image describing line art into the corresponding runes.
package main
var lineArtRuneOffsets = []uint8{
// Index NnSsEeWs NnSsEeWw Rune
0x00, // 00000000 -------- " "
0x01, // 00000001 -------w "╴"
0x01, // 00000010 -------w "╴"
0x10, // 00000011 ------W- "╸"
0x02, // 00000100 -----e-- "╶"
0x03, // 00000101 -----e-w "─"
0x03, // 00000110 -----e-w "─"
0x11, // 00000111 -----eW- "╾"
0x02, // 00001000 -----e-- "╶"
0x03, // 00001001 -----e-w "─"
0x03, // 00001010 -----e-w "─"
0x11, // 00001011 -----eW- "╾"
0x18, // 00001100 ----E--- "╺"
0x19, // 00001101 ----E--w "╼"
0x19, // 00001110 ----E--w "╼"
0x20, // 00001111 ----E-W- "━"
0x04, // 00010000 ---s---- "╷"
0x05, // 00010001 ---s---w "┐"
0x05, // 00010010 ---s---w "┐"
0x12, // 00010011 ---s--W- "┑"
0x06, // 00010100 ---s-e-- "┌"
0x07, // 00010101 ---s-e-w "┬"
0x07, // 00010110 ---s-e-w "┬"
0x13, // 00010111 ---s-eW- "┭"
0x06, // 00011000 ---s-e-- "┌"
0x07, // 00011001 ---s-e-w "┬"
0x07, // 00011010 ---s-e-w "┬"
0x13, // 00011011 ---s-eW- "┭"
0x1a, // 00011100 ---sE--- "┍"
0x1b, // 00011101 ---sE--w "┮"
0x1b, // 00011110 ---sE--w "┮"
0x21, // 00011111 ---sE-W- "┯"
0x04, // 00100000 ---s---- "╷"
0x05, // 00100001 ---s---w "┐"
0x05, // 00100010 ---s---w "┐"
0x12, // 00100011 ---s--W- "┑"
0x06, // 00100100 ---s-e-- "┌"
0x07, // 00100101 ---s-e-w "┬"
0x07, // 00100110 ---s-e-w "┬"
0x13, // 00100111 ---s-eW- "┭"
0x06, // 00101000 ---s-e-- "┌"
0x07, // 00101001 ---s-e-w "┬"
0x07, // 00101010 ---s-e-w "┬"
0x13, // 00101011 ---s-eW- "┭"
0x1a, // 00101100 ---sE--- "┍"
0x1b, // 00101101 ---sE--w "┮"
0x1b, // 00101110 ---sE--w "┮"
0x21, // 00101111 ---sE-W- "┯"
0x24, // 00110000 --S----- "╻"
0x25, // 00110001 --S----w "┒"
0x25, // 00110010 --S----w "┒"
0x2c, // 00110011 --S---W- "┓"
0x26, // 00110100 --S--e-- "┎"
0x27, // 00110101 --S--e-w "┰"
0x27, // 00110110 --S--e-w "┰"
0x2d, // 00110111 --S--eW- "┱"
0x26, // 00111000 --S--e-- "┎"
0x27, // 00111001 --S--e-w "┰"
0x27, // 00111010 --S--e-w "┰"
0x2d, // 00111011 --S--eW- "┱"
0x30, // 00111100 --S-E--- "┏"
0x31, // 00111101 --S-E--w "┲"
0x31, // 00111110 --S-E--w "┲"
0x34, // 00111111 --S-E-W- "┳"
0x08, // 01000000 -n------ "╵"
0x09, // 01000001 -n-----w "┘"
0x09, // 01000010 -n-----w "┘"
0x14, // 01000011 -n----W- "┙"
0x0a, // 01000100 -n---e-- "└"
0x0b, // 01000101 -n---e-w "┴"
0x0b, // 01000110 -n---e-w "┴"
0x15, // 01000111 -n---eW- "┵"
0x0a, // 01001000 -n---e-- "└"
0x0b, // 01001001 -n---e-w "┴"
0x0b, // 01001010 -n---e-w "┴"
0x15, // 01001011 -n---eW- "┵"
0x1c, // 01001100 -n--E--- "┕"
0x1d, // 01001101 -n--E--w "┶"
0x1d, // 01001110 -n--E--w "┶"
0x22, // 01001111 -n--E-W- "┷"
0x0c, // 01010000 -n-s---- "│"
0x0d, // 01010001 -n-s---w "┤"
0x0d, // 01010010 -n-s---w "┤"
0x16, // 01010011 -n-s--W- "┥"
0x0e, // 01010100 -n-s-e-- "├"
0x0f, // 01010101 -n-s-e-w "┼"
0x0f, // 01010110 -n-s-e-w "┼"
0x17, // 01010111 -n-s-eW- "┽"
0x0e, // 01011000 -n-s-e-- "├"
0x0f, // 01011001 -n-s-e-w "┼"
0x0f, // 01011010 -n-s-e-w "┼"
0x17, // 01011011 -n-s-eW- "┽"
0x1e, // 01011100 -n-sE--- "┝"
0x1f, // 01011101 -n-sE--w "┾"
0x1f, // 01011110 -n-sE--w "┾"
0x23, // 01011111 -n-sE-W- "┿"
0x0c, // 01100000 -n-s---- "│"
0x0d, // 01100001 -n-s---w "┤"
0x0d, // 01100010 -n-s---w "┤"
0x16, // 01100011 -n-s--W- "┥"
0x0e, // 01100100 -n-s-e-- "├"
0x0f, // 01100101 -n-s-e-w "┼"
0x0f, // 01100110 -n-s-e-w "┼"
0x17, // 01100111 -n-s-eW- "┽"
0x0e, // 01101000 -n-s-e-- "├"
0x0f, // 01101001 -n-s-e-w "┼"
0x0f, // 01101010 -n-s-e-w "┼"
0x17, // 01101011 -n-s-eW- "┽"
0x1e, // 01101100 -n-sE--- "┝"
0x1f, // 01101101 -n-sE--w "┾"
0x1f, // 01101110 -n-sE--w "┾"
0x23, // 01101111 -n-sE-W- "┿"
0x28, // 01110000 -nS----- "╽"
0x29, // 01110001 -nS----w "┧"
0x29, // 01110010 -nS----w "┧"
0x2e, // 01110011 -nS---W- "┪"
0x2a, // 01110100 -nS--e-- "┟"
0x2b, // 01110101 -nS--e-w "╁"
0x2b, // 01110110 -nS--e-w "╁"
0x2f, // 01110111 -nS--eW- "╅"
0x2a, // 01111000 -nS--e-- "┟"
0x2b, // 01111001 -nS--e-w "╁"
0x2b, // 01111010 -nS--e-w "╁"
0x2f, // 01111011 -nS--eW- "╅"
0x32, // 01111100 -nS-E--- "┢"
0x33, // 01111101 -nS-E--w "╆"
0x33, // 01111110 -nS-E--w "╆"
0x35, // 01111111 -nS-E-W- "╈"
0x08, // 10000000 -n------ "╵"
0x09, // 10000001 -n-----w "┘"
0x09, // 10000010 -n-----w "┘"
0x14, // 10000011 -n----W- "┙"
0x0a, // 10000100 -n---e-- "└"
0x0b, // 10000101 -n---e-w "┴"
0x0b, // 10000110 -n---e-w "┴"
0x15, // 10000111 -n---eW- "┵"
0x0a, // 10001000 -n---e-- "└"
0x0b, // 10001001 -n---e-w "┴"
0x0b, // 10001010 -n---e-w "┴"
0x15, // 10001011 -n---eW- "┵"
0x1c, // 10001100 -n--E--- "┕"
0x1d, // 10001101 -n--E--w "┶"
0x1d, // 10001110 -n--E--w "┶"
0x22, // 10001111 -n--E-W- "┷"
0x0c, // 10010000 -n-s---- "│"
0x0d, // 10010001 -n-s---w "┤"
0x0d, // 10010010 -n-s---w "┤"
0x16, // 10010011 -n-s--W- "┥"
0x0e, // 10010100 -n-s-e-- "├"
0x0f, // 10010101 -n-s-e-w "┼"
0x0f, // 10010110 -n-s-e-w "┼"
0x17, // 10010111 -n-s-eW- "┽"
0x0e, // 10011000 -n-s-e-- "├"
0x0f, // 10011001 -n-s-e-w "┼"
0x0f, // 10011010 -n-s-e-w "┼"
0x17, // 10011011 -n-s-eW- "┽"
0x1e, // 10011100 -n-sE--- "┝"
0x1f, // 10011101 -n-sE--w "┾"
0x1f, // 10011110 -n-sE--w "┾"
0x23, // 10011111 -n-sE-W- "┿"
0x0c, // 10100000 -n-s---- "│"
0x0d, // 10100001 -n-s---w "┤"
0x0d, // 10100010 -n-s---w "┤"
0x16, // 10100011 -n-s--W- "┥"
0x0e, // 10100100 -n-s-e-- "├"
0x0f, // 10100101 -n-s-e-w "┼"
0x0f, // 10100110 -n-s-e-w "┼"
0x17, // 10100111 -n-s-eW- "┽"
0x0e, // 10101000 -n-s-e-- "├"
0x0f, // 10101001 -n-s-e-w "┼"
0x0f, // 10101010 -n-s-e-w "┼"
0x17, // 10101011 -n-s-eW- "┽"
0x1e, // 10101100 -n-sE--- "┝"
0x1f, // 10101101 -n-sE--w "┾"
0x1f, // 10101110 -n-sE--w "┾"
0x23, // 10101111 -n-sE-W- "┿"
0x28, // 10110000 -nS----- "╽"
0x29, // 10110001 -nS----w "┧"
0x29, // 10110010 -nS----w "┧"
0x2e, // 10110011 -nS---W- "┪"
0x2a, // 10110100 -nS--e-- "┟"
0x2b, // 10110101 -nS--e-w "╁"
0x2b, // 10110110 -nS--e-w "╁"
0x2f, // 10110111 -nS--eW- "╅"
0x2a, // 10111000 -nS--e-- "┟"
0x2b, // 10111001 -nS--e-w "╁"
0x2b, // 10111010 -nS--e-w "╁"
0x2f, // 10111011 -nS--eW- "╅"
0x32, // 10111100 -nS-E--- "┢"
0x33, // 10111101 -nS-E--w "╆"
0x33, // 10111110 -nS-E--w "╆"
0x35, // 10111111 -nS-E-W- "╈"
0x36, // 11000000 N------- "╹"
0x37, // 11000001 N------w "┚"
0x37, // 11000010 N------w "┚"
0x3e, // 11000011 N-----W- "┛"
0x38, // 11000100 N----e-- "┖"
0x39, // 11000101 N----e-w "┸"
0x39, // 11000110 N----e-w "┸"
0x3f, // 11000111 N----eW- "┹"
0x38, // 11001000 N----e-- "┖"
0x39, // 11001001 N----e-w "┸"
0x39, // 11001010 N----e-w "┸"
0x3f, // 11001011 N----eW- "┹"
0x42, // 11001100 N---E--- "┗"
0x43, // 11001101 N---E--w "┺"
0x43, // 11001110 N---E--w "┺"
0x46, // 11001111 N---E-W- "┻"
0x3a, // 11010000 N--s---- "╿"
0x3b, // 11010001 N--s---w "┦"
0x3b, // 11010010 N--s---w "┦"
0x40, // 11010011 N--s--W- "┩"
0x3c, // 11010100 N--s-e-- "┞"
0x3d, // 11010101 N--s-e-w "╀"
0x3d, // 11010110 N--s-e-w "╀"
0x41, // 11010111 N--s-eW- "╃"
0x3c, // 11011000 N--s-e-- "┞"
0x3d, // 11011001 N--s-e-w "╀"
0x3d, // 11011010 N--s-e-w "╀"
0x41, // 11011011 N--s-eW- "╃"
0x44, // 11011100 N--sE--- "┡"
0x45, // 11011101 N--sE--w "╄"
0x45, // 11011110 N--sE--w "╄"
0x47, // 11011111 N--sE-W- "╇"
0x3a, // 11100000 N--s---- "╿"
0x3b, // 11100001 N--s---w "┦"
0x3b, // 11100010 N--s---w "┦"
0x40, // 11100011 N--s--W- "┩"
0x3c, // 11100100 N--s-e-- "┞"
0x3d, // 11100101 N--s-e-w "╀"
0x3d, // 11100110 N--s-e-w "╀"
0x41, // 11100111 N--s-eW- "╃"
0x3c, // 11101000 N--s-e-- "┞"
0x3d, // 11101001 N--s-e-w "╀"
0x3d, // 11101010 N--s-e-w "╀"
0x41, // 11101011 N--s-eW- "╃"
0x44, // 11101100 N--sE--- "┡"
0x45, // 11101101 N--sE--w "╄"
0x45, // 11101110 N--sE--w "╄"
0x47, // 11101111 N--sE-W- "╇"
0x48, // 11110000 N-S----- "┃"
0x49, // 11110001 N-S----w "┨"
0x49, // 11110010 N-S----w "┨"
0x4c, // 11110011 N-S---W- "┫"
0x4a, // 11110100 N-S--e-- "┠"
0x4b, // 11110101 N-S--e-w "╂"
0x4b, // 11110110 N-S--e-w "╂"
0x4d, // 11110111 N-S--eW- "╉"
0x4a, // 11111000 N-S--e-- "┠"
0x4b, // 11111001 N-S--e-w "╂"
0x4b, // 11111010 N-S--e-w "╂"
0x4d, // 11111011 N-S--eW- "╉"
0x4e, // 11111100 N-S-E--- "┣"
0x4f, // 11111101 N-S-E--w "╊"
0x4f, // 11111110 N-S-E--w "╊"
0x50, // 11111111 N-S-E-W- "╋"
}
var lineArtRunes = []rune{
' ', // 0x00
'╴', // 0x01
'╶', // 0x02
'─', // 0x03
'╷', // 0x04
'┐', // 0x05
'┌', // 0x06
'┬', // 0x07
'╵', // 0x08
'┘', // 0x09
'└', // 0x0a
'┴', // 0x0b
'│', // 0x0c
'┤', // 0x0d
'├', // 0x0e
'┼', // 0x0f
'╸', // 0x10
'╾', // 0x11
'┑', // 0x12
'┭', // 0x13
'┙', // 0x14
'┵', // 0x15
'┥', // 0x16
'┽', // 0x17
'╺', // 0x18
'╼', // 0x19
'┍', // 0x1a
'┮', // 0x1b
'┕', // 0x1c
'┶', // 0x1d
'┝', // 0x1e
'┾', // 0x1f
'━', // 0x20
'┯', // 0x21
'┷', // 0x22
'┿', // 0x23
'╻', // 0x24
'┒', // 0x25
'┎', // 0x26
'┰', // 0x27
'╽', // 0x28
'┧', // 0x29
'┟', // 0x2a
'╁', // 0x2b
'┓', // 0x2c
'┱', // 0x2d
'┪', // 0x2e
'╅', // 0x2f
'┏', // 0x30
'┲', // 0x31
'┢', // 0x32
'╆', // 0x33
'┳', // 0x34
'╈', // 0x35
'╹', // 0x36
'┚', // 0x37
'┖', // 0x38
'┸', // 0x39
'╿', // 0x3a
'┦', // 0x3b
'┞', // 0x3c
'╀', // 0x3d
'┛', // 0x3e
'┹', // 0x3f
'┩', // 0x40
'╃', // 0x41
'┗', // 0x42
'┺', // 0x43
'┡', // 0x44
'╄', // 0x45
'┻', // 0x46
'╇', // 0x47
'┃', // 0x48
'┨', // 0x49
'┠', // 0x4a
'╂', // 0x4b
'┫', // 0x4c
'╉', // 0x4d
'┣', // 0x4e
'╊', // 0x4f
'╋', // 0x50
}
# Hello friends.
#
# This is a Perl script that reads runes.txt on
# standard input and produces runes.go on standard
# output.
# This script contains the tables necessary
# for rendering line art based on a byte map
# describing the thickness of each line.
#
# Line art has four possible edges and two possible
# weights: light and heavy.
# We denote these edges as north, south, east,
# and west, and capture two bits of information
# for each direction to indicate whether the
# corresponding line should be absent, light, or
# heavy.
# Since we have a domain of four possible input
# values and three possible representations,
# we use light lines to represent the middle 50% of
# the range, so heavy and absent represent outliers.
#
# For a one byte representation with the bits
# "NnSsEeWw", we construct a number in [0, 4) where:
# - 00 indicates absence.
# - 01 and 10 both indicate light lines.
# - 11 indicates a heavy line.
# Consequently, there are 256 possible
# inputs and 80 possible runes.
#
# runes.go captures two tables: one for the 80 runes,
# and another for the 256 possible input states and
# the indexes of the corresponding runes in the rune
# table.
#
# Each entry in runes.txt describes each of the 80
# runes and is of the form "N-S--e-w ╂" for every line
# art unicode rune annotated by whether each edge
# (north, south, east, west) is present, light, or
# heavy.
# Dash indicates absence.
# Miniscules indicate light.
# Majuscules indicate heavy.
#
# Like all Perl scripts, it is an expedient but
# heinous abomination.
my %table;
my %glyphs;
my %hints;
my $num = 0;
for (<>) {
chomp;
my $offset = $num++;
my ($bits, $glyph) = split ' ';
$glyphs[$offset] = $glyph || ' ';
$hints[$offset] = $bits;
my ($N, $n, $S, $s, $E, $e, $W, $w) = map {
$_ ne '-' || 0;
} split '', $bits;
my @ns = $N ? (3) : $n ? (1, 2) : ();
my @dims = map {
my ($big, $small) = @$_;
[$big ? ("11") : $small ? ("10", "01") : ("00")];
} ([$N, $n], [$S, $s], [$E, $e], [$W, $w]);
my @combos = ('');
for my $dim (@dims) {
@combos = map {
my $head = $_;
map {
$head . $_;
} @$dim;
} @combos;
}
for my $address (map {
unpack "C", pack "B[8]", $_;
} @combos) {
$table[$address] = $offset;
}
}
printf "package main\n";
printf "\n";
printf "var lineArtRuneOffsets = []uint8{\n";
printf "\t// Index NnSsEeWs NnSsEeWw Rune\n";
for my $address (0..255) {
my $offset = $table[$address];
my $glyph = $glyphs[$offset];
my $hint = $hints[$offset];
printf "\t0x%02x, // %08b %s \"%s\"\n", $offset, $address, $hint, $glyph;
}
printf "}\n";
printf "\n";
printf "var lineArtRunes = []rune{\n";
for my $offset (0..80) {
printf "\t'%s', // 0x%02x\n", $glyphs[$offset], $offset;
}
printf "}\n";
--------
-------w ╴
-----e-- ╶
-----e-w ─
---s---- ╷
---s---w ┐
---s-e-- ┌
---s-e-w ┬
-n------ ╵
-n-----w ┘
-n---e-- └
-n---e-w ┴
-n-s---- │
-n-s---w ┤
-n-s-e-- ├
-n-s-e-w ┼
------W- ╸
-----eW- ╾
---s--W- ┑
---s-eW- ┭
-n----W- ┙
-n---eW- ┵
-n-s--W- ┥
-n-s-eW- ┽
----E--- ╺
----E--w ╼
---sE--- ┍
---sE--w ┮
-n--E--- ┕
-n--E--w ┶
-n-sE--- ┝
-n-sE--w ┾
----E-W- ━
---sE-W- ┯
-n--E-W- ┷
-n-sE-W- ┿
--S----- ╻
--S----w ┒
--S--e-- ┎
--S--e-w ┰
-nS----- ╽
-nS----w ┧
-nS--e-- ┟
-nS--e-w ╁
--S---W- ┓
--S--eW- ┱
-nS---W- ┪
-nS--eW- ╅
--S-E--- ┏
--S-E--w ┲
-nS-E--- ┢
-nS-E--w ╆
--S-E-W- ┳
-nS-E-W- ╈
N------- ╹
N------w ┚
N----e-- ┖
N----e-w ┸
N--s---- ╿
N--s---w ┦
N--s-e-- ┞
N--s-e-w ╀
N-----W- ┛
N----eW- ┹
N--s--W- ┩
N--s-eW- ╃
N---E--- ┗
N---E--w ┺
N--sE--- ┡
N--sE--w ╄
N---E-W- ┻
N--sE-W- ╇
N-S----- ┃
N-S----w ┨
N-S--e-- ┠
N-S--e-w ╂
N-S---W- ┫
N-S--eW- ╉
N-S-E--- ┣
N-S-E--w ╊
N-S-E-W- ╋
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment