Complete day 13
This commit is contained in:
6
pom.xml
6
pom.xml
@@ -34,6 +34,12 @@
|
||||
<artifactId>myClasses</artifactId>
|
||||
<version>1.3.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mattrixwv</groupId>
|
||||
<artifactId>matrix</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -24,6 +24,8 @@ import com.mattrixwv.adventOfCode24.days.Problem21;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem22;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem23;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem24;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem25;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem26;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem3;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem4;
|
||||
import com.mattrixwv.adventOfCode24.days.Problem5;
|
||||
@@ -39,7 +41,7 @@ public class ProblemSelector{
|
||||
protected static final List<Integer> PROBLEM_NUMBERS = List.of(
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24
|
||||
20, 21, 22, 23, 24, 25, 26
|
||||
);
|
||||
|
||||
|
||||
@@ -76,6 +78,8 @@ public class ProblemSelector{
|
||||
case 22 : day = new Problem22(); break;
|
||||
case 23 : day = new Problem23(); break;
|
||||
case 24 : day = new Problem24(); break;
|
||||
case 25 : day = new Problem25(); break;
|
||||
case 26 : day = new Problem26(); break;
|
||||
default: throw new InvalidParameterException();
|
||||
}
|
||||
return day;
|
||||
|
||||
184
src/main/java/com/mattrixwv/adventOfCode24/days/Problem25.java
Normal file
184
src/main/java/com/mattrixwv/adventOfCode24/days/Problem25.java
Normal file
@@ -0,0 +1,184 @@
|
||||
package com.mattrixwv.adventOfCode24.days;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.mattrixwv.Stopwatch;
|
||||
import com.mattrixwv.Triple;
|
||||
|
||||
|
||||
public class Problem25 extends Problem{
|
||||
private static final String inputFileName = "days/Problem25.txt";
|
||||
private static final int A_VALUE = 3;
|
||||
private static final int B_VALUE = 1;
|
||||
private static final int MAX_PRESSES = 100;
|
||||
//games = Triple<A, B, Prize>
|
||||
//A & B = Triple<X, Y, Token>
|
||||
//Prize = Triple<X, Y, smallestValue>
|
||||
private List<Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>>> games;
|
||||
private List<Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>>> results;
|
||||
|
||||
|
||||
public Problem25(){
|
||||
super();
|
||||
description = "What is the sum of the minimum number of tokens that can be used to win each solvable game.";
|
||||
result = "Unresolved";
|
||||
}
|
||||
|
||||
|
||||
public String runSolution(){
|
||||
Stopwatch timer = new Stopwatch();
|
||||
timer.start();
|
||||
|
||||
|
||||
//Read the file
|
||||
games = new ArrayList<>();
|
||||
try(Scanner scanner = new Scanner(this.getClass().getClassLoader().getResourceAsStream(inputFileName))){
|
||||
scanner.useDelimiter("\n\n");
|
||||
while(scanner.hasNext()){
|
||||
String machineSetup = scanner.next();
|
||||
String[] elements = machineSetup.split("\n");
|
||||
int xMovementA = 0;
|
||||
int yMovementA = 0;
|
||||
int xMovementB = 0;
|
||||
int yMovementB = 0;
|
||||
int xLocation = 0;
|
||||
int yLocation = 0;
|
||||
for(String element : elements){
|
||||
if(element.startsWith("Button A")){
|
||||
String buttonAParams = element.split(": ")[1];
|
||||
String xParam = buttonAParams.split(", ")[0];
|
||||
String yParam = buttonAParams.split(", ")[1];
|
||||
xMovementA = Integer.parseInt(xParam.split("X")[1]);
|
||||
yMovementA = Integer.parseInt(yParam.split("Y")[1]);
|
||||
}
|
||||
else if(element.startsWith("Button B")){
|
||||
String buttonAParams = element.split(": ")[1];
|
||||
String xParam = buttonAParams.split(", ")[0];
|
||||
String yParam = buttonAParams.split(", ")[1];
|
||||
xMovementB = Integer.parseInt(xParam.split("X")[1]);
|
||||
yMovementB = Integer.parseInt(yParam.split("Y")[1]);
|
||||
}
|
||||
else if(element.startsWith("Prize")){
|
||||
String prizeParams = element.split(": ")[1];
|
||||
String xParam = prizeParams.split(", ")[0];
|
||||
String yParam = prizeParams.split(", ")[1];
|
||||
xLocation = Integer.parseInt(xParam.split("X=")[1]);
|
||||
yLocation = Integer.parseInt(yParam.split("Y=")[1]);
|
||||
}
|
||||
}
|
||||
Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> game = new Triple<>(new Triple<>(xMovementA, yMovementA, 3), new Triple<>(xMovementB, yMovementB, 1), new Triple<>(xLocation, yLocation, 0));
|
||||
games.add(game);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
results = new ArrayList<>();
|
||||
for(Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> game : games){
|
||||
Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> result = findSmallestValue(game);
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
int sum = 0;
|
||||
for(Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> result : results){
|
||||
sum += result.getC().getC();
|
||||
}
|
||||
|
||||
|
||||
//Save the result
|
||||
timer.stop();
|
||||
result = "The sum of the minimum tokens needed to win each winnable game is " + sum + ".\nIt took " + timer.toString() + " to run this algorithm.";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> findSmallestValue(Triple<Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>, Triple<Integer, Integer, Integer>> game){
|
||||
int smallestTokens = 0;
|
||||
List<Character> buttonPresses = new ArrayList<>();
|
||||
final int xValueA = game.getA().getA();
|
||||
final int yValueA = game.getA().getB();
|
||||
final int xValueB = game.getB().getA();
|
||||
final int yValueB = game.getB().getB();
|
||||
final int xLoc = game.getC().getA();
|
||||
final int yLoc = game.getC().getB();
|
||||
|
||||
|
||||
//Add A's until X or Y are >= the prize or MAX is reached.
|
||||
Triple<Integer, Integer, Integer> curLoc = new Triple<>(0, 0, 1);
|
||||
int aCnt = 0;
|
||||
while((curLoc.getA() < xLoc) && (curLoc.getB() < yLoc) && (aCnt < MAX_PRESSES)){
|
||||
buttonPresses.add('A');
|
||||
++aCnt;
|
||||
curLoc = calcLocation(buttonPresses, xValueA, yValueA, xValueB, yValueB);
|
||||
}
|
||||
//If X and Y match check if the number of tokens is < current solution (or solution is 0) and save if appropriate
|
||||
if((curLoc.getA() == xLoc) && (curLoc.getB() == yLoc)){
|
||||
int currentTokens = calculateTokens(buttonPresses);
|
||||
if((smallestTokens == 0) || (currentTokens < smallestTokens)){
|
||||
smallestTokens = currentTokens;
|
||||
}
|
||||
}
|
||||
//Remove A's and add B's until X or Y are >= the prize or MAX is reached.
|
||||
int bCnt = 0;
|
||||
while(buttonPresses.contains('A')){
|
||||
buttonPresses.remove((Character)'A');
|
||||
--aCnt;
|
||||
curLoc = calcLocation(buttonPresses, xValueA, yValueA, xValueB, yValueB);
|
||||
while((curLoc.getA() < xLoc) && (curLoc.getB() < yLoc) && (bCnt < MAX_PRESSES)){
|
||||
buttonPresses.add('B');
|
||||
++bCnt;
|
||||
curLoc = calcLocation(buttonPresses, xValueA, yValueA, xValueB, yValueB);
|
||||
}
|
||||
//If X and Y match check if the number of tokens is < current solution (or solution is 0) and save if appropriate
|
||||
if((curLoc.getA() == xLoc) && (curLoc.getB() == yLoc)){
|
||||
int currentTokens = calculateTokens(buttonPresses);
|
||||
if((smallestTokens == 0) || (currentTokens < smallestTokens)){
|
||||
smallestTokens = currentTokens;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Return a new object with the new token value
|
||||
return new Triple<>(game.getA(), game.getB(), new Triple<>(game.getC().getA(), game.getC().getB(), smallestTokens));
|
||||
}
|
||||
|
||||
private int calculateTokens(List<Character> buttonPresses){
|
||||
int tokens = 0;
|
||||
for(Character ch : buttonPresses){
|
||||
if(ch == 'A'){
|
||||
tokens += A_VALUE;
|
||||
}
|
||||
else if(ch == 'B'){
|
||||
tokens += B_VALUE;
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private Triple<Integer, Integer, Integer> calcLocation(List<Character> buttonPresses, int xValueA, int yValueA, int xValueB, int yValueB){
|
||||
int xLoc = 0;
|
||||
int yLoc = 0;
|
||||
for(Character ch : buttonPresses){
|
||||
if(ch == 'A'){
|
||||
xLoc += xValueA;
|
||||
yLoc += yValueA;
|
||||
}
|
||||
else if(ch == 'B'){
|
||||
xLoc += xValueB;
|
||||
yLoc += yValueB;
|
||||
}
|
||||
}
|
||||
|
||||
return new Triple<Integer, Integer, Integer>(xLoc, yLoc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
What is the sum of the minimum number of tokens that can be used to win each solvable game.
|
||||
The sum of the minimum tokens needed to win each winnable game is 31623.
|
||||
It took 65.497 milliseconds to run this algorithm.
|
||||
*/
|
||||
137
src/main/java/com/mattrixwv/adventOfCode24/days/Problem26.java
Normal file
137
src/main/java/com/mattrixwv/adventOfCode24/days/Problem26.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package com.mattrixwv.adventOfCode24.days;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.mattrixwv.Stopwatch;
|
||||
import com.mattrixwv.Triple;
|
||||
import com.mattrixwv.matrix.DoubleMatrix;
|
||||
|
||||
|
||||
public class Problem26 extends Problem{
|
||||
private static final String inputFileName = "days/Problem25.txt";
|
||||
private static final int A_VALUE = 3;
|
||||
private static final int B_VALUE = 1;
|
||||
private static final double DOUBLE_MARGIN = 0.001D;
|
||||
//games = Triple<A, B, Prize>
|
||||
//A & B = Triple<X, Y, Token>
|
||||
//Prize = Triple<X, Y, smallestValue>
|
||||
private List<Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>>> games;
|
||||
private List<Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>>> results;
|
||||
|
||||
|
||||
public Problem26(){
|
||||
super();
|
||||
description = "What is the sum of the minimum number of tokens that can be used to win each solvable game.";
|
||||
result = "Unresolved";
|
||||
}
|
||||
|
||||
|
||||
public String runSolution(){
|
||||
Stopwatch timer = new Stopwatch();
|
||||
timer.start();
|
||||
|
||||
|
||||
//Read the file
|
||||
games = new ArrayList<>();
|
||||
try(Scanner scanner = new Scanner(this.getClass().getClassLoader().getResourceAsStream(inputFileName))){
|
||||
scanner.useDelimiter("\n\n");
|
||||
while(scanner.hasNext()){
|
||||
String machineSetup = scanner.next();
|
||||
String[] elements = machineSetup.split("\n");
|
||||
long xMovementA = 0;
|
||||
long yMovementA = 0;
|
||||
long xMovementB = 0;
|
||||
long yMovementB = 0;
|
||||
long xLocation = 0;
|
||||
long yLocation = 0;
|
||||
for(String element : elements){
|
||||
if(element.startsWith("Button A")){
|
||||
String buttonAParams = element.split(": ")[1];
|
||||
String xParam = buttonAParams.split(", ")[0];
|
||||
String yParam = buttonAParams.split(", ")[1];
|
||||
xMovementA = Long.parseLong(xParam.split("X")[1]);
|
||||
yMovementA = Long.parseLong(yParam.split("Y")[1]);
|
||||
}
|
||||
else if(element.startsWith("Button B")){
|
||||
String buttonAParams = element.split(": ")[1];
|
||||
String xParam = buttonAParams.split(", ")[0];
|
||||
String yParam = buttonAParams.split(", ")[1];
|
||||
xMovementB = Long.parseLong(xParam.split("X")[1]);
|
||||
yMovementB = Long.parseLong(yParam.split("Y")[1]);
|
||||
}
|
||||
else if(element.startsWith("Prize")){
|
||||
String prizeParams = element.split(": ")[1];
|
||||
String xParam = prizeParams.split(", ")[0];
|
||||
String yParam = prizeParams.split(", ")[1];
|
||||
xLocation = Long.parseLong(xParam.split("X=")[1]) + 10000000000000L;
|
||||
yLocation = Long.parseLong(yParam.split("Y=")[1]) + 10000000000000L;
|
||||
}
|
||||
}
|
||||
Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> game = new Triple<>(new Triple<>(xMovementA, yMovementA, 3L), new Triple<>(xMovementB, yMovementB, 1L), new Triple<>(xLocation, yLocation, 0L));
|
||||
games.add(game);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
results = new ArrayList<>();
|
||||
for(Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> game : games){
|
||||
Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> result = findSmallestValue(game);
|
||||
if(result.getC().getC() > 0L){
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
long sum = 0;
|
||||
for(Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> result : results){
|
||||
sum += result.getC().getC();
|
||||
}
|
||||
|
||||
|
||||
//Save the result
|
||||
timer.stop();
|
||||
result = "The sum of the minimum tokens needed to win each winnable game is " + sum + ".\nIt took " + timer.toString() + " to run this algorithm.";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> findSmallestValue(Triple<Triple<Long, Long, Long>, Triple<Long, Long, Long>, Triple<Long, Long, Long>> game){
|
||||
long tokens = 0L;
|
||||
final Long xValueA = game.getA().getA();
|
||||
final Long yValueA = game.getA().getB();
|
||||
final Long xValueB = game.getB().getA();
|
||||
final Long yValueB = game.getB().getB();
|
||||
final Long xLoc = game.getC().getA();
|
||||
final Long yLoc = game.getC().getB();
|
||||
final DoubleMatrix Ad = new DoubleMatrix(new double[][]{{xValueA.doubleValue(), xValueB.doubleValue()}, {yValueA.doubleValue(), yValueB.doubleValue()}});
|
||||
final DoubleMatrix bd = new DoubleMatrix(new double[][]{{xLoc.doubleValue()}, {yLoc.doubleValue()}});
|
||||
if(Ad.det() != 0){
|
||||
final DoubleMatrix solution = Ad.inverse().multiply(bd);
|
||||
final Double aTimes = solution.get(0, 0);
|
||||
final Double bTimes = solution.get(1, 0);
|
||||
if(((aTimes % 1 < DOUBLE_MARGIN) || (aTimes % 1 > 1 - DOUBLE_MARGIN)) && ((bTimes % 1 < DOUBLE_MARGIN) || (bTimes % 1 > 1 - DOUBLE_MARGIN))){
|
||||
tokens = calculateTokens(Math.round(solution.get(0, 0)), Math.round(solution.get(1, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Return a new object with the new token value
|
||||
return new Triple<>(game.getA(), game.getB(), new Triple<>(game.getC().getA(), game.getC().getB(), tokens));
|
||||
}
|
||||
|
||||
private long calculateTokens(long aCnt, long bCnt){
|
||||
long tokens = 0;
|
||||
tokens += (aCnt * A_VALUE);
|
||||
tokens += (bCnt * B_VALUE);
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
What is the sum of the minimum number of tokens that can be used to win each solvable game.
|
||||
The sum of the minimum tokens needed to win each winnable game is 93209116744825.
|
||||
It took 22.761 milliseconds to run this algorithm.
|
||||
*/
|
||||
1279
src/main/resources/days/Problem25.txt
Normal file
1279
src/main/resources/days/Problem25.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user