Skip to content

Commit

Permalink
Solution for 2024, Day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikh Mehdi committed Dec 19, 2024
1 parent 222cda3 commit 7995330
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 7 deletions.
90 changes: 90 additions & 0 deletions 2024/src/main/java/me/zodac/advent/Day19.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* BSD Zero Clause License
*
* Copyright (c) 2021-2024 zodac.me
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package me.zodac.advent;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Solution for 2024, Day 19.
*
* @see <a href="https://adventofcode.com/2024/day/19">[2024: 19] Linen Layout</a>
*/
public final class Day19 {

private Day19() {

}

/**
* Given a {@link List} of values (representing a final 'design'), and a {@link List} of keys (representing a single 'towel' which is part of the
* full design), find which values have a possible valid combination from the provided keys.
*
* @param towels the input keys (towels to make the designs)
* @param finalDesigns the input values (designs)
* @return the number of valid designs that can be created
*/
public static long countPossibleDesigns(final List<String> towels, final List<String> finalDesigns) {
return finalDesigns
.stream()
.filter(design -> hasDesignAnyValidCombinations(design, towels))
.count();
}

/**
* Given a {@link List} of values (representing a final 'design'), and a {@link List} of keys (representing a single 'towel' which is part of the
* full design), find which values have a possible valid combination from the provided keys. For each of these, find the total number of possible
* combinations of towels that can make the design.
*
* @param towels the input keys (towels to make the designs)
* @param finalDesigns the input values (designs)
* @return the total number of towel combinations to create valid designs
*/
public static long countAllCombinationsOfValidDesigns(final List<String> towels, final List<String> finalDesigns) {
return finalDesigns
.stream()
.filter(design -> hasDesignAnyValidCombinations(design, towels))
.mapToLong(design -> countCombinationsForDesign(design, towels, new HashMap<>()))
.sum();
}

private static boolean hasDesignAnyValidCombinations(final String value, final List<String> keys) {
return keys
.stream()
.anyMatch(key -> value.equals(key) || (value.startsWith(key) && hasDesignAnyValidCombinations(value.substring(key.length()), keys)));
}

private static long countCombinationsForDesign(final String design, final List<String> towels, final Map<String, Long> cache) {
if (cache.containsKey(design)) {
return cache.get(design);
}

long numberOfCombinations = 0L;
for (final String towel : towels) {
if (design.equals(towel)) {
numberOfCombinations++;
} else if (design.startsWith(towel)) {
numberOfCombinations += countCombinationsForDesign(design.substring(towel.length()), towels, cache);
}
}

cache.put(design, numberOfCombinations);
return numberOfCombinations;
}
}
92 changes: 92 additions & 0 deletions 2024/src/test/java/me/zodac/advent/Day19Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* BSD Zero Clause License
*
* Copyright (c) 2021-2024 zodac.me
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package me.zodac.advent;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import me.zodac.advent.input.InputReader;
import org.junit.jupiter.api.Test;

/**
* Tests to verify answers for {@link Day19}.
*/
class Day19Test {

private static final String INPUT_FILENAME = "day19.txt";

@Test
void example() {
final List<List<String>> valuesRaw = InputReader
.forExample(INPUT_FILENAME)
.asStrings()
.grouped()
.byDelimiter(String::isBlank);

final List<String> keys = parseKeys(valuesRaw);
final List<String> values = valuesRaw.getLast();

final long part1Result = Day19.countPossibleDesigns(keys, values);
assertThat(part1Result)
.isEqualTo(6L);

final long part2Result = Day19.countAllCombinationsOfValidDesigns(keys, values);
assertThat(part2Result)
.isEqualTo(16L);
}

@Test
void part1() {
final List<List<String>> valuesRaw = InputReader
.forPuzzle(INPUT_FILENAME)
.asStrings()
.grouped()
.byDelimiter(String::isBlank);

final List<String> keys = parseKeys(valuesRaw);
final List<String> values = valuesRaw.getLast();

final long part1Result = Day19.countPossibleDesigns(keys, values);
assertThat(part1Result)
.isEqualTo(263L);
}

@Test
void part2() {
final List<List<String>> valuesRaw = InputReader
.forPuzzle(INPUT_FILENAME)
.asStrings()
.grouped()
.byDelimiter(String::isBlank);

final List<String> keys = parseKeys(valuesRaw);
final List<String> values = valuesRaw.getLast();

final long part2Result = Day19.countAllCombinationsOfValidDesigns(keys, values);
assertThat(part2Result)
.isEqualTo(723_524_534_506_343L);
}

private static List<String> parseKeys(List<List<String>> valuesRaw) {
final String[] keys = valuesRaw.getFirst().getFirst().split(", ");
return new ArrayList<>(Arrays.asList(keys)).stream().sorted(Comparator.comparingInt(String::length).reversed()).toList();
}
}
10 changes: 10 additions & 0 deletions 2024/src/test/resources/day19.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
r, wr, b, g, bwu, rb, gb, br

brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Advent Of Code: Java Edition

![2024](https://img.shields.io/badge/2024%20⭐-30-yellow)
![2024](https://img.shields.io/badge/2024%20⭐-32-yellow)
![2023](https://img.shields.io/badge/2023%20⭐-32-yellow)
![2022](https://img.shields.io/badge/2022%20⭐-28-yellow)
![2021](https://img.shields.io/badge/2021%20⭐-19-orange)
Expand Down Expand Up @@ -76,6 +76,7 @@ The source code is released under the [BSD Zero Clause License](https://opensour
| [Day 16](https://adventofcode.com/2024/day/16) | | |
| [Day 17](https://adventofcode.com/2024/day/17) | | |
| [Day 18](https://adventofcode.com/2024/day/18) | 22,587 ⭐ | 21,997 ⭐ |
| [Day 19](https://adventofcode.com/2024/day/19) | 7,778 ⭐ | 6,372 ⭐ |

</details>

Expand Down
2 changes: 1 addition & 1 deletion advent-of-code-inputs
10 changes: 5 additions & 5 deletions create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ function main() {
fi

echo "${output}" | head -n -1 > "./advent-of-code-inputs/${year}/day${day_long}.txt" || exit 1
cd ./advent-of-code-inputs || exit 1
git add "${year}/day${day_long}.txt"
git commit --quiet -m "Adding input for ${year}, Day ${day_long}"
git push origin HEAD:main --quiet
cd .. || exit 1
# cd ./advent-of-code-inputs || exit 1
# git add "${year}/day${day_long}.txt"
# git commit --quiet -m "Adding input for ${year}, Day ${day_long}"
# git push origin HEAD:main --quiet
# cd .. || exit 1
fi

# Example input file
Expand Down

0 comments on commit 7995330

Please sign in to comment.