{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "344"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Load the larger test file and process it using the solution\n",
    "file_path = 'input'\n",
    "\n",
    "def process_large_file(file_path):\n",
    "    with open(file_path, 'r') as file:\n",
    "        lines = [line.rstrip('\\n') for line in file.readlines()]\n",
    "    \n",
    "    height = len(lines)\n",
    "    width = len(lines[0]) if height > 0 else 0\n",
    "\n",
    "    # Identify antennas and their frequencies\n",
    "    freq_map = {}\n",
    "    for y in range(height):\n",
    "        for x in range(width):\n",
    "            c = lines[y][x]\n",
    "            if c != '.':\n",
    "                if c not in freq_map:\n",
    "                    freq_map[c] = []\n",
    "                freq_map[c].append((x, y))\n",
    "\n",
    "    # A set to hold all unique antinode locations\n",
    "    antinodes = set()\n",
    "\n",
    "    # Candidate λ values based on derived equations\n",
    "    lambdas = [2, -1, 1/3, 2/3]\n",
    "\n",
    "    for freq, antennas in freq_map.items():\n",
    "        n = len(antennas)\n",
    "        if n < 2:\n",
    "            continue\n",
    "\n",
    "        for i in range(n):\n",
    "            for j in range(i+1, n):\n",
    "                x1, y1 = antennas[i]\n",
    "                x2, y2 = antennas[j]\n",
    "                dx = x2 - x1\n",
    "                dy = y2 - y1\n",
    "\n",
    "                for lam in lambdas:\n",
    "                    px = x1 + lam * dx\n",
    "                    py = y1 + lam * dy\n",
    "\n",
    "                    if abs(px - round(px)) < 1e-12 and abs(py - round(py)) < 1e-12:\n",
    "                        rx = round(px)\n",
    "                        ry = round(py)\n",
    "\n",
    "                        if 0 <= rx < width and 0 <= ry < height:\n",
    "                            antinodes.add((rx, ry))\n",
    "\n",
    "    # Output the number of unique antinode locations\n",
    "    return len(antinodes)\n",
    "\n",
    "process_large_file(file_path)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1182"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def process_part_two(file_path):\n",
    "    with open(file_path, 'r') as file:\n",
    "        lines = [line.rstrip('\\n') for line in file.readlines()]\n",
    "\n",
    "    height = len(lines)\n",
    "    width = len(lines[0]) if height > 0 else 0\n",
    "\n",
    "    # Identify antennas and their frequencies\n",
    "    freq_map = {}\n",
    "    for y in range(height):\n",
    "        for x in range(width):\n",
    "            c = lines[y][x]\n",
    "            if c != '.':\n",
    "                if c not in freq_map:\n",
    "                    freq_map[c] = []\n",
    "                freq_map[c].append((x, y))\n",
    "\n",
    "    # A set to hold all unique antinode locations\n",
    "    antinodes = set()\n",
    "\n",
    "    # For each frequency group, consider all pairs of antennas\n",
    "    for freq, antennas in freq_map.items():\n",
    "        n = len(antennas)\n",
    "        if n < 2:\n",
    "            continue\n",
    "\n",
    "        for i in range(n):\n",
    "            for j in range(i + 1, n):\n",
    "                x1, y1 = antennas[i]\n",
    "                x2, y2 = antennas[j]\n",
    "\n",
    "                # Calculate the collinearity condition\n",
    "                for x in range(width):\n",
    "                    for y in range(height):\n",
    "                        if (x2 - x1) * (y - y1) == (y2 - y1) * (x - x1):\n",
    "                            antinodes.add((x, y))\n",
    "\n",
    "    # Include the positions of all antennas as antinodes\n",
    "    for freq, antennas in freq_map.items():\n",
    "        for x, y in antennas:\n",
    "            antinodes.add((x, y))\n",
    "\n",
    "    # Return the number of unique antinode locations\n",
    "    return len(antinodes)\n",
    "\n",
    "\n",
    "# Process the larger test file for part two\n",
    "process_part_two('input')\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
