September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -0,0 +1,132 @@
\
\ anagrams.8th
\ Rosetta Code - Anagrams problem
\ Using the word list at:
\ http://www.puzzlers.org/pub/wordlists/unixdict.txt,
\ find the sets of words that share the same characters
\ that contain the most words in them.
\
ns: anagrams
m:new var, anamap
a:new var, anaptr
0 var, analen
\ sort a string
: s:sort \ s -- s \
null s:/ \ a
' s:cmpi a:sort \ a
"" a:join \ s
;
: process-words \ word -- \ word
s:lc \ word
dup \ word word
>r \ word | word
\ 1. we create a sorted version of the curret word (sword)
s:sort \ sword | word
\ We check if sword can be found in map anamap
anamap @ \ sword anamap | word
over \ sword anamap sword | word
m:exists? \ sword anamap boolean | word
if \ sword anamap | word
\ If sword already exists in anamap:
\ - get mapvalue, which is an array
\ - add the original word to that array
\ - store the array in the map with key sword
over \ sword anamap sword | word
m:@ \ sword anamap array | word
r> \ sword anamap array word
a:push \ sword anamap array
rot \ anamap array sword
swap \ anamap sword array
m:! \ anamap
else \ sword anamap | word
\ If sword does not yet exist in anamap:
\ - create empty array
\ - put the original word into that array
\ - store the array in the map with key sword
swap \ anamap sword | word
a:new \ anamap sword array | word
r> \ anamap sword array word
a:push \ anamap sword array
m:! \ anamap
then
drop \
;
\ Read and check all words in array analist
: read-and-check-words \ -- \
"analist.txt" \ fname
f:open-ro \ f
' process-words f:eachline \ f
f:close \
;
: len< \ key array arraylen -- \ key array arraylen
2drop \ key
drop \
;
: len= \ key array arraylen -- \ key array arraylen
2drop \ key
anaptr @ \ key anaptr
swap \ anaptr key
a:push \ anaptr
drop \
;
: len> \ key array arraylen -- \ key array arraylen
analen \ key array arraylen analen
! \ key array
drop \ key
anaptr @ \ key anaptr
a:clear \ key anaptr
swap \ anaptr key
a:push \ anaptr
drop \
;
: fetch-longest-list \ key array -- \ key array
a:len \ key array arraylen
analen @ \ key array arraylen analen
2dup \ key array arraylen analen arraylen analen
n:cmp \ key array arraylen analen value
1 n:+ \ key array arraylen analen value
nip \ key array arraylen value
[ ' len< , ' len= , ' len> ] \ key array arraylen value swarr
swap \ key array arraylen swarr value
caseof \
;
: list-words-1 \ ix value -- \ ix value
nip \ value
"\t" . . \
;
: list-words \ ix value -- \ ix value
nip \ value
anamap @ \ value anamap
swap \ anamap value
m:@ \ anamap array
nip \ array
' list-words-1 a:each \ array
cr \ array
drop \
;
: app:main
\ Create a map, where the values are arrays, containing all words
\ which are the same when sorted (sword); sword is used as key
read-and-check-words
\ Create an array that holds the keys for anamap, for which the value,
\ which is the array of anagrams, has the biggest length found.
anamap @ ' fetch-longest-list m:each
\ Dump the resulting words to the console
anaptr @ ' list-words a:each drop
bye
;

View file

@ -0,0 +1,15 @@
(->> (slurp "http://www.puzzlers.org/pub/wordlists/unixdict.txt")
(apply str)
clojure.string/split-lines
(group-by sort)
vals
(sort-by count #(compare %2 %1)) ;; sort in reverse
(partition-by count)
first)
;; (["caret" "carte" "cater" "crate" "trace"]
;; ["angel" "angle" "galen" "glean" "lange"]
;; ["elan" "lane" "lean" "lena" "neal"]
;; ["alger" "glare" "lager" "large" "regal"]
;; ["evil" "levi" "live" "veil" "vile"]
;; ["abel" "able" "bale" "bela" "elba"])

View file

@ -1,9 +0,0 @@
import std.stdio, std.algorithm, std.range, std.string, std.exception;
void main() {
string[][const ubyte[]] an;
foreach (w; "unixdict.txt".File.byLine(KeepTerminator.no))
an[w.dup.representation.sort().release.assumeUnique] ~= w.idup;
immutable m = an.byValue.map!q{ a.length }.reduce!max;
writefln("%(%s\n%)", an.byValue.filter!(ws => ws.length == m));
}

View file

@ -1,13 +0,0 @@
import std.stdio, std.algorithm, std.file, std.string;
void main() {
char[] keys = cast(char[])"unixdict.txt".read;
immutable vals = keys.idup;
string[][string] anags;
foreach (w; keys.splitter) {
immutable k = cast(string)w.representation.sort().release;
anags[k] ~= vals[k.ptr-keys.ptr .. k.ptr-keys.ptr + k.length];
}
immutable m = anags.byValue.map!q{ a.length }.reduce!max;
writefln("%(%s\n%)", anags.byValue.filter!(ws => ws.length == m));
}

View file

@ -1,10 +0,0 @@
import std.stdio, std.stream, tools.functional, tools.base;
void main() {
( (new BufferedFile("/usr/share/dict/cracklib-small"))
/map/ ex!("s -> s.dup")
/groupby/ ex!("s -> s.dup.sort")
/map/ (string key, string[] value) { return value; }
/qsort/ ex!("a, b -> a.length < b.length")
)[$-1].writefln();
}

View file

@ -1,34 +1,37 @@
#import system.
#import system'routines.
#import system'io.
#import system'collections.
#import extensions.
#import extensions'routines.
import system'routines.
import system'calendar.
import system'io.
import system'collections.
import extensions.
import extensions'routines.
#class(extension) op
extension op
{
#method normalized
= self toArray ascendant summarize:(String new) literal.
normalized
= self toArray; ascendant; summarize(String new); literal.
}
#symbol program =
symbol program =
[
#var aDictionary := Dictionary new.
var aDictionary := Dictionary new.
"unixdict.txt" file_path run &eachLine: aWord
File new("unixdict.txt"); forEachLine(:aWord)
[
#var aKey := aWord normalized.
#var anItem := aDictionary@aKey.
($nil == anItem) ?
var s := aWord.
var aKey := aWord normalized.
var anItem := aDictionary[aKey].
if ($nil == anItem)
[
anItem := ArrayList new.
aDictionary@aKey := anItem.
aDictionary[aKey] := anItem.
].
anItem += aWord.
anItem append:aWord.
].
aDictionary array_list
sort: (:aFormer:aLater) [ aFormer length > aLater length ]
top:20 run &each: aPair [ console writeLine:aPair ].
aDictionary array_list;
sort(:aFormer:aLater)( aFormer length > aLater length );
top:20; forEach(:aPair)[ console printLine(aPair value) ].
console readChar.
].

View file

@ -0,0 +1,20 @@
d = new dict
for w = lines["http://www.puzzlers.org/pub/wordlists/unixdict.txt"]
{
sorted = sort[charList[w]]
curr = d@sorted
if curr
d@sorted.push[w]
else
d@sorted = [w]
}
most = sort[toArray[d], {|a,b| length[b@1] <=> length[a@1]}]
longest = length[most@0@1]
i = 0
while length[most@i@1] == longest
{
println[most@i@1]
i = i + 1
}

View file

@ -0,0 +1,12 @@
import Data.List (groupBy, maximumBy, sort)
import Data.Ord (comparing)
import Data.Function (on)
import Data.Text (pack)
main :: IO ()
main = do
f <- readFile "./unixdict.txt"
let ws = groupBy (on (==) fst) (sort (((,) =<< pack . sort) <$> lines f))
mapM_
(print . fmap snd)
(filter ((length (maximumBy (comparing length) ws) ==) . length) ws)

View file

@ -2,7 +2,7 @@ def anagrams:
(reduce .[] as $word (
{table: {}, max: 0}; # state
($word | explode | sort | implode) as $hash
| .table = ( .table + { ($hash): ( .table[$hash] + [ $word ]) })
| .table[$hash] += [ $word ]
| .max = ([ .max, ( .table[$hash] | length) ] | max ) ))
| .max as $max
| .table | .[] | select(length == $max) ;

View file

@ -1,6 +1,6 @@
url = "http://www.puzzlers.org/pub/wordlists/unixdict.txt"
wordlist = map!(chomp,(open(readlines, download(url))))
wordlist = open(readlines, download(url))
wsort(word) = join(sort(collect(word)))

View file

@ -0,0 +1,25 @@
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.URL
fun main(args: Array<String>) {
val url = URL("http://www.puzzlers.org/pub/wordlists/unixdict.txt")
val isr = InputStreamReader(url.openStream())
val reader = BufferedReader(isr)
val anagrams = mutableMapOf<String, MutableList<String>>()
var count = 0
var word = reader.readLine()
while (word != null) {
val chars = word.toCharArray()
chars.sort()
val key = chars.joinToString("")
if (!anagrams.containsKey(key)) anagrams.put(key, mutableListOf())
anagrams[key]!!.add(word)
count = Math.max(count, anagrams[key]!!.size)
word = reader.readLine()
}
reader.close()
anagrams.values
.filter { it.size == count }
.forEach { println(it) }
}

View file

@ -11,8 +11,8 @@ proc main() =
anagrams.mgetOrPut(key, newSeq[string]()).add(word)
count = max(count, anagrams[key].len)
for k, v in anagrams:
for _, v in anagrams:
if v.len == count:
v.join(", ").echo
v.join(" ").echo
main()

View file

@ -1,52 +0,0 @@
import tables
proc sort(s: string): string =
var
i,j: int
t: char
result = s
for i in 0 .. result.len - 1:
j = i
t = result[j]
while(j > 0) and (result[j - 1] > t):
result[j] = result[j - 1]
dec(j)
result[j] = t
# end sort
proc maxCount(an: TTable[string,seq[string]]): int =
result = 0
for v in an.values:
if v.len > result:
result = v.len
#end maxCount
proc showAnagrams(s: seq[string]) =
for v in s:
write(stdout,v)
write(stdout," ")
writeln(stdout,"")
#end showAnagrams
proc processFile: TTable[string,seq[string]] =
var
fd: TFile
sline,line: string
result = initTable[string,seq[string]]()
if Open(fd,"unixdict.txt"):
while not EndOfFile(fd):
line = fd.readLine()
sline = sort(line)
if result.hasKey(sline):
result[sline] = result[sline] & line
else:
result[sline] = @[line]
var
anagrams:TTable[string,seq[string]] = processFile()
max = anagrams.maxCount
for v in anagrams.values:
if v.len == max: showAnagrams(v)

View file

@ -0,0 +1,35 @@
-- This assumes you've already downloaded the following file and placed it
-- in the current directory: http://www.puzzlers.org/pub/wordlists/unixdict.txt
-- There are several different ways of reading the file. I chose the
-- supplier method just because I haven't used it yet in any other examples.
source = .stream~new('unixdict.txt')~supplier
-- this holds our mappings of the anagrams
anagrams = .directory~new
count = 0 -- this is used to keep track of the maximums
loop while source~available
word = source~item
-- this produces a string consisting of the characters in sorted order
-- Note: the ~~ used to invoke sort makes that message return value be
-- the target array. The sort method does not normally have a return value.
key = word~makearray('')~~sort~tostring("l", "")
-- make sure we have an accumulator collection for this key
list = anagrams[key]
if list == .nil then do
list = .array~new
anagrams[key] = list
end
-- this word is now associate with this key
list~append(word)
-- and see if this is a new highest count
count = max(count, list~items)
source~next
end
loop letters over anagrams
list = anagrams[letters]
if list~items >= count then
say letters":" list~makestring("l", ", ")
end

View file

@ -0,0 +1,46 @@
-- This assumes you've already downloaded the following file and placed it
-- in the current directory: http://www.puzzlers.org/pub/wordlists/unixdict.txt
-- There are several different ways of reading the file. I chose the
-- supplier method just because I haven't used it yet in any other examples.
source = .stream~new('unixdict.txt')~supplier
-- this holds our mappings of the anagrams. This is good use for the
-- relation class
anagrams = .relation~new
count = 0 -- this is used to keep track of the maximums
loop while source~available
word = source~item
-- this produces a string consisting of the characters in sorted order
-- Note: the ~~ used to invoke sort makes that message return value be
-- the target array. The sort method does not normally have a return value.
key = word~makearray('')~~sort~tostring("l", "")
-- add this to our mapping. This creates multiple entries for each
-- word that uses the same key
anagrams[key] = word
source~next
end
-- now get the set of unique keys
keys = .set~new~~putall(anagrams~allIndexes)
count = 0 -- this is used to keep track of the maximums
most = .directory~new
loop key over keys
words = anagrams~allAt(key)
newCount = words~items
if newCount > count then do
-- throw away our old set
most~empty
count = newCount
most[key] = words
end
-- matches our highest count, add it to the list
else if newCount == count then
most[key] = words
end
loop letters over most
words = most[letters]
say letters":" words~makestring("l", ", ")
end

View file

@ -1,22 +0,0 @@
>>> import urllib, itertools
>>> words = urllib.urlopen('http://www.puzzlers.org/pub/wordlists/unixdict.txt').read().split()
>>> len(words)
25104
>>> anagrams = [list(g) for k,g in itertools.groupby(sorted(words, key=sorted), key=sorted)]
>>> count = max(len(ana) for ana in anagrams)
>>> for ana in anagrams:
if len(ana) >= count:
print ana
['abel', 'able', 'bale', 'bela', 'elba']
['caret', 'carte', 'cater', 'crate', 'trace']
['angel', 'angle', 'galen', 'glean', 'lange']
['alger', 'glare', 'lager', 'large', 'regal']
['elan', 'lane', 'lean', 'lena', 'neal']
['evil', 'levi', 'live', 'veil', 'vile']
>>> count
5
>>>

View file

@ -1,21 +0,0 @@
#lang racket
(require net/url)
(define (get-lines url-string)
(define port (get-pure-port (string->url url-string)))
(for/list ([l (in-lines port)]) l))
(define (hash-words words)
(for/fold ([ws-hash (hash)]) ([w words])
(hash-update ws-hash
(list->string (sort (string->list w) < #:key (λ (c) (char->integer c))))
(λ (ws) (cons w ws))
(λ () '()))))
(define (get-maxes h)
(define max-ws (apply max (map length (hash-values h))))
(define max-keys (filter (λ (k) (= (length (hash-ref h k)) max-ws)) (hash-keys h)))
(map (λ (k) (hash-ref h k)) max-keys))
(get-maxes (hash-words (get-lines "http://www.puzzlers.org/pub/wordlists/unixdict.txt")))

View file

@ -1,6 +0,0 @@
'(("neal" "lena" "lean" "lane" "elan")
("trace" "crate" "cater" "carte" "caret")
("regal" "large" "lager" "glare" "alger")
("elba" "bela" "bale" "able" "abel")
("lange" "glean" "galen" "angle" "angel")
("vile" "veil" "live" "levi" "evil"))

View file

@ -1,34 +0,0 @@
on mouseUp
repeat for each word W in url "http://www.puzzlers.org/pub/wordlists/unixdict.txt"
put W & comma after A[sortChars(W)]
end repeat
put 0 into winningLength
repeat for each element E in A
get the number of items in E
if it < winningLength then next repeat
if it > winningLength then
put it into winningLength
put empty into winningList
end if
put (char 1 to -2 of E) & cr after winningList
end repeat
put winningList
end mouseUp
function sortChars X
get charsToItems(X)
sort items of it
return itemsToChars(it)
end sortChars
function charsToItems X
repeat for each char C in X
put C & comma after R
end repeat
return char 1 to -2 of R
end charsToItems
function itemsToChars X
replace comma with empty in X
return X
end itemsToChars

View file

@ -0,0 +1,30 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead,BufReader};
use std::borrow::ToOwned;
extern crate unicode_segmentation;
use unicode_segmentation::{UnicodeSegmentation};
fn main () {
let file = BufReader::new(File::open("unixdict.txt").unwrap());
let mut map = HashMap::new();
for line in file.lines() {
let s = line.unwrap();
//Bytes: let mut sorted = s.trim().bytes().collect::<Vec<_>>();
//Codepoints: let mut sorted = s.trim().chars().collect::<Vec<_>>();
let mut sorted = s.trim().graphemes(true).map(ToOwned::to_owned).collect::<Vec<_>>();
sorted.sort();
map.entry(sorted).or_insert_with(Vec::new).push(s);
}
if let Some(max_len) = map.values().map(|v| v.len()).max() {
for anagram in map.values().filter(|v| v.len() == max_len) {
for word in anagram {
print!("{} ", word);
}
println!();
}
}
}

View file

@ -0,0 +1,42 @@
use std::collections::HashMap;
use std::path::Path;
use std::io::{self, BufRead, BufReader};
use std::fs::File;
fn main() {
if let Ok(anagrams) = find_anagrams("unixdict.txt") {
for anagram in anagrams {
for word in anagram {
print!("{} ", word);
}
println!();
}
}
}
const PRIMES: [u64; 256] = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127
,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257
,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401
,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563
,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709
,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877
,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033
,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171
,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301
,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453
,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583
,1597,1601,1607,1609,1613,1619];
fn find_anagrams<P: AsRef<Path>>(file: P) -> io::Result<Vec<Vec<String>>> {
let file = BufReader::new(File::open(file)?);
let mut map = HashMap::new();
for line in file.lines() {
let string = line?;
let mut num = 1;
for ch in string.trim().bytes() {
num *= PRIMES[ch as usize];
}
map.entry(num).or_insert_with(Vec::new).push(string);
}
Ok(map.into_iter().map(|(_, entry)| entry).collect())
}

View file

@ -1,27 +0,0 @@
use std::collections::HashMap;
use std::collections::hash_map::Entry::*;
use std::fs::File;
use std::io::{BufRead,BufReader};
use std::cmp;
fn sort_string(string: &str) -> String {
let mut chars = string.chars().collect::<Vec<char>>();
chars.sort();
chars.into_iter().collect()
}
fn main () {
let file = BufReader::new(File::open("unixdict.txt").unwrap());
let mut map = HashMap::new();
for line in file.lines() {
let s: String = line.unwrap().trim().into();
match map.entry(sort_string(&s)) {
Vacant(entry) => { entry.insert(vec![s]); },
Occupied(mut entry) => { entry.get_mut().push(s); }
}
}
let max_length = map.values().fold(0, |s, v| cmp::max(s, v.len()));
for v in map.values().filter(|&v| v.len() == max_length) {
println!("{}", v.join(" "))
}
}

View file

@ -0,0 +1,41 @@
(import (scheme base)
(scheme char)
(scheme file)
(scheme write)
(srfi 125) ; hash tables
(srfi 132)) ; sorting library
;; read in the words
(define (read-groups)
(with-input-from-file
"unixdict.txt"
(lambda ()
(let ((groups (hash-table string=?)))
(do ((line (read-line) (read-line)))
((eof-object? line) groups)
(let* ((key (list->string (list-sort char<? (string->list line))))
(val (hash-table-ref/default groups key '())))
(hash-table-set! groups key (cons line val))))))))
;; extract the longest values from given hash-table of groups
(define (largest-groups groups)
(define (find-largest grps n sofar)
(cond ((null? grps)
sofar)
((> (length (car grps)) n)
(find-largest (cdr grps) (length (car grps)) (list (car grps))))
((= (length (car grps)) n)
(find-largest (cdr grps) n (cons (car grps) sofar)))
(else
(find-largest (cdr grps) n sofar))))
(find-largest (hash-table-values groups) 0 '()))
;; print results
(for-each
(lambda (group)
(display "[ ")
(for-each (lambda (word) (display word) (display " ")) group)
(display "]\n"))
(list-sort (lambda (a b) (string<? (car a) (car b)))
(map (lambda (grp) (list-sort string<? grp))
(largest-groups (read-groups)))))

View file

@ -0,0 +1,269 @@
COMMENT COMPILE WITH
$ cim -m64 anagrams-hashmap.sim
;
BEGIN
COMMENT ----- CLASSES FOR GENERAL USE ;
! ABSTRACT HASH KEY TYPE ;
CLASS HASHKEY;
VIRTUAL:
PROCEDURE HASH IS
INTEGER PROCEDURE HASH;;
PROCEDURE EQUALTO IS
BOOLEAN PROCEDURE EQUALTO(K); REF(HASHKEY) K;;
BEGIN
END HASHKEY;
! ABSTRACT HASH VALUE TYPE ;
CLASS HASHVAL;
BEGIN
! THERE IS NOTHING REQUIRED FOR THE VALUE TYPE ;
END HASHVAL;
CLASS HASHMAP;
BEGIN
CLASS INNERHASHMAP(N); INTEGER N;
BEGIN
INTEGER PROCEDURE INDEX(K); REF(HASHKEY) K;
BEGIN
INTEGER I;
IF K == NONE THEN
ERROR("HASHMAP.INDEX: NONE IS NOT A VALID KEY");
I := MOD(K.HASH,N);
LOOP:
IF KEYTABLE(I) == NONE OR ELSE KEYTABLE(I).EQUALTO(K) THEN
INDEX := I
ELSE BEGIN
I := IF I+1 = N THEN 0 ELSE I+1;
GO TO LOOP;
END;
END INDEX;
! PUT SOMETHING IN ;
PROCEDURE PUT(K,V); REF(HASHKEY) K; REF(HASHVAL) V;
BEGIN
INTEGER I;
IF V == NONE THEN
ERROR("HASHMAP.PUT: NONE IS NOT A VALID VALUE");
I := INDEX(K);
IF KEYTABLE(I) == NONE THEN BEGIN
IF SIZE = N THEN
ERROR("HASHMAP.PUT: TABLE FILLED COMPLETELY");
KEYTABLE(I) :- K;
VALTABLE(I) :- V;
SIZE := SIZE+1;
END ELSE
VALTABLE(I) :- V;
END PUT;
! GET SOMETHING OUT ;
REF(HASHVAL) PROCEDURE GET(K); REF(HASHKEY) K;
BEGIN
INTEGER I;
IF K == NONE THEN
ERROR("HASHMAP.GET: NONE IS NOT A VALID KEY");
I := INDEX(K);
IF KEYTABLE(I) == NONE THEN
GET :- NONE ! ERROR("HASHMAP.GET: KEY NOT FOUND");
ELSE
GET :- VALTABLE(I);
END GET;
PROCEDURE CLEAR;
BEGIN
INTEGER I;
FOR I := 0 STEP 1 UNTIL N-1 DO BEGIN
KEYTABLE(I) :- NONE;
VALTABLE(I) :- NONE;
END;
SIZE := 0;
END CLEAR;
! DATA MEMBERS OF CLASS HASHMAP ;
REF(HASHKEY) ARRAY KEYTABLE(0:N-1);
REF(HASHVAL) ARRAY VALTABLE(0:N-1);
INTEGER SIZE;
END INNERHASHMAP;
PROCEDURE PUT(K,V); REF(HASHKEY) K; REF(HASHVAL) V;
BEGIN
IF IMAP.SIZE >= 0.75 * IMAP.N THEN
BEGIN
COMMENT RESIZE HASHMAP ;
REF(INNERHASHMAP) NEWIMAP;
REF(ITERATOR) IT;
NEWIMAP :- NEW INNERHASHMAP(2 * IMAP.N);
IT :- NEW ITERATOR(THIS HASHMAP);
WHILE IT.MORE DO
BEGIN
REF(HASHKEY) KEY;
KEY :- IT.NEXT;
NEWIMAP.PUT(KEY, IMAP.GET(KEY));
END;
IMAP.CLEAR;
IMAP :- NEWIMAP;
END;
IMAP.PUT(K, V);
END;
REF(HASHVAL) PROCEDURE GET(K); REF(HASHKEY) K;
GET :- IMAP.GET(K);
PROCEDURE CLEAR;
IMAP.CLEAR;
INTEGER PROCEDURE SIZE;
SIZE := IMAP.SIZE;
REF(INNERHASHMAP) IMAP;
IMAP :- NEW INNERHASHMAP(16);
END HASHMAP;
CLASS ITERATOR(H); REF(HASHMAP) H;
BEGIN
INTEGER POS,KEYCOUNT;
BOOLEAN PROCEDURE MORE;
MORE := KEYCOUNT < H.SIZE;
REF(HASHKEY) PROCEDURE NEXT;
BEGIN
INSPECT H.IMAP DO
BEGIN
WHILE KEYTABLE(POS) == NONE DO
POS := POS+1;
NEXT :- KEYTABLE(POS);
KEYCOUNT := KEYCOUNT+1;
POS := POS+1;
END;
END NEXT;
END ITERATOR;
COMMENT ----- PROBLEM SPECIFIC CLASSES ;
HASHKEY CLASS TEXTHASHKEY(T); VALUE T; TEXT T;
BEGIN
INTEGER PROCEDURE HASH;
BEGIN
INTEGER I;
T.SETPOS(1);
WHILE T.MORE DO
I := 31*I+RANK(T.GETCHAR);
HASH := I;
END HASH;
BOOLEAN PROCEDURE EQUALTO(K); REF(HASHKEY) K;
EQUALTO := T = K QUA TEXTHASHKEY.T;
END TEXTHASHKEY;
HASHVAL CLASS TEXTVECTOR;
BEGIN
CLASS ARRAYHOLDER(N); INTEGER N;
BEGIN
TEXT ARRAY DATA(1:N);
END ARRAYHOLDER;
REF(ARRAYHOLDER) HOLDER;
INTEGER SIZE;
PROCEDURE DOUBLESIZE;
BEGIN
REF(ARRAYHOLDER) NEWHOLDER;
INTEGER I;
NEWHOLDER :- NEW ARRAYHOLDER(2 * HOLDER.N);
FOR I := 1 STEP 1 UNTIL HOLDER.N DO
NEWHOLDER.DATA(I) :- HOLDER.DATA(I);
HOLDER :- NEWHOLDER;
END;
PROCEDURE ADD(WORD); TEXT WORD;
BEGIN
SIZE := SIZE + 1;
IF SIZE > HOLDER.N THEN
DOUBLESIZE;
HOLDER.DATA(SIZE) :- WORD;
END;
HOLDER :- NEW ARRAYHOLDER(16);
END TEXTVECTOR;
TEXT PROCEDURE MAKEKEY(WORD); TEXT WORD;
BEGIN
TEXT KEY;
INTEGER I;
KEY :- BLANKS(WORD.LENGTH);
KEY.SETPOS(1);
FOR I := RANK('a') STEP 1 UNTIL RANK('z'),
RANK('0') STEP 1 UNTIL RANK('9') DO
BEGIN
WORD.SETPOS(1);
WHILE WORD.MORE DO
IF WORD.GETCHAR = CHAR(I) THEN
KEY.PUTCHAR(CHAR(I));
END;
MAKEKEY :- KEY;
END MAKEKEY;
REF(INFILE) INF;
REF(HASHMAP) MAP;
REF(HASHKEY) KEY;
REF(TEXTVECTOR) TVEC;
REF(ITERATOR) IT;
TEXT WORD;
INTEGER I, J, LONGEST;
MAP :- NEW HASHMAP;
INF :- NEW INFILE("unixdict.txt");
INF.OPEN(BLANKS(132));
WHILE NOT INF.LASTITEM DO
BEGIN
WORD :- COPY(INF.IMAGE).STRIP; INF.INIMAGE;
KEY :- NEW TEXTHASHKEY(MAKEKEY(WORD));
TVEC :- MAP.GET(KEY);
IF TVEC == NONE THEN
BEGIN
TVEC :- NEW TEXTVECTOR;
MAP.PUT(KEY, TVEC);
END;
TVEC.ADD(WORD);
END;
INF.CLOSE;
COMMENT FIND LONGEST ENTRIES ;
IT :- NEW ITERATOR(MAP);
WHILE IT.MORE DO
BEGIN
TVEC :- MAP.GET(IT.NEXT);
IF TVEC.SIZE > LONGEST THEN
LONGEST := TVEC.SIZE;
END;
COMMENT OUTPUT LONGEST ENTRIES ;
IT :- NEW ITERATOR(MAP);
WHILE IT.MORE DO
BEGIN
KEY :- IT.NEXT;
TVEC :- MAP.GET(KEY);
IF TVEC.SIZE = LONGEST THEN
BEGIN
OUTTEXT(KEY QUA TEXTHASHKEY.T);
OUTTEXT(":");
FOR J := 1 STEP 1 UNTIL TVEC.SIZE DO
INSPECT TVEC.HOLDER DO
BEGIN
OUTCHAR(' ');
OUTTEXT(DATA(J));
END;
OUTIMAGE;
END;
END;
END

View file

@ -0,0 +1,13 @@
File("unixdict.txt").read(*) // dictionary file to blob, copied from web
// blob to dictionary: key is word "fuzzed", values are anagram words
.pump(Void,T(fcn(w,d){
key:=w.split("").sort().concat(); // fuzz word to key
d.appendV(key,w); // add or append w
},d:=Dictionary(0d60_000)));
d.filter(fcn([(k,v)]){ v.len()>3 }) // prune to list of # words > 3
.sort(fcn([(_,v1)],[(_,v2)]){ v1.len()>v2.len() }) // sort by word count
[0,10].pump(Console.println,'wrap([(zz,v)]){ // and print 10 biggest
"%d:%s: %s".fmt(v.len(),zz.strip(),
v.apply("strip").concat(","))
});

View file

@ -0,0 +1,5 @@
URL:="http://www.puzzlers.org/pub/wordlists/unixdict.txt";
var ZC=Import("zklCurl");
unixdict:=ZC().get(URL); //--> T(Data,bytes of header, bytes of trailer)
unixdict=unixdict[0].del(0,unixdict[1]); // remove HTTP header
File("unixdict.txt","w").write(unixdict);