Bitwise and Dict

Allergies
Allergies in Elm
import Dict exposing (Dict)

allergies : Dict Int Allergy
allergies = 
  Dict.fromList 
    [ (1, Eggs)
    , (2, Peanuts)
    , (3, Shellfish)
    , (4, Strawberries)
    , (5, Tomatoes)
    , (6, Chocolate)
    , (7, Pollen)
    , (8, Cats)
    ]

toList : Int -> List Allergy
toList score =
  Dict.foldr (\key value list -> if Bitwise.and (2 ^ (key - 1)) score > 0 then (value :: list) else list) [] allergies

isAllergicTo : Allergy -> Int -> Bool
isAllergicTo allergy score =
  toList score |> List.member allergy

In this approach

This approach explicitly uses the key of the Dict to represent the bit position of an Allergy.

Dict.foldr is used to create a list of Allergy, using Bitwise.and to match the allergy value with the score.

You can see a variation of a Bitwise and Dict solution on Exercism.

When to use this approach?

This code is idiomatic in Elm and is better at embracing the concept of using bit positions in the allergy score to represent a list of Allergy.

isAllergicTo is a slightly expensive operation, iterating the allergies dict once to make a list, and that list is iterated to match the allergy. It is faster than the Bitwise and List approach. However allergies is known and of very small size, so for this exercise we should not try to prematurely optimise.

The compiler does not guarantee that the allergies dict contains all the Allergy types. You can use the type iterator pattern to fix this.

This approach does not guarantee that all bit positions are valid.

This approach doesn't guarantee that all bit positions are sequential. This is potentially useful, and means that if there was ever a need for non sequential bit positions, we could support it, but it does also make it easier to make a mistake if the bit positions are required to be sequential.

13th Dec 2024 · Found it useful?