37
\$\begingroup\$

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,

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
\$\endgroup\$
  • 4
    \$\begingroup\$ Can the input be given in all lowercase? \$\endgroup\$ – ETHproductions Sep 12 '16 at 17:11
  • 15
    \$\begingroup\$ My wife who is a native Welsh speaker would recommend that the J is added into the "Borrowed" letters section as it isn't actually part of the Welsh alphabet \$\endgroup\$ – Rich Starkie Sep 12 '16 at 20:29
  • \$\begingroup\$ @RichStarkie The Wikipedia article was a little vague on that front. My understanding is that j is used in borrowed words even when it's not present in the original word, so it's used phonologically, which implies that at this stage it's natualized into the language. I've seen similar arguments about v in Irish. It's widely considered not to be part of the Irish alphabet, but it exists in some Irish names, such as Ó Cuiv. \$\endgroup\$ – TRiG Sep 12 '16 at 21:06
  • 1
    \$\begingroup\$ And a footnote in the Welsh orthography article lists mh, nh, and ngh as graphems. Methinks I need to open a question on Linguistics SE. \$\endgroup\$ – TRiG Sep 13 '16 at 15:13
  • 3
    \$\begingroup\$ Shame it's too late; that triple-glyphed "ngh" might have made it a little more complicated. \$\endgroup\$ – megaflop Sep 13 '16 at 15:15

15 Answers 15

6
\$\begingroup\$

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!

\$\endgroup\$
16
\$\begingroup\$

Retina, 23 bytes

i`[cprt]h|dd|ff|ng|ll|.

Try it online!

Even moar regex.

\$\endgroup\$
  • \$\begingroup\$ It's probably my ignorance of Retina, but where is the outputting of the length of the input text? The documentation on Retina doesn't seem to explain how that's working in the "Try it online!" site. \$\endgroup\$ – Xaero Degreaz Sep 13 '16 at 14:38
  • 2
    \$\begingroup\$ The output is implicit, because the only line is a Match stage, returning the number of matches. Here, the regex matches every Welsh letter. \$\endgroup\$ – user48538 Sep 13 '16 at 15:17
  • \$\begingroup\$ So by that logic, then every answer below where the length is explicitly called in the code can be shortened? \$\endgroup\$ – Xaero Degreaz Sep 13 '16 at 15:29
  • 2
    \$\begingroup\$ @XaeroDegreaz Retina is one of the only languages that automatically counts matches and prints them out. This is how Retina, the language, works. It is not how other languages work, and so those languages need to call their length functions explicitly to get the right output. \$\endgroup\$ – isaacg Sep 13 '16 at 15:42
  • \$\begingroup\$ Thanks, I understand now. After reading more into the documentation I see the default "Match" stage performs this output. \$\endgroup\$ – Xaero Degreaz Sep 13 '16 at 16:02
5
\$\begingroup\$

JavaScript (ES6), 44 bytes

x=>x.match(/[cprt]h|dd|ff|ng|ll|./gi).length

The trivial answer may be the shortest.

\$\endgroup\$
5
\$\begingroup\$

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).

\$\endgroup\$
  • 1
    \$\begingroup\$ Why grep -o .|wc -l instead of wc -c? \$\endgroup\$ – Jordan Sep 13 '16 at 5:04
  • \$\begingroup\$ wc -c counts â through ẁ as two. \$\endgroup\$ – Riley Sep 13 '16 at 12:27
  • \$\begingroup\$ Ah, of course. FWIW if you use GNU or BSD wc you can use -m to count characters instead of bytes. \$\endgroup\$ – Jordan Sep 13 '16 at 12:56
  • \$\begingroup\$ Can you move the c from ch in with the [prt]? sed -r 's,dd|ff|ng|ll|[cprt]h,1,gi'|wc -m \$\endgroup\$ – megaflop Sep 13 '16 at 15:15
  • 2
    \$\begingroup\$ It's a shame ([dfl])\1 would longer than dd|ff|ll. Just one more doubled-consonant would favour the clever version. \$\endgroup\$ – Toby Speight Nov 11 '16 at 14:51
4
\$\begingroup\$

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! (The added code is to verify all test cases)

\$\endgroup\$
  • \$\begingroup\$ How does this language differ from something like Retina? \$\endgroup\$ – Downgoat Sep 12 '16 at 21:33
  • \$\begingroup\$ @Downgoat Straw is stack-based :P \$\endgroup\$ – TuxCrafting Sep 12 '16 at 21:34
3
\$\begingroup\$

Python 3, 64 bytes

import re
print(len(re.findall("[cprt]h|dd|ff|ng|ll|.",input())))

Uses regex again

Ideone it!

\$\endgroup\$
3
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ I'm not familiar with PowerShell, but do you really need the parentheses around [prtc]h? \$\endgroup\$ – Jordan Sep 12 '16 at 17:38
  • \$\begingroup\$ @Jordan No, I do not. That's not a PowerShell thing, that's a me-not-good-at-regex thing. :D Thanks for the golf! \$\endgroup\$ – AdmBorkBork Sep 12 '16 at 18:03
2
\$\begingroup\$

V, 31 bytes

Íã[cprt]hüddüffüngüllü./
Dé0@"

Try it online, or Verify all test cases!

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@"
\$\endgroup\$
2
\$\begingroup\$

PHP , 56 Bytes

<?=preg_match_all("#[cprt]h|dd|ff|ll|ng|.#iu",$argv[1]);
\$\endgroup\$
  • 1
    \$\begingroup\$ I believe [dfl]{2} matches df, ld, etc. as well as its intended matches. dd|ff|ll is the same length. \$\endgroup\$ – ETHproductions Sep 12 '16 at 20:14
  • 1
    \$\begingroup\$ I know that your believe is true but I think that your believe s not a type of believe. it looks more than a type of kowledge \$\endgroup\$ – Jörg Hülsermann Sep 12 '16 at 20:34
  • 1
    \$\begingroup\$ Instead of echo(space at the end), use <?=, which saves 2 bytes. Also, the $t isn't necessary there, saving you 3 more bytes. \$\endgroup\$ – Ismael Miguel Sep 13 '16 at 10:57
  • \$\begingroup\$ Thnak You Ismael . I must be more then a little confused that I not remove the $t \$\endgroup\$ – Jörg Hülsermann Sep 13 '16 at 11:14
2
\$\begingroup\$

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.

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
\$\endgroup\$
  • \$\begingroup\$ You import and then you don't use Matcher directly? :o Also, Matcher can be defined in the for loop. \$\endgroup\$ – Olivier Grégoire Sep 13 '16 at 13:03
  • 1
    \$\begingroup\$ I have the strong feeling that return s.replaceAll("[cprt]h|dd|ff|ng|ll","a").length() is way, way shorter. Can't this work? \$\endgroup\$ – Olivier Grégoire Sep 13 '16 at 13:07
  • \$\begingroup\$ Well, yes, it works, and it's 73 bytes for the Java 7 version (int c(String s){return s.replaceAll("[cprt]h|dd|ff|ng|ll","a").length();}). And only 51 for the Java 8 version (s->s.replaceAll("[cprt]h|dd|ff|ng|ll","a").length()). \$\endgroup\$ – Olivier Grégoire Sep 13 '16 at 13:17
  • 1
    \$\begingroup\$ @OlivierGrégoire Thanks. The Matcher was an accident. I had it correctly in the test code, but not in the golfed code.. >.> Your replaceAll works better though, thanks. \$\endgroup\$ – Kevin Cruijssen Sep 13 '16 at 13:27
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 36 bytes

+*.comb(/:i.|<[cprt]>h|dd|ff|ng|ll/)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

XQuery, 77 bytes

declare variable$s external;count(tokenize($s,'[cprt]h|ff|dd|ll|ng|.','i'))-1
\$\endgroup\$
0
\$\begingroup\$

tcl, 71

proc L s {string le [regsub -all -nocase ch|dd|ff|ng|ll|ph|rh|th $s @]}

demo

\$\endgroup\$
0
\$\begingroup\$

Perl 5, 35 + 1 (-p) = 36 bytes

s/[cprt]h|dd|ff|ng|ll/a/gi;$_=y///c

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.