From b39e9126eed98cd6f0115d64e81f9decea530c4c Mon Sep 17 00:00:00 2001 From: AlephAlpha Date: Fri, 2 Aug 2024 13:47:38 +0800 Subject: [PATCH] :potato: --- analysis/Ideas.md | 8 ++++--- analysis/corpus.txt | 1 + analysis/freq_1gram.txt | 6 ++--- analysis/freq_2gram.txt | 2 ++ analysis/freq_3gram.txt | 1 + app/Doc.hs | 2 ++ doc/Builtins.md | 23 ++++++++++++++++++ src/Nekomata/Builtin.hs | 6 ----- src/Nekomata/Particle.hs | 50 ++++++++++++++++++++++++++++++++++++++++ src/Nekomata/Result.hs | 22 +++++++++++++++++- test/Eval.hs | 6 +++++ 11 files changed, 114 insertions(+), 13 deletions(-) diff --git a/analysis/Ideas.md b/analysis/Ideas.md index a832d33..4515082 100644 --- a/analysis/Ideas.md +++ b/analysis/Ideas.md @@ -5,9 +5,11 @@ 此处总结一下 Code Page 中已有但还没有用上的字符: ``` -.W`w +¤.W`w ``` +`¤` 原本是用于 `\normalForm` 函数。但这个函数由于定义不清晰且在现有的答案中没有用到,因此被移除了。这个字符空了出来,可以用于其它的内置函数。 + 如果 CodePage 中的 256 个字符都用完了,可以考虑用像 05AB1E 那样,用 `.` 开头的字符来表示双字节的内置函数。现在的 CodePage 还没有用完,先不考虑这个问题,但 `.` 也先不要用掉。 LiberationMono 字体所支持的字符列举于[此文件](analysis/LiberationMonoGlyphs.txt),以供选取。 @@ -185,7 +187,7 @@ LiberationMono 字体所支持的字符列举于[此文件](analysis/LiberationM 自动开启 block 是很大的 breaking change,会影响到大量的解答。最好能有一个改动没有这么大的方案。 -可以考虑如果一个助词出现在程序的结尾,其修饰的就是除它之外的整个程序。比如说 `ᶦ{Ƃ2ŗɔƃ3M` 可以写成 `Ƃ2ŗɔƃ3Mᶦ`。这样解决不了所有的问题,但可以解决一些问题。不过这会降低可读性,而且 parser 也会变得复杂。 +可以考虑如果一个助词出现在程序的结尾,其修饰的就是除它之外的整个程序。比如说 `ᶦ{Ƃ2ŗɔƃ3M` 可以写成 `Ƃ2ŗɔƃ3Mᶦ`。这样解决不了所有的问题,但可以解决一些问题。不过这会降低可读性(虽然 golfing language 谈可读性本就有点搞笑),而且 parser 也不好写。 另一个问题是很多助词的 arity 限制太严格了,比如说 `\map` 只能用于 arity 为 `m -> 1` 的函数。这限制了函数的使用方式。下面的关于 arity 的部分作了一些讨论。不过,也许有另一种改动没那么大的方案。 @@ -222,6 +224,6 @@ LiberationMono 字体所支持的字符列举于[此文件](analysis/LiberationM 目前的文档还很不完善。需要增加更多的例子,以及更详细的说明。 -- [ ] 为每个函数增加例子。可以考虑把这些例子用作单元测试。现有的函数太多,不可能一下子全写完,可以慢慢来。 +- [ ] 为每个函数和助词增加例子,并把这些例子用作单元测试。目前函数的部分已完成,助词的部分还没有。 - [ ] 重写现有的 Tutorial。考虑分成多个文件,每个文件只讲一个主题。 - [ ] REPL 的 `\Info` 命令,可以考虑改成能一次输出多个函数的信息。 diff --git a/analysis/corpus.txt b/analysis/corpus.txt index ff169f0..09455e9 100644 --- a/analysis/corpus.txt +++ b/analysis/corpus.txt @@ -33,6 +33,7 @@ RtƊjo1cɗ →rᵉÇË* 2ᵚR1cʳ× 1ᶦ{ƊY$Ĭɗ +¬õ@ ˡ∑ ˡ½ Ňŧ diff --git a/analysis/freq_1gram.txt b/analysis/freq_1gram.txt index 8bed246..f2c222e 100644 --- a/analysis/freq_1gram.txt +++ b/analysis/freq_1gram.txt @@ -73,6 +73,7 @@ E : 10 ž : 10 ŋ : 10 ? : 10 +@ : 10 % : 10 ᶠ : 10 ∏ : 10 @@ -81,19 +82,18 @@ C : 10 z : 10 ᵈ : 10 ᶜ : 9 +¬ : 9 ≥ : 9 ‼ : 9 ŗ : 9 ᵗ : 9 ≈ : 9 i : 9 -@ : 9 P : 8 f : 8 ᵚ : 8 × : 8 ů : 8 -¬ : 8 ∕ : 8 £ : 8 ƒ : 8 @@ -138,6 +138,7 @@ d : 5 Ç : 5 ř : 5 ʳ : 5 +õ : 5 G : 5 Å : 5 s : 5 @@ -167,7 +168,6 @@ D : 4 ň : 4 Ṗ : 4 U : 4 -õ : 4 Ṃ : 3 Y : 3 T : 3 diff --git a/analysis/freq_2gram.txt b/analysis/freq_2gram.txt index a79ac38..1b6fc87 100644 --- a/analysis/freq_2gram.txt +++ b/analysis/freq_2gram.txt @@ -343,6 +343,8 @@ cʳ : 1 {Ɗ : 1 ƊY : 1 Ĭɗ : 1 +¬õ : 1 +õ@ : 1 ˡ∑ : 1 ˡ½ : 1 $Z : 1 diff --git a/analysis/freq_3gram.txt b/analysis/freq_3gram.txt index 33bf829..8907bc4 100644 --- a/analysis/freq_3gram.txt +++ b/analysis/freq_3gram.txt @@ -148,6 +148,7 @@ cʳ× : 1 ƊY$ : 1 Y$Ĭ : 1 $Ĭɗ : 1 +¬õ@ : 1 ʷ{$ : 1 {$Z : 1 $Zᵉ : 1 diff --git a/app/Doc.hs b/app/Doc.hs index 650a73c..d5f273f 100644 --- a/app/Doc.hs +++ b/app/Doc.hs @@ -22,6 +22,8 @@ docBuiltins = ++ "Nekomata is still in an early stage. The full names, short names, " ++ "and meanings of built-in functions and particles are subject " ++ "to change.\n\n" + ++ "- [Functions](#functions)\n" + ++ "- [Particles](#particles)\n\n" ++ "## Functions\n\n" ++ concat [infoMarkdown b | b <- builtins] ++ "## Particles\n\n" diff --git a/doc/Builtins.md b/doc/Builtins.md index 7168759..7a67ba7 100644 --- a/doc/Builtins.md +++ b/doc/Builtins.md @@ -2,6 +2,9 @@ Nekomata is still in an early stage. The full names, short names, and meanings of built-in functions and particles are subject to change. +- [Functions](#functions) +- [Particles](#particles) + ## Functions ### `choice` (`?`, `2 -> 1`) @@ -2314,22 +2317,42 @@ Apply a function to the top two values of the stack. If the function takes no argument, simply apply it twice. +__Examples__: + +- `1 2 ᵃ{1+} Ð` → `[2,3]` + ### `noPop` (`ˣ`, `(m -> n) -> (m -> m + n)`) Apply a function without popping the stack. +__Examples__: + +- `1 ˣ{1+} Ð` → `[1,2]` + ### `dip` (`ᵈ`, `(m -> n) -> (m + 1 -> n + 1)`) Pop the top value of the stack, apply a function to the rest, and push the popped value back. +__Examples__: + +- `1 2 ᵈ{1+} Ð` → `[2,2]` + ### `dupDip` (`ᵉ`, `(m -> n) -> (m -> n + 1)`) Apply a function to the stack, and then push the original top value back. +__Examples__: + +- `1 ᵈ{1+} Ð` → `[2,1]` + ### `dupDip2` (`ᵋ`, `(m -> n) -> (m -> n + 2)`) Apply a function to the stack, and then push the original top two values back. +__Examples__: + +- `1 2 ᵋ{+} ÐÐ` → `[3,[1,2]]` + ### `map` (`ᵐ`, `(0 -> 1) -> (1 -> 1) or (m -> 1) -> (m -> 1) where m > 0`) Apply a function to each value in a list. diff --git a/src/Nekomata/Builtin.hs b/src/Nekomata/Builtin.hs index d86c62a..3443291 100644 --- a/src/Nekomata/Builtin.hs +++ b/src/Nekomata/Builtin.hs @@ -93,12 +93,6 @@ infoByName name' = '\\' : name'' -> Map.lookup name'' builtinMap _ -> Map.lookup name' builtinMap -all_ :: [String] -> Result -all_ = All False - -truncate_ :: [String] -> Result -truncate_ = All True - -- | The list of all builtin functions builtins :: [Builtin] builtins = diff --git a/src/Nekomata/Particle.hs b/src/Nekomata/Particle.hs index be70075..395e135 100644 --- a/src/Nekomata/Particle.hs +++ b/src/Nekomata/Particle.hs @@ -19,6 +19,7 @@ import Nekomata.Data import Nekomata.Function hiding (arity) import qualified Nekomata.Function as Function import Nekomata.NonDet +import Nekomata.Result {- | A particle is a higher-order function that modifies a function @@ -39,6 +40,8 @@ data BuiltinParticle = BuiltinParticle -- ^ The arity of the particle , help :: String -- ^ The help message for the particle + , examples :: [(String, Result)] + -- ^ Some examples for the particle } instance Show BuiltinParticle where @@ -54,6 +57,19 @@ info b = ++ arity b ++ "):\n" ++ help b + ++ if null (examples b) + then "" + else + "\nExamples:\n" + ++ unlines + [ " " + ++ example + ++ " -> " + ++ if result == all_ [] + then "Fail" + else show result + | (example, result) <- examples b + ] -- | Get the info string for a builtin particle in Markdown format infoMarkdown :: BuiltinParticle -> String @@ -66,6 +82,20 @@ infoMarkdown b = ++ arity b ++ "`)\n\n" ++ concatMap (++ "\n\n") (lines (help b)) + ++ if null (examples b) + then "" + else + "__Examples__:\n\n" + ++ unlines + [ "- `" + ++ example + ++ "` → " + ++ if result == all_ [] + then "Fail" + else "`" ++ show result ++ "`" + | (example, result) <- examples b + ] + ++ "\n" -- | Get the info string for a builtin particle by name infoByName :: String -> Maybe String @@ -86,12 +116,14 @@ builtinParticles = \or (m -> n) -> (m + 1 -> 2 * n) where m > 0" "Apply a function to the top two values of the stack.\n\ \If the function takes no argument, simply apply it twice." + [("1 2 ᵃ{1+} Ð", all_ ["[2,3]"])] , BuiltinParticle "noPop" 'ˣ' noPop "(m -> n) -> (m -> m + n)" "Apply a function without popping the stack." + [("1 ˣ{1+} Ð", all_ ["[1,2]"])] , BuiltinParticle "dip" 'ᵈ' @@ -99,6 +131,7 @@ builtinParticles = "(m -> n) -> (m + 1 -> n + 1)" "Pop the top value of the stack, apply a function to the rest, \ \and push the popped value back." + [("1 2 ᵈ{1+} Ð", all_ ["[2,2]"])] , BuiltinParticle "dupDip" 'ᵉ' @@ -106,6 +139,7 @@ builtinParticles = "(m -> n) -> (m -> n + 1)" "Apply a function to the stack, \ \and then push the original top value back." + [("1 ᵈ{1+} Ð", all_ ["[2,1]"])] , BuiltinParticle "dupDip2" 'ᵋ' @@ -113,6 +147,7 @@ builtinParticles = "(m -> n) -> (m -> n + 2)" "Apply a function to the stack, \ \and then push the original top two values back." + [("1 2 ᵋ{+} ÐÐ", all_ ["[3,[1,2]]"])] , BuiltinParticle "map" 'ᵐ' @@ -124,6 +159,7 @@ builtinParticles = \from 0 to the input minus 1.\n\ \If the function takes no argument, return a list of n copies \ \of the result of the function, where n is the length of the input." + [] , BuiltinParticle "mapWith" 'ᵚ' @@ -134,6 +170,7 @@ builtinParticles = \If the function is unary, return a list of n copies of the \ \result of applying the function to the second argument, where \ \n is the length of the first argument." + [] , BuiltinParticle "zipWith" 'ᶻ' @@ -143,6 +180,7 @@ builtinParticles = \Fail if the lists have different lengths.\n\ \If one of the input is an number, apply the function to each \ \integer from 0 to the input minus 1." + [] , BuiltinParticle "zipWithTrunc" 'ᶾ' @@ -153,6 +191,7 @@ builtinParticles = \to the length of the shorter list.\n\ \If one of the input is an number, apply the function to each \ \integer from 0 to the input minus 1." + [] , BuiltinParticle "outer" 'ᵒ' @@ -162,6 +201,7 @@ builtinParticles = \and return a list of lists.\n\ \If one of the input is an number, apply the function to each \ \integer from 0 to the input minus 1." + [] , BuiltinParticle "predicate" 'ᵖ' @@ -170,6 +210,7 @@ builtinParticles = "Check if a function would succeed without actually applying it.\n\ \If the function fails, replace the top value with Fail.\n\ \Otherwise, do nothing." + [] , BuiltinParticle "predicateNot" 'ᵗ' @@ -178,6 +219,7 @@ builtinParticles = "Check if a function would fail without actually applying it.\n\ \If the function does not fail, replace the top value with Fail.\n\ \Otherwise, do nothing." + [] , BuiltinParticle "filter" 'ᶠ' @@ -187,12 +229,14 @@ builtinParticles = \without actually applying it, and remove the value if it fails.\n\ \If the input is an number, convert it to a list of integers \ \from 0 to the input minus 1 before filtering." + [] , BuiltinParticle "orApply" 'ᶜ' orApply "(n -> n) -> (n -> n)" "Apply a function zero or one time non-deterministically." + [] , BuiltinParticle "iterate" 'ᶦ' @@ -202,6 +246,7 @@ builtinParticles = \until the top value of the stack is Fail.\n\ \This is different from `while` in that it returns \ \the intermediate results." + [] , BuiltinParticle "nTimes" 'ᵑ' @@ -209,6 +254,7 @@ builtinParticles = "(n -> n) -> (n + 1 -> n)" "Take an integer from the top of the stack, \ \and apply a function that many times." + [] , BuiltinParticle "while" 'ʷ' @@ -218,6 +264,7 @@ builtinParticles = \until the top value of the stack is Fail.\n\ \This is different from `iterate` in that it does not \ \return the intermediate results." + [] , BuiltinParticle "lengthWhile" 'ˡ' @@ -226,6 +273,7 @@ builtinParticles = "Apply a function zero or more times, \ \until the top value of the stack is Fail, \ \and return the number of times the function was applied." + [] , BuiltinParticle "firstInt" 'ᵏ' @@ -233,6 +281,7 @@ builtinParticles = "(m -> n) -> (0 -> 1)" "Find the smallest non-negative integer for which a function \ \does not fail, and return it." + [] , BuiltinParticle "fold1" 'ʳ' @@ -243,6 +292,7 @@ builtinParticles = \and so on until the end of the list.\n\ \If the input is an number, convert it to a list of integers \ \from 0 to the input minus 1 before folding." + [] ] -- | The map of from names to builtin particles diff --git a/src/Nekomata/Result.hs b/src/Nekomata/Result.hs index 2f8051f..948d7f5 100644 --- a/src/Nekomata/Result.hs +++ b/src/Nekomata/Result.hs @@ -1,7 +1,11 @@ module Nekomata.Result ( Result (..), + all_, + first_, + nothing_, showResult, truncate', + truncate_, ) where import Data.Maybe (fromMaybe) @@ -34,4 +38,20 @@ showResult (Check b) = [show b] -- | Truncate a list of strings to a given length truncate' :: Int -> [String] -> Result truncate' n xs = - let (ys, zs) = splitAt n xs in All (not $ null zs) ys \ No newline at end of file + let (ys, zs) = splitAt n xs in All (not $ null zs) ys + +-- | All results, not truncated +all_ :: [String] -> Result +all_ = All False + +-- | First few results +truncate_ :: [String] -> Result +truncate_ = All True + +-- | The first result +first_ :: String -> Result +first_ = First . Just + +-- | No results +nothing_ :: Result +nothing_ = First Nothing \ No newline at end of file diff --git a/test/Eval.hs b/test/Eval.hs index 4ad3173..ef894fb 100644 --- a/test/Eval.hs +++ b/test/Eval.hs @@ -401,6 +401,12 @@ testEval = describe "Solutions to Code Golf Stack Exchange challenges" $ do specEval "1ᶦ{ƊY$Ĭɗ" [("", truncate_ ["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211", "31131211131221", "13211311123113112211"])] + describe "q70779: Consolidate an Array" $ do + specEval + "¬õ@" + [ ("[1,0,2,0,-5,0,3,4,5,0,0,6]", all_ ["[1,2,-5,3,4,5,6,0,0,0,0,0]"]) + , ("[0,5,8,8,3,5,1,6,8,4,0,3,7,5]", all_ ["[5,8,8,3,5,1,6,8,4,3,7,5,0,0]"]) + ] describe "q71476: Determine the depth of an array" $ do specEval "ˡ∑"