Skip to content

Commit ae13701

Browse files
committed
Compile instructions for Day 17 Part 2
1 parent 5f4b48e commit ae13701

File tree

4 files changed

+500
-90
lines changed

4 files changed

+500
-90
lines changed

aoclib/aocio.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,28 @@ static inline std::optional<int64_t> parse_num_i64(const std::string& str, bool
189189
return n;
190190
}
191191

192+
static inline std::optional<uint64_t> parse_num_u64(const std::string& str, bool strict = false)
193+
{
194+
size_t num_read = 0;
195+
uint64_t n;
196+
try {
197+
n = std::stoull(str, &num_read);
198+
} catch (const std::invalid_argument& err) {
199+
return {};
200+
} catch (const std::out_of_range& err) {
201+
std::cerr << "parse_num_u64: the converted value would fall out of the range of uint64_t";
202+
return {};
203+
}
204+
205+
if (strict && num_read != str.size()) {
206+
return {};
207+
}
208+
if (num_read == 0) {
209+
return {};
210+
}
211+
return n;
212+
}
213+
192214
static inline std::optional<int> parse_digit(char c)
193215
{
194216
int digit = static_cast<int>(c) - '0';
@@ -507,6 +529,15 @@ class RDParser
507529
}
508530
return num;
509531
}
532+
template<>
533+
std::optional<uint64_t> accept_int<uint64_t>()
534+
{
535+
const auto num = aocio::parse_num_u64(std::string{_current_token}, true);
536+
if (num.has_value()) {
537+
next_token();
538+
}
539+
return num;
540+
}
510541

511542
template<class IntT> IntT require_int();
512543
template<>
@@ -533,6 +564,18 @@ class RDParser
533564
const std::string info = "on line " + std::to_string(line + 1) + " (col " + std::to_string(col - current_token().size()) + "):\n'" + offending_line + "'";
534565
throw std::runtime_error("Parser::require_int: Required int token does not match actual token\n'" + std::string{current_token()} + "'\n" + info);
535566
}
567+
template<>
568+
uint64_t require_int<uint64_t>()
569+
{
570+
const auto num = aocio::parse_num_u64(std::string{_current_token}, true);
571+
if (num.has_value()) {
572+
next_token();
573+
return num.value();
574+
}
575+
const std::string offending_line = line < lines.size() ? lines.at(line) : "";
576+
const std::string info = "on line " + std::to_string(line + 1) + " (col " + std::to_string(col - current_token().size()) + "):\n'" + offending_line + "'";
577+
throw std::runtime_error("Parser::require_int: Required int token does not match actual token\n'" + std::string{current_token()} + "'\n" + info);
578+
}
536579

537580
bool accept_newline()
538581
{

aoclib/parallel.hpp

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22
#include <thread>
3+
#include <future>
4+
#include <chrono>
35
#include <iostream>
46
#include <concepts>
57
#include <utility>
@@ -142,4 +144,120 @@ T parallel_transform_reduce(int num_threads, ForwardIt first, ForwardIt last, T
142144
{
143145
return parallel_transform_reduce(first, last, init, reduce, transform, num_threads);
144146
}
145-
}
147+
148+
// template<class ForwardIt, class WorkFn, class WorkFnResultOptional>
149+
// void parallel_search_first(ForwardIt begin, ForwardIt end, WorkFn work_fn, std::chrono::milliseconds busy_loop_sleep = 0)
150+
// {
151+
// std::promise<void> done_promise;
152+
// std::shared_future<void> done_future = done_promise.get_future();
153+
154+
// const auto worker = [done_future](ForwardIt begin, ForwardIt end, std::promise<WorkFnResultOptional> result_promise)
155+
// {
156+
// for (auto it = begin; it != end; ++it) {
157+
// if (done_future.wait_for(std::chrono::nanoseconds{0}) == std::future_status::ready) {
158+
// return;
159+
// }
160+
// WorkFnResultOptional result = work_fn(*begin);
161+
// if (result.has_value()) {
162+
// result_promise.set_value(result);
163+
// return;
164+
// }
165+
// }
166+
// result_promise.set_exception(WorkFnResultOptional{});
167+
// };
168+
169+
// if (num_threads > num_elems) {
170+
// num_threads = num_elems;
171+
// }
172+
173+
// const ptrdiff_t elems_per_thread = num_elems / num_threads;
174+
// ptrdiff_t remainder = num_elems % num_threads;
175+
// assert(elems_per_thread > 0 || remainder > 0);
176+
// assert((elems_per_thread * num_threads + remainder) == num_elems);
177+
178+
// std::vector<std::thread> workers;
179+
// std::vector<std::future<WorkFnResultOptional>> worker_futures;
180+
// std::vector<std::future<WorkFnResultOptional>> worker_results;
181+
182+
// for (auto start_it = first; start_it != last;) {
183+
// assert(std::ssize(workers) < num_threads);
184+
// ptrdiff_t increment = elems_per_thread;
185+
// if (remainder) {
186+
// ++increment;
187+
// --remainder;
188+
// }
189+
// assert(increment > 0);
190+
191+
// const auto end_it = std::next(start_it, increment);
192+
193+
// std::promise<WorkFnResultOptional> worker_promise;
194+
// worker_futures.push_back(worker_promise.get_future());
195+
// assert(worker_futures.back().valid());
196+
// workers.push_back(std::thread(worker, start_it, end_it, std::move(worker_promise)));
197+
198+
// start_it = end_it;
199+
// }
200+
// assert(std::ssize(workers) == num_threads);
201+
// assert(remainder == 0);
202+
// assert(worker_futures.size() == workers.size());
203+
204+
// const auto is_first_result = [&worker_futures, &worker_results](size_t idx)
205+
// {
206+
// const auto& future = worker_futures.at(i);
207+
// bool is_first_res = true;
208+
// for (int j = 0; j < i; ++j) {
209+
// if (worker_futures.at(j).valid() || worker_results.at(j).has_value()) {
210+
// is_first_res = false;
211+
// break;
212+
// }
213+
// }
214+
// return is_first_res;
215+
// }
216+
217+
// WorkFnResultOptional result = {};
218+
// for (;;) {
219+
// size_t not_found = 0;
220+
// for (size_t i = 0; i < worker_futures.size(); ++i) {
221+
// auto& wrk_future = worker_futures.at(i);
222+
// auto& wrk_result = worker_results.at(i);
223+
224+
// const bool is_first_res = is_first_result(i);
225+
226+
// const auto is_done = [is_first_res, &wrk_future, &result, &wrk_result, &not_found, &done_promise]() -> bool {
227+
// if (!wrk_results.has_value() || !is_first_res) {
228+
// ++not_found;
229+
// return false;
230+
// } else {
231+
// result = wrk_result;
232+
// done_promise.set_value(); // Signal to all workers we found a solution.
233+
// return true;
234+
// }
235+
// };
236+
237+
// if (!future.valid() && is_done()) {
238+
// assert(result.has_value());
239+
// goto end;
240+
// } else if (future.valid() && future.wait_for(busy_loop_sleep) == std::future_status::ready) {
241+
// wrk_result = future.get();
242+
// assert(!future.valid());
243+
// if (is_done()) {
244+
// assert(result.has_value());
245+
// goto end;
246+
// }
247+
// }
248+
// }
249+
250+
// if (not_found == worker_futures.size()) {
251+
// assert(!result.has_value());
252+
// goto end;
253+
// }
254+
// }
255+
256+
// end:
257+
// for (auto& w: workers) {
258+
// w.join();
259+
// }
260+
// return result;
261+
// }
262+
263+
}

0 commit comments

Comments
 (0)