Search code examples
haskelltestingencodingbarcodedecoding

EAN13 Barcode Encoding in Haskell: How to test it?


I am completing the chapter 12 of Real World Haskell. In this chapter, the author explains how to perform Barcode Recognition with EAN13 encoding.

I reproduced the most of the code from the book snippets into my repo and when I finally arrived to check if my over 300 rows of code where working as expected, I got a bad news:

-- 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

Since the book was published, I noticed the some type signatures have changed such as:

$ 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

I tried to reproduce in GHCi every example and, except from the last one, I always get the same result as the book.

Has anyone covered that topic from this book?

The author is not explaining every single line of code and, in particular, the input variable is not defined anywhere let input = zip (runLengths $ encodeEAN13 "9780132114677") (cycle [Zero, One])

Some EAN13 encoded barcode for testing?

In case no one knows this book, would you have some sample of EAN13 encoded barcodes such as:

*Main M> encodeEAN13 "9780132114677"
"101011101100010010100111001100101000010101011011001100110110011010111001010000100010010001001010000101"

To make sure that my tests on functions are correct?

Thank you very much in advance


Solution

  • You have two bugs in your implementation:

    First, in encodeDigits, you've written splitAt 5 when it should be splitAt 6. This fixes the encoding bug noted by @Brian Anderson.

    Second, in bestScores, you've written:

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

    when you should have written:

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

    This fixes your decoding bug.

    I wish I could say I used my superhuman debugging skills to find these bugs, but I just happened to have my own copy of Barcode.hs around from when I did Chapter 12 myself a few years ago.