2017-10-19 75 views
1

我正在完成chapter 12 of Real World Haskell。在本章中,作者解释了如何使用EAN13 encoding执行条形码识别。EAN13 Haskell中的条形码编码:如何测试它?

我转载的大多数代码从the book snippets into my repo,当我终于来到检查是否按预期工作在我的超过300行的代码,我得到了一个坏消息:

-- Finding the Correct Sequence 
*Main> let input = zip (runLengths $ encodeEAN13 "9780132114677") (cycle [Zero, One]) 
*Main> listToMaybe . solve . candidateDigits $ input 
Just [0,2,0,1,0,0,0,0,0,0,0,0,1] -- WRONG Actual 
Just [9,7,8,0,1,3,2,1,1,4,6,7,7] -- Expected 

由于该书出版,我注意到一些类型的签名已更改,如:

$ ghci 
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help 
Prelude> import qualified Data.Map as M 
Prelude M> :t M.lookup 
M.lookup :: Ord k => k -> M.Map k a -> Maybe a 
-- in the book: M.lookup :: (Ord k, Monad m) => k -> M.Map k a -> m a 

我试图在GHCI重现每一个例子,除了从最后一个,我总是得到相同的结果书。

有没有人从这本书中涉及这个话题?

作者不说明的每一行代码和,特别地,所述input变量没有在任何地方let input = zip (runLengths $ encodeEAN13 "9780132114677") (cycle [Zero, One])

用于测试一些EAN13编码条形码定义?

如果没有人知道这本书,你会EAN13的一些样本编码条形码,如:

*Main M> encodeEAN13 "9780132114677" 
"101011101100010010100111001100101000010101011011001100110110011010111001010000100010010001001010000101" 

为了确保我的功能测试是正确的?

非常感谢你提前

回答

1

您的实现两个错误:

首先,在encodeDigits,你写splitAt 5当它应该是splitAt 6。这解决了@Brian Anderson提到的编码错误。

其次,在bestScores,你写的:

[(distance d (scaleToOne ps), n) | d <- srl, n <- digits] 

当你应该写:

zip [distance d (scaleToOne ps) | d <- srl] digits 

此修复您的解码错误。

我希望我可以说我用我的超人调试技巧来发现这些错误,但是从几年前我做第12章时起,我碰巧有自己的副本Barcode.hs

+0

谢谢!它工作完美 – mabe02

1

enter image description here

它看起来像有三个问题你1的序列和0。首先是你的[A] EAN-13中心代码似乎覆盖了你的第六个字符的开头。它应该真的是[B]的地方。而且你还有一个额外的4个零点和一个额外的结束标记,并将其添加到序列的末尾。

这里是一个工具,不会产生校验和铺设工作的1和0:

var arrayCodeEANBin, arrayStructEAN; 
 
arrayCodeEANBin = [ [ '0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011' ], [ '0100111', '0110011', '0011011', '0100001', '0011101', '0111001', '0000101', '0010001', '0001001', '0010111' ], [ '1110010', '1100110', '1101100', '1000010', '1011100', '1001110', '1010000', '1000100', '1001000', '1110100' ] ]; 
 
arrayStructEAN = ['000000', '001011', '001101', '001110', '010011', '011001', '011100', '010101', '010110', '011010'] 
 

 
var strRaw = ""; 
 
var strText = ""; 
 

 
function funcEAN() { // EAN-13 
 
var intSumOdd = 0, intSumEven = 0, intCheck, i, j, strStruct; 
 
// Compute check digit and add it to raw string 
 
for (i = 0; i < 12; i += 2) { 
 
    intSumEven += parseInt(strText[i]); 
 
    intSumOdd += parseInt(strText[i+1]); 
 
} 
 
intCheck = ((intSumOdd * 3) + intSumEven) % 10; 
 
if (intCheck > 0) { 
 
    \t intCheck = 10 - intCheck; 
 
} 
 
strText += intCheck; 
 
// Converts Code EAN array into string of 1's and 0's 
 
strRaw = "101" 
 
// First six bar sequences 
 
for (i = 1; i < 7; i += 1) { 
 
    strStruct = arrayStructEAN[strText[0]]; 
 
    strRaw += arrayCodeEANBin[strStruct[i-1]][strText[i]]; 
 
} 
 
// Middle sequence 
 
strRaw += "01010"; 
 
// Last six bar sequences, including check digit 
 
for (i = 0; i < 6; i += 1) { 
 
    strRaw += arrayCodeEANBin[2][strText[i+7]]; 
 
} 
 
strRaw += "101"; 
 
} // End EAN-13 
 

 

 
var buttonBarcode = document.getElementById("btnGenBar"); 
 
buttonBarcode.onclick = function() { 
 
strText = document.getElementById("textBarcode").value; 
 
funcEAN(); 
 
document.getElementById("textRaw").value = strRaw; 
 
document.getElementById("textRaw").select(); 
 
}
<head> 
 
<title>EAN-13 Barcodes in vanilla JavaScript</title> 
 
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" > 
 
</head> 
 
<body> 
 
<div id="inputForm"> 
 
    \t Enter Text:&nbsp;<input type="text" id="textBarcode" tabindex=1/> 
 
    \t &nbsp;<input type="button" id="btnGenBar" value="Gen 1's and 0's" tabindex=4/> 
 
</div> 
 
<p></p> 
 
<div id="result"></div> 
 
<p></p> 
 
<textarea rows="3" cols="110" id="textRaw" tabindex=0></textarea> 
 
<script type="text/javascript" src="./SO_JS-EAN-13.js"></script> 
 
</body> 
 
</html>

如果你想看到实际生成的条码,我有一个codepen 。它不添加格式化的文本,但条形码扫描。