diff --git a/2 b/2 deleted file mode 100644 index b7b3e7c..0000000 --- a/2 +++ /dev/null @@ -1,110 +0,0 @@ -% @doc a word is an ordset of ltrs -% -% This mathematically is a cluster of letters; so in "A + B + AB", this is one -% of the summands. -% -% multiplication is implied in a word -% -% empty word is 1 -% -% anything times itself equals itself, so duplication is ignored -% -% multiplication = inclusive union -% -% operations assume all inputs are valid --module(wfc_word). - --export_type([ - word/0 -]). - --export([ - %% constructors - one/0, - validate/1, - from_list/1, to_list/1, - %% ops - mul/2, mul/1 -]). - --opaque word() :: {w, ordsets:ordset(wfc_ltr:ltr())}. - -%%---------------------------- -%% constructor -%%---------------------------- - --spec one() -> word(). - -one() -> - {w, []}. - - --spec validate(Word) -> Result - when Word :: word(), - Result :: ok - | {error, Reason :: string()}. -% @doc -% check each letter in the word for validity -% -% also check that word shape is valid -% @end - -validate(W = {w, Letters}) -> - case from_list(Letters) of - {ok, Result} when Result =:= W -> - ok; - Error -> - Error - end; -validate(X) -> - {error, wfc_utils:str("wfc_word:validate: malformed word: ~tp", [X])}. - - - --spec to_list(word()) -> Result - when Result :: {ok, [wfc_ltr:ltr()]} - | {error, string()}. - -to_list({w, Ltrs}) -> {ok, Ltrs}; -to_list(Bad) -> {error, wfc_utils:str("wfc_word:to_list: bad letter: ~tp", [Bad])}. - - - --spec from_list(Ltrs) -> Result - when Ltrs :: list(wfc_ltr:ltr()), - Result :: {ok, word()} - | {error, Reason :: string()}. - -from_list(Chars) -> - from_list(ordsets:from_list(Chars), []). - - -%% validate each letter -from_list([Ltr | Rest], Acc) -> - case wfc_ltr:validate(Ltr) of - ok -> from_list(Rest, [Ltr | Acc]); - Error -> Error - end; -% done, all good -from_list([], Acc) -> - {ok, {w, lists:reverse(Acc)}}. - - -%%---------------------------- -%% ops -%%---------------------------- - --spec mul(word(), word()) -> word(). -% @doc product of two words -% -% assumes the words are valid - -mul({w, X}, {w, Y}) -> - {w, ordsets:union(X, Y)}. - - --spec mul([word()]) -> word(). -% @doc multiply a list of words together - -mul([Word | Rest]) -> mul(Word, mul(Rest)); -mul([]) -> one(). diff --git a/src/wfc.erl b/src/wfc.erl index 8512811..31bcc00 100644 --- a/src/wfc.erl +++ b/src/wfc.erl @@ -7,16 +7,8 @@ ]). -export([ - - zero/0, one/0, - add/1, add/2, - mul/1, mul/2 ]). -type sentence() :: wfc_sentence:sentence(). - -%% constructors --spec -zero() diff --git a/src/wfc_sentence.erl b/src/wfc_sentence.erl index 06d019e..3587edd 100644 --- a/src/wfc_sentence.erl +++ b/src/wfc_sentence.erl @@ -26,7 +26,7 @@ %% constructors %%-------------------------- --spec zero() :: sentence(). +-spec zero() -> sentence(). zero() -> {s, []}. @@ -60,16 +60,34 @@ to_list({s, Words}) -> {ok, Words}; to_list(Bad) -> {error, wfc_utils:str("wfc_sentence:to_list: bad sentence: ~tp", [Bad])}. + +-spec validate(sentence()) -> ok | {error, string()}. + +validate({s, [W | Rest]}) -> + case wfc_word:validate(W) of + ok -> validate({s, Rest}); + Error -> Error + end; +validate({s, []}) -> + ok; +validate(Bad) -> + {error, wfc_utils:str("wfc_sentence:validate: bad sentence: ~tp", [Bad])}. + + %%--------------------------- %% prim ops %%--------------------------- -add({s, X}, {s, Y}) -> {s, disjoint_union(X, Y)}. +-spec add(sentence(), sentence()) -> sentence(). -disjoint_union(X, Y) -> +add({s, X}, {s, Y}) -> {s, symdiff(X, Y)}. + +symdiff(X, Y) -> ordsets:subtract(ordsets:union(X, Y), ordsets:intersection(X, Y)). +-spec add([sentence()]) -> sentence(). + add([S | Rest]) -> add(S, add(Rest)); add([]) -> zero(). diff --git a/src/wfc_word.erl b/src/wfc_word.erl index 04888ae..b7b3e7c 100644 --- a/src/wfc_word.erl +++ b/src/wfc_word.erl @@ -108,6 +108,3 @@ mul({w, X}, {w, Y}) -> mul([Word | Rest]) -> mul(Word, mul(Rest)); mul([]) -> one(). - - -add(