import qualified Data.Set as Set import qualified Data.List as List n = 12 additionInZn a b = (a+b) `mod` n multiplicationInZn a b = (a*b) `mod` n theta n = n `mod` 4 q = quotientRing additionInZn [0..n-1] (kernel theta [0..n-1]) multiplicationTable = setwiseOperationTable q multiplicationInZn additionTable = setwiseOperationTable q additionInZn main = putStrLn $ (latexTable additionTable q q latexRepresentationOfList "+") ++ "\n\n" ++ (latexTable multiplicationTable q q latexRepresentationOfList "*") join j s = concat $ List.intersperse j s concatTimes n s = concatMap (\c -> s) [1..n] latexRepresentationOfList s = "\\{" ++ (join ", " $ map show s) ++ "\\}" latexTable rows header left representation operation = "\\begin{tabular}{r|" ++ (concatTimes (length header) "r") ++ "}\n" ++ operation ++ "\n& " ++ (join "\n& " $ map representation header) ++ "\n\\\\ \\hline\n" ++ body ++ "\\end{tabular}" where body = flip concatMap (zip left rows) (\(leftColumn, columns) -> representation leftColumn ++ "\n" ++ flip concatMap columns (\c -> "& " ++ representation c ++ "\n") ++ "\\\\\n") uniqueSorted l = Set.toAscList $ Set.fromList l cosetCombination a b operation = uniqueSorted [operation i j | i<-a, j<-b] setwiseOperationTable ring operation = [[cosetCombination x y operation | x <- ring ] | y <- ring] quotientRing addition ring ideal = uniqueSorted [uniqueSorted [addition i r | i<-ideal] | r<-ring] kernel f domain = [d | d<- domain, f(d) == 0]