(* ::Package:: *)

(************************************************************************)
(* This file was generated automatically by the Mathematica front end.  *)
(* It contains Initialization cells from a Notebook file, which         *)
(* typically will have the same name as this file except ending in      *)
(* ".nb" instead of ".m".                                               *)
(*                                                                      *)
(* This file is intended to be loaded into the Mathematica kernel using *)
(* the package loading commands Get or Needs.  Doing so is equivalent   *)
(* to using the Evaluate Initialization Cells menu command in the front *)
(* end.                                                                 *)
(*                                                                      *)
(* DO NOT EDIT THIS FILE.  This entire file is regenerated              *)
(* automatically each time the parent Notebook file is saved in the     *)
(* Mathematica front end.  Any changes you make to this file will be    *)
(* overwritten.                                                         *)
(************************************************************************)



(* :Name: PwM`Chap09Strings` *)


(* :Book: Programming with Mathematica: An Introduction *)


(* :Author: Paul Wellin *)


(* :Summary: This package contains the functions defined in Chapter 9, Strings. *)


(* :Context: PwM`Chap09Strings` *)


(* :Package Version: 1.0 *)


(* :Copyright: Copyright 2012, Paul R. Wellin *)


(* :History: Version 1.0 by Paul Wellin, Dec 2012 *)
(* :Updated: April 2015 to be compatible with Version 10.1 *)


(* :Keywords: checksum, hash, anagram, blanagram, subsequence, gc ratio, palindrome, random strings, padding strings, DNA sequence table *)


(* :Source: Chap09Strings.nb *)


(* :Mathematica Version: 10.1.0 *)


Remove[FindSubsequence]


BeginPackage["PwM`Chap09Strings`"]


AdlerChecksum::usage="AdlerChecksum[expr] returns the integer hash code for the expression expr using the Adler checksum algorithm.";


Anagrams::usage="Anagrams[word] finds all anagrams of the string word in the dictionary.";


Blanagrams::usage="Blanagrams[word] returns all blanagrams of word in the built-in dictionary.";


BlockSize::usage="BlockSize is an option to SequenceTable that specifies the size of the strings in each block.";


FilterText::usage="FilterText[str, lis] removes all stops words given in the list lis from the string str.";


FindSubsequence::usage="FindSubsequence[num, subseq] returns the starting and ending positions of the subsequence subseq in the number num.";


FindWordsContaining::usage="FindWordsContaining[str] finds all words in the built-in dictionary that contain the string str. The option WordPosition\[Rule]pos can be used to specify the position of str. pos can be either \"Start\", \"Middle\", \"End\", or \"Anywhere\".";


GCRatio::usage="GCRatio[str, blocksize] computes the GC ratio in the string str for substrings of size blocksize.";


MakeVarList::usage="MakeVarList[sym, n] generates a list of n indexed symbols.\nMakeVarList[sym, {n,m}] generates a list of indexed symbols from \!\(\*SubscriptBox[\(sym\), \(n\)]\) to \!\(\*SubscriptBox[\(sym\), \(m\)]\).";


OrderedWordQ::usage="OrderedWordQ[word] returns True if the characters in word are ordered in the sense of their character codes.";


PalindromeQ::usage="Palindrome[expr] returns True of expr is palindromic. The expression expr can be either a string or a number.";


Palindromes::usage="Palindromes[[n] finds all palindromic words of length n in the built-in dictionary.";


RandomString::usage="RandomString[{\!\(\*SubscriptBox[\(c\), \(1\)]\),\!\(\*SubscriptBox[\(c\), \(2\)]\),\[Ellipsis],\!\(\*SubscriptBox[\(c\), \(n\)]\)}] generates a random string of length n from among the characters \!\(\*SubscriptBox[\(c\), \(i\)]\) chosen at random. The option Weights can be used to give weighted choices of the characters.\nRandomString[{list,{\!\(\*SubscriptBox[\(n\), \(1\)]\),\!\(\*SubscriptBox[\(n\), \(2\)]\),\[Ellipsis]}] generates an \!\(\*SubscriptBox[\(n\), \(1\)]\)\[Times]\!\(\*SubscriptBox[\(n\), \(2\)]\)\[Times]\[Ellipsis] array of random strings.";


RandomString::badwt="The length of the list of weights must be the same as the length of the list of characters.";


SequenceTable::usage="SequenceTable[lis] returns a formatted table suitable for displaying gene sequences. SequenceTable inherits options from Grid.";


StringPad::usage="StringPad[str,n] pads string str out to length n with whitespace.\nStringPad[str,{n}] appends n whitespace characters to the end of str.";


StringPad::badlen="Pad length `1` must be greater than the length of string `2`.";


stringPartition::usage="stringPartition[[list,n] partitions list into non-overlapping sublists of strings of length n. stringPartition has the same argument structure as Partition.";


stringRotateLeft::usage="stringRotateLeft[str] rotates the string one character to the left.\nstringRotateLeft[str, n] rotates the string str n characters to the left.";


UcLc::usage="UcLc[str] converts the first character in the string str to uppercase.";


UniqueCharacters::usage="UniqueCharacters[str] returns a list of unique characters in the string str, deleting duplicates.";


WordPosition::usage="WordPosition is an option to FindWordsContaining that determines where the target string occurs. Possible values are \"Start\", \"Middle\", \"End\", or \"Anywhere\".";


Options[FindWordsContaining]={WordPosition->"Start"};


Options[RandomString]={Weights->{}};


Options[SequenceTable]=Join[{BlockSize->10},Options[Grid]];


Begin["`Private`"];


AdlerChecksum[str_String]:=Module[{codes,n,m},
codes=ToCharacterCode[str];
m=Mod[Accumulate[Join[{1},codes]],65521];
n=Mod[Accumulate[Rest[m]],65521];
Last[m]+Last[n] 65536
]


Anagrams[word_String]:=Module[{len=StringLength[word],words},
words=DictionaryLookup[RegularExpression["\\w{"<>ToString[len]<>"}"]];
Select[words,Sort[Characters[#]]==Sort[Characters[word]]&]
]


Blanagrams[word_String]:=Module[{blana},
blana=Table[
Map[StringReplacePart[word,ch,{#,#}]&,Range[StringLength[word]]],
{ch,CharacterRange["a","z"]}];
DeleteDuplicates[Flatten[Map[Anagrams,blana,{2}]]]
]


FilterText[str_String,stopwords_List]:=Module[{tmp},
tmp=StringSplit[str,Characters[":,;.!? "]..];
Flatten@StringSplit[tmp,WordBoundary~~Apply[Alternatives,stopwords]~~WordBoundary,IgnoreCase->True]
]


FindSubsequence[num_?NumberQ,subseq_?NumberQ]:=Module[{n=ToString[num],s=ToString[subseq]},
StringPosition[Part[StringSplit[n,"."],2],s]
]


FindWordsContaining[str_String,OptionsPattern[]]:=Module[{wp=OptionValue[WordPosition]},
Which[
wp=="Start",DictionaryLookup[RegularExpression[StringJoin["\\b",str,".*\\b"]]],
wp=="Middle",DictionaryLookup[RegularExpression[StringJoin["\\b.+",str,".+\\b"]]],
wp=="End",DictionaryLookup[RegularExpression[StringJoin["\\b.*",str,"\\b"]]],
wp=="Anywhere",DictionaryLookup[RegularExpression[StringJoin["\\b.*",str,".*\\b"]]]
]]


gcRatio[ls_String]:=Module[{gc,at},
gc=StringCount[ls,"G"|"C"];
at=StringCount[ls,"A"|"T"];
N[gc/(gc+at)]
]


GCRatio[str_String,blocksize_Integer]:=Module[{lis,blocks},
lis=stringPartition[str,blocksize];
blocks=Table[i,{i,1,StringLength[str],blocksize}];
Transpose[{blocks,Map[gcRatio,lis]}]
]


GCRatio[{str_String},blocksize_Integer]:=GCRatio[str,blocksize]


MakeVarList[x_Symbol,n_Integer]:=ToExpression[Map[ToString[x]<>ToString[#]&,Range[n]]]


MakeVarList[x_Symbol,{n_Integer?Positive,m_Integer?Positive}]:=ToExpression[Map[ToString[x]<>ToString[#]&,Range[n,m]]]


OrderedWordQ[word_String]:=OrderedQ[ToCharacterCode[word]]


PalindromeQ[str_String]:=StringReverse[str]==str


PalindromeQ[num_Integer]:=PalindromeQ[ToString[num]]


Palindromes[len_Integer]:=DictionaryLookup[w__/;(w==StringReverse[w] && StringLength[w]==len)]


Palindromes[]:=DictionaryLookup[w__/;(w==StringReverse[w] )]


RandomString[{c__String},n_Integer:1,OptionsPattern[]]:=Module[{wts=OptionValue[Weights]},
Which[
Length[wts]==0,StringJoin[RandomChoice[{c},n]],
Length[wts]==Length[{c}],StringJoin[RandomChoice[wts->{c},n]],
True,Message[RandomString::badwt]
]]


RandomString[{c__String},{n_Integer,len_Integer},OptionsPattern[]]:=Module[{wts=OptionValue[Weights]},
Which[
Length[wts]==0,Map[StringJoin,RandomChoice[{c},{n,len}]],
Length[wts]==Length[{c}],Map[StringJoin,RandomChoice[wts->{c},{n,len}]],
True,Message[RandomString::badwt]
]]


SequenceTable[lis_String,opts:OptionsPattern[]]:=
Module[{n=OptionValue[BlockSize],len=StringLength[lis],rowlength=5,str,blocks,ind},
str=StringPartition[lis,n];
blocks=Partition[str,5,5,1," "];
ind=Select[Range[len],Mod[#,rowlength*n]==1&];
Grid[MapThread[Prepend[#1,#2]&,{blocks,ind}],
FilterRules[{opts}, Options[Grid]],Alignment->{{Right,{Left}},Automatic},Frame->True,Dividers->{{True,False},All}]
]


StringPad[str_String,{n_}]:=StringJoin[str,Table[" ",{n}]]


StringPad[str_String,n_]:=With[{len=StringLength[str]},If[len>n,Message[StringPad::badlen,n,str],StringPad[str,{n-len}]]]


StringPad[str_String,n_,m_]:=StringJoin[Table[" ",{n}],str,Table[" ",{m}]]


stringPartition[str_String,seq__]:=Map[StringJoin,Partition[Characters[str],seq]]


stringPartition[str_String,blocksize_]:=Map[StringJoin,Partition[Characters[str],blocksize,blocksize,1,{}]]


stringRotateLeft[str_,n_:1]:=StringJoin[RotateLeft[Characters[str],n]]


UcLc[word_String]:=StringReplace[word,RegularExpression["(.)([a-z]+)"]:>ToUpperCase["$1"]~~"$2"]


UniqueCharacters[str_String]:=DeleteDuplicates[Characters[str]]


End[];


EndPackage[]



