aoc24: add day11
This commit is contained in:
1
dat/24/ex/09.txt
Normal file
1
dat/24/ex/09.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2333133121414131402
|
||||||
1
dat/24/ex/11a.txt
Normal file
1
dat/24/ex/11a.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0 1 10 99 999
|
||||||
1
dat/24/ex/11b.txt
Normal file
1
dat/24/ex/11b.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
125 17
|
||||||
1
dat/24/re/09.txt
Normal file
1
dat/24/re/09.txt
Normal file
File diff suppressed because one or more lines are too long
1
dat/24/re/11.txt
Normal file
1
dat/24/re/11.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
112 1110 163902 0 7656027 83039 9 74
|
||||||
@@ -13,6 +13,7 @@ set(SOURCES
|
|||||||
"day08.cpp"
|
"day08.cpp"
|
||||||
"day09.cpp"
|
"day09.cpp"
|
||||||
"day10.cpp"
|
"day10.cpp"
|
||||||
|
"day11.cpp"
|
||||||
)
|
)
|
||||||
add_library(aoc24 STATIC ${HEADERS} ${SOURCES})
|
add_library(aoc24 STATIC ${HEADERS} ${SOURCES})
|
||||||
target_include_directories(aoc24
|
target_include_directories(aoc24
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ auto entry([[maybe_unused]]std::span<char const*> const& args) -> std::expected<
|
|||||||
case 6: return day06(args);
|
case 6: return day06(args);
|
||||||
case 7: return day07(args);
|
case 7: return day07(args);
|
||||||
case 8: return day08(args);
|
case 8: return day08(args);
|
||||||
// case 9: return day09(args);
|
case 9: return day09(args);
|
||||||
case 10: return day10(args);
|
case 10: return day10(args);
|
||||||
|
case 11: return day11(args);
|
||||||
default:
|
default:
|
||||||
return aoc::make_error(fmt::format("day {}", day), std::errc::not_supported);
|
return aoc::make_error(fmt::format("day {}", day), std::errc::not_supported);
|
||||||
}
|
}
|
||||||
|
|||||||
240
sol/24/day09.cpp
240
sol/24/day09.cpp
@@ -1,7 +1,243 @@
|
|||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
#include "aoc.hpp"
|
#include "aoc.hpp"
|
||||||
#include "aoc/utils.hpp"
|
#include "aoc/utils.hpp"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
||||||
auto aoc24::day09([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
using namespace aoc::types;
|
||||||
return aoc::make_error("", std::errc::not_supported);
|
|
||||||
|
namespace dsk {
|
||||||
|
enum class format : u8 {
|
||||||
|
file,
|
||||||
|
free,
|
||||||
|
};
|
||||||
|
|
||||||
|
class block {
|
||||||
|
public:
|
||||||
|
block(u32 id, dsk::format format) : m_id(id), m_format(format) {}
|
||||||
|
|
||||||
|
auto id() const -> u32 { return m_id; }
|
||||||
|
auto format() const -> dsk::format { return m_format; }
|
||||||
|
auto str() const -> std::string {
|
||||||
|
using namespace std::string_literals;
|
||||||
|
std::string str{"{"};
|
||||||
|
auto const id = m_id == aoc::lim<u32>::max() ? "na" : std::to_string(m_id);
|
||||||
|
str += " id: "s + id + ",";
|
||||||
|
str += " type: "s + std::to_string(u32(m_format)) + ",";
|
||||||
|
str += " }";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u32 m_id;
|
||||||
|
dsk::format m_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
class page_block {
|
||||||
|
public:
|
||||||
|
page_block(u32 id, dsk::format format, u32 size)
|
||||||
|
: m_format(format), m_size(size) {
|
||||||
|
for (u32 i = 0; i < m_size; ++i) {
|
||||||
|
m_blocks.emplace_back(id, format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format() const -> dsk::format { return m_format; }
|
||||||
|
auto size() const -> u32 { return m_size; }
|
||||||
|
auto blocks() const -> std::vector<block> const& { return m_blocks; }
|
||||||
|
|
||||||
|
auto str() const -> std::string {
|
||||||
|
using namespace std::string_literals;
|
||||||
|
std::string str{"page_block {"};
|
||||||
|
str += " size: "s + std::to_string(u32(m_size)) + ",";
|
||||||
|
str += " data: [ "s;
|
||||||
|
for (usize i = 0; i < m_blocks.size(); ++i) {
|
||||||
|
str += fmt::format("{}: ", i);
|
||||||
|
str += m_blocks[i].str();
|
||||||
|
if (i < m_blocks.size() - 1) str += ", ";
|
||||||
|
else if (i == m_blocks.size() - 1) str += " ";
|
||||||
|
}
|
||||||
|
str += "]";
|
||||||
|
str += " }";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
dsk::format m_format;
|
||||||
|
u32 m_size;
|
||||||
|
std::vector<block> m_blocks{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class disk_map {
|
||||||
|
public:
|
||||||
|
disk_map(std::string const& input_str) {
|
||||||
|
m_pages = input_str | std::views::filter([](auto const& c) { return c != '\n'; })
|
||||||
|
| std::views::transform(
|
||||||
|
[i = 0u, id = 0u](auto const& size_char) mutable {
|
||||||
|
auto const f = format(i++ % 2);
|
||||||
|
auto curr_id = id;
|
||||||
|
if (f == format::file)
|
||||||
|
++id;
|
||||||
|
else
|
||||||
|
curr_id = aoc::lim<u32>::max();
|
||||||
|
return page_block(curr_id, f, u32(size_char - '0'));
|
||||||
|
}
|
||||||
|
) | std::ranges::to<std::vector>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pages() const -> std::vector<page_block> {
|
||||||
|
return m_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto to_blocks(std::vector<page_block> const& pages) const -> std::vector<block> {
|
||||||
|
std::vector<block> tmp{};
|
||||||
|
for (usize i = 0; i < pages.size(); ++i) {
|
||||||
|
auto const& blocks = pages[i].blocks();
|
||||||
|
for (usize j = 0; j < blocks.size(); ++j) {
|
||||||
|
tmp.push_back(blocks[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto defrag_block(std::vector<block> const& blocks) -> std::vector<block> {
|
||||||
|
if (blocks.size() == 0) return {};
|
||||||
|
|
||||||
|
std::vector<block> cpy = blocks;
|
||||||
|
usize free_index = 0;
|
||||||
|
usize file_index = cpy.size() - 1;
|
||||||
|
while (free_index < cpy.size()) {
|
||||||
|
free_index = next_free(cpy, free_index);
|
||||||
|
if (free_index >= cpy.size() - 1) break;
|
||||||
|
file_index = next_file(cpy, file_index);
|
||||||
|
if (file_index == 0) break;
|
||||||
|
|
||||||
|
if (free_index >= file_index) break;
|
||||||
|
std::swap(cpy[free_index], cpy[file_index]);
|
||||||
|
}
|
||||||
|
return cpy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto defrag_page(std::vector<page_block> const& pages) -> std::vector<page_block> {
|
||||||
|
// if (pages.size() == 0) return {};
|
||||||
|
//
|
||||||
|
// std::vector<page_block> cpy = pages;
|
||||||
|
// usize free_index = 0;
|
||||||
|
// usize file_index = cpy.size() - 1;
|
||||||
|
// while (free_index < cpy.size()) {
|
||||||
|
// free_index = next_page_free(cpy, free_index);
|
||||||
|
// if (free_index >= cpy.size() - 1) break;
|
||||||
|
// auto const& tmp = cpy[free_index];
|
||||||
|
//
|
||||||
|
// file_index = next_page_file(cpy, file_index, tmp.size());
|
||||||
|
// if (file_index == 0) break;
|
||||||
|
//
|
||||||
|
// if (free_index >= file_index) break;
|
||||||
|
//
|
||||||
|
// fmt::print("{}, {}\n", file_index, free_index);
|
||||||
|
// std::swap(cpy[free_index], cpy[file_index]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return cpy;
|
||||||
|
// }
|
||||||
|
|
||||||
|
auto checksum(std::vector<block> const& blocks) const -> u64 {
|
||||||
|
u64 sum = 0;
|
||||||
|
for (usize i = 0; i < blocks.size(); ++i) {
|
||||||
|
auto const& block = blocks[i];
|
||||||
|
if (block.format() == format::free) break;
|
||||||
|
sum += i * block.id();
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto debug_str(std::vector<block> const& blocks) const -> std::string {
|
||||||
|
using namespace std::string_literals;
|
||||||
|
std::string str{};
|
||||||
|
|
||||||
|
for (usize i = 0; i < blocks.size(); ++i) {
|
||||||
|
auto const& b = blocks[i];
|
||||||
|
if (b.format() == format::file) {
|
||||||
|
str += fmt::format("{}", b.id());
|
||||||
|
if (b.id() > 9) str += "'";
|
||||||
|
} else {
|
||||||
|
str += ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto str() const -> std::string {
|
||||||
|
using namespace std::string_literals;
|
||||||
|
std::string str{"disk_map [\n"};
|
||||||
|
auto const blocks = to_blocks(m_pages);
|
||||||
|
|
||||||
|
for (usize i = 0; i < blocks.size(); ++i) {
|
||||||
|
str += " "s + blocks[i].str();
|
||||||
|
if (i < blocks.size() - 1)
|
||||||
|
str += ",\n";
|
||||||
|
}
|
||||||
|
str += "\n]";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto next_free(std::vector<block> const& blocks, usize start) const -> usize {
|
||||||
|
while (start < blocks.size()) {
|
||||||
|
if (blocks[start].format() == format::free)
|
||||||
|
break;
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto next_file(std::vector<block> const& blocks, usize start) const -> usize {
|
||||||
|
while (start >= 0) {
|
||||||
|
if (blocks[start].format() == format::file)
|
||||||
|
break;
|
||||||
|
--start;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto next_page_free(std::vector<page_block> const& pages, usize start) const -> usize {
|
||||||
|
while (start < pages.size()) {
|
||||||
|
if (pages[start].format() == format::free)
|
||||||
|
break;
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto next_page_file(std::vector<page_block> const& pages, usize start, u32 size) const -> usize {
|
||||||
|
while (start >= 0) {
|
||||||
|
if (pages[start].format() == format::file && pages[start].size() <= size)
|
||||||
|
break;
|
||||||
|
--start;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<page_block> m_pages{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto aoc24::day09([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
||||||
|
auto res = aoc::read_text("./dat/24/ex/09.txt");
|
||||||
|
// auto res = aoc::read_text("./dat/24/re/09.txt");
|
||||||
|
if (!res) return std::unexpected(res.error());
|
||||||
|
auto const txt = *res;
|
||||||
|
|
||||||
|
dsk::disk_map dsk{txt};
|
||||||
|
fmt::print("{}\n", dsk.debug_str(dsk.to_blocks(dsk.pages())));
|
||||||
|
auto const bl = dsk.defrag_block(dsk.to_blocks(dsk.pages()));
|
||||||
|
fmt::print("{}\n", dsk.debug_str(bl));
|
||||||
|
fmt::print("{}\n", dsk.checksum(bl));
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,25 +14,6 @@ namespace lpf {
|
|||||||
using edge_t = std::pair<class node, class node>;
|
using edge_t = std::pair<class node, class node>;
|
||||||
using edges_t = std::vector<edge_t>;
|
using edges_t = std::vector<edge_t>;
|
||||||
|
|
||||||
class node {
|
|
||||||
public:
|
|
||||||
node(i32 id, i32 value, edges_t const& edges)
|
|
||||||
: m_id(id), m_value(value), m_edges(edges) {}
|
|
||||||
|
|
||||||
auto operator==(node const& other) const -> bool {
|
|
||||||
return m_id == other.m_id && m_value == other.m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto id() const -> i32 { return m_id; }
|
|
||||||
auto value() const -> i32 { return m_value; }
|
|
||||||
auto edges() const -> edges_t const& { return m_edges; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
i32 m_id;
|
|
||||||
i32 m_value;
|
|
||||||
edges_t m_edges;
|
|
||||||
};
|
|
||||||
|
|
||||||
class trail {
|
class trail {
|
||||||
public:
|
public:
|
||||||
trail(std::string const& str) {
|
trail(std::string const& str) {
|
||||||
@@ -71,6 +52,32 @@ private:
|
|||||||
usize m_cols;
|
usize m_cols;
|
||||||
std::vector<u8> m_data;
|
std::vector<u8> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class node {
|
||||||
|
public:
|
||||||
|
node(i32 id, i32 value, edges_t const& edges)
|
||||||
|
: m_id(id), m_value(value), m_edges(edges) {}
|
||||||
|
|
||||||
|
auto operator==(node const& other) const -> bool {
|
||||||
|
return m_id == other.m_id && m_value == other.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto id() const -> i32 { return m_id; }
|
||||||
|
auto value() const -> i32 { return m_value; }
|
||||||
|
auto edges() const -> edges_t const& { return m_edges; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 m_id;
|
||||||
|
i32 m_value;
|
||||||
|
edges_t m_edges;
|
||||||
|
};
|
||||||
|
|
||||||
|
class graph {
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto aoc24::day10([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
auto aoc24::day10([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
||||||
|
|||||||
141
sol/24/day11.cpp
Normal file
141
sol/24/day11.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <thread>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "aoc.hpp"
|
||||||
|
#include "aoc/utils.hpp"
|
||||||
|
#include "fmt/format.h"
|
||||||
|
|
||||||
|
using namespace aoc::types;
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
namespace ms {
|
||||||
|
class magic {
|
||||||
|
public:
|
||||||
|
magic(std::string const& str) {
|
||||||
|
m_stones = str | std::views::filter([](auto const& c) { return c != '\n'; })
|
||||||
|
| std::views::split(" "sv)
|
||||||
|
| std::views::transform([](auto const& c_str) {
|
||||||
|
return std::stoll(std::string(std::begin(c_str), std::end(c_str)));
|
||||||
|
}) | std::ranges::to<std::vector>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto blink() -> void {
|
||||||
|
std::vector<i64> stones{};
|
||||||
|
for (usize i = 0; i < m_stones.size(); ++i) {
|
||||||
|
auto const stone = m_stones[i];
|
||||||
|
auto const str = std::to_string(stone);
|
||||||
|
|
||||||
|
if (stone == 0) stones.emplace_back(1);
|
||||||
|
else if (str.length() % 2 == 0) {
|
||||||
|
auto const a = std::stoll(str.substr(0, str.length() / 2));
|
||||||
|
auto const b = std::stoll(str.substr(str.length() / 2));
|
||||||
|
stones.emplace_back(a);
|
||||||
|
stones.emplace_back(b);
|
||||||
|
} else {
|
||||||
|
stones.emplace_back(stone * 2024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stones = stones;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto blink(usize order, std::span<i64*> const& stones) -> void {
|
||||||
|
std::vector<i64> compute{};
|
||||||
|
|
||||||
|
for (usize i = 0; i < stones.size(); ++i) {
|
||||||
|
auto const stone = stones[i];
|
||||||
|
auto const str = std::to_string(*stone);
|
||||||
|
|
||||||
|
if (stone == 0) compute.emplace_back(1);
|
||||||
|
else if (str.length() % 2 == 0) {
|
||||||
|
auto const a = std::stoll(str.substr(0, str.length() / 2));
|
||||||
|
auto const b = std::stoll(str.substr(str.length() / 2));
|
||||||
|
compute.emplace_back(a);
|
||||||
|
compute.emplace_back(b);
|
||||||
|
} else {
|
||||||
|
compute.emplace_back(stone * 2024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mutex.lock();
|
||||||
|
m_tmp.push_back({order, compute});
|
||||||
|
m_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size() const -> usize { return m_stones.size(); }
|
||||||
|
|
||||||
|
auto join(i32 current) -> void {
|
||||||
|
std::sort(std::begin(m_tmp), std::end(m_tmp), [](auto const& a, auto const& b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
m_stones = {};
|
||||||
|
for (usize i = 0; i < m_tmp.size(); ++i) {
|
||||||
|
for (usize j = 0; j < m_tmp[i].second.size(); ++j) {
|
||||||
|
m_stones.push_back(m_tmp[i].second[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_tmp = {};
|
||||||
|
(void)current;
|
||||||
|
|
||||||
|
// fmt::print("join... {}, {}\n", current, m_stones.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data() const -> std::vector<i64> const& { return m_stones; }
|
||||||
|
auto str() const -> std::string {
|
||||||
|
std::string str{};
|
||||||
|
for (usize i = 0; i < m_stones.size(); ++i) {
|
||||||
|
str += std::to_string(m_stones[i]);
|
||||||
|
if (i < m_stones.size() - 1) str += " ";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<i64> m_stones{};
|
||||||
|
std::vector<std::pair<usize, std::vector<i64>>> m_tmp{};
|
||||||
|
std::mutex m_mutex{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto aoc24::day11([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
||||||
|
auto res = aoc::read_text("./dat/24/re/11.txt");
|
||||||
|
// auto res = aoc::read_text("./dat/24/ex/11b.txt");
|
||||||
|
if (!res) return std::unexpected(res.error());
|
||||||
|
auto const txt = *res;
|
||||||
|
|
||||||
|
ms::magic magic{txt};
|
||||||
|
fmt::print("{}\n", magic.str());
|
||||||
|
|
||||||
|
auto const max_threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
|
for (i32 i = 0; i < 75; ++i) {
|
||||||
|
auto const& stones = magic.data();
|
||||||
|
auto chunk_size = stones.size() / max_threads;
|
||||||
|
if (chunk_size == 0) chunk_size = stones.size();
|
||||||
|
|
||||||
|
std::vector<std::thread> threads{};
|
||||||
|
for (usize k = 0; k < max_threads; ++k) {
|
||||||
|
auto start_index = k * chunk_size;
|
||||||
|
auto end_index = std::min((k + 1) * chunk_size, stones.size());
|
||||||
|
if (start_index >= stones.size()) break;
|
||||||
|
|
||||||
|
// Fix: Proper range span construction
|
||||||
|
std::span<i64*> split{stones.data(), static_cast<std::size_t>(2)};
|
||||||
|
threads.emplace_back([&]{ magic.blink(k, split); });
|
||||||
|
}
|
||||||
|
for (usize k = 0; k < threads.size(); ++k) {
|
||||||
|
threads[k].join();
|
||||||
|
}
|
||||||
|
magic.join(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::print("stones: {}\n", magic.size());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user