From b936dda857a15cfcd004959e9a88b4451323f1c6 Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Sun, 9 Feb 2025 22:17:18 -0600 Subject: [PATCH] more documentation/generic string functions --- .../Instructions/GenericInstructions.hs | 76 +++++++++++++---- src/HushGP/Instructions/StringInstructions.hs | 85 +++++++++++++------ 2 files changed, 119 insertions(+), 42 deletions(-) diff --git a/src/HushGP/Instructions/GenericInstructions.hs b/src/HushGP/Instructions/GenericInstructions.hs index fdca24a..a5173da 100644 --- a/src/HushGP/Instructions/GenericInstructions.hs +++ b/src/HushGP/Instructions/GenericInstructions.hs @@ -242,8 +242,8 @@ instructionConcat accessor state = -- |Based on two lenses, one of a primitive type and the next of a vector type, -- takes the top item of the primitive stack and prepends it to the first vector in -- the vector stack if there is one. -instructionConj :: Lens' State [a] -> Lens' State [[a]] -> State -> State -instructionConj primAccessor vectorAccessor state = +instructionVectorConj :: Lens' State [a] -> Lens' State [[a]] -> State -> State +instructionVectorConj primAccessor vectorAccessor state = case (uncons (view primAccessor state), uncons (view vectorAccessor state)) of (Just (p1,ps), Just (v1,vs)) -> state & primAccessor .~ ps & vectorAccessor .~ ((p1 : v1) : vs) _ -> state @@ -251,20 +251,27 @@ instructionConj primAccessor vectorAccessor state = -- |Based on two lenses, one of a primitive type and the next of a vector type, -- takes the top item of the primitive stack and appends it to the first vector in -- the vector stack if there is one. -instructionConjEnd :: Lens' State [a] -> Lens' State [[a]] -> State -> State -instructionConjEnd primAccessor vectorAccessor state = +instructionVectorConjEnd :: Lens' State [a] -> Lens' State [[a]] -> State -> State +instructionVectorConjEnd primAccessor vectorAccessor state = case (uncons (view primAccessor state), uncons (view vectorAccessor state)) of (Just (p1,ps), Just (v1,vs)) -> state & primAccessor .~ ps & vectorAccessor .~ ((v1 <> [p1]) : vs) _ -> state -- |Takes the first N items from the first vector on the top of a vector stack and -- pushes the result to said vector stack. -instructionTakeN :: Lens' State [[a]] -> State -> State -instructionTakeN accessor state@(State {_int = i1 : is}) = +instructionVectorTakeN :: Lens' State [[a]] -> State -> State +instructionVectorTakeN accessor state@(State {_int = i1 : is}) = case uncons (view accessor state) of Just (v1, vs) -> state{_int = is} & accessor .~ (take (absNum i1 v1) v1 : vs) _ -> state -instructionTakeN _ state = state +instructionVectorTakeN _ state = state + +instructionVectorTakeRN :: Lens' State [[a]] -> State -> State +instructionVectorTakeRN accessor state@(State {_int = i1 : is}) = + case uncons (view accessor state) of + Just (v1, vs) -> state{_int = is} & accessor .~ (takeR (absNum i1 v1) v1 : vs) + _ -> state +instructionVectorTakeRN _ state = state -- |Takes the sublist of the top vector based on a passed lens. Check out the -- subList documentation for information on how this works. @@ -341,21 +348,38 @@ instructionVectorFromNthPrim _ state = state -- |Takes the top vector, removes the first item of said vector, and pushes the result back to top -- of the stack, based on a lens. -instructionRest :: Lens' State [[a]] -> State -> State -instructionRest accessor state = +instructionVectorRest :: Lens' State [[a]] -> State -> State +instructionVectorRest accessor state = case uncons (view accessor state) of Just (v1, vs) -> state & accessor .~ (drop 1 v1 : vs) _ -> state -- |Takes the top vector, removes the last item of said vector, and pushes the result back to top --- of the stack, based on a lens. -instructionButLast :: Lens' State [[a]] -> State -> State -instructionButLast accessor state = +-- of the stack, based on a vector lens. +instructionVectorButLast :: Lens' State [[a]] -> State -> State +instructionVectorButLast accessor state = case uncons (view accessor state) of Just (v1, vs) -> state & accessor .~ (safeInit v1 : vs) _ -> state --- |Takes the top vector, pushes the length of that vector to the int stack, based on a lens. +-- |Based on a vector lens, drops the first N items from the top vector. +-- Pushes the result back to the vector stack. N is pulled from the top +-- of the int stack. +instructionVectorDrop :: Lens' State [[a]] -> State -> State +instructionVectorDrop accessor state@(State {_int = i1 : is}) = + case uncons (view accessor state{_int = is}) of + Just (v1, vs) -> state{_int = is} & accessor .~ (drop (absNum i1 v1) v1 : vs) + _ -> state +instructionVectorDrop _ state = state + +instructionVectorDropR :: Lens' State [[a]] -> State -> State +instructionVectorDropR accessor state@(State {_int = i1 : is}) = + case uncons (view accessor state{_int = is}) of + Just (v1, vs) -> state{_int = is} & accessor .~ (dropR (absNum i1 v1) v1 : vs) + _ -> state +instructionVectorDropR _ state = state + +-- |Takes the top vector, pushes the length of that vector to the int stack, based on a vector lens. instructionLength :: Lens' State [[a]] -> State -> State instructionLength accessor state@(State {_int = is}) = case uncons (view accessor state) of @@ -479,15 +503,23 @@ instructionVectorSplitOnVector accessor state = _ -> state -- |Based on two lenses, one of a primitive type and the next of a vector type, --- replaces all occurrences inside of the top vector from the vector stack with two values from +-- replaces Maybe Int occurrences inside of the top vector from the vector stack with two values from -- the primitive stack. The top of the primitive stack is the old value to be replaced. The second item --- in the primitive stack is the new value to replace the old one. +-- in the primitive stack is the new value to replace the old one. Nothing replaces all occurrences. instructionVectorReplace :: Eq a => Lens' State [a] -> Lens' State [[a]] -> Maybe Int -> State -> State instructionVectorReplace primAccessor vectorAccessor amt state = case (uncons (view vectorAccessor state), uncons (view primAccessor state)) of (Just (v1, vs), Just (p1, p2 : ps)) -> state & vectorAccessor .~ (replace v1 [p1] [p2] amt: vs) & primAccessor .~ ps _ -> state +-- |Based on two lenses, one of a primitive type and the next of a vector type, +-- replaces N occurrences inside of the top vector from the vector stack with two values from +-- the primitive stack. The top of the primitive stack is the old value to be replaced. The second item +-- in the primitive stack is the new value to replace the old one. N is pulled from the top of the int stack. +instructionVectorReplaceN :: Eq a => Lens' State [a] -> Lens' State [[a]] -> State -> State +instructionVectorReplaceN primAccessor vectorAccessor state@(State {_int = i1 : is}) = instructionVectorReplace primAccessor vectorAccessor (Just i1) state{_int = is} +instructionVectorReplaceN _ _ state = state + -- |Based on a vector lens and the top three vectors on said stack. -- Inside of the first vector, replaces the number of instances specified -- by the Maybe Int parameter of the second vector with the third vector. @@ -508,12 +540,20 @@ instructionVectorReplaceVectorN _ state = state -- |Based on two lenses, one of a primitive type and the next of a vector type, -- Removes all occurrences inside of the top vector from the vector stack where the top -- item from the primitive stack equals a primitive inside of the vector stack. -instructionVectorRemove :: Eq a => Lens' State [a] -> Lens' State [[a]] -> State -> State -instructionVectorRemove primAccessor vectorAccessor state = +instructionVectorRemove :: Eq a => Lens' State [a] -> Lens' State [[a]] -> Maybe Int -> State -> State +instructionVectorRemove primAccessor vectorAccessor amt state = case (uncons (view vectorAccessor state), uncons (view primAccessor state)) of - (Just (v1, vs), Just (p1, ps)) -> state & vectorAccessor .~ (replace v1 [p1] [] Nothing : vs) & primAccessor .~ ps + (Just (v1, vs), Just (p1, ps)) -> state & vectorAccessor .~ (replace v1 [p1] [] amt: vs) & primAccessor .~ ps _ -> state +-- |Based on two lenses, one of a primitive type and the next of a vector type, +-- Removes N occurrences inside of the top vector from the vector stack where the top +-- item from the primitive stack equals a primitive inside of the vector stack. N is pulled +-- from the top of the int stack. +instructionVectorRemoveN :: Eq a => Lens' State [a] -> Lens' State [[a]] -> State -> State +instructionVectorRemoveN primAccessor vectorAccessor state@(State {_int = i1 : is}) = instructionVectorRemove primAccessor vectorAccessor (Just i1) state{_int = is} +instructionVectorRemoveN _ _ state = state + -- |Based on a vector lens and the two vectors on top of said stack. -- Inside of the first vector, removes the number of instances specified -- by the Maybe Int parameter of the second vector. Nothing removes all instances. diff --git a/src/HushGP/Instructions/StringInstructions.hs b/src/HushGP/Instructions/StringInstructions.hs index 4a56b38..7abbc13 100644 --- a/src/HushGP/Instructions/StringInstructions.hs +++ b/src/HushGP/Instructions/StringInstructions.hs @@ -2,7 +2,6 @@ module HushGP.Instructions.StringInstructions where import HushGP.State import HushGP.Instructions.GenericInstructions -import Data.List.Split import Control.Lens -- |Utility String: Whitespack characters. @@ -139,74 +138,112 @@ instructionStringContainsChar = instructionVectorContains char string instructionStringIndexOfChar :: State -> State instructionStringIndexOfChar = instructionVectorIndexOf char string --- |@TODO +-- |Takes the top string from the string stack and the top +-- char from the char stack. Splits the top string based on +-- the top char and pushes the result to the string stack. instructionStringSplitOnChar :: State -> State instructionStringSplitOnChar = instructionVectorSplitOn char string +-- |Takes the top string from the string stack and the two top char from the char stack. +-- Replaces the first instance of the top char with the second char. instructionStringReplaceFirstChar :: State -> State instructionStringReplaceFirstChar = instructionVectorReplace char string (Just 1) +-- |Takes the top string from the string stack and the two top char from the char stack. +-- Replaces N instances of the top char with the second char. N is determined by the +-- top int on the int stack. instructionStringReplaceNChar :: State -> State -instructionStringReplaceNChar state@(State {_string = s1 : ss, _char = c1 : c2 : cs, _int = i1 : is}) = state{_string = replace s1 [c1] [c2] (Just i1) : ss, _char = cs, _int = is} -instructionStringReplaceNChar state = state +instructionStringReplaceNChar = instructionVectorReplaceN char string +-- |Takes the top string from the string stack and the two top char from the char stack. +-- Replaces all instances of the top char with the second char. instructionStringReplaceAllChar :: State -> State instructionStringReplaceAllChar = instructionVectorReplace char string Nothing +-- |Takes the top string from the string stack and the top char from the char stack. +-- Removes the first instance of the top char with the second char. instructionStringRemoveFirstChar :: State -> State -instructionStringRemoveFirstChar state@(State {_string = s1 : ss, _char = c1 : cs}) = state {_string = replace s1 [c1] "" (Just 1) : ss, _char = cs} -instructionStringRemoveFirstChar state = state +instructionStringRemoveFirstChar = instructionVectorRemove char string (Just 1) +-- |Takes the top string from the string stack and the top char from the char stack. +-- Removes N instances of the top char with the second char. N is pulled from the top +-- of the int stack. instructionStringRemoveNChar :: State -> State -instructionStringRemoveNChar state@(State {_string = s1 : ss, _char = c1 : cs, _int = i1 : is}) = state{_string = replace s1 [c1] "" (Just i1) : ss, _char = cs, _int = is} -instructionStringRemoveNChar state = state +instructionStringRemoveNChar = instructionVectorRemoveN char string +-- |Takes the top string from the string stack and the top char from the char stack. +-- Removes all instances of the top char with the second char. instructionStringRemoveAllChar :: State -> State -instructionStringRemoveAllChar = instructionVectorRemove char string +instructionStringRemoveAllChar = instructionVectorRemove char string Nothing +-- |Takes the top string from the string stack and the top char from the char stack. +-- Counts the amount of occurrences of the top char inside of the top string. Pushes +-- this result to the int stack. instructionStringOccurrencesOfChar :: State -> State instructionStringOccurrencesOfChar = instructionVectorOccurrencesOf char string +-- |Takes the top string from the string stack and reverses it. Pushes the reversed string +-- to the top of the stack. instructionStringReverse :: State -> State instructionStringReverse = instructionReverse string +-- |Takes the top string from the string stack, takes the first N chars from the top string, +-- and pushes the result to the string stack. N is pulled from the top of the int stack. instructionStringHead :: State -> State -instructionStringHead = instructionTakeN string +instructionStringHead = instructionVectorTakeN string +-- |Takes the top string from the string stack, takes the last N chars from the top string, +-- and pushes the result to the string stack. N is pulled from the top of the int stack. instructionStringTail :: State -> State -instructionStringTail state@(State {_string = s1 : ss, _int = i1 : is}) = state{_string = takeR (absNum i1 s1) s1 : ss, _int = is} -instructionStringTail state = state +instructionStringTail = instructionVectorTakeRN string +-- |Takes the top string from the string stack and the top char from the char stack. +-- Prepends the top char to the top string. Pushes the result to the string stack. +instructionStringPrependChar :: State -> State +instructionStringPrependChar = instructionVectorConj char string + +-- |Takes the top string from the string stack and the top char from the char stack. +-- Appends the top char to the top string. Pushes the result to the string stack. instructionStringAppendChar :: State -> State -instructionStringAppendChar = instructionConj char string - -instructionStringConjEndChar :: State -> State -instructionStringConjEndChar = instructionConjEnd char string +instructionStringAppendChar = instructionVectorConjEnd char string +-- |Takes the top string from the string stack and removes the first char +-- from said string. Pushes the result to the string stack. instructionStringRest :: State -> State -instructionStringRest = instructionRest string +instructionStringRest = instructionVectorRest string +-- |Takes the top string from the string stack and removes the last char +-- from said string. Pushes the result to the string stack. instructionStringButLast :: State -> State -instructionStringButLast = instructionButLast string +instructionStringButLast = instructionVectorButLast string +-- |Takes the top string from the string stack and drops the first N characters +-- from said string. Pushes the result to the string stack. N is pulled from the top +-- of the int stack. instructionStringDrop :: State -> State -instructionStringDrop state@(State {_string = s1 : ss, _int = i1 : is}) = state{_string = drop (absNum i1 s1) s1 : ss, _int = is} -instructionStringDrop state = state +instructionStringDrop = instructionVectorDrop string +-- |Takes the top string from the string stack and drops the last N characters +-- from said string. Pushes the result to the string stack. N is pulled from the top +-- of the int stack. instructionStringButLastN :: State -> State -instructionStringButLastN state@(State {_string = s1 : ss, _int = i1 : is}) = state{_string = dropR (absNum i1 s1) s1 : ss, _int = is} -instructionStringButLastN state = state +instructionStringButLastN = instructionVectorDropR string +-- |Takes the top string from the string stack and calculates the length. The length +-- is then pushed to the int stack. instructionStringLength :: State -> State instructionStringLength = instructionLength string +-- |Makes an empty string and pushes it to the top of the string stack. instructionStringMakeEmpty :: State -> State instructionStringMakeEmpty = instructionVectorMakeEmpty string +-- |Checks to see if the top string is empty on the string stack. +-- Pushes True to the bool stack if empty. Pushes False if not. instructionStringIsEmptyString :: State -> State -instructionStringIsEmptyString state@(State {_string = s1 : ss, _bool = bs}) = state{_string = ss, _bool = null s1 : bs} -instructionStringIsEmptyString state = state +instructionStringIsEmptyString = instructionVectorIsEmpty string +-- TODO: Make this generic instructionStringRemoveNth :: State -> State instructionStringRemoveNth state@(State {_string = s1 : ss, _int = i1 : is}) = state{_string = deleteAt (absNum i1 s1) s1 : ss, _int = is} instructionStringRemoveNth state = state