Skip to content

Instantly share code, notes, and snippets.

@mattpodwysocki
Created April 17, 2009 01:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattpodwysocki/96799 to your computer and use it in GitHub Desktop.
Save mattpodwysocki/96799 to your computer and use it in GitHub Desktop.
import Data.Map((!), intersection, fromList, keys, Map(..))
import Data.List(sort)
type Preferences = Map String (Map String Double)
type Similarity = Preferences -> String -> String -> Double
critics :: Preferences
critics = fromList [
("Lisa Rose", fromList
[("Lady in the Water" , 2.5),
("Snakes on a Plane" , 3.5),
("Just My Luck" , 3.0),
("Superman Returns" , 3.5),
("You, Me and Dupree", 2.5),
("The Night Listener", 3.0)
]),
("Gene Seymour", fromList
[("Lady in the Water" , 3.0),
("Snakes on a Plane" , 3.5),
("Just My Luck" , 1.5),
("Superman Returns" , 5.0),
("The Night Listener", 3.0),
("You, Me and Dupree", 3.5)
]),
("Michael Phillips", fromList
[("Lady in the Water" , 2.5),
("Snakes on a Plane" , 3.0),
("Superman Returns" , 3.5),
("The Night Listener", 4.0)
]),
("Claudia Puig", fromList
[("Snakes on a Plane" , 3.5),
("Just My Luck" , 3.0),
("The Night Listener", 4.5),
("Superman Returns" , 4.0),
("You, Me and Dupree", 2.5)
]),
("Mick LaSalle", fromList
[("Lady in the Water" , 3.0),
("Snakes on a Plane" , 4.0),
("Just My Luck" , 2.0),
("Superman Returns" , 3.0),
("The Night Listener", 3.0),
("You, Me and Dupree", 2.0)
]),
("Jack Matthews", fromList
[("Lady in the Water" , 3.0),
("Snakes on a Plane" , 4.0),
("The Night Listener", 3.0),
("Superman Returns" , 5.0),
("You, Me and Dupree", 3.5)
]),
("Matt", fromList
[("Snakes on a Plane" ,4.5),
("You, Me and Dupree",1.0),
("Superman Returns" ,4.0)
])
]
sim_distance :: Preferences -> String -> String -> Double
sim_distance prefs p1 p2 =
let si = keys $ intersection (prefs ! p1) (prefs ! p2)
in case si of
[] -> 0
otherwise ->
1 / (1 + sqrt sum_of_squares)
where sum_of_squares =
sum [((prefs ! p1 ! item) - (prefs ! p2 ! item)) ^ 2 | item <- si]
sim_pearson :: Preferences -> String -> String -> Double
sim_pearson prefs p1 p2 =
let si = keys $ intersection (prefs ! p1) (prefs ! p2)
n = fromIntegral $ length si
in case n of
0 -> 0
otherwise ->
let sum1 = sum [prefs ! p1 ! item | item <- si]
sum2 = sum [prefs ! p2 ! item | item <- si]
sum1Sq = sum [prefs ! p1 ! item ^ 2 | item <- si]
sum2Sq = sum [prefs ! p2 ! item ^ 2 | item <- si]
pSum = sum [(prefs ! p1 ! item) * (prefs ! p2 ! item) | item <- si]
num = pSum - (sum1 * sum2 / n)
den = sqrt ((sum1Sq - sum1 ^ 2 / n) *
(sum2Sq - sum2 ^ 2 / n))
in case den of
0 -> 0
otherwise -> num / den
topMatches :: Preferences -> String -> Int -> Similarity -> [(Double, String)]
topMatches prefs person n similarity =
take n $
reverse $
sort [(similarity prefs person other, other) |
other <- keys prefs,
other /= person]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment