text:
Count rotary dial pulses in a phone number (including letters)
In your grandparents' day, dialing a phone number was done with a rotary dial like this:

To dial each digit, put your finger in the corresponding hole, pull it over to the finger stop, and release it.  A mechanism will cause the dial to spin back to its resting position, and the phone will disconnect and reconnect a circuit a specified number of times, making audible clicks.
Dialing the digit N requires N such “pulses”, except for N=0 which is ten pulses.
Rotary phones have the property that large digits (8, 9, 0) take longer to dial than small digits (1, 2, 3).  This was an important consideration in drawing up early area code maps, and why New York City with its heavy population (and phone line) density got 212 (only 5 pulses), while while 907 (26 pulses) went to sparsely-inhabited Alaska.  Of course, this all became irrelevant when touch-tone dialing became popular.
The challenge
Write, in as few bytes as possible, a program or function that takes as input a string (or sequence of characters) containing a telephone number, and outputs its number of rotary dial pulses.  These are to be counted as follows:
Digits

Digits 1-9 count as that number of pulses.
Digit 0 counts as 10 pulses.

Letters
Note that digits 2-9 on the dial have letters of the Latin alphabet associated with them.  These were originally intended for named exchanges, but were latter re-appropriated for phonewords, and for text message input systems.
You must support having letters in your phone numbers, using the E.161 assignment of letters to digits:

A, B, C = 2
D, E, F = 3
G, H, I = 4
J, K, L = 5
M, N, O = 6
P, Q, R, S = 7
T, U, V = 8
W, X, Y, Z = 9

You may assume that the input has already been case-folded, to either upper or lower case.
Other characters
You must allow arbitrary use of the characters ()+-./ and space as formatting separators.  You may chose to allow any non-alphanumeric character for this purpose, if it's easier to implement.
These characters do not contribute to the pulse count.
Example code
A non-golfed lookup table and function in Python:
PULSES = {
    '1': 1,
    '2': 2, 'A': 2, 'B': 2, 'C': 2,
    '3': 3, 'D': 3, 'E': 3, 'F': 3,
    '4': 4, 'G': 4, 'H': 4, 'I': 4,
    '5': 5, 'J': 5, 'K': 5, 'L': 5,
    '6': 6, 'M': 6, 'N': 6, 'O': 6,
    '7': 7, 'P': 7, 'Q': 7, 'R': 7, 'S': 7,
    '8': 8, 'T': 8, 'U': 8, 'V': 8,
    '9': 9, 'W': 9, 'X': 9, 'Y': 9, 'Z': 9,
    '0': 10
}

def pulse_count(phone_num):
    return sum(PULSES.get(digit, 0) for digit in phone_num)

Example input and output

911 → 11
867-5309 → 48
713 555 0123 → 42
+1 (212) PE6-5000 → 57
1-800-FLOWERS → 69
PUZZLES → 48

I assume that the Arbitrary ASCII punctuation and spaces are restricted to those normally used for phone numbers (+- ()*#.) just like letters are restricted to uppercase. Correct me if I'm wrong.

@Adám: I've restricted the required punctuation marks to just a few common separators.  It deliberately does not include * and #, which have special meanings on touch-tone phones and are not dialable on rotaries.

Can we use all-lowercase input instead of all-uppercase? Can we take an array of chars instead of a string?

@Grimy: Sure.  I've edited the question accordingly.

I'm a time traveller! I'm a time traveller! I'm a time traveller! Since I definitely used phones like this when I was a kid, clearly I AM MY OWN GRANDFATHER!!!!!!! Which is actually pretty icky when I think about it. Bleah!!!

I'm the grandfather.  I used phones like this in the 1950s.  And when I moved to a town in a rural location, I discovered that the phone company did not offer touch-tone service.  This was in 1985!  No kidding!  My grandmother had a phone in the parlor that had a hook and a crank.  You took the earpiece off the hook, and turned the crank to obtain a switchboard operator.  She had to replace it when direct distance dialing was set up.

Since Z seems to be special cased in many of the answers, a test case containing it might be useful.

Ha! I used dial numbers by hitting the disconnect button as fast as I can, sometimes it worked great

05AB1E, 19 18 17 15 bytes
AÁ0ªā6+žq÷9š‡þO

Try it online!
This is the first answer to use π. Why use π, you might ask? Well, the letters are associated with 22233344455566677778889999, in order. Notice how most digits repeat 3 times, but 7 repeats 4 times. You could say that each digit repeats (3+1/7) times, on average. I wonder if there’s any number that’s approximately 3+1/7 and takes fewer bytes than 22/7…
This only gives 4 7s, not 4 9s, so we still need to handle Z as a special case.
A               # alphabet (abcdefghijklmnopqrstuvwxyz)
 Á              # rotate right (zabcdefghijklmnopqrstuvwxy)
  0ª            # append 0 (zabcdefghijklmnopqrstuvwxy0)

ā6+             # range [7..33]
   žq÷          # divide by π (22233344455566677778889991010)
      9š        # prepend 9 (922233344455566677778889991010)

‡               # transliterate the implicit input with the two lists above
                # this replaces z → 9, a → 2, … y → 9, 0 → 10
 þ              # remove all non-digits
  O             # sum

Why lowercase instead of uppercase?

@dan04 because 05AB1E has a built-in to push "abcdefghijklmnopqrstuvwxyz", but not for "ABCDEFGHIJKLMNOPQRSTUVWXYZ". I could convert the alphabet to uppercase rather than convert the input to lowercase, but that’s the same bytecount.

I've edited the question to make your first two commands unnecessary.

How did you figure out the pi trick?

@Jonah I started with the idea of dividing a range by a constant to get the desired sequence, then while looking for the best way to express "slightly more than 3" in 05AB1E I remembered pi was a built-in.

C# (Visual C# Interactive Compiler), 51 bytes
n=>n.Sum(x=>x>64?(x-59-x/83-x/90)/3:x>47?1-~x%~9:0)

Saved 1 byte thanks to @recursive
Saved 10 bytes thanks to @ExpiredData's observation that only () +-/. will be in the input
Try it online!
n =>                     // Function taking input as string
  n.Sum(x =>             // Map each value 'x' through the following
    x>64 ?               //   If 'x' is an uppercase letter
      (x-59-x/83-x/90)/3 //     Take each char's ASCII value subtracted by 59, and subtract
                         //     one if the char is 'S' and one if the char is 'Z'
    : x>47 ?             //   Else if the char is a digit
      1-~x%~9            //   Take 1 - (-x - 1) % -10 (Maps 0 to 10, and 1-9 to themselves
    : 0                  //   Else, 0
  )                      // And sum it all up, then return it

-10 is ~9, which should work in context.

@recursive That's smart, thanks

x<91 check is redundant since the input will only consist of ()+-./ the space key and numbers which are all < 64 hence we can determine if the character is uppercase simply by checking x>64 (so -5 bytes)

Same goes for the x<58 check, since nothing in the range 58-64 will be in the input

51 bytes

Python 2, 74 bytes
lambda s:sum([(n-59-n/83-n/90)/3,1-~n%~9][n<58]for n in map(ord,s)if n>47)

Try it online!
Does some arithmetic on the ASCII value for each character. The first option checks for letters and the second options checks for numbers. The clarification that all punctuation characters allowed in the input are ones with ASCII values less than 48 let me simplify the logic, but a new method altogether might now be better.
Python 2, 84 bytes
lambda s:sum(1+'1xxxx2ABCx3DEFx4GHIx5JKLx6MNOx7PQRS8TUVx9WXYZ0'.find(c)/5for c in s)

Try it online!
Uses a hardcoded lookup string, with each block of 5 characters corresponding to the characters giving each value starting with 1. Blank spaces are filled with x, which can't be in the input which is capitalized. Fortuitously, characters not appearing in the string produce -1 for the .find which gives a summand of zero.

JavaScript (Node.js), ... 76 69 bytes
s=>s.replace(/\w/g,q=>w+=1/q?+q||10:parseInt(q,35)*.32-1|0||9,w=0)&&w

Try it online!
-7 thanks @Arnauld!
Explanation
 q |     1/q     |  +q  | parseInt(q,35)*.32 | parseInt(q,35)*.32-1|0 | Output
---+-------------+------+--------------------+------------------------+--------
 0 | Infinity(T) | 0(F) |         N/A        |           N/A          |   10
 1 |  1.0000(T)  | 1(T) |         N/A        |           N/A          |    1
 2 |  0.5000(T)  | 2(T) |         N/A        |           N/A          |    2
 3 |  0.3333(T)  | 3(T) |         N/A        |           N/A          |    3
 4 |  0.2500(T)  | 4(T) |         N/A        |           N/A          |    4
 5 |  0.2000(T)  | 5(T) |         N/A        |           N/A          |    5
 6 |  0.1666(T)  | 6(T) |         N/A        |           N/A          |    6
 7 |  0.1428(T)  | 7(T) |         N/A        |           N/A          |    7
 8 |  0.1250(T)  | 8(T) |         N/A        |           N/A          |    8
 9 |  0.1111(T)  | 9(T) |         N/A        |           N/A          |    9
 A |    NaN(F)   |  N/A |        3.20        |          2(T)          |    2
 B |    NaN(F)   |  N/A |        3.52        |          2(T)          |    2
 C |    NaN(F)   |  N/A |        3.84        |          2(T)          |    2
 D |    NaN(F)   |  N/A |        4.16        |          3(T)          |    3
 E |    NaN(F)   |  N/A |        4.48        |          3(T)          |    3
 F |    NaN(F)   |  N/A |        4.80        |          3(T)          |    3
 G |    NaN(F)   |  N/A |        5.12        |          4(T)          |    4
 H |    NaN(F)   |  N/A |        5.44        |          4(T)          |    4
 I |    NaN(F)   |  N/A |        5.76        |          4(T)          |    4
 J |    NaN(F)   |  N/A |        6.08        |          5(T)          |    5
 K |    NaN(F)   |  N/A |        6.40        |          5(T)          |    5
 L |    NaN(F)   |  N/A |        6.72        |          5(T)          |    5
 M |    NaN(F)   |  N/A |        7.04        |          6(T)          |    6
 N |    NaN(F)   |  N/A |        7.36        |          6(T)          |    6
 O |    NaN(F)   |  N/A |        7.68        |          6(T)          |    6
 P |    NaN(F)   |  N/A |        8.00        |          7(T)          |    7
 Q |    NaN(F)   |  N/A |        8.32        |          7(T)          |    7
 R |    NaN(F)   |  N/A |        8.64        |          7(T)          |    7
 S |    NaN(F)   |  N/A |        8.96        |          7(T)          |    7
 T |    NaN(F)   |  N/A |        9.28        |          8(T)          |    8
 U |    NaN(F)   |  N/A |        9.60        |          8(T)          |    8
 V |    NaN(F)   |  N/A |        9.92        |          8(T)          |    8
 W |    NaN(F)   |  N/A |       10.24        |          9(T)          |    9
 X |    NaN(F)   |  N/A |       10.56        |          9(T)          |    9
 Y |    NaN(F)   |  N/A |       10.88        |          9(T)          |    9
 Z |    NaN(F)   |  N/A |         NaN        |          0(F)          |    9

All of [space]().+-/ are not captured by /\w/g, so they won't affect the total.

Perl 5 -p, 52 51 bytes
@Grimy gets credit for -1
y/A-Z/22233344455566677778889/;map$\+=$_||10,/./g}{

Try it online!

/\d/g should be /./g for -1 (yes it still handles punctuation correctly).

APL (Dyalog Unicode), 27 bytesSBCS
Anonymous tacit prefix function.
+/'@ADGJMPTW'∘⍸+11|(1⌽⎕D)∘⍳

Try it online!
(…)∘⍳ find the ɩndex* of each character in the following string:
  * elements that are not found, get the index 1+the maximum index, i.e. 11
 ⎕D the digits: "0123456789"
 1⌽ cyclically rotate one step left; "1234567890"
11| division remainder when divided by 11*
  * this gives 0 for all non-digits
…+ add that to the following:
 '@ADGJMPTW'∘⍸ the ɩnterval ɩndex* for each character
  * So [−∞,"@") gives 0, ["@","A") gives 1, ["A","D") gives 2, etc.
+/ sum that

J, 39 bytes
1#.'?@CFILOSVZ'&I.+11|1+'1234567890'i.]

Try it online!
A port of Adám's APL solution

Nice use of interval index

@Jonah Thanks to Adam :)

Retina 0.8.2, 34 bytes
T`WTPMJGDA`Rd
}T`L`2L
0
55
\d
$*
1

Try it online! Link includes test cases. Explanation:
T`WTPMJGDA`Rd

Convert the letters WTPMJGDA to the digits 9..0.
}T`L`2L

Shuffle all the remaining letters down by 1 and repeat until all of the letters have been converted to digits.
0
55

Replace 0 with 55 as they take the same number of pulses to dial.
\d
$*
1

Take the digital sum.

C (gcc), 94 89 86 80 bytes
Thanks to ceilingcat, nwellnhof and Rogem for the suggestions.
c;f(char*s){c=*s-48;s=*s?(c<10U?c?c:10:c-17<26U?(c-11-c/35-c/42)/3:0)+f(s+1):0;}

Try it online!

80 bytes by using recursion instead of a loop.

Suggest c<43U instead of c-17<26U

K4, 44 bytes
Solution:
+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?

Examples:
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"911"
11
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"867-5309"
48
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"+1 (212) PE6-5000"
57
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"1-800-FLOWERS"
69

Explanation:
Naive approach, likely pretty golfable. Lookup index of character, lookup score, sum.
+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")? / the solution
                                           ? / lookup
                          (               )  / do this together
                                       "0"   / string "0"
                                      ,      / join with
                                  .Q.n       / string "0123456789"
                                1_           / drop first
                               ,             / join with
                           .Q.A              / "A..Z"
  (                      )                   / do this together
                      !10                    / range 0..9
                     ,                       / join with
     (              )                        / do this together
               4 3 4                         / list (4;3;4)
              ,                              / join with
         (5#3)                               / list (3;3;3;3;3)
        &                                    / where, creates list 0 0 0 1 1 1 2 2 etc
      1+                                     / add 1
   1+                                        / add 1
+/                                           / sum up

Perl 6, 53 bytes
{sum +<<m:g/\d/X||10}o{S:g[<:L>]=$/.ord*.313-28+|0+9}

Try it online!
Multiplies the ASCII code with 0.313 instead of 1/3 and uses bitwise OR which rounds to zero to get the correct bias.

Jelly, 33 24 bytes
7r32:ØP«9Ṿ€ØAżFyfØDV€o⁵S

Try it online!
A monadic link taking a string as its argument and returning the number of pulses. Rewritten inspired by @Grimy’s 05AB1E answer so be sure to upvote them!

Bash, 256 bytes
You can replace the (( … )) constructs with let for identical byte count.  There may be a good algorithm to reduce the case statements but not found it so far. With a bit of rework you could make it a function also (but not in same or less bytes unless you can discount the function fname { … } top and tail).
read p;while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; ([ABC) ((d+=2));; ([P-S]) ((d+=7));; ([W-Z]) ((d+=9));;([DEF]) ((d+=3));; ([GHI]) ((d+=4));; ([JKL]) ((d+=5));; ([MNO]) ((d+=6));; (?) d=$d; esac;p=${p#?};done;echo $d

Try it online!
A better solution using the map character technique makes use of the tr tool:
[Bash with tr], 173 bytes
read p;p=$(echo $p|tr A-Z 22233344455566677778889999);while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; (?) d=$d; esac;p=${p#?}; done;echo $d

Try it online!

One algorithm I missed of course is to do some string replacement/translation on A-Z.  This would be good.  I will amend the above to suit.

while((${#p})) works, saving three bytes.  c=${p:0:1};case c in ([0-9]) ((d+=c?c:10));; saves another 16.  With tr -dc 0-9 added to the tr pipeline you don't need a case statement at all and the addition can be folded into the while condition with &&.

Thanks OMG. I don't often use ternary assignment so I missed that.  Interesting use of delete complement as well (but that assumes like my solution ignore any other character).  I have managed to get it down to 133 bytes as in:
read p;p=$(echo $p|tr A-Z 22233344455566677778889999|tr -dc [0-9]);while ((${#p}));do c=${p:0:1}&&((d+=c?c:10));p=${p#?};done;echo $d

118: p=$(head -1|tr A-Z 22233344455566677778889|tr -dc 0-9);while((${#p}));do((d+=(c=${p:0:1})?c:10));p=${p#?};done;echo $d .. the last three 9's are not needed because tr will reuse the last replacement character if the second argument is too short.

99: read p;echo $p|tr A-Z 22233344455566677778889999|sed 's/[^0-9]//g;s/[1-9]/&+/g;s/0/10+/g;s/+$//'|bc

The first example can be stripped down from 256 to 236 by removing a few unnecessary spaces. read p;while((${#p}>0));do case ${p:0:1} in ([1-9])((d+=${p:0:1}));;([0])((d+=10));;([ABC)((d+=2));;([P-S])((d+=7));;([W-Z])((d+=9));;([DEF])((d+=3));;([GHI])((d+=4));;([JKL])((d+=5));;([MNO])((d+=6));;(?)d=$d;esac;p=${p#?};done;echo $d

Fair comment -- I decided not to do more golf on that one as the second approach was far better.

PowerShell,109 102 87 bytes
$(switch -r($args|% t*y){\d{$_}[A-Y]{("{0}"-f(.313*$_-18))[0]}[Z]{9}0{10}})-join'+'|iex

Try it online!
EDIT: Used @mazzy's idea for a regex switch with some string formatting to cast char -> int -> string and grab only the first 'digit'
Original:

[char[]]"$args"|%{$a+=(48,(('22233344455566677778889999')[$_-65],(58,$_)[$_-ne48])[$_-lt64])[$_-gt47]-=48};$a

I was hoping to get <100 bytes, so I'll keep looking at it to see if there is anything else I can do. There's probably a way to remove the number string
Sorry if this is confusing as I nested arrays with boolean indexing statements but -
Explanation:
[char[]]"$args"|%{ reads the input casted as a string and then explodes it to a char array and begins a for-each loop with checking ()[$_-gt47] to see if any ()+-./ was entered (all have ascii character values <48)
Note: Powershell accepts $true and $false as 1 and 0 respectively for array indices
Then we get either 48 for the symbols, or:
('22233344455566677778889999'[$_-65],(58,$_)[$_-ne48])[$_-lt64]
The [$_-lt64] checks for a number or a letter (all assumed capital here). If it's a letter, '22233344455566677778889999'[$_-65] changes it to 0-25 to index into the array and output the pulse value (as a char). If the character is a number, we instead look at: (58,$_)[$_-ne48] checking for 0 and outputting 58 or just the numeric char itself.
Around everything $a+= ... -=48 initializes a numeric variable $a at 0 and then adds the output. The output is the ascii char value of a number, so subtract 48.
Note: if the input was a symbol, we get $a+=48-48, effectively ignoring it. If it was 0, we get $a+=58-48 to obtain our +10
Lastly, ;$a just outputs our final value post for-each loop

you could save a few bytes Try it online!

Ah, yeah I had some extra parentheses and the = in there, left over from my previous methods of solving this, thanks for the catch! Though, I haven't seen the t*y before, could you explain why that works to explode the string into a character array?

https://codegolf.stackexchange.com/a/111526/80745 and https://codegolf.stackexchange.com/a/168174/80745

to get '< 100 bytes': Try it online! :)

good idea with -f and [0].

PowerShell, 95 85 79 bytes
inspired by nwellnhof's answer.
inspired by [0] from Sinusoid's answer.
$(switch -r($args|% t*y){\d{$_}0{10}[A-Y]{"$(.313*$_-18)"[0]}Z{9}})-join'+'|iex

Try it online!
Unrolled version:
$(
    switch -r($args|% toCharArray){
        \d    {$_}
        0     {10}
        [A-Y] {"$(.313*$_-18)"[0]}
        Z     {9}
    }
)-join '+'|Invoke-Expression

key .313*$_-18 "$(...)"[0]
--- ---------- -----------
  A      2.345 2
  B      2.658 2
  C      2.971 2
  D      3.284 3
  E      3.597 3
  F      3.910 3
  G      4.223 4
  H      4.536 4
  I      4.849 4
  J      5.162 5
  K      5.475 5
  L      5.788 5
  M      6.101 6
  N      6.414 6
  O      6.727 6
  P      7.040 7
  Q      7.353 7
  R      7.666 7
  S      7.979 7
  T      8.292 8
  U      8.605 8
  V      8.918 8
  W      9.231 9
  X      9.544 9
  Y      9.857 9

Team effort! :D

Stax, 21 bytes
éT6T&\²|└t5φ╛│█♪√┘↑▓^

Run and debug it

Kotlin, 113 bytes
{s:String->var t=0
for(c in s){val v=c-'0'
t+=when(v){0->10
in 1..9->v
in 17..42->(v-11-v/35-v/42)/3
else->0}}
t}

Try it online!

Python 3, 134 123 bytes
f=lambda n:sum(map(int,n.translate(n.maketrans('ADGJMPTWBEHKNQUXCFILORVYSZ','23456789'*3+'79','()+-./ '))))+10*n.count('0')

Try it online!
-11 bytes thanks to @dan04

By rearranging the letters to 'ADGJMPTWBEHKNQUXCFILNRVYSZ', you can reduce the string of numbers to '23456789'*3+'79'.

authors: Bob Jarvis - Слава Україні

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


text:
Construct a word ladder
Given a list of at least two words (made only of lowercase letters), construct and display an ASCII ladder of the words by alternating the direction of writing first to the right, then to the left, relatively to the initial direction from left to right.
When you finish writing a word, change the direction and only then start writing the next word.
If your language doesn't support lists of words, or it's more convenient for you, you can take the input as a string of words, separated by a single space.
Leading and trailing whitespaces are allowed.
["hello", "world"] or "hello world"
hello
    w
    o
    r
    l
    d

Here we start by writing hello and when we come to the next word (or in the case of the input as a string - a space is found), we change the relative direction to the right and continue to write world
Test cases:
["another", "test", "string"] or "another test string" ->

another
      t
      e
      s
      tstring

["programming", "puzzles", "and", "code", "golf"] or "programming puzzles and code golf" ->

programming
          p
          u
          z
          z
          l
          e
          sand
             c
             o
             d
             egolf

["a", "single", "a"] or "a single a" ->

a
s
i
n
g
l
ea

Wining criteria
The shortest code in bytes in every language wins. Don't let be discouraged by the golfing languages!
Sandbox

Related

@Arnauld Yes, I'll add it to the description.

Charcoal, 9 bytes
Ｆ⮌Ａ«↑⮌ι‖↗

Try it online! Link is to verbose version of code. Explanation: Works by drawing the text backwards, transposing the canvas after every word. 10 bytes for string input:
Ｆ⮌Ｓ≡ι ‖↗←ι

Try it online! Link is to verbose version of code. Explanation: Draws the text backwards, transposing the canvas for spaces.

C (gcc), 94 78 74 bytes
-4 from Johan du Toit

o,f;g(int*s){for(o=f=0;*s;s++)*s<33?f=!f:printf("\n%*c"+!f,f*(o+=!f),*s);}

Try it online!
Prints the ladder, one character (of the input) at a time. Takes a space-separated string of words.

Could change *s==32 into *s<33 to save a byte.

74 Bytes

05AB1E, 19 16 bytes
€θ¨õšøíJD€gs24SΛ

-3 bytes thanks to @Emigna.
Try it online.
General explanation:
Just like @Emigna's 05AB1E answer (make sure to upvote him btw!!), I use the Canvas builtin Λ.
The options I use are different however (which is why my answer is longer..):

b (the strings to print): I leave the first string in the list unchanged, and add the trailing character to each next string in the list. For example ["abc","def","ghi","jklmno"] would become ["abc","cdef","fghi","ijklmno"].
a (the sizes of the lines): This would be equal to these strings, so [3,4,4,7] with the example above.
c (the direction to print in): [2,4], which would map to [→,↓,→,↓,→,↓,...]

So the example above would step-by-step do the following:

Draw abc in direction 2/→.
Draw cdef in direction 4/↓ (where the first character overlaps with the last character, which is why we had to modify the list like this)
Draw fghi in direction 2/→ again (also with overlap of trailing/leading characters)
Draw ijklmno in direction 4/↓ again (also with overlap)
Output the result of the drawn Canvas immediately to STDOUT

Code explanation:
€θ                # Only leave the last characters in the (implicit) input-list
  ¨               # Remove the last one
   õš             # And prepend an empty string "" instead
     ø            # Create pairs with the (implicit) input-list
      í           # Reverse each pair
       J          # And then join each pair together to single strings
        D€g       # Get the length of each string (without popping by duplicating first)
           s      # Swap so the lengths are before the strings
            24S   # Push [2,4]
               Λ  # Use the Canvas builtin (which outputs immediately implicitly)

Your versions 2/3/4 could save 3 bytes with €θ¨õšsøJ.

@Emigna Thanks! Now that I see it it looks so simple.. And here I had three alternative 19-byters instead..

Some alternatives to €θ¨õšsøJ are õIvy«¤}), õUεXì¤U} and ε¯Jθì¤ˆ} (the last two require --no-lazy). Unfortunately, those are all the same length. This would be much easier if one of the variables defaulted to ""...

@Grimy "This would be much easier if one of the variables defaulted to ""..." Are you looking for õ, or you mean if X/Y/® would have been ""? Btw, nice 13 byter in the comment of Emigna's answer. Quite different than both mine and his tbh, with the directions [→,↙,↓,↗] that you've used.

õ is not a variable. Yes, I mean a variable that defaults to "". I literally do õU at the start of one of the snippets, so if X (or any other variable) defaulted to "", it would trivially save two bytes.
Thanks! Yeah, ↙↗ is a bit new, but I got the idea of interspersing the true writes with length 2 dummy writes from Emigna's answer.

@Grimy Maybe ask Adnan in the 05AB1E chat to add a new variable that defaults to an empty string? I could use a fourth variable anyway for big complex answers sometimes. Preferably one that works similar as ©/® (so without popping). Then we'll have two that pop and two that doesn't pop. Not sure if there are still enough 1-byters left and if Adnan is willing to add it, though.

05AB1E, 14 13 bytes
Saved 1 byte thanks to Grimy
€ðÀD€g>sŽ9÷SΛ

Try it online!
Explanation
                 # example input ["Hello", "World"]
€ðÀ              # push a space after each word
                 # STACK: ["Hello"," ","World"," "]
   D             # duplicate
    €g>          # get the length of each word in the copy and add 1
                 # these are the lengths to draw
                 # STACK: ["Hello"," ","World"," "], [6, 2, 6, 2]
       s         # swap the list of word to the top of the stack
        Ž9÷S     # push [2, 5, 4, 1]
                 # this is the list of directions to draw
                 # 1=northeast, 2=east, 4=south, 5=southwest
            Λ    # paint on canvas

Oh dang, nice approach! I will post my 19-byte versions in a moment, but very nice with the Bifurcate and drawing just two letters.

Btw, you know there is a builtin for interspersing, right? €Y¦ could be 2.ý (not that it would save any bytes here). And this is the first time where I've seen the new behavior of € in comparison to the regular map being useful.

@KevinCruijssen: I have seen .ý used before but I've never used myself so I didn't think of it. € is the regular map to me and I've often used it, the other one is the "new" map ;)

13, other 13

@Grimy: Unfortunately neither of those work with an even number of words. I've tried similar things but finding out the direction start has been too expensive.

My bad, I failed to notice the even/odd difficulty! Here's a 13 that should actually work: €ðÀD€g>sŽ9÷SΛ

@Grimy. Doh! Why didn't I even consider using 5? Thanks!

Canvas, 17 12 11 10 bytes
ø⁸⇵｛⟳Ｋ└×∔⤢

Try it here!
Explanation:
ø⁸⇵{⟳K└×∔⤢  full program taking array as input (loaded with ⁸)

ø         push an empty canvas               ["test", "str"], ""
 ⁸⇵{      for each input word, in reverse:   "str", "test" (showing 2nd iter)
    ⟳       rotate the word vertically       "str", "t¶e¶s¶t"
     K      pop off the last letter          "str", "t¶e¶s", "t"
      └     swap the two items below top     "t¶e¶s", "str", "t"
       ×    prepend                          "t¶e¶s", "tstr"
        ∔   vertically append                "t¶e¶s¶tstr"
         ⤢  transpose the canvas             "test
                                                 s
                                                 t
                                                 r"

JavaScript (ES8),  91 79  77 bytes
Takes input as an array of words.
a=>a.map((s,i)=>i&1?[...s].join(p):s+=p+=''.padEnd(s.length-!i),p=`
`).join``

Try it online!
Commented
a =>                 // a[] = input array
  a.map((s, i) =>    // for each word s at position i in a[]:
    i & 1 ?          //   if this is a vertical word:
      [...s].join(p) //     split s and join it with p
    :                //   else:
      s +=           //     add to s:
        p +=         //       add to p:
          ''.padEnd( //         as many spaces
            s.length //         as there are letters in s
            - !i     //         minus 1 if this is the 1st word (because it's not connected
          ),         //         with the last letter of the previous vertical word)
    p = `\n`         //   start with p = linefeed
  ).join``           // end of map(); join everything

Use of p for keeping track of line endings is very smart +1

Python 2, 82 bytes
b=p=0
r=''
for w in input():
 for c in w:r+='\n'.ljust(p)*b+c;p+=1-b
 b^=1
print r

Try it online!

JavaScript, 62 bytes
a=>' '+a.replace(/./g,c=>1-c?(a=!a,''):a?(p+=' ',c):p+c,p=`
`)

Try it online!
Thanks Rick Hitchcock, 2 bytes saved.

JavaScript, 65 bytes
a=>a.replace(/./g,c=>1-c?(t=!t,''):t?p+c:(p+=p?' ':`
`,c),t=p='')

Try it online!
a=>a.replace(/./g,c=>( // for each character c in string a
    1 - c ?            //   if (c is space)
      (t = !t,         //     update t: boolean value describe word index
                       //       truthy: odd indexed words;
                       //       falsy: even indexed words
        '') :          //     generate nothing for space
    t?                 //   if (is odd index) which means is vertical
      p+c :            //     add '\n', some spaces, and a sigle charater
                       //   else
      (p+=p?' ':'\n',  //     prepare the prepend string for vertical words
         c)            //     add a single character
),
  t=p=''               //   initialize
)

I think you can save 2 bytes by replacing t with a, then removing t=

brainfuck, 57 bytes
->,[[.<+>,],[<<[-]++++++++++.--[-<++++>]>[-<+<.>>]>.<,],]

Try it online!
Takes input as NUL separated strings. Note that this is using EOF as 0, and will stop working when the ladder exceeds 256 spaces.
Explanation:
-           Initialise counter as -1
>,[         Start ladder
   [.<+>,]  Print the first word, adding the length of it to the counter
   ,[       Loop over each letter of the second word
      <<[-]++++++++++.    Print a newline
      --[-<++++>]         Create a space character
      >[-<+<.>>]          Print counter many spaces
      >.<,                Print the letter and move to the next letter
   ]
   ,        Repeat until there are no more words
]

May I ask for solution in Brain-Flak?

My first attempt to understand BF.  2 questions: How is the first word being printed when there is no . char in line 3 (of the commented version)?  I was trying to play with the input on TIO.  On Mac, I switched keyboard to Unicode text input and tried creating new word boundaries by typing option+0000 but it didn't work.  Any idea why not?

@Jonah Ah good catch, I accidentally typed - instead of . for the explanation. For adding NUL bytes in TIO, I recommend using the console and running a command like $('#input').value = $('#input').value.replace(/\s/g,"\0");. I don't know why your way didn't work

Aheui (esotope), 490 458 455 bytes
삭뱃밸때샏배샐배새뱄밿때빠뱋빼쌘투＠밧우
＠두내백뱃빼선대내백뱃섣＠여우샐처샐추
희차＠＠＠뭏누번사＠빼뭏오추뻐＠＠＠배
Ｂｙ＠＠＠새대백＠＠＠우뻐색
Ｌｅｇｅｎ＠＠빼쵸누번＠＠빼
ＤＵＳＴ＠＠＠샌뽀터본섣숃멓
＠＠＠＠＠＠＠오어아＠먛요아＠＠샏매우
＠＠＠＠＠아＠＠＠＠＠＠오＠＠＠＠＠서어
＠＠＠＠＠희차＠＠요

Try it online!
Slightly golfed by using full-width characters(2 bytes) instead Korean(3 bytes).
Explanation
Aheui is befunge-like esolang. Here is code with color:

?1 part checks if current character is space or not.
?2 parts check whether words had written right-to-left or top-to-down.
?3 part is break condition of loop which types spaces.
?4 parts check if current character is end of line(-1).
Red part is stack initialization. Aheui uses stacks (from Nothing to ㅎ : 28 stacks) to store value.
Orange part takes input(뱋) and check if it is space, by subtracting with 32(ascii code of space).
Green part add 1 to stack which stores value of length of space, if writing right-to-left.
Purple part is loop for printing spaces, if writing up-to-down.
Grey part check if current character is -1, by adding one to current character.
Blue part prints current character, and prepare for next character.

What did you use to generate the image in this post?

@bb94 base is AheuiChem, nice built Korean Aheui online (sort of) IDE. And I used Powerpoint to color it.

Perl 6, 65 bytes
{$/=0;.map:{$/+=$++%2??!.comb.fmt("%$/s","
").print!!.say*.comb}}

Try it online!
Anonymous code block that takes a list of words and prints straight to STDOUT.
Explanation
{                           }  # Anonymous code block
 $/=0;                         # Initialise $/ to 0
 .map:{                    }   # Map the list of words to
       $/+=                    # Increment $/ by
           $++%2??             # For even indexes
                   .comb       # Each letter of the word
                   .fmt(           ) # Formatted as
                        "%$/s"       # Padded with $/-1 spaces
                              ,"\n"  # Joined by newlines
                   .print            # And printed without a newline
                  !   # Boolean not this to add 0 to $/
                !!            # For odd indexes
                  .say        # Print with a newline
                      *.comb  # And add the length of the word

I'm curious how this one works Jo, I don't know Perl 6

@Jonah I've added an explanation

Thanks, nice solution.

Japt -P, 15 bytes
ò mrÈ+R+YÕùT±Xl

Try it
ò mrÈ+R+YÕùT±Xl     :Implicit input of string array
ò                   :Partition into 2s
  m                 :Map each pair
   r                :  Reduce by
    È               :  Passing through the following function as X & Y
     +              :    Append to X
      R             :    Newline
       +            :    Append
        YÕ          :    Transpose Y
          ù         :    Left pad each line with spaces to length
           T±       :      T (initially 0) incremented by
             Xl     :      Length of X
                    :Implicitly join and output

bash, 119 chars
X=("\e7" "\n\e8")
w="$@"
l=${#w}
d=0
for((i=0;i<l;i++));do
c="${w:$i:1}"
[ -z $c ]&&d=$((1-d))||printf ${X[$d]}$c
done

This uses ANSI control sequences to move the cursor - here I'm only using save \e7 and restore \e8; but the restore has to be prefixed with \n to scroll the output if it's already at the bottom of the terminal. For some reason it doesn't work if you're not already at the bottom of the terminal. * shrug *
The current character $c is isolated as a single-character substring from the input string $w, using the for loop index $i as the index into the string.
The only real trick I'm using here is [ -z $c ] which will return true, i.e. the string is blank, when $c is a space, because it's unquoted. In correct usage of bash, you would quote the string being tested with -z to avoid exactly this situation. This allows us flip the direction flag $d between 1 and 0, which is then used as an index into the ANSI control sequence array, X on the next non-space value of $c.
I'd be interested to see something that uses printf "%${x}s" $c.
Oh gosh let's add some whitespace. I can't see where I am...
X=("\e7" "\n\e8")
w="$@"
l=${#w}
d=0
for ((i=0;i<l;i++)); do
  c="${w:$i:1}"
  [ -z $c ] && d=$((1-d)) || printf ${X[$d]}$c
done

Oh by the way, you can't try this one on that tio.run site - like a few others, there's no ANSI control sequence handling so it just barfs.

Charcoal, 19 bytes
ＦＬθ¿﹪ι²«↓§θι↗»«§θι↙

Input as a list of strings
Try it online (verbose) or try it online (pure)
Explanation:
Loop in the range [0, input-length):
For(Length(q))
ＦＬθ

If the index is odd:
If(Modulo(i,2)){...}
﹪ι²«...»

Print the string at index i in a downward direction:
Print(:Down, AtIndex(q,i));
↓§θι

And then move the cursor once towards the top-right:
Move(:UpRight);
↗

Else (the index is even):
Else{...}
«...

Print the string at index i in a regular right direction:
Print(AtIndex(q,i));
§θι

And then move the cursor once towards the bottom-left:
Move(:DownLeft);
↙

Python 2, 89 88 bytes
s=i=-1
r=''
for w in input():r+=[('\n'+' '*s).join(' '+w),w][i];s-=i*len(w);i=~i
print r

Try it online!

J, 47 45 43 bytes
;[`(([:<@(+/)\#&>##$#:@1 2)@])`([' '"0/[)}]

Try it online!
I found a fun, different approach...
I started messing around with left pads and zips with cyclic gerunds and so on, but then I realized it would be easier to just calculate each letter's position (this boils down to a scan sum of the correctly chosen array) and apply amend } to a blank canvas on the razed input.
The solution is handled almost entirely by Amend }:
; [`(([: <@(+/)\ #&> # # $ #:@1 2)@])`([ ' '"0/ [)} ]

; ( single verb that does all the work ) ] overall fork
; left part razes the input, ie, puts all the letters into a contiguous string
] right part is the input itself
(stuff)} we use the gerund form of amend }, which consists of three parts v0`v1`v2.

v0 gives us the "new values", which is the raze (ie, all the characters of the input as one string), so we use [.
v2 gives us the starting value, which we are transforming.  we simply want a blank canvas of spaces of the needed dimensions.  ([ ' '"0/ [) gives us one of size (all chars)x(all chars).
The middle verb v1 selects which positions we will put our replacement characters in.  This is the crux of the logic...

Starting at position 0 0 in the upper left, we notice that each new character is either 1 to the right of the previous position (ie, prev + 0 1) or one down (ie, prev + 1 0).  Indeed we do the former "len of word 1" times, then the latter "len of word 2" times, and so on, alternating.  So we'll just create the correct sequence of these movements, then scan sum them, and we'll have our positions, which we then box because that's how Amend works.  What follows is just the mechanics of this idea...
([: <@(+/)\ #&> # # $ 1 - e.@0 1)

First #:@1 2 creates the constant matrix 0 1;1 0.
# $ then extends it so it has as many rows as the input.  eg, if the input contains 3 words it will produce 0 1;1 0;0 1.
#&> # the left part of that is an array of the lengths of the input words and # is copy, so it copies 0 1 "len of word 1" times, then 1 0 "len of word 2 times", etc.
[: <@(+/)\ does the scan sum and box.

C# (Visual C# Interactive Compiler), 122 bytes
a=>{int i=0;var t="\n";foreach(var z in a)Write(i++%2<1?z+(t+="".PadRight(z.Length-(i<2?1:0))):string.Join(t,z.Skip(0)));}

Try it online!

T-SQL, 185 bytes
DECLARE @ varchar(max)='Thomas Clausen Codegolf Script'
,@b bit=0,@s INT=0SET @+=':'WHILE @ like'%_:%'SELECT
@b+=len(left(@,1))-1,@=stuff(@,1,1,'')+iif(left(@,@b)='','','
'+space(@s))+trim(left(@,1)),@s+=len(left(@,~@b))PRINT
stuff(@,1,1,'')

Try it online

Very clever use of BIT values, the delimiter spaces, and circular string processing.  Much better answer than mine!

Retina, 51 bytes
1,2,`\w+
;$&
+(m`^(.(.*?)) ?;(.)
$1¶$.2* $3;
; |;$

Try it online!
A rather straightforward approach that marks every other word and then applies the transformation directly.
Explanation
1,2,`\w+
;$&

We mark every other  word with a semicolon by matching each word, but only applying the replacement to the matches (which are zero indexed) starting from match 1 and then 3 and so on.
+(m`^(.(.*?)) ?;(.)
$1¶$.2* $3;

+(m sets some properties for the following stages. The plus begins a "while this group of stages changes something" loop, and the open bracket denotes that the plus should apply to all of the following stages until there is a close bracket in front of a backtick (which is all of the stages in this case). The m just tells the regex to treat ^ as also matching from the beginning of lines instead of just the beginning of the string.
The actual regex is pretty straightforward. We simply match the appropriate amount of stuff before the first semicolon and then use Retina's * replacement syntax to put in the correct number of spaces.
; |;$

This stage is applied after the last one to remove semicolons and spaces at the end of words that we changed to vertical.

Retina 0.8.2, 58 bytes
(?<!^(\S* \S* )*\S*)
¶
¶?

+`(..(.)*¶)((?<-2> )*\S)
$1 $3

Try it online! Link includes test cases. Alternative solution, also 58 bytes:
( \S*)
$1¶
+` (.)
¶$1
 ¶

+`(..(.)*¶)((?<-2> )*\S)
$1 $3

Try it online! Link includes test cases.
I'm deliberately not using Retina 1 here, so I don't get operations on alternate words for free; instead I have two approaches. The first approach splits on all letters in alternate words by counting preceding spaces, while the second approach replaces alternate spaces with newlines and then uses the remaining spaces to help it split alternate words into letters. Each approach has to then join the last vertical letter with the next horizontal word, although the code is different because they split the words in different ways. The final stage of both approaches then pads each line until its first non-space character is aligned under the last character of the previous line.
Note that I don't assume that words are just letters because I don't have to.

T-SQL, 289 bytes
DECLARE @ VARCHAR(MAX)='a a',@I INT=1,@S INT=0,@B INT=0WHILE @I<=LEN(@)IF SUBSTRING(@,@I,1)=''IF @B=0SELECT @S-=1,@=STUFF(@,@I,1,'
'+SPACE(@S)),@I+=@S+3,@B=1 ELSE SELECT @=STUFF(@,@I,1,''),@S+=1,@B=\ELSE IF @B=0SELECT @I+=1,@S+=1 ELSE SELECT @=STUFF(@,@I,0,'
'+SPACE(@S)),@I+=@S+3PRINT @

This runs on SQL Server 2016 and other versions.
@ holds the space-delimited list.  @I tracks the index position in the string.  @S tracks the total number of spaces to indent from the left.  @B tracks which axis the string is aligned with at point @I.
The byte count includes the minimal example list.  The script goes through the list, character by character, and changes the string so that it will display according to the requirements.  When the end of the string is reached, the string is PRINTed.

Hi @Mugo It seems there is a glitch in your script when using longer input. If you test with the data from my answer, you will see there is a unintended bend in the last word between p and t

@t-clausen.dk Oops, I didn't handle the last iteration properly.  Thanks!

confirmed it works now

J, 35 33 bytes
3 :'[;.0>(,|:)&:,.&.>/_98{.;:|.y'

This is a verb that takes the input as a single string with the words separated by spaces.  For example, you could call it like this:
3 :'[;.0>(,|:)&:,.&.>/_98{.;:|.y' 'programming puzzles and code golf'

The output is a matrix of letters and spaces, which the interpreter outputs with newlines as required.  Each line will be padded with spaces so they have the exact same length.
There's one slight problem with the code: it won't work if the input has more than 98 words.  If you want to allow a longer input, replace the _98 in the code by _998 to allow up to 998 words, etc.

Let me explain how this works through some examples.
Suppose we have a matrix of letters and spaces that we imagine is a partial output for some words, starting with a horizontal word.
   [m=: 3 3$'vwx  y  z'
vwx
  y
  z

How could we prepend a new word before this, vertically?  It's not hard: just turn the new word to a single-column matrix of letters with the verb ,., then append the output to that single-column matrix.  (The verb ,. is convenient because it behaves as an identity function if you apply it to a matrix, which we use for golfing.)
   (,.'cat') , m
c
a
t
vwx
  y
  z

Now we can't just iterate this way of prepending a word as is, because then we'd only get vertical words.  But if we transpose the output matrix between each step, then every other word will be horizontal.
   (,.'dog') , |: (,.'cat') , m
d
o
g
catv
   w
   xyz

So our first attempt for a solution is to put each word into a single-column matrix, then fold these by appending and transposing between them.
   > (,|:)&.>/ ,.&.>;: 'car house dog children'
c
a
r
housed
     o
     g
     children

But there's a big problem with this.  This puts the first letter of the next word before turning a right angle, but the specification requires turning before putting the first letter, so the output should be something like this instead:
c
a
rhouse
     d
     o
     gchildren

The way we achieve this is to reverse the entire input string, as in
nerdlihc god esuoh rac

then use the above procedure to build the zig-zag but turning only after the first letter of each word:
n
e
r
d
l
i
h
c
gode
   s
   u
   o
   h
   rac

Then flip the output:
   [;.0> (,|:)&.>/ ,.&.>;:|. 'car house dog children'
car
  h
  o
  u
  s
  edog
     c
     h
     i
     l
     d
     r
     e
     n

But now we have yet another problem.  If the input has an odd number of words, then the output will have the first word vertical, whereas the specification says that the first word must be horizontal.  To fix this, my solution pads the list of words to exactly 98 words, appending empty words, since that doesn't change the output.

PowerShell, 101 89 83 bytes
-12 bytes thanks to mazzy.
$args|%{$l+=if(++$i%2){$_.length-1;$t+=$_}else{1;$_|% t*y|%{$t+='
'+' '*$l+$_}}};$t

Try it online!

nice. you can: 1) remove first line, 2) use a splatting & $b @p (each word as one argument), 3) use shorter form for new line constant. see 3,4 line at this example

@mazzy, with the splatting i get wrong answer for foo. see the code.

oO! The splatting splits one word to a char array. Interesting. Thanks!

@mazzy, it's not my fault :)

I think we can use the rule Given a list of at least two words...

74 bytes with PadLeft

Declaring an array as ('foo', @('foo')) allows to use the splatting with single-word list. Look at this example.

R, 126 bytes
function(x,`>`=strrep)for(i in seq(x)){H=i%%2;cat(paste0('
'>!H,' '>F*!H,e<-'if'(H,x,strsplit(x,''))[[i]]))
F=F+nchar(e[1])-H}

Try it online!

-3 bytes thanks to @Giuseppe

PowerShell, 74 65 bytes
-join($args|%{$_|% t*y|%{($p+=(' ','
')[!$p]*!$i)*$i;$_};$i=!$i})

Try it online!

JavaScript (Node.js), 75 bytes
a=>a.map(x=>i++&1?[,...x].join(`
`.padEnd(n)):(n+=x.length,x),n=i=0).join``

Try it online!
Explanation and ungolfed
function f(a) {                   // Main function:
 return a.map(                    //  Map through all words:
  function(x) {
   if (i++ & 1)                   //   If i % 2 == 1 (i.e. vertical):
    return [,...x].join(          //    Since the first one needs to have its own linefeed
                                  //    and indentation, add a dummy item to the start.
     "\n".padEnd(n)               //    Join the array with the padded line feeds.
    );
   else {                         //   If i % 2 == 0 (i.e. horizontal):
    n += x.length;                //    Add the length of this string to the variable that
                                  //    counts how long the padded line feeds should be.
    return x;                     //    Append the string at the end without line feeds.
   }
  },
  n = i = 0                       //   Initialize variables.
                                  //   n: the length of the padded line feeds
                                  //      (including the line feed)
                                  //   i: keeps track of the direction
 ).join("")                       //  Join all stuffs and return.
}

Stax, 12 bytes
ìZΣFτëWº═φ‼R

Run and debug it

C (gcc), 93 87 bytes
Thanks to gastropner for the suggestions.
This version takes an array of strings terminated by a NULL pointer.
c,d;f(s,t)char**s,*t;{for(c=d=0;t=*s++;d=!d)for(;*t;c+=!d)printf("\n%*c"+!d,d*c,*t++);}

Try it online!

87 bytes

Jelly, 21 bytes
Ẉm2Ä’x2Ż⁶xⱮṛ;⁷ɗ;ⱮY¥ƭ"

Try it online!
A full program taking the input as a list of strings and implicitly outputting to stdout the word ladder.

Brain-Flak, 152 bytes
<>([()])<>{<>({}<>{()<({}<>)><>}<>)<>{}{<>({}<((()()()()()){})>)({<({}[()]<((((()()()()){}){}){})>)>()}{})<>(({}<>({}))[({}[{}])])<>}{}}<>{}{({}<>)<>}<>

Try it online!
I suspect this can be shorter by combining the two loops for odd and even words.

Thank you for this!

[ bash + stty ], 155 bytes
This does not trump @Rich solution but with more work it might be good.  I realise it has an error atm (direction of new word) but since I don't have the reputation to comment on Rich's solution I have added this new answer even with an error to show another approach. It also does not suffer from a problem with whether at bottom of screen or not.
It wont work with TIO either ("not a possible ioctl" error).
j=0;for s;do
l=${#s};stty -onlcr
if((j%2==0));then
printf "%s\n\b" $s;else
for((i=0;i<$l;i++));do
printf "%s\n\b" ${s:$i:1}
done;fi;((j+=1));done;stty onlcr

Code that does work is:
j=0;for s;do l=${#s};stty -onlcr
if !((j%2));then
F=%s
f=$s
else
for((i=0;i<$l;i++));do
F=$F\\n\\b%s
f=$f\ ${s:$i:1}
done
fi
printf $F $f
f=;F=
((j+=1))
done
stty onlcr

Not so good as @Rich but 168 bytes.  Could be cheeky and remove initialisation to save 4 bytes but that I feel is cheating.

AH-HA there is ANOTHER way that avoids stty. There is a VT character (Vertical Tab) that effectively moves down one line on a screen.  Removing the stty  code and changing \\n to \\v works for 127 bytes.

Python 3, 218 bytes

words=input().split();space=-1;
for i in range(len(words)):
 if i%2==0:
  print(words[i]);space+=len(words[i])
 else:
  for ch in words[i][:-1]:
   print(" "*(space)+ch)
  print(" "*(space)+words[i][-1],end="")

Try it online!
218 bytes i need to learn to reduce it ...

Tips for golfing in Python may help you with that...

Welcome to PPCG! I formatted the submission for you. You can easily trim the leading and trailing whitespaces and use tabs: TIO

source: Stack Exchange

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

sort: votes


text:
Point out a string character
Introduction
In many programming languages, within syntax exceptions, it is often pointed out to the programmer exactly which character or line is the culprit. This challenge will be a bit of a modification of that - specifically, using an arrow to point out any specific character of an input string.
The challenge
Your job is to:

Define a function that takes two parameters.
This function will print the string to stdout (or an acceptable alternative), along with pointing out the index of the string requested.
The index is zero-based, meaning index 0 is actually he first character of the string.
If a half index is passed in, you are to use a double arrow (/\ instead of ^) to point out the middle of the two characters.

Don't quite get what I mean? Here's some test cases:
f("hello world", 3):
hello world
   ^
   l

f("Code Golf", 0):
Code Golf
^
C

f("MY STRING!", 4.5):
MY STRING!
    /\
    TR

You may use any language. No input from stdin - must be through a function. Do not use any of the common loopholes. And most importantly, have fun!
Leaderboard
You can view the leaderboard for this post by expanding the widget/snippet below. In order for your post to be included in the rankings, you need a header (# header text) with the following info:

The name of the language (end it with a comma , or dash -), followed by...
The byte count, as the last number to appear in your header.

For example, JavaScript (ES6), 72 bytes is valid, but Fortran, 143 bytes (8-bit) is invalid because the byte count is not the last number in the header (your answer will be recognized as 8 bytes - don't take advantage of this).

<iframe src="https://xmikee1.github.io/ppcg-leaderboard/?id=186018" width="100%" height="100%" style="border: none;">Oops, your browser is too old to view this content! Please upgrade to a newer version of your browser that supports HTML5.</iframe><style>html,body{margin:0;padding:0;height:100%;overflow:hidden}</style>

Will the index always be valid? (ie 0<=i<=len(string))

Why must it be a function?

Please consider lifting the I/O restrictions.

Why must the index be zero-based?

You examples indicate that the pointed-out characters are to be printed on a third line, but your challenge spec doesn't actually state that.

To back up @Adám 's point above: was the 3rd line just added to highlight the letters that are marked? Or is it part of the required output? Either way, the challenge should be clarified.

I really like this challenge idea, so I hope you do clean it up.

@xnor I'm going to let it fall by the wayside, unfortunately. Sorry about that. Except a new one shortly.

@connectyourcharger In that case, do you mind if I edit to address the comments?

Question since this is in limbo anyway… is there a meta consensus on if/when to add a leaderboard? I feel like I largely see that on catalog 'challenges', or challenges that may as well be… that is, very trivial & tons of answers. I guess adding a leaderboard to any given challenge isn't really a problem, it just feels odd seeing it on something like this (with no offense to OP).

@brhfl That's a good comment. I've just been putting them on my questions to showcase my leaderboard system, but I wonder if it's worth a meta inquiry to establish some guidelines for when a post is eligible for a leaderboard.

Why was this reopened when the issues that were raised haven't been addressed?

@Shaggy I'm actually not sure, I want it closed.

@connectyourcharger ??? It's your challenge; you're the one who should be fixing the problems.

@Shaggy I don't really have time to maintain this question anymore, unfortunately. It's a good question but it's past any hope of popularity and frankly not worth fixing.

Python 2, 78 77 75 74 bytes
def f(s,i):j=int(i);x='\n'+j*' ';print s+x+'/^\\'[i==j::2]+x+s[j:(i>j)-~j]

Try it online!
-1 byte, thanks to Arnauld

05AB1E, 25 24 23 bytes
…^/\ć‚Y.ïè©XY.$®g£‚YúXš

Function taking X as string and Y as number, and returning a list of string-lines.
Try it online.
Explanation:
…^/\         # Push string "^/\"
    ć        # Extract head; pop and push remainder "/\" and head "^"
     ‚       # Pair them together: ["/\","^"]
      Y.ï    # Check if number `Y` is an integer (1 if truthy; 0 if falsey)
         è   # Use that to index into the pair ("^" if integer; "/\" if decimal)
          ©  # Store it in the register (without popping)
XY.$         # Remove the first `int(Y)` characters from string `X`
    ®g       # Get the length of the string we saved in the register
      £      # Leave that many leading characters from the string
‚            # Pair it with the earlier "^" or "/\"
 Yú          # Pad both with `int(Y)` amount of leading spaces
Xš           # Prepend string `X` to this list
             # (which is returned implicitly as result)

The function definition is:
"…^/\ć‚Y.ïè©XY.$®g£‚YúXš"ˆ

Which can then be called like this:
"MY STRING!"U  4.5V ¯`.V»,

C (gcc), 165 125 101 99 90 85 bytes
-40 Bytes @Kevin Cruijssen
-24 Bytes @Arnauld
-2  Bytes
-9  Bytes @attinat
-5  Bytes @ceilingcat
t,u;a(char*s,float i){t=i;u=i>t;printf("%s\n%*s\n%*.*s",s,t+u,L" ^尯"+u,t+u,++u,s+t);}

Try it online!

I think you're missing a part of the challenge. a("MY STRING",4.5); gives an error in your TIO.

@KevinCruijssen forgot about that, doesn't seem as elegant any more :)

Perhaps, but you can still save a bunch of bytes now. :) 125 bytes

101 bytes with some trailing spaces.

90 bytes

Note that my 101-byte version was based upon @KevinCruijssen 's 125-byte version, so I don't deserve all the credit for -64. :)

@Arnauld My initial answer here is really more of a hack to get it to conform to all rules of the challenge, I didn't have any time left when I saw that I missed some rules.

83 bytes

Pepe, 229 bytes
This took very long to make. Probably my longest Pepe code yet. Everything could be so much easier if not the third output line. I didn't write in Pepe for a long while so I'm proud of it.
Note: This is not a valid answer because the specs require it to be a function – but there are no functions in Pepe, officially.
REEeReeeReeERREeeRREeEEerREEreeeEeEEEEreeEeEEEeeREeREEEerREEreeEeEEEEeREerEeeEeeeeerrEEeeeErereeeREEEERREEEEEEeReEReeErereeeRREEEEEEEREEEeRrErrEEREEEEReREEEeREEEEereerreErEereeREEEEReEereRrEeEEeRrEEEEEEErEEEerrEEREEEEReReEerEeree

Try it online!
Non-minified code, with comments, if you can understand it...
# The line
REEe   # Take input
Reee   # Output it
ReeE   # End line

# Index
RREee    # Take the number [n]
RREeEEe  # Floor in a copy

# Function [n]
rREE

  reeeEeEEEE reeEeEEEee  # Output /\

REe  # End

# Move pointer to last item
REEEe

# Function floor[n], overrides [n] if it's an integer
rREE

  reeEeEEEEe  # Output ^

REe

# Line 2 – spaces
rEeeEeeeee  # A space
rrEEeeeE    # Repeat it [n] times
re          # Remove one
reee        # Output

# Line 2 – pointer
REEEE      # Go to first item
RREEEEEEe  # Copy to other stack
ReE        # Call it
ReeE       # End the line

# Line 3 – spaces
re     # Remove the item
reee   # Output

# Line 3 – letters
RREEEEEEE  # Move the index to other stack
REEEe      # Move R pointer to the end
RrE        # Prepend 0
rrEE       # Label 0
  REEEE      # Go to the first item
  Re         # Pop it
  REEEe      # Go to the last item
  REEEEe     # Decrement
  ree        # Recurse while unequal
  rreE       # Equal, end
    # This is a flag I've added because I thought that I should add something in its place
    # I never thought it will be useful. But apparently it is. For recursion.
rEe
ree        # Call if unequal
REEEE      # Move to first item
ReEe       # Output it
re         # Pop the 0
RrEeEEe    # Floor the first item in a copy
RrEEEEEEE  # Move the item to the other stack
rEEEe      # Move to the end
rrEE       # Label floor[n]
  REEEE      # Move to first item of R
  Re         # Remove it
  ReEe       # Output the next one
rEe        # End
ree        # Enter it if [n] is not an integer

Wow, haven't seen you do a Pepe answer in a long time

JavaScript (ES8),  65  63 bytes
Takes input as (string)(position).
s=>n=>s+(x=`
`.padEnd(n+1))+(n%1?'/\\'+x+s[~~n++]:'^'+x)+s[~~n]

Try it online!

JavaScript (ES8), 39 bytes
This version is based on the challenge description, without the 3rd line. The original version above includes it, like suggested by the test cases. Awaiting OP clarification.
Takes input as (string)(position).
s=>n=>s+`
`.padEnd(n+1)+(n%1?'/\\':'^')

Try it online!

Jelly, 22 bytes
⁾/\”^%?1,ịṭ€Ḟ’⁶xƲ{;@W}

Try it online!
A dyadic link which takes the position as its left argument and the string as its right. It returns a list of Jelly strings (presumed to be an ‘acceptable alternative’) representing the output. The TIO link outputs these to stdout separated by newlines.
This is currently using 1-indexing since that is the norm for Jelly. If 0-indexing is a must, here’s an alternative dyadic link:
Jelly, 23 bytes
⁾/\”^%?1,‘ị¥ṭ€Ḟ⁶xƊ{;@W}

Try it online!

I personally think the strict I/O rules are bs, but currently your answer is invalid. Yours is a full program instead of function; it's 1-indexed instead of 0-indexed; it returns a list instead of printing to STDOUT. I would keep it as is and mark it as non-competing (for now), or perhaps add a second version which does comply to these cumbersome rules.. Regardless, nice answer! 2 bytes shorter than what I had as full program in 05AB1E.

@KevinCruijssen Regarding STDOUT, the challenge does mention "or an acceptable alternative".

@Arnauld Ah, you're right. Saved a byte in my 05AB1E 'function' by returning a string instead of printing. Thanks. :)

@KevinCruijssen thanks. I’ve added a new version using 1-indexing. A single link is the Jelly equivalent of a function. The TIO link is to a full program that calls that link and formats the output for printing, but the link itself works as described taking two arguments and returning a list of Jelly strings.

C# (Visual C# Interactive Compiler), 100 98 bytes
a=>b=>a+(b>(i=(int)b)?"/\\":"^").PadLeft((v=b>i?2:1)+i)+'\n'+a.Substring(i,v).PadLeft(v+i);int i,v

Try it online!

I'm not convinced having the new line character in the input to the function is ok.
Basically your code does not work with "Hello World" it only works with "Hello World\n" (and arguably it doesnt work with that).

Java 11, 103 bytes
(s,n)->{int i=(int)n;var t="\n"+" ".repeat(i);return s+t+(n>i?"/\\":"^")+t+s.substring(i,n>i?i+2:i+1);}

Try it online.

Python 3.8 (pre-release), 72 bytes
Very similar to @TFeld's answer, but makes use of Python 3.8's handy := lambda assignment operator.
f=lambda s,i:s+(x:='\n'+' '*(j:=int(i)))+'/^\\'[i==j::2]+x+s[j:(i>j)-~j]

Try it online!

Stax, 21 bytes
ë└¥1ç4┴îdΩ8½öyε∙µ$%T▐

Run and debug it


text:
Convert between Korean two-set keyboard and qwerty keyboard
Introduction
It is somewhat like DVORAK Keyboard layout , but MUCH harder.
Let's talk about the Korean keyboard first. As you can see in Wikipedia, there is a Kor/Eng key to change between Korean and English key sets.
Koreans sometime type wrong : they attempt to write in Korean on a qwerty keyboard or in English on a two-set keyboard.
So, here's the problem : if given Korean characters typed in two-set keyboard, convert it to alphabetic characters typed in qwerty keyboard. If given alphabetic characters typed in qwerty, change it to two-set keyboard.
Two-set Keyboard
Here is the two-set keyboard layout :
ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ
 ㅁㄴㅇㄹㅎㅗㅓㅏㅣ
  ㅋㅌㅊㅍㅠㅜㅡ

and with shift key :
ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ

just the top row changes while the others do not.
About Korean Characters
if it ended here, it could be easy, but no.
When you type
dkssud, tprP!

output is not shown in this way:
ㅇㅏㄴㄴㅕㅇ, ㅅㅔㄱㅖ!

but in this way :
안녕, 세계!(means Hello, World!)

and it makes things much harder.
Korean Characters separate into three parts : 'Choseong(consonant)', 'Jungseong(Vowel)', and 'Jongseong(consonant in the end of syllable : can be blank)', and you have to separate it.
Fortunately, there is way to do that.
How to separate
There are 19 Choseong, 21 Jungseong, and 28 Jongseong(with blank), and 0xAC00 is '가', first character of the Korean characters. Using this, we can separate Korean characters into three parts. Here is the order of each and its position in two-set keyboard.
choseong order :
ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
r R s e E f a q Q t T d w W c z x v g

jungseong order :
ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
k o i O j p u P h hk ho hl y n nj np nl b m ml l

jongseong order :
()ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ
()r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g

Let's say (unicode value of some character) - 0xAC00 is Korean_code,
and index of Choseong, Jungseong, Jongseong is Cho, Jung, Jong.
Then, Korean_code is (Cho * 21 * 28) + Jung * 28 + Jong
Here is the javascript code which separate Korean character from this Korean website, for your convenience.
var rCho = [ "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ" ];
var rJung =[ "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ" ];
var rJong = [ "", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ", "ㄻ", "ㄼ", "ㄽ", "ㄾ","ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ" ];
var cho, jung, jong;
var sTest = "탱";
var nTmp = sTest.charCodeAt(0) - 0xAC00;
jong = nTmp % 28; // Jeongseong
jung = ((nTmp - jong) / 28 ) % 21 // Jungseong
cho = ( ( (nTmp - jong) / 28 ) - jung ) / 21 // Choseong

alert("Choseong:" + rCho[cho] + "\n" + "Jungseong:" + rJung[jung] + "\n" + "Jongseong:" + rJong[jong]);

When assembled

Note that ㅘ, ㅙ, ㅚ, ㅝ, ㅞ, ㅟ, ㅢ is a combination of other jungseongs.

ㅗ+ㅏ=ㅘ, ㅗ+ㅐ=ㅙ, ㅗ+ㅣ=ㅚ, ㅜ+ㅓ=ㅝ, ㅜ+ㅔ=ㅞ, ㅜ+ㅣ=ㅟ, ㅡ+ㅣ=ㅢ

Choseong is necessary. That means, if frk is given, which is ㄹㄱㅏ, it can change in two way : ㄺㅏ and ㄹ가. Then, you have to convert it into a way which has choseong. If jjjrjr given, which is ㅓㅓㅓㄱㅓㄱ, leading ㅓs don't have anything that can be choseong, but the fourth ㅓ has ㄱ that can be choseong, so it's changed into ㅓㅓㅓ걱.

Another example : 세계(tprP). It can be changed to 섹ㅖ((ㅅㅔㄱ)(ㅖ)), but because choseong is necessary, it's changed into 세계((ㅅㅔ)(ㄱㅖ))
Examples
input 1
안녕하세요

output 1
dkssudgktpdy

input 2
input 2

output 2
ㅑㅞㅕㅅ 2

input 3
힘ㄴㄴ

output 3
glass

input 4
아희(Aheui) is esolang which you can program with pure Korean characters.

output 4
dkgml(모뎌ㅑ) ㅑㄴ ㄷ내ㅣ뭏 조ㅑ초 ㅛㅐㅕ ㅊ무 ㅔ갷ㄱ므 쟈소 ㅔㅕㄱㄷ ㅏㅐㄱㄷ무 촘ㄱㅁㅊㅅㄷㄱㄴ.

input 5
dkssud, tprP!

output 5
안녕, 세계!

input 6
ㅗ디ㅣㅐ, 째깅! Hello, World!

output 6
hello, World! ㅗ디ㅣㅐ, 째깅!

Shortest code wins.(in bytes)
New rule for you convenience
You can dismiss characters like A which do not have its counterpart in two-set keyboard. so Aheui to Aㅗ뎌ㅑ is OK. But, if you change Aheui to 모뎌ㅑ, you can get -5 point, so you can earn 5 bytes.
You can separate two jungseongs(like ㅘ to ㅗ+ㅏ). like rhk to 고ㅏ, or how to ㅗㅐㅈ. But if you combine it(like rhk to 과 or how to ㅙㅈ), you can earn additional -5 points.

In the jungseong order section one of the letters is missing. I see 21 Korean symbols, but only 20 letter(-pair)s. EDIT: Seems to be missing a trialing l after ml for the Korean symbol ㅣ.

@KevinCruijssen edited. l for ㅣ.

Welcome to PPCG! Your examples seem to indicate this, but I wanted to clarify -- if the character/letter is not in the choseong, jungseong, or jongseong lists (e.g., 2) it should remain untouched?

@AdmBorkBork As you can see in example 2, 4, and 6, yes. 스택 익스체인지 프로그래밍 퍼즐 & 코드 골프 should converted to tmxor dlrtmcpdlswm vmfhrmfoald vjwmf & zhem rhfvm

Sometimes there can be more than one interpretation. For example, fjfau could be interpreted as 럶ㅕ or 럴며. How do we resolve this?

It always interperted into 럴며., because it is typing.  If I want to type 럶ㅕ, I have to type 럶, than space and backspace, than type ㅕ.

Do jongseong ever occur alone (outside a syllable) in input or output?

Why does np in the second test case (input 2) transform from ㅜㅔ to ㅞ? Both ㅜ and ㅔ are jungseong. Based on your separation paragraph and Korean_code formula I thought characters should only be combined as choseong+jungseong+jongseong or choseong+jungseong+empty. But apparently other combinations are possible as well?.. :S

Some 'jungseong's combines to another. For example : ㅗㅣ to ㅚ, ㅗㅐ to ㅙ, ㅜㅔ to ㅞ, ㅗㅏ  to ㅘ, ㅜㅓ to ㅝ, ㅜㅣ to ㅟ. I'll edit question to make it clear... I'm Korean and I thought that is just obvious.

@LegenDUST Well, I can't read a single word Korean, so I'll have to go with your explanation. ;p As for tprP in test case 5: this transforms into ㅅㅔㄱㅖ , where ㅅ is a choseong, ㅔ is a jungseong and ㄱ is a jongseong. So should't this transform into 섷ㅖ (grouped like (ㅅㅔㄱ)(ㅖ)) instead of 세계 (grouped like (ㅅㅔ)(ㄱㅖ))? In an earlier comment you state it is interpret by typing, so I would expect ㅅㅔㄱ to transform into 섷. Or is Korean typing from right to left instead of left to right?

If there is jongseong followed by jungseong, it changed to choseong. tprP changed into ㅅㅔㄱㅖ. Note that choseong is necessary, unless there is nothing. Note that almost every characters in jongseong is same as choseong. So frk(ㄹㄱㅏ) changed to ㄹ가, not ㄺㅏ. Maybe Wikipedia can help. I'll fix problem to make it sure.

This task is perfect for AutoHotkey.

I have made an editing pass to improve the English. Feel free to roll back if you think I've changed it for the worse.

Do you have a list of all combined Korean characters somewhere? Or do you know the lowest and highest unicode for a range of the combined characters?

@Veskah Thanks a lot.

@KevinCruijssen PDF file from Unicode.org. AC00(가) to D7AF(힣).

It looks like IME instead of layout to me.

@tsh It is IME, but that doesn't mean it is not layout. Maybe IME is better than layout in this question?

Jelly, 296 264 bytes
Ẏœṣjƭƒ
“ȮdȥŒ~ṙ7Ṗ:4ȦịØ¹ʂ ="÷Ƥi-ẓdµ£f§ñỌ¥ẋaḣc~Ṡd1ÄḅQ¥_æ>VÑʠ|⁵Ċ³(Ė8ịẋs|Ṇdɼ⁼:Œẓİ,ḃṙɠX’ṃØẠs2ḟ€”A
“|zƒẉ“®6ẎẈ3°Ɠ“⁸)Ƙ¿’ḃ2’T€ị¢
¢ĖẈṪ$ÞṚƊ€
3£OŻ€3¦ŒpFḟ0Ɗ€J+“Ḥœ’,ƲyO2£OJ+⁽.[,Ʋ¤y¹ỌŒḊ?€µ¢ṖŒpZF€’ḋ588,28+“Ḥþ’Ʋ0;,ʋ/ṚƲ€ñṣ0ḊḢ+®Ṫ¤Ɗ;ṫ®$Ɗ¹Ḋ;⁶Ṫ⁼ṁ@¥¥Ƈ@¢ṪẈṪ‘;Ʋ€¤ḢƲ©?€ṭḢƲF2£żJ+⁽.[Ɗ$ẈṪ$ÞṚ¤ñỌ

Try it online!
A full program that takes a string as its argument and returns a string (which is implicitly printed). This works in three passes: first it converts all Korean characters to lists of code points for the Latin letters. Then it identifies and builds the compound Korean characters. Finally, it turns any remaining stray Latin letters to the Korean equivalent. Note that other characters and Latin letters that don’t appear in the spec (e.g. A) are left alone.
If conversion to lower case of capital letters outside spec is needed, this can be done at a cost of an additional 10 bytes.
Explanation
Helper link 1: dyadic link with arguments x and y. x is a list of pairs of search and replace sublists. y will have each search sublist replaced with the corresponding replace sublist
Ẏ      | Tighten (reduce to a single list of alternating search and replace sublists)
     ƒ | Reduce using y as starting argument and the following link:
    ƭ  | - Alternate between using the following two links:
 œṣ    |   - Split at sublist
   j   |   - Join using sublist

Helper link 2: List of Latin characters/character pairs in the order that corresponds to the Unicode order of the Korean characters
“Ȯ..X’          | Base 250 integer 912...
      ṃØẠ       | Base decompress into Latin letters (A..Za..z)
         s2     | Split into twos
           ḟ€”A | Filter out A from each (used as filler for the single characters)

Helper link 3: Lists of Latin characters used for Choseong, Jungseong and Jongseong
“|...¿’        | List of base 250 integers, [1960852478, 2251799815782398, 2143287262]
       ḃ2      | Convert to bijective base 2
         ’     | Decrease by 1
          T€   | List of indices of true values for each list
            ị¢ | Index into helper link 2

Helper link 4: Above lists of Latin characters enumerated and sorted in decreasing order of length
¢         | Helper link 3 as a nilad
       Ɗ€ | For each list, the following three links as a monad
 Ė        | - Enumerate (i.e. prepend a sequential index starting at 1 to each member of the list)
    $Þ    | - Sort using, as a key, the following two links as a monad
  Ẉ       |   - Lengths of lists
   Ṫ      |   - Tail (this will be the length of the original character or characters)
      Ṛ   | - Reverse

Main link: Monad that takes a Jelly string as its argument and returns the translated Jelly string
Section 1: Convert morphemic blocks to the Unicode codepoints of the corresponding Latin characters
Section 1.1: Get the list of Latin character(s) needed to make the blocks
3£      | Helper link 3 as a nilad (lists of Latin characters used for Choseong, Jungseong and Jongseong)
  O     | Convert to Unicode code points
   Ż€3¦ | Prepend a zero to the third list (Jongseong)

Section 1.2: Create all combinations of these letters (19×21×28 = 11,172 combinations in the appropriate lexical order)
Œp      | Cartesian product
     Ɗ€ | For each combination:
  F     | - Flatten
   ḟ0   | - Filter zero (i.e. combinations with an empty Jonseong)

Section 1.3: Pair the Unicode code points of the blocks with the corresponding list of Latin characters, and use these to translate the morphemic blocks in the input string
       Ʋ   | Following as a monad
J          | - Sequence from 1..11172
 +“Ḥœ’     | - Add 44031
      ,    | - Pair with the blocks themelves
        y  | Translate the following using this pair of lists
         O | - The input string converted to Unicode code points

Section 2: Convert the individual Korean characters in the output from section 1 to the code points of the Latin equivalent
          ¤  | Following as a nilad
2£           | Helper link 2 (list of Latin characters/character pairs in the order that corresponds to the Unicode order of the Korean characters)
  O          | Convert to Unicode code points
         Ʋ   | Following as a monad:
   J         | - Sequence along these (from 1..51)
    +⁽.[     | - Add 12592
        ,    | - Pair with list of Latin characters
           y | Translate the output from section 1 using this mapping

Section 3: Tidy up untranslated characters in the output from section 2 (works because anything translated from Korean will now be in a sublist and so have depth 1)
  ŒḊ?€  | For each member of list if the depth is 1:
¹       | - Keep as is
 Ọ      | Else: convert back from Unicode code points to characters
      µ | Start a new monadic chain using the output from this section as its argument

Section 4: Convert morphemic blocks of Latin characters into Korean
Section 4.1: Get all possible combinations of Choseong and Jungseong
¢    | Helper link 4 (lists of Latin characters enumerated and sorted in decreasing order of length)
 Ṗ   | Discard last list (Jongseong)
  Œp | Cartesian product

Section 4.2: Label each combination with the Unicode code point for the base morphemic block (i.e. with no Jongseong)
                       Ʋ€ | For each Choseong/Jungseong combination
Z                         | - Transpose, so that we now have e.g. [[1,1],["r","k"]]
 F€                       | - Flatten each, joining the strings together
                    ʋ/    | - Reduce using the following as a dyad (effectively using the numbers as left argument and string of Latin characters as right)
                Ʋ         |   - Following links as a monad
   ’                      |     - Decrease by 1
    ḋ588,28               |     - Dot product with 21×28,28
           +“Ḥþ’          |     - Add 44032
                 0;       |     - Prepend zero; used for splitting in section 4.3 before each morphemic block (Ż won’t work because on a single integer it produces a range)
                   ,      |     - Pair with the string of Latin characters
                      Ṛ   |   - Reverse (so we now have e.g. ["rk", 44032]

Section 4.3: Replace these strings of Latin characters in the output from section 3 with the Unicode code points of the base morphemic block
ñ   | Call helper link 1 (effectively search and replace)
 ṣ0 | Split at the zeros introduced in section 4.2

Section 4.4: Identify whether there is a Jongseong as part of each morphemic block
                                        Ʋ | Following as a monad:
Ḋ                                         | - Remove the first sublist (which won’t contain a morphemic block; note this will be restored later)
                                     €    | - For each of the other lists Z returned by the split in section 4.3 (i.e. each will have a morphemic block at the beginning):
                                  Ʋ©?     |   - If the following is true (capturing its value in the register in the process)
             Ḋ                            |     - Remove first item (i.e. the Unicode code point for the base morphemic block introduced in section 4.3)
              ;⁶                          |     - Append a space (avoids ending up with an empty list if there is nothing after the morphemic block code point)
                                          |       (Output from the above will be referred to as X below)
                                ¤         |       * Following as a nilad (call this Y):
                        ¢                 |         * Helper link 4
                         Ṫ                |         * Jongseong
                              Ʋ€          |         * For each Jongseong Latin list:
                          Ẉ               |           * Lengths of lists
                           Ṫ              |           * Tail (i.e. length of Latin character string)
                            ‘             |           * Increase by 1
                             ;            |           * Prepend this (e.g. [1, 1, "r"]
                     ¥Ƈ@                  |     - Filter Y using X from above and the following criteria
                Ṫ                         |       - Tail (i.e. the Latin characters for the relevant Jongseong
                 ⁼ṁ@¥                     |       - is equal to the beginning of X trimmed to match the relevant Jongseong (or extended but this doesn’t matter since no Jongseong are a double letter)
                                  Ḣ       |       - First matching Jongseong (which since they’re sorted by descending size order will prefer the longer one if there is a matching shorter one)
           Ɗ                              | - Then: do the following as a monad (note this is now using the list Z mentioned much earlier):
      Ɗ                                   |   - Following as a monad
 Ḣ                                        |     - Head (the Unicode code point of the base morphemic block)
  +®Ṫ¤                                    |     - Add the tail of the register (the position of the matched Jongsepng in the list of Jongseong)
       ;                                  |   - Concatenate to:
        ṫ®$                               |     - The rest of the list after removing the Latin characters representing the Jongseong
            ¹                             | - Else: leave the list untouched (no matching Jongseong)
                                       ṭ  | - Prepend:
                                        Ḣ |   - The first sublist from the split that was removed at the beginning of this subsection

Section 5: Handle remaining Latin characters that match Korean ones but are not part of a morphemuc block
F                   | Flatten
                ¤   | Following as a nilad
 2£                 | - Helper link 2 (Latin characters/pairs of characters in Unicode order of corresponding Korean character)
          $         | - Following as a monad
   ż     Ɗ          |   - zip with following as a monad
    J               |     - Sequence along helper link 2 (1..51)
     +⁽.[           |     - Add 12592
             $Þ     | - Sort using following as key
           Ẉ        |   - Lengths of lists
            Ṫ       |   - Tail (i.e. length of Latin string)
               Ṛ    | - Reverse
                 ñ  | Call helper link 1 (search Latin character strings and replace with Korean code points)
                  Ọ | Finally, convert all Unicode code points back to characters and implicitly output

Output is wrong : When I put 책, I excepted cor, but it gave cBor. And it does not change c to ㅊ. can had to converted into ㅊ무, but it converted into c무. And I also excepted large characters which don't appear in spec would decapitalized, but it can be fine.

@LegenDUST the c problem is fixed. I used A as a placeholder for the second character of single characters, and for some reason the one after c was coming out as a B. Conversion to lower case of other letters could be done, but feels like an unnecessary complication to what’s already a difficult challenge.

I understand this is hard. So I added new rule : if you decapitalize, you can earn 5 bytes. But this is fine.

JavaScript (Node.js), 587 582 575 569 557 554 550 549 bytes
tfw you didn't know that string.charCodeAt() == string.charCodeAt(0).
s=>s.replace(eval(`/[ㄱ-힣]|${M="(h[kol]?|n[jpl]?|ml?|[bi-puyOP])"}|([${S="rRseEfaqQtTdwWczxvg"}])(${M}((s[wg]|f[raqtxvg]|qt|[${S}])(?!${M}))?)?/g`,L="r,R,rt,s,sw,sg,e,E,f,fr,fa,fq,ft,fx,fv,fg,a,q,Q,qt,t,T,d,w,W,c,z,x,v,g,k,o,i,O,j,p,u,P,h,hk,ho,hl,y,n,nj,np,nl,n,m,ml,l".split`,`,l=L.filter(x=>!/[EQW]/.test(x)),I="indexOf"),(a,E,A,B,C,D)=>a<"~"?E?X(E):A&&C?F(43193+S[I](A)*588+L[I](C)*28+l[I](D)):X(A)+X(C)+X(D):(b=a.charCodeAt()-44032)<0?L[b+31439]||a:S[b/588|0]+L[30+b/28%21|0]+["",...l][b%28],F=String.fromCharCode,X=n=>n?F(L[I](n)+12593):"")

Try it online!
547 if characters outside alphabets and korean jamos can be ignored.
Okay I struggled for so long to write this, but this should work. No Korean jamo/syllable is used because they are too expensive (3 bytes per use). Used in the regular expression to save bytes.
s=>                                                    // Main Function:
 s.replace(                                            //  Replace all convertible strings:
  eval(
   `/                                                  //   Matching this regex:
    [ㄱ-힣]                                             //   ($0) All Korean jamos and syllables
    |${M="(h[kol]?|n[jpl]?|ml?|[bi-puyOP])"}           //   ($1) Isolated jungseong codes
    |([${S="rRseEfaqQtTdwWczxvg"}])                    //   ($2) Choseong codes (also acts as lookup)
     (                                                 //   ($3) Jungseong and jongseong codes:
      ${M}                                             //   ($4)  Jungseong codes
      (                                                //   ($5)  Jongseong codes:
       (                                               //   ($6)
        s[wg]|f[raqtxvg]|qt                            //          Diagraphs unique to jongseongs
        |[${S}]                                        //          Or jamos usable as choseongs
       )
       (?!${M})                                        //         Not linked to the next jungseong
      )?                                               //        Optional to match codes w/o jongseong
     )?                                                //       Optional to match choseong-only codes
   /g`,                                                //   Match all
   L="(...LOOKUP TABLE...)".split`,`,                  //   Lookup table of codes in jamo order
   l=L.filter(x=>!/[EQW]/.test(x)),                    //   Jongseong lookup - only first half is used
   I="indexOf"                                         //   [String|Array].prototype.indexOf
  ),
  (a,E,A,B,C,D)=>                                      //   Using this function:
   a<"~"?                                              //    If the match is code (alphabets):
    E?                                                 //     If isolated jungseongs code:
     X(E)                                              //      Return corresponding jamo
    :A&&C?                                             //     Else if complete syllable code:
     F(43193+S[I](A)*588+L[I](C)*28+l[I](D))           //      Return the corresponding syllable
    :X(A)+X(C)+X(D)                                    //     Else return corresponding jamos joined
   :(b=a.charCodeAt()-44032)<0?                        //    Else if not syllable:
    L[b+31439]||a                                      //     Return code if jamo (if not, ignore)
   :S[b/588|0]+L[30+b/28%21|0]+["",...l][b%28],        //    Else return code for the syllable
  F=String.fromCharCode,                               //   String.fromCharCode
  X=n=>                                                //   Helper function to convert code to jamo
   n?                                                  //    If not undefined:
    F(L[I](n)+12593)                                   //     Return the corresponding jamo
   :""                                                 //    Else return empty string
 )

Wolfram Language (Mathematica), 405 401 400 bytes
c=CharacterRange
p=StringReplace
q=StringReverse
r=Reverse
t=Thread
j=Join
a=j[alphabet@"Korean",4520~c~4546]
x=j[#,r/@#]&@t[a->Characters@"rRseEfaqQtTdwWczxvgkoiOjpuPh"~j~StringSplit@"hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g"]
y=t[""<>r@#&/@Tuples@TakeList[Insert[a,"",41]~p~x~p~x,{19,21,28}]->44032~c~55203]
f=q@p[q@#,#2]&
g=f[#,r/@y]~p~x~f~y&

Try it online!
Slightly ungolfed
To test this in Mathematica just replace alphabet with Alphabet; however, TIO doesn't support the Wolfram Cloud so I defined Alphabet["Korean"] in the header.
We first decompose all Hangul syllables to the Hangul alphabet, then swap Latin and Hangul characters, then recompose the syllables.

Test case input 2 results in ㅑㅜㅔㅕㅅ 2 instead of ㅑㅞㅕㅅ 2 in your TIO. Although the same happens in the solution I was working on, since both ㅜ and ㅔ are jungseong, and I was under the impression only choseong+jungseong+jongseong or choseong+jungseong+empty would be combined. I asked OP for verification why ㅜㅔ became ㅞ.

@KevinCruijssen ㅞ (np) is a jungseong in its own right

This doesn’t seem to work properly for two character consonants or vowels. For example fnpfa should be a single character 뤪 but instead ends up as 루ㅔㄹㅁ

Fix in progress. It shouldn't cost too much.

Java 19, 1133 1126 1133 bytes
s->{String r="",k="ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ",K[]=k.split(" "),a="r R s e E f a q Q t T d w W c z x v g k o i O j p u P h hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g";var A=java.util.Arrays.asList(a.split(" "));k=k.replace(" ","");int i,z,y,x=44032;for(var c:s.toCharArray())if(c>=x&c<55204){z=(i=c-x)%28;y=(i=(i-z)/28)%21;s=s.replace(c+r,r+K[0].charAt((i-y)/21)+K[1].charAt(y)+(z>0?K[2].charAt(z-1):r));}for(var c:s.split(r))r+=c.charAt(0)<33?c:(i=k.indexOf(c))<0?(i=A.indexOf(c))<0?c:k.charAt(i):A.get(i);for(i=r.length()-1;i-->0;r=z>0?r.substring(0,i)+(char)(K[0].indexOf(r.charAt(i))*588+K[1].indexOf(r.charAt(i+1))*28+((z=K[2].indexOf(r.charAt(i+2)))<0?0:z+1)+x)+r.substring(z<0?i+2:i+3):r)for(z=y=2;y-->0;)z&=K[y].contains(r.charAt(i+y)+"")?2:0;for(var p:"ㅗㅏㅘㅗㅐㅙㅗㅣㅚㅜㅓㅝㅜㅔㅞㅜㅣㅟㅡㅣㅢ".split("(?<=\\G...)"))r=r.replace(p.substring(0,2),p.substring(2));return r;}

Outputs with capital letters ASDFGHJKLZXCVBNM unchanged, since .toLowerCase() costs more than the -5 bonus.
Back +7 bytes as a bug-fix for non-Korean characters above unicode value 20,000 (thanks @NickKennedy for noticing).
Try it online.
Explanation:
s->{                         // Method with String as both parameter and return-type
  String r="",               //  Result-String, starting empty
         k="ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ",
                             //  String containing the Korean characters
         K[]=k.split(" "),   //  Array containing the three character-categories
         a="r R s e E f a q Q t T d w W c z x v g k o i O j p u P h hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g";
                             //  String containing the English characters
  var A=java.util.Arrays.asList(a.split(" "));
                             //  List containing the English character-groups
  k=k.replace(" ","");       //  Remove the spaces from the Korean String
  int i,z,y,                 //  Temp integers
      x=44032;               //  Integer for 0xAC00
  for(var c:s.toCharArray()) //  Loop over the characters of the input:
    if(c>=x&c<55204){        //   If the unicode value is in the range [44032,55203]
                             //   (so a Korean combination character):
      z=(i=c-x)%28;          //    Set `i` to this unicode value - 0xAC00,
                             //    And then `z` to `i` modulo-28
      y=(i=(i-z)/28)%21;     //    Then set `i` to `i`-`z` integer divided by 28
                             //    And then `y` to `i` modulo-21
      s=s.replace(c+r,       //    Replace the current non-Korean character with:
        r+K[0].charAt((i-y)/21)
                             //     The corresponding choseong
         +K[1].charAt(y)     //     Appended with jungseong
         +(z>0?K[2].charAt(z-1):r));}
                             //     Appended with jongseong if necessary
  for(var c:s.split(r))      //  Then loop over the characters of the modified String:
    r+=                      //   Append to the result-String:
       c.charAt(0)<33?       //    If the character is a space:
        c                    //     Simply append that space
       :(i=k.indexOf(c))<0?  //    Else-if the character is NOT a Korean character:
         (i=A.indexOf(c))<0? //     If the character is NOT in the English group List:
          c                  //      Simply append that character
         :                   //     Else:
          k.charAt(i)        //      Append the corresponding Korean character
       :                     //    Else:
        A.get(i);            //     Append the corresponding letter
  for(i=r.length()-1;i-->0   //  Then loop `i` in the range (result-length - 2, 0]:
      ;                      //    After every iteration:
       r=z>0?                //     If a group of Korean characters can be merged:
          r.substring(0,i)   //      Leave the leading part of the result unchanged
          +(char)(K[0].indexOf(r.charAt(i))
                             //      Get the index of the first Korean character,
                   *588      //      multiplied by 588
                  +K[1].indexOf(r.charAt(i+1))
                             //      Get the index of the second Korean character,
                   *28       //      multiplied by 28
                  +((z=K[2].indexOf(r.charAt(i+2)))
                             //      Get the index of the third character
                    <0?      //      And if it's a Korean character in the third group:
                      0:z+1) //       Add that index + 1
                  +x         //      And add 0xAC00
                 )           //      Then convert that integer to a character
          +r.substring(z<0?i+2:i+3)
                             //      Leave the trailing part of the result unchanged as well
         :                   //     Else (these characters cannot be merged)
          r)                 //      Leave the result the same
     for(z=y=2;              //   Reset `z` to 2
         y-->0;)             //   Inner loop `y` in the range (2, 0]:
       z&=                   //    Bitwise-AND `z` with:
         K[y].contains(      //     If the `y`'th Korean group contains
           r.charAt(i+y)+"")?//     the (`i`+`y`)'th character of the result
          2                  //      Bitwise-AND `z` with 2
         :                   //     Else:
          0;                 //      Bitwise-AND `z` with 0
                             //   (If `z` is still 2 after this inner loop, it means
                             //    Korean characters can be merged)
  for(var p:"ㅗㅏㅘㅗㅐㅙㅗㅣㅚㅜㅓㅝㅜㅔㅞㅜㅣㅟㅡㅣㅢ".split("(?<=\\G...)"))
                             //  Loop over these Korean character per chunk of 3:
    r=r.replace(p.substring(0,2),
                             //   Replace the first 2 characters in this chunk
         p.substring(2));    //   With the third one in the result-String
  return r;}                 //  And finally return the result-String

they’re from 44032 to 55203. You’ve already got the start location coded. The end is just 44032 + 19×21×28 - 1

Works well now. Thought I’d already upvoted you but hadn’t, so here you go!


text:
Maximum summed sub sequences with no two numbers sharing the same digit
Suppose there are 5 positive integers in an array or list as 14, 12, 23, 45, 39.
14 and 12 cannot be taken in the subset as 1 is common in both. Similarly {12, 23}, {23, 39}, {14, 45} cannot be included in the same subset.
So the subset which forms the maximum sum is {12, 45, 39}. The maximum sum such formed is 96.
the result should be the maximum sum of such combination.
Sample TestCase 1
Input
3,5,7,2
Output
17
Sample Test Case 2
Input
121,23,3,333,4
Output
458
Sample Test Case 3
Input
32,42,52,62,72,82,92
Output
92
Explanation
Test Case 1: {3, 5, 7, 2} = 17
Test Case 2: {121, 333, 4} = 458
Test Case 3: {92} = 92

thanks for the information, i've tagged it appropriately.

Welcome to PPCG!

added few more test cases.

Is this challenge from another programming contest site?

Why did you remove the winning criterion? Doing so makes the challenge off-topic.

...plus there are already nine answers using code-golf as a winning criteria.

05AB1E, 11 bytes
æʒ€ÙJDÙQ}OZ

Try it online!
Explanation
æʒ      }    # filter the powerset of the input, keep only elements
  €Ù         # where each number with duplicate digits removed
    JDÙQ     # have different digits from the other numbers
         O   # sum each
          Z  # take max

Test Case 2: {121, 333, 4} = 458

@JonathanAllan: Ah OK. Same digits in a number is okay. Fixed :)

Wolfram Language (Mathematica), 77 bytes
Max[Tr/@Select[(s=Subsets)@#,!Or@@IntersectingQ@@@s[IntegerDigits/@#,{2}]&]]&

Try it online!

thanks for the solution, could you please explain, as I have limited knowledge of Wolfram Langauge.

Python 2, 137 112 105 119 116 bytes
lambda a,s='':a and max([x+f(a[1:],y)for x,y in(0,s),(a[0],s+`set(`a[0]`)`)if max(map(y.count,'1234567890'))<2])or 0

Try it online!

Python 3.8 (pre-release), 116 bytes
lambda a,s='':a and max(x+f(a[1:],y)for x in(0,a[0])if max(map((y:=s+str(set(str(x)*x))).count,'1234567890'))<2)or 0

Try it online!

Thanks for the solution, added more test cases.

Failing the second test case. Sample Test Case 2 Input 121,23,3,333,4 Output 458

Needs more work I think since print f([121,23,3,333,4]) in the TIO returns 27, not 458.

@biziden Fixed.

@KjetilS. Fixed

thanks for the solution, although it's giving syntax error on Python 3.7

@biziden The top one is for Python 2 (probably 2.7), the bottom one uses 3.8 features, neither will work in 3.7. Furthermore note that this stack is not the place to get a piece of code to do the task at hand, in most cases the code would not be what you want to use in any real scenario.

@JonathanAllan thanks, I am new here and didn't know it, I am happy to see so many new programming languages, which I was not aware of, do we also provide pseudo-code over here.

Pseudo-code cannot usually compete (unless the challenge warrants it, which is unlikely). Note that the vast majority of challenges have a winning criteria of [tag:code-golf].

Jelly,  12  11 bytes
-1 thanks to Nick Kennedy (use the implicit make_digits of Q to get rid of D)
ŒPQ€FQƑƊƇ§Ṁ

A monadic Link accepting a list of positive integers which yields the maximal sum of those subsets which repeat no decimal digits between elements.
Try it online!
How?
ŒPQ€FQƑƊƇ§Ṁ - Link: list of positive integers
ŒP          - power set
        Ƈ   - filter keep those for which:
       Ɗ    -   last three links as a monad:
  Q€        -     de-duplicate each
    F       -     flatten
      Ƒ     -     is invariant under:
     Q      -       de-duplication
         §  - sum each
          Ṁ - maximum

You can drop the D: ŒPQ€FQƑƊƇ§Ṁ for 11

Ah, yes I forgot that Q performs a call to iterable with make_digits=True. Thanks!

JavaScript (ES6), 77 bytes
f=([n,...a],s=m=0,p='')=>n?f(a,s,p,p.match(`[${n}]`)||f(a,s+n,p+n)):m=m>s?m:s

Try it online!
Commented
f = (                    // f is a recursive function taking:
  [n, ...a],             //   n = next value from a[]; a[] = remaining values
  s =                    //   s = current sum
  m = 0,                 //   m = maximum sum, which is eventually returned
  p = ''                 //   p = all previous digits, as a string
) =>                     //
  n ?                    // if n is defined:
    f(                   //   do a recursive call ...
      a, s, p,           //     ... with all parameters unchanged
      p.match(`[${n}]`)  //     tests whether p contains any digit of n
      ||                 //     if it doesn't:
        f(               //       do another recursive call with:
          a,             //         a[] unchanged
          s + n,         //         n added to s (as an integer)
          p + n          //         n appended to p (as a string)
        )                //       end of inner recursive call
    )                    //   end of outer recursive call
  :                      // else:
    m = m > s ? m : s    //   this is a leaf node: update m to max(m, s)

Haskell, 81 76 bytes
_?[]=0
n?(a:b)|any(`elem`n)$show a=n?b|True=max(n?b)$a+(n++show a)?b
g=(""?)

Try it online!

Brachylog, 13 bytes
{⊇.dᵐc≠∧}ᶠ+ᵒt

Try it online!
Explanation
{     }ᶠ         Find all…
 ⊇.                subsets of the input…
   dᵐ              …where each number with duplicate digits removed…
     c≠∧           …has different digits from the others
          +ᵒ     Order by sum
            t    Tail (last element)

@JonathanAllan Fixed at the cost of 2 bytes, thanks.

You seem to output the list instead of the sum.

might not work for all the cases.

Perl 5, 82 bytes
max(map{my$n=2*$_;my@t=grep{($n/=2)%2}@_;"@t"!~/(\d).* .*\1/?sum(@t):0}0..2**@_-1)

Try it online!
With spaces:
sub f {
    max(
      map {
        my $n = 2 * $_;
        my @t = grep {($n/=2)%2} @_;
        "@t"!~/(\d).* .*\1/ ? sum(@t) : 0
      }
      0 .. 2**@_-1
    )
}

Loops through all possible 2^n subarrays of the input array where each element either participates or not. Then for valid subarrays, those not matching the regex which finds common digits in other elements, use the sum of them and return the max of those valid sums.

Python 2, 94 bytes
f=lambda l,r=[],S=set:l and max([f(l[1:],r+l[:1]),f(l[1:],r)][S(`l[0]`)&S(`r`)>S():])or sum(r)

Try it online!

Python 3.8 (pre-release), 95 bytes
f=lambda l,r=[]:l and max([f(k:=l[1:],r+l[:1]),f(k,r)][bool({*str(l[0])}&{*str(r)}):])or sum(r)

Try it online!