#include "BUCASCS320.hats"
#define :: list0_cons
#define cons list0_cons
#define nil list0_nil
typedef charlst = list0 char
extern fun string_perm_test (s1: string, s2: string): bool
implement string_perm_test (s1, s2) = let
fun cnt (cs: charlst, c: char, res: int): int =
case+ cs of
| c1 :: cs1 => let
val res = (if c = c1 then res + 1 else res): int
in
cnt (cs1, c, res)
end | nil () => res
fun test (cs: charlst, cs1: charlst, cs2: charlst): bool =
case+ cs of
| c :: cs => let
val n1 = cnt (cs1, c, 0) and n2 = cnt (cs2, c, 0)
in
if n1 = n2 then test (cs, cs1, cs2) else false
end
| nil () => true
in
if string_length s1 = string_length s2 then let
val cs1 = string_explode (s1) and cs2 = string_explode (s2)
in
test (cs1, cs1, cs2)
end else false
end
fun mylook
(inp: FILEref, prfx: string): void = let
val word = input_line (inp)
in
if stropt_is_some word then let
val word = stropt_unsome (word)
val word = string1_of_string word
val word = string_tolower word
val word = string1_of_strbuf (word)
val ans = string_perm_test (prfx, word)
val () = if ans then printf ("%s\n", @(word))
in
mylook (inp, prfx)
end else begin
end
end
#define WORDS_FILE "/usr/share/dict/words"
implement main (argc, argv) = let
val () = assert (argc >= 2)
val prfx = argv.[1]
val prfx = string1_of_string prfx
val prfx = string_tolower prfx
val prfx = string1_of_strbuf prfx
val inp = open_file_exn (WORDS_FILE, file_mode_r)
val () = mylook (inp, prfx)
val () = close_file_exn (inp)
in
end