ABC words: Difference between revisions
Content added Content deleted
m (→{{header|Haskell}}: desugared do) |
(→{{header|Python}}: Added a functionally composed variant.) |
||
Line 823: | Line 823: | ||
' < unixdict.txt |
' < unixdict.txt |
||
</lang> |
</lang> |
||
Or a functionally composed variant, with a predicate which takes a single recursive pass through the characters of each word: |
|||
<lang python>'''ABC Words''' |
|||
# isABC :: String -> Bool |
|||
def isABC(s): |
|||
'''True if s contains 'a', 'b' and 'c', with the |
|||
first occurrences of each in that order. |
|||
''' |
|||
return None != bind( |
|||
bind( |
|||
residue('a')('bc')(s) |
|||
)( |
|||
residue('b')('c') |
|||
) |
|||
)( |
|||
residue('c')('') |
|||
) |
|||
# residue Char -> String -> String -> Maybe String |
|||
def residue(c): |
|||
'''Any characters remaining in s after c, unless |
|||
c is preceded by excluded characters. |
|||
''' |
|||
def excluding(cs): |
|||
def go(s): |
|||
if s: |
|||
x = s[0] |
|||
return None if x in cs else ( |
|||
s[1:] if c == x else go(s[1:]) |
|||
) |
|||
else: |
|||
return None |
|||
return go |
|||
return excluding |
|||
# ------------------------- TEST ------------------------- |
|||
# main :: IO () |
|||
def main(): |
|||
'''All words matching the isABC predicate |
|||
in a local copy of unixdict.txt |
|||
''' |
|||
for x in enumerate( |
|||
filter( |
|||
isABC, |
|||
readFile('unixdict.txt').splitlines() |
|||
), |
|||
start=1 |
|||
): |
|||
print(x) |
|||
# ----------------------- GENERIC ------------------------ |
|||
# bind (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b |
|||
def bind(m): |
|||
'''Composition of a sequence of (a -> None | b) functions. |
|||
If m is None, it is passed straight through. |
|||
If m is x, the result is an application |
|||
of the (a -> None | b) function (mf) to x. |
|||
''' |
|||
def go(mf): |
|||
return m if None is m else mf(m) |
|||
return go |
|||
# readFile :: FilePath -> IO String |
|||
def readFile(fp): |
|||
'''The contents of any file at the path |
|||
derived by expanding any ~ in fp. |
|||
''' |
|||
with open(fp, 'r', encoding='utf-8') as f: |
|||
return f.read() |
|||
# MAIN --- |
|||
if __name__ == '__main__': |
|||
main()</lang> |
|||
{{Out}} |
|||
<pre>(1, 'aback') |
|||
(2, 'abacus') |
|||
(3, 'abc') |
|||
(4, 'abdicate') |
|||
(5, 'abduct') |
|||
(6, 'abeyance') |
|||
(7, 'abject') |
|||
(8, 'abreact') |
|||
(9, 'abscess') |
|||
(10, 'abscissa') |
|||
(11, 'abscissae') |
|||
(12, 'absence') |
|||
(13, 'abstract') |
|||
(14, 'abstracter') |
|||
(15, 'abstractor') |
|||
(16, 'adiabatic') |
|||
(17, 'aerobacter') |
|||
(18, 'aerobic') |
|||
(19, 'albacore') |
|||
(20, 'alberich') |
|||
(21, 'albrecht') |
|||
(22, 'algebraic') |
|||
(23, 'alphabetic') |
|||
(24, 'ambiance') |
|||
(25, 'ambuscade') |
|||
(26, 'aminobenzoic') |
|||
(27, 'anaerobic') |
|||
(28, 'arabic') |
|||
(29, 'athabascan') |
|||
(30, 'auerbach') |
|||
(31, 'diabetic') |
|||
(32, 'diabolic') |
|||
(33, 'drawback') |
|||
(34, 'fabric') |
|||
(35, 'fabricate') |
|||
(36, 'flashback') |
|||
(37, 'halfback') |
|||
(38, 'iambic') |
|||
(39, 'lampblack') |
|||
(40, 'leatherback') |
|||
(41, 'metabolic') |
|||
(42, 'nabisco') |
|||
(43, 'paperback') |
|||
(44, 'parabolic') |
|||
(45, 'playback') |
|||
(46, 'prefabricate') |
|||
(47, 'quarterback') |
|||
(48, 'razorback') |
|||
(49, 'roadblock') |
|||
(50, 'sabbatical') |
|||
(51, 'snapback') |
|||
(52, 'strabismic') |
|||
(53, 'syllabic') |
|||
(54, 'tabernacle') |
|||
(55, 'tablecloth')</pre> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |