输入字符的所有可能的长度为n的字符串-Haskell

我试图在由 _ 和其他字母组成的字符串中生成输入字符的所有可能位置,其中输入字符只能替换 _ 表示的位置。

我到目前为止所做的代码在这里:

possibleNewWords currentString letterInput listOfPossibleStrings currentColumn iterations
  | iterations == length currentString = removeDuplicates listOfPossibleStrings
  | (currentColumn == length currentString) && (currentString!!iterations == '_') = possibleNewWords iteredString letterInput listOfPossibleStrings 0 (iterations+1)
  | (currentColumn == length currentString) && (currentString!!iterations /= '_') = possibleNewWords currentString letterInput listOfPossibleStrings 0 (iterations+1)
  | currentString!!currentColumn == '_' = possibleNewWords currentString letterInput (possibleStringNormal:listOfPossibleStrings) (currentColumn+1) iterations
  | currentString!!currentColumn /= '_' = possibleNewWords currentString letterInput listOfPossibleStrings (currentColumn+1) iterations
  
  where
    possibleStringNormal = replaceInString currentColumn letterInput currentString
    iteredString = replaceInString iterations letterInput currentString
    
possibleNewWordsBlank currentString letterInput listOfPossibleStrings currentColumn iterations
  | iterations == length currentString = removeDuplicates listOfPossibleStrings
  | (currentColumn == length currentString) && (currentString!!iterations == '_') = possibleNewWordsBlank iteredString letterInput listOfPossibleStrings 0 (iterations+1)
  | (currentColumn == length currentString) && (currentString!!iterations /= '_') = possibleNewWordsBlank currentString letterInput listOfPossibleStrings 0 (iterations+1)
  | (currentString!!currentColumn == '_') && (currentColumn > (iterations+1)) = possibleNewWordsBlank currentString letterInput (possibleStringNormal:listOfPossibleStrings) (currentColumn+1) iterations
  | (currentString!!currentColumn /= '_') || (currentColumn <= (iterations+1)) = possibleNewWordsBlank currentString letterInput listOfPossibleStrings (currentColumn+1) iterations
  
  where
    possibleStringNormal = replaceInString currentColumn letterInput currentString
    halfIteredString = replaceInString iterations '_' currentString
    iteredString = replaceInString (iterations+1) letterInput currentString

top 函数可以生成绝大多数可能性(它本质上在每个可用的下划线中放置一个输入字符,然后在字符串的第一个位置永久放置一个字符,重复该过程直到每个 _ 都被输入字符替换)但我意识到它没有考虑到诸如 之类的情况"_F_F_",所以我尝试编写第二个函数 (possibleNewWordsBlank) 并计划组合结果并删除最终集合的重复项,但我无法输出剩余的潜在组合。那时我意识到我可能错误地处理了整个问题,并认为寻求帮助是明智的。

我正在尝试做的一个例子是,如果我们试图找到所有可能性"____"并且输入字符是 'F' 那么["____", "F___", "_F__", "__F_", "___F", "FF__", "F_F_", "F__F", "FFF_", "FF_F", "FFFF", "_FFF", "_FF_", "_F_F", "__FF", "F_FF"]将被输出。我想尝试从我的第一个函数输出中反转字符串,但意识到这不会涵盖较大 n 的所有情况。

我试图用这种方式处理预先存在的字母的一个例子是"__F_W"输入字符是 'G' 的地方将输出["G_F_W", "_GF_W", "__FGW", "GGF_W", "G_FGW", "GGFGW", "_GFGW", "__F_W"]

回答

从您对“迭代”和“currentColumn”的使用以及大量列表索引的使用可以看出,您似乎是从一种相当命令式的风格来的。一个更好的主意是发挥 Haskell 的优势,并以函数式风格来考虑这一点。

首先,尝试为您想要的函数编写类型签名。我把这个给你:

replaceBlanks :: Char -> String -> [String]

接下来,尝试递归思考。 Char不是递归数据结构,而是递归数据结构,String所以一个好的开始是在String. 我的存根可能是这样的:

replaceBlanks newChar [] = ...
replaceBlanks newChar (firstChar : restOfString) = ...

The next step to thinking recursively is the base case. This particular example is actually trickier than it might first appear, but it's not too bad. Ask yourself: What should my program produce if the caller provides the empty string as the second argument?

After that, you need to write the recursive case. The trick here is to start by assuming your program works and then write the program. I know, it sounds weird, but it actually makes sense when you think recursively. What I mean is, pretend that if you call replaceBlanks newChar restOfString, then you magically get the correct answer. Now, using that correct answer, can you extend it to turn into the correct answer for the call to replaceBlanks newChar (firstChar : restOfString)? It will look something like this:

replaceBlanks newChar (firstChar : restOfString) = 
  let partialAnswer = replaceBlanks newChar restOfString
  in ...

让我们使用您自己的具体示例。您正在尝试解决replaceBlanks 'G' "__F_W". 这是一个很难的问题。但是,假设它replaceBlanks 'G' "_F_W"神奇地起作用,并且它正确地返回给您["GFGW","GF_W","_FGW","_F_W"]。你可以用这个列表做什么来把它变成["GGFGW","GGF_W","G_FGW","G_F_W","_GFGW","_GF_W","__FGW","__F_W"]你最终想要的解决方案?你看到任何图案了吗?(提示:map函数是你的朋友!)

一旦你填写了...(并假设你做对了),那么你的程序应该神奇地工作。递归的魔力!


以上是输入字符的所有可能的长度为n的字符串-Haskell的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>