Unable to add Floor Restrictions to My Miconic PDDL domain codes - restriction

I am trying to add floor restrictions to my codes but it is not running in PDDL. Can someone help me find where I made mistakes?
Here is the PDDL domain:
(define (domain miconic)
(:requirements :adl :typing :strips)
(:types passenger - object
floor - count
elevator - object
elevator1 elevator2 elevator3 - elevator
)
(:predicates
(origin ?person - passenger ?floor - floor)
;; entry of ?lift ?person is ?floor
;; inertia
(destin ?person - passenger ?floor - floor)
;; exit of ?lift ?person is ?floor
;; inertia
(reachable-floor ?lift - elevator ?f - floor)
(above ?floor1 - floor ?floor2 - floor)
;; ?floor2 is located above of ?floor1
(boarded ?person - passenger ?lift - elevator)
;; true if ?person has boarded the lift
(served ?person - passenger ?lift - elevator)
;; true if ?person has alighted as her destination
(lift-at ?lift - elevator ?floor - floor)
;; current position of the ?lift is at ?floor
)
;;stop
(:action stop
:parameters (?lift - elevator ?f - floor)
:precondition (lift-at ?lift ?f)
:effect (and
(forall (?p - passenger)
(when (and (boarded ?p ?lift)
(destin ?p ?f))
(and (not (boarded ?p ?lift))
(served ?p ?lift))))
(forall (?p - passenger)
(when (and (origin ?p ?f) (not (served ?p ?lift)))
(boarded ?p ?lift)))))
)
;;drive up elevator1
(:action up-elevator1
:parameters (?lift - elevator1 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f1 ?f2) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))
)
;;drive down elevator1
(:action down-elevator1
:parameters (?lift - elevator1 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f2 ?f1) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))
)
;;drive up elevator2
(:action up-elevator2
:parameters (?lift - elevator2 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f1 ?f2) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))))
;;drive down elevator2
(:action down-elevator2
:parameters (?lift - elevator2 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f2 ?f1) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))))
;;drive up elevator3
(:action up-elevator3
:parameters (?lift - elevator3 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f1 ?f2) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))))
;;drive down elevator3
(:action down-elevator3
:parameters (?lift - elevator3 ?f1 - floor ?f2 - floor)
:precondition (and (lift-at ?lift ?f1) (above ?f2 ?f1) (reachable-floor ?lift ?f2))
:effect (and (lift-at ?lift ?f2) (not (lift-at ?lift ?f1))))
Here is the PDDL problem:
(define (problem mixed-f2-p1-u0-v0-g0-a0-n0-A0-B0-N0-F0-r0)
(:domain miconic)
(:objects
p0 p1 p2 p3 p4 p5 p6 - passenger
f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 - floor
e1 - elevator1
e2 - elevator2
e3 - elevator3
)
(:init
(above f0 f1) (above f0 f2) (above f0 f3) (above f0 f4) (above f0 f5) (above f0 f6) (above f0 f7) (above f0 f8) (above f0 f9) (above f0 f10) (above f0 f11)
(above f1 f2) (above f1 f3) (above f1 f4) (above f1 f5) (above f1 f6) (above f1 f7) (above f1 f8) (above f1 f9) (above f1 f10) (above f1 f11)
(above f2 f3) (above f2 f4) (above f2 f5) (above f2 f6) (above f2 f7) (above f2 f8) (above f2 f9) (above f2 f10) (above f2 f11)
(above f3 f4) (above f3 f5) (above f3 f6) (above f3 f7) (above f3 f8) (above f3 f9) (above f3 f10) (above f3 f11)
(above f4 f5) (above f4 f6) (above f4 f7) (above f4 f8) (above f4 f9) (above f4 f10) (above f4 f11)
(above f5 f6) (above f5 f7) (above f5 f8) (above f5 f9) (above f5 f10) (above f5 f11)
(above f6 f7) (above f6 f8) (above f6 f9) (above f6 f10) (above f6 f11)
(above f7 f8) (above f7 f9) (above f7 f10) (above f7 f11)
(above f8 f9) (above f8 f10) (above f8 f11)
(above f9 f10) (above f9 f11)
(above f10 f11)
(origin p0 f4)
(destin p0 f5)
(origin p1 f3)
(destin p1 f0)
(origin p2 f6)
(destin p2 f7)
(origin p3 f6)
(destin p3 f1)
(origin p4 f7)
(destin p4 f3)
(origin p5 f8)
(destin p5 f11)
(origin p6 f11)
(destin p6 f5)
(lift-at e1 f0)
(reachable-floor e1 f1)(reachable-floor e1 f3)(reachable-floor e1 f5)(reachable-floor e1 f7)(reachable-floor e1 f9)(reachable-floor e1 f11)
(lift-at e2 f0)
(reachable-floor e2 f0)(reachable-floor e2 f2)(reachable-floor e2 f4)(reachable-floor e2 f6)(reachable-floor e2 f8)(reachable-floor e2 f10)
(lift-at e3 f0)
(reachable-floor e3 f3)(reachable-floor e3 f6)(reachable-floor e3 f9)
)
(:goal (forall (?lift - elevator ?p - passenger ?f - floor) (served ?p ?lift)))
)

Related

Can I co_await an operation executed by one io_context in a coroutine executed by another in Asio?

I have an HTTP server library writen by Asio with one io_context per thread model. It has an io_context_pool which retrieves one io_context orderly. So when the server starts, io_context #1 will be used to execute the acceptor and io_context #2 will be used for the first connection and io_context #3 will be with the second and so on.
It also wait for signal to call the io_context.stop() orderly to stop the server and it works well.
I would like to refactor it with C++20 coroutine. I've almost finished but I found that if signal reveived to call io_context.stop(), heap used after free will be reported by sanitizer. I've no idea how to solve this.
Here is a simplified example:
constexpr int wait_second = 2;
constexpr int run_second = 3;
asio::awaitable<void> co_main(asio::io_context& other_ctx){
asio::steady_timer timer(other_ctx);
timer.expires_after(std::chrono::seconds(wait_second));
co_await timer.async_wait(asio::use_awaitable);
std::cout<<"timer"<<std::endl;
}
int main() {
asio::io_context ctx;
asio::io_context other_ctx;
asio::executor_work_guard<asio::io_context::executor_type> g1(ctx.get_executor());
asio::executor_work_guard<asio::io_context::executor_type> g2(other_ctx.get_executor());
asio::co_spawn(ctx, co_main(other_ctx), asio::detached);
std::thread([&]{
std::this_thread::sleep_for(std::chrono::seconds(run_second));
ctx.stop();
other_ctx.stop();
}).detach();
std::thread t1([&]{ctx.run();});
std::thread t2([&]{other_ctx.run();});
t1.join();
t2.join();
return 0;
}
The coroutine co_main is executed by ctx but the timer in it is executed by other_ctx. The wait_second represents the waiting duration of the timer while run_second represent after how many seconds the ctx and io_context will be stopped.
If the wait_second is less than run_second, everything works fine but if wait_second is longer, heap used after free will be reported by sanitizer. So is this the right way to use asio::awaitable? Can I mix use the io_context with coroutine?
Yes this usage is fine. Not optimal, but fine.
The thing to note about binding IO objects to an executor is that it mostly serves two purposes:
firstly it indicates which execution context holds the service instance for the IO object's implementation
secondly it serves as the default(!) executor for completion handlers
Note that 1. implies that it may incur more overhead than sharing the context, and 2. means that there is little behavioral difference in this case. It's the default only, so the awaitable's coro executor overrides it here. This may not be as you expected. See e.g. this similar question Boost asio steady_timer work on different strand than intended
What's the sanitizer issue
It's a lifetime issue. Let's instrument a bit and use BOOST_ASIO_ENABLE_HANDLER_TRACKING as well:
#include <boost/asio.hpp>
#include <iostream>
using namespace std::chrono_literals;
namespace asio = boost::asio;
constexpr auto wait_for = 200ms, run_for = 300ms;
asio::awaitable<void> co_main(asio::io_context& other_ctx){
asio::steady_timer timer{other_ctx.get_executor(), wait_for};
co_await timer.async_wait(asio::use_awaitable);
std::cout << "timer" << std::endl;
}
int main() {
{
asio::io_context other_ctx;
{
asio::io_context ctx;
//auto g1 = ctx.get_executor();
//auto g2 = other_ctx.get_executor();
asio::co_spawn(ctx, co_main(other_ctx), asio::detached);
std::thread stopper([&] {
std::this_thread::sleep_for(run_for);
ctx.stop();
other_ctx.stop();
});
std::thread t1([&] { ctx.run(); });
std::thread t2([&] { other_ctx.run(); });
stopper.join();
t1.join();
t2.join();
std::cout << "All joined" << std::endl;
std::cout << "ctx: " << &ctx << std::endl;
std::cout << "other_ctx: " << &other_ctx << std::endl;
}
std::cout << "ctx destructed" << std::endl;
}
std::cout << "other_ctx destructed" << std::endl;
}
After all threads are done (and joined), the destructor of other_ctx abandons all operations in the operation queue. Some of the completions are bound to the executor of ctx (because of the coro, see above) which is already gone. This leads to the use-after-scope (truncating for SO):
#asio|1661689229.839262|0^1|in 'co_spawn_entry_point' (/home/sehe/custom/superboost/boost/asio/impl/co_spawn.hpp:154)
#asio|1661689229.839262|0*1|io_context#0x7ffe27cf56a0.execute
#asio|1661689229.839715|>1|
#asio|1661689229.839961|1*2|deadline_timer#0x6110000000a0.async_wait
#asio|1661689229.839986|<1|
All joined
ctx: 0x7ffe27cf56a0
other_ctx: 0x7ffe27cf5680
ctx destructed
#asio|1661689230.139986|2*3|io_context#0x7ffe27cf56a0.execute
=================================================================
==16129==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffe27cf56a8 at pc 0x55bace9962f6 bp 0x7ffe27cf4270 sp 0x7ffe27cf4260
READ of size 8 at 0x7ffe27cf56a8 thread T0
#0 0x55bace9962f5 in void boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>::....hpp:319
#1 0x55bace968067 in void boost::asio::execution::detail::any_executor_base::execute<boost::asio::d....hpp:611
#2 0x55bace968067 in std::enable_if<boost_asio_execution_execute_fn::call_traits<boost_asio_executi....hpp:208
#3 0x55bace968067 in void boost::asio::detail::initiate_post_with_executor<boost::asio::any_io_exec....hpp:122
#4 0x55bace968067 in void boost::asio::detail::completion_handler_async_result<boost::asio::detail:....hpp:482
#5 0x55bace968067 in boost::asio::constraint<boost::asio::detail::async_result_has_initiate_memfn<b....hpp:896
#6 0x55bace968067 in auto boost::asio::post<boost::asio::any_io_executor, boost::asio::detail::awai....hpp:242
#7 0x55bace969443 in boost::asio::detail::awaitable_thread<boost::asio::any_io_executor>::~awaitabl....hpp:673
#8 0x55bace99ecb0 in boost::asio::detail::awaitable_handler_base<boost::asio::any_io_executor, void....hpp:29
#9 0x55bace99ecb0 in boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::sy....hpp:78
#10 0x55bace99ecb0 in boost::asio::detail::binder1<boost::asio::detail::awaitable_handler<boost::as....hpp:139
#11 0x55bace99ecb0 in boost::asio::detail::wait_handler<boost::asio::detail::awaitable_handler<boos....hpp:67
#12 0x55bace91be12 in boost::asio::detail::scheduler_operation::destroy() /home/sehe/custom/superbo....hpp:45
#13 0x55bace91be12 in void boost::asio::detail::op_queue_access::destroy<boost::asio::detail::sched....hpp:47
#14 0x55bace91be12 in boost::asio::detail::op_queue<boost::asio::detail::scheduler_operation>::~op_....hpp:81
#15 0x55bace91be12 in boost::asio::detail::scheduler::abandon_operations(boost::asio::detail::op_qu....ipp:444
#16 0x55bace91be12 in boost::asio::detail::epoll_reactor::shutdown() /home/sehe/custom/superboost/b....ipp:92
#17 0x55bace8ebc8c in boost::asio::detail::service_registry::shutdown_services() /home/sehe/custom/....ipp:44
#18 0x55bace8ebc8c in boost::asio::execution_context::shutdown() /home/sehe/custom/superboost/boost....ipp:41
#19 0x55bace8ebc8c in boost::asio::execution_context::~execution_context() /home/sehe/custom/superb....ipp:34
#20 0x55bace88d684 in boost::asio::io_context::~io_context() /home/sehe/custom/superboost/boost/asi....ipp:56
#21 0x55bace88d684 in main /home/sehe/Projects/stackoverflow/test.cpp:16
#22 0x7efe676d0c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
#23 0x55bace88e859 in _start (/home/sehe/Projects/stackoverflow/build/sotest+0x1a5859)
Address 0x7ffe27cf56a8 is located in stack of thread T0 at offset 904 in frame
#0 0x55bace88bd2f in main /home/sehe/Projects/stackoverflow/test.cpp:14
This frame has 34 object(s):
// ... skipped
[128, 136) '<unknown>'
[160, 168) 'stopper' (line 24)
[192, 200) 't1' (line 30)
[224, 232) '<unknown>'
[256, 264) 't2' (line 31)
[288, 296) '<unknown>'
// ... skipped
[832, 840) '<unknown>'
[864, 880) 'other_ctx' (line 16)
[896, 912) 'ctx' (line 18) <== Memory access at offset 904 is inside this variable
[928, 944) '<unknown>'
[960, 1016) '<unknown>'
[1056, 1112) '<unknown>'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope /home/sehe/custom/superboost/boost/asio/impl/io_context.hpp:319 in void boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const
Shadow bytes around the buggy address:
0x100044f96a80: f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2
0x100044f96a90: f8 f2 f2 f2 f8 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2
0x100044f96aa0: 00 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2
0x100044f96ab0: f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2
0x100044f96ac0: f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2
=>0x100044f96ad0: 00 00 f2 f2 f8[f8]f2 f2 f8 f8 f2 f2 f8 f8 f8 f8
0x100044f96ae0: f8 f8 f8 f2 f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f8 f3
0x100044f96af0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x100044f96b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100044f96b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100044f96b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==16129==ABORTING
Ironically, flipping the order of executor destruction doesn't help:
{
asio::io_context ctx;
{
asio::io_context other_ctx;
// ... skiped unchanged
}
std::cout << "other_ctx destructed" << std::endl;
}
std::cout << "ctx destructed" << std::endl;
Now we get the inverse dependency: after all threads have joined, the destructor of other_ctx correctly queues completion for the async_wait on ctx. But once ctx destructor shuts down its services, it will destroy the coro stack frame, which includes the timer object which ... has a stale reference to the other_ctx destructor.
#asio|1661689960.225134|0^1|in 'co_spawn_entry_point' (/home/sehe/custom/superboost/boost/asio/impl/co_spawn.hpp:154)
#asio|1661689960.225134|0*1|io_context#0x7ffd9e839d80.execute
#asio|1661689960.225576|>1|
#asio|1661689960.225876|1*2|deadline_timer#0x6110000000a0.async_wait
#asio|1661689960.225899|<1|
All joined
ctx: 0x7ffd9e839d80
other_ctx: 0x7ffd9e839da0
#asio|1661689960.525759|2*3|io_context#0x7ffd9e839d80.execute
#asio|1661689960.525773|~2|
other_ctx destructed
/usr/include/c++/10/coroutine:128: runtime error: member call on null pointer of type 'struct steady_timer'
/home/sehe/custom/superboost/boost/asio/basic_waitable_timer.hpp:382:3: runtime error: member access within null pointer of type 'struct basic_waitable_timer'
/home/sehe/custom/superboost/boost/asio/basic_waitable_timer.hpp:382:3: runtime error: member call on null pointer of type 'struct io_object_impl'
/home/sehe/custom/superboost/boost/asio/detail/io_object_impl.hpp:97:5: runtime error: member access within null pointer of type 'struct io_object_impl'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==22649==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x558135f6b18f bp 0x7ffd9e837d10 sp 0x7ffd9e837a00 T0)
==22649==The signal is caused by a READ memory access.
==22649==Hint: address points to the zero page.
#0 0x558135f6b18f in boost::asio::detail::io_object_impl<boost::asio::detail::deadline_timer_service<bo....hpp:97
#1 0x558135e6d07a in boost::asio::basic_waitable_timer<std::chrono::_V2::steady_clock, boost::asio::wai....hpp:382
#2 0x558135e6d07a in co_main(boost::asio::io_context&) [clone .actor] /home/sehe/custom/superboost/boos....hpp:380
#3 0x558135f0b5e9 in std::__n4861::coroutine_handle<void>::destroy() const /usr/include/c++/10/coroutine:128
#4 0x558135f0b5e9 in boost::asio::detail::awaitable_frame_base<boost::asio::any_io_executor>::destroy()....hpp:496
#5 0x558135f0b5e9 in boost::asio::awaitable<void, boost::asio::any_io_executor>::~awaitable() /home/seh....hpp:77
#6 0x558135f0b5e9 in boost::asio::awaitable<boost::asio::detail::awaitable_thread_entry_point, boost::a....actor] /home/sehe/custom/superboost/boost/asio/impl/co_spawn.hpp:183
#7 0x558135ea6d1d in std::__n4861::coroutine_handle<void>::destroy() const /usr/include/c++/10/coroutine:128
#8 0x558135ea6d1d in boost::asio::detail::awaitable_frame_base<boost::asio::any_io_executor>::destroy()....hpp:496
#9 0x558135ea6d1d in boost::asio::awaitable<boost::asio::detail::awaitable_thread_entry_point, boost::a....hpp:77
#10 0x558135ea6d1d in boost::asio::detail::awaitable_thread<boost::asio::any_io_executor>::~awaitable_t....hpp:674
#11 0x558135ea6d1d in boost::asio::detail::binder0<boost::asio::detail::awaitable_thread<boost::asio::a....hpp:32
#12 0x558135ea6d1d in void boost::asio::detail::executor_function::complete<boost::asio::detail::binder....hpp:110
#13 0x558135f6ecfb in boost::asio::detail::executor_function::~executor_function() /home/sehe/custom/su....hpp:55
#14 0x558135f6ecfb in boost::asio::detail::executor_op<boost::asio::detail::executor_function, std::all....hpp:62
#15 0x558135ec4893 in boost::asio::detail::scheduler_operation::destroy() /home/sehe/custom/superboost/....hpp:45
#16 0x558135ec4893 in boost::asio::detail::scheduler::shutdown() /home/sehe/custom/superboost/boost/asi....ipp:176
#17 0x558135ebfc8c in boost::asio::detail::service_registry::shutdown_services() /home/sehe/custom/supe....ipp:44
#18 0x558135ebfc8c in boost::asio::execution_context::shutdown() /home/sehe/custom/superboost/boost/asi....ipp:41
#19 0x558135ebfc8c in boost::asio::execution_context::~execution_context() /home/sehe/custom/superboost....ipp:34
#20 0x558135e61684 in boost::asio::io_context::~io_context() /home/sehe/custom/superboost/boost/asio/im....ipp:56
#21 0x558135e61684 in main /home/sehe/Projects/stackoverflow/test.cpp:16
#22 0x7fbd0bd07c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
#23 0x558135e62859 in _start (/home/sehe/Projects/stackoverflow/build/sotest+0x1a5859)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/sehe/custom/superboost/boost/asio/detail/io_object_impl.hpp:97 in boost::asio::detail::io_object_impl<boost::asio::detail::deadline_timer_service<boost::asio::detail::chrono_time_traits<std::chrono::_V2::steady_clock, boost::asio::wait_traits<std::chrono::_V2::steady_clock> > >, boost::asio::any_io_executor>::~io_object_impl()
==22649==ABORTING
The problem appears to be that the coro frame outlives the lifetime of other_ctx here.
Conclusion
You have to avoid destruction of both contexts from inter-depending cyclically. This practically means avoiding uncompleted operations in their operation queues.
It's good to note that the problems mostly start with using io_context::stop() to stop context mid-operation. In addition, there doesn't currently seem to be a reason run() the other_ctx in the first place.
Consider using async completion / awaitable operators with cancellation.

Occasional heap oveflow error while running a program that deals with struct pointers

I've been doing a DSA course online and this is my attempt at a solution for one of the problems. I acknowledge that I know very little about C++ and I shouldn't be messing around with structs and pointers at all, but I've been trying this for a while in order to learn a bit on my own and I can't seem to figure out what is wrong.
Problem Statement: Given a set of n segments {[a 0 , b 0 ], [a 1 , b 1 ], . . . , [a n−1 , b n−1 ]} with integer coordinates on a line, find
the minimum number m of points such that each segment contains at least one point. That is, find a
set of integers X of the minimum size such that for any segment [a i , b i ] there is a point x ∈ X such
that a i ≤ x ≤ b i .
#include <iostream>
#include <algorithm>
#include <vector>
#include <climits>
#include <unistd.h>
std::vector<int> output;
struct linedata
{
int start;
int end;
bool covered = false;
struct linepoint* sloc = (struct linepoint*)malloc(sizeof(struct linepoint*));
struct linepoint* eloc = (struct linepoint*)malloc(sizeof(struct linepoint*));
};
struct linepoint
{
int coord;
bool start;
struct linedata* refer = (struct linedata*)malloc(sizeof(struct linedata*));
struct linepoint* selfrefer = (struct linepoint*)malloc(sizeof(struct linepoint*));
};
bool linesort(struct linepoint a, struct linepoint b)
{
struct linepoint* atemp = (struct linepoint*)malloc(sizeof(struct linepoint*));
atemp = a.selfrefer;
struct linepoint* btemp = (struct linepoint*)malloc(sizeof(struct linepoint*));
btemp = b.selfrefer;
std::cout << a.selfrefer << " " << b.selfrefer << "\n";
if(a.coord < b.coord)
{
if(a.start == true)
{
atemp -> refer -> sloc = btemp;
}
if(a.start == false)
{
atemp -> refer -> eloc = btemp;
}
if(b.start == true)
{
btemp -> refer -> sloc = atemp;
}
if(b.start == true)
{
btemp -> refer -> sloc = atemp;
}
std::swap(b.selfrefer -> coord, a.selfrefer -> coord);
std::swap(b.selfrefer -> start, a.selfrefer -> start);
std::swap(b.selfrefer -> refer, a.selfrefer -> refer);
std::swap(b.selfrefer -> selfrefer, a.selfrefer -> selfrefer);
return false;
}
if((a.coord == b.coord) && (a.start > b.start))
{
if(a.start == true)
{
a.selfrefer -> refer -> sloc = b.selfrefer;
}
if(a.start == false)
{
a.selfrefer -> refer -> eloc = b.selfrefer;
}
if(b.start == true)
{
b.selfrefer -> refer -> sloc = a.selfrefer;
}
if(b.start == true)
{
b.selfrefer -> refer -> sloc = a.selfrefer;
}
std::swap(b.selfrefer -> coord, a.selfrefer -> coord);
std::swap(b.selfrefer -> start, a.selfrefer -> start);
std::swap(b.selfrefer -> refer, a.selfrefer -> refer);
std::swap(b.selfrefer -> selfrefer, a.selfrefer -> selfrefer);
return false;
}
return false;
}
int rescan(int point, struct linedata lines[], struct linepoint points[], int scanlength, bool tosort)
{
output.push_back(point);
int removed = 0;
for(int i = 0; i < scanlength; i++)
{
if((lines[i].covered == false) && (lines[i].start <= point) && (lines[i].end >= point))
{
lines[i].covered = true;
lines[i].sloc -> coord = INT_MAX - lines[i].start;
lines[i].eloc -> coord = INT_MAX - lines[i].end;
removed = removed + 1;
}
}
if(tosort == true)
{
std::sort(points, points+2*scanlength, linesort);
}
return removed;
}
int main(void)
{
int num;
std::cin >> num;
int left = 0;
int track = 0;
struct linedata lines[num];
struct linepoint points[2*num];
struct linepoint* indexor[2*num];
for(int i = 0; i < num; i++)
{
std::cin >> lines[i].start >> lines[i].end;
points[2*i].coord = lines[i].start;
points[2*i].start = true;
points[2*i + 1].coord = lines[i].end;
points[2*i + 1].start = false;
lines[i].sloc = &points[2*i];
lines[i].eloc = &points[2*i + 1];
points[2*i].selfrefer = &points[2*i];
points[2*i + 1].selfrefer = &points[2*i + 1];
left = left + 1;
if(lines[i].start == lines[i].end)
{
left = left - rescan(lines[i].start, lines, points, i + 1, false);
}
}
for(int i = 0; i < 2*num; i++)
{
std::cout << i << " " << points[i].coord << " " << points[i].start << " " << sizeof(&points[i]) << " " << &points[i] << "\n";
}
std::sort(points, points+2*num, linesort);
while(left)
{
for(int i = 0; i < left; i++)
{
if(points[i].start == true)
{
std::cout << "loop part 1: " << left << " " << i << "\n";
for(int i = 0; i < 2*num; i++)
{
std::cout << i << " " << points[i].coord << " " << points[i].start << "\n";
}
sleep(1);
track = track + 1;
continue;
}
if((track != 0) && (points[i].start == false))
{
left = left - rescan(points[i].coord, lines, points, num, true);
std::cout << "loop part 2: " << left << " " << i << "\n";
for(int i = 0; i < 2*num; i++)
{
std::cout << i << " " << points[i].coord << " " << points[i].start << "\n";
}
sleep(1);
track = 0;
continue;
}
}
}
std::cout << output.size() << "\n";
for(int i = 0; i < output.size(); i++)
{
std::cout << output.at(i) << " ";
}
std::cout << "\n";
}
The code behaves unpredictably, to say the least. I'm pretty sure there's some undefined condition in my code and both libasan and valgrind complain about invalid writes in the linesort function. Seeing how the invalid writes are of size 8, I think the writes are pertaining to me exchanging memory addresses to cross-reference linepoint and linedata structs. But seeing how it errors out randomly, I don't know what is causing it to behave like this.
This is from a couple of libasan runs
4
4 7
1 3
2 5
5 6
0 4 1 8 0x7ffe0c863880
1 7 0 8 0x7ffe0c863898
2 1 1 8 0x7ffe0c8638b0
3 3 0 8 0x7ffe0c8638c8
4 2 1 8 0x7ffe0c8638e0
5 5 0 8 0x7ffe0c8638f8
6 5 1 8 0x7ffe0c863910
7 6 0 8 0x7ffe0c863928
0x7ffe0c863898 0x7ffe0c863880
0x7ffe0c863898 0x7ffe0c863880
0x7ffe0c8638b0 0x7ffe0c863880
=================================================================
==188113==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000001a0 at pc 0x562db1500d54 bp 0x7ffe0c8635e0 sp 0x7ffe0c8635d0
WRITE of size 8 at 0x6020000001a0 thread T0
#0 0x562db1500d53 in linesort(linepoint, linepoint) /home/kevin/Downloads/Week3_5.cpp:37
#1 0x562db1502ac0 in bool __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>::operator()<linepoint*, linepoint*>(linepoint*, linepoint*) /usr/include/c++/10/bits/predefined_ops.h:156
#2 0x562db1502ac0 in void std::__insertion_sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1846
#3 0x562db1500341 in void std::__final_insertion_sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1891
#4 0x562db1500341 in void std::__sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1977
#5 0x562db1500341 in void std::sort<linepoint*, bool (*)(linepoint, linepoint)>(linepoint*, linepoint*, bool (*)(linepoint, linepoint)) /usr/include/c++/10/bits/stl_algo.h:4892
#6 0x562db1500341 in main /home/kevin/Downloads/Week3_5.cpp:137
#7 0x7febd76450b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#8 0x562db150063d in _start (/home/kevin/Downloads/5+0x363d)
0x6020000001a0 is located 8 bytes to the right of 8-byte region [0x602000000190,0x602000000198)
allocated by thread T0 here:
#0 0x7febd7abc517 in malloc (/lib/x86_64-linux-gnu/libasan.so.6+0xb0517)
#1 0x562db14ff7e9 in linepoint::linepoint() /home/kevin/Downloads/Week3_5.cpp:18
#2 0x562db14ff7e9 in main /home/kevin/Downloads/Week3_5.cpp:112
#3 0x7febd76450b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/kevin/Downloads/Week3_5.cpp:37 in linesort(linepoint, linepoint)
Shadow bytes around the buggy address:
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff8000: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8010: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8020: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
=>0x0c047fff8030: fa fa 00 fa[fa]fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8040: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8050: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==188113==ABORTING
5
2 6
8 19
2 5
1 2
56 981
0 2 1 8 0x7ffdc275be20
1 6 0 8 0x7ffdc275be38
2 8 1 8 0x7ffdc275be50
3 19 0 8 0x7ffdc275be68
4 2 1 8 0x7ffdc275be80
5 5 0 8 0x7ffdc275be98
6 1 1 8 0x7ffdc275beb0
7 2 0 8 0x7ffdc275bec8
8 56 1 8 0x7ffdc275bee0
9 981 0 8 0x7ffdc275bef8
0x7ffdc275be38 0x7ffdc275be20
0x7ffdc275be38 0x7ffdc275be20
0x7ffdc275be50 0x7ffdc275be20
0x7ffdc275be50 0x7ffdc275be38
0x7ffdc275be68 0x7ffdc275be20
0x7ffdc275be68 0x7ffdc275be50
0x7ffdc275be80 0x7ffdc275be20
0x7ffdc275be80 0x7ffdc275be68
=================================================================
==188263==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000260 at pc 0x558343333d54 bp 0x7ffdc275ba80 sp 0x7ffdc275ba70
WRITE of size 8 at 0x602000000260 thread T0
#0 0x558343333d53 in linesort(linepoint, linepoint) /home/kevin/Downloads/Week3_5.cpp:37
#1 0x55834333568d in bool __gnu_cxx::__ops::_Val_comp_iter<bool (*)(linepoint, linepoint)>::operator()<linepoint, linepoint*>(linepoint&, linepoint*) /usr/include/c++/10/bits/predefined_ops.h:238
#2 0x55834333568d in void std::__unguarded_linear_insert<linepoint*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1826
#3 0x558343335af6 in void std::__insertion_sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1854
#4 0x558343333341 in void std::__final_insertion_sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1891
#5 0x558343333341 in void std::__sort<linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)> >(linepoint*, linepoint*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(linepoint, linepoint)>) /usr/include/c++/10/bits/stl_algo.h:1977
#6 0x558343333341 in void std::sort<linepoint*, bool (*)(linepoint, linepoint)>(linepoint*, linepoint*, bool (*)(linepoint, linepoint)) /usr/include/c++/10/bits/stl_algo.h:4892
#7 0x558343333341 in main /home/kevin/Downloads/Week3_5.cpp:137
#8 0x7f4b800a50b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#9 0x55834333363d in _start (/home/kevin/Downloads/5+0x363d)
0x602000000260 is located 8 bytes to the right of 8-byte region [0x602000000250,0x602000000258)
allocated by thread T0 here:
#0 0x7f4b8051c517 in malloc (/lib/x86_64-linux-gnu/libasan.so.6+0xb0517)
#1 0x5583433327e9 in linepoint::linepoint() /home/kevin/Downloads/Week3_5.cpp:18
#2 0x5583433327e9 in main /home/kevin/Downloads/Week3_5.cpp:112
#3 0x7f4b800a50b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/kevin/Downloads/Week3_5.cpp:37 in linesort(linepoint, linepoint)
Shadow bytes around the buggy address:
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff8000: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8010: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8020: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8030: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
=>0x0c047fff8040: fa fa 00 fa fa fa 00 fa fa fa 00 fa[fa]fa 00 fa
0x0c047fff8050: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8060: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c047fff8070: fa fa 00 fa fa fa 00 fa fa fa fa fa fa fa fa fa
0x0c047fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==188263==ABORTING
I've used g++ 10 with the -O2 flag turned on. I'm running on Ubuntu 20.04.
I would appreciate any help or guidance regarding this. Once again, I am very inexperienced in C++ and I might be doing things horribly wrong.
struct linepoint* sloc = (struct linepoint*)malloc(sizeof(struct linepoint*));
Your intention is to allocate memory for a linepoint, then assign the address of that allocated memory to sloc.
This is not what is happening, as you try to allocate space for a linepoint*, i.e. enough space for a pointer to such struct. You don't allocate enough memory
Change your code to
struct linepoint* sloc = (struct linepoint*)malloc(sizeof(struct linepoint)); so that malloc can allocate enough space.
Aside from that, you should rethink your use of malloc(). malloc does nothing more than allocate a chunk of memory for you. In C++ however, you should work with the laguage provided keyword new. new also allocates memory and returns a pointer to it, but it also makes sure that operations such as calling the constructors of your objects are performed.

Populating map with new pointers in a loop (C++)

So I am working on the Copy List with Random Pointer question from leetcode and ran into a bit of a problem.
for (; iterateOG->next != nullptr;
iterateOG = iterateOG->next) {
Node* tmp = new Node;
hashTable.insert(std::pair<Node*,Node*>(iterateOG,tmp));
}
So I want to create a new Node object for every existing node in the orginal list. After running the test cases I get an error message like including the HINT below
'hashTable' <== Memory access at offset 912 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Does anyone know what is causing this problem? I know the cause might be because I created a new object and didn't do anything with it within the scope, but I don't see a solution around this problem. Any help would be appreciated. Thank you!
Full code and error message below
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if (head == nullptr)
return nullptr;
Node* iterateOG = head;
std::map<Node*, Node*> hashTable;
for (; iterateOG->next != nullptr;
iterateOG = iterateOG->next) {
Node* tmp = new Node;
hashTable.insert(std::pair<Node*,Node*>(iterateOG,tmp));
}
std::cout << endl;
iterateOG = head;
for (; iterateOG->next != nullptr;
iterateOG = iterateOG->next) {
hashTable.find(iterateOG)->second->val = iterateOG->val;
hashTable.find(iterateOG)->second->next = hashTable.find(iterateOG->next)->second;
hashTable.find(iterateOG)->second->random = hashTable.find(iterateOG->random)->second;
std::cout << hashTable.find(iterateOG)->second->val << ',';
}
std::cout << endl;
return hashTable.find(head)->second;
}
};
Error Message
=================================================================
==29==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc4dbbbb70 at pc 0x00000041d7eb bp 0x7ffc4dbbb7b0 sp 0x7ffc4dbbb7a8
READ of size 8 at 0x7ffc4dbbbb70 thread T0
#2 0x7fa042ca92e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
Address 0x7ffc4dbbbb70 is located in stack of thread T0 at offset 912 in frame
This frame has 14 object(s):
[32, 33) '__c'
[96, 97) '__c'
[160, 168) 'iterateOG'
[224, 232) 'tmp'
[288, 296) '<unknown>'
[352, 360) '<unknown>'
[416, 424) '<unknown>'
[480, 488) '<unknown>'
[544, 552) '<unknown>'
[608, 616) '<unknown>'
[672, 680) '<unknown>'
[736, 744) 'head'
[800, 816) '<unknown>'
[864, 912) 'hashTable' <== Memory access at offset 912 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x100009b6f710: 00 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2 f2 f2
0x100009b6f720: f8 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2 f2
0x100009b6f730: 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2 f2
0x100009b6f740: 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2 f2
0x100009b6f750: 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2 f2
=>0x100009b6f760: f8 f8 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00[f2]f2
0x100009b6f770: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x100009b6f780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009b6f790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009b6f7a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009b6f7b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==29==ABORTING
The bug is on this line:
hashTable.find(iterateOG)->second->next = hashTable.find(iterateOG->next)->second;
For the last node iterateOG->next has value that isn't in hashTable.

Merging lines in chess ply sequences

I have a file containing the ply sequences of multiple chess games. Games are separated by one or more new lines and the corresponding ply sequence of each game can be also split into multiple lines.
I would like to merge all lines corresponding to the same game, so as to have only one line per game. I have tried different options, but none worked. A remark is that the file contains more than 14M games, so I need a fast solution. I work on Linux.
Example:
e4 e5 Bb5 c6 Bc4 b5 Bxf7+ Kxf7 Nf3 Qf6 d4 d6 dxe5 dxe5
Bg5 Qe6 Nc3 Be7 Be3 Nf6 b4 Rd8 Ng5+ Kg8 Nd5 Qd6 Qf3 cxd5
Bc5 Qe6 Nxe6 Bxe6 Bxe7
e4 e5 Nf3 Qf6 Bc4 Bc5 Nc3 c6 Na4 Bb4 c3 Ba5 Nc5 d6 Nb3
Bb6 d4 h6 dxe5 dxe5 O-O Ne7 Be3 Nd7 Bxb6 Nxb6 Be2 O-O
Nc5 Ng6 b4 Nf4 Nd3 Rd8 Qc2 Nc4 Nxf4 Na3 Qb3 Qxf4
Qxa3 Qxe4 Rfe1 f6 Qb3+ Kh8 Bd1 Qf4 Bc2 Bg4 Re4 Qf5 Rxe5
Qd7 Re3 Qd6 Nh4 Qd5 Ng6+ Kh7 Ne7+ f5 Nxd5 Rxd5 c4 Rd2
h3 Bh5 Bxf5+ Kh8
e4 e5 Nf3 Nc6 Bb5 Nf6 Bxc6 bxc6 O-O d6 h3 Nxe4 Re1 Bf5
d4 f6 dxe5 fxe5 Nbd2 Nxd2 Bxd2 Be7 Qc1 O-O c3 h6 c4 e4
Nd4 Qd7 b3 d5 Nxf5 Qxf5 Be3 Bf6 Rb1 d4 Bd2 c5
d4 Nf6 Nc3 d5 Bg5 Ne4 Nxe4 dxe4 c3 h6 Be3 e6 Qc2 f5 g4
Be7 Bg2 O-O O-O-O Nd7 d5 Nb6 dxe6 Qe8 gxf5 Rxf5 Bxe4 Rf8
Bh7+ Kh8 Bg6
Should become:
e4 e5 Bb5 c6 Bc4 b5 Bxf7+ Kxf7 Nf3 Qf6 d4 d6 dxe5 dxe5 Bg5 Qe6 Nc3 Be7 Be3 Nf6 b4 Rd8 Ng5+ Kg8 Nd5 Qd6 Qf3 cxd5 Bc5 Qe6 Nxe6 Bxe6 Bxe7
e4 e5 Nf3 Qf6 Bc4 Bc5 Nc3 c6 Na4 Bb4 c3 Ba5 Nc5 d6 Nb3 Bb6 d4 h6 dxe5 dxe5 O-O Ne7 Be3 Nd7 Bxb6 Nxb6 Be2 O-O Nc5 Ng6 b4 Nf4 Nd3 Rd8 Qc2 Nc4 Nxf4 Na3 Qb3 Qxf4 Qxa3 Qxe4 Rfe1 f6 Qb3+ Kh8 Bd1 Qf4 Bc2 Bg4 Re4 Qf5 Rxe5 Qd7 Re3 Qd6 Nh4 Qd5 Ng6+ Kh7 Ne7+ f5 Nxd5 Rxd5 c4 Rd2 h3 Bh5 Bxf5+ Kh8
e4 e5 Nf3 Nc6 Bb5 Nf6 Bxc6 bxc6 O-O d6 h3 Nxe4 Re1 Bf5 d4 f6 dxe5 fxe5 Nbd2 Nxd2 Bxd2 Be7 Qc1 O-O c3 h6 c4 e4 Nd4 Qd7 b3 d5 Nxf5 Qxf5 Be3 Bf6 Rb1 d4 Bd2 c5
d4 Nf6 Nc3 d5 Bg5 Ne4 Nxe4 dxe4 c3 h6 Be3 e6 Qc2 f5 g4 Be7 Bg2 O-O O-O-O Nd7 d5 Nb6 dxe6 Qe8 gxf5 Rxf5 Bxe4 Rf8 Bh7+ Kh8 Bg6
With awk, you can set the record separator to the empty string, which makes records being separated by blank lines. Then you replace for each record the newlines with a space:
awk -v RS="" '{gsub("\n", " ")} 1' infile
Or, as an alternative, with sed:
sed ':a;N;/\n$/!s/\n//;ta;s/\n$//;/^$/d' infile
This works as follows:
:label # Label to jump back to
N # Append next line to pattern sapce
/\n$/! s/\n// # If pattern space does not end with newline, remove newline
t label # Jump back to label if we changed something
s/\n$// # Remove trailing newline
/^$/ d # Delete empty line
The last command isn't strictly necessary for the given input, but if there are more than two consecutive empty lines, there would be empty output lines without it. It's just there to make the sed command equivalent to the awk command.

In Clojure core.logic, why can't I use threading macros?

When I run the following code, I get the ensuing error:
(run 3 [q]
(fresh [a0 a1 a2
b0 b1 b2
c0 c1 c2]
(== q [[a0 a1 a2] [b0 b1 b2] [c0 c1 c2]])
(fd/in a0 a1 a2 b0 b1 b2 c0 c1 c2 (fd/interval 1 9))
(fd/distinct [a0 a1 a2 b0 b1 b2 c0 c1 c2])
(fd/eq
(= a0 4)
(= 22 (- (* a0 a1) a2))
(= -1 (-> b0 (* b1) (- b2)))
)))
error:
2. Unhandled clojure.lang.Compiler$CompilerException
Error compiling src/euler/core.clj at (1392:5)
1. Caused by java.lang.IllegalArgumentException
Can't call nil
core.clj: 3081 clojure.core/eval
main.clj: 240 clojure.main/repl/read-eval-print/fn
main.clj: 240 clojure.main/repl/read-eval-print
main.clj: 258 clojure.main/repl/fn
main.clj: 258 clojure.main/repl
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 630 clojure.core/apply
core.clj: 1868 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
...
Notice the line with the threading macro ->, in CIDER I'll macro expand it and everything looks fine, but in the end the code crashes. I'm assuming this is the fault of macros, but I'm not sure why. Any ideas?
You should look at the source of clojure.core.logic.fd. The error occurs in the macro eq, which process all of its forms before macroexpansion can occur.
For a quick solution, I've created a version of eq which calls macroexpand-all on all of its forms before doing anything else. It seems to work for your code, although I have not tested it in other contexts:
(defmacro mac-eq [& forms]
(let [exp-forms (map clojure.walk/macroexpand-all forms)]
`(fd/eq ~#exp-forms)))
Let's try it!
stack-prj.logicThreadMacro> (run 3 [q]
(fresh [a0 a1 a2
b0 b1 b2
c0 c1 c2]
(== q [[a0 a1 a2] [b0 b1 b2] [c0 c1 c2]])
(fd/in a0 a1 a2 b0 b1 b2 c0 c1 c2 (fd/interval 1 9))
(fd/distinct [a0 a1 a2 b0 b1 b2 c0 c1 c2])
(mac-eq
(= a0 4)
(= 22 (- (* a0 a1) a2))
(= -1 (-> b0 (* b1) (- b2))))))
()