The Drunken Bishop
Dyalog APL (178)
{⎕ML←3⋄F←9 17⍴0⋄5 9{(⍺⌷F)+←1⋄×⍴⍵:(1 1⌈9 17⌊⍺-1 1-2×↑⍵)∇1↓⍵⋄(⍺⌷F)←16⋄F[5;9]←15⋄K⍪(M,' .o+=*BOX@%&#/^SE'[1+F],M←'|')⍪K←'+','+',⍨17⍴'-'}⊃,/{↓⊖4 2⍴⍉(4/2)⊤¯1+⍵⍳⍨⎕D,'abcdef'}¨⍵⊂⍨':'≠⍵}
This is a function that takes the string as its right argument, and returns a character matrix containing the ASCII art representation, e.g.:
F←{⎕ML←3⋄F←9 17⍴0⋄5 9{(⍺⌷F)+←1⋄×⍴⍵:(1 1⌈9 17⌊⍺-1 1-2×↑⍵)∇1↓⍵⋄(⍺⌷F)←16⋄F[5;9]←15⋄K⍪(M,' .o+=*BOX@%&#/^SE'[1+F],M←'|')⍪K←'+','+',⍨17⍴'-'}⊃,/{↓⊖4 2⍴⍉(4/2)⊤¯1+⍵⍳⍨⎕D,'abcdef'}¨⍵⊂⍨':'≠⍵}
F '16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48'
+-----------------+
| . |
| + . |
| . B . |
| o * + |
| X * S |
| + O o . . |
| . E . o |
| . . o |
| . . |
+-----------------+
F 'b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b'
+-----------------+
| o.o |
| .= E.|
| .B.o|
| .= |
| S = .|
| . o . .= |
| . . . oo.|
| . o+|
| .o.|
+-----------------+
Explanation:
⎕ML←3
: set⎕ML
to3
. This makes⊂
more useful for splitting strings.F←9 17⍴0
: make a 17-by-9 matrix of zeroes.F
represents how many times each position has been visited.⍵⊂⍨':'≠⍵
: split⍵
on:
characters.{
...}¨
: for each group:¯1+⍵⍳⍨⎕D,'abcdef'
: find the index of each character in the string'01234567890abcdef'
. Subtract 1, because APL is 1-indexed by default.(4/2)⊤
: convert the values to their 4-bit representations (there should now be 2-by-4 matrix).↓⊖4 2⍴⍉
: rotate the matrix, use the elements to fill a 2-by-4 matrix instead, mirror that matrix horizontally, and then get each line separately. This gives us the 4 2-bit values we need.
⊃,/
: join the resulting lists together, giving a list of 2-bit steps.5 9{
...}
: given the list of steps, and starting at position [9,5]:(⍺⌷F)+←1
: increment the current position inF
.×⍴⍵:
: if the list of steps is not empty:↑⍵
: take the first step from the list⍺-1 1-2×
: get the delta for that step, and subtract it from the current position1 1⌈9 17⌊
: restrict movement to within the field(
...)∇1↓⍵
: continue with the new position and the rest of the steps
- If it is empty:
(⍺⌷F)←16
: setF
to 16 at the final positionF[5;9]←15
: setF
to 15 at the start position' .o+=*BOX@%&#/^SE'[1+F]
: map each position to the corresponding characterK⍪(M,
...,M←'|')⍪K←'+','+',⍨17⍴'-'
: wrap the result in lines
Perl, 300 + 1 (-n) = 301 bytes
perl -ne 'sub b{$b=$_[0]+$_[1];$_[0]=$b<0?0:$b>$_[2]?$_[2]:$b}$v=pack"(H2)*",/\w\w/g;($x,$y)=(8,4);$a[b($y,($_&2)-1,8)*17+b($x,($_&1)*2-1,16)]++for map{vec$v,$_,2}0..63;@a[76,$y*17+$x]=(15,16);$c=" .o+=*BOX@%&#/^SE";print$d="+".("-"x17)."+\n",(map{+"|",(map{substr$c,$_,1}@a[$_*17..($_+1)*17-1]),"|\n"}0..8),$d'
This answer is disgusting, but it's also the first one for this puzzle, so it'll do for now.
-n
to take a line of input on STDIN and fill $_
.
# b($v, -1 or 1, max) modifies $v within 0..max
sub b{$b=$_[0]+$_[1];$_[0]=$b<0?0:$b>$_[2]?$_[2]:$b}
# turn $_ into a binary string
$v=pack"(H2)*",/\w\w/g;
# initialize cursor
($x,$y)=(8,4);
# find an element of single-dimensional buffer @a
$a[
# y += (bitpair & 2) - 1, within 8
b($y,($_&2)-1,8) * 17
# x += (bitpair & 1) * 2 - 1, within 17
+ b($x,($_&1)*2-1,16)
# and increment it
]++
# for each bit pair (in the right order!)
for map{vec$v,$_,2}0..63;
# overwrite the starting and ending positions
@a[76,$y*17+$x]=(15,16);
# ascii art lookup table
$c=" .o+=*BOX@%&#/^SE";
# output
print
# the top row, saving it for later
$d="+".("-"x17)."+\n",
# each of the eight middle rows
(map{+
# converting each character in @a in this row as appropriate
"|",(map{substr$c,$_,1}@a[$_*17..($_+1)*17-1]),"|\n"
}0..8),
# the bottom row
$d
R, 465 459 410 393 382 357 bytes
f=function(a){s=strsplit;C=matrix(as.integer(sapply(strtoi(el(s(a,":")),16),intToBits)[1:8,]),2);C[!C]=-1;n=c(17,9);R=array(0,n);w=c(9,5);for(i in 1:64){w=w+C[,i];w[w<1]=1;w[w>n]=n[w>n];x=w[1];y=w[2];R[x,y]=R[x,y]+1};R[]=el(s(" .o+=*BOX@%&#/^",""))[R+1];R[9,5]="S";R[x,y]="E";z="+-----------------+\n";cat(z);for(i in 1:9)cat("|",R[,i],"|\n",sep="");cat(z)}
With indentations and newlines:
f=function(a){
s=strsplit
C=matrix(as.integer(sapply(strtoi(el(s(a,":")),16),intToBits)[1:8,]),2)
C[!C]=-1
n=c(17,9)
R=array(0,n)
w=c(9,5)
for(i in 1:64){
w=w+C[,i]
w[w<1]=1
w[w>n]=n[w>n]
x=w[1]
y=w[2]
R[x,y]=R[x,y]+1
}
R[]=el(s(" .o+=*BOX@%&#/^",""))[R+1]
R[9,5]="S"
R[x,y]="E"
z="+-----------------+\n"
cat(z)
for(i in 1:9)cat("|",R[,i],"|\n",sep="")
cat(z)
}
Usage:
> f("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48")
+-----------------+
| . |
| + . |
| . B . |
| o * + |
| X * S |
| + O o . . |
| . E . o |
| . . o |
| . . |
+-----------------+
> f("37:e4:6a:2d:48:38:1a:0a:f3:72:6d:d9:17:6b:bd:5e")
+-----------------+
| |
| |
| . |
| . o |
|o . o . S + |
|.+ + = . B . |
|o + + o B o E |
| o . + . o |
| .o |
+-----------------+