September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -4,7 +4,7 @@ A [[wp:semordnilap|semordnilap]] is a word (or phrase) that spells a different w
|
|||
Example: ''lager'' and ''regal''
|
||||
<br><br>
|
||||
;Task
|
||||
Using only words from <u>[http://www.puzzlers.org/pub/wordlists/unixdict.txt this list]</u>, report the total number of unique semordnilap pairs, and print 5 examples. (Note that lager/regal and regal/lager should be counted as one unique pair.)
|
||||
Using only words from <u>[http://wiki.puzzlers.org/pub/wordlists/unixdict.txt this list]</u>, report the total number of unique semordnilap pairs, and print 5 examples. (Note that lager/regal and regal/lager should be counted as one unique pair.)
|
||||
<br><br>
|
||||
;Related tasks
|
||||
* [[Palindrome_detection|Palindrome detection]]
|
||||
|
|
|
|||
1
Task/Semordnilap/00META.yaml
Normal file
1
Task/Semordnilap/00META.yaml
Normal file
|
|
@ -0,0 +1 @@
|
|||
--- {}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
integer p;
|
||||
integer p, z;
|
||||
record r;
|
||||
file f;
|
||||
text s, t;
|
||||
|
|
|
|||
21
Task/Semordnilap/Factor/semordnilap.factor
Normal file
21
Task/Semordnilap/Factor/semordnilap.factor
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
USING: assocs combinators.short-circuit formatting
|
||||
io.encodings.utf8 io.files kernel literals locals make
|
||||
prettyprint random sequences ;
|
||||
IN: rosetta-code.semordnilap
|
||||
|
||||
CONSTANT: words $[ "unixdict.txt" utf8 file-lines ]
|
||||
|
||||
: semordnilap? ( str1 str2 -- ? )
|
||||
{ [ = not ] [ nip words member? ] } 2&& ;
|
||||
|
||||
[
|
||||
[let
|
||||
V{ } clone :> seen words
|
||||
[
|
||||
dup reverse 2dup
|
||||
{ [ semordnilap? ] [ drop seen member? not ] } 2&&
|
||||
[ 2dup [ seen push ] bi@ ,, ] [ 2drop ] if
|
||||
] each
|
||||
]
|
||||
] H{ } make >alist
|
||||
[ length "%d semordnilap pairs.\n" printf ] [ 5 sample . ] bi
|
||||
|
|
@ -14,4 +14,4 @@ main = do
|
|||
s <- readFile "unixdict.txt"
|
||||
let l = semordnilaps (lines s)
|
||||
print $ length l
|
||||
mapM_ (print . ((,) <*> reverse)) $ take 5 l
|
||||
mapM_ (print . ((,) <*> reverse)) $ take 5 (filter ((4 <) . length) l)
|
||||
|
|
|
|||
60
Task/Semordnilap/JavaScript/semordnilap-3.js
Normal file
60
Task/Semordnilap/JavaScript/semordnilap-3.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// semordnilap :: [String] -> String
|
||||
const semordnilap = xs => {
|
||||
const go = ([s, ws], w) =>
|
||||
s.has(w.split('').reverse().join('')) ? (
|
||||
[s, [w].concat(ws)]
|
||||
) : [s.add(w), ws];
|
||||
return xs.reduce(go, [new Set(), []])[1];
|
||||
};
|
||||
|
||||
const main = () => {
|
||||
|
||||
// xs :: [String]
|
||||
const xs = semordnilap(
|
||||
lines(readFile('unixdict.txt'))
|
||||
);
|
||||
|
||||
console.log(xs.length);
|
||||
xs.filter(x => 4 < x.length).forEach(
|
||||
x => showLog(...[x, x.split('').reverse().join('')])
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
// GENERIC FUNCTIONS ----------------------------
|
||||
|
||||
// lines :: String -> [String]
|
||||
const lines = s => s.split(/[\r\n]/);
|
||||
|
||||
// readFile :: FilePath -> IO String
|
||||
const readFile = fp => {
|
||||
const
|
||||
e = $(),
|
||||
uw = ObjC.unwrap,
|
||||
s = uw(
|
||||
$.NSString.stringWithContentsOfFileEncodingError(
|
||||
$(fp)
|
||||
.stringByStandardizingPath,
|
||||
$.NSUTF8StringEncoding,
|
||||
e
|
||||
)
|
||||
);
|
||||
return undefined !== s ? (
|
||||
s
|
||||
) : uw(e.localizedDescription);
|
||||
};
|
||||
|
||||
// showLog :: a -> IO ()
|
||||
const showLog = (...args) =>
|
||||
console.log(
|
||||
args
|
||||
.map(JSON.stringify)
|
||||
.join(' -> ')
|
||||
);
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
112
Task/Semordnilap/Python/semordnilap-3.py
Normal file
112
Task/Semordnilap/Python/semordnilap-3.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
'''Dictionary words paired by equivalence under reversal'''
|
||||
|
||||
from functools import (reduce)
|
||||
from itertools import (chain)
|
||||
import urllib.request
|
||||
|
||||
|
||||
# semordnilaps :: [String] -> [String]
|
||||
def semordnilaps(xs):
|
||||
'''The subset of words in a list which
|
||||
are paired (by equivalence under reversal)
|
||||
with other words in that list.
|
||||
'''
|
||||
def go(tpl, w):
|
||||
(s, ws) = tpl
|
||||
if w[::-1] in s:
|
||||
return (s, ws + [w])
|
||||
else:
|
||||
s.add(w)
|
||||
return (s, ws)
|
||||
return reduce(go, xs, (set(), []))[1]
|
||||
|
||||
|
||||
# TEST ----------------------------------------------------
|
||||
def main():
|
||||
'''Test'''
|
||||
|
||||
url = 'http://wiki.puzzlers.org/pub/wordlists/unixdict.txt'
|
||||
ws = semordnilaps(
|
||||
urllib.request.urlopen(
|
||||
url
|
||||
).read().splitlines()
|
||||
)
|
||||
print(
|
||||
fTable(
|
||||
__doc__ + ':\n\n(longest of ' +
|
||||
str(len(ws)) + ' in ' + url + ')\n'
|
||||
)(snd)(fst)(identity)(
|
||||
sorted(
|
||||
concatMap(
|
||||
lambda x: (
|
||||
lambda s=x.decode('utf8'): [
|
||||
(s, s[::-1])
|
||||
] if 4 < len(x) else []
|
||||
)()
|
||||
)(ws),
|
||||
key=compose(len)(fst),
|
||||
reverse=True
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
|
||||
def compose(g):
|
||||
'''Right to left function composition.'''
|
||||
return lambda f: lambda x: g(f(x))
|
||||
|
||||
|
||||
# concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
def concatMap(f):
|
||||
'''A concatenated list over which a function has been mapped.
|
||||
The list monad can be derived by using a function f which
|
||||
wraps its output in a list,
|
||||
(using an empty list to represent computational failure).'''
|
||||
return lambda xs: list(
|
||||
chain.from_iterable(map(f, xs))
|
||||
)
|
||||
|
||||
|
||||
# FORMATTING ----------------------------------------------
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function -> fx display function ->
|
||||
f -> xs -> tabular string.
|
||||
'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
ys = [xShow(x) for x in xs]
|
||||
w = max(map(len, ys))
|
||||
return s + '\n' + '\n'.join(map(
|
||||
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
|
||||
xs, ys
|
||||
))
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# fst :: (a, b) -> a
|
||||
def fst(tpl):
|
||||
'''First member of a pair.'''
|
||||
return tpl[0]
|
||||
|
||||
|
||||
# identity :: a -> a
|
||||
def identity(x):
|
||||
'''The identity function.'''
|
||||
return x
|
||||
|
||||
|
||||
# snd :: (a, b) -> b
|
||||
def snd(tpl):
|
||||
'''Second member of a pair.'''
|
||||
return tpl[1]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
63
Task/Semordnilap/Python/semordnilap-4.py
Normal file
63
Task/Semordnilap/Python/semordnilap-4.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import sys
|
||||
import random
|
||||
import requests
|
||||
|
||||
URL = 'http://wiki.puzzlers.org/pub/wordlists/unixdict.txt'
|
||||
|
||||
|
||||
def find_semordnilaps():
|
||||
"""
|
||||
This generator could just take the `word_generator`
|
||||
as an argument and read words from it. That would
|
||||
have been both simpler and more efficient, but it
|
||||
is implemented this way for the sake of illustration.
|
||||
"""
|
||||
seen = set()
|
||||
word = None
|
||||
|
||||
while True:
|
||||
word = yield word
|
||||
|
||||
if word not in seen:
|
||||
seen.add(word[::-1])
|
||||
word = None
|
||||
|
||||
|
||||
def semordnilap_words(word_generator):
|
||||
|
||||
semordnilaps_finder = find_semordnilaps()
|
||||
semordnilaps_finder.send(None)
|
||||
|
||||
words = map(semordnilaps_finder.send, word_generator)
|
||||
|
||||
# need to get rid of `None` values for words which are not semordnilaps
|
||||
yield from filter(None, words)
|
||||
|
||||
|
||||
def url_lines(url):
|
||||
with requests.get(url, stream=True) as req:
|
||||
yield from req.iter_lines(decode_unicode=True)
|
||||
|
||||
|
||||
def main(url=URL, num_of_examples=5):
|
||||
|
||||
semordnilaps_generator = semordnilap_words(url_lines(url))
|
||||
|
||||
semordnilaps = list(semordnilaps_generator)
|
||||
|
||||
example_words = random.choices(semordnilaps, k=num_of_examples)
|
||||
example_pairs = ((word, word[::-1]) for word in example_words)
|
||||
|
||||
print(('found %(num)s semordnilap usernames:\n'
|
||||
'%(examples)s\n'
|
||||
'...'
|
||||
) % dict(
|
||||
num = len(semordnilaps),
|
||||
examples = '\n'.join(str(pair) for pair in example_pairs),
|
||||
))
|
||||
|
||||
return semordnilaps
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(*sys.argv[1:])
|
||||
Loading…
Add table
Add a link
Reference in a new issue