【问题标题】:Doing a binary search on some elements in Haskell对 Haskell 中的某些元素进行二分搜索
【发布时间】:2008-11-15 23:45:36
【问题描述】:

我正在尝试完成我的 Haskell 作业的最后一部分,但我卡住了,我的代码到目前为止:

data Entry = Entry (String, String)

class Lexico a where
    (<!), (=!), (>!) :: a -> a -> Bool

instance Lexico Entry where
    Entry (a,_) <! Entry (b,_) = a <  b
    Entry (a,_) =! Entry (b,_) = a == b
    Entry (a,_) >! Entry (b,_) = a >  b

entries :: [(String, String)]
entries =  [("saves", "en vaut"), ("time", "temps"), ("in", "<`a>"),
              ("{", "{"), ("A", "Un"), ("}", "}"), ("stitch", "point"),
              ("nine.", "cent."), ("Zazie", "Zazie")]

build :: (String, String) -> Entry
build (a, b) = Entry (a, b)

diction :: [Entry]
diction = quiksrt (map build entries)

size :: [a] -> Integer
size [] = 0
size (x:xs) = 1+ size xs

quiksrt :: Lexico a => [a] -> [a]
quiksrt [] = []
quiksrt (x:xs)
    |(size [y|y <- xs, y =! x]) > 0 = error "Duplicates not allowed."
    |otherwise = quiksrt [y|y <- xs, y <! x]++ [x] ++ quiksrt [y|y <- xs, y >! x] 


english :: String
english = "A stitch in time save nine."

show :: Entry -> String
show (Entry (a, b)) = "(" ++ Prelude.show a ++ ", " ++ Prelude.show b ++ ")"

showAll :: [Entry] -> String
showAll [] = []
showAll (x:xs) = Main.show x ++ "\n" ++ showAll xs

main :: IO ()
main = do putStr (showAll ( diction ))

问题问:

编写一个 Haskell 程序 英文句子“english”,看起来 提高英语-法语中的每个单词 使用二进制搜索的字典, 执行逐字替换, 组装法语翻译,和 打印出来。

函数“快速排序”拒绝 重复条目(带有“错误”/中止) 所以恰好有一个法国人 任何英语单词的定义。测试 '快速排序'与原始 'raw_data' 并在添加后 '("saves", "sauve")' 到 'raw_data'。

这是一个冯诺依曼迟到 二进制搜索的版本。做一个 直译为 Haskell。 进入后,Haskell 版本必须验证递归 “循环不变”,以 '错误'/如果它未能保持,则中止。它 也以相同的方式终止,如果 找不到英文单词。

function binsearch (x : integer) : integer
local j, k, h : integer
j,k := 1,n
do j+1 <> k --->
  h := (j+k) div 2
  {a[j] <= x < a[k]}        // loop invariant
  if x <  a[h] ---> k := h
   | x >= a[h] ---> j := h
  fi
od
{a[j] <= x < a[j+1]}        // termination assertion
found := x = a[j]
if found     ---> return j
 | not found ---> return 0
fi

在 Haskell 版本中

binsearch :: String -> Integer -> Integer -> Entry

作为常量字典'a'类型 '[Entry]' 是全局可见的。暗示: 把你的字符串(英文单词)变成 进入后立即“进入” 'binsearch'。

的编程价值 高级数据类型“条目”是, 如果你能设计这两个功能 在整数上,它是微不足道的 将它们抬起以在 Entry 上方进行操作。

有人知道我应该如何使用二进制搜索功能吗?

【问题讨论】:

    标签: search haskell


    【解决方案1】:

    教师要求“直译”,因此请以相同的顺序使用相同的变量名。但请注意一些差异:

    • 给定的版本只需要 1 参数,他给出的签名 需要 3. 嗯,
    • 给定的版本不是递归的,但他要求一个 递归版本。

    另一个答案是转换为数组,但是对于这么小的练习(这毕竟是家庭作业),我觉得我们可以假装列表是直接访问的。我刚刚接受了您的 diction::[Entry] 并对其进行了索引。我确实不得不在几个地方在 Int 和 Integer 之间进行转换。

    小问题:你的英文值有错字(bs 是我创建的 binSearch 的快捷方式):

      *Main> map bs (words english)
    [Entry ("A","Un"),Entry ("stitch","point"),Entry ("in","<`a>"),Entry ("time","te
    mps"),*** Exception: Not found
    *Main> map bs (words englishFixed)
    [Entry ("A","Un"),Entry ("stitch","point"),Entry ("in","<`a>"),Entry ("time","te
    mps"),Entry ("saves","en vaut"),Entry ("nine.","cent.")]
    *Main>
    

    【讨论】:

    • 是的,那个错字给我带来了很多麻烦,当我运行代码时出现了一些无限循环。
    【解决方案2】:

    二分查找需要随机访问,这在列表中是不可能的。因此,首先要做的可能是将列表转换为Array(带有listArray),然后对其进行搜索。

    【讨论】:

      【解决方案3】:

      这是我的代码,仅用于问题的英文部分(我对其进行了测试,它运行良好):

      module Main where
      
      class Lex a where
          (<!), (=!), (>!) :: a -> a -> Bool
      
      data Entry = Entry String String
      
      instance Lex Entry where
          (Entry a _) <!  (Entry b _) = a <  b
          (Entry a _) =!  (Entry b _) = a == b
          (Entry a _) >!  (Entry b _) = a >  b
        -- at this point, three binary (infix) operators on values of type 'Entry'
        -- have been defined
      
      type Raw = (String, String)
      
      raw_data :: [Raw]
      raw_data  =  [("than a", "qu'un"), ("saves", "en vaut"), ("time", "temps"),
                      ("in", "<`a>"), ("worse", "pire"), ("{", "{"), ("A", "Un"),
                      ("}", "}"), ("stitch", "point"), ("crime;", "crime,"),
                      ("a", "une"), ("nine.", "cent."), ("It's", "C'est"),
                      ("Zazie", "Zazie"), ("cat", "chat"), ("it's", "c'est"),
                      ("raisin", "raisin sec"), ("mistake.", "faute."),
                      ("blueberry", "myrtille"), ("luck", "chance"),
                      ("bad", "mauvais")]
      
      cook :: Raw -> Entry
      cook (x, y) = Entry x y
      
      a :: [Entry]
      a = map cook raw_data
      
      quicksort :: Lex a => [a] -> [a]
      quicksort []     = []
      quicksort (x:xs) = quicksort (filter (<! x) xs) ++ [x] ++ quicksort (filter (=! x) xs) ++ quicksort (filter (>! x) xs) 
      
      getfirst :: Entry -> String
      getfirst (Entry x y) = x
      
      getsecond :: Entry -> String
      getsecond (Entry x y) = y
      
      binarysearch :: String -> [Entry] -> Int -> Int -> String
      binarysearch s e low high 
          | low > high = " NOT fOUND "
          | getfirst ((e)!!(mid)) > s = binarysearch s (e) low (mid-1)
          | getfirst ((e)!!(mid)) < s = binarysearch s (e) (mid+1) high
          | otherwise = getsecond ((e)!!(mid))
              where mid = (div (low+high) 2)
      
      translator :: [String] -> [Entry] -> [String]
      translator [] y = []
      translator (x:xs) y = (binarysearch x y 0 ((length y)-1):translator xs y)
      
      english :: String
      english = "A stitch in time saves nine."
      
      compute :: String -> [Entry] -> String
      compute x y = unwords(translator (words (x)) y)
      
      main = do
          putStr (compute english (quicksort a))
      

      【讨论】:

      • @Reza,请将您的代码块缩进 4 个空格,以便将其格式化为代码。我只是在这篇文章中为你做到了。
      【解决方案4】:

      一个重要的 Prelude 运算符是:

      (!!) :: [a] -> Integer -> a
      -- xs!!n returns the nth element of xs, starting at the left and
      -- counting from 0.
      

      因此,[14,7,3]!!1 ~~> 7.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        • 1970-01-01
        相关资源
        最近更新 更多