text:
Let's make a map of dungeon
Long time ago, when I was spending more time playing RPG, one of the issues what some players had, was to track party movement and to draw proper map.
So I come with idea, to check how you guys come deal with this issue.
Task is to write a function, which takes as input parameter list of directions (passed as structure of your choice) ^v<>, display map of dungeon.
In example for input: >>>vvv<<<^^^ output will be:
+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+

Testcases
>>>>>>vvvvv<<<<^^^>>v

 +-------+
 |       |
 +-+---+ |
   |   | |
   | + | |
   | +-+ |
   |     |
   +-----+

^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^

          +-+
       +-+| | +-++-+
       | || | | ++ ++
       | ++ +-+     |
       |        +-+ |
       +--+ +-+ +-+-+
          | | |   |
          +-+ +---+

As it is golf code challenge, shortest code wins.
Happy golfing.
EDIT
Sorry for late edit, I didn't have much time recently.
Map is generated based on movement.  It should contain only corridors which were visited during walk. Hence creating one big room won't be a valid answer.
There are three valid symbols in the map:

| vertical wall
| horizontal wall
+ intersection of vertical and horizontal wall.

Maximum length of the path is 255 character (but if you can, do not limit yourself).
More test cases:
 ><><><><

 +--+
 |  |
 +--+

 >^<v

 +--+
 |  |
 |  |
 +--+

I hope now everything is clear.

You need to provide a description of the task. The two test cases aren't even handled in a way that appears consistent -- the first adds a disconnected region for no apparent reason.

Your second example has a closed-off room, which I initially thought was because the outer border should be rectangular, but then the third example disproves that idea. Please use the Sandbox to get feedback on a challenge before posting.

@feersum sorry about that, it's fixed now

@El'endiaStarman that was my mistake, sorry about that.

Excellent. I'd still suggest being explicit about how the dungeon is constructed from the movements.

What do you mean by "display map"? Is returning the map from a function allowed?

Any limits to input length or map size? Any rules on spacing (e.g. why does the second example have extra space on the left or is it an error)? I'm sure we each see the problem as straight-forward but still these details can avoid even innocent technicalities.

Is this challenge to generate the minimal floor-space dungeon that contains the movements? IE- The generated dungeon can't just be 1 giant room?

This looks interesting. Any chance of editing to get it re-opened? Things to look at in particular: from the examples, it looks like you don't mind extra whitespace around the output but it would be good to clarify. Also if you explicitly describe the wall appearance and answer milk's question it should make the question sufficiently clear. One thing I think you haven't covered is what output vvv>>^^^<< would produce (crosses? pipes?)

@Dave I edited this question, and i hope i cleared everything.

I think @Dave is still onto something, when do you have to use |/- over +? Can a corner be formed by two +s instead of one? Can an intersection be a - next to a | instead of a + next to either? etc. Unfortunately I can't layout these things in a comment.

How much spurious whitespace at all sides of the dungeon is allowed ? Several of your examples have unnecessary whitespace

@TonHospel i might miss something, but tell me in which example you have unnecessary white space?

@user902383 The ^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^ example is indented more to the right than the example above. The number of lines between the control string and the map is also different.

Javascript (ES6), 261 254 243 bytes
s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=`
`));return z}

JSFiddle

You can remove the return by replacing the ; with , and the {} with ()

@Cyoce - There's a for loop in there which cannot be embedded that way.

then replace the { with eval(" and } with ") to remove the return http://codegolf.stackexchange.com/a/80967/41042

@Cyoce - Unfortunately, I think I'd need to escape the literal linebreak as '\\n' if I do so. If I count correctly, that actually leads to +1 byte. Or is there a better way to embed the linebreak in the eval?

You would only need \n since template strings support literal new lines, but that would still leave it at the same byte count. Oh well

C, 246 bytes
n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}

Takes input as separate characters, for example:
./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'

Or more conveniently, this (intentionally unquoted!) format:
./mapper $(echo '>>>vvv<<<^^^' | fold -w1)

Or for (pretty inefficient) random input:
./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)

And finally, using awk to crop the result means we can get much bigger:
./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'

 +-----+
 |     |
 |     +-+  +-----+
 |       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
 +-+               +--+
 |     ++             |
 +-+  +-++           +-+
   ++   |+--+          |
    +-+ | |        ++  |
     ++ | ++   + +--+ ++
     |  |  +---|      |
     |  |     ++  +---+
     ++ |-+   |   |
      | | +--+-+  |
      | +    +    |
      |        +--+
      +--------+

Outputs to stdout. Uses the fact that padding is allowed around the map (produces a map which has edge length 2*n+1, putting the final position in the middle).
Breakdown
This works by looping over the arguments in reverse and moving in reverse. It actually uses the fact that arg 0 is the program name; it doesn't matter what the name is, but it allows us to visit both the initial and last cell (as well as all cells in-between) without needing special handling.
n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
    for(                            // Step 1: identify visited cells
        n=c*2+3,                    //  Set output grid size
        g=calloc(n*n,8),            //  Allocate map storage space
        p=g+(n+1)*(c+1);            //  Start at centre
        c--;                        //  Loop over directions in reverse
        y=*v[c],                    //  Get current direction
        p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
    )*p=1;                          //  Mark cell visited
    for(y=n-1;--y;)                 // For each row (except edges)
        for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
            putchar(c?" |-++|-+"[   //   Print wall using lookup table
                *p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
            ]:10)                   //   Or newline
        )p=g+y*n+c;                 //   Set current cell (happens first)
}

236 bytes


text:
Count the Bytes!
Challenge
Write a program which takes the URL of a PPCG answer as input and outputs the length of the answer's first code block in bytes.
Code Blocks
There are three different ways of formatting code blocks:
Four spaces before the code (- represents a space, here)
----Code goes here

Surrounding the code in
 tags:

Code goes here

or:

Code goes here

Surrounding the code in
 tags (in that order):

Code goes here

Rules
You should only use the first code block in answer. Assume that the supplied answer will always have a code block.
You must find the length of the answer in bytes, not any other metric such as characters.
Solutions using the Stack Exchange Data Explorer or the Stack Exchange API are allowed. URL shorteners are disallowed.
Assume all programs use UTF-8 encoding.
Examples
Input:  https://codegolf.stackexchange.com/a/91904/30525
Output: 34

Link

Input:  https://codegolf.stackexchange.com/a/91693/30525
Output: 195

Link

Input:  https://codegolf.stackexchange.com/a/80691/30525
Output: 61

Link
Note: Despite what the answer may say, due to APL using a different encoding, 33 bytes isn't its UTF-8 byte count
Winning
The shortest code in bytes wins.

So no scraping the header?

@muddyfish Nope (note the third example)

Some languages use a custom character encoding, different than UTF-8 (I'm pretty sure that's what happens in the APL answer). So the byte count depends on each language's default encoding. I think it may be better for the challenge to ask for character count rather than byte count

@LuisMendo I see, I'll specify UTF-8 then

For example 2 I can only find 195 bytes. It looks like the 199 to 196 edit actually removed 4 bytes, not 3. Am I missing something?

Identation is meaningful in
 tags, and so are newlines in  tags, so your Code goes here examples have three different lengths. If that's intentional, it should be mentioned.

@Dennis I've now removed the indentation

But not the newlines. Both newlines in
\nCode goes here\n
 count. However, they don't count in
\nCode goes here\n

@Dennis Oh, I didn't know that :P

jQuery JavaScript, 97 Bytes
console.log((new Blob([$("#answer-"+location.hash.substr(1)+" code").eq(0).text().trim()])).size)

old version 151 Bytes
s=$('#answer-'+location.hash.substr(1)+' code').eq(0).text().trim();c=0;for(i=s.length;i--;)d=s.charCodeAt(i),c=d<128?c+1:d<2048?c+2:c+3;console.log(c)

old version 163 Bytes
s=$('#answer-'+location.hash.substr(1)+' code').first().text().trim();c=0;for(i=0;i<s.length;i++){d=s.charCodeAt(i);c=(d<128)?c+1:(d<2048)?c+2:c+3;}console.log(c);

input ist location and jQuery is active on the site

Move the c=0 into the for, to save a byte. for(c=i=0;i<s.lengh;i++)

And remove the ; before and after the console.log(c).

@PaulSchmitz Thank You. I prefer to use a while loop instead of your proposal.

s=$("#answer-"+location.hash.substr(1)+" code").eq(0).text().trim();c=0;for(i=s.length;i--;)d=s.charCodeAt(i),c=128>d?c+1:2048>d?c+2:c+3;console.log(c) is 5 bytes shorter. 4 for removing () around the conditions, and 1 by replacing while with for.

C#, 249 270 bytes
u=>{var c=new System.Net.Http.HttpClient().GetStringAsync(u).Result;var i=c.IndexOf("de>",c.IndexOf('"'+u.Split('/')[4]))+3;return System.Text.Encoding.UTF8.GetByteCount(c.Substring(i,c.IndexOf("<",i)-i-1).Replace(">",">").Replace("<","<").Replace("&","&"));};

I've made some assumptions based on observations of the HTML of pages. Hopefully they hold true for all answer posts.
+21 bytes to unencode & to &. My answer failed to count it's own bytes. ;P
Ungolfed:
/*Func<string, int> Lambda =*/ u =>
{
    // Download HTML of the page.
    // Although new System.New.WebClient().DownloadString(u) looks shorter, it doesn't
    // preserve the UTF8 encoding.
    var c = new System.Net.Http.HttpClient().GetStringAsync(u).Result;

    // Using the answer id from the URL, find the index of the start of the code block.
    // Empirical observation has found that all code blocks are in  tags,
    // there are no other HTML tags that end with "de>",
    // and that '>' and '<' are encoded to '>'/'<' so no jerk can put "de>"
    // before the first code block.
    var i = c.IndexOf("de>", c.IndexOf('"' + u.Split('/')[4])) + 3;

    // Get the substring of the code block text, unencode '>'/'<'/'&' and get the byte count.
    // Again, empirical observation shows the closing  tag is always on a new
    // line, so always remove 1 character when getting the substring.
    return System.Text.Encoding.UTF8.GetByteCount(c.Substring(i, c.IndexOf("<", i) - i - 1).Replace(">", ">").Replace("<", "<")..Replace("&", "&"));
};

Results:
Input:  http://codegolf.stackexchange.com/a/91904/30525
Output: 34

Input:  http://codegolf.stackexchange.com/a/91693/30525
Output: 195 (at the time of this answer the first post has 196, but I can't find the 196th
byte, even counting by hand, so assuming 195 is correct)

Input:  http://codegolf.stackexchange.com/a/80691/30525
Output: 61

Input:  http://codegolf.stackexchange.com/a/91995/58106 (this answer)
Output: 270

I find 195 Bytes too

Thanks, I've edited the question and my answer with 195 bytes

Java 7, 314 313 bytes
int c(String u)throws Exception{String x="utf8",s=new java.util.Scanner(new java.net.URL(u).openStream(),x).useDelimiter("\\A").next();int j=s.indexOf("de>",s.indexOf('"'+u.split("/")[4]))+3;return s.substring(j,s.indexOf("<",j)-1).replace(">",">").replace("<","<").replace("&","&").getBytes(x).length;}

Shamelessly stolen from @milk's C# answer and ported to Java 7.
NOTE: This assumes all code is in  blocks. Currently it won't work with just
 tags (but who uses those anyway?.. ;p).
Ungolfed & test cases:
class M{
  static int c(String u) throws Exception{
    String x = "utf8",
           s = new java.util.Scanner(new java.net.URL(u).openStream(), x).useDelimiter("\\A").next();
    int j = s.indexOf("de>", s.indexOf('"'+u.split("/")[4])) + 3;
    return s.substring(j, s.indexOf("<", j) - 1).replace(">", ">").replace("<", "<").replace("&", "&")
        .getBytes(x).length;
  }

  public static void main(String[] a) throws Exception{
    System.out.println(c("https://codegolf.stackexchange.com/a/91904/30525"));
    System.out.println(c("https://codegolf.stackexchange.com/a/91693/30525"));
    System.out.println(c("https://codegolf.stackexchange.com/a/80691/30525"));
    System.out.println(c("https://codegolf.stackexchange.com/a/91995/58106"));
  }
}

Output:
34
195
61
270

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Scan dactylic hexameter in a unique puzzle
As a terrible Latin student for several years I have learned to hate many things about Latin.  However there is one thing I love.
Latin scansion.
Scansion is the act of determining the meter of a particular line of poetry.  For Latin this means demarcating each syllable in the line as "light" or "heavy".
In Latin scansion has many of rules.  However unlike English Latin scansion is fairly regular and often requires no knowledge of Latin vocabulary or grammar to be performed.  For this problem we will be using simplified subset of those rules (real Latin does not have a neat spec).
Before you begin the scansion you must elide. Elision is the dropping syllables between words to ease pronunciation. (e.g. "he is" -> "he's"). Unlike English, Latin elision follows very nice rules.

The final vowel of a word ending with a vowel is omitted if the next word begins with a vowel.
NAUTA EST -> NAUTEST
The same goes for words ending in a vowel followed by "m".
FIDUM AGRICOLAM -> FIDAGRICOLAM
Word-initial "h" followed by a vowel counts as a single vowel for elision purposes and is always dropped when elided.
MULTAE HORAE -> MULTORAE
or
MULTAM HORAM -> MULTORAM

After elision we can begin scansion.  Scansion is done to a specific meter.  The meter for this challenge is dactylic hexameter.  Dactylic hexameter has six "feet" each foot consists of two or three syllables.  Syllables can be either long or short depending on the vowel.  Each of the first five feet will be either a dactyl, a long syllable followed by two short ones, or a spondee, two long syllables. And the last foot will be a long followed by an anceps (short or long, for this problem you will not have to determine which).

A vowel in latin can be either short or long
An "i" sandwiched between two vowels (e.g. eiectum) is a consonant. (i.e. a "j")
An "i" beginning a word followed by a vowel (e.g Iactus) is also a consonant
A "u" after a "q" is also a consonant (i.e. a "v")
Diphthongs (ae, au, ei, eu, oe, and ui) are made up of two vowels but count as one vowel and are always long
A vowel with two or more consonants between it and the next vowel is always long
For the previous rule an "l" or an "r" after a "b","c","d","g","p", or "t" does not count as a consonant
"x" counts as two consonants
"ch", "ph", "th", and "qu" count as one consonant
The syllable "que" at the end of a word (after elision) is always short
If a vowel is not forced by one of the previous rules it can be either long or short this will depend on the meter

Your task will be to take a line of latin and produce the scansion of it.  You will take in the line as string via standard input and output a string representing the final scansion.
The input will contain only spaces and characters A-Z.
To represent the scansion you will output all of the syllables with | demarcating the separation of feet.  A long syllable will be represented by a - while a short syllable will be marked by a v and an anceps (the last syllable of every line) will be marked by a x.  If there are multiple solutions as there often will be you may output anyone of them.
Test Cases
The start of Virgil's Aeneid.
 ARMA VIRUMQUE CANO TROIAE QUI PRIMUS AB ORIS     -> -vv|-vv|--|--|-vv|-x (or -vv|-vv|--|-vv|--|-x)
 ITALIAM FATO PROFUGUS LAVINIAQUE VENIT           -> -vv|--|-vv|-vv|-vv|-x
 LITORA MULTUM ILLE ET TERRIS IACTATUS ET ALTO    -> -vv|--|--|--|-vv|-x
 VI SUPERUM SAEVAE MEMOREM IUNONIS OB IRAM        -> -vv|--|-vv|--|-vv|-x (or -vv|--|-vv|-vv|--|-x)
 MULTA QUOQUE ET BELLO PASSUS DUM CONDERET URBEM  -> -vv|--|--|--|-vv|-x
 INFERRETQUE DEOS LATIO GENUS UNDE LATINUM        -> --|-vv|-vv|-vv|-vv|-x
 ALBANIQUE PATRES ATQUE ALTAE MOENIA ROMAE        -> --|-vv|--|--|-vv|-x

Further stipulations
In the proper fashion of Latin poetry all answers must begin with an invocation to the muses.
Latin has only two one letter words "e" and "a".  You may assume that no other one letter words will appear as input.

Oh god this brings back memories...

An "i" proceeding another vowel is a consonant (i.e. a "j"). In Lavinjaque (--vv) it is, but in Italiam (-vv-) in the same verse it isn't. Maybe put Js in the input? Do you actually have a working solution generating this output?

Oh, the penultimate foot is always a dactyl, classically. You should specify whether answers can assume so.

@Lynn Since the penultimate foot is not always a dactyl I have intentionally left it ambiguous.  It may be either.

@Dave 1) yes you are right 2) It must end the entire word.  I will fix these shortly

How does "QUI" parse? must the "I" vowel be long? or to put it another way, does rule 4/9 on the "QU" mean that rule 5 on the "UI" does not apply?

@Dave "QUI" can be long or short. Rule 5 does not apply.

sed, 402 392 374 359 363 334 333 bytes

“Sing, goddess, the anger of Peleus’ son Achilleus
  and its devastation, which put pains thousandfold upon the Achians,
  hurled in their multitudes to the house of Hades strong souls
  of heroes, but gave their bodies to be the delicate feasting
  of dogs, of all birds, and the will of Zeus was accomplished
  since that time when first there stood in division of conflict
  Atreus’ son the lord of men and brilliant Achilleus.”

— Homer (The Iliad); confused why this quote is here? check the rules.
sed -E 's/[AEIOU]M? H?([AEIOU])/\1/g;s/X/cc/g;s/(^|[ AEIOU])I([AEIOU])/\1c\2/g;s/QUE( |$)/cv/g;s/A[EU]|E[IU]|OE|UI/-/g;s/[CPT]H|[BCDGPT][LR]|QU|[^-vAEIOU ]/c/g;s/ //g;s/ucc+/-/g;s/c//g;s/^[-u]([-u]|[vu]{2})[-u]([-u]|[vu]{2})[-u]([-u]|[vu]{2})[-u]([-u]|[vu]{2})[-u]([-u]|[vu]{2})[-u].$/-\1|-\2|-\3|-\4|-\5|-x/;s/[uv]/-/g;s/---/-vv/g'

Not exactly golfed, but this implements all the given rules in the form of regular expressions, which sed just runs one-by-one to reach the solution. This handles each line independently, so can process an entire multi-line input.
Usage:
printf 'ARMA VIRUMQUE CANO TROIAE QUI PRIMUS AB ORIS
ITALIAM FATO PROFUGUS LAVINIAQUE VENIT
LITORA MULTUM ILLE ET TERRIS IACTATUS ET ALTO
VI SUPERUM SAEVAE MEMOREM IUNONIS OB IRAM
MULTA QUOQUE ET BELLO PASSUS DUM CONDERET URBEM
INFERRETQUE DEOS LATIO GENUS UNDE LATINUM
ALBANIQUE PATRES ATQUE ALTAE MOENIA ROMAE' | sed -E '<...>';

Breakdown:
sed -E "
# Apply Elision
 s/[AEIOU]M? H?([AEIOU])/\1/g;

# Convert into vowels (u, v or -) and consonants (c) according to the rules given
 s/X/cc/g;
 s/(^|[ AEIOU])I([AEIOU])/\1c\2/g;
 s/QUE( |\$)/cv/g;
 s/A[EU]|E[IU]|OE|UI/-/g;
 s/[CPT]H|[BCDGPT][LR]|QU|[^-vAEIOU ]/c/g;
 s/[A-Z]/u/g; # all remaining vowels are unknown

# Remove all spaces
 s/ //g;

# A vowel followed by 2 consonants before the next vowel is long
# (and we don't care if the last vowel is long or short)
 s/ucc+/-/g;

# Remove all consonants
 s/c//g;

# Look for a matching dactylic hexameter and insert pipe separators
 s/^\
[-u]([-u]|[vu]{2})\
[-u]([-u]|[vu]{2})\
[-u]([-u]|[vu]{2})\
[-u]([-u]|[vu]{2})\
[-u]([-u]|[vu]{2})\
[-u].\$/-\1|-\2|-\3|-\4|-\5|-x/;

# Substitute identified feet with the necessary long/short vowels
 s/[uv]/-/g;
 s/---/-vv/g
"

Results for test cases:
-vv|-vv|--|--|-vv|-x
-vv|-vv|--|-vv|-vv|-x
-vv|--|--|--|-vv|-x
-vv|--|-vv|-vv|--|-x
-vv|--|--|--|-vv|-x
--|-vv|-vv|-vv|-vv|-x
--|-vv|--|--|-vv|-x

Worth noting that I get different results for test cases 2 & 3, which appear to be alternative solutions not included in the question. Could be that I misinterpreted a rule though.

I don't think your scansion for test case 2 works.  The last "U" in "PROFUGUS" must be long because there are two consonants ("S" and "L") before the next vowel.  In your scansion you have it short.  I am checking the third one now.  Nice answer anyway :)

@WheatWizard ah ok, that was a rule I was wondering about (should have asked) — I took it to mean 2 consonants without spaces. Easy enough to fix. I'll post an update soon.

Looks like I also had a bug where vccvccv would become -?? instead of --? — fixed now. Looks like it agrees with your samples on all but case #2 now.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Mirror, Mirror, in the Code
Two-dimensional programming languages often have mirror commands like / and \ to redirect the instruction pointer on the grid:
>>>>\
    v
    v
<<<</

In this challenge, you're given an incoming direction and a mirror and you need to determine the outgoing direction.
Rules
The incoming direction will be given as one of the characters NESW and the mirror will be given as either / or \. You may receive these in any order. You must use uppercase letters.
You may take input in any convenient format, including a two-character string, a string using some separator between the characters, a pair of characters in a list, or even a pair of singleton strings. If you do use a string with separator, the separator cannot use any of the characters NWSE\/.
Output should be a character from NESW or single-character string.
You may write a program or a function and use any of the our standard methods of receiving input and providing output.
You may use any programming language, but note that these loopholes are forbidden by default.
This is code-golf, so the shortest valid answer – measured in bytes – wins.
Test Cases
There are only 8 possible inputs you need to handle, so there is no excuse for not testing your code on all of them:
N /   -->   W
N \   -->   E
E /   -->   S
E \   -->   N
S /   -->   E
S \   -->   W
W /   -->   N
W \   -->   S

In languages where backslashes must be escaped on input, are we allowed to assume the input will be "\" where appropriate?

@JDL The actual string (or character) should contain a single \. If your answer is a function submission that takes a string, then of course you'll need \\ in the source code to call it correctly, but if you're reading your input from standard input, for instance, then it should be a single \. In other words, if you call your language's respective string-length function on the input, the result should always be the same, regardless of whether the input contains / or \.

Alright, I was expecting R to have problems when an unescaped "" was entered via stdin, but readline() can handle it.

@JDL You probably need to enter the string escaping (duplicating) that symbol, but the resulting string will be "N"

Python, 40 38 bytes
-2 bytes thanks to @MitchSchwartz (ord(d)+ord(m))%8 -> ord(d)+ord(m)&7
lambda d,m:' NESSWNW'[ord(d)+ord(m)&7]

plain lookup of answer in a list (AKA string) indexed by the smallest mod of the sum of ordinals that works.
Test cases are on ideone

Dangit, I thought I was being super clever taking the ASCII values, summing them, %8 them, and doing an index. Then I see you posted the same solution over an hour ago. Hah. Have a +1.

Python 2, 40 bytes
lambda c,m,k="NWES":k[k.find(c)^(m>k)+1]

Sp3000 saved one byte (.index → .find).
Explanation
We want to map the directions like so:
       \
  N ⇄⇄⇄⇄⇄⇄⇄ E
  ⇅         ⇅
  ⇅         ⇅
/ ⇅         ⇅ /
  ⇅         ⇅
  ⇅         ⇅
  W ⇄⇄⇄⇄⇄⇄⇄ S
       \

We can assign the directions 2-bit codes, and view both flips as XOR-ing the first and second bits:
         xor 2
     0 0 ⇄⇄⇄⇄⇄ 1 0
      ⇅         ⇅
      ⇅         ⇅
xor 1 ⇅         ⇅ xor 1
      ⇅         ⇅
      ⇅         ⇅
     0 1 ⇄⇄⇄⇄⇄ 1 1
         xor 2

The mapping between bit strings and directions happens using the string k. Now we just need to map mirror characters '/' and '\\' to the values 1 and 2. Since '/' < '\\', we could naïvely use (m>'/')+1 as a formula. But wait! Lexicographically,
'/' < 'NWES' < '\\'

and we have 'NWES' nicely assigned to k! So we can use (m>k)+1 instead.

CJam, 14 bytes
(@MartinEnder ported my Python answer)
l1b" NESSWNW"=

How?
l1b" NESSWNW"= -
l              - read input
 1b            - cast characters as base 1 digits
   " NESSWNW"  - the string " NESSWNW"
             = - modulo index into the string

Tests are on aditsu

Javascript (ES6), 50 41 40 37 bytes
d=>m=>(S="NWES")[S.search(d)^-~(m>S)]

Saved 3 more bytes by using comparison, thanks to Lynn's answer
Usage

let f =
d=>m=>(S="NWES")[S.search(d)^-~(m>S)]

console.log(f("N")("/"));  //   -->   W
console.log(f("N")("\\")); //   -->   E
console.log(f("E")("/"));  //   -->   S
console.log(f("E")("\\")); //   -->   N
console.log(f("S")("/"));  //   -->   E
console.log(f("S")("\\")); //   -->   W
console.log(f("W")("/"));  //   -->   N
console.log(f("W")("\\")); //   -->   S

Clever use of ASCII comparisons to get your condition at the end playing your way...

MATL, 19 17 bytes
'NWSE'jy&mjy+Eq-)

Try it online! Or verify the eight cases.
Explanation
'NWSE'    % Push this string
j         % Take first input, say 'W'. Stack contains: 'NWSE', 'W'
y         % Duplicate from below. Stack: 'NWSE', 'W', 'NWSE'
&m        % Index of membership. Stack: 'NWSE', 2
j         % Take second input, say '/'. Stack: 'NWSE', 2, '/'
y         % Duplicate from below. Stack: 'NWSE', 2, '/', 2
+         % Add (char '/' is converted to code point). Stack: 'NWSE', 2, 49
Eq        % Multiply by 2, subtract 1. Stack: 'NWSE', 2, 97
-         % Subtract. Stack: 'NWSE', -95
)         % Apply -95 as (modular, 1-based) index into 'NWSE'. Stack: 'N'
          % Implicitly display

Pyth, 17 16 15 bytes
Thanks to @Jakube and @Maltysen for -1 byte each
@J"NWES"xxJQh>E

A program that takes input of two newline-separated quoted strings, first the direction and then the mirror, and prints the result.
This is a port of @Lynn's Python answer.
Try it online
How it works
@J"NWES"xxJQh>E  Program. Inputs: Q, E
 J"NWES"         J="NWES". Yield J
         xJQ     J.index(Q)
             >E  E>Q, lexographically (implicit input fill)
            h    +1
        x        Bitwise XOR of the above two
@                Index into J with the above
                 Implicitly print

you can save another byte by replacing <QE with >E.

Java 7, 71 70 68 bytes
char c(int d,int m){return"NEWS".charAt("NEWS".indexOf(d)^-~(m%2));}

Too bad the charAt and indexOf takes up so much bytes..
Ungolfed & all test cases:
Try it here.
class M{
  static char c(int d, int m) {
    return "NEWS".charAt("NEWS".indexOf(d) ^ -~(m%2));
  }

  public static void main(String[] a){
    System.out.print(c('N', '/') + " ");
    System.out.print(c('N', '\\') + " ");
    System.out.print(c('E', '/') + " ");
    System.out.print(c('E', '\\') + " ");
    System.out.print(c('S', '/') + " ");
    System.out.print(c('S', '\\') + " ");
    System.out.print(c('W', '/') + " ");
    System.out.print(c('W', '\\') + " ");
  }
}

Output:
W E S N E W N S

Jelly, 14 13 12 bytes
(a port of my Python answer)
-1 byte thanks to @MartinEnder (add a space to end of the string and remove need for modulo 8)
-1 byte thanks to @LuisMendo (take a single string argument rather than two)
OSị“NESSWNW

How?
OSị“NESSWNW  - takes a single argument "dm" (direction and mirror), in either order.
                   strings and lists are equivalent in Jelly
 O            - ordinal: [ord(d),ord(m)]
  S           - sum: ord(d)+ord(m)
    “NESSWNW  - string: "NESSWNW "
   ị          - fetch modulo index (the string is 8 long and 1-based)

Test it on TryItOnline

05AB1E, 14 bytes
‘€Ã‘DIkI'/kÌ^è

‘€Ã‘             # from string "NEWS"
             è   # get element at index
    DIk          # index of 1st input in string "NEWS"
            ^    # XOR
       I'/k      # index of 2nd input in string "/"
           Ì     # +2

Try it online!

Python, 63 61 59 bytes
lambda d,m,x='NESW'*2:x[x.find(d)+2*(m=='/\\'[d in'NS'])-1]

Pretty simple. Can definitely be golfed more. Decides whether to add 1 or -1 to the input's index in 'NESW'.
This is a lambda expression; to use it, prefix it with f=.
Ideone it!

Java 8, 62 58 56 bytes
(d,m)->"SEWN".charAt("NWES".indexOf(d)^m.indexOf(47)+2);

Ungolfed test program
import java.util.function.BiFunction;

public class Mirror {

public static void main(String[] args) {
    BiFunction<String, String, Character> function = (d,m)->"SEWN".charAt("NWES".indexOf(d)^m.indexOf(47)+2);

    System.out.println(function.apply("N", "/")); //W
    System.out.println(function.apply("N", "\\")); //E
    System.out.println(function.apply("W", "/")); //N
    System.out.println(function.apply("W", "\\")); //S
    System.out.println(function.apply("E", "/")); //S
    System.out.println(function.apply("E", "\\")); //N
    System.out.println(function.apply("S", "/")); //E
    System.out.println(function.apply("S", "\\")); //W
}

}

PowerShell v2+, 34 bytes
param($a,$b)"xNESSWNW"[(+$a+$b)%8]

Takes input as two explicit chars, outputs a char.
This works as follows: If we sort the output, we want S / to somehow equal the same as N \, W / to equal E \, etc. Or, at least, produce numbers that are "close enough" yet still distinct. If we look at the ASCII values, we get a table like the below:
In1   In2       Res.    Sum
S 83  / 47  --> E 69 -> 130
N 78  \ 92  --> E 69 -> 170
W 87  / 47  --> N 78 -> 134
E 69  \ 92  --> N 78 -> 161
W 87  \ 92  --> S 83 -> 179
E 69  / 47  --> S 83 -> 116
N 78  / 47  --> W 87 -> 125
S 83  \ 92  --> W 87 -> 175

Running a quick brute-forcer on the summations column (derived from summing the ASCII code points of the inputs) shows that if we take the sums modulo 8, we get the following 2 2 | 6 1 | 3 4 | 5 7. That's evidenced in the string "xNESSWNW", as E is at index 2, N is at 6 and 1, and so on.
So, we just need to sum the inputs (implicitly casting from char to int32 along the way), take that %8, and use that to index into our string.
Test Cases
PS C:\Tools\Scripts\golfing> ('N','/'),('N','\'),('E','/'),('E','\'),('S','/'),('S','\'),('W','/'),('W','\')|%{"$($_[0]) $($_[1]) --> "+(.\mirror-mirror-in-the-code.ps1 ([char]$_[0]) ([char]$_[1]))}
N / --> W
N \ --> E
E / --> S
E \ --> N
S / --> E
S \ --> W
W / --> N
W \ --> S

Batch, 111 bytes
:goto %1
:W/
:E\
@echo N
@exit/b
:S/
:N\
@echo E
@exit/b
:E/
:W\
@echo S
@exit/b
:N/
:S\
@echo W

Accepts e.g. W/ as a two-character string command line parameter. The \ and / make looping awkward; it would have taken 124 bytes.

Idk, I count 96 bytes. Did you strip \r from it?

@ConorO'Brien I write my Batch files using Notepad, so, no.

Octave, 30 bytes
Used the same order of arguments as Jonathan Allan.
Takes the input as two-character string 'W\'.
@(x)['NESSWNW'](mod(sum(x),8))

Try it online.

Nice! You may want to port to MATL: 'NESSWNW 'is) (see all test cases). i is input, s is sum, and ) is indexing, which is modular. I added a space in the string so that the modulo is 8

Thanks :) I feel it's cheating if I add that as a separate answer, since I haven't written it myself. I can add it to this answer though if you don't want to answer it yourself :)

I understand, I would probably do the same :-) I don't want to modify my answer, as it's a totally different approach I didn't come up with. Not sure it adding it to your answer makes sense, though, as it would be two different languages in the answer

It would be my first MATL answer though :P I see it's longer than your MATL answer, so I don't think I'll add it...

C, 44, 35, 34 bytes
f(a,b){return"NWES"[a&a/2&3^b&3];}

It requires two characters as two variables. It takes both lower and upper case. It uses a lot of bit manipulation. The fragment a&a/2 results in a value that has unique values for the lower two bits, &3 cuts off all higher bits. This used as an index into the string "NWES" for the \ mirror. Luckily, the lower two bits of the ASCII characters \ and / are 00 and 11 respectively, which is perfect to XOR with the aforementioned index to get the correct direction for the / mirror.

Nice! You missed an obvious -1 byte, though: return"NWES"[...] (omit the space).

Thanks Tim, it hadn't occured to me that that would be valid C :)

CJam, 17 bytes
r"SWEN"_e!r'/#=er

Input is space-separated.
Try it online! (As a linefeed-separated test suite.)
This is the solution I found before posting the challenge. Not as short as Jonathan's cyclic indexing, but I thought this approach is quite interesting (and novel).
Explanation
The goal is use transliteration (i.e. using a character-to-character mapping) to replace the input character with the output character. To do this, we need to select the correct map based on whether the mirror is / or \. We'll map from the SWEN list to another one which we'll select conditionally. If the input list is SWEN, the two output maps need to be the following:
in  SWEN
/   ENSW
\   WSNE

Note that these are in sorted and reverse-sorted order (which is why we chose the seemingly random SWEN order as the input set). We could generate these by sorting the input list and the reversing the result if the input has \, but there's a better way:
r       e# Read incoming direction.
"SWEN"  e# Push input list for transliteration.
_e!     e# Duplicate and get all permutations. The way, `e!` is implemented, it
        e# always gives the permutations in sort order, regardless of the order
        e# of the input set. Specifically that means that "ENSW" will be first
        e# and "WSNE" will be last in this list.
r       e# Read the mirror.
'/#     e# Find the index of / in this string. If the mirror is '/', then this
        e# gives 0. Otherwise, this gives -1, indicating that '/' was not found.
=       e# Select the corresponding permutation. Indexing is zero-based and
        e# cyclic so that 0 (input '/') gives the first permutation "ENSW" and
        e# -1 (input '\') gives the last permutation "WSNE".
er      e# Perform the transliteration on the incoming direction.
        e# Printing is implicit.

SED 48 (42 + 1 for -r) 43
Saved 5 thanks to Martin Ender♦
s,N/|S\\,W,;s,E/|W\\,S,;s,N.|S/,E,;s,..,N,

Takes input as a two character string.

Mathematica, 98 bytes
If[#2=="/",{"S",,,,,,,,,"W",,,,,"E",,,,"N"},{"N",,,,,,,,,"E",,,,,"W",,,,"S"}][[LetterNumber@#-4]]&

Anonymous function. Takes two strings as input and returns a string as output.

C, 81 bytes
f(char*a){return a!="N/"&a!="S\\"?a!="N\\"&a!="S/"?a!="W\\"&a!="E/"?78:83:69:87;}

Usage
main()
{
    printf("N/ \t %c\n",f("N/"));
    printf("N\\\t %c\n",f("N\\"));
    printf("E/ \t %c\n",f("E/"));
    printf("E\\\t %c\n",f("E\\"));
    printf("S/ \t %c\n",f("S/"));
    printf("S\\\t %c\n",f("S\\"));
    printf("W/ \t %c\n",f("W/"));
    printf("W\\\t %c\n",f("W\\"));
}

Output:
N/      : W
N\      : E
E/      : S
E\      : N
S/      : E
S\      : W
W/      : N
W\      : S

Works only on hardcoded values since uses pointer comparisons.

Pyth, 13 bytes
@."EW¹0`Y"sCM

Test suite
Sum the code points, modular index, compressed string.

TI-Basic, 40 bytes
Hardcodes the inputs. Boring, but the shortest way.
sub("NEWS",1+int(inString("E/W\N\S/N/S\E\W/",Ans)/4),1


text:
Is this a Smith number?
Challenge description
A Smith number is a composite number whose sum of digits is equal to the sum of sums of digits of its prime factors. Given an integer N, determine if it's a Smith number or not.
The first few Smith numbers are 4, 22, 27, 58, 85, 94, 121, 166, 202, 265, 274, 319, 346, 355, 378, 382, 391, 438 (sequence A006753 in OEIS).
Sample input / output
18: False (sum of digits: 1 + 8 = 9; factors: 2, 3, 3; sum of digits of factors: 2 + 3 + 3 = 8)
22: True
13: False (meets the digit requirement, but is prime)
666: True (sum of digits: 6 + 6 + 6 = 18; factors: 2, 3, 3, 37; sum of digits of factors: 2 + 3 + 3 + 3 + 7 = 18)
-265: False (negative numbers can't be composite)
0: False (not composite)
1: False (not composite)
4937775: True

Notes

Your code can be a function (method) or a full working program,
Instead of words like True and False, you can use any truthy and falsy values, as long as it's clear what they are,
This is a code-golf challenge, so make your code as short as possible!

I had to read this: "sum of digits is equal to the sum of sums of digits of its prime factors" a few times :P

@StewieGriffin: Yes, it's a rather complicated sentence, but I felt like I needed to give a proper definition instead of relying solely on the examples :)

This is one of those questions where I thought "Java+this=no", I upvoted for the idea though :P

I sometimes notice patterns in numbers, sum of digits etc., but really, do people notice stuff like this: "Albert Wilansky coined the term Smith number when he noticed the defining property in the phone number of his brother-in-law"?

@StewieGriffin: Yeah, it's like Ramanujan and 1729, always baffled me as well.

@BasicallyAlanTuring I should have listened to you..>.> ;P (posted a very, very long Java 7 answer)

@KevinCruijssen I just pissed myself laughing hahahaaha Great attempt man

@BasicallyAlanTuring Thanks. It works, but with that everything is said.. XD Java & prime-check + prime-factors + sum-of-digits = 50x more bytes used than the current best answer, lmao. I knew you were right with your "Java+this=no", but couldn't resist trying.. ;)

@BasicallyAlanTuring Ok, managed to more than halve the amount of bytes now that I had some time to think about it.. Could probably be tweaked some more here-and-there, but at least it's lowered by a large amount (although it's still higher than any other answer..)

Do the results have to be truthy/falsy in the relevant language? If not, what determines truthiness/falsiness?

Python 2, 122 115 110 106 bytes
n=m=input()
s=0
for d in range(2,n):
 while n%d<1:n/=d;s+=sum(map(int,`d`))
print n<m>s==sum(map(int,`m`))

Saved 4 bytes thanks to Dennis
Try it on ideone.com
Explanation
Reads a number on stdin and outputs True if the number is a Smith number or False if it is not.
n=m=input()                  # stores the number to be checked in n and in m
s=0                          # initializes s, the sum of the sums of digits of prime factors, to 0
for d in range(2,n):         # checks all numbers from 2 to n for prime factors
 while n%d<1:                # while n is divisible by d
                             #   (to include the same prime factor more than once)
  n/=d                       # divide n by d
  s+=sum(map(int,`d`))       # add the sum of the digits of d to s
print                        # print the result: "True" if and only if
      n<m                    #   n was divided at least once, i.e. n is not prime
      >                      #   and m>s (always true) and
      s==sum(map(int,`m`))   #   s is equal to the sum of digits of m (the input)

Down voter - it might be useful to add a comment to explain why

@JonathanAllan The downvote was cast automatically by the Community user when the answer was edited. I consider this a bug.

The last line can be rewritten as print n<m>s==sum(map(int,`m`)).

@Dennis That's a great use of chained comparison!

This doesn't actually really work, due to 4 not being printed despite it being a smith number, anyone have a fix or another solution?

@DialFrost m>s => m>=s works

Jelly, 12 11 bytes
Æfḟȯ.DFżDSE

Returns 1 for Smith numbers and 0 otherwise. Try it online! or verify all test cases.
Background
Æf (prime factorization) and D (integer-to-decimal) are implemented so that P (product) and Ḍ (decimal-to-integer) constitute left inverses.
For the integers -4 to 4, Æf returns the following.
-4 -> [-1, 2, 2]
-3 -> [-1, 3]
-2 -> [-1, 2]
-1 -> [-1]
 0 -> [0]
 1 -> []
 2 -> [2]
 3 -> [3]
 4 -> [2, 2]

For the numbers -10, -1, -0.5, 0, 0.5, 1, 10, D returns the following.
-11   -> [-1, -1]
-10   -> [-1, 0]
 -1   -> [-1]
 -0.5 -> [-0.5]
  0   -> [0]
  0.5 -> [0.5]
  1   -> [1]
 10   -> [1, 0]
 11   -> [1, 1]

How it works
Æfḟȯ.DFżDSE  Main link. Argument: n (integer)

Æf           Yield the prime factorization of n.
  ḟ          Filter; remove n from its prime factorization.
             This yields an empty array if n is -1, 0, 1, or prime.
   ȯ.        If the previous result is an empty array, replace it with 0.5.
     D       Convert all prime factors to decimal.
      F      Flatten the result.
        D    Yield n in decimal.
       ż     Zip the results to both sides, creating a two-column array.
         S   Compute the sum of each column.
             If n is -1, 0, 1, or prime, the sum of the prime factorization's
             digits will be 0.5, and thus unequal to the sum of the decimal array.
             If n < -1, the sum of the prime factorization's digits will be
             positive, while the sum of the decimal array will be negative.
          E  Test both sums for equality.

This is a seriously cool solution I have to say!

@Emigna - It's what I did, but implemented in a far superior fashion :D

@JonathanAllan Unfortunately I don't speak Jelly so I have no idea what your code does :)

@Emigna - yeah I had planned to work out how to golf it down before adding a how does it work section.

Brachylog, 19 bytes
@e+S,?$pPl>1,P@ec+S

Try it online!
Explanation
@e+S,                 S is the sum of the digits of the input.
     ?$pP             P is the list of prime factors of the input.
        Pl>1,         There are more than 1 prime factors.
             P@e      Split each prime factor into a list of digits.
                c     Flatten the list.
                 +S   The sum of this list of digits must be S.

05AB1E, 11 17 bytes
X›0si¹ÒSO¹SOQ¹p_&

Explanation
X›0si              # if input is less than 2 then false, else
       SO          # sum of digits
     ¹Ò            # of prime factors with duplicates
            Q      # equal to
          SO       # sum of digits
         ¹         # of input
                &  # and
             ¹p_   # input is not prime

Try it online!

PowerShell v3+, 183 bytes
param($n)$b=@();for($a=$n;$a-gt1){2..$a|?{'1'*$_-match'^(?!(..+)\1+$)..'-and!($a%$_)}|%{$b+=$_;$a/=$_}}$n-notin$b-and(([char[]]"$n")-join'+'|iex)-eq(($b|%{[char[]]"$_"})-join'+'|iex)

No built-in prime checking. No built-in factoring. No built-in digit-sum. Everything's hand made. :D
Takes input $n as an integer, sets $b equal to an empty array. Here, $b is our collection of prime factors.
Next is a for loop. We first set $a equal to our input number, and the conditional is until $a is less-than-or-equal-to 1. This loop is going to find our prime factors.
We loop from 2 up to $a, uses Where-Object (|?{...}) to pull out primes that are also factors !($a%$_). Those are fed into an inner-loop |%{...} that places the factor into $b and divides $a (thus we'll eventually get to 1).
So, now we have all of our prime factors in $b. Time to formulate our Boolean output. We need to verify that $n is -notin $b, because if it is that means that $n is prime, and so isn't a Smith number. Additionally, (-and) we need to make sure that our two sets of digit sums are -equal. The resulting Boolean is left on the pipeline and output is implicit.
NB - Requires v3 or newer for the -notin operator. I'm still running the input for 4937775 (this is slow to calculate), so I'll update this when that finishes. After 3+ hours, I got a stackoverflow error. So, there's some upper-bound somewhere. Oh well.
This will work for negative input, zero, or one, because the right-hand of the -and will barf out an error while it tries to calculate the digit sums (shown below), which will cause that half to go to $false when evaluated. Since STDERR is ignored by default, and the correct output is still displayed, this is fine.

Test cases
PS C:\Tools\Scripts\golfing> 4,22,27,58,85,94,18,13,666,-265,0,1|%{"$_ -> "+(.\is-this-a-smith-number.ps1 $_)}
4 -> True
22 -> True
27 -> True
58 -> True
85 -> True
94 -> True
18 -> False
13 -> False
666 -> True
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string.
At C:\Tools\Scripts\golfing\is-this-a-smith-number.ps1:1 char:179
+ ... "$_"})-join'+'|iex)
+                    ~~~
    + CategoryInfo          : InvalidData: (:String) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

-265 -> False
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string.
At C:\Tools\Scripts\golfing\is-this-a-smith-number.ps1:1 char:179
+ ... "$_"})-join'+'|iex)
+                    ~~~
    + CategoryInfo          : InvalidData: (:String) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

0 -> False
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string.
At C:\Tools\Scripts\golfing\is-this-a-smith-number.ps1:1 char:179
+ ... "$_"})-join'+'|iex)
+                    ~~~
    + CategoryInfo          : InvalidData: (:String) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

1 -> False

MATL, 17 bytes
YftV!UsGV!Us=wnqh

Outputs truthy or falsey arrays where a truthy output requires that all elements be non-zero.
Try it online

@JonathanAllan Yes. I'm adding a bit about the definition of truthy and falsey.

Jelly, 27 25 23 bytes
(further golfing probably definitely possible)
ḢDS×
ÆFÇ€SḢ
DS=Ça<2oÆP¬

Returns 0 for False or 1 for True
All test cases at TryItOnline
How?
DS=Ça<2oÆP¬ - main link takes an argument, n
DS          - transform n to a decimal list and sum up
   Ç        - call the previous link (ÆFÇ€SḢ)
  =         - test for equality
     <2     - less than 2?
    a       - logical and
        ÆP  - is prime?
       o    - logical or
          ¬ - not
            - all in all tests if the result of the previous link is equal to the digit
              sum if the number is composite otherwise returns 0.

ÆFÇ€SḢ - link takes an argument, n again
ÆF     - list of list of n's prime factors and their multiplicities
  Ç€   - apply the previous link (ḢDS×) for each
    S  - sum up
     Ḣ - pop head of list (there will only be one item)

ḢDS× - link takes an argument, a factor, multiplicity pair
Ḣ    - pop head, the prime factor - modifies list leaving the multiplicity
 DS  - transform n to a decimal list and sum up
   × - multiply the sum with the multiplicity

Actually, 18 bytes
Unfortunately, Actually doesn't have a factorization builtin that gives a number's prime factors to multiplicity, so I had to hack one together. Golfing suggestions welcome. Try it online!
;w`i$n`MΣ♂≈Σ@$♂≈Σ=

Ungolfing
         Implicit input n.
;w       Duplicate n and get the prime factorization of a copy of n.
`...`M   Map the following function over the [prime, exponent] lists of w.
  i        Flatten the list. Stack: prime, exponent.
  $n       Push str(prime) to the stack, exponent times.
            The purpose of this function is to get w's prime factors to multiplicity.
Σ        sum() the result of the map.
          On a list of strings, this has the same effect as "".join()
♂≈Σ      Convert every digit to an int and sum().
@        Swap the top two elements, bringing other copy of n to TOS.
$♂≈Σ     Push str(n), convert every digit to an int, and sum().
=        Check if the sum() of n's digits is equal
          to the sum of the sum of the digits of n's prime factors to multiplicity.
         Implicit return.

Octave, 80 78 bytes
t=num2str(factor(x=input('')))-48;disp(any(t<0)&~sum([num2str(x)-48 -t(t>0)]))

Explanation:
factor(x=input(''))                 % Take input, store as x and factor it
num2str(factor(x=input('')))-48     % Convert it to an array (123 -> [1 2 3])
                                    % and store as t
any(t<0)                            % Check if there are several prime factors
                                    % [2 3] -> [2 -16 3]
sum([num2str(x)-48 -t(t>0)])        % Check if sum of prime factor
                                    % is equal the sum of digits

Try it online.

That any(t<0) for non-primality is very clever

Haskell, 120 105 bytes
1%_=[];a%x|mod a x<1=x:div a x%x|0<1=a%(x+1)
p z=sum[read[c]|c<-show z]
s x|z<-x%2=z<[x]&&sum(p<$>z)==p x

JavaScript (ES6),  87 86  84 bytes
m=>(i=2,S=0,g=n=>([...i+''].map(v=>s-=v,s=S),i-m?n%i?g(n,i++):g(n/i,S=s):s==2*S))(m)

Try it online!

Pyth, 21 bytes
&&>Q1!P_QqsjQTssmjdTP

A program that takes input of an integer and prints True or False as relevant.
Try it online
How it works
&&>Q1!P_QqsjQTssmjdTP  Program. Input: Q
           jQT         Yield digits of the base-10 representation of Q as a list
          s            Add the digits
                    P  Yield prime factors of Q (implicit input fill)
                mjdT   Map base-10 representation across the above, yielding digits of each
                       factor as a list of lists
               s       Flatten the above
              s        Add up the digits
         q             Those two sums are equal
&                      and
  >Q1                  Q>1
 &                     and
     !P_Q              Q is not prime
                       Implicitly print

Perl 6, 92 88 87 bytes

{sub f(\i){my \n=first i%%*,2..i-1;n??n~f i/n!!i}
!.is-prime&&$_>1&&.comb.sum==.&f.comb.sum}

{sub f(\i){my \n=first i%%*,2..^i;n??[n,|f i/n]!!|i}
$_>.&f>1&&.comb.sum==.&f.comb.sum}

An anonymous function that returns a Bool.

Now does 100% manual factorization and primality checking.
Saved some bytes by testing both "input > 1" and "number of factors > 1" with one chained comparison, since m > Ω(m).

(try it online)
EDIT: -1 byte thanks to b2gills

2..i-1 is better spelt as 2..^i.

Brachylog (newer), 11 bytes
¬ṗ&ẹ+.&ḋcẹ+

Try it online!
Predicate succeeds if the input is a Smith number and fails if it is not.
               The input
¬ṗ             is not prime,
  &            and the input's
   ẹ           digits
    +          sum to
     .         the output variable,
      &        and the input's
       ḋ       prime factors' (getting prime factors of a number < 1 fails)
        c      concatenated
         ẹ     digits
          +    sum to
               the output variable.

Japt, 14 11 bytes
ìx ¥Uk x_ìx

-3 bytes thanks to @Shaggy
Try it online!

11 bytes

Note to self: need to remember which functions can be passed functions

APL (Dyalog Extended), 36 29 bytesSBCS
This answer owes its golfiness to Extended's ⍭ monad for returning the prime factors of a number, and that ⊤ is better at base-conversion than in Dyalog Unicode.
Edit: -7 bytes thanks to dzaima.
{2>⍵:0⋄(⊃=+/-⊃×2<≢)+⌿10⊤⍵,⍭⍵}

Try it online!
Explanation
{1⋄(3)2}  A dfn, a function in brackets. ⋄ is a statement separator.
          The numbers signify the sections in the order they are explained.

2>⍵:0  If we have a number less than 2,
       we immediately return 0 to avoid a DOMAIN ERROR.

+⌿10⊤⍵,⍭⍵
        ⍭⍵  We take the factors of ⍵, our input as our right argument,
      ⍵,    and append it to our input again.
   10⊤      before converting the input and its factors into a matrix of their base-10 digits
            (each row is the places, units, tens, hundreds, etc.)
+⌿         And taking their sum across the columns of the resulting matrix,
            to give us the sum of their digits, their digit-sums.

(⊃=+/-⊃×2<≢)  We run this section over the list of sums of digits above.
 ⊃=+/-⊃       We check if the main digit-sum (of our input)
               Is equal to the sum of our digit-sums
               (minus our main digit-sum that is also still in the list)
        ×2<≢   The trick here is that we can sneak in our composite check
               (if our input is prime there will be only two numbers,
               the digit-sum of the prime,
               and the digit-sum of its sole prime factor, itself)
               So if we have a prime, we zero our (minus our main sum)
               in the calculation above, so that primes will not succeed in the check.
               We return the result of the check.

29 bytes - {2>⍵:0⋄(⊃=+/-⊃×2<≢)+⌿10⊤⍵,⍭⍵}

Rutger, 504 bytes
x=$Input;
t=Not[IsPrime[$x]];
c=();
d=p=0;
i=IfElse[{l=LessThan[$x];l[1]}];
i=i[{t=0;}];
i=i[{s=Array[Str[$x]];e=Each[$s];e=e[@i];e=e[{a=Add[$d];d=a[Integer[$i]];}];Do[$e];r=2;w=While[{Decrement[$x];}];w=w[{i=IfElse[{m=Modulo[$x];Not[m[$r]];}];i=i[{a=Append[$c];v=Divide[$x];x=Integer[v[$r]];c=a[Array[Str[$r]]];}];i=i[{r=Increment[$r];}];Do[$i];}];Do[$w];h=Each[$c];h=h[@k];h=h[{l=Each[$k];l=l[@n];l=l[{a=Add[$p];p=a[Integer[$n]];}];Do[$l];}];Do[$h];}];
Do[$i];
z=Times[$t];
e=Equal[$d];
Print[z[e[$p]];

Try it online!
Rutger isn't a particularly short language, and doesn't excel at having to split an integer into its constituent digits.

APL (Dyalog Extended), 26 bytes
(×/≡⍥(+/⍣≡10⊤⊢)⊢×1<≢)⍭⍤⌈∘2

Try it online!
A golfed version of Sherlock9's solution. A nice use case for Over f⍥g, which performs g on both sides and combines the two with f.
How it works
(×/≡⍥(+/⍣≡10⊤⊢)⊢×1<≢)⍭⍤⌈∘2  ⍝ Input: n
                       ⌈∘2  ⍝ max(n,2)
                     ⍭⍤     ⍝ Prime factorization of above
(              ⊢×1<≢)       ⍝ Side 1: if n is not composite, multiply ^ with zero
 ×/                         ⍝ Side 2: multiply all primes to get original number
    ⍥(        )  ⍝ Operate on each side..
          10⊤⊢   ⍝ Base-10 digits of each number
      +/⍣≡       ⍝ Sum all of them
   ≡             ⍝ Check equality of the two sides

tinylisp, 131 bytes
(load library
(d F(q((X)(*(*(not(prime? X))X)(e(sum(to-base 10 X))(sum(map(q((X)(s X 48)))(chars(join(map string(prime-factors X))(

Try it online!
An unintentional golf at join which through some weird behaviour ends up producing the right thing. Rest of it is just the formula given in the question.

Vyxal, 63 bitsv2, 7.875 bytes
₍‡ǐvffṠṠ≈

Try it Online!
Bitstring:
110001111001001111101010000010100001001101010011001110100101010

₍‡ǐvffṠṠ≈
₍          # Wrap the next to items in a list
 ‡ǐvf      # list of digits for each prime factor
     f     # list of digits of original number
      ṠṠ   # vectorised sum twice (quirk of list depth from digit lists)
        ≈  # are they equal

Created with the help of Luminespire.

Pyke, 16 bytes
Pm[`mbs(sQ[qRlt*

Try it here!

Errors without result for input less than 2

@JonathanAllan no output to stdout is falsy. If warnings are disabled stderr gets ignored too

I knew we can ignore stderr, but no output seems a bit weird ...but if it's acceptable then it's acceptable.

Personally I'm not sure if it's acceptable but I can say it is right?

Java 7, 509 506 435 426 419 230 bytes
boolean c(int n){return n<2|p(n)?0>1:d(n)==f(n);}int d(int n){return n>9?n%10+d(n/10):n;}int f(int n){int r=0,i;for(i=1;++i<=n;)for(;n%i<1;n/=i,r+=i>9?d(i):i);return r;}boolean p(int n){int i=2;while(i<n)n=n%i++<1?0:n;return n>1;}

I should have listened to @BasicallyAlanTuring's comment..

This is one of those questions where I thought "Java+this=no", I upvoted for the idea though :P

Ah well.. Some programming languages use a single byte for the prime-factors or prime-check, but Java is certainly not one of them.
EDIT: Halved the amount of bytes now that I had some time to think about it.
Ungolfed (sort-off..) & test cases:
Try it here.
class M{
  static boolean c(int n){
    return n < 2 | p(n)
            ? 0 > 1 //false
            : d(n) == f(n);
  }

  // Sums digits of int
  static int d(int n) {
    return n > 9
            ? n%10 + d(n/10)
            : n;
  }

  // Convert int to sum of prime-factors
  static int f(int n) {
    int r = 0,
        i;
    for(i = 1; ++i <= n; ){
      for( ; n % i < 1; n /= i,
                        r += i > 9 ? d(i) : i);
    }
    return r;
  }

  // Checks if the int is a prime
  static boolean p(int n){
    int i = 2;
    while(i < n){
      n = n % i++ < 1
           ? 0
           : n;
    }
    return n > 1;
  }

  public static void main(String[] a){
    System.out.println(c(18));
    System.out.println(c(22));
    System.out.println(c(13));
    System.out.println(c(666));
    System.out.println(c(-256));
    System.out.println(c(0));
    System.out.println(c(1));
    System.out.println(c(4937775));
  }
}

Output:
false
true
false
true
false
false
false
true

J, 31 30 bytes
0&p:*](=+/)&(1#."."0@":)q: ::1

Try it online!

C (gcc), 139 136 bytes
S(m,i,t,h,_){t=m=m<2?2:m;for(_=h=i=1;m>1;h=1){while(m%++h);for(m/=h;i+=h%10,h/=10;);}while(t%++h);for(m=t;_+=m%10,m/=10;);m=t-h?i==_:0;}

Try it online!
-3 bytes thanks to ceilingcat
Explanation:
/*
 * Variable mappings:
 *  is_smith      => S
 *  argument      => m
 *  factor_digits => i
 *  arg_copy      => t
 *  least_factor  => h
 *  digit_sum     => _
 */
int is_smith(int argument){                     /* S(m,i,t,h,_){ */
    int factor_digits;
    int arg_copy;
    int least_factor;
    int digit_sum;

    /*
     * The cases of 0 and 1 are degenerate.
     * Mapping them to a non-degenerate case with the right result.
     */
    if (argument < 2) {                         /* t=m=m<2?2:m; */
        argument = 2;
    }
    arg_copy = argument;

    /*
     * Initializing these to 1 instead of zero is done for golf reasons.
     * In the end we just compare them, so it doesn't really matter.
     */
    factor_digits = 1;                          /* for(_=h=i=1; */
    digit_sum = 1;

    /* Loop over each prime factor of argument */
    while (argument > 1) {                      /* m>1; */

        /*
         * Find the smallest factor
         * Note that it is initialized to 1 in the golfed version since prefix
         * increment is used in the modulus operation.
         */
        least_factor = 2;                       /* h=1){ */
        while (argument % least_factor != 0)    /* while(m% */
            least_factor++;                     /* ++h); */
        argument /= least_factor;               /* for(m/=h; */

        /* Add its digit sum to factor_digits */
        while (least_factor > 0) {
            factor_digits += least_factor % 10; /* i+=h%10, */
            least_factor /= 10;                 /* h/=10;) */
        }                                       /* ; */

    }                                           /* } */

    /* In the golfed version we get this for free in the for loop. */
    least_factor = 2;
    while (arg_copy % least_factor != 0)        /* while(t% */
        least_factor++;                         /* ++h); */

    /* Restore the argument */
    argument = arg_copy;                        /* for(m=t; */

    /* Compute the arguments digit sum */
    while (argument > 0) {
        digit_sum += argument % 10;             /* _+=m%10, */
        argument /= 10;                         /* m/=10;) */
    }                                           /* ; */

    /* This return is done by assigning to first argument when golfed. */
                                                /* m= */
    if (arg_copy == least_factor) {             /* t==h? */
        return 0; /* prime input */             /* 0 */
    } else {                                    /* : */
        return digit_sum == factor_digits;      /* i == _ */
    }                                           /* ; */
}                                               /* } */

That introduced a few bugs (e.g. 2 and 3) but I think it should still be achievable.

Suggest t-h&&i==_ instead of t-h?i==_:0

Racket 176 bytes
(define(sd x)(if(= x 0)0(+(modulo x 10)(sd(/(- x(modulo x 10))10)))))
(require math)(define(f N)
(if(=(for/sum((i(factorize N)))(*(sd(list-ref i 0))(list-ref i 1)))(sd N))1 0))

Returns 1 if true and 0 if false:
(f 27)
1
(f 28)
0
(f 85)
1
(f 86)
0

Detailed version:
(define (sd x)   ; fn to find sum of digits
  (if (= x 0)
      0
      (+ (modulo x 10)
         (sd (/ (- x (modulo x 10)) 10)))))

(require math)
(define (f N)
  (if (= (for/sum ((i (factorize N)))
           (* (sd (list-ref i 0))
              (list-ref i 1)))
         (sd N)) 1 0))

Rust - 143 bytes
fn t(mut n:u32)->bool{let s=|k:u32| (2..=k).fold((0,k),|(a,m),_|(a+m%10,m/10));s(n).0==(2..n).fold(0,|mut a,d|{while n%d<1{n/=d;a+=s(d).0};a})}

borrowed python solution by @levitatinglion  ... at least this is shorter than Java...
degolfed at play.rust-lang.org

APL(NARS), 39 chars, 78 bytes
{⍵≤0:0⋄0π⍵:0⋄(2×↑a)=+/a←+/¨{⍎¨⍕⍵}¨⍵,π⍵}

test:
  f←{⍵≤0:0⋄0π⍵:0⋄(2×↑a)=+/a←+/¨{⍎¨⍕⍵}¨⍵,π⍵}
  f¨0..10
0 0 0 0 1 0 0 0 0 0 0
  ⎕fmt {⍵,f⍵}¨18,22,13,666,¯265,0,1,4937775
┌8────────────────────────────────────────────────────────────────────┐
│┌2────┐ ┌2────┐ ┌2────┐ ┌2─────┐ ┌2──────┐ ┌2───┐ ┌2───┐ ┌2─────────┐│
││ 18 0│ │ 22 1│ │ 13 0│ │ 666 1│ │ ¯265 0│ │ 0 0│ │ 1 0│ │ 4937775 1││
│└~────┘ └~────┘ └~────┘ └~─────┘ └~──────┘ └~───┘ └~───┘ └~─────────┘2
└∊────────────────────────────────────────────────────────────────────┘

C (gcc), 177 Bytes
Defines a function Q that returns 0 for smith numbers and nonzero for non-smith numbers
#define r return
O(D,i){for(i=0;D>0;i+=D%10,D-=D%10,D/=10);r i;}D(O,o){for(o=1;o<O;)if(O%++o<1)r o;r O;}Q(p,q,i,j){if(p^(q=D(i=p))){for(j=0;p>1;q=D(p/=q))j+=O(q);r j^O(i);}r 1;}

Try it online!
Explanation:
// Return the sum of digits of D if D > 0, otherwise 0
O(D,i){
    // While D is greater than 0:
    // Add the last digit of D to i, and remove the last digit from D
    for(i=0;D>0;i+=D%10,D-=D%10,D/=10);
    return i;
}
// Return the smallest prime factor of O if O>1 else O
D(O,o){
    // Iterate over numbers less than O
    for(o=1;o<O;)
        // If O is divisible by o return o
        if(O%++o<1)
            return o;
    // Otherwise return O
    return O;
}
Q(p,q,i,j){
    // Set q to D(p) and i to p
    // If p != D(p) (i.e, p is composite and > 0)
    if(p^(q=D(i=p))){
        // Iterate over the prime factors of p and store their digit sum in j
        for(j=0;p>1;q=D(p/=q))
            j+=O(q);
        // i is the original value of p. If O(i)^j == 0, O(i) == j
        return j^O(i);
    }
    // If p was composite or < 0, return 1
    return 1;
}

153 bytes

C# (Visual C# Interactive Compiler), 122 bytes
n=>{int m=n,b=0,a=$"{n}".Sum(x=>x-'0');for(int i=2;i<m;i++)if(n%i==0){b+=$"{i}".Sum(x=>x-'0');n/=i;i=1;}return n>0&&a==b;}

Try it online!

118 bytes

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Render the top-down view of a hip roof in ASCII
First, some terminology (source):

A hip roof is (quoting Wikipedia) "a type of roof where all sides slope downwards to the walls, usually with a fairly gentle slope"
A slope is a planar surface that is a part of the roof
A ridge is an edge where two opposite roof slopes meet
A hip is a convex edge where two slopes belonging to perpendicular walls meet
A valley is a concave edge where two slopes belonging to perpendicular walls meet
Hips and valleys shall be collectively referred to as diagonal edges.

Possible input:
 ** * ***
********
 ** *  **

Corresponding output:
    +-------+   +---+   +-----------+
    |\     /|   |\ /|   |\         /|
    | \   / |   | V |   | \   ^---< |
    |  \ /  |   | | |   |  \ / \   \|
+---+   V   +---+ | +---+   X   +---+
|\   \  |  /     \|/     \ / \  |
| >---> | <-------X-------V   > |
|/   /  |  \     /|\         /| |
+---+   ^   +---+ | +-------+ | +---+
    |  / \  |   | | |       | |/   /|
    | /   \ |   | ^ |       | /---< |
    |/     \|   |/ \|       |/     \|
    +-------+   +---+       +-------+

A couple more test cases:
** ***   *    *   * *
*       ***   *****
    ** *****  *****
* *  *  ***  *** ***
* ****   *     * *

Corresponding outputs :
+-------+   +-----------+           +---+               +---+           +---+   +---+
|\     /|   |\         /|           |\ /|               |\ /|           |\ /|   |\ /|
| \---< |   | >-------< |           | V |               | V |           | V |   | X |
| |\   \|   |/         \|           | | |               | | |           | | |   |/ \|
| | +---+   +-----------+       +---+ | +---+           | | +-----------+ | |   +---+
| | |                           |\   \|/   /|           | |/             \| |
| ^ |                           | \   V   / |           | <               > |
|/ \|                           |  \     /  |           |  \             /  |
+---+           +-------+   +---+   \   /   +---+       |   \-----------/   |
                |\     /|   |\   \   \ /   /   /|       |   |\         /|   |
                | >---/ |   | >--->   X   <---< |       |   | \       / |   |
                |/   /| |   |/   /   / \   \   \|       |   |  \     /  |   |
+---+   +---+   +---+ | |   +---+   /   \   +---+   +---+   ^   +---+   ^   +---+
|\ /|   |\ /|       | | |       |  /     \  |       |\   \ / \  |   |  / \ /   /|
| V |   | V |       | | |       | /   ^   \ |       | >---V   > |   | <   V---< |
| | |   | | |       | | |       |/   /|\   \|       |/       /| |   | |\       \|
| | |   | | +-------+ | |       +---+ | +---+       +-------+ | |   | | +-------+
| | |   | |/         \| |           | | |                   | | |   | | |
| ^ |   | /-----------\ |           | ^ |                   | ^ |   | ^ |
|/ \|   |/             \|           |/ \|                   |/ \|   |/ \|
+---+   +---------------+           +---+                   +---+   +---+

Your input will be a bitmap - a 2D array of square pixels - of the area that should be covered by roof. You may assume the boundary of this area will be a Jordan curve - that is, continuous and non-self-intersecting - that is, the roofed area will be continuous, without holes and there will never be four walls meeting at a single point. Valid input formats include a single string with newline separators, a list of strings and a 2D array of chars or booleans.
The rules of building the roof are:

Each straight segment of the roofed area (henceforth referred to as a wall) shall have exactly one adjoining slope. The slope shall rise away from the wall. Each slope shall have at least one adjoining wall, and all walls adjoining to a slope must be collinear.
All slopes shall have the same (nonzero) angle against the horizontal surface. That is, they must have the same pitch.
The slopes shall form a surface whose boundary is the boundary of the roofed area. That is, no surfaces other than the slopes may be used.
Any scenario where more than one solution (up to vertical scaling) is allowed by this specification is considered a bug in the specification. Any corrections apply retroactively.

Equivalently, the roof may be defined by the rule that each point of the roof is  placed as high as possible without exceeding the maximum slope for that roof as measured using the Chebyshev distance in top-down view.
Your output shall be an ASCII art representation of the roof - either a single string containing newline characters or an array of strings, each denoting a single line of the output. The roof shall be rendered in top-down view at a 4x scale - that is, each square of the floor-plan should affect a 5x5 area of the output such that the corners of this 5x5 area are shared with neighboring squares (such that each corner character is affected by four different input squares), as indicated by the example output. Extra whitespace is allowed as long as the output shape is preserved. The characters in output shall be:

an environment-defined newline marker shall be used (usually U+000A, U+000D or a pair of both) if the output is in the form of a single string
 (U+0020 space) represents a point outside a roofed area or a point interior to a slope
+ (U+002B plus sign) represents a point with two perpendicular walls adjoined to it
- (U+002D hyphen-minus) represents a wall or a ridge oriented horizontally (east-west)
/ (U+002F solidus) represents a hip or a valley oriented north-east to south-east, or a point adjoined to two of those
< (U+003C less-than sign) represents a point with two diagonal edges adjoined to it on the east
> (U+003E greater-than sign) represents a point with two diagonal edges adjoined to it on the west
\ (U+005C reverse solidus) represents a hip or a valley oriented north-west to south-east, or a point adjoined to two of those
^ (U+005E circumflex accent) represents a point with two diagonal edges adjoined to it on the south
V (U+0056 latin capital letter v) represents a point with two diagonal edges adjoined to it on the north
X (U+0058 latin capital letter x) represents a point with diagonal edges adjoined to it on all four sides
| (U+007C vertical bar) represents a wall or a ridge oriented vertically (north-south)

Note that it is not possible for an odd number of diagonal edges to end at the same point (except on walls). We can visualize that by partitioning the neighborhood of each point into north slope + south slope  and into east slope + west slope. The boundary between both partitions has to be composed of diagonal edges.
If your environment uses a character encoding incompatible with ASCII, you may use the equivalent characters (same glyph or closest available) in the character encoding your environment uses.
The following (ugly) reference implementation in Ruby is normative with respect to the non-whitespace output. Note particularly the render method:
def pad ary
  row = ary.first.map{-1}
  ([row] + ary + [row]).map{|r| [-1] + r + [-1]}
end

def parse str
  str.split("\n").map{|r| r.chars.map(&{" " => -1, "*" => Float::INFINITY})}
end

def squares ary, size
  ary.each_cons(size).map do |rows|
    rows.map{|row| row.each_cons(size).to_a}.transpose
  end
end

def consmap2d ary, size
  squares(ary, size).map{|sqrow| sqrow.map{|sq| yield sq}}
end

def relax ary
  loop do
    new = consmap2d(pad(ary), 3){|sq| sq[1][1] == -1 ? -1 : sq.flatten.min + 1}
    return new if new == ary
    ary = new
  end
end

def semidouble ary, op
  ary.zip(ary.each_cons(2).map{|r1,r2|r1.zip(r2).map(&op)}).flatten(1).compact.transpose
end

def heightmap str
  relax(semidouble(semidouble(semidouble(semidouble(pad(parse str),:max),:max),:min),:min))
end

def render heightmap
  puts consmap2d(heightmap, 3){|sq|
    next " " if sq[1][1] == -1
    hwall = sq[0][1] == -1 || sq[2][1] == -1
    vwall = sq[1][0] == -1 || sq[1][2] == -1
    next "+" if hwall && vwall
    next "-" if hwall
    next "|" if vwall
    next "+" if sq.flatten.min == -1

    nws = sq[0][1] == sq[1][0]
    nes = sq[0][1] == sq[1][2]
    sws = sq[2][1] == sq[1][0]
    ses = sq[2][1] == sq[1][2]

    next "X"  if nws && nes && sws && ses
    next "V"  if nws && nes
    next "^"  if sws && ses
    next ">"  if nws && sws
    next "<"  if nes && ses
    next "/"  if nes && sws
    next "\\" if nws && ses
    next " "  if sq[0][1] != sq[2][1] || sq[1][0] != sq[1][2]
    next "|"  if sq[0][1] == sq[1][1]
    next "-"  if sq[1][0] == sq[1][1]
    ??
  }.map(&:join)
end

render heightmap $<.read if __FILE__ == $0

You should add more test cases.

@mbomb007 Added. Given the space they take up - should I add any more?

@JanDvorak Maybe add the test case *. Otherwise that's probably enough.

Is [[0,1,1],[1,0,1],[1,1,1]] valid input? (The input has no “holes”, but there's a pesky corner near-self-intersection.)

@Lynn You don't need to worry about that case, it's not valid input. The corner you mention does count as a self-intersecting boundary (or rather, a boundary that is not a curve).

Python 2, 500 bytes
z=input()
W=4*len(z[0])+1
H=4*len(z)+1
R=range
s=[-~W*[0]for _ in R(-~H)]
for y in R(H/4):
 for x in R(W/4):
        for h in R(25):s[y*4+h%5][x*4+h/5]|=z[y][x]
F=[(x/3-1,x%3-1)for x in[1,7,3,5,0,6,8,2]]
exec'for y in R(H):\n for x in R(W):s[y][x]+=0<s[y][x]<=min(s[y+d][x+e]for(e,d)in F)\n'*H
for y in R(H):
 l=''
 for x in R(W):h=s[y][x];a=[s[y+d][x+e]for(e,d)in F[:4]];l+=r' XabcVde^f ||g>h\\+//+<<jk<l//+\\+>>m --^^oVVqrX'[h and int(''.join(`int(n==h)`for n in a),2)*3+((h==1)*2or max(a)==h)+1]
 print l

Tired of golfing it down, and I got to a nice round score, so here it is.
The eight-space indentation is a tab.
Pass a binary matrix over STDIN, like so:
python2.7 roof.py <<<"[[1,1,0,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0], [1,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0], [0,0,0,0,1,1,0,1,1,1,1,1,0,0,1,1,1,1,1,0], [1,0,1,0,0,1,0,0,1,1,1,0,0,1,1,1,0,1,1,1], [1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0]]"

Fully golfed or not, this is amazing. Well done. +1


text:
Draw an Empty Scrabble Board
A standard Scrabble board is a 15×15 grid of spaces to place letter tiles. Most of the spaces are blank but some are double word scores (pink), triple word scores (red), double letter scores (light blue), and triple letter scores (blue). There is usually a star in the very center (which counts as a double word score).

Write a program or function that outputs a standard, empty Scrabble board in ASCII form where:

. represents an empty space
D represents a double word score
T represents a triple word score
d represents a double letter score
t represents a triple letter score
X represents the center star

That is, your exact output must be
T..d...T...d..T
.D...t...t...D.
..D...d.d...D..
d..D...d...D..d
....D.....D....
.t...t...t...t.
..d...d.d...d..
T..d...X...d..T
..d...d.d...d..
.t...t...t...t.
....D.....D....
d..D...d...D..d
..D...d.d...D..
.D...t...t...D.
T..d...T...d..T

optionally followed by a trailing newline.
The shortest code in bytes wins.

Why X and not * to represent the star? :o

* is too high and mighty.

Why not ★? :D

@mbomb007 Non-ASCII char in an ASCII-art challenge? Heresy!

MATL, 59 54 52 bytes
4t:g2I5vXdK8(3K23h32h(H14(t!XR+8: 7:Pht3$)'DtdTX.'w)

Try it online!
Explanation
The code follows three main steps:

Generate the 8x8 matrix
4 0 0 3 0 0 0 4
0 1 0 0 0 2 0 0
0 0 1 0 0 0 3 0
3 0 0 1 0 0 0 3
0 0 0 0 1 0 0 0
0 2 0 0 0 2 0 0
0 0 3 0 0 0 3 0
4 0 0 3 0 0 0 5

Extend it to the 15x15 matrix
4 0 0 3 0 0 0 4 0 0 0 3 0 0 4
0 1 0 0 0 2 0 0 0 2 0 0 0 1 0
0 0 1 0 0 0 3 0 3 0 0 0 1 0 0
3 0 0 1 0 0 0 3 0 0 0 1 0 0 3
0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 2 0 0 0 2 0 0 0 2 0 0 0 2 0
0 0 3 0 0 0 3 0 3 0 0 0 3 0 0
4 0 0 3 0 0 0 5 0 0 0 3 0 0 4
0 0 3 0 0 0 3 0 3 0 0 0 3 0 0
0 2 0 0 0 2 0 0 0 2 0 0 0 2 0
0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
3 0 0 1 0 0 0 3 0 0 0 1 0 0 3
0 0 1 0 0 0 3 0 3 0 0 0 1 0 0
0 1 0 0 0 2 0 0 0 2 0 0 0 1 0
4 0 0 3 0 0 0 4 0 0 0 3 0 0 4

Index the string 'DtdTX.' with that matrix to produce the desired result.

Step 1
4        % Push 4
t:       % Duplicate, range: pushes [1 2 3 4]
g        % Logical: convert to [1 1 1 1]
2I5      % Push 2, then 3, then 5
v        % Concatenate all stack vertically into vector [4 1 1 1 1 2 3 5]
Xd       % Generate diagonal matrix from that vector

Now we need to fill the nonzero off-diagonal entries. We will only fill those below the diagonal, and then make use symmetry to fill the others.
To fill each value we use linear indexing (see this answer, length-12 snippet). That means accessing the matrix as if it had only one dimension. For an 8×8 matrix, each value of the linear index refers to an entry as follows:
1   9         57
2  10         58
3  11
4
5  ...       ...
6
7             63
8  16 ... ... 64

So, the following assigns the value 4 to the lower-left entry:
K        % Push 4
8        % Push 8
(        % Assign 4 to the entry with linear index 8

The code for the value 3 is similar. In this case the index is a vector, because we need to fill several entries:
3        % Push 3
K        % Push 4
23h      % Push 23 and concatenate horizontally: [4 23]
32h      % Push 32 and concatenate horizontally: [4 23 32]
(        % Assign 4 to the entries specified by that vector

And for 2:
H        % Push 2
14       % Push 14
(        % Assign 2 to that entry

We now have the matrix
4 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
3 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 2 0 0 0 2 0 0
0 0 3 0 0 0 3 0
4 0 0 3 0 0 0 5

To fill the upper half we exploit symmetry:
t!       % Duplicate and transpose
XR       % Keep the upper triangular part without the diagonal
+        % Add element-wise

Step 2
The stack now contains the 8×8 matrix resulting from step 1. To extend this matrix we use indexing, this time in the two dimensions.
8:       % Push vector [1 2 ... 7 8]
7:P      % Push vector [7 6 ... 1]
h        % Concatenate horizontally: [1 2 ... 7 8 7 ... 2 1]. This will be the row index
t        % Duplicate. This will be the column index
3$       % Specify that the next function will take 3 inputs
)        % Index the 8×8 matrix with the two vectors. Gives a 15×15 matrix

Step 3
The stack now contains the 15×15 matrix resulting from step 2.
'DtdTX.' % Push this string
w        % Swap the two elements in the stack. This brings the matrix to the top
)        % Index the string with the matrix

This is really, really, cool.

I like this answer in general, though it 'itches' a bit as you use 8 characters to create a vector of length 8. Have you considered obtaining the numbers by a mathematical sequence? Didn't find anything sweet yet but especially the last 7 show such a nice pattern. For instance ceil((1:7)^4/500)

@DennisJ Thanks! Yes, it feels too much. I'll try that later, on the phone now

JavaScript (ES6), 112 bytes
a=Math.abs,f=(n=239)=>n?f(n-1)+(i=a(n%16-8),j=a((n>>4)-7),d=i%7^j%7,n&15?d%4?".":"XdtDDDDTddtd"[(i|j)+d]:`
`):''

JavaScript (ES5), 121 bytes
c="";for(a=-8;8>++a;)for(j=0>a?-a:a,b=-8;9>++b;)i=0>b?-b:b,d=i%7^j%7,c+=i-8?d%4?".":"XdtDDDDTddtd"[(i|j)+d]:"\n";alert(c)

The ES5 version trades a handwritten Math.abs(), two for loops and the output via alert for the unavailable recursive concise arrow function.
Both versions use the idea in the Ruby/C answer above, by Level River St. Using binary | instead of + shortens the defining string, d stays positive when diffing by ^ instead of -.

As far as I can tell, this produces output by putting it in a variable, which is disallowed. However, if you fix up the output formatting a bit, you've managed to outgolf both Neil and Arnauld!

Thanks, @redwolf, I was not aware of the rules. Done. And I added an ES6 answer.

impressive answer! small improvement: (n&15) -> n%16

Thanks, @ngn. While developing I worked with both positive and negative n, the % operator is symmetric and doesn't work in that place. With non-negative n this is fine.

Ruby, 103 97 bytes
Thanks to Mitch Schwartz for a 6 byte improvement on the iterations.
a=(-7..7).map &:abs
a.map{|i|puts a.map{|j|(d=i%7-j%7)%4<1?'X d t DTDdDdDtT d'[i+j+d*d/3]:?.}*''}

A similar but significantly different approach to my original answer below. As before, we use the fact that a letter must be printed if i%7-j%7 is equal to 0 or 4. But here we store that difference in d and use the formula i+j+d*d/3 to give an integer which is unique (up to symmetry) to that particular coloured square. Then we just look it up in the magic string.
Just for fun: C version of this approach, 120 bytes
z,i,j,d;f(){for(z=240;z--;)i=abs(z%16-8),j=abs(z/16-7),putchar(i-8?(d=i%7-j%7)%4?46:"X d t DTDdDdDtT d"[i+j+d*d/3]:10);}

Ruby, 115 113  bytes
2 bytes saved thanks to Value Ink.
(k=-7..7).map{|y|k.map{|x|i=x.abs;j=y.abs
$><<=(i%7-j%7)%4<1?"#{'XdTdT'[(i+j)/3]}dtDDDD"[[i%7,j%7].min]:?.}
puts}

Explanation
The origin is considered to be the centre of the board.
A letter must be printed if the x and y coordinates of the square have magnitudes that are identical or differ by 4. The only exceptions are on the outer edge of the board, but these follow the same pattern as the central row/column of the board, so we can use the same condition if we take the x and y coordinates modulo 7.
The choice of letter displayed is based on the coordinate of minimum magnitude. In this way the doubles and triples at (1,5) and (2,6) follow the same rule as at (1,1) and (2,2) and are obtained from the 7 character string "#{formula}dtDDDD" This does not cover all variations for the edge and centreline squares, so the first character of the string is calculated from the formula 'XdTdT'[(i+j)/3].
(k=-7..7).map{|y|
  k.map{|x|
    i=x.abs;j=y.abs
    print (i%7-j%7)%4<1?      #IF this expression is true print a letter
    "#{'XdTdT'[(i+j)/3]       #select 1st character of magic string where [i%7,j%7].min==0
     }dtDDDD"[[i%7,j%7].min]: #remaining 6 characters of magic string for diagonal
    ?.                        #ELSE print .
  }
  puts                        #at the end of the row print a newline
}

(k=-7..7).map{|y|k.map{... is 2 bytes shorter than your double -7.upto(7) technique.

A few modifications to save 6 bytes: a=(-7..7).map &:abs;a.map{|i|puts a.map{|j|(d=i%7-j%7)%4<1?'X d t DTDdDdDtT d'[i+j+d*d/3]:?.}*''}

brainfuck, 598 596 590 bytes
Golfing tips welcome.
>-[++++[<]>->+]<[>++++>+++++>+++>++<<<<-]>[>>>>+>+>+<<<<<<-]<++++++++++[>+>>>>+>-<<<<<<-]>>+>->>-->++.<<..>.<...>>.<<...>.<..>>.<<<<<.>>>.<.>...<<.>>...<<.>>...<.>.<<<.>>>..<.>...>.<.>.<...<.>..<<<.>>>>.<..<.>...>.<...<.>..>.<<<<.>>>....<.>.....<.>....<<<.>>>.<<.>>...<<.>>...<<.>>...<<.>>.<<<.>>>..>.<...>.<.>.<...>.<..<<<.>>>>>.<<..>.<...>>>----.<<<...>.<..>>.<<<<<.>>>..>.<...>.<.>.<...>.<..<<<.>>>.<<.>>...<<.>>...<<.>>...<<.>>.<<<.>>>....<.>.....<.>....<<<.>>>>.<..<.>...>.<...<.>..>.<<<<.>>>..<.>...>.<.>.<...<.>..<<<.>>>.<.>...<<.>>...<<.>>...<.>.<<<.>>>>>.<<..>.<...>>.<<...>.<..>>.

Explanation
Initialize the tape to [10 116 68 46 100 84 92] i.e. [nl t D . d T \]
>-[++++[<]>->+]<[>++++>+++++>+++>++<<<<-]>[>>>>+>+>+<<<<<<-]<++++++++++[>+>>>>+>-<<<<<<-]>>+>->>-->++
Each line here then prints one line of the board.
The middle line also decreases 92 to 88 i.e. \ to X
.<<..>.<...>>.<<...>.<..>>.<<<<<.
>>>.<.>...<<.>>...<<.>>...<.>.<<<.
>>>..<.>...>.<.>.<...<.>..<<<.
>>>>.<..<.>...>.<...<.>..>.<<<<.
>>>....<.>.....<.>....<<<.
>>>.<<.>>...<<.>>...<<.>>...<<.>>.<<<.
>>>..>.<...>.<.>.<...>.<..<<<.
>>>>>.<<..>.<...>>>----.<<<...>.<..>>.<<<<<.
>>>..>.<...>.<.>.<...>.<..<<<.
>>>.<<.>>...<<.>>...<<.>>...<<.>>.<<<.
>>>....<.>.....<.>....<<<.
>>>>.<..<.>...>.<...<.>..>.<<<<.
>>>..<.>...>.<.>.<...<.>..<<<.
>>>.<.>...<<.>>...<<.>>...<.>.<<<.
>>>>>.<<..>.<...>>.<<...>.<..>>.

Try it online!

Tips for BF: don't ascii golf in BF; nice strategy though.

PowerShell v2+, 147 143 bytes
($x='T..d...T...d..T')
($y='.D...t..','..D...d.','d..D...d','....D...','.t...t..','..d...d.'|%{$_+-join$_[6..0]})
'T..d...X...d..T'
$y[5..0]
$x

Try it online!
Takes advantage of how the default Write-Output at end of program execution handles arrays (i.e., it inserts a newline between elements). Might be a better way to generate the middle of the board -- I'm still working at it.
The first line outputs the top line of the board, also storing it in $x for use later.
The next line generates all the Double-Word lines by taking the left "half" of each, mirroring them (the -join$_[6..0] statement), and storing them as elements in array $y.
The next line is the middle row, with an X in the middle, thanks to -replace.
The next line outputs $y in reverse order, giving us the bottom Double-Word lines.
The final line is just $x again.
PS C:\Tools\Scripts\golfing> .\draw-empty-scrabble-board.ps1
T..d...T...d..T
.D...t...t...D.
..D...d.d...D..
d..D...d...D..d
....D.....D....
.t...t...t...t.
..d...d.d...d..
T..d...X...d..T
..d...d.d...d..
.t...t...t...t.
....D.....D....
d..D...d...D..d
..D...d.d...D..
.D...t...t...D.
T..d...T...d..T

-4 bytes thanks to Veskah.

Hard-coding the middle line saves 4 bytes

><> (Fish), 153 Bytes
\!o;!?l
\'T..d...T...d..T'a'.D...t...t...D.'a'..D...d.d...D..'a'd..D...d...D..d'a'....D.....D....'a'.t...t...t...t.'a'..d...d.d...d..'a'T..d...'
\'X/'02p

A horribly, awfully, inefficient way of doing things. Currently looking into a way of shortening it down by mirroring both horizontally and vertically properly.
Try it online! (If you don't want to be there all day make sure you either set execution speed to max or run without the animation.)

05AB1E, 57 53 bytes
Code
•jd]31‚ŽÔc¦Ïïì¹Ep.Üì8Ìa;“•6B4ÝJ".TdDt"‡5'.3×:Â'Xý15ô»

Uses the CP-1252 encoding. Try it online!

Explanation (outdated)
The •4ç“–šã&$W§ñçvßÖŠ_æá_VFÛÞýi~7¾¬ÏXôc•5B decompresses to this number:
1002000100020010400030003000400040002020004002004000200040020000400000400000300030003000300020002020002001002000

With 4ÝJ".TdtD"‡, we transliterate the following in this big number:
0 -> .
1 -> T
2 -> d
3 -> t
4 -> D

We bifurcate the whole string, leaving the string and the string reversed on the stack and join them by "X" using ý. We split the entire string into pieces of 15 using th 15ô code and join the whole array by newlines using ».

û€û should be a built-in ;).

"TdTDtDddDdDttddTdX"S•1‘o²–•4BS>'.×.ιJ8ôû€û» 44 bytes with interleave.

C, 146 145 142 138 bytes
i,r,c;main(){for(;i<240;)r=abs(i/16-7),c="T..12..0..12..0"[r+7-abs(i%16-7)],putchar(++i%16?c&4?c:"Xd.dd.tt.D..D.dD.dD.tTd."[c%4+r*3]:10);}

Try it online!
1 byte5 bytes saved thanks to Level River St
This exploits the diagonal pattern of the board for encoding.  In particular, if we take the top left quadrant of the board and align the diagonal, we get:
       T..d...T
      .D...t..
     ..D...d.
    d..D...d
   ....D...
  .t...t..
 ..d...d.
T..d...X

...a lot of the columns now line up.  If we encode columns in a line this way:
       0..12..0 y/012/Td./
      .0..12..  y/012/D.t/
     ..0..12.   y/012/D.d/
    2..0..12    y/012/D.d/
   12..0..1     y/012/D../
  .12..0..      y/012/tt./
 ..12..0.       y/012/dd./
T..12..0        y/012/Xd./

...then the board pattern can be collapsed into a 15 character string: T..12..0..12..0; and we simply need the right mappings for each row.
With that in mind, here's an expanded version with comments:
i,r,c;
main() {
   for(;i<240;)  // one char per output including new line
   r=abs(i/16-7) // row; goes from 7 to 0 and back to 7.
   , c="T..12..0..12..0"[r+7-abs(i%16-7)] // pattern char
   , putchar(++i%16 // if this is 0 we need a new line
   ? c&4 // hash to distinguish 'T' and '.' from '0', '1', '2'
     ? c // print 'T' and '.' literally
     : "Xd.dd.tt.D..D.dD.dD.tTd."[c%4+r*3] // otherwise look up replacement char
   : 10 // print the new line
   );
}

Very nice. 1. you can submit a function instead of a program, so i,r,c;f()is fine. 2. (i%16-7)%8 -> i%16-7&7 3. I think c-48 -> c%4 works, doesnt it?

Oops, sorry, functions have to be reusable, so f() would require an addtional i=0 inside the function so it wouldn't save anything.

Thanks for comments!  2 won't work either (%8 uses the implementation's negative moduli to map %16 values 0..15 to -7..7; &7 would map this to 0..7,0..7).  But, yes, 3 will absolutely work... will update when I get a chance.

@LevelRiverSt  Mea culpa; 2 still won't strictly work, but I didn't need that stuff anyway.

05AB1E, 49 44 bytes
•1nÑ=}íge/Þ9,ÑT‰yo¬iNˆå•6B8ôû€û»5ÝJ".TtdDX"‡

Try it online!
Explained:
Push: 1003000104000200004000303004000300004000020002000030003010030005
Split into chunks of 8, palindromize each.
Palindromize again.
Replace numbers with characters.

Other Idea (Someone Try this in MATL)
Seeing as EVERYTHING is garunteed to have a period inbetween it...
Count the number of zeros inbetween each piece:
1003000104000200004000303004000300004000020002000030003010030005
^  ^   ^ ^   ^    ^   ^ ^  ^   ^    ^    ^   ^    ^   ^ ^  ^   ^

131424334342233135 => w\F6ß¿
Taking the counts of zeros runs:
23134312344343123 => ì:¼˜¾
Then you would decrypt and transpose them together.
Using them in 05AB1E (results in a +5 byte increase):
05AB1E, 27 bytes
•w\F6ß¿•6BS•ì:¼˜¾•5BS0×‚øJJ

Try it...

Meta-golfed entry:
05AB1E, 104 bytes
•G¨J´JÏÍ?»"”Ö3úoÙƒ¢y”vf%¯‚6À°IÕNO’Å2Õ=ÙŠxn®žÑŸ¶¼t¨š,Ä]ÓŽÉéÈºÂ/ø‡ŸÖ|e³J—Ë'~!hj«igÄ‹Î‚wî’©•7BžLR"
.DTXdt"‡

Try it!
Meta-golfed using my meta-golfer for ASCII art:
https://tio.run/nexus/05ab1e#JY9NSgNBEIWvUo4/qAQxyfi30yAioiAiuBM6M9U9DT3doao7ccBFrhI3ooss3QguJniRXCR2x01RfK9479Xqtf2@XHy2H78/tw/L6aydq8VXr5sPsuX0LeP1jCwbJD3r54v3dp5mFGbZzWp1wXBPyLpE6@GRQj0C1spiCQJ4gjjSVgG@YBG8HiM4KpHAWbgiXYqmA1wF79ONrxCGa5nBOyCUQSEyCFuCi2LEklwNjGO0YAQpNA3cBTa6hsIF60kjd9Y@jAWhF9SAk1C5Gk1yiTSQ9g1MBKcKAp4q7RGuXWCMFlYioS3iKowBhf@9Kh2DNbEHGSIexhSZeDRIUcq4oTDxDS09aAsjZ3TRHGycb25tP@/s7@51e/386Pjk9OzwDw

Python 3, 138 bytes
d=lambda s:s+s[-2::-1]
print(*d(list(map(d,'T..d...T .D...t.. ..D...d. d..D...d ....D... .t...t.. ..d...d. T..d...X '.split()))),sep='\n')

Change list(map(A)) to [*map(A)], saves 3 bytes (requires Python 3.5+).

Charcoal, 33 bytes (noncompeting)
All credit for this answer goes to @DLosc.
T↑↑↘tdd↗→→↖XdtDDDD↓T..d‖Ｏ⟦↗→↓⟧ＵＢ.

Try it online!
Verbose
Print("T")
Move(:Up)
Move(:Up)
Print(:DownRight, "tdd")
Move(:UpRight)
Move(:Right)
Move(:Right)
Print(:UpLeft, "XdtDDDD")
Print(:Down, "T..d")
ReflectOverlap([:UpRight, :Right, :Down])
SetBackground(".")

Try it online!

The perfect tool for this challenge, with it's diagonal printing capabilities. +1 (and also cool to see a background method like that for ASCII)

Canvas, 30 bytes
TDDDDtdX＼tdd＼６２╋d４１╋T８１╋：⤢ｎ┼.ｒ

Try it here!
A different enough approach to the existing Canvas answer to justify its own post, I think.
Constructs the art as follows:
T
 D
  D
   D
    D
     t
      d
       X

T
 D   t
  D   d
   D   d
    D
     t
      d
       X

T  d
 D   t
  D   d
   D   d
    D
     t
      d
       X

T  d   T
 D   t
  D   d
   D   d
    D
     t
      d
       X

T  d   T
 D   t
  D   d
d  D   d
    D
 t   t
  d   d
T  d   X

T  d   T   d  T
 D   t   t   D
  D   d d   D
d  D   d   D  d
    D     D
 t   t   t   t
  d   d d   d
T  d   X   d  T
  d   d d   d
 t   t   t   t
    D     D
d  D   d   D  d
  D   d d   D
 D   t   t   D
T  d   T   d  T

T..d...T...d..T
.D...t...t...D.
..D...d.d...D..
d..D...d...D..d
....D.....D....
.t...t...t...t.
..d...d.d...d..
T..d...X...d..T
..d...d.d...d..
.t...t...t...t.
....D.....D....
d..D...d...D..d
..D...d.d...D..
.D...t...t...D.
T..d...T...d..T

well done! I figured this would work better. it might be even shorter constructing the top right quadrant instead and using simple overlap

Javascript (ES6), 150 bytes
_=>(r='',"T2d3T3d2T.D3t3t3D3D3d.d3D2d2D3d3D2d4D5D5t3t3t3t3d3d.d3d2T2d3".replace(/./g,c=>(c=+c?'.'.repeat(c):c,r=c+r,c))+'X'+r).match(/.{15}/g).join`
`

How it works
The string "T2d3T3d2T.D3t3t3D3D3d.d3D2d2D3d3D2d4D5D5t3t3t3t3d3d.d3d2T2d3" describes the board from its top left corner to the square just before the 'X', with consecutive empty squares encoded as digits. The replace() function both unpacks the empty squares and builds the mirror string r for the bottom of the board. Then both parts are put together and carriage returns are inserted every 15 characters.
Demo

let f =
_=>(r='',"T2d3T3d2T.D3t3t3D3D3d.d3D2d2D3d3D2d4D5D5t3t3t3t3d3d.d3d2T2d3".replace(/./g,c=>(c=+c?'.'.repeat(c):c,r=c+r,c))+'X'+r).match(/.{15}/g).join`
`
console.log(f())

C 234 Bytes
#define g(t) while(i++<8)putchar(*b++);b-=2;--i;while(--i>0)putchar(*b--);putchar('\n');b+=t;
char*r="T..d...T.D...t....D...d.d..D...d....D....t...t....d...d.T..d...X";i;f(){char*b=r;do{g(9);}while(*b);b-=16;do{g(-7);}while(b>=r);}

Here's the output:
T..d...T...d..T
.D...t...t...D.
..D...d.d...D..
d..D...d...D..d
....D.....D....
.t...t...t...t.
..d...d.d...d..
T..d...X...d..T
..d...d.d...d..
.t...t...t...t.
....D.....D....
d..D...d...D..d
..D...d.d...D..
.D...t...t...D.
T..d...T...d..T

JavaScript (ES6), 221 bytes

f=
_=>(a=[...Array(15)].map(_=>Array(15).fill`.`),r=([c,i,j])=>[a[i][j]=a[k=14-i][j]=a[i][j=14-j]=a[k][j]=c,j,i],[..."TDDDDtdX"].map((c,i)=>r([c,i,i])),"d30t51d62d73T70".replace(/.../g,s=>r(r(s))),a.map(a=>a.join``).join`
`)
;o.textContent=f()
<pre id=o>

Since I went to the trouble of creating this I thought I'd post it anyway even though there's a clearly superior solution available.

Canvas, 33 bytes
“e+╪>ｖ.２eC｝¼Ｐ↕V⁸╋ＵＳF∔uiＴ═Ｉk¼‟８ｎ┼┼

Try it here!
uses a huge compressed string and quad palidromizes it. Can probably be shortened by adding the main diagonal later.

Haskell, 114 bytes
g=(++)<*>reverse.init
unlines$g$g<$>words"T..d...T .D...t.. ..D...d. d..D...d ....D... .t...t.. ..d...d. T..d...X"

g in a non-pointfree version is g x = x ++ (reverse (init x)). It is applied once per (half-)line and again on the result.

GNU sed, 219 205 bytes
s/$/T..d...T...d..T/p;h
s/.*/.D...t...t...D./p;G;h
s/.*/..D...d.d...D../p;G;h
s/.*/d..D...d...D..d/p;G;h
s/.*/....D.....D..../p;G;h
s/.*/.t...t...t...t./p;G;h
s/.*/..d...d.d...d../p;G;h
s/.*\n//;s/T/X/2p;g

Taking advantage of the mirror symmetry of the board, the second half is the first one that was stored in reverse order in the hold space.

sh + coreutils, 119 bytes
This is a binary file. Shown as hexdump:
00000000  74 61 69 6c 20 2d 63 39  34 20 24 30 7c 67 75 6e  |tail -c94 $0|gun|
00000010  7a 69 70 0a 65 78 69 74  0a 1f 8b 08 00 2e ec ca  |zip.exit........|
00000020  57 00 03 65 4f c9 0d c0  30 08 fb 7b 18 4f 91 11  |W..eO...0..{.O..|
00000030  fc e8 00 1e a1 fb ab 08  68 a4 90 07 60 d9 98 43  |........h...`..C|
00000040  a4 49 8a 59 05 ae 40 6f  c7 22 98 84 b3 29 10 fc  |.I.Y..@o."...)..|
00000050  13 59 1d 7a 11 9d b1 bd  15 a8 56 77 26 54 c4 b3  |.Y.z......Vw&T..|
00000060  f7 0d fd f6 9f f3 ef fd  e7 7d f3 7e 8d ff 3e 05  |.........}.~..>.|
00000070  57 d9 a0 f0 00 00 00                              |W......|
00000077

Here's the base64 form so you can copy/paste it:
begin-base64 755 test.sh
dGFpbCAtYzk0ICQwfGd1bnppcApleGl0Ch+LCAAu7MpXAANlT8kNwDAI+3sY
T5ER/OgAHqH7qwhopJAHYNmYQ6RJilkFrkBvxyKYhLMpEPwTWR16EZ2xvRWo
VncmVMSz9w399p/z7/3nffN+jf8+BVfZoPAAAAA=
====

C 230 228 Bytes
char *s="T.D..Dd..D....D.t...t..d...dT..d...X";
int x,y,a,b;
#define X(N) {putchar(s[a]);N y<=x?1:y;}
#define P for(y=1;y<8;y++)X(a+=)for(y--;y+1;y--)X(a-=)puts("");
main(){for(;x<8;x++){a=b+=x;P}for(x=6;x+1;x--){a=b-=(x+1);P}}

try it on ideone
This is an attempt at improving the original C version posted that had quarter of board stored in a C array. Not as short as I was hoping for.  This version only has one eighth of the board stored.
Ungolfed:
char *s="T.D..Dd..D....D.t...t..d...dT..d...X";
int x,y,a,b;
main(){
    for(x = 0; x < 8; x++){
        a=b+=x;
        for(y = 1; y < 8; y++){
            putchar(s[a]);
            a += y<=x ? 1 : y;
        }
        for(y--; y >= 0; y--){
            putchar(s[a]);
            a -= y<=x ? 1 : y;
        }
        puts("");
    }
    for(x=6; x >= 0; x--){
        a=b-=(x+1);
        for(y = 1; y < 8; y++){
            putchar(s[a]);
            a += y<=x ? 1 : y;
        }
        for(y--; y >= 0; y--){
            putchar(s[a]);
            a-= y<=x ? 1 : y;
        }
        puts("");
    }
}

05AB1E, 40 bytes
•7â∍û¯øÉ»₄XÍ«Ÿ=SPтŸƶR±•".TdDtX"Åв8äJ€ûû»

Try it online!
•...•".TdDtX"Åв8äJ€ûû»  # trimmed program
                     »  # join...
             Åв         # list of characters of...
     ".TdDtX"           # literal...
             Åв         # with indices in base-10 values of base length of...
     ".TdDtX"           # literal...
             Åв         # digits of...
•...•                   # 10654502656792583423375424705593131734076028132261...
                ä       # split into...
               8        # literal...
                ä       # equal length pieces...
                        # (implicit) with each element...
                 J      # joined...
                  €     # with each element...
                   û    # concatenated with itself reversed excluding the first character...
                    û   # concatenated with itself reversed excluding the first element...
                     »  # by newlines
                        # implicit output

Excel, 115 bytes
=LET(j,8-ABS(8-ROW(1:15)),k,TRANSPOSE(j),n,IF(k>j,k,j),MID("T.D..Dd..D....D.t...t..d...dT..d...X",n*(n-3)/2+j+k,1))

Link to Spreadsheet

Vyxal, 242 bytes
Try it online!
`T..d...T...d..T
.D...t...t...D.
..D...d.d...D..
d..D...d...D..d
....D.....D....
.t...t...t...t.
..d...d.d...d..
T..d...X...d..T
..d...d.d...d..
.t...t...t...t.
....D.....D....
d..D...d...D..d
..D...d.d...D..
.D...t...t...D.
T..d...T...d..T`,

For answer number 4, we have the empty Scrabble board in its natural habitat.