{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "{-# LANGUAGE NegativeLiterals #-}\n",
    "{-# LANGUAGE FlexibleContexts #-}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "data ParseState = ParseState\n",
    "                    { total :: Int\n",
    "                    , depth :: Int\n",
    "                    , garbageCount :: Int\n",
    "                    , readingGarbage :: Bool\n",
    "                    , ignoreCharacter :: Bool\n",
    "                    } deriving (Show, Eq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "openGroup ps = ps {depth = depth ps + 1}\n",
    "\n",
    "closeGroup ps = ps {total = total ps + depth ps, depth = depth ps - 1}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "-- parse ps c = if ignoreCharacter ps\n",
    "--              then ps {ignoreCharacter = False}\n",
    "--              else if readingGarbage ps \n",
    "--                   then if c == '>'\n",
    "--                        then ps {readingGarbage = False}\n",
    "--                        else ps\n",
    "--                   else case c of '<' -> ps {readingGarbage = True}\n",
    "--                                  '{' -> openGroup ps\n",
    "--                                  '}' -> closeGroup ps\n",
    "--                                  _   -> ps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "parse ps c \n",
    "    | ignoreCharacter ps = ps {ignoreCharacter = False}\n",
    "    | c == '!' = ps {ignoreCharacter = True}\n",
    "    | readingGarbage ps = if c == '>'\n",
    "                          then ps {readingGarbage = False}\n",
    "                          else ps {garbageCount = garbageCount ps + 1}\n",
    "    | otherwise = \n",
    "        case c of \n",
    "            '<' -> ps {readingGarbage = True}\n",
    "            '{' -> openGroup ps\n",
    "            '}' -> closeGroup ps\n",
    "            _   -> ps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "process = foldl parse ps0\n",
    "    where ps0 = ParseState {total = 0, depth = 0, garbageCount = 0,\n",
    "                    readingGarbage = False, ignoreCharacter = False}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "score \"{{<ab>},{<ab>},{<ab>},{<ab>}}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "score \"{{<!!>},{<!!>},{<!!>},{<!!>}}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "score \"{{<a!>},{<a!>},{<a!>},{<ab>}}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "part1 = total . process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "part2 = garbageCount . process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "main :: IO ()\n",
    "main = do \n",
    "        text <- readFile \"../../data/advent09.txt\"\n",
    "        print $ part1 text\n",
    "        print $ part2 text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11089\n",
       "5288"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "main"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "17"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<random characters>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<<<<>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<{!>}>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<!!>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<!!!>>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "part2 \"<{o\\\"i!a,<{i<a>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "name": "haskell",
   "version": "8.0.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}