day 17 parts 1 & 2, before code cleaning.
This commit is contained in:
@@ -19,7 +19,7 @@ LIB := aoc_$(shell uname -m)
|
||||
INCDIR := ../include
|
||||
LIBDIR := ../lib
|
||||
LDFLAGS := -L$(LIBDIR)
|
||||
LDLIB := -l$(LIB)
|
||||
LDLIB := -l$(LIB) -lm
|
||||
|
||||
export LD_LIBRARY_PATH = $(LIBDIR)
|
||||
|
||||
|
@@ -105,3 +105,32 @@ If you're going to fire a highly scientific probe out of a super cool probe laun
|
||||
In the above example, using an initial velocity of 6,9 is the best you can do, causing the probe to reach a maximum y position of 45. (Any higher initial y velocity causes the probe to overshoot the target area entirely.)
|
||||
|
||||
Find the initial velocity that causes the probe to reach the highest y position and still eventually be within the target area after any step. What is the highest y position it reaches on this trajectory?
|
||||
|
||||
Your puzzle answer was 2850.
|
||||
--- Part Two ---
|
||||
|
||||
Maybe a fancy trick shot isn't the best idea; after all, you only have one probe, so you had better not miss.
|
||||
|
||||
To get the best idea of what your options are for launching the probe, you need to find every initial velocity that causes the probe to eventually be within the target area after any step.
|
||||
|
||||
In the above example, there are 112 different initial velocity values that meet these criteria:
|
||||
|
||||
23,-10 25,-9 27,-5 29,-6 22,-6 21,-7 9,0 27,-7 24,-5
|
||||
25,-7 26,-6 25,-5 6,8 11,-2 20,-5 29,-10 6,3 28,-7
|
||||
8,0 30,-6 29,-8 20,-10 6,7 6,4 6,1 14,-4 21,-6
|
||||
26,-10 7,-1 7,7 8,-1 21,-9 6,2 20,-7 30,-10 14,-3
|
||||
20,-8 13,-2 7,3 28,-8 29,-9 15,-3 22,-5 26,-8 25,-8
|
||||
25,-6 15,-4 9,-2 15,-2 12,-2 28,-9 12,-3 24,-6 23,-7
|
||||
25,-10 7,8 11,-3 26,-7 7,1 23,-9 6,0 22,-10 27,-6
|
||||
8,1 22,-8 13,-4 7,6 28,-6 11,-4 12,-4 26,-9 7,4
|
||||
24,-10 23,-8 30,-8 7,0 9,-1 10,-1 26,-5 22,-9 6,5
|
||||
7,5 23,-6 28,-10 10,-2 11,-1 20,-9 14,-2 29,-7 13,-3
|
||||
23,-5 24,-8 27,-9 30,-7 28,-5 21,-10 7,9 6,6 21,-5
|
||||
27,-10 7,2 30,-9 21,-8 22,-7 24,-9 20,-6 6,9 29,-5
|
||||
8,-2 27,-8 30,-5 24,-7
|
||||
|
||||
How many distinct initial velocity values cause the probe to be within the target area after any step?
|
||||
|
||||
Your puzzle answer was 1117.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||
|
235
2021/day17/aoc-c.c
Normal file
235
2021/day17/aoc-c.c
Normal file
@@ -0,0 +1,235 @@
|
||||
/* aoc-c.c: Advent of Code 2021, day 16 parts 1 & 2
|
||||
*
|
||||
* Copyright (C) 2021 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this
|
||||
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "pool.h"
|
||||
#include "bits.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef struct vector {
|
||||
s64 x, y;
|
||||
} vector_t;
|
||||
|
||||
#define TMIN 0
|
||||
#define TMAX 1
|
||||
|
||||
struct target {
|
||||
s64 x1, y1;
|
||||
s64 x2, y2;
|
||||
} target;
|
||||
|
||||
struct bounds {
|
||||
s64 dx_min, dx_max;
|
||||
s64 dy_min, dy_max;
|
||||
s64 steps_min;
|
||||
} bounds;
|
||||
|
||||
inline static int hit(s64 x, s64 y)
|
||||
{
|
||||
return x >= target.x1 && y >= target.y1 &&
|
||||
x <= target.x2 && y <= target.y2;
|
||||
}
|
||||
|
||||
/* if we take hypothesis target y is always negative, we can exclude steps
|
||||
* which are still over 0. We reach back zero after 2 x d1 +1 steps for
|
||||
* initial d1 positive (0 otherwise).
|
||||
*/
|
||||
static s64 nth(s64 x, s64 n)
|
||||
{
|
||||
return ((2 * x) + -1 * (n - 1)) * n / 2;
|
||||
}
|
||||
|
||||
static s64 nth_x(s64 x0, s64 n)
|
||||
{
|
||||
return n >= x0? nth(x0, x0): nth(x0, n);
|
||||
//return ((2 * x0) * -(n - 1)) / 2;
|
||||
}
|
||||
|
||||
/* if we take hypothesis target y is always negative, we can exclude steps
|
||||
* which are still over 0. We reach back zero after 2 x d1 +1 steps for
|
||||
* initial d1 positive (0 otherwise).
|
||||
*/
|
||||
static s64 nth_yzero(s64 y0)
|
||||
{
|
||||
return y0 >= 0? y0 * 2 + 1 : 0;
|
||||
}
|
||||
|
||||
/* determine max possible initial dx :
|
||||
* ( dx )(dx + 1) <= minx * 2
|
||||
* <=> dx² + dx - minx * 2 <= 0
|
||||
* solution is x = (-b ± sqrt(b² - 4 * a * c)) / 2 * b, with a = 1, b = 1, c = -2 * minx
|
||||
* => (-1 ± sqrt(1 + 8 * minx)) / 2 <= 0
|
||||
*/
|
||||
static s64 dx_min(s64 xmin)
|
||||
{
|
||||
s64 res = (s64) ((-1) + sqrt((double)(1 + 8 * xmin))) / 2;
|
||||
|
||||
bounds.steps_min = 1;
|
||||
bounds.dx_min = res;
|
||||
|
||||
/*nmin = (s64) (-(1+2*res) +
|
||||
sqrt((float)(1 + 2 * res)
|
||||
* (float)(1 + 2 * res)
|
||||
- 4 * (2 * res - xmin))) / 2;
|
||||
*/
|
||||
//nmin = ((float) 1 + (float)sqrt(1 + 4.0 * xmin)) / (float)2;
|
||||
//printf("xmin=%ld res=%ld nmin=%ld\n", xmin, res, nmin);
|
||||
//nmin = ((float) 1 - (float)sqrt((float)1 + 4.0 * xmin)) / (float)2;
|
||||
//printf("xmin=%ld res=%ld nmin=%ld\n", xmin, res, nmin);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
static s64 max_y_steps(s64 xmax))
|
||||
{
|
||||
return (xmax - 1) / 2;
|
||||
}
|
||||
*/
|
||||
|
||||
/* The highest solution is the solution of:
|
||||
* y1 * (y1 +1) / 2
|
||||
* (we can ignore x velocity, as we can reach any target x1 with x velocity
|
||||
* becoming zero at x1).
|
||||
*/
|
||||
static s64 part1()
|
||||
{
|
||||
return target.y1 * (target.y1 + 1) / 2;
|
||||
}
|
||||
|
||||
static s64 part2()
|
||||
{
|
||||
return target.y1 * (target.y1 + 1) / 2;
|
||||
}
|
||||
|
||||
/* read input
|
||||
*/
|
||||
static int read_input()
|
||||
{
|
||||
if (scanf("target area: x=%ld..%ld, y=%ld..%ld",
|
||||
&target.x1, &target.x2,
|
||||
&target.y1, &target.y2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int opt, part = 1;
|
||||
|
||||
while ((opt = getopt(ac, av, "d:p:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
debug_level_set(atoi(optarg));
|
||||
break;
|
||||
case 'p': /* 1 or 2 */
|
||||
part = atoi(optarg);
|
||||
if (part < 1 || part > 2)
|
||||
return usage(*av);
|
||||
break;
|
||||
default:
|
||||
return usage(*av);
|
||||
}
|
||||
}
|
||||
if (optind < ac)
|
||||
return usage(*av);
|
||||
|
||||
read_input();
|
||||
printf("%s : xmin=%ld ymin=%ld xmax=%ld ymax=%ld part1=%ld\n", *av,
|
||||
target.x1, target.y1, target.x2, target.y2,
|
||||
part1());
|
||||
//s64 dxmin = dx_min(target.x1);
|
||||
|
||||
//for (s64 i = 0; i < 10; ++i) {
|
||||
dx_min(target.x1);
|
||||
bounds.dx_max = target.x2;
|
||||
bounds.dy_min = target.y1;
|
||||
/* y will comme back at zero with same dy as initial one. next step will be d0+1.
|
||||
* If d0+1 is > min target y, we will never reach target.
|
||||
*/
|
||||
bounds.dy_max = -target.y1;
|
||||
|
||||
printf("yzero(%ld) = %ld xmin(%ld) = %ld\n",
|
||||
target.x2, nth_yzero(target.x2),
|
||||
target.x1, dx_min(target.x1));
|
||||
|
||||
/* loop on x initial acceletation */
|
||||
s64 count = 0, besty=0;
|
||||
for (s64 dx = bounds.dx_min; dx <= bounds.dx_max ; ++dx) {
|
||||
/* maybe here make steps for x only, and find all valid steps.
|
||||
* need to know if dx becomes zero and too low
|
||||
*/
|
||||
for (s64 dy = bounds.dy_min; dy <= bounds.dy_max; ++dy) {
|
||||
s64 maxy = 0;
|
||||
for (s64 step = 1; ; step++) {
|
||||
s64 newx = nth_x(dx, step);
|
||||
s64 newy = nth(dy, step);
|
||||
printf("dx=%ld dy=%ld step=%ld x=%ld y=%ld\n", dx, dy, step, newx, newy);
|
||||
if (newx > target.x2) {
|
||||
printf("\tnext y1\n");
|
||||
goto nexty;
|
||||
}
|
||||
if (newy < target.y1) {
|
||||
printf("\t\tnext y2\n");
|
||||
goto nexty;
|
||||
}
|
||||
if (newy > maxy) {
|
||||
maxy = newy;
|
||||
printf("new maxy = %ld\n", maxy);
|
||||
}
|
||||
|
||||
/* need to check if x can join minx */
|
||||
/* need to find max y bound */
|
||||
|
||||
if (hit(newx, newy)) {
|
||||
printf("\tHIT: %ld,%ld\n", newx, newy);
|
||||
count++;
|
||||
if (maxy > besty) {
|
||||
besty = maxy;
|
||||
printf("new besty = %ld\n", besty);
|
||||
}
|
||||
goto nexty;
|
||||
}
|
||||
}
|
||||
nexty:
|
||||
}
|
||||
nextx:
|
||||
}
|
||||
printf("count=%ld besty=%ld\n", count, besty);
|
||||
exit (0);
|
||||
|
||||
/*
|
||||
for (s64 dx = 0; dx <=10; ++dx) {
|
||||
printf("x0=%2ld: ", dx);
|
||||
for (int i = 0; i < 15; ++i)
|
||||
printf(" %d=%ld/%ld", i, nth_x(dx, i), nth(dx, i));
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
printf("%s : res=%ld\n", *av, part == 1? part1(): part2(&target));
|
||||
exit (0);
|
||||
}
|
Reference in New Issue
Block a user