September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
132
Task/Anagrams/8th/anagrams.8th
Normal file
132
Task/Anagrams/8th/anagrams.8th
Normal 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
|
||||
;
|
||||
15
Task/Anagrams/Clojure/anagrams-2.clj
Normal file
15
Task/Anagrams/Clojure/anagrams-2.clj
Normal 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"])
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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.
|
||||
].
|
||||
|
|
|
|||
20
Task/Anagrams/Frink/anagrams.frink
Normal file
20
Task/Anagrams/Frink/anagrams.frink
Normal 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
|
||||
}
|
||||
12
Task/Anagrams/Go/anagrams-5.go
Normal file
12
Task/Anagrams/Go/anagrams-5.go
Normal 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)
|
||||
|
|
@ -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) ;
|
||||
|
|
@ -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)))
|
||||
|
||||
|
|
|
|||
25
Task/Anagrams/Kotlin/anagrams.kotlin
Normal file
25
Task/Anagrams/Kotlin/anagrams.kotlin
Normal 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) }
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
35
Task/Anagrams/OoRexx/anagrams-1.rexx
Normal file
35
Task/Anagrams/OoRexx/anagrams-1.rexx
Normal 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
|
||||
46
Task/Anagrams/OoRexx/anagrams-2.rexx
Normal file
46
Task/Anagrams/OoRexx/anagrams-2.rexx
Normal 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
|
||||
|
|
@ -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
|
||||
>>>
|
||||
|
|
@ -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")))
|
||||
|
|
@ -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"))
|
||||
|
|
@ -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
|
||||
30
Task/Anagrams/Rust/anagrams-1.rust
Normal file
30
Task/Anagrams/Rust/anagrams-1.rust
Normal 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!();
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Task/Anagrams/Rust/anagrams-2.rust
Normal file
42
Task/Anagrams/Rust/anagrams-2.rust
Normal 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())
|
||||
}
|
||||
|
|
@ -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(" "))
|
||||
}
|
||||
}
|
||||
41
Task/Anagrams/Scheme/anagrams.ss
Normal file
41
Task/Anagrams/Scheme/anagrams.ss
Normal 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)))))
|
||||
269
Task/Anagrams/Simula/anagrams.simula
Normal file
269
Task/Anagrams/Simula/anagrams.simula
Normal 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
|
||||
13
Task/Anagrams/Zkl/anagrams-1.zkl
Normal file
13
Task/Anagrams/Zkl/anagrams-1.zkl
Normal 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(","))
|
||||
});
|
||||
5
Task/Anagrams/Zkl/anagrams-2.zkl
Normal file
5
Task/Anagrams/Zkl/anagrams-2.zkl
Normal 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);
|
||||
Loading…
Add table
Add a link
Reference in a new issue