# Copyright 2021 Christian Ulrich # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # usage: ./part1 < input import sequtils import strutils type Point = tuple[x: uint16, y: uint16] Line = tuple[start: Point, `end`: Point] Orientation = enum Horizontal, Vertical, Diagonal Area = array[1000, array[1000, uint8]] proc orientation(line: Line): Orientation = if line.start.y == line.end.y: result = Horizontal elif line.start.x == line.end.x: result = Vertical else: result = Diagonal proc add(area: var Area, line: Line) = case line.orientation() of Horizontal: for x in line.start.x .. line.end.x: area[x][line.start.y].inc() of Vertical: for y in line.start.y .. line.end.y: area[line.start.x][y].inc() of Diagonal: assert(false, "not implemented") proc initLine(start, `end`: Point): Line = result = (start: start, `end`: `end`) let orientation = result.orientation() if orientation == Horizontal and result.start.x > result.end.x or orientation == Vertical and result.start.y > result.end.y or orientation == Diagonal and result.start.x > result.end.x: result = (start: result.end, `end`: result.start) proc parsePoint(input: string): Point = let coords = input.split(',', 1) if coords.len() != 2: raise newException(ValueError, "invalid point") result = (x: uint16(parseUint(coords[0])), y: uint16(parseUint(coords[1]))) proc parseLines(): seq[Line] = var line = "" while readLine(stdin, line): if line.len() > 0: let tokens = line.split(' ', 2) if tokens.len() != 3 or tokens[1] != "->": raise newException(ValueError, "invalid line") result.add(initLine(parsePoint(tokens[0]), parsePoint(tokens[2]))) proc countOverlaps(): int = let lines = parseLines() var area: Area for line in lines.filterIt(it.orientation() in [Horizontal, Vertical]): area.add(line) for x in 0 .. high(area): for y in 0 .. high(area[0]): if area[x][y] > 1: result.inc() proc main(): int = try: echo countOverlaps() except Exception as error: echo error.msg result = -1 when isMainModule: quit(main())