[Question]
  [
Write a program or function which receives as input a string representing a Welsh word (UTF-8 unless otherwise specified by you).
The following are all *single letters* in Welsh:
> 
> a, b, c, ch, d, dd, e, f, ff, g, ng, h, i, j, l, ll, m, n, o, p, ph, r, rh, s, t, th, u, w, y
> 
> 
> 
To quote [Wikipedia](https://en.wikipedia.org/wiki/Welsh_orthography),
> 
> While the digraphs *ch*, *dd*, *ff*, *ng*, *ll*, *ph*, *rh*, *th* are each written with two symbols, they are all considered to be single letters. This means, for example that Llanelli (a town in South Wales) is considered to have only six letters in Welsh, compared to eight letters in English.
> 
> 
> 
These letters also exist in Welsh, though they are restricted to technical vocabulary borrowed from other languages:
> 
> k, q, v, x, z
> 
> 
> 
Letters with diacritics are not regarded as separate letters, but your function must accept them and be able to count them. Possible such letters are:
> 
> â, ê, î, ô, û, ŷ, ŵ, á, é, í, ó, ú, ý, ẃ, ä, ë, ï, ö, ü, ÿ, ẅ, à, è, ì, ò, ù, ẁ
> 
> 
> 
(This means that ASCII is not an acceptable input encoding, as it cannot encode these characters.)
### Notes:
* This is code golf.
* You do not have to account for words like *llongyfarch*, in which the *ng* is not a digraph, but two separate letters. This word has nine letters, but you can miscount it as eight. (If you *can* account for such words, that's kind of awesome, but outside the scope of this challenge.)
* The input is guaranteed to have no whitespace (unless you prefer it with a single trailing newline (or something more esoteric), in which case that can be provided). There will certainly be no internal whitespace.
### Test cases:
* Llandudno, 8
* Llanelli, 6
* Rhyl, 3
* Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch, 50 (really 51, but we'll count 50)
* Tŷr, 3
* Cymru, 5
* Glyndŵr, 7
  
[Answer]
# [Retina](http://github.com/mbuettner/retina), 23 bytes
```
i`[cprt]h|dd|ff|ng|ll|.
```
[Try it online!](http://retina.tryitonline.net/#code=aWBbY3BydF1ofGRkfGZmfG5nfGxsfC4&input=TmVzYQ)
Even moar regex.
[Answer]
# [05AB1E](http://github.com/Adriandmen/05AB1E), ~~24~~ ~~23~~ 21 bytes
Code:
```
u•éÓœ°D¥M™ù>•30B2ô0:g
```
Explanation:
```
u                      # Convert the input to uppercase.
 •éÓœ°D¥M™ù>•30B       # Compressed version of CHDDFFNGLLPHRHTH.
                         It convert the text between the •'s from base 214 to
                         base 10 and converts that to base 30.
                2ô     # Split into pieces of 2.
                  0:   # Replace each element that also occurs in the input by 0.
                    g  # Get the length of the processed input.
```
Uses the **CP-1252** encoding. [Try it online!](http://05ab1e.tryitonline.net/#code=deKAosOpw5PFk8KwRMKlTeKEosO5PuKAojMwQjLDtDA6Zw&input=Umh5bA)
[Answer]
# JavaScript (ES6), 44 bytes
```
x=>x.match(/[cprt]h|dd|ff|ng|ll|./gi).length
```
The trivial answer may be the shortest.
[Answer]
# BASH 52 50 (sed + wc) 41
-9 thanks to Jordan
```
sed -r 's,dd|ff|ng|ll|[cprt]h,1,gi'|wc -m
```
If uppercase letter are required this needs an `i` at the end of the sed command. (I left it out because all of the "single letters" in the question are lowercase even though some examples aren't).
[Answer]
## [Straw](https://github.com/tuxcrafting/straw), ~~30~~ ~~58~~ ~~35~~ 33 bytes
```
<((?i:[cprt]h|dd|ff|ng|ll|.))0/$>
```
Replace each occurence of the regex by `0`, and convert from unary to decimal.
~~Sadly, Straw can't pass flags to regexs.~~ I forget about the `?flags:` construct
[Try it online!](http://straw.tryitonline.net/#code=KDwoKD9pOltjcHJ0XWh8ZGR8ZmZ8bmd8bGx8LikpMC8kPgo-KTcjKigmKTcjKiY&input=TGxhbmR1ZG5vCkxsYW5lbGxpClJoeWwKTGxhbmZhaXJwd2xsZ3d5bmd5bGxnb2dlcnljaHd5cm5kcm9id2xsbGxhbnR5c2lsaW9nb2dvZ29jaApUxbdyCkN5bXJ1CkdseW5kxbVy) (The added code is to verify all test cases)
[Answer]
# Python 3, 64 bytes
```
import re
print(len(re.findall("[cprt]h|dd|ff|ng|ll|.",input())))
```
Uses regex again
[**Ideone it!**](https://ideone.com/NANtPk)
[Answer]
## PowerShell v2+, ~~52~~ ~~50~~ 48 bytes
```
($args[0]-replace'dd|ff|ng|ll|[prtc]h',0).length
```
Does a `-replace` on all the two-symbol-single-letter letters, changes 'em to `0` (done because changing to a non-numeral would require quotes), then gets the `.length` of the resultant string.
### Test cases
```
PS C:\Tools\Scripts\golfing> 'Llandudno','Llanelli','Rhyl','Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch','Tŷr','Cymru','Glyndŵr'|%{"$_ --> "+(.\how-long-is-a-welsh-word.ps1 $_)}
Llandudno --> 8
Llanelli --> 6
Rhyl --> 3
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch --> 50
Tŷr --> 3
Cymru --> 5
Glyndŵr --> 7
```
[Answer]
# [V](http://github.com/DJMcMayhem/V), 31 bytes
```
Íã[cprt]hüddüffüngüllü./
Dé0@"
```
[Try it online](http://v.tryitonline.net/#code=w43Do1tjcHJ0XWjDvGRkw7xmZsO8bmfDvGxsw7wuLwEKRMOpMEAi&input=TGxhbmZhaXJwd2xsZ3d5bmd5bGxnb2dlcnljaHd5cm5kcm9id2xsbGxhbnR5c2lsaW9nb2dvZ29jaA), or [Verify all test cases!](http://v.tryitonline.net/#code=w43Do1tjcHJ0XWjDvGRkw7xmZsO8bmfDvGxsw7wuLwEKw45Ew6kwQCI&input=TGxhbmR1ZG5vCkxsYW5lbGxpClJoeWwKTGxhbmZhaXJwd2xsZ3d5bmd5bGxnb2dlcnljaHd5cm5kcm9id2xsbGxhbnR5c2lsaW9nb2dvZ29jaApUxbdyCkN5bXJ1CkdseW5kxbVy)
This contains some unprintable characters, so here is a hexdump:
```
0000000: cde3 5b63 7072 745d 68fc 6464 fc66 66fc  ..[cprt]h.dd.ff.
0000010: 6e67 fc6c 6cfc 2e2f 010a 44e9 3040 22    ng.ll../..D.0@"
```
[Answer]
# PHP , 56 Bytes
```
<?=preg_match_all("#[cprt]h|dd|ff|ll|ng|.#iu",$argv[1]);
```
[Answer]
# Java 7, ~~156~~ 73 bytes
Loads of bytes saved thanks to *@OlivierGrégoire*.
```
int c(String s){return s.replaceAll("[cprt]h|dd|ff|ng|ll","*").length();}
```
**Ungolfed & test cases:**
[Try it here.](https://ideone.com/wxWzFF)
```
class M{
  static int c(String s){
    return s.replaceAll("[cprt]h|dd|ff|ng|ll", "*").length();
  }
  public static void main(String[] a){
    System.out.println(c("llandudno"));
    System.out.println(c("llanelli"));
    System.out.println(c("rhyl"));
    System.out.println(c("llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch"));
    System.out.println(c("tŷr"));
    System.out.println(c("cymru"));
    System.out.println(c("glyndŵr"));
  }
}
```
**Output:**
```
8
6
3
50
3
5
7
```
[Answer]
## R, 54 bytes
Very similar to the other answers. Matches any of the two character letters and replaces them with `@` and subsequently counts the number of characters. Reads input from stdin. Uses the option `ignore.case = TRUE` (third argument to `gsub`) to match both upper and lowercase characters.
```
nchar(gsub("ch|dd|ff|ng|ll|ph|rh|th","@",scan(,""),T))
```
**Bonus**
Both `gsub` and `nchar` are vectorized which means that this also works on a character vector, e.g.:
```
v=c("Llandudno","Llanelli","Rhyl","Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch","Tŷr","Cymru","Glyndŵr")
nchar(gsub("ch|dd|ff|ng|ll|ph|rh|th","@",v,T))
```
produces:
```
[1]  8  6  3 50  3  5  7
```
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), 36 bytes
```
+*.comb(/:i.|<[cprt]>h|dd|ff|ng|ll/)
```
[Try it online!](https://tio.run/##HYrNCoJAFIXX@RSXiNAC27VIa9OiTatoFyHmOD9wnZGrIRenx4qewOcyi7M43@E7dUm4HSuGpYT9uF7Fhase4WZnYp/eipra@0F7IbyU3iqPuInGJJCOID1jbsVTWAc/KhENXDTjf8ncUN0hqo6t4qmdKokL3TFZQe4xKZxuLTcGjVP/FBquw4fgyBU94YRsxfCmA/TBrMkZ5osMehkusug1T4LX@AU "Perl 6 – Try It Online")
[Answer]
# XQuery, 77 bytes
```
declare variable$s external;count(tokenize($s,'[cprt]h|ff|dd|ll|ng|.','i'))-1
```
[Answer]
# tcl, 71
```
proc L s {string le [regsub -all -nocase ch|dd|ff|ng|ll|ph|rh|th $s @]}
```
# [demo](http://rextester.com/APD41427)
[Answer]
# [Perl 5](https://www.perl.org/), 35 + 1 (`-p`) = 36 bytes
```
s/[cprt]h|dd|ff|ng|ll/a/gi;$_=y///c
```
[Try it online!](https://tio.run/##HYpBCgMhDAA/02vJqafSH/QHpRSrawyERKIgAd9eV8oc5jBTD@PbWg1esVp/l5nSzHkKTmYIgHS/fB4OAHGtJwfJgawOZhwu6NuKh3ksw02S6Xcn3lv3RkyKf2L5ae2k0ta1ng "Perl 5 – Try It Online")
]