-
-
Save vvvvalvalval/524f83040f697d8d7741eeed0a135d9d to your computer and use it in GitHub Desktop.
Advent of Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(def inputs-for-the-day (clojure.string/split-lines (slurp "src/advent_of_code/day6/input.txt"))) | |
(def sample ["1, 1" | |
"1, 6" | |
"8, 3" | |
"3, 4" | |
"5, 5" | |
"8, 9"]) | |
(defn parse-line [line] | |
(let [[_ x y] (re-matches #"(\d+), (\d+)" line)] | |
[(read-string x) (read-string y)])) | |
;; assign an ID (starting from 1) to each points | |
(defn parse-points [input] | |
(->> input | |
(map parse-line) | |
(map #(zipmap [:label :coord] [%1 %2]) (range 1 (inc (count input)))))) | |
(defn manhattan-distance [a b] | |
(let [;; destructuring for readability | |
[xa ya] a | |
[xb yb] b] | |
(+ (if (< xa xb) (- xb xa) (- xa xb)) | |
(if (< ya yb) (- yb ya) (- ya yb))))) | |
(defn grouped-by-dist [coord points] | |
(group-by #(manhattan-distance coord (:coord %)) points)) | |
(defn closests-point [coord points] | |
(->> points | |
(grouped-by-dist coord) | |
(sort-by key) | |
first | |
second)) | |
(def distance-equality 0) | |
(defn closest-point [coord points] | |
(let [closests (closests-point coord points)] | |
(if (= 1 (count closests)) | |
(:label (first closests)) ;; return the ID of the point | |
distance-equality))) ;; return distance equality if more closest dist equality | |
(defn line-of-closest-points [y range-x points] | |
(map #(closest-point [% y] points) range-x)) | |
(defn areas-with-closest-distances [points] | |
(let [max-x (apply max (map first (map :coord points))) | |
range-x (range (inc (inc max-x))) | |
max-y (apply max (map second (map :coord points))) | |
range-y (range (inc (inc max-y)))] | |
(map #(line-of-closest-points % range-x points) range-y))) | |
;; list of distance equality coord and points which are on the border (so infinite areas) | |
(defn areas-to-filter [areas] | |
;; using a threading macros for readability, | |
;; and transducers for performance | |
(-> #{distance-equality} | |
(into (first areas)) | |
(into (last areas)) | |
(into (map first) areas) | |
(into (map last) areas))) | |
(defn filter-areas [areas] | |
(let [areas-to-filter (areas-to-filter areas)] | |
(sequence | |
;; using a transducer for performance | |
(comp | |
cat | |
(remove areas-to-filter)) ;; NOTE: a set already acts like a function, and remove is the negation of filter | |
areas))) | |
(defn part1 [input] | |
(->> (parse-points input) | |
areas-with-closest-distances | |
filter-areas | |
frequencies | |
vals | |
(apply max))) | |
(defn display-line [line] | |
(apply str (interpose " " line))) | |
(defn display-areas [input] | |
(let [points (parse-points input) | |
areas (areas-with-closest-distances points)] | |
;; for side-effects, you should use run! instead of map | |
(run! #(println (display-line %)) areas))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File | |
import java.util.* | |
import java.util.concurrent.atomic.AtomicInteger | |
data class Coordinate(val x: Int, val y: Int) | |
data class Point(val label: Int, val coordinate: Coordinate) | |
data class area(val associatedToPoint: Point, val size: Int = 0) | |
var seqId = AtomicInteger(1) | |
fun parseLine(line: String): Point { | |
val s = line.split(",") | |
val coord = Coordinate(s[0].trim().toInt(), s[1].trim().toInt()) | |
return Point(seqId.getAndIncrement(), coord) | |
} | |
fun parseFile(filename: String): List<Point> { | |
return File(filename).readLines().map { parseLine(it) } | |
} | |
fun manhattanDistance(a: Coordinate, b: Coordinate): Int { | |
val x = if (a.x < b.x) b.x - a.x else a.x - b.x | |
val y = if (a.y < b.y) b.y - a.y else a.y - b.y | |
return x + y | |
} | |
fun findClosestPoint(coordinate: Coordinate, points: List<Point>): Int { | |
val sorted = points.groupBy { manhattanDistance(coordinate, it.coordinate) }.toSortedMap() | |
val closest: List<Point> = sorted[sorted.firstKey()] ?: emptyList() | |
if (closest.size == 1) { | |
return closest.first().label | |
} else { | |
return 0 | |
} | |
} | |
fun buildAreasOfClosestPoints(points: List<Point>): List<List<Int>> { | |
val maxX = points.map { it.coordinate.x }.max()!! + 1 | |
val maxY = points.map { it.coordinate.x }.max()!! + 1 | |
return (0..maxY).map { y -> | |
(0..maxX).map { x -> | |
findClosestPoint(Coordinate(x, y), points) | |
} | |
} | |
} | |
fun areaToFilter(areas: List<List<Int>>) : Set<Int> { | |
return setOf(0) | |
.plus(areas.first()) | |
.plus(areas.last()) | |
.plus(areas.map { it.first() }) | |
.plus(areas.map { it.last() }) | |
} | |
fun biggestArea(points: List<Point>) : Int { | |
val areas = buildAreasOfClosestPoints(points) | |
val areasToFilter = areaToFilter(areas) | |
return areas | |
.flatten() | |
.filter { !areasToFilter.contains(it) } | |
.groupBy { it } | |
.values | |
.map { it.size } | |
.max()!! | |
} | |
fun main(args: Array<String>) { | |
//parseFile("day6.txt").forEach { println(it) } | |
val points = parseFile("day6.txt") | |
println("Biggest area : " + biggestArea(points)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment