Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Teacup-rim-text/00-META.yaml
Normal file
2
Task/Teacup-rim-text/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Teacup_rim_text
|
||||
32
Task/Teacup-rim-text/00-TASK.txt
Normal file
32
Task/Teacup-rim-text/00-TASK.txt
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
On a set of coasters we have, there's a picture of a teacup. On the rim of the teacup the word '''TEA''' appears a number of times separated by bullet characters (•).
|
||||
|
||||
It occurred to me that if the bullet were removed and the words run together, you could start at any letter and still end up with a meaningful three-letter word.
|
||||
|
||||
So start at the '''T''' and read '''TEA'''. Start at the '''E''' and read '''EAT''', or start at the '''A''' and read '''ATE'''.
|
||||
|
||||
That got me thinking that maybe there are other words that could be used rather that '''TEA'''. And that's just English. What about Italian or Greek or ... um ... Telugu.
|
||||
|
||||
For English, we will use the unixdict (now) located at: [http://wiki.puzzlers.org/pub/wordlists/unixdict.txt unixdict.txt].
|
||||
|
||||
(This will maintain continuity with other Rosetta Code tasks that also use it.)
|
||||
|
||||
|
||||
;Task:
|
||||
Search for a set of words that could be printed around the edge of a teacup. The words in each set are to be of the same length, that length being greater than two (thus precluding '''AH''' and '''HA''', for example.)
|
||||
|
||||
Having listed a set, for example ['''ate tea eat'''], refrain from displaying permutations of that set, e.g.: ['''eat tea ate'''] etc.
|
||||
|
||||
The words should also be made of more than one letter (thus precluding '''III''' and '''OOO''' etc.)
|
||||
|
||||
The relationship between these words is (using ATE as an example) that the first letter of the first becomes the last letter of the second. The first letter of the second becomes the last letter of the third. So '''ATE''' becomes '''TEA''' and '''TEA''' becomes '''EAT'''.
|
||||
|
||||
All of the possible permutations, using this particular permutation technique, must be words in the list.
|
||||
|
||||
The set you generate for '''ATE''' will never included the word '''ETA''' as that cannot be reached via the first-to-last movement method.
|
||||
|
||||
Display one line for each set of teacup rim words.
|
||||
|
||||
|
||||
{{Template:Strings}}
|
||||
<br><br>
|
||||
|
||||
26
Task/Teacup-rim-text/11l/teacup-rim-text.11l
Normal file
26
Task/Teacup-rim-text/11l/teacup-rim-text.11l
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
F rotated(String s)
|
||||
R s[1..]‘’s[0]
|
||||
|
||||
V s = Set(File(‘unixdict.txt’).read().rtrim("\n").split("\n"))
|
||||
L !s.empty
|
||||
L(=word) s // `=` is needed here because otherwise after `s.remove(word)` `word` becomes invalid
|
||||
s.remove(word)
|
||||
I word.len < 3
|
||||
L.break
|
||||
|
||||
V w = word
|
||||
L 0 .< word.len - 1
|
||||
w = rotated(w)
|
||||
I w C s
|
||||
s.remove(w)
|
||||
E
|
||||
L.break
|
||||
L.was_no_break
|
||||
print(word, end' ‘’)
|
||||
w = word
|
||||
L 0 .< word.len - 1
|
||||
w = rotated(w)
|
||||
print(‘ -> ’w, end' ‘’)
|
||||
print()
|
||||
|
||||
L.break
|
||||
40
Task/Teacup-rim-text/AWK/teacup-rim-text.awk
Normal file
40
Task/Teacup-rim-text/AWK/teacup-rim-text.awk
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# syntax: GAWK -f TEACUP_RIM_TEXT.AWK UNIXDICT.TXT
|
||||
#
|
||||
# sorting:
|
||||
# PROCINFO["sorted_in"] is used by GAWK
|
||||
# SORTTYPE is used by Thompson Automation's TAWK
|
||||
#
|
||||
{ for (i=1; i<=NF; i++) {
|
||||
arr[tolower($i)] = 0
|
||||
}
|
||||
}
|
||||
END {
|
||||
PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
|
||||
for (i in arr) {
|
||||
leng = length(i)
|
||||
if (leng > 2) {
|
||||
delete tmp_arr
|
||||
words = str = i
|
||||
tmp_arr[i] = ""
|
||||
for (j=2; j<=leng; j++) {
|
||||
str = substr(str,2) substr(str,1,1)
|
||||
if (str in arr) {
|
||||
words = words " " str
|
||||
tmp_arr[str] = ""
|
||||
}
|
||||
}
|
||||
if (length(tmp_arr) == leng) {
|
||||
count = 0
|
||||
for (j in tmp_arr) {
|
||||
(arr[j] == 0) ? arr[j]++ : count++
|
||||
}
|
||||
if (count == 0) {
|
||||
printf("%s\n",words)
|
||||
circular++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%d words, %d circular\n",length(arr),circular)
|
||||
exit(0)
|
||||
}
|
||||
21
Task/Teacup-rim-text/Arturo/teacup-rim-text.arturo
Normal file
21
Task/Teacup-rim-text/Arturo/teacup-rim-text.arturo
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
wordset: map read.lines relative "unixdict.txt" => strip
|
||||
|
||||
rotateable?: function [w][
|
||||
loop 1..dec size w 'i [
|
||||
rotated: rotate w i
|
||||
if or? [rotated = w][not? contains? wordset rotated] ->
|
||||
return false
|
||||
]
|
||||
return true
|
||||
]
|
||||
|
||||
results: new []
|
||||
loop select wordset 'word [3 =< size word] 'word [
|
||||
if rotateable? word ->
|
||||
'results ++ @[ sort map 1..size word 'i [ rotate word i ]]
|
||||
]
|
||||
|
||||
loop sort unique results 'result [
|
||||
root: first result
|
||||
print join.with: " -> " map 1..size root 'i [ rotate.left root i]
|
||||
]
|
||||
29
Task/Teacup-rim-text/AutoHotkey/teacup-rim-text-1.ahk
Normal file
29
Task/Teacup-rim-text/AutoHotkey/teacup-rim-text-1.ahk
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Teacup_rim_text(wList){
|
||||
oWord := [], oRes := [], n := 0
|
||||
for i, w in StrSplit(wList, "`n", "`r")
|
||||
if StrLen(w) >= 3
|
||||
oWord[StrLen(w), w] := true
|
||||
|
||||
for l, obj in oWord
|
||||
{
|
||||
for w, bool in obj
|
||||
{
|
||||
loop % l
|
||||
if oWord[l, rotate(w)]
|
||||
{
|
||||
oWord[l, w] := 0
|
||||
if (A_Index = 1)
|
||||
n++, oRes[n] := w
|
||||
if (A_Index < l)
|
||||
oRes[n] := oRes[n] "," (w := rotate(w))
|
||||
}
|
||||
if (StrSplit(oRes[n], ",").Count() <> l)
|
||||
oRes.RemoveAt(n)
|
||||
}
|
||||
}
|
||||
return oRes
|
||||
}
|
||||
|
||||
rotate(w){
|
||||
return SubStr(w, 2) . SubStr(w, 1, 1)
|
||||
}
|
||||
6
Task/Teacup-rim-text/AutoHotkey/teacup-rim-text-2.ahk
Normal file
6
Task/Teacup-rim-text/AutoHotkey/teacup-rim-text-2.ahk
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
FileRead, wList, % A_Desktop "\unixdict.txt"
|
||||
result := ""
|
||||
for i, v in Teacup_rim_text(wList)
|
||||
result .= v "`n"
|
||||
MsgBox % result
|
||||
return
|
||||
18
Task/Teacup-rim-text/BaCon/teacup-rim-text.bacon
Normal file
18
Task/Teacup-rim-text/BaCon/teacup-rim-text.bacon
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
OPTION COLLAPSE TRUE
|
||||
|
||||
dict$ = LOAD$(DIRNAME$(ME$) & "/unixdict.txt")
|
||||
|
||||
FOR word$ IN dict$ STEP NL$
|
||||
IF LEN(word$) = 3 AND AMOUNT(UNIQ$(EXPLODE$(word$, 1))) = 3 THEN domain$ = APPEND$(domain$, 0, word$)
|
||||
NEXT
|
||||
|
||||
FOR w1$ IN domain$
|
||||
w2$ = RIGHT$(w1$, 2) & LEFT$(w1$, 1)
|
||||
w3$ = RIGHT$(w2$, 2) & LEFT$(w2$, 1)
|
||||
IF TALLY(domain$, w2$) AND TALLY(domain$, w3$) AND NOT(TALLY(result$, w1$)) THEN
|
||||
result$ = APPEND$(result$, 0, w1$ & " " & w2$ & " " & w3$, NL$)
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
PRINT result$
|
||||
PRINT "Total words: ", AMOUNT(dict$, NL$), ", and ", AMOUNT(result$, NL$), " are circular."
|
||||
58
Task/Teacup-rim-text/C++/teacup-rim-text.cpp
Normal file
58
Task/Teacup-rim-text/C++/teacup-rim-text.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// filename is expected to contain one lowercase word per line
|
||||
std::set<std::string> load_dictionary(const std::string& filename) {
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
throw std::runtime_error("Cannot open file " + filename);
|
||||
std::set<std::string> words;
|
||||
std::string word;
|
||||
while (getline(in, word))
|
||||
words.insert(word);
|
||||
return words;
|
||||
}
|
||||
|
||||
void find_teacup_words(const std::set<std::string>& words) {
|
||||
std::vector<std::string> teacup_words;
|
||||
std::set<std::string> found;
|
||||
for (auto w = words.begin(); w != words.end(); ++w) {
|
||||
std::string word = *w;
|
||||
size_t len = word.size();
|
||||
if (len < 3 || found.find(word) != found.end())
|
||||
continue;
|
||||
teacup_words.clear();
|
||||
teacup_words.push_back(word);
|
||||
for (size_t i = 0; i + 1 < len; ++i) {
|
||||
std::rotate(word.begin(), word.begin() + 1, word.end());
|
||||
if (word == *w || words.find(word) == words.end())
|
||||
break;
|
||||
teacup_words.push_back(word);
|
||||
}
|
||||
if (teacup_words.size() == len) {
|
||||
found.insert(teacup_words.begin(), teacup_words.end());
|
||||
std::cout << teacup_words[0];
|
||||
for (size_t i = 1; i < len; ++i)
|
||||
std::cout << ' ' << teacup_words[i];
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "usage: " << argv[0] << " dictionary\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
try {
|
||||
find_teacup_words(load_dictionary(argv[1]));
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << ex.what() << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
107
Task/Teacup-rim-text/C/teacup-rim-text.c
Normal file
107
Task/Teacup-rim-text/C/teacup-rim-text.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
int string_compare(gconstpointer p1, gconstpointer p2) {
|
||||
const char* const* s1 = p1;
|
||||
const char* const* s2 = p2;
|
||||
return strcmp(*s1, *s2);
|
||||
}
|
||||
|
||||
GPtrArray* load_dictionary(const char* file, GError** error_ptr) {
|
||||
GError* error = NULL;
|
||||
GIOChannel* channel = g_io_channel_new_file(file, "r", &error);
|
||||
if (channel == NULL) {
|
||||
g_propagate_error(error_ptr, error);
|
||||
return NULL;
|
||||
}
|
||||
GPtrArray* dict = g_ptr_array_new_full(1024, g_free);
|
||||
GString* line = g_string_sized_new(64);
|
||||
gsize term_pos;
|
||||
while (g_io_channel_read_line_string(channel, line, &term_pos,
|
||||
&error) == G_IO_STATUS_NORMAL) {
|
||||
char* word = g_strdup(line->str);
|
||||
word[term_pos] = '\0';
|
||||
g_ptr_array_add(dict, word);
|
||||
}
|
||||
g_string_free(line, TRUE);
|
||||
g_io_channel_unref(channel);
|
||||
if (error != NULL) {
|
||||
g_propagate_error(error_ptr, error);
|
||||
g_ptr_array_free(dict, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
g_ptr_array_sort(dict, string_compare);
|
||||
return dict;
|
||||
}
|
||||
|
||||
void rotate(char* str, size_t len) {
|
||||
char c = str[0];
|
||||
memmove(str, str + 1, len - 1);
|
||||
str[len - 1] = c;
|
||||
}
|
||||
|
||||
char* dictionary_search(const GPtrArray* dictionary, const char* word) {
|
||||
char** result = bsearch(&word, dictionary->pdata, dictionary->len,
|
||||
sizeof(char*), string_compare);
|
||||
return result != NULL ? *result : NULL;
|
||||
}
|
||||
|
||||
void find_teacup_words(GPtrArray* dictionary) {
|
||||
GHashTable* found = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
GPtrArray* teacup_words = g_ptr_array_new();
|
||||
GString* temp = g_string_sized_new(8);
|
||||
for (size_t i = 0, n = dictionary->len; i < n; ++i) {
|
||||
char* word = g_ptr_array_index(dictionary, i);
|
||||
size_t len = strlen(word);
|
||||
if (len < 3 || g_hash_table_contains(found, word))
|
||||
continue;
|
||||
g_ptr_array_set_size(teacup_words, 0);
|
||||
g_string_assign(temp, word);
|
||||
bool is_teacup_word = true;
|
||||
for (size_t i = 0; i < len - 1; ++i) {
|
||||
rotate(temp->str, len);
|
||||
char* w = dictionary_search(dictionary, temp->str);
|
||||
if (w == NULL) {
|
||||
is_teacup_word = false;
|
||||
break;
|
||||
}
|
||||
if (strcmp(word, w) != 0 && !g_ptr_array_find(teacup_words, w, NULL))
|
||||
g_ptr_array_add(teacup_words, w);
|
||||
}
|
||||
if (is_teacup_word && teacup_words->len > 0) {
|
||||
printf("%s", word);
|
||||
g_hash_table_add(found, word);
|
||||
for (size_t i = 0; i < teacup_words->len; ++i) {
|
||||
char* teacup_word = g_ptr_array_index(teacup_words, i);
|
||||
printf(" %s", teacup_word);
|
||||
g_hash_table_add(found, teacup_word);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
g_string_free(temp, TRUE);
|
||||
g_ptr_array_free(teacup_words, TRUE);
|
||||
g_hash_table_destroy(found);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s dictionary\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
GError* error = NULL;
|
||||
GPtrArray* dictionary = load_dictionary(argv[1], &error);
|
||||
if (dictionary == NULL) {
|
||||
if (error != NULL) {
|
||||
fprintf(stderr, "Cannot load dictionary file '%s': %s\n",
|
||||
argv[1], error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
find_teacup_words(dictionary);
|
||||
g_ptr_array_free(dictionary, TRUE);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
4
Task/Teacup-rim-text/F-Sharp/teacup-rim-text.fs
Normal file
4
Task/Teacup-rim-text/F-Sharp/teacup-rim-text.fs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Teacup rim text. Nigel Galloway: August 7th., 2019
|
||||
let N=System.IO.File.ReadAllLines("dict.txt")|>Array.filter(fun n->String.length n=3 && Seq.length(Seq.distinct n)>1)|>Set.ofArray
|
||||
let fG z=Set.map(fun n->System.String(Array.ofSeq (Seq.permute(fun g->(g+z)%3)n))) N
|
||||
Set.intersectMany [N;fG 1;fG 2]|>Seq.distinctBy(Seq.sort>>Array.ofSeq>>System.String)|>Seq.iter(printfn "%s")
|
||||
8
Task/Teacup-rim-text/Factor/teacup-rim-text.factor
Normal file
8
Task/Teacup-rim-text/Factor/teacup-rim-text.factor
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
USING: combinators.short-circuit fry grouping hash-sets
|
||||
http.client kernel math prettyprint sequences sequences.extras
|
||||
sets sorting splitting ;
|
||||
|
||||
"https://www.mit.edu/~ecprice/wordlist.10000" http-get nip
|
||||
"\n" split [ { [ length 3 < ] [ all-equal? ] } 1|| ] reject
|
||||
[ [ all-rotations ] map ] [ >hash-set ] bi
|
||||
'[ [ _ in? ] all? ] filter [ natural-sort ] map members .
|
||||
70
Task/Teacup-rim-text/Go/teacup-rim-text.go
Normal file
70
Task/Teacup-rim-text/Go/teacup-rim-text.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func readWords(fileName string) []string {
|
||||
file, err := os.Open(fileName)
|
||||
check(err)
|
||||
defer file.Close()
|
||||
var words []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
word := strings.ToLower(strings.TrimSpace(scanner.Text()))
|
||||
if len(word) >= 3 {
|
||||
words = append(words, word)
|
||||
}
|
||||
}
|
||||
check(scanner.Err())
|
||||
return words
|
||||
}
|
||||
|
||||
func rotate(runes []rune) {
|
||||
first := runes[0]
|
||||
copy(runes, runes[1:])
|
||||
runes[len(runes)-1] = first
|
||||
}
|
||||
|
||||
func main() {
|
||||
dicts := []string{"mit_10000.txt", "unixdict.txt"} // local copies
|
||||
for _, dict := range dicts {
|
||||
fmt.Printf("Using %s:\n\n", dict)
|
||||
words := readWords(dict)
|
||||
n := len(words)
|
||||
used := make(map[string]bool)
|
||||
outer:
|
||||
for _, word := range words {
|
||||
runes := []rune(word)
|
||||
variants := []string{word}
|
||||
for i := 0; i < len(runes)-1; i++ {
|
||||
rotate(runes)
|
||||
word2 := string(runes)
|
||||
if word == word2 || used[word2] {
|
||||
continue outer
|
||||
}
|
||||
ix := sort.SearchStrings(words, word2)
|
||||
if ix == n || words[ix] != word2 {
|
||||
continue outer
|
||||
}
|
||||
variants = append(variants, word2)
|
||||
}
|
||||
for _, variant := range variants {
|
||||
used[variant] = true
|
||||
}
|
||||
fmt.Println(variants)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
31
Task/Teacup-rim-text/Haskell/teacup-rim-text-1.hs
Normal file
31
Task/Teacup-rim-text/Haskell/teacup-rim-text-1.hs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import Data.List (groupBy, intercalate, sort, sortBy)
|
||||
import qualified Data.Set as S
|
||||
import Data.Ord (comparing)
|
||||
import Data.Function (on)
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
readFile "mitWords.txt" >>= (putStrLn . showGroups . circularWords . lines)
|
||||
|
||||
circularWords :: [String] -> [String]
|
||||
circularWords ws =
|
||||
let lexicon = S.fromList ws
|
||||
in filter (isCircular lexicon) ws
|
||||
|
||||
isCircular :: S.Set String -> String -> Bool
|
||||
isCircular lex w = 2 < length w && all (`S.member` lex) (rotations w)
|
||||
|
||||
rotations :: [a] -> [[a]]
|
||||
rotations = fmap <$> rotated <*> (enumFromTo 0 . pred . length)
|
||||
|
||||
rotated :: [a] -> Int -> [a]
|
||||
rotated [] _ = []
|
||||
rotated xs n = zipWith const (drop n (cycle xs)) xs
|
||||
|
||||
showGroups :: [String] -> String
|
||||
showGroups xs =
|
||||
unlines $
|
||||
intercalate " -> " . fmap snd <$>
|
||||
filter
|
||||
((1 <) . length)
|
||||
(groupBy (on (==) fst) (sortBy (comparing fst) (((,) =<< sort) <$> xs)))
|
||||
47
Task/Teacup-rim-text/Haskell/teacup-rim-text-2.hs
Normal file
47
Task/Teacup-rim-text/Haskell/teacup-rim-text-2.hs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import Data.Function (on)
|
||||
import Data.List (groupBy, intercalate, sort, sortOn)
|
||||
import Data.Ord (comparing)
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
readFile "mitWords.txt"
|
||||
>>= ( putStrLn
|
||||
. unlines
|
||||
. fmap (intercalate " -> ")
|
||||
. (circularOnly =<<)
|
||||
. anagrams
|
||||
. lines
|
||||
)
|
||||
|
||||
anagrams :: [String] -> [[String]]
|
||||
anagrams ws =
|
||||
let harvest group px
|
||||
| px = [fmap snd group]
|
||||
| otherwise = []
|
||||
in groupBy
|
||||
(on (==) fst)
|
||||
(sortOn fst (((,) =<< sort) <$> ws))
|
||||
>>= (harvest <*> ((> 2) . length))
|
||||
|
||||
circularOnly :: [String] -> [[String]]
|
||||
circularOnly ws
|
||||
| (length h - 1) > length rs = []
|
||||
| otherwise = [h : rs]
|
||||
where
|
||||
h = head ws
|
||||
rs = filter (isRotation h) (tail ws)
|
||||
|
||||
isRotation :: String -> String -> Bool
|
||||
isRotation xs ys =
|
||||
xs
|
||||
/= until
|
||||
( (||)
|
||||
. (ys ==)
|
||||
<*> (xs ==)
|
||||
)
|
||||
rotated
|
||||
(rotated xs)
|
||||
|
||||
rotated :: [a] -> [a]
|
||||
rotated [] = []
|
||||
rotated (x : xs) = xs <> [x]
|
||||
4
Task/Teacup-rim-text/J/teacup-rim-text.j
Normal file
4
Task/Teacup-rim-text/J/teacup-rim-text.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
>@{.@> (#~ (=&#>@{.)@> * 2 < #@>)(</.~ {.@/:~@(|."0 1~ i.@#)L:0)cutLF fread'unixdict.txt'
|
||||
apt
|
||||
arc
|
||||
ate
|
||||
60
Task/Teacup-rim-text/Java/teacup-rim-text.java
Normal file
60
Task/Teacup-rim-text/Java/teacup-rim-text.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Teacup {
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 1) {
|
||||
System.err.println("usage: java Teacup dictionary");
|
||||
System.exit(1);
|
||||
}
|
||||
try {
|
||||
findTeacupWords(loadDictionary(args[0]));
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// The file is expected to contain one lowercase word per line
|
||||
private static Set<String> loadDictionary(String fileName) throws IOException {
|
||||
Set<String> words = new TreeSet<>();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
|
||||
String word;
|
||||
while ((word = reader.readLine()) != null)
|
||||
words.add(word);
|
||||
return words;
|
||||
}
|
||||
}
|
||||
|
||||
private static void findTeacupWords(Set<String> words) {
|
||||
List<String> teacupWords = new ArrayList<>();
|
||||
Set<String> found = new HashSet<>();
|
||||
for (String word : words) {
|
||||
int len = word.length();
|
||||
if (len < 3 || found.contains(word))
|
||||
continue;
|
||||
teacupWords.clear();
|
||||
teacupWords.add(word);
|
||||
char[] chars = word.toCharArray();
|
||||
for (int i = 0; i < len - 1; ++i) {
|
||||
String rotated = new String(rotate(chars));
|
||||
if (rotated.equals(word) || !words.contains(rotated))
|
||||
break;
|
||||
teacupWords.add(rotated);
|
||||
}
|
||||
if (teacupWords.size() == len) {
|
||||
found.addAll(teacupWords);
|
||||
System.out.print(word);
|
||||
for (int i = 1; i < len; ++i)
|
||||
System.out.print(" " + teacupWords.get(i));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static char[] rotate(char[] ch) {
|
||||
char c = ch[0];
|
||||
System.arraycopy(ch, 1, ch, 0, ch.length - 1);
|
||||
ch[ch.length - 1] = c;
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
158
Task/Teacup-rim-text/JavaScript/teacup-rim-text-1.js
Normal file
158
Task/Teacup-rim-text/JavaScript/teacup-rim-text-1.js
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// main :: IO ()
|
||||
const main = () =>
|
||||
showGroups(
|
||||
circularWords(
|
||||
// Local copy of:
|
||||
// https://www.mit.edu/~ecprice/wordlist.10000
|
||||
lines(readFile('~/mitWords.txt'))
|
||||
)
|
||||
);
|
||||
|
||||
// circularWords :: [String] -> [String]
|
||||
const circularWords = ws =>
|
||||
ws.filter(isCircular(new Set(ws)), ws);
|
||||
|
||||
// isCircular :: Set String -> String -> Bool
|
||||
const isCircular = lexicon => w => {
|
||||
const iLast = w.length - 1;
|
||||
return 1 < iLast && until(
|
||||
([i, bln, s]) => iLast < i || !bln,
|
||||
([i, bln, s]) => [1 + i, lexicon.has(s), rotated(s)],
|
||||
[0, true, rotated(w)]
|
||||
)[1];
|
||||
};
|
||||
|
||||
// DISPLAY --------------------------------------------
|
||||
|
||||
// showGroups :: [String] -> String
|
||||
const showGroups = xs =>
|
||||
unlines(map(
|
||||
gp => map(snd, gp).join(' -> '),
|
||||
groupBy(
|
||||
(a, b) => fst(a) === fst(b),
|
||||
sortBy(
|
||||
comparing(fst),
|
||||
map(x => Tuple(concat(sort(chars(x))), x),
|
||||
xs
|
||||
)
|
||||
)
|
||||
).filter(gp => 1 < gp.length)
|
||||
));
|
||||
|
||||
|
||||
// MAC OS JS FOR AUTOMATION ---------------------------
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
// GENERIC FUNCTIONS ----------------------------------
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = (a, b) => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// chars :: String -> [Char]
|
||||
const chars = s => s.split('');
|
||||
|
||||
// comparing :: (a -> b) -> (a -> a -> Ordering)
|
||||
const comparing = f =>
|
||||
(x, y) => {
|
||||
const
|
||||
a = f(x),
|
||||
b = f(y);
|
||||
return a < b ? -1 : (a > b ? 1 : 0);
|
||||
};
|
||||
|
||||
// concat :: [[a]] -> [a]
|
||||
// concat :: [String] -> String
|
||||
const concat = xs =>
|
||||
0 < xs.length ? (() => {
|
||||
const unit = 'string' !== typeof xs[0] ? (
|
||||
[]
|
||||
) : '';
|
||||
return unit.concat.apply(unit, xs);
|
||||
})() : [];
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl[0];
|
||||
|
||||
// groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
|
||||
const groupBy = (f, xs) => {
|
||||
const tpl = xs.slice(1)
|
||||
.reduce((a, x) => {
|
||||
const h = a[1].length > 0 ? a[1][0] : undefined;
|
||||
return (undefined !== h) && f(h, x) ? (
|
||||
Tuple(a[0], a[1].concat([x]))
|
||||
) : Tuple(a[0].concat([a[1]]), [x]);
|
||||
}, Tuple([], 0 < xs.length ? [xs[0]] : []));
|
||||
return tpl[0].concat([tpl[1]]);
|
||||
};
|
||||
|
||||
// lines :: String -> [String]
|
||||
const lines = s => s.split(/[\r\n]/);
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = (f, xs) =>
|
||||
(Array.isArray(xs) ? (
|
||||
xs
|
||||
) : xs.split('')).map(f);
|
||||
|
||||
// rotated :: String -> String
|
||||
const rotated = xs =>
|
||||
xs.slice(1) + xs[0];
|
||||
|
||||
// showLog :: a -> IO ()
|
||||
const showLog = (...args) =>
|
||||
console.log(
|
||||
args
|
||||
.map(JSON.stringify)
|
||||
.join(' -> ')
|
||||
);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl[1];
|
||||
|
||||
// sort :: Ord a => [a] -> [a]
|
||||
const sort = xs => xs.slice()
|
||||
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0));
|
||||
|
||||
// sortBy :: (a -> a -> Ordering) -> [a] -> [a]
|
||||
const sortBy = (f, xs) =>
|
||||
xs.slice()
|
||||
.sort(f);
|
||||
|
||||
// unlines :: [String] -> String
|
||||
const unlines = xs => xs.join('\n');
|
||||
|
||||
// until :: (a -> Bool) -> (a -> a) -> a -> a
|
||||
const until = (p, f, x) => {
|
||||
let v = x;
|
||||
while (!p(v)) v = f(v);
|
||||
return v;
|
||||
};
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
140
Task/Teacup-rim-text/JavaScript/teacup-rim-text-2.js
Normal file
140
Task/Teacup-rim-text/JavaScript/teacup-rim-text-2.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// main :: IO ()
|
||||
const main = () =>
|
||||
anagrams(lines(readFile('~/mitWords.txt')))
|
||||
.flatMap(circularOnly)
|
||||
.map(xs => xs.join(' -> '))
|
||||
.join('\n')
|
||||
|
||||
// anagrams :: [String] -> [[String]]
|
||||
const anagrams = ws =>
|
||||
groupBy(
|
||||
on(eq, fst),
|
||||
sortBy(
|
||||
comparing(fst),
|
||||
ws.map(w => Tuple(sort(chars(w)).join(''), w))
|
||||
)
|
||||
).flatMap(
|
||||
gp => 2 < gp.length ? [
|
||||
gp.map(snd)
|
||||
] : []
|
||||
)
|
||||
|
||||
// circularOnly :: [String] -> [[String]]
|
||||
const circularOnly = ws => {
|
||||
const h = ws[0];
|
||||
return ws.length < h.length ? (
|
||||
[]
|
||||
) : (() => {
|
||||
const rs = rotations(h);
|
||||
return rs.every(r => ws.includes(r)) ? (
|
||||
[rs]
|
||||
) : [];
|
||||
})();
|
||||
};
|
||||
|
||||
// rotations :: String -> [String]
|
||||
const rotations = s =>
|
||||
takeIterate(s.length, rotated, s)
|
||||
|
||||
// rotated :: [a] -> [a]
|
||||
const rotated = xs => xs.slice(1).concat(xs[0]);
|
||||
|
||||
|
||||
// GENERIC FUNCTIONS ----------------------------
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = (a, b) => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// chars :: String -> [Char]
|
||||
const chars = s => s.split('');
|
||||
|
||||
// comparing :: (a -> b) -> (a -> a -> Ordering)
|
||||
const comparing = f =>
|
||||
(x, y) => {
|
||||
const
|
||||
a = f(x),
|
||||
b = f(y);
|
||||
return a < b ? -1 : (a > b ? 1 : 0);
|
||||
};
|
||||
|
||||
// eq (==) :: Eq a => a -> a -> Bool
|
||||
const eq = (a, b) => a === b
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl[0];
|
||||
|
||||
// groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
|
||||
const groupBy = (f, xs) => {
|
||||
const tpl = xs.slice(1)
|
||||
.reduce((a, x) => {
|
||||
const h = a[1].length > 0 ? a[1][0] : undefined;
|
||||
return (undefined !== h) && f(h, x) ? (
|
||||
Tuple(a[0], a[1].concat([x]))
|
||||
) : Tuple(a[0].concat([a[1]]), [x]);
|
||||
}, Tuple([], 0 < xs.length ? [xs[0]] : []));
|
||||
return tpl[0].concat([tpl[1]]);
|
||||
};
|
||||
|
||||
// lines :: String -> [String]
|
||||
const lines = s => s.split(/[\r\n]/);
|
||||
|
||||
// mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
|
||||
const mapAccumL = (f, acc, xs) =>
|
||||
xs.reduce((a, x, i) => {
|
||||
const pair = f(a[0], x, i);
|
||||
return Tuple(pair[0], a[1].concat(pair[1]));
|
||||
}, Tuple(acc, []));
|
||||
|
||||
// on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
|
||||
const on = (f, g) => (a, b) => f(g(a), g(b));
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl[1];
|
||||
|
||||
// sort :: Ord a => [a] -> [a]
|
||||
const sort = xs => xs.slice()
|
||||
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0));
|
||||
|
||||
// sortBy :: (a -> a -> Ordering) -> [a] -> [a]
|
||||
const sortBy = (f, xs) =>
|
||||
xs.slice()
|
||||
.sort(f);
|
||||
|
||||
// takeIterate :: Int -> (a -> a) -> a -> [a]
|
||||
const takeIterate = (n, f, x) =>
|
||||
snd(mapAccumL((a, _, i) => {
|
||||
const v = 0 !== i ? f(a) : x;
|
||||
return [v, v];
|
||||
}, x, Array.from({
|
||||
length: n
|
||||
})));
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
31
Task/Teacup-rim-text/Jq/teacup-rim-text.jq
Normal file
31
Task/Teacup-rim-text/Jq/teacup-rim-text.jq
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Output: an array of the words when read around the rim
|
||||
def read_teacup:
|
||||
. as $in
|
||||
| [range(0; length) | $in[.:] + $in[:.] ];
|
||||
|
||||
# Boolean
|
||||
def is_teacup_word($dict):
|
||||
. as $in
|
||||
| all( range(1; length); . as $i | $dict[ $in[$i:] + $in[:$i] ]) ;
|
||||
|
||||
# Output: a stream of the eligible teacup words
|
||||
def teacup_words:
|
||||
def same_letters:
|
||||
explode
|
||||
| .[0] as $first
|
||||
| all( .[1:][]; . == $first);
|
||||
|
||||
# Only consider one word in a teacup cycle
|
||||
def consider: explode | .[0] == min;
|
||||
|
||||
# Create the dictionary
|
||||
reduce (inputs
|
||||
| select(length>2 and (same_letters|not))) as $w ( {};
|
||||
.[$w]=true )
|
||||
| . as $dict
|
||||
| keys[]
|
||||
| select(consider and is_teacup_word($dict)) ;
|
||||
|
||||
# The task:
|
||||
teacup_words
|
||||
| read_teacup
|
||||
15
Task/Teacup-rim-text/Julia/teacup-rim-text.julia
Normal file
15
Task/Teacup-rim-text/Julia/teacup-rim-text.julia
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using HTTP
|
||||
|
||||
rotate(s, n) = String(circshift(Vector{UInt8}(s), n))
|
||||
|
||||
isliketea(w, d) = (n = length(w); n > 2 && any(c -> c != w[1], w) &&
|
||||
all(i -> haskey(d, rotate(w, i)), 1:n-1))
|
||||
|
||||
function getteawords(listuri)
|
||||
req = HTTP.request("GET", listuri)
|
||||
wdict = Dict{String, Int}((lowercase(string(x)), 1) for x in split(String(req.body), r"\s+"))
|
||||
sort(unique([sort([rotate(word, i) for i in 1:length(word)])
|
||||
for word in collect(keys(wdict)) if isliketea(word, wdict)]))
|
||||
end
|
||||
|
||||
foreach(println, getteawords("https://www.mit.edu/~ecprice/wordlist.10000"))
|
||||
28
Task/Teacup-rim-text/Lychen/teacup-rim-text.lychen
Normal file
28
Task/Teacup-rim-text/Lychen/teacup-rim-text.lychen
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const wc = new CS.System.Net.WebClient();
|
||||
const lines = wc.DownloadString("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt");
|
||||
const words = lines.split(/\n/g);
|
||||
const collection = {};
|
||||
words.filter(word => word.length > 2).forEach(word => {
|
||||
let allok = true;
|
||||
let newword = word;
|
||||
for (let i = 0; i < word.length - 1; i++) {
|
||||
newword = newword.substr(1) + newword.substr(0, 1);
|
||||
if (!words.includes(newword)) {
|
||||
allok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allok) {
|
||||
const key = word.split("").sort().join("");
|
||||
if (!collection[key]) {
|
||||
collection[key] = [word];
|
||||
} else {
|
||||
if (!collection[key].includes(word)) {
|
||||
collection[key].push(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(collection)
|
||||
.filter(key => collection[key].length > 1)
|
||||
.forEach(key => console.log("%s", collection[key].join(", ")));
|
||||
21
Task/Teacup-rim-text/Mathematica/teacup-rim-text.math
Normal file
21
Task/Teacup-rim-text/Mathematica/teacup-rim-text.math
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
ClearAll[Teacuppable]
|
||||
TeacuppableHelper[set_List] := Module[{f, s},
|
||||
f = First[set];
|
||||
s = StringRotateLeft[f, #] & /@ Range[Length[set]];
|
||||
Sort[s] == Sort[set]
|
||||
]
|
||||
Teacuppable[set_List] := Module[{ss, l},
|
||||
l = StringLength[First[set]];
|
||||
ss = Subsets[set, {l}];
|
||||
Select[ss, TeacuppableHelper]
|
||||
]
|
||||
s = Import["http://wiki.puzzlers.org/pub/wordlists/unixdict.txt", "String"];
|
||||
s //= StringSplit[#, "\n"] &;
|
||||
s //= Select[StringLength /* GreaterThan[2]];
|
||||
s //= Map[ToLowerCase];
|
||||
s //= Map[{#, Sort[Characters[#]]} &];
|
||||
s //= GatherBy[#, Last] &;
|
||||
s //= Select[Length /* GreaterEqualThan[2]];
|
||||
s = s[[All, All, 1]];
|
||||
s //= Select[StringLength[First[#]] <= Length[#] &];
|
||||
Flatten[Teacuppable /@ s, 1]
|
||||
30
Task/Teacup-rim-text/Nim/teacup-rim-text.nim
Normal file
30
Task/Teacup-rim-text/Nim/teacup-rim-text.nim
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import sequtils, sets, sugar
|
||||
|
||||
let words = collect(initHashSet, for word in "unixdict.txt".lines: {word})
|
||||
|
||||
proc rotate(s: var string) =
|
||||
let first = s[0]
|
||||
for i in 1..s.high: s[i - 1] = s[i]
|
||||
s[^1] = first
|
||||
|
||||
var result: seq[string]
|
||||
for word in "unixdict.txt".lines:
|
||||
if word.len >= 3:
|
||||
block checkWord:
|
||||
var w = word
|
||||
for _ in 1..w.len:
|
||||
w.rotate()
|
||||
if w notin words or w in result:
|
||||
# Not present in dictionary or already encountered.
|
||||
break checkWord
|
||||
if word.anyIt(it != word[0]):
|
||||
# More then one letter.
|
||||
result.add word
|
||||
|
||||
for word in result:
|
||||
var w = word
|
||||
stdout.write w
|
||||
for _ in 2..w.len:
|
||||
w.rotate()
|
||||
stdout.write " → ", w
|
||||
echo()
|
||||
35
Task/Teacup-rim-text/Perl/teacup-rim-text.pl
Normal file
35
Task/Teacup-rim-text/Perl/teacup-rim-text.pl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use List::Util qw(uniqstr any);
|
||||
|
||||
my(%words,@teacups,%seen);
|
||||
|
||||
open my $fh, '<', 'ref/wordlist.10000';
|
||||
while (<$fh>) {
|
||||
chomp(my $w = uc $_);
|
||||
next if length $w < 3;
|
||||
push @{$words{join '', sort split //, $w}}, $w;}
|
||||
|
||||
for my $these (values %words) {
|
||||
next if @$these < 3;
|
||||
MAYBE: for (@$these) {
|
||||
my $maybe = $_;
|
||||
next if $seen{$_};
|
||||
my @print;
|
||||
for my $i (0 .. length $maybe) {
|
||||
if (any { $maybe eq $_ } @$these) {
|
||||
push @print, $maybe;
|
||||
$maybe = substr($maybe,1) . substr($maybe,0,1)
|
||||
} else {
|
||||
@print = () and next MAYBE
|
||||
}
|
||||
}
|
||||
if (@print) {
|
||||
push @teacups, [@print];
|
||||
$seen{$_}++ for @print;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
say join ', ', uniqstr @$_ for sort @teacups;
|
||||
73
Task/Teacup-rim-text/Phix/teacup-rim-text.phix
Normal file
73
Task/Teacup-rim-text/Phix/teacup-rim-text.phix
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
-->
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">filter_set</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- anagrams is a (small) set of words that are all anagrams of each other
|
||||
-- for example: {"angel","angle","galen","glean","lange"}
|
||||
-- print any set(s) for which every rotation is also present (marking as
|
||||
-- you go to prevent the same set appearing with each word being first)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">used</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">used</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">used</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">anagrams</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">word</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]&</span><span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">used</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">res</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">teacup</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">minlen</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">allow_mono</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">letters</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- a sorted word, eg "ate" -> "aet".</span>
|
||||
<span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- in eg {{"aet","ate"},...} form</span>
|
||||
<span style="color: #000000;">anagrams</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- a set with same letters</span>
|
||||
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- (for building such sets)</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">word</span>
|
||||
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"using %s"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"r"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">&</span><span style="color: #008000;">" not found"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)))</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">minlen</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">letters</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">letters</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">", %d words read\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- group by anagram</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">letters</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">letters</span><span style="color: #0000FF;">=</span><span style="color: #000000;">last</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">anagrams</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">allow_mono</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">last</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">filter_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">letters</span>
|
||||
<span style="color: #000000;">anagrams</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">word</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">allow_mono</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">last</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">filter_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">anagrams</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000000;">teacup</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join_path</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"demo"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"unixdict.txt"</span><span style="color: #0000FF;">}))</span>
|
||||
<span style="color: #000080;font-style:italic;">-- These match output from other entries:
|
||||
--teacup(join_path({"demo","unixdict.txt"}),allow_mono:=true)
|
||||
--teacup(join_path({"demo","rosetta","mit.wordlist.10000.txt"}))
|
||||
--teacup(join_path({"demo","rosetta","words.txt"}),4,true)
|
||||
-- Note that allow_mono is needed to display eg {"agag","gaga"}</span>
|
||||
<!--
|
||||
31
Task/Teacup-rim-text/PicoLisp/teacup-rim-text.l
Normal file
31
Task/Teacup-rim-text/PicoLisp/teacup-rim-text.l
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
(de rotw (W)
|
||||
(let W (chop W)
|
||||
(unless (or (apply = W) (not (cddr W)))
|
||||
(make
|
||||
(do (length W)
|
||||
(link (pack (copy W)))
|
||||
(rot W) ) ) ) ) )
|
||||
(off D)
|
||||
(put 'D 'v (cons))
|
||||
(mapc
|
||||
'((W)
|
||||
(idx 'D (cons (hash W) W) T) )
|
||||
(setq Words
|
||||
(make (in "wordlist.10000" (while (line T) (link @)))) ) )
|
||||
(mapc
|
||||
println
|
||||
(extract
|
||||
'((W)
|
||||
(let? Lst (rotw W)
|
||||
(when
|
||||
(and
|
||||
(fully
|
||||
'((L) (idx 'D (cons (hash L) L)))
|
||||
Lst )
|
||||
(not
|
||||
(member (car Lst) (car (get 'D 'v))) ) )
|
||||
(mapc
|
||||
'((L) (push (get 'D 'v) L))
|
||||
Lst )
|
||||
Lst ) ) )
|
||||
Words ) )
|
||||
31
Task/Teacup-rim-text/PureBasic/teacup-rim-text.basic
Normal file
31
Task/Teacup-rim-text/PureBasic/teacup-rim-text.basic
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
DataSection
|
||||
dname:
|
||||
Data.s "./Data/unixdict.txt"
|
||||
Data.s "./Data/wordlist.10000.txt"
|
||||
Data.s ""
|
||||
EndDataSection
|
||||
|
||||
EnableExplicit
|
||||
Dim c.s{1}(2)
|
||||
Define.s txt, bset, res, dn
|
||||
Define.i i,q, cw
|
||||
Restore dname : Read.s dn
|
||||
While OpenConsole() And ReadFile(0,dn)
|
||||
While Not Eof(0)
|
||||
cw+1
|
||||
txt=ReadString(0)
|
||||
If Len(txt)=3 : bset+txt+";" : EndIf
|
||||
Wend
|
||||
CloseFile(0)
|
||||
For i=1 To CountString(bset,";")
|
||||
PokeS(c(),StringField(bset,i,";"))
|
||||
If FindString(res,c(0)+c(1)+c(2)) : Continue : EndIf
|
||||
If c(0)=c(1) Or c(1)=c(2) Or c(0)=c(2) : Continue : EndIf
|
||||
If FindString(bset,c(1)+c(2)+c(0)) And FindString(bset,c(2)+c(0)+c(1))
|
||||
res+c(0)+c(1)+c(2)+~"\t"+c(1)+c(2)+c(0)+~"\t"+c(2)+c(0)+c(1)+~"\n"
|
||||
EndIf
|
||||
Next
|
||||
PrintN(res+Str(cw)+" words, "+Str(CountString(res,~"\n"))+" circular") : Input()
|
||||
bset="" : res="" : cw=0
|
||||
Read.s dn
|
||||
Wend
|
||||
198
Task/Teacup-rim-text/Python/teacup-rim-text.py
Normal file
198
Task/Teacup-rim-text/Python/teacup-rim-text.py
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
'''Teacup rim text'''
|
||||
|
||||
from itertools import chain, groupby
|
||||
from os.path import expanduser
|
||||
from functools import reduce
|
||||
|
||||
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Circular anagram groups, of more than one word,
|
||||
and containing words of length > 2, found in:
|
||||
https://www.mit.edu/~ecprice/wordlist.10000
|
||||
'''
|
||||
print('\n'.join(
|
||||
concatMap(circularGroup)(
|
||||
anagrams(3)(
|
||||
# Reading from a local copy.
|
||||
lines(readFile('~/mitWords.txt'))
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
# anagrams :: Int -> [String] -> [[String]]
|
||||
def anagrams(n):
|
||||
'''Groups of anagrams, of minimum group size n,
|
||||
found in the given word list.
|
||||
'''
|
||||
def go(ws):
|
||||
def f(xs):
|
||||
return [
|
||||
[snd(x) for x in xs]
|
||||
] if n <= len(xs) >= len(xs[0][0]) else []
|
||||
return concatMap(f)(groupBy(fst)(sorted(
|
||||
[(''.join(sorted(w)), w) for w in ws],
|
||||
key=fst
|
||||
)))
|
||||
return go
|
||||
|
||||
|
||||
# circularGroup :: [String] -> [String]
|
||||
def circularGroup(ws):
|
||||
'''Either an empty list, or a list containing
|
||||
a string showing any circular subset found in ws.
|
||||
'''
|
||||
lex = set(ws)
|
||||
iLast = len(ws) - 1
|
||||
# If the set contains one word that is circular,
|
||||
# then it must contain all of them.
|
||||
(i, blnCircular) = until(
|
||||
lambda tpl: tpl[1] or (tpl[0] > iLast)
|
||||
)(
|
||||
lambda tpl: (1 + tpl[0], isCircular(lex)(ws[tpl[0]]))
|
||||
)(
|
||||
(0, False)
|
||||
)
|
||||
return [' -> '.join(allRotations(ws[i]))] if blnCircular else []
|
||||
|
||||
|
||||
# isCircular :: Set String -> String -> Bool
|
||||
def isCircular(lexicon):
|
||||
'''True if all of a word's rotations
|
||||
are found in the given lexicon.
|
||||
'''
|
||||
def go(w):
|
||||
def f(tpl):
|
||||
(i, _, x) = tpl
|
||||
return (1 + i, x in lexicon, rotated(x))
|
||||
|
||||
iLast = len(w) - 1
|
||||
return until(
|
||||
lambda tpl: iLast < tpl[0] or (not tpl[1])
|
||||
)(f)(
|
||||
(0, True, rotated(w))
|
||||
)[1]
|
||||
return go
|
||||
|
||||
|
||||
# allRotations :: String -> [String]
|
||||
def allRotations(w):
|
||||
'''All rotations of the string w.'''
|
||||
return takeIterate(len(w) - 1)(
|
||||
rotated
|
||||
)(w)
|
||||
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
# 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).
|
||||
'''
|
||||
def go(xs):
|
||||
return chain.from_iterable(map(f, xs))
|
||||
return go
|
||||
|
||||
|
||||
# fst :: (a, b) -> a
|
||||
def fst(tpl):
|
||||
'''First member of a pair.'''
|
||||
return tpl[0]
|
||||
|
||||
|
||||
# groupBy :: (a -> b) -> [a] -> [[a]]
|
||||
def groupBy(f):
|
||||
'''The elements of xs grouped,
|
||||
preserving order, by equality
|
||||
in terms of the key function f.
|
||||
'''
|
||||
def go(xs):
|
||||
return [
|
||||
list(x[1]) for x in groupby(xs, key=f)
|
||||
]
|
||||
return go
|
||||
|
||||
|
||||
# lines :: String -> [String]
|
||||
def lines(s):
|
||||
'''A list of strings,
|
||||
(containing no newline characters)
|
||||
derived from a single new-line delimited string.
|
||||
'''
|
||||
return s.splitlines()
|
||||
|
||||
|
||||
# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
|
||||
def mapAccumL(f):
|
||||
'''A tuple of an accumulation and a list derived by a
|
||||
combined map and fold,
|
||||
with accumulation from left to right.
|
||||
'''
|
||||
def go(a, x):
|
||||
tpl = f(a[0], x)
|
||||
return (tpl[0], a[1] + [tpl[1]])
|
||||
return lambda acc: lambda xs: (
|
||||
reduce(go, xs, (acc, []))
|
||||
)
|
||||
|
||||
|
||||
# readFile :: FilePath -> IO String
|
||||
def readFile(fp):
|
||||
'''The contents of any file at the path
|
||||
derived by expanding any ~ in fp.
|
||||
'''
|
||||
with open(expanduser(fp), 'r', encoding='utf-8') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
# rotated :: String -> String
|
||||
def rotated(s):
|
||||
'''A string rotated 1 character to the right.'''
|
||||
return s[1:] + s[0]
|
||||
|
||||
|
||||
# snd :: (a, b) -> b
|
||||
def snd(tpl):
|
||||
'''Second member of a pair.'''
|
||||
return tpl[1]
|
||||
|
||||
|
||||
# takeIterate :: Int -> (a -> a) -> a -> [a]
|
||||
def takeIterate(n):
|
||||
'''Each value of n iterations of f
|
||||
over a start value of x.
|
||||
'''
|
||||
def go(f):
|
||||
def g(x):
|
||||
def h(a, i):
|
||||
v = f(a) if i else x
|
||||
return (v, v)
|
||||
return mapAccumL(h)(x)(
|
||||
range(0, 1 + n)
|
||||
)[1]
|
||||
return g
|
||||
return go
|
||||
|
||||
|
||||
# until :: (a -> Bool) -> (a -> a) -> a -> a
|
||||
def until(p):
|
||||
'''The result of repeatedly applying f until p holds.
|
||||
The initial seed value is x.
|
||||
'''
|
||||
def go(f):
|
||||
def g(x):
|
||||
v = x
|
||||
while not p(v):
|
||||
v = f(v)
|
||||
return v
|
||||
return g
|
||||
return go
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
31
Task/Teacup-rim-text/REXX/teacup-rim-text.rexx
Normal file
31
Task/Teacup-rim-text/REXX/teacup-rim-text.rexx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*REXX pgm finds circular words (length>2), using a dictionary, suppress permutations.*/
|
||||
parse arg iFID L . /*obtain optional arguments from the CL*/
|
||||
if iFID==''|iFID=="," then iFID= 'wordlist.10k' /*Not specified? Then use the default.*/
|
||||
if L==''| L=="," then L= 3 /* " " " " " " */
|
||||
#= 0 /*number of words in dictionary, Len>L.*/
|
||||
@.= /*stemmed array of non─duplicated words*/
|
||||
do r=0 while lines(iFID) \== 0 /*read all lines (words) in dictionary.*/
|
||||
parse upper value linein(iFID) with z . /*obtain a word from the dictionary. */
|
||||
if length(z)<L | @.z\=='' then iterate /*length must be L or more, no dups.*/
|
||||
if \datatype(z, 'U') then iterate /*Word contains non-letters? Then skip*/
|
||||
@.z = z /*assign a word from the dictionary. */
|
||||
#= # + 1; $.#= z /*bump word count; append word to list.*/
|
||||
end /*r*/ /* [↑] dictionary need not be sorted. */
|
||||
cw= 0 /*the number of circular words (so far)*/
|
||||
say "There're " r ' entries in the dictionary (of all types): ' iFID
|
||||
say "There're " # ' words in the dictionary of at least length ' L
|
||||
say
|
||||
do j=1 for #; x= $.j; y= x /*obtain the Jth word in the list. */
|
||||
if x=='' then iterate /*if a null, don't show variants. */
|
||||
yy= y /*the start of a list of the variants. */
|
||||
do k=1 for length(x)-1 /*"circulate" the litters in the word. */
|
||||
y= substr(y, 2)left(y, 1) /*add the left letter to the right end.*/
|
||||
if @.y=='' then iterate j /*if not a word, then skip this word. */
|
||||
yy= yy',' y /*append to the list of the variants. */
|
||||
@.y= /*nullify word to suppress permutations*/
|
||||
end /*k*/
|
||||
cw= cw + 1 /*bump counter of circular words found.*/
|
||||
say 'circular word: ' yy /*display a circular word and variants.*/
|
||||
end /*j*/
|
||||
say
|
||||
say cw ' circular words were found.' /*stick a fork in it, we're all done. */
|
||||
33
Task/Teacup-rim-text/Raku/teacup-rim-text.raku
Normal file
33
Task/Teacup-rim-text/Raku/teacup-rim-text.raku
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
my %*SUB-MAIN-OPTS = :named-anywhere;
|
||||
|
||||
unit sub MAIN ( $dict = 'unixdict.txt', :$min-chars = 3, :$mono = False );
|
||||
|
||||
my %words;
|
||||
$dict.IO.slurp.words.map: { .chars < $min-chars ?? (next) !! %words{.uc.comb.sort.join}.push: .uc };
|
||||
|
||||
my @teacups;
|
||||
my %seen;
|
||||
|
||||
for %words.values -> @these {
|
||||
next if !$mono && @these < 2;
|
||||
MAYBE: for @these {
|
||||
my $maybe = $_;
|
||||
next if %seen{$_};
|
||||
my @print;
|
||||
for ^$maybe.chars {
|
||||
if $maybe ∈ @these {
|
||||
@print.push: $maybe;
|
||||
$maybe = $maybe.comb.list.rotate.join;
|
||||
} else {
|
||||
@print = ();
|
||||
next MAYBE
|
||||
}
|
||||
}
|
||||
if @print.elems {
|
||||
@teacups.push: @print;
|
||||
%seen{$_}++ for @print;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
say .unique.join(", ") for sort @teacups;
|
||||
15
Task/Teacup-rim-text/Ruby/teacup-rim-text.rb
Normal file
15
Task/Teacup-rim-text/Ruby/teacup-rim-text.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
lists = ["unixdict.txt", "wordlist.10000", "woordenlijst.txt"]
|
||||
|
||||
lists.each do |list|
|
||||
words = open(list).readlines( chomp: true).reject{|w| w.size < 3 }
|
||||
grouped_by_size = words.group_by(&:size)
|
||||
tea_words = words.filter_map do |word|
|
||||
chars = word.chars
|
||||
next unless chars.none?{|c| c < chars.first }
|
||||
next if chars.uniq.size == 1
|
||||
rotations = word.size.times.map {|i| chars.rotate(i).join }
|
||||
rotations if rotations.all?{|rot| grouped_by_size[rot.size].include? rot }
|
||||
end
|
||||
puts "", list + ":"
|
||||
tea_words.uniq(&:to_set).each{|ar| puts ar.join(", ") }
|
||||
end
|
||||
63
Task/Teacup-rim-text/Rust/teacup-rim-text.rust
Normal file
63
Task/Teacup-rim-text/Rust/teacup-rim-text.rust
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
fn load_dictionary(filename: &str) -> std::io::Result<BTreeSet<String>> {
|
||||
let file = File::open(filename)?;
|
||||
let mut dict = BTreeSet::new();
|
||||
for line in io::BufReader::new(file).lines() {
|
||||
let word = line?;
|
||||
dict.insert(word);
|
||||
}
|
||||
Ok(dict)
|
||||
}
|
||||
|
||||
fn find_teacup_words(dict: &BTreeSet<String>) {
|
||||
let mut teacup_words: Vec<&String> = Vec::new();
|
||||
let mut found: HashSet<&String> = HashSet::new();
|
||||
for word in dict {
|
||||
let len = word.len();
|
||||
if len < 3 || found.contains(word) {
|
||||
continue;
|
||||
}
|
||||
teacup_words.clear();
|
||||
let mut is_teacup_word = true;
|
||||
let mut chars: Vec<char> = word.chars().collect();
|
||||
for _ in 1..len {
|
||||
chars.rotate_left(1);
|
||||
if let Some(w) = dict.get(&String::from_iter(&chars)) {
|
||||
if !w.eq(word) && !teacup_words.contains(&w) {
|
||||
teacup_words.push(w);
|
||||
}
|
||||
} else {
|
||||
is_teacup_word = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !is_teacup_word || teacup_words.is_empty() {
|
||||
continue;
|
||||
}
|
||||
print!("{}", word);
|
||||
found.insert(word);
|
||||
for w in &teacup_words {
|
||||
found.insert(w);
|
||||
print!(" {}", w);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() != 2 {
|
||||
eprintln!("Usage: teacup dictionary");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let dict = load_dictionary(&args[1]);
|
||||
match dict {
|
||||
Ok(dict) => find_teacup_words(&dict),
|
||||
Err(error) => eprintln!("Cannot open file {}: {}", &args[1], error),
|
||||
}
|
||||
}
|
||||
56
Task/Teacup-rim-text/Swift/teacup-rim-text.swift
Normal file
56
Task/Teacup-rim-text/Swift/teacup-rim-text.swift
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import Foundation
|
||||
|
||||
func loadDictionary(_ path: String) throws -> Set<String> {
|
||||
let contents = try String(contentsOfFile: path, encoding: String.Encoding.ascii)
|
||||
return Set<String>(contents.components(separatedBy: "\n").filter{!$0.isEmpty})
|
||||
}
|
||||
|
||||
func rotate<T>(_ array: inout [T]) {
|
||||
guard array.count > 1 else {
|
||||
return
|
||||
}
|
||||
let first = array[0]
|
||||
array.replaceSubrange(0..<array.count-1, with: array[1...])
|
||||
array[array.count - 1] = first
|
||||
}
|
||||
|
||||
func findTeacupWords(_ dictionary: Set<String>) {
|
||||
var teacupWords: [String] = []
|
||||
var found = Set<String>()
|
||||
for word in dictionary {
|
||||
if word.count < 3 || found.contains(word) {
|
||||
continue
|
||||
}
|
||||
teacupWords.removeAll()
|
||||
var isTeacupWord = true
|
||||
var chars = Array(word)
|
||||
for _ in 1..<word.count {
|
||||
rotate(&chars)
|
||||
let w = String(chars)
|
||||
if (!dictionary.contains(w)) {
|
||||
isTeacupWord = false
|
||||
break
|
||||
}
|
||||
if w != word && !teacupWords.contains(w) {
|
||||
teacupWords.append(w)
|
||||
}
|
||||
}
|
||||
if !isTeacupWord || teacupWords.isEmpty {
|
||||
continue
|
||||
}
|
||||
print(word, terminator: "")
|
||||
found.insert(word)
|
||||
for w in teacupWords {
|
||||
found.insert(w)
|
||||
print(" \(w)", terminator: "")
|
||||
}
|
||||
print()
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
let dictionary = try loadDictionary("unixdict.txt")
|
||||
findTeacupWords(dictionary)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
39
Task/Teacup-rim-text/Wren/teacup-rim-text.wren
Normal file
39
Task/Teacup-rim-text/Wren/teacup-rim-text.wren
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import "io" for File
|
||||
import "/str" for Str
|
||||
import "/sort" for Find
|
||||
|
||||
var readWords = Fn.new { |fileName|
|
||||
var dict = File.read(fileName).split("\n")
|
||||
return dict.where { |w| w.count >= 3 }.toList
|
||||
}
|
||||
|
||||
var dicts = ["mit10000.txt", "unixdict.txt"]
|
||||
for (dict in dicts) {
|
||||
System.print("Using %(dict):\n")
|
||||
var words = readWords.call(dict)
|
||||
var n = words.count
|
||||
var used = {}
|
||||
for (word in words) {
|
||||
var outer = false
|
||||
var variants = [word]
|
||||
var word2 = word
|
||||
for (i in 0...word.count-1) {
|
||||
word2 = Str.lshift(word2)
|
||||
if (word == word2 || used[word2]) {
|
||||
outer = true
|
||||
break
|
||||
}
|
||||
var ix = Find.first(words, word2)
|
||||
if (ix == n || words[ix] != word2) {
|
||||
outer = true
|
||||
break
|
||||
}
|
||||
variants.add(word2)
|
||||
}
|
||||
if (!outer) {
|
||||
for (variant in variants) used[variant] = true
|
||||
System.print(variants)
|
||||
}
|
||||
}
|
||||
System.print()
|
||||
}
|
||||
18
Task/Teacup-rim-text/Zkl/teacup-rim-text-1.zkl
Normal file
18
Task/Teacup-rim-text/Zkl/teacup-rim-text-1.zkl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Limited to ASCII
|
||||
// This is limited to the max items a Dictionary can hold
|
||||
fcn teacut(wordFile){
|
||||
words:=File(wordFile).pump(Dictionary().add.fp1(True),"strip");
|
||||
seen :=Dictionary();
|
||||
foreach word in (words.keys){
|
||||
rots,w,sz := List(), word, word.len();
|
||||
if(sz>2 and word.unique().len()>2 and not seen.holds(word)){
|
||||
do(sz-1){
|
||||
w=String(w[-1],w[0,-1]); // rotate one character
|
||||
if(not words.holds(w)) continue(2); // not a word, skip these
|
||||
rots.append(w); // I'd like to see all the rotations
|
||||
}
|
||||
println(rots.append(word).sort().concat(" "));
|
||||
rots.pump(seen.add.fp1(True)); // we've seen these rotations
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Task/Teacup-rim-text/Zkl/teacup-rim-text-2.zkl
Normal file
2
Task/Teacup-rim-text/Zkl/teacup-rim-text-2.zkl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
println("\nunixdict:"); teacut("unixdict.txt");
|
||||
println("\nmit_wordlist_10000:"); teacut("mit_wordlist_10000.txt");
|
||||
Loading…
Add table
Add a link
Reference in a new issue