From 71313cc4fcd1d766f5b6852d5edf4ba8cf177a01 Mon Sep 17 00:00:00 2001 From: narimiran Date: Sat, 14 Dec 2024 17:34:46 +0100 Subject: [PATCH] day 14 --- clojure/aoc.clj | 13 + clojure/day14.clj | 306 ++++++++++++++++++ clojure/tests/aoc_tests.clj | 5 + clojure/tests/solutions_tests.clj | 3 +- index.md | 1 + inputs/14.txt | 500 ++++++++++++++++++++++++++++++ 6 files changed, 827 insertions(+), 1 deletion(-) create mode 100644 clojure/day14.clj create mode 100644 inputs/14.txt diff --git a/clojure/aoc.clj b/clojure/aoc.clj index 5a38f6f..4a195ee 100644 --- a/clojure/aoc.clj +++ b/clojure/aoc.clj @@ -148,6 +148,18 @@ ([v pred mult] (grid->point-set v pred mult))) +;; Sometimes we need to inspect a grid. +;; With `points->lines`, we create a list of points in each line. +;; +(defn points->lines [points] + (if (map? points) (points->lines (set (keys points))) + (let [x-lim (inc (reduce max (map first points))) + y-lim (inc (reduce max (map second points)))] + (for [y (range y-lim)] + (str/join (for [x (range x-lim)] + (if (points [x y]) + \█ \space))))))) + ;; ### 2D grids @@ -451,6 +463,7 @@ long inc))) +;; (defn ) diff --git a/clojure/day14.clj b/clojure/day14.clj new file mode 100644 index 0000000..017290b --- /dev/null +++ b/clojure/day14.clj @@ -0,0 +1,306 @@ +^{:nextjournal.clerk/visibility {:code :hide :result :hide}} +(ns day14 + {:nextjournal.clerk/auto-expand-results? true + :nextjournal.clerk/toc :collapsed} + (:require + aoc + [quil.core :as q] + [quil.middleware :as m] + [nextjournal.clerk :as clerk])) + + + +;; # Day 14: Restroom Redoubt +;; +;; We're at Easter Bunny Headquarters and one of The Historians needs +;; to use the bathroom. +;; But there are robots guarding the area outside the bathroom. +;; They are moving in predictable straight lines and our task is to find +;; out where will they be after 100 seconds. +;; +;; For each robot we have its current position (at time 0) and its +;; velocity, e.g. `p=2,4 v=2,-3`. +;; +;; NOTE: Since the task changes some parameters between the example and +;; the real input, we won't be solving it for the example. + + + + + +;; ## Input parsing +;; +;; To get a position and a velocity of a robot, we need to extract all +;; integers from an input line. +;; +;; Since the positions will change every second, while the velocities stay +;; constant, we will split them in two separate lists: +;; +(defn parse-data [input] + (let [robots (for [[px py vx vy] (aoc/parse-lines input :ints)] + [[px py] [vx vy]]) + positions (mapv first robots) + velocities (mapv second robots)] + [positions velocities])) + +(def data (parse-data (aoc/read-input 14))) + + +;; The task defines the `width` and `height` of the floor as: +;; +(def width 101) +(def height 103) + + + + +;; ## Part 1 +;; +;; Our task for Part 1 consists of two tasks: +;; - find the positions of robots after 100 seconds +;; - count the number of robots in each quadrant of the floor +;; +;; Moving a robot is easy. +;; We move it `n` times, making sure it is still inside of the floor +;; using `mod` (it works also for negative number): +;; +(defn move-robot + ([pos vel] (move-robot 1 pos vel)) + ([n [px py] [vx vy]] + (let [px' (mod (+ px (* n vx)) width) + py' (mod (+ py (* n vy)) height)] + [px' py']))) + +;; The function has two arities. +;; We can call it with two arguments and get the next position (after 1 second) +;; of a robot, or if we call it with three arguments, we get the position +;; of a robot after `n` seconds. + +(let [p [2 4] + v [2 -3]] + [(move-robot p v) + (move-robot 100 p v)]) + + + + + + +;; For the second task, we can divide the floor in four quadrants like this: +;; ``` +;; ..... ..... +;; .-.-. .+.-. +;; ..... ..... +;; C +;; ..... ..... +;; .-.+. .+.+. +;; ..... ..... +;; ``` +;; +;; `C` is a point in the centre of the floor. +;; Points in the top-left quadrant have both x- and y- positions smaller than `C`. +;; Points in the top-right quadrant have x-position larger than x-position of `C` +;; and lower y-position. Etc. +;; +;; Our task is to count the number of robots in each quadrant. +;; To do that, we will check how many robots satisfy the conditions of +;; a quadrant: +;; +(defn count-in-quadrant [positions [cx cy] [x-cond y-cond]] + (aoc/do-count [[x y] positions + :when (and (x-cond x cx) + (y-cond y cy))])) + + +;; Putting it all together, we get this: +;; +(defn part-1 [[positions velocities]] + (let [positions' (mapv (partial move-robot 100) + positions + velocities) + center [(quot width 2) (quot height 2)] + quad-count (partial count-in-quadrant positions' center) + quad-conds [[< <] ; top-left + [> <] ; top-right + [< >] ; bottom-left + [> >]]] ; bottom-right + (aoc/prod-map quad-count quad-conds))) + + +;; Several things to highlight: +;; - For each robot, we will move it 100 times, so we can partially apply +;; the `move-robot` function by using +;; [`partial`](https://clojuredocs.org/clojure.core/partial). +;; - We are taking the advantage of `map/mapv` taking multiple arguments which are +;; passed in parallel to the function we're calling. +;; Here, the function will receive two arguments: the first element of +;; `positions` and the first element of `velocities`, then the second element +;; of each, etc. +;; - One more usage of `partial`. The only thing that changes when calling +;; the `count-in-quadrant` function are the conditions of each quadrant, +;; so the `positions'` and `center` can be partially applied in advance. +;; - We are interested in a product of numbers in each quadrant, so I'm +;; using the `aoc/prod-map` function, which is an equivalent of +;; `(reduce * (map ...))`. +;; + +(part-1 data) + + + + + + + +;; ## Part 2 +;; +;; We need to find an _Easter_ egg: a _Christmas_ tree. +;; +;; I've seen people use different approaches for this task.\ +;; The one I used is kind of hinted in Part 1, where we're shown some +;; situations where two robots occupy the same space. +;; I've guessed that for an image to appear, every robot should be in its +;; own position, with no overlapping. +;; +;; I'm using the [`distinct?` function](https://clojuredocs.org/clojure.core/distinct_q) +;; to check if all positions are unique. +;; If they are, we've got the solution. +;; If not, we move robots for one second and check again. +;; +(defn part-2 [[positions velocities]] + (reduce + (fn [positions n] + (if (apply distinct? positions) + (reduced n) + (mapv move-robot positions velocities))) + positions + (range))) + + +(part-2 data) + + + + + + + + +;; ## Visualization +;; +;; Let's see how that Christmas tree looks like: +;; +(let [[positions velocities] data + positions' (mapv (partial move-robot 8168) positions velocities) + axes-common {:showgrid false + :zeroline false}] + (clerk/plotly + {:config {:displayModeBar false + :displayLogo false} + :data [{:x (mapv first positions') + :y (mapv second positions') + :mode :markers + :marker {:symbol :square + :size 5}}] + :layout {:xaxis axes-common + :yaxis (merge axes-common {:autorange :reversed}) + :height 700 + :width 700 + :margin {:l 0 :r 0 :t 0 :b 0} + :showlegend false}})) + + + + + + +;; ## Animation +;; +;; Ok, we have a final image, but let's also see how we got there! +;; +;; Here are the last few seconds of robot movements in a slow-motion: +;; +{:nextjournal.clerk/visibility {:result :hide}} + +(defn setup [] + (let [[pos vel] data + step 1/180 + start (- 8168 (* 600 step)) + init-pos (mapv (partial move-robot start) pos vel)] + (q/frame-rate 60) + (q/no-stroke) + {:pos init-pos + :step-size step + :vel vel + :step start})) + +(defn update-state [{:keys [pos vel step step-size] :as state}] + (-> state + (assoc :pos (mapv (partial move-robot step-size) pos vel)) + (update :step + step-size))) + +(defn draw-state [{:keys [pos step]}] + (q/scale 7) + (q/background 15 15 35) + (when (= step 8168) + (q/exit)) + (doseq [[x y] pos] + (q/fill 255 255 102) + (q/rect x y 1 1)) + #_(q/save-frame "/tmp/imgs/day14-###.jpg")) + +(comment + (q/sketch + :size [(* 7 (inc width)) + (* 7 (inc height))] + :setup #'setup + :update #'update-state + :draw #'draw-state + :middleware [m/fun-mode])) + + +;; To make a video from the frames created above, I'm using the following command:\ +;; `ffmpeg -framerate 60 -i /tmp/imgs/day14-%03d.jpg -vf tpad=stop_mode=clone:stop_duration=2 -c:v libx264 -pix_fmt yuv420p imgs/day14.mp4` +;; +;; And the result is: +;; +^{:nextjournal.clerk/visibility {:code :hide + :result :show}} +(clerk/html + [:video {:controls true} + [:source {:src "https://i.imgur.com/AnVFvb8.mp4" + :type "video/mp4"}] + "Your browser does not support the video tag."]) + + + + + + + +;; ## Conclusion +;; +;; The hardest part of today's task was to figure out when/how the image +;; of a Christmas tree would appear.\ +;; The coding part of the task was easy. +;; +;; Today's highlights: +;; - multi-arity functions +;; - `partial`: partially apply a function +;; - `distinct?`: check uniqueness of its arguments + + + + + + + + + + + +^{:nextjournal.clerk/visibility {:code :hide :result :hide}} +(defn -main [input] + (let [data (parse-data input)] + [(part-1 data) + (part-2 data)])) diff --git a/clojure/tests/aoc_tests.clj b/clojure/tests/aoc_tests.clj index 91de232..15ce8c0 100644 --- a/clojure/tests/aoc_tests.clj +++ b/clojure/tests/aoc_tests.clj @@ -90,6 +90,7 @@ (def grid ["#.." "..#" "##."]) +(def grid-print ["█ " " █" "██ "]) (def walls {[0 0] \# , [2 1] \# , [0 2] \# , [1 2] \#}) (deftest vec->map @@ -98,6 +99,10 @@ (deftest vec->set (is (= (set (keys walls)) (aoc/grid->point-set grid #{\#})))) +(deftest points->lines + (is (= grid-print (aoc/points->lines walls))) + (is (= grid-print (aoc/points->lines (set (keys walls)))))) + (deftest graph-traversal (let [walls #{[0 1] [1 1] [1 3] [2 3] [3 0] [3 1] [3 2] [3 3]} with-hole (disj walls [3 1]) diff --git a/clojure/tests/solutions_tests.clj b/clojure/tests/solutions_tests.clj index ac1f7be..0b6b71d 100644 --- a/clojure/tests/solutions_tests.clj +++ b/clojure/tests/solutions_tests.clj @@ -2,7 +2,7 @@ (:require day01 day02 day03 day04 day05 day06 day07 day08 day09 day10 - day11 day12 day13 ;day14 day15 + day11 day12 day13 day14 ;day15 ;; day16 day17 day18 day19 day20 ;; day21 day22 day23 day24 day25 [clojure.test :refer [deftest is run-tests successful?]])) @@ -36,6 +36,7 @@ (check-day 11 [55312 65601038650482] [183435 218279375708592]) (check-day 12 [1930 1206] [1464678 877492]) (check-day 13 [480 875318608908] [27105 101726882250942]) +(check-day 14 nil [226236192 8168]) (let [summary (run-tests)] diff --git a/index.md b/index.md index 86bae0f..259d978 100644 --- a/index.md +++ b/index.md @@ -66,4 +66,5 @@ Task | Notebook | Comment [Day 11: Plutonian Pebbles](https://adventofcode.com/2024/day/11) | [day11.clj](clojure/day11) | Episode VI: Return of the Lanternfish [Day 12: Garden Groups](https://adventofcode.com/2024/day/12) | [day12.clj](clojure/day12) | Turns = sides. [Day 13: Claw Contraption](https://adventofcode.com/2024/day/13) | [day13.clj](clojure/day13) | Kosmo Cramer! +[Day 14: Restroom Redoubt](https://adventofcode.com/2024/day/14) | [day14.clj](clojure/day14) | Christmas egg: Easter tree. diff --git a/inputs/14.txt b/inputs/14.txt new file mode 100644 index 0000000..2f1206e --- /dev/null +++ b/inputs/14.txt @@ -0,0 +1,500 @@ +p=50,78 v=89,45 +p=65,96 v=88,-21 +p=23,63 v=61,46 +p=61,76 v=25,-67 +p=23,90 v=6,91 +p=1,47 v=-17,-9 +p=84,56 v=-73,-24 +p=78,66 v=-20,-76 +p=49,59 v=-22,17 +p=73,95 v=34,-64 +p=99,76 v=67,-40 +p=59,77 v=-49,-4 +p=15,30 v=24,65 +p=89,2 v=-19,-38 +p=28,70 v=93,66 +p=39,33 v=24,-42 +p=14,42 v=-33,-49 +p=68,85 v=-37,-47 +p=91,0 v=-45,12 +p=88,92 v=78,-24 +p=19,63 v=-70,-10 +p=69,4 v=-40,90 +p=61,91 v=64,-11 +p=47,95 v=-77,46 +p=20,10 v=-23,-63 +p=98,82 v=90,96 +p=90,30 v=4,74 +p=0,28 v=-73,8 +p=88,102 v=51,-51 +p=66,29 v=26,1 +p=19,20 v=-61,-15 +p=13,18 v=6,71 +p=12,39 v=67,24 +p=41,67 v=-24,-23 +p=78,10 v=-59,-68 +p=30,2 v=-35,85 +p=86,47 v=-95,53 +p=44,36 v=-69,-89 +p=19,20 v=-87,-95 +p=65,3 v=73,16 +p=95,29 v=43,61 +p=66,50 v=49,-69 +p=28,92 v=-25,19 +p=74,60 v=-6,-98 +p=15,80 v=92,-27 +p=80,12 v=18,-62 +p=72,34 v=19,-65 +p=46,75 v=33,-74 +p=14,100 v=-79,99 +p=94,97 v=74,49 +p=46,13 v=-45,-61 +p=93,39 v=-9,-64 +p=100,45 v=45,-76 +p=62,19 v=-76,85 +p=18,85 v=30,-71 +p=24,68 v=84,-73 +p=31,20 v=-86,-35 +p=76,46 v=-59,77 +p=27,52 v=-95,77 +p=52,81 v=1,59 +p=43,60 v=-71,-38 +p=59,38 v=-6,24 +p=70,65 v=26,-23 +p=11,40 v=60,-33 +p=26,77 v=62,43 +p=24,93 v=99,-51 +p=46,84 v=24,76 +p=48,30 v=58,-87 +p=46,100 v=21,98 +p=24,39 v=-23,84 +p=25,6 v=47,-78 +p=89,73 v=-73,23 +p=4,49 v=-96,14 +p=69,61 v=52,-10 +p=96,68 v=-96,99 +p=17,12 v=-30,75 +p=91,47 v=-98,-87 +p=50,38 v=71,67 +p=68,58 v=-13,17 +p=39,30 v=84,93 +p=93,19 v=-66,98 +p=31,7 v=-8,75 +p=7,81 v=-95,-4 +p=38,43 v=8,-89 +p=24,21 v=-98,3 +p=72,43 v=25,-13 +p=4,98 v=-71,78 +p=79,65 v=-91,-57 +p=49,47 v=-97,23 +p=37,7 v=-15,45 +p=41,74 v=-15,36 +p=58,30 v=-92,71 +p=72,92 v=68,-7 +p=1,79 v=-4,-75 +p=82,99 v=42,6 +p=62,51 v=57,63 +p=10,43 v=48,-74 +p=74,70 v=65,-40 +p=25,35 v=-1,-39 +p=50,71 v=37,68 +p=51,84 v=67,55 +p=71,25 v=-45,-98 +p=47,14 v=-7,28 +p=70,99 v=69,46 +p=21,44 v=-94,-16 +p=52,40 v=-83,-49 +p=76,99 v=-71,63 +p=21,92 v=-32,-34 +p=78,27 v=-85,-55 +p=42,92 v=-76,-61 +p=50,29 v=95,77 +p=72,10 v=65,58 +p=92,48 v=20,-1 +p=42,80 v=55,-98 +p=69,96 v=41,62 +p=68,35 v=-91,-45 +p=18,56 v=-33,37 +p=52,96 v=1,49 +p=22,87 v=53,99 +p=84,31 v=19,41 +p=87,38 v=58,-13 +p=9,13 v=-18,98 +p=40,0 v=-94,-31 +p=71,16 v=-62,76 +p=41,88 v=-46,99 +p=27,97 v=-15,-4 +p=25,54 v=23,-36 +p=61,0 v=-60,-21 +p=28,75 v=41,-79 +p=64,46 v=-8,34 +p=97,26 v=37,74 +p=32,67 v=-48,-93 +p=18,81 v=53,-2 +p=12,101 v=30,-1 +p=80,40 v=-90,-16 +p=48,16 v=-69,61 +p=7,89 v=52,49 +p=93,0 v=-35,-61 +p=24,52 v=31,53 +p=37,67 v=-98,36 +p=92,77 v=28,46 +p=76,59 v=-74,-21 +p=96,63 v=58,57 +p=62,2 v=-68,-68 +p=39,20 v=-39,-25 +p=5,12 v=60,88 +p=75,35 v=-37,88 +p=77,24 v=-52,-13 +p=42,0 v=92,-72 +p=33,61 v=-91,-6 +p=10,74 v=23,-17 +p=6,73 v=37,-54 +p=76,99 v=2,-71 +p=53,20 v=71,91 +p=82,31 v=71,-82 +p=20,87 v=-40,26 +p=52,47 v=-45,-69 +p=32,38 v=43,-55 +p=8,85 v=-56,-77 +p=11,0 v=68,2 +p=40,30 v=-46,-72 +p=26,53 v=27,-43 +p=5,40 v=98,-90 +p=46,4 v=39,-85 +p=15,36 v=-95,87 +p=0,4 v=-49,42 +p=69,11 v=-86,-87 +p=47,47 v=86,-17 +p=95,88 v=-73,26 +p=2,5 v=53,52 +p=92,84 v=63,79 +p=25,0 v=47,-35 +p=83,55 v=-43,-46 +p=95,43 v=-3,40 +p=30,60 v=-79,-27 +p=89,79 v=-39,-80 +p=10,19 v=6,-95 +p=70,64 v=87,10 +p=51,93 v=79,-31 +p=30,82 v=85,16 +p=66,75 v=-51,40 +p=79,70 v=-20,-20 +p=59,60 v=25,63 +p=86,17 v=75,-62 +p=3,62 v=-18,-47 +p=43,20 v=24,91 +p=23,13 v=56,93 +p=32,13 v=71,76 +p=12,10 v=53,-28 +p=20,86 v=-71,-74 +p=91,90 v=-97,-75 +p=76,66 v=-67,83 +p=54,54 v=-84,64 +p=66,70 v=-12,36 +p=30,73 v=54,43 +p=62,22 v=-21,31 +p=11,92 v=-94,76 +p=47,101 v=93,-25 +p=37,21 v=96,19 +p=93,51 v=20,97 +p=46,31 v=-54,61 +p=26,99 v=-64,-11 +p=6,91 v=-55,-90 +p=95,7 v=95,33 +p=1,89 v=5,19 +p=69,24 v=-83,81 +p=82,37 v=-66,-92 +p=20,66 v=-80,-77 +p=45,87 v=-47,-11 +p=19,77 v=8,1 +p=61,12 v=-70,79 +p=59,48 v=14,44 +p=68,70 v=48,-37 +p=77,94 v=42,-84 +p=47,31 v=1,-32 +p=22,1 v=-40,95 +p=41,98 v=-53,16 +p=38,49 v=48,77 +p=21,98 v=-71,12 +p=67,92 v=-13,69 +p=99,99 v=-80,-84 +p=50,18 v=-77,-45 +p=71,35 v=-36,-22 +p=61,65 v=-68,10 +p=96,25 v=56,-21 +p=77,65 v=-20,-40 +p=56,81 v=56,29 +p=81,19 v=-97,-15 +p=31,12 v=-62,-38 +p=92,83 v=51,-4 +p=70,23 v=-44,45 +p=55,61 v=-27,-33 +p=9,48 v=99,40 +p=20,36 v=-80,-52 +p=83,46 v=-35,-59 +p=52,43 v=58,-88 +p=2,88 v=-49,-34 +p=31,99 v=54,59 +p=76,21 v=11,31 +p=5,51 v=-27,35 +p=57,88 v=2,19 +p=86,41 v=-51,60 +p=82,58 v=-98,-96 +p=100,70 v=-38,-85 +p=81,47 v=-10,-30 +p=96,88 v=82,6 +p=24,28 v=62,98 +p=44,71 v=-69,-50 +p=75,11 v=-99,-52 +p=35,80 v=16,-37 +p=2,21 v=-27,84 +p=80,14 v=-43,98 +p=49,76 v=80,21 +p=84,96 v=-82,67 +p=32,79 v=-95,74 +p=35,81 v=-90,-68 +p=47,45 v=-22,-6 +p=69,45 v=41,-83 +p=63,21 v=1,-92 +p=57,1 v=-98,4 +p=34,4 v=-93,-81 +p=46,63 v=-99,47 +p=8,99 v=5,29 +p=32,27 v=54,-42 +p=27,98 v=17,-98 +p=63,22 v=81,98 +p=75,36 v=-86,66 +p=58,5 v=-67,-58 +p=82,20 v=81,-57 +p=82,67 v=81,83 +p=58,58 v=17,-13 +p=18,89 v=14,-21 +p=76,63 v=24,65 +p=38,48 v=-85,-99 +p=17,34 v=45,21 +p=77,70 v=3,-50 +p=56,82 v=17,76 +p=64,97 v=94,-71 +p=16,40 v=37,84 +p=29,96 v=-61,-7 +p=12,79 v=-95,-34 +p=1,72 v=63,38 +p=0,20 v=60,68 +p=43,60 v=-6,40 +p=20,22 v=-17,58 +p=47,49 v=-70,94 +p=12,29 v=-25,-32 +p=22,69 v=-44,-22 +p=44,78 v=31,33 +p=86,50 v=76,-19 +p=0,92 v=35,16 +p=42,8 v=-39,87 +p=30,1 v=14,61 +p=41,57 v=18,-84 +p=83,82 v=-97,36 +p=72,7 v=-78,62 +p=17,4 v=-95,12 +p=15,15 v=60,73 +p=80,79 v=-59,56 +p=49,76 v=-22,-47 +p=58,82 v=26,62 +p=59,101 v=-82,96 +p=78,56 v=-97,-56 +p=19,62 v=85,-44 +p=21,4 v=61,-91 +p=80,66 v=-12,-27 +p=66,17 v=96,28 +p=57,6 v=-45,-38 +p=24,70 v=61,-90 +p=4,12 v=68,-58 +p=27,37 v=15,-59 +p=10,66 v=-33,-50 +p=22,64 v=95,-38 +p=47,44 v=24,-39 +p=96,28 v=75,71 +p=95,20 v=32,30 +p=38,52 v=-89,10 +p=88,94 v=96,-6 +p=93,31 v=-38,18 +p=61,79 v=46,-3 +p=22,27 v=-33,5 +p=77,62 v=81,-60 +p=63,13 v=-94,81 +p=39,49 v=93,89 +p=7,37 v=-2,-89 +p=59,2 v=24,-58 +p=82,32 v=-4,-45 +p=28,55 v=-70,-13 +p=36,49 v=-93,90 +p=16,74 v=53,-20 +p=56,69 v=-84,93 +p=40,25 v=-93,-89 +p=73,60 v=-75,90 +p=28,82 v=-47,-27 +p=35,67 v=-8,-73 +p=76,17 v=68,63 +p=33,43 v=1,37 +p=5,7 v=-52,-34 +p=79,49 v=89,60 +p=78,59 v=20,57 +p=96,31 v=-93,-50 +p=24,88 v=78,-24 +p=12,39 v=37,-16 +p=60,15 v=-21,45 +p=25,17 v=-40,-45 +p=9,63 v=-42,13 +p=46,48 v=8,1 +p=16,85 v=18,48 +p=36,45 v=-41,95 +p=62,88 v=54,6 +p=46,57 v=-99,23 +p=57,67 v=79,-40 +p=88,96 v=4,-51 +p=82,19 v=66,-2 +p=9,73 v=68,-54 +p=66,38 v=9,74 +p=40,68 v=-15,83 +p=97,24 v=-64,-55 +p=52,56 v=-61,7 +p=55,15 v=-53,91 +p=98,66 v=78,-47 +p=27,46 v=-47,4 +p=100,19 v=36,-78 +p=5,9 v=6,82 +p=63,35 v=49,21 +p=40,101 v=8,-14 +p=98,19 v=-74,-28 +p=74,15 v=96,-65 +p=53,47 v=-84,34 +p=48,14 v=94,-98 +p=69,2 v=3,-71 +p=38,10 v=78,35 +p=74,76 v=-90,-60 +p=37,68 v=55,-70 +p=52,78 v=-31,48 +p=6,24 v=-73,24 +p=77,51 v=38,94 +p=73,45 v=-42,-72 +p=52,57 v=67,-51 +p=12,14 v=46,39 +p=6,11 v=65,21 +p=29,37 v=-54,-95 +p=41,24 v=-85,68 +p=78,102 v=96,-24 +p=13,25 v=-16,66 +p=8,53 v=6,90 +p=77,6 v=26,-71 +p=98,45 v=-95,84 +p=56,15 v=-27,-83 +p=82,98 v=-35,52 +p=24,42 v=-8,-29 +p=16,46 v=-78,-53 +p=25,15 v=-34,-54 +p=27,42 v=-11,-13 +p=12,69 v=46,3 +p=74,20 v=43,-9 +p=25,85 v=9,-93 +p=65,99 v=26,-1 +p=90,78 v=74,36 +p=41,6 v=77,-88 +p=85,62 v=-43,93 +p=34,61 v=33,2 +p=0,65 v=75,53 +p=40,30 v=48,-36 +p=31,1 v=47,48 +p=24,100 v=85,99 +p=97,24 v=-76,-67 +p=69,59 v=21,28 +p=82,72 v=7,96 +p=9,10 v=68,25 +p=26,91 v=85,49 +p=35,86 v=39,-24 +p=38,35 v=48,-99 +p=99,61 v=35,-61 +p=79,86 v=-98,99 +p=94,40 v=50,-22 +p=47,101 v=16,72 +p=53,61 v=41,-3 +p=27,101 v=-48,89 +p=28,82 v=15,29 +p=83,58 v=58,-10 +p=40,38 v=-14,-82 +p=52,78 v=79,16 +p=45,15 v=-47,78 +p=72,0 v=81,64 +p=72,51 v=-95,-32 +p=88,67 v=34,70 +p=89,72 v=12,-90 +p=61,31 v=25,-92 +p=68,53 v=48,70 +p=47,53 v=94,10 +p=15,53 v=-72,27 +p=80,8 v=20,-37 +p=28,66 v=-16,-17 +p=77,17 v=99,-11 +p=46,10 v=-9,-66 +p=76,71 v=78,-78 +p=26,62 v=-85,56 +p=87,9 v=-80,-71 +p=67,36 v=-67,18 +p=99,32 v=-80,61 +p=69,87 v=73,89 +p=6,100 v=-72,-48 +p=40,38 v=-93,-92 +p=89,12 v=81,-92 +p=85,97 v=-19,-88 +p=22,100 v=37,-4 +p=11,45 v=-33,34 +p=43,32 v=6,79 +p=47,102 v=-84,52 +p=89,94 v=-84,65 +p=75,14 v=-3,-11 +p=11,65 v=2,46 +p=76,59 v=65,35 +p=65,60 v=-75,40 +p=92,36 v=-32,-9 +p=69,16 v=11,15 +p=62,63 v=32,80 +p=47,50 v=-30,60 +p=13,98 v=-80,-98 +p=32,82 v=23,-74 +p=28,6 v=-92,35 +p=72,89 v=4,3 +p=72,57 v=-3,80 +p=6,44 v=89,-1 +p=33,19 v=31,-78 +p=43,101 v=-39,78 +p=46,51 v=-30,-63 +p=24,37 v=-79,-82 +p=51,46 v=64,44 +p=0,36 v=13,-99 +p=71,6 v=72,9 +p=40,98 v=78,-81 +p=36,33 v=96,-14 +p=63,100 v=95,12 +p=12,42 v=-41,87 +p=66,48 v=-52,77 +p=5,77 v=36,23 +p=94,54 v=80,24 +p=77,71 v=-50,1 +p=81,20 v=89,-85 +p=9,13 v=-95,42 +p=13,78 v=71,20 +p=36,43 v=-21,88 +p=56,94 v=87,69 +p=91,53 v=21,57 +p=80,84 v=-74,-44 +p=19,90 v=-87,96 +p=13,83 v=-63,-51 +p=14,91 v=5,56 +p=23,1 v=-72,-15 +p=50,44 v=71,-73 +p=6,49 v=45,67 +p=4,0 v=-9,-91 +p=70,8 v=-98,45 +p=30,42 v=-78,61 +p=87,74 v=-97,26 +p=35,89 v=92,-32 +p=23,61 v=94,41 +p=87,21 v=-82,28