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 :+:
|
|
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
data Expr = Zero
|
|
|
|
|
| Succ Expr
|
|
|
|
|
| Len Expr
|
|
|
|
|
| FirstZero Expr
|
|
|
|
|
| Sort Expr
|
|
|
|
|
| SubList Expr Expr Expr
|
|
|
|
|
| Expr :+: Expr
|
|
|
|
|
| Recursive Expr
|
|
|
|
|
| ZeroList
|
|
|
|
|
| InList
|
2025-09-18 00:31:50 +03:00
|
|
|
deriving (Read, Show, Eq)
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
data Type = IntT | ListT
|
2025-09-18 00:31:50 +03:00
|
|
|
deriving (Read, Show, Eq)
|
2025-09-23 19:34:52 +03:00
|
|
|
data Value = IntV Int | ListV [Int]
|
|
|
|
|
deriving (Read, Show, Eq)
|
|
|
|
|
|
|
|
|
|
typeOf :: Expr -> Type
|
|
|
|
|
typeOf Zero = IntT
|
|
|
|
|
typeOf (Succ {}) = IntT
|
|
|
|
|
typeOf (Len {}) = IntT
|
|
|
|
|
typeOf (FirstZero {}) = IntT
|
|
|
|
|
typeOf _ = ListT
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
data Env = Env {input :: [Int], prog :: Expr, steps :: Int}
|
2025-09-18 00:31:50 +03:00
|
|
|
|
|
|
|
|
stepInEnv :: Env -> Env
|
|
|
|
|
stepInEnv env@(Env {input, prog, steps}) = env { steps = steps - 1 }
|
|
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
execInt :: Env -> Expr -> Maybe Int
|
2025-09-18 00:31:50 +03:00
|
|
|
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-23 19:34:52 +03:00
|
|
|
execInt _ _ = Nothing
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
execList :: Env -> Expr -> Maybe [Int]
|
2025-09-18 00:31:50 +03:00
|
|
|
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
|
2025-09-23 19:34:52 +03:00
|
|
|
execList _ _ = Nothing
|
2025-09-18 00:31:50 +03:00
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
-- TODO: union
|
|
|
|
|
execProg :: [Int] -> Expr -> 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
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
terminals :: [Expr]
|
2025-09-30 10:34:37 +03:00
|
|
|
terminals = [Zero, ZeroList, InList] -- ,
|
|
|
|
|
-- Succ Zero, Len InList]
|
2025-09-23 19:34:52 +03:00
|
|
|
|
|
|
|
|
concatShuffle :: [[Expr]] -> [Expr]
|
|
|
|
|
concatShuffle xxs = let xxs' = filter (not . null) xxs in
|
|
|
|
|
if null xxs' then [] else
|
|
|
|
|
map head xxs' ++ concatShuffle (map tail xxs')
|
|
|
|
|
|
2025-09-30 10:10:43 +03:00
|
|
|
nextSimpleExprsLists :: [Expr] -> [[Expr]]
|
2025-09-30 10:47:20 +03:00
|
|
|
nextSimpleExprsLists exprs = let listExprs = [ e | e <- exprs, typeOf e == ListT] in
|
|
|
|
|
[[Succ e | e <- exprs, typeOf e == IntT],
|
|
|
|
|
map Sort listExprs,
|
|
|
|
|
map Recursive listExprs,
|
|
|
|
|
map FirstZero listExprs,
|
|
|
|
|
map Len listExprs]
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
nextExprsLists :: [Expr] -> [[Expr]]
|
2025-09-30 10:47:20 +03:00
|
|
|
nextExprsLists exprs = let listExprs = [ e | e <- exprs, typeOf e == ListT] in
|
|
|
|
|
let intExprs = [ e | e <- exprs, typeOf e == IntT] in
|
|
|
|
|
nextSimpleExprsLists exprs ++
|
|
|
|
|
[[e :+: e' | e <- listExprs,
|
|
|
|
|
e' <- listExprs],
|
|
|
|
|
[SubList e from to | e <- listExprs, from <- intExprs, to <- intExprs]]
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
nextSimpleExprs :: [Expr] -> [Expr]
|
|
|
|
|
nextSimpleExprs exprs = (++) exprs $ concatShuffle $ nextSimpleExprsLists exprs
|
|
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
nextExprs :: [Expr] -> [Expr]
|
2025-09-30 10:10:43 +03:00
|
|
|
nextExprs exprs = (++) exprs $ concatShuffle $ nextExprsLists exprs
|
|
|
|
|
|
|
|
|
|
nextSimpleExprs' :: [Expr] -> [Expr]
|
|
|
|
|
nextSimpleExprs' = concatShuffle . nextSimpleExprsLists
|
|
|
|
|
|
|
|
|
|
nextExprsLists' :: [Expr] -> [Expr] -> [[Expr]]
|
2025-09-30 10:59:11 +03:00
|
|
|
nextExprsLists' newExprs oldExprs = let listNewExprs = [ e | e <- newExprs, typeOf e == ListT] in
|
|
|
|
|
let intNewExprs = [ e | e <- newExprs, typeOf e == IntT] in
|
|
|
|
|
let listOldExprs = [ e | e <- oldExprs, typeOf e == ListT] in
|
|
|
|
|
let intOldExprs = [ e | e <- oldExprs, typeOf e == IntT] in
|
|
|
|
|
nextSimpleExprsLists newExprs ++
|
2025-09-30 11:02:26 +03:00
|
|
|
[concat [[e :+: e' | e <- listNewExprs, e' <- listNewExprs],
|
|
|
|
|
[e :+: e' | e <- listNewExprs, e' <- listOldExprs],
|
|
|
|
|
[e :+: e' | e <- listOldExprs, e' <- listNewExprs]],
|
|
|
|
|
concat [[SubList e from to | e <- listNewExprs, from <- intNewExprs, to <- intNewExprs],
|
|
|
|
|
[SubList e from to | e <- listOldExprs, from <- intNewExprs, to <- intNewExprs],
|
|
|
|
|
[SubList e from to | e <- listNewExprs, from <- intOldExprs, to <- intNewExprs],
|
|
|
|
|
[SubList e from to | e <- listNewExprs, from <- intNewExprs, to <- intOldExprs],
|
|
|
|
|
[SubList e from to | e <- listOldExprs, from <- intOldExprs, to <- intNewExprs],
|
|
|
|
|
[SubList e from to | e <- listOldExprs, from <- intNewExprs, to <- intOldExprs],
|
|
|
|
|
[SubList e from to | e <- listNewExprs, from <- intOldExprs, to <- intOldExprs]]]
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
nextExprs' :: [Expr] -> [Expr] -> [Expr]
|
2025-09-30 11:02:26 +03:00
|
|
|
nextExprs' newExprs oldExprs = concatShuffle $ nextExprsLists' newExprs oldExprs
|
2025-09-30 10:10:43 +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
|
2025-09-23 19:34:52 +03:00
|
|
|
isCorrect :: [Example] -> Expr -> 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-23 19:34:52 +03:00
|
|
|
isValid :: [Example] -> Expr -> Bool
|
|
|
|
|
isValid examples expr | typeOf expr == IntT = True
|
|
|
|
|
| otherwise = 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-23 19:34:52 +03:00
|
|
|
areSame :: [Example] -> Expr -> Expr -> Bool
|
|
|
|
|
areSame examples exprLeft exprRight | typeOf exprLeft == IntT = False
|
|
|
|
|
| typeOf exprRight == IntT = False
|
2025-09-30 10:34:37 +03:00
|
|
|
| otherwise = all (\Example {exampleInput, exampleOutput} -> let Just resLeft = execProg exampleInput exprLeft in
|
|
|
|
|
let Just resRight = execProg exampleInput exprRight in
|
2025-09-30 10:47:20 +03:00
|
|
|
resLeft /= [] -- NOTE: not in the base algorithm, way to remove rec deletion (?)
|
|
|
|
|
&& resLeft == resRight) examples
|
2025-09-23 19:34:52 +03:00
|
|
|
|
2025-09-30 10:10:43 +03:00
|
|
|
-----
|
|
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
upSyntesisStep :: [Example] -> [Expr] -> Either [Expr] Expr
|
2025-09-30 10:10:43 +03:00
|
|
|
upSyntesisStep examples exprs = case find (isCorrect examples) exprs of
|
|
|
|
|
Just answer -> Right answer
|
|
|
|
|
Nothing -> let exprs' = filter (isValid examples) exprs in -- exclude invalid fragments
|
2025-09-30 10:34:37 +03:00
|
|
|
let exprs'' = foldl (\acc expr -> if any (areSame examples expr) acc then acc else expr : acc) [] exprs' in -- merge same values
|
|
|
|
|
Left $
|
|
|
|
|
nextSimpleExprs $
|
|
|
|
|
nextExprs exprs''
|
2025-09-23 19:34:52 +03:00
|
|
|
|
|
|
|
|
upSyntesisRec :: [Example] -> Int -> [Expr] -> Maybe Expr
|
2025-09-18 00:31:50 +03:00
|
|
|
upSyntesisRec _ 0 _ = Nothing
|
|
|
|
|
upSyntesisRec examples steps exprs = case upSyntesisStep examples exprs of
|
2025-09-30 10:10:43 +03:00
|
|
|
Right answer -> Just answer
|
|
|
|
|
Left exprs' -> upSyntesisRec examples (steps - 1) exprs'
|
|
|
|
|
|
2025-09-18 00:31:50 +03:00
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
upSyntesis :: [Example] -> Int -> Maybe Expr
|
2025-09-30 10:34:37 +03:00
|
|
|
upSyntesis examples steps = upSyntesisRec examples steps $ nextSimpleExprs terminals
|
2025-09-18 00:31:50 +03:00
|
|
|
|
|
|
|
|
-----
|
2025-09-17 17:26:01 +03:00
|
|
|
|
2025-09-30 10:10:43 +03:00
|
|
|
upSyntesisStep' :: [Example] -> [Expr] -> [Expr] -> Either [Expr] Expr
|
2025-09-30 10:59:11 +03:00
|
|
|
upSyntesisStep' examples newExprs oldExprs =
|
|
|
|
|
case find (isCorrect examples) newExprs of
|
2025-09-30 10:10:43 +03:00
|
|
|
Just answer -> Right answer
|
2025-09-30 10:59:11 +03:00
|
|
|
Nothing -> let newExprs' = filter (isValid examples) newExprs in -- exclude invalid fragments
|
|
|
|
|
-- NOTE: new exprs are not checked against old exprs for now
|
|
|
|
|
let newExprs'' = foldl (\acc expr -> if any (areSame examples expr) acc then acc else expr : acc) [] newExprs' in -- merge same values
|
2025-09-30 10:34:37 +03:00
|
|
|
Left $
|
|
|
|
|
-- nextSimpleExprs $
|
2025-09-30 10:59:11 +03:00
|
|
|
nextExprs' newExprs'' oldExprs
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
upSyntesisRec' :: [Example] -> Int -> [Expr] -> [Expr] -> Maybe Expr
|
|
|
|
|
upSyntesisRec' _ 0 _ _ = Nothing
|
2025-09-30 10:59:11 +03:00
|
|
|
upSyntesisRec' examples steps newExprs oldExprs = case upSyntesisStep' examples newExprs oldExprs of
|
2025-09-30 10:10:43 +03:00
|
|
|
Right answer -> Just answer
|
2025-09-30 10:59:11 +03:00
|
|
|
Left exprs -> upSyntesisRec' examples (steps - 1) exprs (newExprs ++ oldExprs)
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
upSyntesis' :: [Example] -> Int -> Maybe Expr
|
2025-09-30 10:59:11 +03:00
|
|
|
upSyntesis' examples steps = upSyntesisRec' examples steps (nextSimpleExprs terminals) []
|
2025-09-30 10:10:43 +03:00
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
2025-09-23 11:40:41 +03:00
|
|
|
exampleOf :: [Int] -> [Int] -> Example
|
|
|
|
|
exampleOf input output = Example {exampleInput = input, exampleOutput = output}
|
|
|
|
|
|
2025-09-23 19:34:52 +03:00
|
|
|
sameExamplesExpected = InList
|
2025-09-23 11:40:41 +03:00
|
|
|
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]]
|
2025-09-23 19:34:52 +03:00
|
|
|
revExamplesExpected = Recursive (SubList InList (Succ Zero) (Len InList)) :+: SubList InList Zero Zero
|
2025-09-23 11:40:41 +03:00
|
|
|
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]]
|
|
|
|
|
|
2025-09-30 10:10:43 +03:00
|
|
|
main = print $ upSyntesis' revExamples 4
|