Count how many vowels and consonants occur in a string: Difference between revisions
Content added Content deleted
(→{{header|Python}}: Updated output) |
(→{{header|JavaScript}}: Added four possible interpretations) |
||
Line 329: | Line 329: | ||
('t',1) |
('t',1) |
||
('v',1)</pre> |
('v',1)</pre> |
||
=={{header|JavaScript}}== |
|||
This is a new genre-of deliberately ambiguous task description, perhaps ? |
|||
I suppose it might be thought to offer scope for variety, |
|||
but is it really achieving the Rosetta goal of comparability ? |
|||
(There seem to have been a surprising number of these recently, often |
|||
associated with tasks of uncertain novelty ...) |
|||
===Count of "Vowels and Consonants" ?=== |
|||
<lang javascript>(() => { |
|||
"use strict"; |
|||
// -------- COUNT OF "VOWELS AND CONSONANTS" --------- |
|||
// countOfVowelsAndConsonants :: String -> Int |
|||
const countOfVowelsAndConsonants = s => |
|||
s.split("").filter(isAlpha).length; |
|||
// ---------------------- TEST ----------------------- |
|||
const main = () => |
|||
`${countOfVowelsAndConsonants( |
|||
"Forever Fortran 2018 programming language" |
|||
)} "vowels and consonants"`; |
|||
// --------------------- GENERIC --------------------- |
|||
// isAlpha :: Char -> Bool |
|||
const isAlpha = c => |
|||
(/[A-Za-z\u00C0-\u00FF]/u).test(c); |
|||
// MAIN --- |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre>33 "vowels and consonants"</pre> |
|||
===Counts of distinct vowels and distinct consonants used ?=== |
|||
<lang javascript>(() => { |
|||
"use strict"; |
|||
// COUNTS OF DISTINCT VOWELS, AND DISTINCT CONSONANTS |
|||
// distinctVowelsAndConsonants :: |
|||
// String -> ([Char], [Char]) |
|||
const distinctVowelsAndConsonants = s => |
|||
both( |
|||
cs => sort(Array.from(new Set(cs))) |
|||
)( |
|||
partition(isVowel)( |
|||
Array.from(s).filter(isAlpha) |
|||
) |
|||
); |
|||
// ---------------------- TEST ----------------------- |
|||
// main :: IO () |
|||
const main = () => { |
|||
const vc = both( |
|||
cs => `(${cs.join("")}, ${cs.length})` |
|||
)( |
|||
distinctVowelsAndConsonants( |
|||
"Forever Fortran 2018 programming language" |
|||
) |
|||
); |
|||
return [ |
|||
`Distinct vowels: ${vc[0]}`, |
|||
`Distict consonants: ${vc[1]}` |
|||
].join("\n\n"); |
|||
}; |
|||
// --------------------- GENERIC --------------------- |
|||
// Tuple (,) :: a -> b -> (a, b) |
|||
const Tuple = a => |
|||
b => ({ |
|||
type: "Tuple", |
|||
"0": a, |
|||
"1": b, |
|||
length: 2 |
|||
}); |
|||
// both :: (a -> b) -> (a, a) -> (b, b) |
|||
const both = f => |
|||
ab => Tuple( |
|||
f(ab[0]) |
|||
)( |
|||
f(ab[1]) |
|||
); |
|||
// isAlpha :: Char -> Bool |
|||
const isAlpha = c => |
|||
(/[A-Za-z\u00C0-\u00FF]/u).test(c); |
|||
// isVowel :: Char -> Bool |
|||
const isVowel = c => |
|||
(/[AEIOUaeiou]/u).test(c); |
|||
// partition :: (a -> Bool) -> [a] -> ([a], [a]) |
|||
const partition = p => |
|||
// A tuple of two lists - those elements in |
|||
// xs which match p, and those which do not. |
|||
xs => xs.reduce( |
|||
(a, x) => p(x) ? ( |
|||
Tuple(a[0].concat(x))(a[1]) |
|||
) : Tuple(a[0])(a[1].concat(x)), |
|||
Tuple([])([]) |
|||
); |
|||
// sort :: Ord a => [a] -> [a] |
|||
const sort = xs => |
|||
// An A-Z sorted copy of xs. |
|||
xs.slice() |
|||
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); |
|||
// MAIN --- |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre>Distinct vowels: (aeiou, 5) |
|||
Distict consonants: (Fglmnprtv, 9)</pre> |
|||
===Counts of vowel and consonant occurrences ?=== |
|||
<lang javascript>(() => { |
|||
"use strict"; |
|||
// ---- COUNTS OF VOWEL AND CONSONANT OCCURRENCES ---- |
|||
// vowelConsonantOccurrenceTotals :: String -> (Int, Int) |
|||
const vowelConsonantOccurrenceTotals = s => |
|||
Array.from(s).reduce( |
|||
(ab, c) => ( |
|||
isAlpha(c) ? ( |
|||
isVowel(c) ? ( |
|||
first(succ) |
|||
) : second(succ) |
|||
) : identity |
|||
)(ab), |
|||
Tuple(0)(0) |
|||
); |
|||
// ---------------------- TEST ----------------------- |
|||
const main = () => { |
|||
const vc = |
|||
vowelConsonantOccurrenceTotals( |
|||
"Forever Fortran 2018 programming language" |
|||
); |
|||
return [ |
|||
`Vowel occurrences: ${vc[0]}`, |
|||
`Consonent occurrences: ${vc[1]}` |
|||
].join("\n\n"); |
|||
}; |
|||
// --------------------- GENERIC --------------------- |
|||
// Tuple (,) :: a -> b -> (a, b) |
|||
const Tuple = a => |
|||
b => ({ |
|||
type: "Tuple", |
|||
"0": a, |
|||
"1": b, |
|||
length: 2 |
|||
}); |
|||
// first :: (a -> b) -> ((a, c) -> (b, c)) |
|||
const first = f => |
|||
// A simple function lifted to one which applies |
|||
// to a tuple, transforming only its first item. |
|||
xy => { |
|||
const tpl = Tuple(f(xy[0]))(xy[1]); |
|||
return Array.isArray(xy) ? ( |
|||
Array.from(tpl) |
|||
) : tpl; |
|||
}; |
|||
// identity :: a -> a |
|||
const identity = x => |
|||
// The identity function. |
|||
x; |
|||
// isAlpha :: Char -> Bool |
|||
const isAlpha = c => |
|||
(/[A-Za-z\u00C0-\u00FF]/u).test(c); |
|||
// isVowel :: Char -> Bool |
|||
const isVowel = c => |
|||
(/[AEIOUaeiou]/u).test(c); |
|||
// second :: (a -> b) -> ((c, a) -> (c, b)) |
|||
const second = f => |
|||
// A function over a simple value lifted |
|||
// to a function over a tuple. |
|||
// f (a, b) -> (a, f(b)) |
|||
xy => { |
|||
const tpl = Tuple(xy[0])(f(xy[1])); |
|||
return Array.isArray(xy) ? ( |
|||
Array.from(tpl) |
|||
) : tpl; |
|||
}; |
|||
// succ :: Int -> Int |
|||
const succ = x => |
|||
1 + x; |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre>Vowel occurrences: 12 |
|||
Consonent occurrences: 21</pre> |
|||
===Counts of occurrence for each vowel and consonant ?=== |
|||
<lang javascript>(() => { |
|||
"use strict"; |
|||
// COUNTS OF OCCURRENCE FOR EACH VOWEL AND CONSONANT |
|||
// countsOfEachVowelAndConsonant :: |
|||
// String -> ([(Char, Int)], [(Char, Int)]) |
|||
const countsOfEachVowelAndConsonant = s => |
|||
partition( |
|||
cn => isVowel(cn[0]) |
|||
)( |
|||
sort( |
|||
Object.entries( |
|||
charCounts( |
|||
Array.from(s).filter(isAlpha) |
|||
) |
|||
) |
|||
) |
|||
.map(([c, n]) => Tuple(c)(n)) |
|||
); |
|||
// ---------------------- TEST ----------------------- |
|||
const main = () => { |
|||
const report = label => |
|||
cns => { |
|||
const |
|||
total = cns.reduce( |
|||
(a, cn) => a + cn[1], |
|||
0 |
|||
), |
|||
rows = cns.map( |
|||
compose(s => `\t${s}`, showTuple) |
|||
).join("\n"); |
|||
return [ |
|||
`${label} counts:\n${rows}`, |
|||
`\ttotal: ${total}` |
|||
].join("\n\n"); |
|||
}; |
|||
const counts = countsOfEachVowelAndConsonant( |
|||
"Forever Fortran 2018 programming language" |
|||
); |
|||
return Array.from( |
|||
bimap( |
|||
report("Vowel") |
|||
)( |
|||
report("Consonant") |
|||
)( |
|||
counts |
|||
) |
|||
).join("\n\n"); |
|||
}; |
|||
// --------------------- GENERIC --------------------- |
|||
// Tuple (,) :: a -> b -> (a, b) |
|||
const Tuple = a => |
|||
b => ({ |
|||
type: "Tuple", |
|||
"0": a, |
|||
"1": b, |
|||
length: 2 |
|||
}); |
|||
// bimap :: (a -> b) -> (c -> d) -> (a, c) -> (b, d) |
|||
const bimap = f => |
|||
// Tuple instance of bimap. |
|||
// A tuple of the application of f and g to the |
|||
// first and second values respectively. |
|||
g => tpl => Tuple(f(tpl[0]))( |
|||
g(tpl[1]) |
|||
); |
|||
// charCounts :: String -> Dict |
|||
const charCounts = s => { |
|||
// A dictionary of characters seen, |
|||
// with their frequencies. |
|||
const go = (dct, c) => |
|||
Object.assign(dct, { |
|||
[c]: 1 + (dct[c] || 0) |
|||
}); |
|||
return Array.from(s).reduce(go, {}); |
|||
}; |
|||
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c |
|||
const compose = (...fs) => |
|||
// A function defined by the right-to-left |
|||
// composition of all the functions in fs. |
|||
fs.reduce( |
|||
(f, g) => x => f(g(x)), |
|||
x => x |
|||
); |
|||
// isAlpha :: Char -> Bool |
|||
const isAlpha = c => |
|||
(/[A-Za-z\u00C0-\u00FF]/u).test(c); |
|||
// isVowel :: Char -> Bool |
|||
const isVowel = c => |
|||
(/[AEIOUaeiou]/u).test(c); |
|||
// partition :: (a -> Bool) -> [a] -> ([a], [a]) |
|||
const partition = p => |
|||
// A tuple of two lists - those elements in |
|||
// xs which match p, and those which do not. |
|||
xs => xs.reduce( |
|||
(a, x) => p(x) ? ( |
|||
Tuple(a[0].concat(x))(a[1]) |
|||
) : Tuple(a[0])(a[1].concat(x)), |
|||
Tuple([])([]) |
|||
); |
|||
// sort :: Ord a => [a] -> [a] |
|||
const sort = xs => |
|||
// An A-Z sorted copy of xs. |
|||
xs.slice() |
|||
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); |
|||
// showTuple :: Tuple -> String |
|||
const showTuple = tpl => |
|||
`(${tpl[0]}, ${tpl[1]})`; |
|||
// MAIN --- |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre>Vowel counts: |
|||
(a, 4) |
|||
(e, 3) |
|||
(i, 1) |
|||
(o, 3) |
|||
(u, 1) |
|||
total: 12 |
|||
Consonant counts: |
|||
(F, 2) |
|||
(g, 4) |
|||
(l, 1) |
|||
(m, 2) |
|||
(n, 3) |
|||
(p, 1) |
|||
(r, 6) |
|||
(t, 1) |
|||
(v, 1) |
|||
total: 21</pre> |
|||
=={{header|jq}}== |
=={{header|jq}}== |