2025-09-18 00:31:50 +03:00
|
|
|
import Data.List (elemIndex, sort, find)
|
|
|
|
|
import Data.Maybe (isJust)
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
infixl 4 :+:
|
|
|
|
|
|
|
|
|
|
data IntExpr = Zero
|
|
|
|
|
| Succ IntExpr
|
|
|
|
|
| Len ListExpr
|
|
|
|
|
| FirstZero ListExpr
|
2025-09-18 00:31:50 +03:00
|
|
|
deriving (Read, Show, Eq)
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
data ListExpr = Sort ListExpr
|
|
|
|
|
| SubList ListExpr IntExpr IntExpr
|
|
|
|
|
| ListExpr :+: ListExpr
|
|
|
|
|
| Recursive ListExpr
|
|
|
|
|
| ZeroList
|
|
|
|
|
| InList
|
2025-09-18 00:31:50 +03:00
|
|
|
deriving (Read, Show, Eq)
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-18 00:31:50 +03:00
|
|
|
data Env = Env {input :: [Int], prog :: ListExpr, steps :: Int}
|
|
|
|
|
|
|
|
|
|
stepInEnv :: Env -> Env
|
|
|
|
|
stepInEnv env@(Env {input, prog, steps}) = env { steps = steps - 1 }
|
|
|
|
|
|
|
|
|
|
execInt :: Env -> IntExpr -> Maybe Int
|
|
|
|
|
execInt (Env {input, prog, steps=0}) _ = Nothing
|
|
|
|
|
execInt _ Zero = Just 0
|
|
|
|
|
execInt env (Succ expr) = (+) 1 <$> execInt (stepInEnv env) expr
|
2025-09-23 11:40:41 +03:00
|
|
|
execInt env (Len listExpr) = length <$> execList (stepInEnv env) listExpr
|
2025-09-18 00:31:50 +03:00
|
|
|
execInt env (FirstZero listExpr) = do value <- execList (stepInEnv env) listExpr
|
|
|
|
|
0 `elemIndex` value
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
-- TODO: limit execution steps
|
2025-09-18 00:31:50 +03:00
|
|
|
execList :: Env -> ListExpr -> Maybe [Int]
|
|
|
|
|
execList (Env {input, prog, steps=0}) _ = Nothing
|
|
|
|
|
execList env (Sort listExpr) = sort <$> execList (stepInEnv env) listExpr
|
|
|
|
|
execList env (SubList listExpr exprFrom exprTo) = do valFrom <- execInt (stepInEnv env) exprFrom
|
|
|
|
|
valTo <- execInt (stepInEnv env) exprTo
|
|
|
|
|
listValue <- execList (stepInEnv env) listExpr
|
2025-09-23 11:40:41 +03:00
|
|
|
return $ drop valFrom $ take (valTo + 1) listValue
|
2025-09-18 00:31:50 +03:00
|
|
|
execList env (exprLeft :+: exprRight) = do valLeft <- execList (stepInEnv env) exprLeft
|
|
|
|
|
valRight <- execList (stepInEnv env) exprRight
|
|
|
|
|
return $ valLeft ++ valRight
|
2025-09-23 11:40:41 +03:00
|
|
|
execList env (Recursive listExpr) = do listValue <- execList (stepInEnv env) listExpr
|
|
|
|
|
if null listValue then Just [] else execList (stepInEnv $ env {input = listValue}) (prog env)
|
2025-09-18 00:31:50 +03:00
|
|
|
execList _ ZeroList = Just [0]
|
|
|
|
|
execList (Env {input, prog, steps}) InList = Just input
|
|
|
|
|
|
|
|
|
|
execProg :: [Int] -> ListExpr -> Maybe [Int]
|
2025-09-23 11:40:41 +03:00
|
|
|
execProg input expr = execList (Env {input, prog=expr, steps=20}) expr
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
data AllExprs = AllExprs {ints :: [IntExpr], lists :: [ListExpr]}
|
2025-09-23 11:40:41 +03:00
|
|
|
deriving (Read, Show, Eq)
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
terminals :: AllExprs
|
|
|
|
|
terminals = AllExprs {ints = [Zero], lists = [ZeroList, InList]}
|
|
|
|
|
|
2025-09-18 00:31:50 +03:00
|
|
|
nextExprs :: AllExprs -> AllExprs
|
|
|
|
|
nextExprs (AllExprs {ints, lists}) = AllExprs {ints = map Succ ints ++ map Len lists ++ map FirstZero lists ++ ints,
|
2025-09-23 11:40:41 +03:00
|
|
|
lists = map Sort lists ++
|
|
|
|
|
[SubList list from to | list <- lists, from <- ints, to <- ints] ++
|
|
|
|
|
[left :+: right | left <- lists, right <- lists] ++
|
|
|
|
|
map Recursive lists ++
|
|
|
|
|
lists}
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-18 00:31:50 +03:00
|
|
|
data Example = Example {exampleInput :: [Int], exampleOutput :: [Int]}
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
-- check expr on all examples
|
|
|
|
|
isCorrect :: [Example] -> ListExpr -> Bool
|
2025-09-18 00:31:50 +03:00
|
|
|
isCorrect examples expr = all (\Example {exampleInput, exampleOutput} -> execProg exampleInput expr == Just exampleOutput) examples
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-18 00:31:50 +03:00
|
|
|
isValid :: [Example] -> ListExpr -> Bool
|
|
|
|
|
isValid examples expr = all (\Example {exampleInput, exampleOutput} -> isJust $ execProg exampleInput expr) examples
|
2025-09-17 17:26:01 +03:00
|
|
|
|
|
|
|
|
-- check are exprs produce same results on all the examples
|
2025-09-18 00:31:50 +03:00
|
|
|
areSame :: [Example] -> ListExpr -> ListExpr -> Bool
|
|
|
|
|
areSame examples exprLeft exprRight = all (\Example {exampleInput, exampleOutput} -> execProg exampleInput exprLeft == execProg exampleInput exprRight ) examples
|
|
|
|
|
|
|
|
|
|
upSyntesisStep :: [Example] -> AllExprs -> Either AllExprs ListExpr
|
2025-09-23 11:40:41 +03:00
|
|
|
upSyntesisStep examples allExprs@(AllExprs {ints, lists}) = let lists' = filter (isValid examples) lists in -- exclude invalid fragments
|
|
|
|
|
let lists'' = foldl (\acc expr -> if any (areSame examples expr) acc then acc else expr : acc) [] lists' in -- merge same values
|
|
|
|
|
case find (isCorrect examples) lists'' of
|
2025-09-18 00:31:50 +03:00
|
|
|
Just answer -> Right answer
|
2025-09-23 11:40:41 +03:00
|
|
|
Nothing -> Left $ nextExprs allExprs{lists=lists''}
|
2025-09-18 00:31:50 +03:00
|
|
|
|
|
|
|
|
upSyntesisRec :: [Example] -> Int -> AllExprs -> Maybe ListExpr
|
|
|
|
|
upSyntesisRec _ 0 _ = Nothing
|
|
|
|
|
upSyntesisRec examples steps exprs = case upSyntesisStep examples exprs of
|
|
|
|
|
Right answer -> Just answer
|
|
|
|
|
Left exprs' -> upSyntesisRec examples (steps - 1) exprs'
|
|
|
|
|
|
2025-09-23 11:40:41 +03:00
|
|
|
upSyntesis :: [Example] -> Int -> Maybe ListExpr
|
|
|
|
|
upSyntesis examples steps = upSyntesisRec examples steps terminals
|
2025-09-18 00:31:50 +03:00
|
|
|
|
|
|
|
|
-----
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-23 11:40:41 +03:00
|
|
|
exampleOf :: [Int] -> [Int] -> Example
|
|
|
|
|
exampleOf input output = Example {exampleInput = input, exampleOutput = output}
|
|
|
|
|
|
|
|
|
|
-- InList
|
|
|
|
|
sameExamples = [exampleOf [1] [1], exampleOf [1,2] [1,2], exampleOf [1,2,3] [1,2,3], exampleOf [1,2,3,4] [1,2,3,4]]
|
|
|
|
|
-- (Recursive $ SubList InList (Suc Zero) (Len InList)) :+: (SubList InList Zero Zero)
|
|
|
|
|
revExamples = [exampleOf [1] [1], exampleOf [1,2] [2,1], exampleOf [1,2,3] [3,2,1], exampleOf [1,2,3,4] [4,3,2,1]]
|
|
|
|
|
|
|
|
|
|
main = print $ upSyntesis revExamples 5
|