我正在完成chapter 12 of Real World Haskell。在本章中,作者解释了如何使用EAN13 encoding执行条形码识别。
我从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"
确保我对功能的测试是正确的吗?
非常感谢您提前
答案 0 :(得分:2)
您的实施中有两个错误:
首先,在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
副本。
答案 1 :(得分:1)
您的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) {
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();
}
&#13;
<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">
Enter Text: <input type="text" id="textBarcode" tabindex=1/>
<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>
&#13;
如果您想查看生成的实际条形码,我有一个codepen。它不会添加格式化文本,但条形码会扫描。