From 87e85603b9bb3321203bdaf9e331b5ceb55357cf Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 1 May 2019 23:13:53 +0000 Subject: [PATCH] Merged PR 3215853: Fix spacing/layout for block characters and many retroactively-recategorized emoji (and more!) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This encompasses a handful of problems with column counting. The Terminal project didn't set a fallback column counter. Oops. I've fixed this to use the `DxEngine` as the fallback. The `DxEngine` didn't implement its fallback method. Oops. I've fixed this to use the `CustomTextLayout` to figure out the advances based on the same font and fallback pattern as the real final layout, just without "rounding" it into cells yet. - `CustomTextLayout` has been updated to move the advance-correction into a separate phase from glyph shaping. Previously, we corrected the advances to nice round cell counts during shaping, which is fine for drawing, but hard for column count analysis. - Now that there are separate phases, an `Analyze` method was added to the `CustomTextLayout` which just performs the text analysis steps and the glyph shaping, but no advance correction to column boundaries nor actual drawing. I've taken the caching code that I was working on to improve chafa, and I've brought it into this. Now that we're doing a lot of fallback and heavy lifting in terms of analysis via the layout, we should cache the results until the font changes. I've adjusted how column counting is done overall. It's always been in these phases: 1. We used a quick-lookup of ranges of characters we knew to rapidly decide `Narrow`, `Wide` or `Invalid` (a.k.a. "I dunno") 2. If it was `Invalid`, we consulted a table based off of the Unicode standard that has either `Narrow`, `Wide`, or `Ambiguous` as a result. 3. If it's still `Ambiguous`, we consult a render engine fallback (usually GDI or now DX) to see how many columns it would take. 4. If we still don't know, then it's `Wide` to be safe. - I've added an additional flow here. The quick-lookup can now return `Ambiguous` off the bat for some glyph characters in the x2000-x3000 range that used to just be simple shapes but have been retroactively recategorized as emoji and are frequently now using full width color glyphs. - This new state causes the lookup to go immediately to the render engine if it is available instead of consulting the Unicode standard table first because the half/fullwidth table doesn't appear to have been updated for this nuance to reclass these characters as ambiguous, but we'd like to keep that table as a "generated from the spec" sort of table and keep our exceptions in the "quick lookup" function. I have confirmed the following things "just work" now: - The windows logo flag from the demo. (⚫⚪💖✅🌌😊) - The dotted chart on the side of crossterm demo (•) - The powerline characters that make arrows with the Consolas patched font (██) - An accented é - The warning and checkmark symbols appearing same size as the X. (✔⚠🔥) Related work items: #21167256, #21237515, #21243859, #21274645, #21296827 --- src/cascadia/TerminalControl/TermControl.cpp | 6 + src/host/ft_host/API_BufferTests.cpp | 67 +++ src/host/ft_host/Host.FeatureTests.vcxproj | 4 + .../ft_host/Host.FeatureTests.vcxproj.filters | 8 + src/host/ft_host/Host.Tests.Feature.rc | Bin 0 -> 124 bytes src/host/ft_host/chafa.txt | 482 ++++++++++++++++++ src/host/ft_host/precomp.h | 2 + src/host/ft_host/resource.h | 1 + src/host/screenInfo.cpp | 2 + .../ut_host/CodepointWidthDetectorTests.cpp | 49 +- src/renderer/dx/CustomTextLayout.cpp | 255 +++++---- src/renderer/dx/CustomTextLayout.h | 11 +- src/renderer/dx/DxRenderer.cpp | 24 +- src/types/CodepointWidthDetector.cpp | 93 +++- src/types/GlyphWidth.cpp | 11 + src/types/convert.cpp | 103 +++- src/types/inc/CodepointWidthDetector.hpp | 3 + src/types/inc/GlyphWidth.hpp | 1 + src/types/inc/convert.hpp | 2 +- 19 files changed, 996 insertions(+), 128 deletions(-) create mode 100644 src/host/ft_host/Host.Tests.Feature.rc create mode 100644 src/host/ft_host/chafa.txt create mode 100644 src/host/ft_host/resource.h diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index fe2608e3ce..185c4d8c82 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "..\..\types\inc\GlyphWidth.hpp" using namespace ::Microsoft::Console::Types; using namespace ::Microsoft::Terminal::Core; @@ -294,6 +295,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); _renderer->AddRenderEngine(dxEngine.get()); + // Set up the renderer to be used to calculate the width of a glyph, + // should we be unable to figure out it's width another way. + auto pfn = std::bind(&::Microsoft::Console::Render::Renderer::IsGlyphWideByFont, _renderer.get(), std::placeholders::_1); + SetGlyphWidthFallback(pfn); + // Initialize our font with the renderer // We don't have to care about DPI. We'll get a change message immediately if it's not 96 // and react accordingly. diff --git a/src/host/ft_host/API_BufferTests.cpp b/src/host/ft_host/API_BufferTests.cpp index c48dd9e039..afa0fd5997 100644 --- a/src/host/ft_host/API_BufferTests.cpp +++ b/src/host/ft_host/API_BufferTests.cpp @@ -3,6 +3,8 @@ #include "precomp.h" +extern "C" IMAGE_DOS_HEADER __ImageBase; + // This class is intended to test boundary conditions for: // SetConsoleActiveScreenBuffer class BufferTests @@ -23,6 +25,8 @@ class BufferTests END_TEST_METHOD() TEST_METHOD(ScrollLargeBufferPerformance); + + TEST_METHOD(ChafaGifPerformance); }; void BufferTests::TestSetConsoleActiveScreenBufferInvalid() @@ -144,3 +148,66 @@ void BufferTests::ScrollLargeBufferPerformance() Log::Comment(String().Format(L"%d calls took %d ms. Avg %d ms per call", count, delta, delta/count)); } +void BufferTests::ChafaGifPerformance() +{ + BEGIN_TEST_METHOD_PROPERTIES() + TEST_METHOD_PROPERTY(L"IsPerfTest", L"true") + END_TEST_METHOD_PROPERTIES() + + const auto Out = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_SCREEN_BUFFER_INFO Info; + GetConsoleScreenBufferInfo(Out, &Info); + + // We need a large buffer + Info.dwSize.Y = 9999; + SetConsoleScreenBufferSize(Out, Info.dwSize); + + SetConsoleCursorPosition(Out, { 0}); + + DWORD Mode = 0; + GetConsoleMode(Out, &Mode); + Mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(Out, Mode); + + SetConsoleOutputCP(CP_UTF8); + + // Taken from: https://blog.kowalczyk.info/article/zy/Embedding-binary-resources-on-Windows.html + HGLOBAL res_handle = NULL; + HRSRC res; + char * res_data; + DWORD res_size; + + // NOTE: providing g_hInstance is important, NULL might not work + HMODULE hModule = (HMODULE)&__ImageBase; + + res = FindResource(hModule, MAKEINTRESOURCE(CHAFA_CONTENT), RT_RCDATA); + if (!res) + { + VERIFY_FAIL(L"Couldn't find resource."); + return; + } + res_handle = LoadResource(hModule, res); + if (!res_handle) + { + VERIFY_FAIL(L"Couldn't load resource."); + return; + } + res_data = (char*)LockResource(res_handle); + res_size = SizeofResource(hModule, res); + /* you can now use the resource data */ + + Log::Comment(L"Working. Please wait..."); + const auto now = std::chrono::steady_clock::now(); + + DWORD count = 0; + for (DWORD pos = 0; pos < res_size; pos += 1000) + { + DWORD written = 0; + WriteConsoleA(Out, res_data + pos, min(1000, res_size-pos), &written, nullptr); + count++; + } + + const auto delta = std::chrono::duration_cast(std::chrono::steady_clock::now() - now).count(); + Log::Comment(String().Format(L"%d calls took %d ms. Avg %d ms per call", count, delta, delta / count)); +} diff --git a/src/host/ft_host/Host.FeatureTests.vcxproj b/src/host/ft_host/Host.FeatureTests.vcxproj index d206af5f21..7a8205072a 100644 --- a/src/host/ft_host/Host.FeatureTests.vcxproj +++ b/src/host/ft_host/Host.FeatureTests.vcxproj @@ -30,12 +30,16 @@ + {18d09a24-8240-42d6-8cb6-236eee820263} + + + {8CDB8850-7484-4EC7-B45B-181F85B2EE54} Win32Proj diff --git a/src/host/ft_host/Host.FeatureTests.vcxproj.filters b/src/host/ft_host/Host.FeatureTests.vcxproj.filters index f0e7dfc2ce..514a6e7512 100644 --- a/src/host/ft_host/Host.FeatureTests.vcxproj.filters +++ b/src/host/ft_host/Host.FeatureTests.vcxproj.filters @@ -98,8 +98,16 @@ Header Files + + Header Files + + + + Resource Files + + \ No newline at end of file diff --git a/src/host/ft_host/Host.Tests.Feature.rc b/src/host/ft_host/Host.Tests.Feature.rc new file mode 100644 index 0000000000000000000000000000000000000000..2f3866d96ea52860cf402fdc63e94ff90c7d8be7 GIT binary patch literal 124 zcmXAh%?dzJ6okLE@(yC}9pon~O7@bUC{Y*X=`okZcg|_%%sjV?L%_^R$HGa^fQOIK s-r1xWIRhb+RQqj-$%)8Bqr0S_CjF*IB_)wl3)|Ew*)ocdgG>B9FFAP=L;wH) literal 0 HcmV?d00001 diff --git a/src/host/ft_host/chafa.txt b/src/host/ft_host/chafa.txt new file mode 100644 index 0000000000..b205bc4fde --- /dev/null +++ b/src/host/ft_host/chafa.txt @@ -0,0 +1,482 @@ +[?25l +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂╴▂┈▪⎽▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▘⎺▆▅▍▗╾⎼▃▊▅╾┚┶╲⎽▄▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅┳▃▂⎽⎽▃▃▅▅▄▄▗▖⎺▆▆▅▎▍▄▃▂▊▗▆⎼▃▂▝▖⎺◆⎺▅▅▃▂▄▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▋▃▂⎼▊▗▊▅▄▄▃▅▋▆▆▅▅▮▎▂▂⎽▊▍▍▂⎺⎺▍▋⎺▆▆▂▲▄▃▃▆▄▂╴│╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅━╾⎼▃▍▄▌▄▃━▋▃▍▅▄▄▊▃▃⎺▆▆▋▍▍⎺▆▆▍▊▅▅⎻▌┈▆▆▄▂▅▃⎺▆▄▃▂⎽⎽⎽▂▃▖▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▄▃▂▊⎽▉▃▅▅▅▍▂▄▄▃▂▌▊▗▆▅▅▄▎▅▅▄▄▍▊▄━━▋▖┈▪▝▄⎺▌▅▂▪▃▂⎽⎽╲  ▝▗▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▊▂⎽⎺⎺▍▲▌⎼▄▃▖●▊━▅▄▄▍▋▗▃━━▌▎▃▃▂▂▖▉⎼⎼⎼▃▆▅▄▂⎽⎺▍┈▎⎺⎺▆▆▆▎▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▘⎺⎺⎺┳▆▆▃▂▂▂▋▅▌▃▂▂▂▎▌▝▄▄▃▌▘▝▃▃▂▋▉■┈⎽▉▏⎺▆▅▃▆▘┈▌▎▋ ╵▌▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗⎻⎻▆━▘▅▋⎺╴⎺⎻▍▆▘┈⎺▆▆⎺▍▂⎽▂⎽▌▘▎⎺⎺⎺▋▉⎺▖┈⎺▎▎▊▍▖┈▆▗▝▅▃▂└⎽▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂▂▃▃▃▝▄▘▅▄⎺▄▲▲▄▄▃▃▘▅▅▄▄▄▄⎺╱▄▄▃▃▋ ━━━━▎▂⎽▉▝┈▘▎◀▎▆▄▃▂▂▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▋⎼⎽▂▂▌▆╺━▲⎼⎼▋▅▅▅▄▃▲▅▅▅▄▄▅▄▖▏▄▄▃▃▋ ▂▂┈⎽▌▎▊⎺▅▃▂▌▏▌▉▘▌▎ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎺⎺┑▂▂▂▄▄▄▂▂▄▄▃▃▃▃▂▄▃▃▃◆⎺▆▆▆▆▝▅▄▄▄▃▂⎽▆▅▄▂╳▘┥▊▂▘⎽▗▗▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▄▅┒▅⎺▅▃⎽┈▅▃▃ ▆▅▄▃▂▋▂▪▉▋▌▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲●▝⎼▆▄▂┈⎺▅▃▂◀▋   ▂▃▘▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄⎺⎺▆▅▄▄▄▄▅▆⎺┯▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚┆ ╵╴┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂▂▂┈│▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▗▆▅▅▖▌▂▂⎼▊▄▃▃▃▂⎺▄▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▆▄▃▃▂▃▃▅▄▄▃▖▖▆▅▅▄▎▍▄▄▃▊▌▃▃▂▂╱▖⎺⎺▆▄▄▂▃▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▋▄▃▃▃▅▖▄▃▃▃▅▋▅▄▄▼▮▎▃▃▂▊▍▌▅▄▃▍▋⎺▆▅▂▗▃▂▆▄▂┈▍│╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▃─━▃━▍▄▌━━━▋▃▍▄▃▃▊▃▃▂⎽⎺▋▍▍▃▂▂▌▋▆▅⎻▌┈▆▄▂▲▃⎺▆▅▃▂⎽⎽⎽▂▃▄▖▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▌▃▂⎼▂⎽▗▅▅▄▄▍▃▂▂▲━▌▊▘▆▆▆▌▍▖⎺⎺▆▍▊▄━━▋▖┈▉▄▍▆▅▄▲▄▂▂▪▲▪  ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▊⎼⎼▃▂▍⎽▗▃▃▂▂▝▊▄▃▃▃▍▋▗▄▄▃▌▃▆▅▅▄▌▉─⎼▃▅▅▄▂⎽▖▝▍┈▎▆▆▆▆⎺▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂◀⎽⎽━▋▆▆▂⎽⎺⎺⎺▅▍⎽⎽▲⎺▎▌▂▅▅▄▌●▍━━━▌▉⎽⎽⎽▉▏⎺▅▃⎽▄▘┊▌▏▎▮┕▉▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▆▆▼⎻▆▅▋┳▆▆▅▍▆▅▆▅▅▅⎺▍▃▂▂⎽▍▘▝▃▂▂▋▉⎺▖⎺┳▎┫╱▉▏▆▄▏▝▄▂⎽┊⎽▊▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▄▃━▃▄▝▄▍▃▃━━▮▉▃▂▂▲▗▄▆▅▅▅▅●▄▎⎺▆▆▋ ▏━━━▎▘▏▋▌┈▋▎▎▆▅▄▃▃▃▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅╺▃▂▂▂▌▆▗▄▃▃▂▋▅▅▅▄▃▲▅▅▅▄▄▅▄▖▂▂⎽⎽●▖ ▂▂┈⎽▌▎⎺▅▃▂▂▌╲▌▗▘▌▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺┑▂▂▂▼▼▼▂▂▄▄▃▃▃▃▂▄▃▃▃▃━▅▄▅⎼▝▅▄▄▃▂⎽▆▅▃▂╵⎺▅▘▊▃▘▗┄▗▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▄▄▝⎺▅▃⎽┈▅▃▂└⎺▅▄▃▂▂▘▃┈▎▋▍▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲●⎼▆▄▃┈⎺▅▃▂⎽▌▊ ┈⎽▃▅▚⎻─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄╹⎺▅▄▄▄▄▅▆⎺⎺▂▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╷·╶ ┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂▂⎽┈│▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▗▄▄▃▖▌▂▂⎼▊▖▅▅▄▄▖▄▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▆▅▄▄▃▗▃▃▃▃▂▂▖▄▄▃▃▎▍⎼▄▃▊▍▄▄▄▃▃▖⎺⎺▆▃▃⎽▄▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▋▅▅▄▗▅▊▃▂▂▂▅▋▃━━┑▮▎▃▃▂▊▍▌━━━▍▋⎺▆▅▖▃▂⎺▅▃⎽┊▍│╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄━▅▄─▘▄▍━▅▄▋▃▍▅▄▄▊▃▃▂▂⎺▋▍▂▃▂▃▍▋▆⎻▄▌▆▅▃▲▄▂⎺▅▄▃▂▂▂▂▃▅▆▖⎺╎▆▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▌▄▄▃╸▂▗▄▃▃▃▍▃▄▄▃▃▌▊▘⎺▆▆▌▍▝▃▂▂▌▊▄━╾▋▖┈┃▃▆▅▃━╾▃▂▂■⎽╴  ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▊▃▂▂▂▍▲▗▂▂⎼⎽▃▊▂▂▂⎺▝▋▗▄▄▄▌▝▍⎺⎺⎺▌▉⎼⎼▂▝▄▃⎽┈▝▆▍┈▎⎺⎺⎺╴⎺▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂⎽⎼▃▂▂▆▆⎺⎺▆▆▆▅▍▆▆▆▅▎▌▂▅▅▄▗▖▗▅▄▄▋▉⎽┈▝▉⎺▆▄▂▅▂▋┊▌╻┚▼╲▋▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▂⎺⎺⎺▍▅▋▅▅▄▄▎▆▝▄▃▃▃▏▍▃▂▂▂▍▏⎽▅▅▄▋▉⎺▖▆▼▎▋╴▌⎺▅▃▚▝▃⎽┈└⎽▊▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▅▅⎻⎻⎻▝▄▎━▅▅┰▮▪▄▄▄▃▋▅▆▅▅▅▅▝▘▎⎽▂┈▊ ▏━━⎼▎▋┦┊▊▉▋▎▌▅▄▃▃▃▄▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▝▄▄▄▃▘▆▗▂▂▂▂▋▅▅▄▃⎺⎺▅▅▅▄▄▅▄▖▄▄▄▃▄▋ ▂▂┈⎽▗▖▅▄▂⎽╴▌▪▌▋▘▍▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺▪▲⎺⎺┯⎺▘▂▂▄▄▃▃▃▃▂▄▃▃▃▃━▅▄▅⎼▝▅▄▃▂▖⎺▝▃▂⎽⎺▅▘▎▊▏▌▏╴▗▉▍▊▝▝▊▎▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▄╵⎺▅▃⎽┈▆▃▂┓┡▅▄▃▃▂▃▘▅◀▎▊▎▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲⎺▆▅▃⎽⎺▅▃▂▘··▊┈⎽▃▅┯▅▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▘⎺▆▅▄▄▄▅▆⎺╴ ┄▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿╌▅┚╴▘╶ ┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽╵┊▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▃▂▲⎽▗▗▲⎼⎼▊▖▅▆▆▅▖▅▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▖▆▆▅▅▗▃▂▂▂▲▗▖▂▲▪⎼▎▍▄▃▃▊▌▆▆▅▅▄▖⎺▆▅▂▂▆▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▆▆▅▅▅▊▲⎽⎼▪▅▋▄▄▃▖▮▎▃▂▂▊▍▌▄▄▄▍▋▆▅▄▍▂┊▆▄▂▊·▍│╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅⎻⎻▆▅▘▄▍▄▃▃▋▃▍▃▃▂▊▂▃⎽⎺⎺▋▍▃▃▃▂▍▋▅⎻╾▌▅▃▂▄▂⎽▆▄▃▂▂▂▃▃▅▆⎺▖╳▂╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▅▅▅▗▂▗▃▂▂▂▍▃▂┈▂⎺▌▊▗▆▆▅▘▍▍⎼▄▄▍▊━╾⎼▋▖ ▊⎺▅▃▃╾▄▃▂▂⎽▂   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▋▄▄▃▃▘▮▌▲⎽⎺▆▄▊▆▆▆▅▍▋▗▄▃▃▌▎▍▂▂⎽▌▉⎼▃▂▝▃▂▎┈⎺▝▍╴▎▆┱╷▍▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂━━▲▂▄▆▆▆▆▅▅▘▅▌▄▃▃━▎▌▝▅▄▄▌▖▍▆▆▆▌▉▮┈▄⎺▆▄▂▅▃┙▋┊▌▎▋▖┝▌▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋▃▂▂▂▍▅▋▄▃━━▎▆▎▅▄▄▄▏▍▂▂⎽⎽▌▃▃▃▃▂▋▉⎺▆⎻◆▎▋╏⎺▆▃▆┻▊▂┈┈╴⎽▂▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗⎺⎺▆▆▆▃▄▗▄▄▃▃▮▍⎽⎽⎽▂▊▅▅▅▅▄▄▉▘▃▃▃▂▋ ━━⎼▃▍▍▍▋▊┈▋▎▌▗▄▃▃▄▅▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▘▆▆▅▅▘▆▊▂▂▆▆▋▅▘▆▆▅▅▘▅▅▄▄▅▄▖▆▆▅▅▆▌ ▎⎽┈▉▅▅▄▂⎽▏▋▌·▌▉▎▘▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺▪▝▆▆▆▅▘▂▂▄▄▃▃▃▃▂▄▃▃▃▃━▅▄▅⎼▝▄▃▂⎽⎽▅▝▂┈·▅▃▊▎▊▶▘┆┈▗▊▍▊▝▝▊▗▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▄▆▅▃⎽⎺▆▄▂╱└╷▄▃▃▃▃▄▘┈┕⎽▂▎▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲▄▅▃⎽⎺▅▄▂┈▘ ·▝▂▃▅⎺⎺▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃┑▆▅▄▄▅▅▆⎺┆┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿⎽▅⎻╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂⎽┊·╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▆▅▅▄▄▗▃▃▂⎺▗▆⎺▆▆▎▝▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅┱⎺⎺▆▆▗▃▂▂⎽▄▄▃▃▂▂⎺▎▍▂⎺▲▊▌▆▆▆▆▃▖▆▅▄▂▅╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎺⎺⎺▗┎▊⎼▄▃▖▏▋⎺⎺⎺▉▪▎▲▮⎺▊▍▌▅▅▅▍▋▅▄━▌·▆▄▂┈▊ ▍│╵·▆▅▄▄▃▂▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄⎽⎺▼⎺▍▄▍▃▂▂▋▃▍▆▆▆▊▂▃▆▆▅▋▎▃▄▃▃▍▊▄━⎼▗▄▂▅▃⎽▆▅▄▃▂▂▃▄▅▆┈┈▖▆▂╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘⎺⎺⎻▊▂▗▂▂⎽⎺▍▂▅▅▅▄▌▊▗▄▄▄▘▍▂▲▲▪▌▊━⎼▂▋▖┈⎺▆▄▂┳▄▃▂▖┷▂▃   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▅▅▅▄▘▲▌▆▆▆▅▄▊▃▃▃▃▘▋▂━━━▌▎▍▃▂▂▌▉▃▂▝▝▂⎽▗┈▉▝▍┈▎⎺┱▏▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝⎼━━┷▆▆▅▅▄▄▘▅▌▄▄▄▄▎▌▝▃▃▃▌▎▍⎺⎺▆▋▉▪┊▆▅▅▃▆▄▂▏▋┊▌┧▌╲▋▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋▂▂▂⎼▍▅▋━━━━▎▆▖▂▂⎽▂▏▗▏⎺▃⎺▍▖▄▄▄▃▌▉▆⎻━─▎▋▌▆▄▂▅▘▊⎽┈┈⎽▂▃▖▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▘⎽⎽⎽▊▃▄▃▃▂▂▂▮▍▆▆▆▅▅▅▃▃▃▃▃▘▘▄▄▄▄▋ ╾⎼▂⎽▍╷▅⎽┩▋⎺▎▊▗▄▄▄▅⎺▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▼⎺⎺⎺▖▆▗⎺⎺▆▆▋▅▋▃▃▂▂▘▅▅▄▄▅▄▖▆▆▆▆▆▌ ▎▊┈⎺▝▄▂▅▗┒▊▌▏▌▪┕┙▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺▪▝▅▅▄▄▘▂▂▄▄▃▃▃▃▂▄▃▃▃▃━▅▄▅⎼▝▃▂⎽▆▅▘▍▪┈▅▃▂▊▎▊⎽·╎┈▗▊▍▊▝▝▉▎▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▆▝▃▂⎺▅▄▂▍▅▅▅▄▃▃▃▄▅┈┈▋▂▄▂▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅▮▆▅▃⎽⎺▅▄▂┈┈▍▉⎽▂▃▅■▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃⎺▆▅▅▄▅▆⎺⎺▉▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿╌▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▘━■▆▊▗▄▅▆▆▅▅▅▅▄▄▗▆▆▆▅▖▆⎺⎺▆▎▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▘▃▂▂▎▃⎽⎽▄▄▄▃▅▅▅▅▎▍▆▆▆▅▌▗▆▆▆▗▆▅▄▃┊▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂▂▂▋▅▊▃▃▂▊▮▋▅▅▄▄▆▎▅▅▅▊▍▌▅▅▅▍▋▄━⎼▅▆▅▃⎽ ▊ ▍│╵·▆▅▄▂▂▂▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗▂▂⎽⎽▍▄▍▂▂⎺▋▃▍▄▃▃▊▃▗▄▄▃▋▎▃▄▄▃▍▋━⎼▂▗▂■▃┈⎺▅▄▃▃▃▃▄▅▆┈ ┈▖╹▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▆▆▆▊┶▉⎺⎺⎺▆▍▃▏▅▅▅▌▊▂▂▂▲▋▍▂▂▂▲▍▊⎼▂▪▋▖┈▆▅▃▂┱▄▃⎽┈▂▃▖   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅┙▆▆▆▆▘▲▋▅▅▅▅▄▊▄▄▃▃▍▋▝▃▃▃▋▎▝▃▃▂▌▉⎽▝⎺▊⎽▝▌┊▌▝▍┈▎⎺⎺⎺ ▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▅┯⎻⎻▆▆▃▄▃▃┛▅▍▂▂⎽⎺▎▌▎⎽⎽⎺▌▎▍▆⎺▖▋▉▅▆▄▼▃▆▄▂▎▌▋┊▌╏▎▂╵▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋⎼━━─▘▅▋▅▅▄▄▍▆▆▆▆▅▅▏▍▅▅▅▅▖▖▄▄▄▄▌▉⎻━─▃▎▋▆▄▂▆▄▘▊⎽┈⎽▂▄▘▎▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▘⎽▃▂▖▝▄▘▂▃▂▖▮▊▂▆▆▆▖▖▎━━▅━▘▘▄▄▄▄▋ ▃▂┈▋▍▍╹▋▌⎺▆▎▝▗▄▄▅⎺┈▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▅▆▆▆▄▋▅▋▂▃▃▂▌▅▅▄▄▅▅▖▆┈⎺▆◀▌ ▎▍┈▅▍▂▂▍▗┱▎▌▏▌┹▃▋▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▝▃▃▃▃▘▂▄◆⎺⎺⎺┻▃▂▄▃▃▃▃━▅▄▅⎼▝▂⎽▆▅▃▋▍⎺▅▄▂▘▊▎▊▂▂⎽╴▗⎽▎▘▝▝▊▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃▃⎺▅▅⎽⎺▅▃▂╴⎺▆▏▗▃▃▃▄▅⎺ ┈▂▄▆▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄┄⎺▅▃⎽⎺▅▄▂▃⎽┈⎽⎽▂▃▅▮▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃━▆▅▅▅▅▆⎺⎺┋┆▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴▘╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂╸⎽▅▆▪▊▗▄▅▆▆▅▅▅▅▄▄▖▄▄▄▃■▆▆▆▆▎▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅⎽⎼⎼▃▎▃▄▆▄▄▄┲▃▃▂▂┓▍▄▄▃▃▌▆▆▆▅▍▅▄▃▂┈▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎼⎼▃▋⎼▊▂▂┵⎺▅▋▂▂▲⎽▄▎━━━▊▍▌▅▅▅▍▋━⎽▂▅▅▃▂⎽·▊ ▍│╵·▆▅▂▂▃▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄⎽▃▂▂▎▄▍▲⎺⎺▋▃▍▄▄▄▊▃▘▄▂▄▋▍▃▃▃▃▍▋⎼▂⎺▃▲▄▂⎺▆▅▄▃▃▃▄▅⎺⎺  ┈▖╏▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▂⎽⎽▊⎽▉▆▆▆▆▍▃▃▂▂▂▋▊▃▃▃▂▋▍▂▲▲▪▍▊▂▲▅▋▃⎺▅▃▂▲▄⎼⎽⎽▂▃▅▖   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅┙⎺⎺⎺⎺▘▲▋▅▅▄▄▄▊⎺⎺⎺⎺▍▋▍⎺⎺⎺▌▎▍▂▂▂▌▉▮⎺▅▊▄▝▌ ▖▝▍┈▎·▌▉▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▆▅▆▅▆▆┻▃▃▂┛▅▝▅▅▅▅▎▌▅▅▅▅▌▖▍⎺⎺⎺▋▉▆⎻━⎼▂▄▂⎽▍▅▋┊▌╏▋▖╵▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋▂▃▂▂▘▅▗▄▄▄▃▍▆▲━■━━▏▍▅▅▅▅▍▃▃▄▄▃▌┊━⎼▂⎽▎▆▅▃▆▄▃▂▊⎽▂▃▄▆▃▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━▲▂▂▂⎼●▄▘▂⎽▂▉▮▊▃▃▃▂▃▖▘▂▂▂▂▍▘▃▄▄▃▋ ▂▮┈▆▍▍▊▋▋⎺▆▎▝▗▅▆⎺⎺ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▅▅▅▃▆▋▅▗⎺⎺⎺⎺▋▅▅▆▆▅▅▖▆▆▆▆◀▌ ▎▆▅━▌▖▌▉▌▍▊▌╿▌▃┬▍▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▪▂▃▂━▍▂▝▃▄▄▃▘▃▂▄▃▃▃▃━▅▄▅⎼▋┈▅▄▃⎽▗▍▅▄▂⎽╼▊▎▊▂▎▎▃▗▂▎▘▝▝▊▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▝▆▅▃▖⎺▝▃⎽▋⎺▆▅▘▄▃▄▄▆⎺▊┈▂▄▆▼▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▅⎺▅▃▂⎽▅▄▃▂▮┈┈▝▂▄▅▃▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃━▆▅▅▅▅▆⎺▼⎺·╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂━◀▅▅▖▊▗▄▅▆▆▅▅▅▅▄▄▅▂▲▲▪▖▅▆▅▅▖▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▂▂⎽⎼▎▃▃▄▃▄▄▄▪▪⎼▅▅▍⎼⎼⎼▊▍▅▅▅▄▍▃▃⎽⎽╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂▂⎼▊▄▊▂▂⎺⎺▏▗▂▂▂⎺▎▎▃▃▂▊▍▌▄▄▄▍▋⎼▂⎺▄▄▂┊▏·▊ ▍│╵··▃▂▃▄▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅⎼⎽▃▃▍▄▌⎺⎺▆▋▃▍⎺⎺⎺▊▂╍▂▂⎽▋▍▂▂▂▃▍▋┹ ▆▂▄▂▼▆▅▄▄▄▄▄▆⎺⎺┊  ┈▖╏▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▂▂▂▊⎽▉▅▆▅▅▍▂▆▆▆▅▌▊▄▆▆▆▋▘▝▄▄▃▌▊▮▆▅▋▖▅▄▃▂━▄▄⎽▂▄▅⎺▋   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▲⎽▮⎺▌▲▋▄▄▄▃▄▊▄▄▄▄▍▋▄▄▄▄▘▅▍▂▂⎺▌▉▆▅━▊▄▝▋╵⎺▝▍┈▎┃▋▖▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▅⎺⎻▗▆▆▲▂━━▌▅▌▲▲▲━▎▌▝▅▅▅▌▖▗▆▆▆▌▉⎻╾⎼▂▅▃⎽⎽▍▝▋┊▌╏▎ ┕▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗━━━━▘▅▗▃▃▃▃▍▆▂▂▃▂▂▮▍▂▂▂▂▌▮▂▅▄▅▋┊⎼▂┈╱▏▅▃⎽▅▃▂▂▊▂▃▄▆▃▅┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▆▂▃▃▂▂▝▄▘■⎽⎺⎺▮▊▆⎺■⎺▋┒▃▆▆▆▆▍▘▂▂▂▂▋ ▏▊▆⎻▍▍▄▊▏▆▅▖▝▅▆⎺▏⎺ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▗▄▅▅▅▋▅▋▃▃▃▃▌▪▂▂▂▂▂▘▅▅▅▅▅▌ ▎⎻╾▃▌▊┣▌┌▍▊▌▊▌⎽▌▋▌ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▍▲▂▲▲▍▂▎▃▃▃▃▍▃▂▄▃▃▃▃━▅▄▅⎼▋ ▃▂┈▊▝▅▄▂⎽▂▘▊▎▊▖▄▍▆▂▄┊┈▋▊▋▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▅▃▂▃▆▂┱▼⎺⎺▃━━▆▅▅⎽▆━━▆━━▅▆▄▃⎽⎽▅▝▼┈┈▆▅▄▏▗▄▅▆┳▍▂▂▄▆▼▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅▃▂⎽▅▄▃▂⎽●┈⎽▂▄▆●▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄╶◆⎺▆▅▅▅▆⎺╲▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂▂▄▖▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▅▄▄▄▄⎺▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▂▂▂╾▎▃▃▄▃▄▄▄▃▃▃▅▅▗▆▆▆▆▌▗▄▃▃▗▂⎽⎽·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌━━▂▊▆▊⎺⎺⎺▆▪▗▅▅▅▅▪▎▆▆▅▊▍▌━━━▗▋▂⎺▆▃▂⎽⎺▏·▊ ▍·┄·⎽▂▃▄▅▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▂⎼⎼⎼▍▄▌▆▆▆▋▃▍▄▄▄▊▃▏▄▄▄▋▍▍▄▂▃▍▋▪▆▄▌▃⎽⎺▆▅▄▄▄▅▆━▍⎽┈  ┈▖╏▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▃▃▃▊⎽▉▅▅▅▅▍▃●━━━▌▊▝▃▃▄▋▍▂▂▂▂▌▊▆▅━▋▆▄▃▂⎽⎽┰▂▃▄▅⎺▏▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▂▂▂⎽▍⎽▋▄▄▃▅▄▊▄▄▄▄▍▋▝▄▄▄▌▝▆▆▆▆▌▉⎻━⎼▊▆▝▋▝▌▝▍┈▎╷▋▎╷▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅⎺⎺⎺▖▆▆▲━━▲▌▅▌▂▂▂▂▎▌▎▂⎽⎽▌▏▗▄▄▄▌▉╾▃⎽▚▃⎽▖▗▍▅▋┊▌▂▋▪·▂▍▝▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▃▄▄▄▍▅▗▂▃▃▂▍▆▆▆⎺⎺▆▆▍▅▆▆▅▍▘▝▄▄▄▋┊⎽▪┈▅▆▄▂▅▄▃▂▂▊▃▄▆▃▅▆┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━┻▃▃▃▃▝▄▘⎺⎺⎺▆▲▊▃▃▃▃▘▅▏▅▆▆▅▍▄▎⎽⎽┊▋ ▏▆⎻╾▎▍╱⎺▆▅▅▖▖▆⎺◀▗┆ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▗▄▄▅▄▋▅▋▃▄▄▄▌▖▅▂▂▂▂▎▃▃▃▃▄▋ ▎╾▃▂▌▎┄╎ ▎▊▌▏▌▎▗▌▍ ▊▏▎▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▍⎼▂⎽⎼▍⎽▘▆▆▆▆▍┹▅▆▆▆▆▃━▅▄▅⎼▋ ▎⎽┈⎺▝▃▂⎽▎▝▃▊▎▊▖▉▘▂▄▆┊┈▝▝▋▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃┅▄▄▅▄▄▘━━▆▅▅⎽▆━━▆━━▝▄▂⎽▆▄▃▌▎┈▆▅▅▄▏▗▅▆▍▋⎽▃▄▆┯▃▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▅▆▆▃▂⎽▅▄▃▂⎽⎽╲⎽▃▄▆◀▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▮⎺▆▅▅▆▆⎺⎺▊▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂▂▂▖▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▂▂▂▂⎽▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▂▂▂▂▎▃▃▄▃▄▄▄▃▃▃▅▅▌▃▃▃▂▗▲▂▂⎼▍▃┊▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▃━▲▊▅▊⎺⎺⎺▆▪▶▃▃▃▂┱▎▂▂▂▊▍▍▃▃▃▗┫╺▆▄▃⎽▪ ··▊ ▍│·▂▂▄▅▅▅▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▂▄⎼⎼▍▄▌▅▅▆▘▃▍▂▂▲▊▃▋▄▄▄▋▍▍▂▂⎽▌▋▆⎻━▌⎽⎺▆▅▅▄▅▅▆┈▎▝▂▖  ┈▖▆▂╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍⎼⎼▃▊⎽▉▅▅▅▅▍▃▄▄▄▃▌▊▌▂▂▂▋▍▆▆▆▆▍▊▅━⎼▗▅▃▂▂⎽▂┳▃▄▅⎺╴┊▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▂▂▂⎽▍⎽▋▄▄▃▅▄▊▂▂▂⎽▍▋▆⎺⎺▆▌▎▄▄▄▄▖▉╾⎼▂▊▍▝▋▘└▝▍┈▎·┈·▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▆▆⎺▊⎺▆▲▲▲▲▌▅▌▆▆▆▆▎▌▄▄▄▄▍▎▝▅▅▅▌▉▂┈▝▊▂┄▍▗▍▅▋┊▌▅▍┊▂▃▘ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▄⎻⎻▄▍▅▗▂▃▂▂▍▆▝▄▄▄▃⎺▍▅▅▅▅▌▘▎▂▂▂▋▉▏▖▅◆▄▂▆▄▃▃▂▃▝▄■▃▅⎺▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▆▃▃▄▃▃▝▄▘▆⎺⎺⎺▮▊▝▄▄▄▖▖▪⎽▂▂┈▍▗▅▆▆▆▋ ▅╺╾▃▍╏⎺⎺▆▅▅▎▋▎▋┕▏▅ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▗▃▄▄▄▋▅▗⎽⎽⎽⎽▋┱▃▅▆▆▅▉⎽⎽■▆■▖ ▎▂┈▊▌▉▉▌▉┱·▌▌▌╸▄▍▎ ▊▏▎▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▍⎼┰▪⎼▍⎽▍▅▅▅▅▍▊⎽▲▲━━▪━▅▄▆⎼▋ ▎▌▆▅▋⎽⎽▗▆▉▉▊▎▊┝▂▂▄▆⎺ ┈╲▂▘▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▃▆▃▃▂▃▅▮⎼━▪┰▎━━▆▅▅⎽▆━━▆━━▝▂⎽▅▄▂▊▌▆⎺▆▅▄▄╲▗▆┈▍⎽▃▅▆▆━▃▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅━▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▄▆▅▄▂⎽▅▄▃▂⎽⎽▂⎽▃▄▆▆▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─⎺⎺▆▆▅▆⎺▅▼╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂▂▂▖▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▖▃⎽┈·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▂▂▂▂▎▃▃▄▃▄▄▄▃▃▃▅▅▃▂▃▃▄▗▅▂▂▂▍▃╵▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▃━▲▊▅▊⎺⎺⎺▆▮▲⎽▄━⎽▆▘▂▂▆▊▍▍⎺⎺⎺▃▆▆▅▃▂▄┊ ··▊ ▍ ▂▂▄▅▆▆▅▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▂⎽▄⎼▍▄▌▆▆▆▋▃▍▃▃▃▊▂▄▆⎺▆▋▍▌▆▆▆▍▊▄━⎼▗▎⎺▆▅▅▅▆▆⎺┈⎽▂▃┊  ┈▖╏▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍⎼⎼▃▊⎽▉▅▅▅▅▍▃▂▂▂⎺▌▊▗▅▅▅▋▎▃▄▄▃▍▊━⎼▂▗▄▃▂▂▂▂╈▅▆▖▄▉ ▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▂▂▂⎽▍▲▋▄▄▄▅▄▊▆▆▆▆▍▋▂▃▃▃▌▎⎽▲▲▲▌▉▃▂╱▊▝▝▗┊⎺▝▍┈▎╏▎▝▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▆▆▆⎺▖⎺▆▲━━▲▌▅▌▄▄▄▄▎▌▃▄▄▃▌▎▍▂▂▂▋▉▪┈▆▉⎽▝▍▉▋▝▋┊▌▗▌▂▃▅⎽ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▄⎻⎻▄▍▅▗▂▃▃▂▍▆▮▅▲━▪⎺▍⎺⎽▮┈▌▖▎▆▆▆▋▉▆▅━▲▃▆▅▄▃▃▃▄▝■▃▅⎺▖▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━▃▃▄▃▃▝▄▘⎺⎺⎺▉▮▊⎽▂▂▂▊╶▎▅▅▅▅▍⎽▅▃▃▃▋ ━⎼▂⎽▍▍⎺▆▆▅▆▎◀▎┏▌▗▃ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▗▄▄▄▅▋▅▋▆▆▆▆▌▖▋▅▅▅▅╱▘▂▂▃▂▊▉▎⎽┈⎺▌▌╱▍▗▎▊▌▏▌▗▆▋▎┈▂▃▘▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▍⎼▂⎽⎼▍▂▍▆▆▆▆▍▗▖▂▂⎽▅▎▅▅▅▅▆▋┈▎▆⎻━▋ ▉▉┊▶▪▊▎▊⎽▂▄▆⎺╴┈▂▘⎽▘▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▃▃▂▃▆⎽▂▃⎽┈▎▝▄▅▅▄▅⎺━━▆━━▋ ▝▃▂⎽▊▋⎺▆▅▅▅▅▏▌┈ ▃▃▅▆▆▆━▃▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▉▆▆▆▆▆▃▃▄▄▅▅▅▄▃┳⎽▃▂▂▃▆▄▃▃⎽▝▄▃▂▂⎽▪▂▃▅▆▌┭▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄⎺⎺▆▆▆▆⎺⎺▆⎺╶▊▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂┷▂▂⎽▖▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▂▂▂⎼▎▃▃▄▃▄▄▄▃▃▃▅▅▃▂▃▃▄▊▅▆▅▅▖▃╵▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▲▂▂▊▘▊▂▂▆⎺▏▲╸⎽╺▅▅▗▄▄▄▄▍▗▅▄▄▍▅▅▃▂┉⎽  ··▊ ╴⎽▃▄▅▆▆▆▅▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▂⎼▃▃▍▄▌⎺⎺▆▋▃▍⎺⎽⎺▊▃●▃▃▃▌▍▌━━■▍▋━⎼▂▗┇▆▆▅▅▆⎺⎺┈⎼▂▃▄▖  ┈▖╹▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▃▃▂▊⎽▉▅▆▅▅▍▂▅▆▆▆▌▊▌▅▅▄▋▎▝▄▂▄▌▊⎼▂▪▗▃▃▂▂▃▃▼▉⎺⎺▊▝┊▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎽▂⎽⎽▌▲▋▄▄▄▆▄▊▄▄▄▄▍▋▍▂▂▂▌▗▍▂▃▂▌▉⎽▝⎺▊▖┓▋┈▊▝▍┈▎▊▉▊▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅⎺⎺⎺▖▆▆▲▂▂━▌▅▌▅▆▅▂▎▌▆⎺⎺⎺▌▄▆▆▆▆▋▉▝▆⎻▊▖▊▍▗▍▝▋┊▌▃▂▄▅▂▂ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▄▃▃▃▘▅▗▃▃▃▃▍▆▃▃▃▃▃▆▝▄▄▄▄▍▂▍▃▃▼▋▉⎻━⎼▃⎽▅▄▃▃▃▄▄▊▃▅⎺┈▪▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━┻▃▃▃▃▝▄▘⎽⎽▆⎺▮▊⎺⎺⎺⎺▆▖▎▄▄▄▄▍▘▝▃▃▃▋ ▃▂┈▊▍▋⎺▆▆▆⎺▎◀▎▉▍·▋ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▗▄▅▅▅▋▅▋▄▄▄▄▌▪▖▮╍⎽▂┣▃▆⎺⎺⎺▋ ▎▌⎺▅▌▍▌▌┡▍·▌▝▌▘▖▌▌▂▘▅▘▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▍▲▂▲▲▍▂▎▄▄▄▄▍▋▂▄▄▄▄▉▂▂▂▂▂▖ ▍⎻╾⎼▋▍╴┊⎺┩▪▊▎▊▃▅▆▘┅▎▂▃▃▚▋▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▆▅⎺⎺⎺▎▋▝▄▄▄▖▎━━▆━━▋ ▍▘┈▌▝▆▆▅▅▅▅▆⎺▌ ⎽▃▅▆▂▆▆■▼▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅╴▄▄▄▄▄▃▼⎺▼▼▅▝▄▃┳⎽▃▂▃▅▄▃⎽▂▅▝▃▂▂▂▃▂▃▅⎺▼▘┭▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺▆▝⎺▆▆▆▆⎺▄▄⎺┘╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂╍◀▅▅▖▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▲⎽⎼⎼▎▃▄▆▄▄▄▄▃▃▃▅▅▃▂▃▃▄▃▂▃▃▂┳▃╵▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂⎼⎼▋▘▊▂▂▂⎺▏▲╸⎺·▅▅▅▂⎽▂▮▗▂▂▂⎽▍▄▃▂⎽┉╱ ▉┊ ⎺┈▂▃▄▅▆⎺▆▆▅▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▄▄▃▃▍▄▍▲⎺⎺▋▃▗▆▆▆▆▃▅▃▃▃▋▍▍▃▃▃▌▋⎼▂⎽▄⎺▆▆▆▆┒▌▪⎽▂▃▄▄▖  ┈▖▆▂╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▂▂▂▊⎽▉▆▆▆▆▍▂▅▅▅▅▘▊▌⎺⎺⎺▋▎▍▂▂⎽▌▊▂▪▅▄▃▃▃▃▄▅▌▊│┊·▉┊▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎺⎺⎺⎺▌▲▋▅▅▄▄▄▊▃▃▃━▍▋▍▆▆▅▌▎▅▆▆▅▍▉⎺▅▅▊▄▌▌┊▊▝▍┈▎┢▎▉▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▅▅⎻▆▆▆┻▃▃━┛▅▌▄▄▄▄▎▌▃▃▃▃▌▏▃▃▃▃▖▉▆⎻━▉▏▍▍▉▍▋▋┊▌▂▄▅▂▃▖ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗━━━▃▘▅▗▄▄▄▃▍▆▂▂▂⎽▂╏▍▄▄▄▄▍▘▝▃▃▃▋┈━⎼▃▂▅▄▄▃▃▄▅┩╌▅⎺▖▆▋▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━▂▂▂▂▂▝▄▘⎽⎽▆▉▮▊▆▆▆▆▆▖▎⎺▼◀⎺▍╸▎┐⎺╱▊ ⎽▘┈▝▍▆▆▆▆⎺⎺▎·▎▉▍·▋ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▅▅⎺▆▆▋▅▋━━━━▌▄▄▄▄▄▅┃▂▃▃▃▃┛ ▎▆▅⎻▌╌▎▍▗▎▊▌┊▌┎▄▶▂▄▘▅┈▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▪▂▃▃━▍▂╽▂▂▂▂▌▊▝▄▄▄▖┃⎺▂▃▃▃▊ ▎─▃▂▋┒▎┻▉┨▏▊▎▝▅▆▍▌⎽▂▃▃▃▖▊▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆▅▆▆▆▆▎▗▖▅▆┈⎺▏▆▆▆▆▆▋ ▍▘ ▝▝▆▅▅▅▆▆⎺▌⎽▂▃▅▆⎺▂▆▅▆▼▃▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▊▂▃▃▃▃▚▝▃▄▄▃▄▝▃┳⎽▃▂▝▃▂⎽▆▅▄▝▂▂▂▃▂▄▅┳━▄▘┭▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯╶▅╴▆▆▆⎺━▝▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂╶▪▅▆▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅⎽⎼⎽▂▎▃▄⎽▄▗▄▄▃▃▃▅▅▃▂▃▃▄▃▄▃⎺▂▂▃╵▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎽⎽▂▋▄▊▃▃▂▊▘▲╸⎺·▅▅▅▅▄▅▆▗▄▂▂▄▍▂▂⎽┊╴╱  ··┅▂▃▄▆▆⎺⎺⎺▆▄▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄▂▂▂▂▎▄▍▂▂⎺▋▃▗▆▆▆▅▂▄▆▆▆▆▍▗⎺▆▆▌▋┹⎽▝▆⎺▆▆⎺┈▍▂▂▃▄▄▅▄▖  ┈▖╹▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘⎽⎽⎽▊▂▉⎺⎺⎺▆▍▂▄▅▄▄▘▊▅▅▅▅▋▎▗▅▅▅▌▊⎽▅▅▄▃▃▃▄▅▆▏▊┇╵▊▎ ▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅╶⎺⎺⎺⎺▘▲▋▅▅▅▅▄▊━━━━▍▋▌━━━▌▎▂▄▃▄▌▉⎺▆⎻▊▏┓▋┈▝▆▍┈▎·▎╻▏▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▄▆▆▅━▆▆▃▄▄▃┛▅▌▄▄▄▃▎▌▝▄▄▃▌▘▝▃▃▃▋▉⎻━━▉▏▍▍▗▌▅▋┊▝▄▅▂▃▃▖ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋▂▂▂▃▘▅▋▅▅▅▄▎▆▂┈┈▂▉⎺▍●┹▂⎽▌▅⎺⎺⎺▆▋┊⎼▂⎽⎽▅▄▄▄▄▅▂▏▉⎺┈▌▘▋▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━⎽⎽⎼⎼⎽▝▄▘▂▂⎽▖▮▊▅▅▅▅▘▄▄▅▅▅▅▎▃▗▄▄▄▋ ▏▊┊⎺▍⎺▆▆╴⎺▊▎┕▎▉▍·▋ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▄▂▂▂▗▆▅▆▆▆⎺▋▅▋━━━━▌▪▊▅▅▅▅▊▘▝▄▄▃▊ ▎▅⎻━▌▘▍▍▝▗┫▌▋▌▘⎽▃▄▅▅▅╲▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺⎽▝▃▄▃▃▘⎽╽▂▂▂⎽▌▗▖⎽⎽▂▃┣▄⎺▆⎺⎺▊ ▎▃▂▂▋┄·╷┹▋▄▊▏▆⎺┊▎⎽▃▃▄▃▃▂▊▂▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▄▅▅▅▅▎▋▃▄▄▄▄▊▂▂▂▂▃▖ ▍▘┈▆▝▅▅▆▆⎺⎺◀▊▂▄▆⎺■⎺⎺▅▄▄▆▼▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▊▲▂▂▲▪▚▌▃▃▃▃▖▎▃┳⎽▃▂▋▂⎽▆▅▄▃▋▂▂⎼▂▄▆⎺⎽━▄▘┭▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▄▃⎺⎺▼▼▄▄▄▄▃⎺▆⎺┳⎻⎺⎺▆▆·⎺▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▖▘▂▂⎺▎▃▂▂⎽▄▄▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▅▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂▂⎺▊▗▊⎼▄▃▖▅▲╸⎺·▅▅▅▅▄▅▆▊▅▅▅▅▖▂▘▘⎽╴╱ ▉┊⎽▂▃▅▆⎺▪■⎺▆▅▄▖▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗▂▆▂⎺▍▄▍▃▃▂▋▃▗▆▆▆▅▃▄▄▄▄▖▍▄▄▄▃▚┫▲┊╹▆⎺⎺■⎺⎽⎽▆▗▄▅▅▅▄▖  ┈▖╏▆╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▆⎺▅▊▂▗▂▂⎽⎺▍▂▅▅▅▄▄▊▃▃▂▂▋▎▍━━▅▌▊▆⎺▆▄▄▄▄▅▆⎺▌▊▪┍▎▉ ▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅┙▆▆▆▅▘▲▌▆▆▆▆▄▊▃━━━▍▋▝▄▄▃▌▎▝▃▃▂▌▉▆▅⎻▊╎▝▋┈▊▝▍┈▎▌▎╴╵▮▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝⎻⎻⎻▄▆▆▅▅▄▄▘▅▌▄▄▄▃▎▌▎⎽▂■▌▗▖⎺⎺⎺▌▉━╾⎼▉▏▍▍▗▌▋▋┈▝▆▂▃▄▄▖ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋▃▃▂▂▌▅▋━━━━▎▆▂┈┈▂▉⎺▍▅▅▅▅▍▂▄▄▄▄▖┊▂▪┈╸▄▄▄▅▆▂▃┓▊┊ ▌▆╎▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂▂▂▂▊▃▄▃▃▃▂▂▮▊▅▅▅▅▘▃⎽▂▂▂━▘⎺▝▄▄▄▋ ▏▮┈▆▍▆⎺┐▎┈▘▎◀▎╷▍▏┊ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▅▃▂▂▲▪▆▗⎺⎺⎺▆▋▅▋━━━━▌▪▊▂▂▂▂▎▘▎⎺⎺▉▊ ▎━━━▌▎▍▄▊▎▊▌▏▌⎽▃▄▅▆▆▅▘▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺▪▝▅▅▅▄▘⎺╽▂▂▂⎽▌▊▆▆▆▆▆▉▖▃▄▄▃▘ ▎▘┈⎽▋▌▘▉▘▂▂▘▘⎺ ┊▂▃▄▄▄▃▂▝▊┗▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▄▅▅▅▅▎▋▂▅▅▅━▊┈▃▃▃▃▊┊▍▌┈▆▝▅▆▆⎺⎺▍▚▂▄▆⎺⎺⎺⎺▆▅▃▃▄▆▃▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▊▂▂▂▲▂▚▌▎▘┈⎽⎽▆▆┳▆▆▆▊┈▝▄▄▃▃▋▃⎼▃▄▆▆▅⎽━▄▘┭▅▅▅▅▅▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▝▅▅▅▄▅▝▄▄▄▃⎺▆▗⎺⎺⎺⎺⎺⎺▅▝▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▖▆▆▆▆▗▃▂▂▂▲┱▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▅▅▅▆▆▂▂▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎺⎺▆▖▅▊▂▲⎼▪▅▲╸⎺·▅▅▅▅▄▅▆▆▃▃▂▂▂▌▲▘⎽┊⎽▪┈⎽▃▄▅▆▪⎺⎺⎺⎺▆▄▃▂▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄▆▅⎺⎻▍▄▍▄▄▃▋▃▗⎺▆▆▆▃▃▃▃▂▂▍▍⎼⎼⎼▝┫▲┊▼▆⎺⎺▍┈▶▂━▗▅▅▅▅▄┊  ▝▖⎺┒╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▆⎻▆▅⎺▗▃▂▂▂▍▂▅▅▅▅▘▊▝⎼▄▄▋▎▍▂▂▂▌▊⎺▆▆▄▄▅▆⎺├▃▏▊┇╸▋▝┊▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▅▅▄▄▘⎽▌▲⎼⎺▆▄▊▄▃▃━▍▋▍▂▂⎽▌▎▍▅▆▆▌▉▅⎻▄▊▝▝▌┈▋▋▍┈▎▊⎽╷▲▮▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂┗━━▃▂▆▆▆▆▅▅▅▅▌▅▅▄▄▎▌▎▆▆▆▌▏▄▄▄▄▌▉━─⎼▉▏▝▎▌▍┈▋┈▆▂▃▄▄▃▖ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▋⎼⎼⎼▃▍▅▋▄▄▃━▎▆▂▂▂▂▂▏▍▄▃▃▃▍▏⎽▅▄▄▋ ⎽╸┈▶▄▄▅▆▂▄▅▶▊┊┈▎╴▪▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▘▂▆⎺⎺▃▄▪▄▄▄▃▮▊▆▆▆▆▅▖▎▄▄▄▃▍▘▎⎽▂⎻▊ ▏▖⎺▆▍⎺▖▉▌┈▋▎◀▎▗▎▏┊ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▘▆⎺⎺▆▆▆▊▂▂▂▆▋▅▋▃▃━━▌▪▊⎺⎺⎺■▎▖▗▅▅▅▋ ▎━━━▌▌▪┊▃╴▊▌┊▝▃▄▅▆▆▅▅▘▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺▪▝▆▆▆▅▘▂┃▃▃▂▂▌▋▗▄▄▄▘▊▂▝▄▄▄▋ ▎▂┈⎽▋▋▌⎽⎽▂▄▘┝▍┈▂▃▄▄▄▃▂▪▝▊▎▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▅▆▆▆▆▎▋▝▃▃▃▃▗▅▎⎺┊▗▋╴▍▖▆▆▝▆⎺┈▋▎⎽▃▄▆⎺▂⎺⎺▆▅▃▂⎽▂▄▎▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▊▃▃▃▃▃▚▗▆▆▆▆▆▊▃▃▃▂▃▖┈▝▃▃▃▃⎽▂▃▅▆▆▄▅⎽━▄▘┭▅▅▅▅▄▄▅▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▝▂▂▂▂▃▝▄▄▄▃⎺▂⎺⎺⎺⎺⎺⎺▄▘▃▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▖▅▅▅▄▗▃▃▃▃▂▂▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▅▅▅▆▅▃⎽▄▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▆▅▅▗▅▊▃▂▂▂▘▲▶⎽━▅▅▅▅▄▅▆▅▲▮╸⎻▃▌▲▘⎽┊┈⎽▂▃▄▅▆┈⎺⎽▂■▆▅▃▂▄▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅⎻▆▅▅▘▄▍━▅▄▋▃▍▂▂⎽▊▃▂▂▂⎽⎽▗▃▂⎺⎽▄▆▪┊⎽▗▎⎽■▗▂▃▅▗▆▆▅▄▃▖  ▝▖▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▅▅▄▄┷▗▄▃▃▃▍▃▎⎺▆▆▌▊▄▃▃▃▋▎▍⎺▆▆▌▊▆▆▅▗▅▆⎺ ┃┫▶▊▶▍▝▉ ▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▝▃▃▃▂▍▲▗▂▂⎼⎽▃▊▅▅▄▄▍▋▍▂⎺⎺▌▎▗▄▄▄▌▉⎻▄▄▊▆▝┪╴▝▊▍┈▎▗┛⎽╹▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▲▂⎼⎼⎼▆▆⎺⎺⎺▆▆▅▌▃▆▆▂▎▌▆▆▅▅▌▏⎽▅▅▄▌▉─⎼⎼▉▏▎▍⎽⎽▃▘┊▗▄▄▄▄▃▂ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▂▂⎽⎽▍▅▋▅▅▄▄▎▆▎▃▃▃▖▏▍▃▄▆▂▘▘▎▂▘┈▋ ⎽▪┈⎽▅▅▆▂▄▆⎺▍▊┊ ▌╷▶▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▆▆▆▅▅▝▄▎━━▂┱▮▊▏⎺⎺⎺▋▖▎▃▃▂▂▍▄▆▆▆▅▋ ▏▖┈⎺▍▍▂▉▌▋▘▎╱▎╷▍▏┊ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▘▅▅▅▅▘▆▊▂▂▂▂▋▅▋▅▄▄▄▌┳▊⎺⎺⎺▆▊▂■■▆━▋ ▎━━━▌▊┋▖▍▎▊▌▏▝▅▆▆▆▆▅▄▎▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺┑▲⎺⎺┯⎺▌▂▎▄▄▄▄▌▋▃▃▂■▪┫▆▎⎽▘┈▊ ▎⎽┈⎽▋▗▂▂▃▄▆▍▊▍┊⎼▄▅▄▄▃⎽▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▖▅▆⎺⎺▎▋▍▂▂▂▂┠▂▅▅▄▄▘╴▍▖⎺⎺▆▖▎ ▪⎽▃▅▆▼⎺▼⎺⎺▆▄▂┈ ⎽▂▘▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅▉▅▅▄▄▄▃▗▅▅▅▅▅▊ ▄▃▃▃▊┈▝▃▃⎼⎼▂▃▅■⎺▅▄▅⎽━▄▘┭▅▅▅▼■▼▄▆▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▎╾┯⎼⎼▂▪▅▄◆┯●▼⎺⎺⎺▆⎺┬▄▘▃▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▖▄▄▃▃▗▃▅▄▄▃▖▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▅▅▅▆▄▂⎽▄▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▋▅▄▄▃▘▖▄▃▃▃▅■▂▂━▂▅▅▅▄▅▆▅▅▋▝⎺▃▌▲▘┈┉▂▂▃▄▆⎺⎺⎽■▂▂⎺▆▄▂▃▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄━▄▄━▘▄▌━━━▋▃▍▄▃▃▊▃▂▂▂⎽⎽▗▆▆▆▅▅▆▪┊⎽▋▂▂⎽▂▄▄▆▌▆▆▅▄▂┈ ┈▆▖·▆▆▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▝▄▃▃▂▂▗▅▅▄▄▍▃▃▂▂⎽▌▊▄▃▃▂▋▎▅▅▄▄▖▊▆▅▅▋▆⎺⎺▝▖▍▌▊▏╹▊⎼┊▌   ▝▏▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▊▂▂⎼⎼▍⎽▗▃▃▂▂▝▊⎺⎺▆▆▍▋▍⎽⎺⎺▌▎▍━━┳▌▉▅▅⎻▊▆▝▊┈▌▝▍┈▎⎽▂⎽·▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂⎽▂▂▂▂▆▆▂⎽⎺⎺⎺▅▌▅▄▄▄▎▌▆▅▅▅▌▘▝▃▂▂▋▉─━─▊▎▅⎽⎽▃▄⎽┈▗▅▅▄▄▂⎽ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗⎺⎺▆▆▍▅▋▆▆▆▅▍▆●▂▲▲▪⎺▍▃▆▅▂▘▃▎▗⎺▆▌┊▂▪⎽⎽▆▆▃▄▆⎺▉▍▊┊┈▎ ▶▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▅⎻⎻▄▃▝▄▍▄▃▃▃▮▊▝▂▂▂▘▖▎▃▃▂▂▍▂▄▄▃▃▖┈▏▅┈▖▍▎▍▋▋┈▋▎╷▎▉▍·▃ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▝▄▃▃▃┛▆▊▄▃▃▃▋▅▗⎺▆▆▆▌┳▊┓⎺▆▆┃●▝▃▃▃▊ ▎━━┙▌▌▗▍▋╸⎽▌▎▝▆▆▆▆▅▘▃▎▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺┑▂▂▃▼▼▼▂▍▃▃▆▆▍▋▃▂■■▪╋▘▎⎺╴┊▊ ▎▂┈⎽▋⎽▂▃▅▆▍▍▂⎽▪▪▅▅▄▃▂┈▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▅▂▂▂▂┈▎▋▍▂▂▂⎽▊▖▂▆▆▆▊╴▍▪┈┝▊▌▋┈▂▃▅▆━▼▅▼┈▆▄▃┈ ▆▄┛▌▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅⎼⎻⎺·▅▅▃▗▅▅▅▅▅▊┈⎽┈⎽▘▊▏▝▄⎼▂▃▄▆▲▝▆▅▄▅⎽━▄▘┭▅▅⎺▆▅▆┑⎺▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▍┭⎼▄▄▂▝▅▅▅▄▅■⎺⎺⎻▪▄─▄▘▃▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▆▃▃▂▃▃▃▆▅▅▄▖▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▅▅▄⎽▂⎽⎽▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▃▃▂▂▄▊▅▅▄▄▅▗▄▄▃▃▆▅▅▄▅▆▅▅▋▝⎺▃▌▲▘▂▂▃▄▅▆⎺▏┈▂■▂⎺▆▅▃▂▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅━━─▂▍▄▌▄▃━▋▃▍▃▂━▊▃▃▃▂▂⎽▋▅▅▄▄▄┫▲⎽⎽▌▃⎼▂▄▅▆▎▌▆▆▅▃▂┈ ▆▅▖▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▌▂⎼⎽▊⎽▗▃▆▅▅▎▃▲▅▄▃▌▊▝▄▃▃▋▎▄▃▃▂▖▊▅▅▄▋▖┈┃▝▝╷▏▊┃┆▋▆╷▌   ▝▗▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▊⎼▃▂⎺▍▲▌▪▄▄▖▝▊▃▂▂▂▍▋▍▂⎽⎺▌▎▍▄▄▃▌▉▅▅▆▊▖▝▋┈▊▆▍┈▂▂▂⎽▶▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂◀⎽⎽⎺▆⎺▆▃▂▂⎽▋▅▌┈⎺▆▆▎▌▎▆▆▅▌▘▍⎽⎽⎽▋▉━━━▊▏⎽▂▃▅▂▃┊▗▅▅▄▃■▘▝▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▅▼⎻⎻▆▅▋⎺╴·▆▍▆▅▅▄▄▄▆▍▃▃▃▂▍▖▆▅▅▅▋ ▂▂▂▃⎺▃▄▆╴┈▉▍▊┊ ▌╷▋▝┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▗▃▃▂▂▂▝▄▘▅▅▄▄▲▊━▅▅▄▖▖▎▄▃▃▃▍⎽▃▂▲━▖ ▎▊┈▋▍▌┌╹▊┈▍▎╷▎⎽▍▏┊ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅╺▂▂⎼⎼▌▆▉━▲⎼⎼▋▅▋▂▃⎽▂▋▪▊┊⎺⎺⎺┃▘▎▂⎽▘▊ ▎▃⎻▘▌▋▊▉▍⎽▃▘▌▆⎺⎺▆▆▄▃▖▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺■⎼⎺┑▂▂▂▄▄▄▂▘▆▅▅▅▍▊▗▃▃▃▼╋▂▎▅▅▅▋ ▎▄▂▃▋▃▄▅⎺▎▎▂⎼⎼▪▅▅▄▃▂┈┈▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃┅▂━▲━━▘▋▝▃▂▂▂▊⎽▅▄▄▄▊╴▍▖┈[48;2;47;47;47m▋▊▌▋▂▄▅⎺▼▼▄⎺⎺▆▅▃⎽ ▆▅▃▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▗▆▆▆▆▅▗▆┖┈▃⎺▊┊⎽⎼▂▃▄▆⎺■▝▆▅▄▅⎽━▄▘┭▅▅▆▄▃▃▅▘▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▝▂▲▲▲▂▝▃▃▂▂▃▅■┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄⎺ ╴▪┏╸┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▆▂▲⎽▪▃▃▆▆▅▅▎▄▃▃▃▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▅▄▄▃▂▂⎽⎽▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂⎼⎼▋▅▊▆▅▅▄▘▗⎺▆▅▅▗▅▅▄▅▆▅▅▋▝⎺▃▶▂▂▃▃▄▅▆◀▍▲▂▂━▂⎺▆▄▂▂▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▲⎼▃▃▍▄▌▅▄▄▋▃▍▆▅▄▊▃▄▄▃▃▂▊▅▄▄▃▄┫━▂▃▌━▂▄▅▆▊▎▌▆▅▄▂⎽ ┈▅▄■▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▃▂▄▊⎽▗▄▄▃▄▎▂▝▄▃━▌▊▃━▲⎼▋▎▃▂▂▲▌▊▌▮▪▋▃┈▊▉│▊▏▊●┣▝ ┈▋   ▝▗▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▂┊⎺▆▍⎽╺━▲━▪▝▊▂▅▅▄▍▋▝▃▃▂▌▎▝▃▃▂▌▉▆▆⎺▊▍▝▋┈╵┈▍┈▂▂▂╸╱▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▆⎺⎺▆▅▆▆▄▃▃▂▌⎽▌▃▃▂▂▎▌▎⎽⎺▖▌▎▍⎽⎺┳▋▉┅⎻⎻▊⎽▂▃▅▆▃▖┊▗▅▄▃▂▅▘ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗⎻━━⎻▘▅▗┈⎽⎺⎺▍▆▖⎺⎺⎺▆▏▍▅▅▄▄▍▖▅▄▄▄▌┊▃▃⎼╼▃▄▆⎺▖┈▉▍▊┊ ▌▘⎺▆▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▆▂▃━▂▂▝▄▘▆▆▅▅┗▊▅▄▄▃▘▃▎■━▅▄▘▏▂▅▄▄▋ ▏▊┈⎽▎▍▆▊▍┈▍▎╷▎⎽▍▏┊ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌▃▂▃⎽▌▆╺▃━▂━▋▅▋▅▅▄▄▌▪▊▂▃⎽⎽▎▘▎⎽⎺▪▊ ▎▅▆▊▌▊·⎽▂▃▅▘▋⎺⎺⎺▆▅▃▂┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆⎺⎺⎺⎺▆┑▂▂▂▄▄▄⎽▎▂▂⎽▅▍▊▌▅▅▄▘▊▲▅▄▄▄▋ ▎▃⎼╼▝▅▆┈▊▎┻▃▲━┯▅▅▄▂╴┈▆▋▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆▆▅▅▅▅▘▋▝▅▄▄▖▊▂▄▃▃▃▊┊▍▏ ▌▊▌▂▄▆⎺▼▄▃▄⎺⎺▅▃▂ ┈▅▃▂▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▌▎▅┊▗⎺▗▅⎺⎺▆▆▘⎽▂▃▄▅⎺┈▲■▝▆▅▄▅⎽━▄▘┭▅■▅▃⎽⎽▃▘⎻─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▝▄▃▃▃▄▋▂▂▲━━▃⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄⎺ ╴▪┣⎺┈▎⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅━▄▃▃▃▃▘⎺▆▆▎▖▂━▮▅▅▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▆╸▃▄▂▂▂▂⎽⎽▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎼▃▂▋⎼▊⎺▆▆▅▆▋▄▃▂⎺▗▅▅▄▅▆▅▅▋▝⎺▃▃▃▄▄▄▆⎺⎽▲▂▃▃▃▲⎺▆▅▃▂▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▃▂▂⎽▍▄▍▆▅▅▋▃▍▂⎺⎺▊▂▅▆▅▅▖▗▄▄▃▃▘▋⎼⎼╼▂▃▄▅⎺⎺▊▎▌▆▄▃⎽▘┈▆▄▂▮▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍⎺⎽▆▊▂▗▅▄▄▃▍▃▌⎺▆▆▌▊▗▄▄▃▋▎▃▂▲▪▌▊▂▂▂▋▃┈▉▌▌▍▏▊▍▝▍╴▆▖   ▝▂▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎺▆▼⎻▍⎽▝▃▃▂━▝▊▅▅▄▄▍▋▍━▅▄▌▎▝▃▂▂▌▉┊▄▆▊▊▝┫▉⎽▂▎┈▃▂⎽·▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▆▆▆▅▅▆▆▲▄▄▃▌▅▝▃━▲━▎▌▝▃▂▘▌▎▍⎺▅╍▋▉▅▅▆▉▂▄▅▂▃▅▖┊▗▅▄▂▆▄▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▅─⎼▃▘▅▗▂▂▼▂▍▆▏▄▃▃▂▮▍▏⎺▆┈▍▖▅▄▄▃▍┈⎼╼━⎻▅▆⎺┑·┈▉▍▊┊ ▌▎▆▄▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅━⎼⎼▃▄▝▄▘┈┈▆▄▮▊▎▮⎺⎺▊▅▄▄▄▃▃▘▏▲▅▄▄▋ ▎▶⎽▖▍▌▝▍▌▊┃▎╷▎⎽▌┊▎ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌┈┊▆⎺▌▆▆▅▄▃▃┛▅▋▅▄▄▃▌▖▊▄▄▃▃▎▘▎⎽⎺┅▊┊▎▆┈▉▌▎⎽▂▄▅▆▍╿⎺⎺▆▅▄▂▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺┳╴▆▆▆▆▪▂▂▂▄▄▄⎽▪▅▄▃▃▍▗▖⎺⎺⎺⎺┠▲▅▄▃▄▋ ▎╼━▘▅▖▍┈⎽▪▲▲▲▮▅▅▄▃⎽⎺┊▘▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▅⎺▆▃▋▄▃▃▂▂▊■▄▃▃▂▊┊▍▘┈▂▝▃▄▆■▼▅▄▃▼⎺▆▄▂┈┊▅▃⎽▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▌▃▂▂⎽▖▗▅⎺▆▆▆▘▃▄▅▆▅▘⎽▲●▝▆▅▄▅⎽━▄▘┭■▅▃⎽ ⎺⎽▂▝─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▅▄▆▆▆⎺▋▂▂━▪━▃⎺┳⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄⎺▉╴▪▍⎺▆▲⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴▘╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▄▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▄▄▃▃▃▃▎▂⎺▆▎⎽▄▃▃▂┱▃▂▃▃▄▃▄▂⎺▂▂▃╵▏·╸▗▅▂▂▃▃▂▂▃▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂▂⎺▋▄▊▂⎺▆▆▘▊▃▂▲▂▎▄▲⎽▅▆▅▅▋▝⎺▗▄▄▅▆▆⎺┈▂▃⎽▃▃▃▲▆▅▃▂▃▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄▂⎽⎺⎺▍▄▍⎺▆▅▋▃▍━▄▄▊▃▅▂⎺⎺▋▋▅▅▄▃▘▋┷━▄▃▄▆⎺▆╷▊▎▌▅▃▂⎽▃⎺▅▃▂┳▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▆┯⎻▊▂▗▆▅▅▄▍▃▄▃▃▂▌▊▌⎺▆▆▋▎▃▃▂━▌▊▃⎼─▋▖┈▊┝▝▖▏▊┃▎▋┮▅▖   ▝▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▅⎻▆▅▘⎽▝▄▃▃▃▝▊▂▂┭⎺▍▋▍▅▄▄▌▎▝▄▃▂▌▉⎽⎽▂▊▃▝▊⎽▂▃▎┈▂▂┛▉▝▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▅▄▄▄▆▆■━▅▄▌▅▌▆▆▅▅▝▌▃▆▅▄▘▎▍⎽▪⎺▋▉⎺┈▆╲▄▅▂▄▅▆▋┊▗▄▃■▄▂▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▄▃▂▂▌▅▗▃▂▂▂▍▆▝▃━■■▏▍▃▃▂▂▍▖▅▅▄▄▌┊━⎻▅▆⎺⎺▎▉▏┈▉▍▊┊ ▎⎺▅▃▎▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅⎼▃▂▂▖▝▄▘┊▆▆▆▎▊▝▄▃▃▖▖▘⎺⎺▆▆╿⎽■━▄▄▋ ▂▃⎼┘▍▌▌▊▌┈⎽▎╷▎⎽▌▗▘ ▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌┈▆▆▆▍▆▅▆▅▄▄▘▅▋⎽⎽⎺⎺▋▅▄▄▃■▪┨▘▎⎽⎽┉▊┊▎▌ ⎽▌⎽▃▄▅▆⎺▖▊⎺⎺▆▄▃┈▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▃▆▅▅▄▘┑▂▂▂▄▄▄▂▝▅▄▄▄▘▊▝▃▃▂▂┣┙▎▅▄▄▋┈▎⎻▅▚▋▍▊┈⎼▲▂▂▮▆▅▄▃▂▉▆▄▂▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃▗▍⎺▆▆▅▊⎽▅▄▃▃▊┈▍▘▖▂▃▅▆▼▃▆▅▄▼▼▆▄▂┈┊▅▃┈╶▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▝▃▂▲▲▂▗▆▝⎺⎺▆▘▅▆⎺▄▄▅⎽▲●▝▆▅▄▅⎽━▄▘╱▆▄▂ ┈▅▃▉▎─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎┚▄▝▃▂▂▲━▄⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄⎺·┆⎺▄▅▅⎺▲▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴▘╵╴┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▗▅▆▆▅▅▅▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▃▄▃▃▃▃▎▂▂▆▎▄▆▆▅▅▗▃▂▃▃▄▃▄▂⎺▂▂▃╵▏▂┈⎽▂▃▃▃▃▂⎽▃▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂▆▆▖▄▊▂⎺⎺▉▘▋▆▅▄▄▆▗▄▃▂▂▅▅▋▝⎺▃▅▆▆▪▗⎽▂▃⎼▄▄▃▂⎺▆▄▂▃▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄⎺⎺⎻▆▘▄▍⎽▆▆▋▃▍▅▄▃▊▃▗▂▲⎼▋▗▆▆▅▄▍▋⎻▅▆▗▆⎺▄▪⎺▊┏▗▄▂▲▄▃▆▄▂⎽▆▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍┯┱⎻▗▂▗⎺▆▅▅▍▂▝▃▅▅▌▊▌▄▃▂▋▎▅▄▃▃▖▊┶━▄▋▖┈▊▉▊▊▏▊▶├╴▆▄▂  ┈▝▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎻▆▅▅▘▮▗▅▄▃▃▝▊━▄▄▃▍▋▍⎽⎺⎺▌▎╏▅▄▄▌▉▂▃⎼▊▄▂┹▂▃▃▘┈▂⎽▎⎺▉▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▄▃▃▃▆▆▪━━▅▌▅▌▃▂▂⎺▎▌▆▆▅▄▌▘▝▂⎽⎽▋▉▪┈▮▂▆▂▄▅▆▆▋┊▗▄▂▅▃⎽▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▃▂⎼⎼▍▅▗▄▃▂▂▍▆▖⎺▆▅▅▏▍▄▃▂━▘▗▎▆▅▅▌▉▅▆⎺▃▎▌╴▋╴┈▉▍▊┊ ⎺▆▄⎽▖▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃━▃▂▂⎽⎺▃▄▘┊┊▆▆▏▪▄▃▃▆▖▖▏▄▃▂▂▍▂▃▂■━▖ ⎼╼━▘▍·▄▊╴⎽⎽▎╷▎╶▌·▋┈▍┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▗▆▅▅▄▍▆▆▆▆▅▅▘▅▋▄▃▃▂▌▪▖⎺⎺▆▆▊▏▝▂▂▃▊┊▎▊⎽▖▝▃▅▆⎺⎺▌●╿⎺▆▅▃⎽┈▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▅▅▄▄▃▘┑▂▂▂▄▄▄▂▂⎺▼⎺⎺┻▊▋▃▂▆▆●▃▎▆▅▆▋┊▍▖┊▊▋▍▪⎼▂▂▂▂▆▅▅▃▂⎺▆▄▎▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃▋▝▂▂┈⎽┃▃▂▅▅▄▊ ▍⎼▂▄▅⎺▼▄▃▆▅▃▼▆▅▃┈┊▆▄┈┈╶▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▼⎺▆▆▅▆▊┈▏┈▂⎺▉⎺▅▄▄▄▅⎽▲●▝▆▅▄▅⎽━▄⎺▆▄▂┈┊▅▃▘▉▎─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▄┹▄▃▃▃▃▅⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄◀▉╸⎺▆▄▄▅▆▮▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶ ┚│▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▗▅▆▆▅▂⎽▅▄▄▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▃▄▃▃▃▃▎▃▂⎺▎▖▄▃▂▂▎▃▂▃▃▄▃▄▂⎺▂▂▃┊⎽⎽▂▃▃▄▄▄▃▂▂▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎺▆▅▖▄▊▃▂⎺⎺▅▋▃▂⎺▉▪▘⎺▆▅▅▆■▋▝⎺▗▆⎻▎⎽▍▃⎼▄▃▄▄▃▂⎺▅▃⎽▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗⎺▆▆▆▘▄▍⎽⎺▆▋▃▍⎽⎺▆▊▂▆▆▅▄▋▗▖▆▆▆▍▋▅╴⎺▌┈⎺┒▅┍▊▮▗▃▂▅▄▆▅▃⎽┵╸▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▅▅▅▗▂▗⎽▆▅▅▍▃▆▆▅▅▌▊▗▄▃━▋▎▗▅▅▄▖▊⎻▅▆▋▖┈·│┕▉▏▊┠▍▆▅▃▂  ┈▄▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎻▅▅▄▘▮▋▅▄▄▃▝▊▅▄▃▃▘▋▂▅▄▄▌▎▗▃━━▌▉─━━▊╵⎽▂▃▄▄▘┈▎┟▋╵⎺▉▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝▄▃▂▂▆▆▪━━━▌▅▌━▅▄▄▎▌▃▂▂⎺▌▎▝▄▃▂▋▉⎽▂▃⎼▃▄▅▆⎺⎺▋┊▗▂▆▄▂┑▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▂⎼▃▂▍▅▋▄▃▃▂▍▆▄▃▂▂⎽▏▍⎺⎺▆▆▌▘▎▂▗⎺▌▉⎺▖┈╻▎▋ ▍▏┈▉▍▊┊┈▆▄▂▅▖▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▘⎽⎽⎺⎺▄▄▘┈┊⎺⎺▏▍▖⎺▆▆▅▄▎▄▃■■▍▄▅▅▄▃▖ ▏⎻▅▚▍▎╴⎽╴⎽▂▎╷▎╶▋┊│┈▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▗▆▅⎻▄▍▆▆━▆▅▅▘▅▘▄▃▂▂▘▖▊▄▃▂▂┃⎽▎▄▄▃▋ ▂▃⎼╸▄▅▆┈▋▌▎▋╿▆▅▃▂▖ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▅▄▃▃▃▎┑▂▂▂▄▄▄▂▂▄▄▃▃▃▗▖⎺⎺▆▆▎▘▎⎺┊┊▊╴▎▍ ▊▋▍⎼▂▂▂⎽⎽▆▅▄▂▶⎺▅▃▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃▝▃▃▂▂▃▄▂▄▃▂▆▋⎽▂▃▄▆⎺▝▄▄▃▆▅▼▆▅▃⎽┊▆▄·┈┈▖ ▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▊ ▃▂⎽⎽▉●▃▄▄▄▅⎽▲●▝▆▅▄▅⎽━▼▆▄▂┈┊▅▃▘▋▊▏─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▅▆▆▅▅▅▮⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄◀·⎺▆▅▃▃▄▆▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚╴╄╶ ┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽⎼▅▆▆▅▗▃▂▂▗▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▃▄▃▃▃▃▎▃▂⎺▎▊▃▂⎼⎼▎▌▃▂▂▪▃▄▂⎺▂▂▃▂▂▂▃▄▄▄▄▄▃⎽▂▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎺▆▅▖▄▊▃▂⎺⎺▅▋━▄▃▖▄▎╾▄▃▊▆▂⎽▪⎽▗▖▂▂⎼▍▄⎽⎽┷▄▃▂┊▆▄▂⎽▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗⎺⎻▆▅▘▄▍⎽⎺▆▋▃▍▄▃▂▊▃▋▃▂⎺▋▍▝▃▂▂▌▋▅┈▂▌┈▝▝⎽▝▊⎺▗▂▗▃▅▅▃▂▮▮▆▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘┱▆▅▗┺▗⎽▆▅▅▍▃▃▂⎽▆▌▊▌⎽⎺▆▋▎▍⎺⎺▆▌▊▆▆▅▋▖ ▊▉▝⎽▏▊┇⎺▅▃▂▗╸┈⎺▄▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗╺▅▄▃▘⎽▋▅▄▄▄▝▊▮⎺▆▅▍▋▆▅▅▄▌▎▍▅▄▄▌▉▄▄▅▊▂▃▄▄▄▄▍┈▎▉▋▝╵⎺▏▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝▃▃▂▂▆▆▄━━━▌▅▌▅▄▃▃▎▌▄▃▂▲▘▏▃▃▄▃▌▉⎼⎼━▄▄▅▆⎺┈⎺▋┊▗■▄▂⎽▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅╺⎼⎼▃▂▍▅▋▄▄▃▃▍▆▎▆▅▄▄▪▍▅▃▃▂▌▎▝▃▂▂▋▉▏▪▂▗▎▋╶▉⎽┈▉▍▊┊⎺▅▃▆▃▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂⎽⎺⎺▆▄▄▘⎽┊⎺⎺▲▪▃▂⎽▂▊▉▪⎽▼┱▆▌╸▎⎺▆▆▋┈▆■┈▌▍▍⎽▂⎽⎽⎽▎╷▎╷▌▂⎺▆▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▗▅⎻⎻▄▍▆▆▼▆▅▅▅▅▄■▆▆▅▅┱▃▅▄▃▃┫▖▗▃■■▋ ▎━━▘▆▖⎺ ▋▊▪▍▍▝▄▂▍▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▅▄▃▃▂▆┑▂▂▂▄▄▄▂▂▄▄▃▃▃▊▝▄▃▃▃┃▮▝▂▃┈▊┈▎▊┈▃▝▂▂▂▂▂⎽▆▅▄▂┈▆▅▃⎽▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━╍▆▆▆⎺▊▄▎▆▅▅▘▃▄▅▆·┒▆▄▄▃▆▆■▅▃▂┈▆▄▂▊┈▅╶▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▊⎽⎽▅▄▖▂■▃▄▄▄▅⎽▲●▝▆▅▄▅⎽━▆▅▃┈┊▅▃▂▌▋▊▎─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▼▼▼▼▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶▚▄◀⎺▆▅▄▃▃▄▅▲▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚┤└╶ ┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▗▅▆▆▅▗▅▄▃▖▅▃▃▄▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▃▄▃▃▃▃▎▃▂⎺▎▖▅▄▃▃▎▗▆▅▄▄▃▄▂⎺▂▂▂▃▃▄▄▅▅▅▄▃▂⎽▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎺▆▅▖▗▊▃▂⎺⎺▪▋▄▃━┑▅▎▅▄▃▘■▄▄▃▂▘▋⎼⎼╼▂▂▂⎽━▄▃┊▆▄▂▝┊▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗⎺⎻▆▅▘▄▍⎽⎺▆▋▃▍▃▅▄▊▃▏▃━━▋▍▃▂▲⎼▍▋▲▂⎼▌┈▅▝⎺⎺▆▆▂▲▄⎺▆▄▂⎽⎽▄╸▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▘▅▆▅━┷▗⎽▆▅▅▍▃▲▄▃▃▌▊▂▅▄▃▋▎▝▄▃▂▌▊▄▋⎼▋▖┈·▉▝▖▏▊⎺▆▄▂▲▄▪┊⎺▄▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎻━▄▄▘▮▋▅▄▄▃▝▊▃▂⎽⎺▍▋▝▃▂⎽▋▎▍⎽⎺╱▌▉▆▆⎺▊▃▄▄▅▄▃▎┈▎┆▎┕⎺▆▎▍▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝▃▃▂▂▆▆▪━━━▌▅▍⎺▆▆▅▎▌▎⎺▆▆▌▃▆▅▄▄▌▉━⎻▄▅▆⎺⎺⎺┈▆▖┊▆▅▃⎽▪▋▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▂⎼▃▂▍▅▋▄▃▃▂▍▆╏▄▄▃▃▏▍▅▄▃▃▍⎽▃■▲▪▌▉▂▃⎼▗▎▋╴▎▖┈▉▍▊⎺▅▃■▄▂▏▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂⎽⎺⎺▆▄▄▘┈┊⎺⎺▏▉▂▅▄▃▋▃▎▅▄▄▃▍▘▝▂⎽┹▊┊▎▊┈⎽▎⎽⎽▂⎽⎽⎽▎╷▎╷▍⎺⎺▅▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▗▅⎻▄▃▍▆▆━▆▅▅▘▅▅▅▄⎺⎺▅▖┫▂⎺⎺▆▎▘▎▆▅▆▋┈▎▅▆▊▌▎▎ ▌▊⎺▍▍▝▂⎽▘▎ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▅▄▃▃▃▎┑▂▂▂▄▄▄▂▂▄▄▃▃▃┻▅▄▃▃▄▉▖▂▅▅▅▋ ▎▂⎼▂▂▃▃▂▂⎽▆▅▄▂┈┈▅▃▂⎽▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅▆▊┈⎽▃┈▗▗▅▆⎺▘▄┒▆▄▄▃▘⎺▆▄▂┈▆▄▂┡⎺▅▄▂▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅╇▅▄▃▃▄▆■▃▄▄▄▅⎽▲●▝▆▅▄▅⎽┯▅▃⎽ ▆▄▂⎽▌▋▘▏─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶╻▅·⎺▅▄▃▃▃▄▅▲▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿⎽▅⎻╷·┘╴┚│▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▗▅▆▆▅▘▆▅▅▖▅⎽▮▅▅▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▃▄▃▃▃▃▎▂⎺▆▎▖▆▆▅▄▎▍⎼▂⎺▊▃▄▂⎺▂━▃▄▅▅▅▅▅▅▄▃▃▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎽▆▆▖▄▊▂⎺⎺⎺▆▋▆▅▄▼▮▎▂⎺⎺▊▗▖▆▆▅▌▋━┷▄▂▂▂▲╾▃■⎺▅▃⎽┈▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▗⎺⎺▆▆▘▄▍⎽▆▆▋▃▍▄▄▃▋▃▏⎺▆▅▋▍▆▅▄▄▖▋⎼⎼╼▌┈▊▋╴⎺▅▅▃▄▃▆▅▃▂⎽⎽▮╸▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▅⎺▅▗▂▗⎺▆▅▅▍▃▃▃━━▌▊▅▅▄▄▋▎▗▃━━▌▊⎽▂▂▋▖ ▊▉▝┪▶▊⎺▅▃▲▄▃▂⎺⎺▝▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎻▅╾▄▘▲▗▅▄▃▃▝▊┭▄▃▃▍▋▄▃▂▲▘▎▂▄▃▃▌▉┈▅▍▝▄▅▅▅▄▃▍┈▎┇▎▪⎺▆▎▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▝▄▃▃▂▆▆▪━━▅▌▅▌▂⎽⎽⎺▎▌▝▄▃▃▌▘▍⎽┊▗▌▉▅▆▆⎺⎺▆⎺⎺⎺▆▖┊▝▃⎽▂╵▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▂⎼⎼▄▍▅▗▄▃▂▂▍▆▏▆▆▅▅╍▍▂▪⎺⎺▌▄▆▅▅▄▋ ⎼╼━┛▎▋▉▊▖┈▉▍▊▆▄▂▅▃⎽┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂▂⎺▄⎺▃▄▘┊┊▆▆▮▉▄▃▂▲▗▅▃▆▅▄▄▖⎽▶■▅▅▋ ▏▶▂▖▎▂▂▂⎽⎽⎽▎┊▎╶◀⎺▅▄▖┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▗▆▅⎻▄▍▆▆▆▆▅▄▘▅▅▅▄▃▲▅▖▂▆▅▄▖▘▘▎▂▃▘▊╴▎▪┈▊▌▎▊ ▌⎺⎺▍┥▝⎽│▍▎ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▅▄▃▃▃▘┑▂▂▂▄▄▄▂▂▄▄▃▃▃▃▂⎽▼▼▼▂▃▆▅▄▄▘ ▝⎼▂▃▃▃▃▂⎽⎺▆▄▃▂┈▆▄▂⎽▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅▆▊⎽▅▄▄▃▂▅▃▆▄▅┒▆▄▄▃⎺▆▄▂┈⎺▅▃╸⎺▅▘▃⎽▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃━⎺▃▃■■▃▄▄▄▅⎽▲●▝▆▅▄▅■▅▃⎽┈▆▄▂┈┈▌▋▊▎─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶╻╱⎺▅▄▃▃▃▄▅▆▮▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿⎽▅⎻┆ ╵╴┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊⎽▄▅▆▆▅▍▆▆▆▍▗▄▃▂▂▄▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▄▄▃▃▃▃▎▂⎺▆▎▖▪⎺▆▅▎▍▃▂▂▊▄▂▲▘▂┷▅▅▆▆▅▆▅▄▃▂▄▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▂⎺▆▖▗▊▂⎺▆▆▅▋⎺▆▅▅▮▎━▄▄▊▗▌▃▂▂▌▋▄▄▅▃▂▂━▄▂⎺▆▄▂┊·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄▂⎺⎺▅▘▄▍⎺▆▅▋▃▍▅▅▄▊▃▲▄▃▂▋▍▍▂⎺⎺▌▋┷━━▌┈▊⎺⎺▆▄▃╾▃┊▅▄▂⎽⎽⎽▮▆▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▆┱⎺▗▂▗▆▅▄▄▍▂▅▄▃▂▘▊▃▂⎽⎺▋▍▍▆▅▅▌▊▃⎼⎼▋▖ ▪▖│▉▌▉▅▃▂▪▃▂⎽⎺┈▝▆▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎻▆▅▅▘⎽▗▄▃▃▂▝▊━━▄▄▍▋▍▆▆▅▌▎▄▄▃▃▌▉⎽■⎽▅▅▅▅▄▃▂▍┈▎▉▎┊▆▅▖▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▄▄▃▃▆▆■━▅▄▌▅▌▃▃▂▂▎▌▅▄▃━▌▏▂▪▄▃▋▉▆┈▆▉▏▖▍⎺▆▅▖┊▝▂┫▎┋▌▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊▃▂▂⎼▍▅▗▃▂▂▂▍▆╽┊⎺▆▆⎺▍▅▄▄▃▌▘▎⎽⎽▼▋┊┅⎻⎻▘▎▋▎▌╴┈▉▌▉▄▂▅▃▂▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▘▂⎽⎽▊▃▄▘┊▆▆▅▮─▅▄▃▃▘▖▎▂⎽⎽▅▍╸▎▅▅▅▋ ▂▃▃▖⎽▂▂▂⎽⎽▍▎·▎┍▋▆▄▃▂┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌⎺▆▅▅▍▆▅▆▅▄▄▘▅▅▅▄▃▲▅▅▅▄▄▃▄▉▂▂▅▄▄▋┊▎▏ ▉▌▎▌┈▊⎺▆▘┑▌▂▄▏▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺▆▅▄▄▄▎┑▂▂▂▄▄▄▂▂▄▄▃▃▃▃▂▄▃▃▃▘▆⎽▘⎺┊▊⎽▂▂▃▄▃▃▂⎽⎽▆▅▃⎽▋▆▄▂╸▗▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▝▄▄▃▃▃▆▄━▆▄▅┒▆▄▄⎺▆▄▂┈⎺▅▃▘⎺▆▄▘▂⎽▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲●▝▆▅▄▝▆▄▂ ▆▄▃┈┈┈▌▋▉▝─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺╶┝⎺▆▄▃▃▃▄▅▆⎺▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚┆ ╶╶┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂▂⎽⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▍▂⎺▆▍▗▆▆▅▄▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▅▄▄▃▃▃▃▘▆▆▆▎▖▂⎺▆▆▎▍▆▅▄▄▖▄▄▃▃▂▆▆▆▆▅▆▅▄▂▄▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌▃▂▆▋▄▊⎺▆▆▅▆▋▮▆▆▆▪▎▅▄▃▊▍▄▃▂▂▖▋▅▅▅▃▂▲▅▃▂▆▅▃╴╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▄▃▂⎺⎺▍▄▍▆▅▅▋▃▍▆▅▅▊▃▃▃▃▃▋▍▍▅▄▃▍▋▄⎻⎻▌┈▄▃▆▄▃━▃┈▆▄▃▂⎽⎽⎽▂┳▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍▪⎺┳▊⎽▗▅▄▄▃▍▂▅▄▄▃▘▊▂▲⎼▄▋▍▝▃▂⎽▌▊╼━━▋▖┈▉▌▅▉▮▊▄▂■▄▂▂⎺┈ ▝▗▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗▆▼⎻▆▘▲▝▃▃━━▝▊▃━━▅▍▋▝▃▂⎽▋▗▍⎺▆▆▍▉▂▂▂▄▆▆▅▄▃⎽▍┈▎┣▋⎺▆▅▖▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂▅▅▅▄▄▆▆▲▄▄▃▌▅▌▄▃▃▂▎▌▎⎺▆▆▌▃▅▄▄▃▖▉▪┈▖▉▏▝⎺⎺▅▄▂╴▌⎽▌▖▊▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▊⎼▃▃▂▘▅▗▂▂⎽⎽▍▆▂┈┊▆⎺⎺▍▅▄▃▃▍▏▶▅▄▄▋▉▅▅▆╱▎▋▍▉╵┈▉▍▗▃▆▄▂▂▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▅▂⎼▂▂▂▝▄▘┈┈▆▄▮─▅▅▄▄▘▃▎▅▄▄▃▍▘▎⎽⎽▪▊ ⎼⎼╼━▂▂▂▂▏┈▘▎▉▎▝▆▅▃▂▂┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌┊⎺▆▆▍▆▆▅▄▃▃┛▅▅▅▄▃▲▅▅▅▅▅▆▆▖▃▅▅▄▄▘ ▎▉┈⎽▌▎▪ ▪▆▅▘▏▌┏▍▍▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺┊▆▆▅▅▘┑▂▂▂▄▄▄▂▂▄▄▃▃▃▃▂▄▃▃▃▊⎽▅▄▄▄▂▃▃▃▄▄▃▃▂⎽▆▅▃▂▌▝▄▂⎽╴▗▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆▄▄▆▆▄▄▄━▆▄▅┒▆▄▄▆▄▃┈┈▅▃┈▌▆▄▃▘▂⎽▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲●▝▆▅▆▆▄▂┈▆▅▃⎽┈ ┈▌╿▊▄─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆⎺▪⎺▆▅▄▃▃▄▅▆⎺⎺▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╿⎽▅⎻╴▘╶ ┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +▄▄▄▃▃⎽⎽⎺╵╺━━⎽▃▃▃━⎺▃▃▃▂▃▃▃▄▃▃▄▃▂▂▂⎽▂⎽╴▏▪┋└·▝▆■▆▃▝▃▃▃▂▃▃▄▄▃▄▃▂▂┺ ▃▃▃▄·⎽▗▃▂▉╺■⎺▆▆▄▄ +▄▄▅▆▅▅▅▅▄▅▆▄▃▃▂▂▂■■▆▊▗▄▅▆▆▅▍▂⎺▆▍▗▃▂⎺▆▃▄▼┖⎽·▆▅▆▆▂▆▆▆▆▄▂▃▄▄▃▃▆▆▄▃▃▃▃▃▃▂▆▃▂▃▄▃▃▃▂▂▪ +▲▅▅▆▂┷▃▄▅▆▆▅▅▅▆▲▪▄▃▃▃▆▆▅▅▎▖▂⎺▆▆▎▍●⎺▆▊▗▄⎺▆▅▄▖⎺⎺⎺▅▅▄▃▃▅▅▆▆▂▅▅▆▆▆▆▆▃▅▄▄▅▆▅▃▄▄▄▅▅▄▃▂ +▂▄▄▄▄▄▄▄▄▃▅▅▅▃▌⎼⎼▃▋▗▊▆▅▅▄▆▋▮▆▆▆▮▎⎽▆▆▊▍▆▆▅▅▖▋▆▆▆▃▂━▄▂▪▅▃⎽╴╵·▆▅▄▄▅▅▅▅▅▄▄▅▃╷╵·⎺·⎻┄▆ +▅▃▆▅▄▆▅▄▄▄▄▃▆▅▃▃▂▂▎▄▌▅▄▄▋▃▍▆▅▅▊▂▄▆▅▄▋▍▗▄▃■▍▋▅▅▅▌┈▄⎺▅▃●▄╾⎺▅▃▂┷⎽⎽⎽▂▖▆┗╷▆·┈⎺ ┈▉┺┎╲╎ +▅▄▅▅▆▆▃▎⎺╲▄▃▄▍⎽⎽⎺▋⎽▉▝▃▃▅▍▂▅▄▄▃▘▊▗▄▃▃▘▎▃▂▃▃▌▊━━▃▋▖┈▪▝▝╷▏▄▃▲▗▃╾⎺╺  ▝▗▃▅▄▃▂▏╲▉╴╽▪▉╴ +⎽┈▅▃▃▄▃▂▗▲▼▅▗⎺▆▆▼▍⎽╺━▲▅▪▝▊▃━▅▅▍▋▍━▅▄▌▘▝▃▃▂▌▉▃⎼▃⎽▆▅▄▃▂┅▍┈▎▝┓▆▆▅▎▌▖ ▍▄▄▄▃▂▃▂╌╶▪▌⎼┊ +▃▂▂▃▄▃▃▅▆⎺▃▂⎺⎺▆▆▅▆▆▄▃▃▂▋⎽▌▄▃▃▂▎▌▝▂▂⎽▌▅▍⎺⎺⎺▋▉▮┈▮▉▏⎺⎺▆▄▂⎽ ▌▊▋·▊▊▌ ▖▄▝■▌▖▂▂▂▂▂⎽▂▄▄▄ +⎺▆▄▄▅▄▅▅▄▅▅▗▅╾─▄▘▅▗⎽⎽⎺⎺▍▆⎽┊┊▅⎺⎺▍▏⎺▆▆▍▖▗▄▄▄▋▉▆▖▆▖▎▋▎▋╴┈▉▪⎺⎽▄▃⎽⎽▊┊▍▅▝▌▅▅▄▄▃●▆▆▆▅▆▅ +▃▃▄▄▃▄▖▅▄▃▆┻▂▂⎼▪▝▄▍┈▆▅▅▲─▅▅▄▄▘╻▃▃▂▂■▘▏▝▅▄▄▋ ━━━┷▂▂▂⎽▊┈▋▎▮▎⎺▅▄▃▂▂┊▏▖▝▄▅▅▅▅▆▆▅▅▅▅▄ +▅▄▃▃▂▃▃▃▂▅▌⎽▅▂▄▌▆▉▃━▂━▋▅▅▅▄▃▲▅▅▅▄▄▅▄▖▘▎▘▅┈▊ ▎▂┈⎽▌▎▎┊▆▅▃▌▏▌┅▍▌▍ ▊┊▍▉▌▌▄▄▗▅▅▅▅▃▃▄▂ +▅▅▅▆▅▅▄▮⎺⎺⎺⎺⎺⎺▆▆┑▂▂▂▄▄▄▂▂▄▄▃▃▃▃▂▄▃▃▃┹▄▃▃▂▃▄▄▄▄▄▄▃▂⎽▆▅▃▂▎▶▝▃⎽▅┊▗▊▍▊▝▝▊▖▄▄▊·▎▘▅▅▘▉ +▂▅▃▂▃▂▌▄▂▅▆▄⎽▆▆▅▅▅▆▆▃▂▃▆■▆▃▆▄▃━━▆▅▅⎽▆━━▆━━▄▃━▆▃▄┒▆▼▆▅▃┈┈▅▃┈┈▆▅▃▂▋▂⎽▎▋▋▂■■▅▄▅▅┓⎽▃ +▄▃▄▅▅▅▘▂▂▄▅▂▂▂▂▂▄▄▃▃▄▅▅┷▅⎺ ▄⎺▃▃▄▄▅▅▅▄▃┳⎽▃▂■■▃▄▄▄▅⎽▲●▝▆⎺▆▄▂┈▆▅▃▂▊  ┈▝⎽▋▂─■▲▲⎽▂▄▄▅ +▃▄▄▄▄▃▝▅▄━▆━━▆━━▆▆▆⎺▆▆▅▄▄▃▃▃▃▂▃▃▂▎▃▃▄▄▄▄▃⎺▆⎺┯⎺◆▄─▄▘▃▃▃▃▄▆┘▪▆▅▄▃▃▄▅▆┯◆⎽▪▍▝▄▄▃▂⎽▋▗ +╁⎺▆▅▅▄▅▅▃▅▝▅▄▃▄▄▅▆━▌▂▂▅▍▅╸▅▅▅▆▆▆▆▅▅▄▂▄▅▖━▃▃▂·╎■╷▆▅▄▅╵┒┕▄▪⎽╷·▅┚┤└╶·┸┅▆▄▄▄▅▅▅▆▅▆▆▅ +[?25h \ No newline at end of file diff --git a/src/host/ft_host/precomp.h b/src/host/ft_host/precomp.h index 26b14a1f7a..d5817949fc 100644 --- a/src/host/ft_host/precomp.h +++ b/src/host/ft_host/precomp.h @@ -32,3 +32,5 @@ using namespace WEX::TestExecution; // Include our common helpers #include "common.hpp" + +#include "resource.h" diff --git a/src/host/ft_host/resource.h b/src/host/ft_host/resource.h new file mode 100644 index 0000000000..85447dd6c6 --- /dev/null +++ b/src/host/ft_host/resource.h @@ -0,0 +1 @@ +#define CHAFA_CONTENT 300 diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index fa5337659e..59cd793fce 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -545,6 +545,8 @@ void SCREEN_INFORMATION::RefreshFontWithRenderer() ->TriggerFontChange(ServiceLocator::LocateGlobals().dpi, GetDesiredFont(), GetCurrentFont()); + + NotifyGlyphWidthFontChanged(); } } } diff --git a/src/host/ut_host/CodepointWidthDetectorTests.cpp b/src/host/ut_host/CodepointWidthDetectorTests.cpp index e5e584e253..7bf2000a25 100644 --- a/src/host/ut_host/CodepointWidthDetectorTests.cpp +++ b/src/host/ut_host/CodepointWidthDetectorTests.cpp @@ -12,6 +12,8 @@ using namespace WEX::Logging; static const std::wstring emoji = L"\xD83E\xDD22"; // U+1F922 nauseated face +static const std::wstring ambiguous = L"\x414"; // U+0414 cyrillic capital de + // codepoint and utf16 encoded string static const std::vector> testData = { @@ -34,7 +36,7 @@ class CodepointWidthDetectorTests TEST_METHOD(CodepointWidthDetectDefersMapPopulation) { - const CodepointWidthDetector widthDetector; + CodepointWidthDetector widthDetector; VERIFY_IS_TRUE(widthDetector._map.empty()); widthDetector.IsWide(UNICODE_SPACE); VERIFY_IS_TRUE(widthDetector._map.empty()); @@ -45,13 +47,13 @@ class CodepointWidthDetectorTests TEST_METHOD(CanLookUpEmoji) { - const CodepointWidthDetector widthDetector; + CodepointWidthDetector widthDetector; VERIFY_IS_TRUE(widthDetector.IsWide(emoji)); } TEST_METHOD(TestUnicodeRangeCompare) { - const CodepointWidthDetector::UnicodeRangeCompare compare; + CodepointWidthDetector::UnicodeRangeCompare compare; // test comparing 2 search terms CodepointWidthDetector::UnicodeRange a{ 0x10 }; CodepointWidthDetector::UnicodeRange b{ 0x15 }; @@ -60,7 +62,7 @@ class CodepointWidthDetectorTests TEST_METHOD(CanExtractCodepoint) { - const CodepointWidthDetector widthDetector; + CodepointWidthDetector widthDetector; for (const auto& data : testData) { const auto& expected = std::get<0>(data); @@ -72,7 +74,7 @@ class CodepointWidthDetectorTests TEST_METHOD(CanGetWidths) { - const CodepointWidthDetector widthDetector; + CodepointWidthDetector widthDetector; for (const auto& data : testData) { const auto& expected = std::get<2>(data); @@ -82,4 +84,41 @@ class CodepointWidthDetectorTests } } + static bool FallbackMethod(const std::wstring_view glyph) + { + if (glyph.size() < 1) + { + return false; + } + else + { + return (glyph.at(0) % 2) == 1; + } + } + + TEST_METHOD(AmbiguousCache) + { + // Set up a detector with fallback. + CodepointWidthDetector widthDetector; + widthDetector.SetFallbackMethod(std::bind(&FallbackMethod, std::placeholders::_1)); + + // Ensure fallback cache is empty. + VERIFY_ARE_EQUAL(0u, widthDetector._fallbackCache.size()); + + // Lookup ambiguous width character. + widthDetector.IsWide(ambiguous); + + // Cache should hold it. + VERIFY_ARE_EQUAL(1u, widthDetector._fallbackCache.size()); + + // Cached item should match what we expect + const auto it = widthDetector._fallbackCache.begin(); + VERIFY_ARE_EQUAL(ambiguous, it->first); + VERIFY_ARE_EQUAL(FallbackMethod(ambiguous), it->second); + + // Cache should empty when font changes. + widthDetector.NotifyFontChanged(); + VERIFY_ARE_EQUAL(0u, widthDetector._fallbackCache.size()); + } + }; diff --git a/src/renderer/dx/CustomTextLayout.cpp b/src/renderer/dx/CustomTextLayout.cpp index 3280a98b4a..72e98f3e47 100644 --- a/src/renderer/dx/CustomTextLayout.cpp +++ b/src/renderer/dx/CustomTextLayout.cpp @@ -49,6 +49,27 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory2* const factory, } } +// Routine Description: +// - Figures out how many columns this layout should take. This will use the analyze step only. +// Arguments: +// - columns - The number of columns the layout should consume when done. +// Return Value: +// - S_OK or suitable DirectX/DirectWrite/Direct2D result code. +[[nodiscard]] +HRESULT STDMETHODCALLTYPE CustomTextLayout::GetColumns(_Out_ UINT32* columns) +{ + *columns = 0; + + RETURN_IF_FAILED(_AnalyzeRuns()); + RETURN_IF_FAILED(_ShapeGlyphRuns()); + + const auto totalAdvance = std::accumulate(_glyphAdvances.cbegin(), _glyphAdvances.cend(), 0.0f); + + *columns = static_cast(ceil(totalAdvance / _width)); + + return S_OK; +} + // Routine Description: // - Implements a drawing interface similarly to the default IDWriteTextLayout which will // take the string from construction, analyze it for complexity, shape up the glyphs, @@ -72,6 +93,7 @@ HRESULT STDMETHODCALLTYPE CustomTextLayout::Draw(_In_opt_ void* clientDrawingCon { RETURN_IF_FAILED(_AnalyzeRuns()); RETURN_IF_FAILED(_ShapeGlyphRuns()); + RETURN_IF_FAILED(_CorrectGlyphRuns()); RETURN_IF_FAILED(_DrawGlyphRuns(clientDrawingContext, renderer, { originX, originY })); return S_OK; @@ -117,6 +139,15 @@ HRESULT CustomTextLayout::_AnalyzeRuns() noexcept // Perform our custom font fallback analyzer that mimics the pattern of the real analyzers. RETURN_IF_FAILED(_AnalyzeFontFallback(this, 0, textLength)); + // Ensure that a font face is attached to every run + for (auto& run : _runs) + { + if (!run.fontFace) + { + run.fontFace = _font; + } + } + // Resequence the resulting runs in order before returning to caller. size_t totalRuns = _runs.size(); std::vector runs; @@ -195,13 +226,13 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta { try { - // Shapes a single run of text into glyphs. - // Alternately, you could iteratively interleave shaping and line - // breaking to reduce the number glyphs held onto at once. It's simpler - // for this demostration to just do shaping and line breaking as two - // separate processes, but realize that this does have the consequence that - // certain advanced fonts containing line specific features (like Gabriola) - // will shape as if the line is not broken. + // Shapes a single run of text into glyphs. + // Alternately, you could iteratively interleave shaping and line + // breaking to reduce the number glyphs held onto at once. It's simpler + // for this demostration to just do shaping and line breaking as two + // separate processes, but realize that this does have the consequence that + // certain advanced fonts containing line specific features (like Gabriola) + // will shape as if the line is not broken. Run& run = _runs.at(runIndex); UINT32 textStart = run.textStart; @@ -217,17 +248,6 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta return S_FALSE; // Nothing to do.. } - // Get the font for this run - ::Microsoft::WRL::ComPtr face; - if (run.font) - { - RETURN_IF_FAILED(run.font->CreateFontFace(&face)); - } - else - { - face = _font; - } - // Allocate space for shaping to fill with glyphs and other information, // with about as many glyphs as there are text characters. We'll actually // need more glyphs than codepoints if they are decomposed into separate @@ -255,7 +275,7 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta hr = _analyzer->GetGlyphs( &_text[textStart], textLength, - face.Get(), + run.fontFace.Get(), run.isSideways, // isSideways, WI_IsFlagSet(run.bidiLevel, 1), // isRightToLeft &run.script, @@ -306,7 +326,7 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta &_glyphIndices[glyphStart], &glyphProps[0], actualGlyphCount, - face.Get(), + run.fontFace.Get(), fontSize, run.isSideways, (run.bidiLevel & 1), // isRightToLeft @@ -321,69 +341,108 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta RETURN_IF_FAILED(hr); - // If we need to detect font fallback, we can do it this way: - // if (!_font->Equals(face.Get())) + // Set the final glyph count of this run and advance the starting glyph. + run.glyphCount = actualGlyphCount; + glyphStart += actualGlyphCount; + } + CATCH_RETURN(); + return S_OK; +} + +// Routine Description: +// - Adjusts the glyph information from shaping to fit the layout pattern required +// for our renderer. +// This is effectively a loop of _CorrectGlyphRun. See it for details. +// Arguments: +// - - Uses internal state +// Return Value: +// - S_OK or suitable DirectWrite or STL error code +[[nodiscard]] +HRESULT CustomTextLayout::_CorrectGlyphRuns() noexcept +{ + try + { + // Correct each run separately. This is needed whenever script, locale, + // or reading direction changes. + for (UINT32 runIndex = 0; runIndex < _runs.size(); ++runIndex) + { + LOG_IF_FAILED(_CorrectGlyphRun(runIndex)); + } + } + CATCH_RETURN(); + return S_OK; +} + +// Routine Description: +// - Adjusts the advances for each glyph in the run so it fits within a fixed-column count of cells. +// Arguments: +// - runIndex - The ID number of the internal runs array to use while shaping +// Return Value: +// - S_OK or suitable DirectWrite or STL error code +[[nodiscard]] +HRESULT CustomTextLayout::_CorrectGlyphRun(const UINT32 runIndex) noexcept +{ + try + { + Run& run = _runs.at(runIndex); + + if (run.textLength == 0) + { + return S_FALSE; // Nothing to do.. + } // We're going to walk through and check for advances that don't match the space that we expect to give out. + + DWRITE_FONT_METRICS1 metrics; + run.fontFace->GetMetrics(&metrics); + + // Walk through advances and space out characters that are too small to consume their box. + for (auto i = run.glyphStart; i < (run.glyphStart + run.glyphCount); i++) { - IDWriteFontFace1* face1; - RETURN_IF_FAILED(face.Get()->QueryInterface(&face1)); + // Advance is how wide in pixels the glyph is + auto& advance = _glyphAdvances[i]; - DWRITE_FONT_METRICS1 metrics; - face1->GetMetrics(&metrics); + // Offsets is how far to move the origin (in pixels) from where it is + auto& offset = _glyphOffsets[i]; - // Walk through advances and space out characters that are too small to consume their box. - for (auto i = glyphStart; i < (glyphStart + actualGlyphCount); i++) + // Get how many columns we expected the glyph to have and mutiply into pixels. + const auto columns = _textClusterColumns[i]; + const auto advanceExpected = static_cast(columns * _width); + + // If what we expect is bigger than what we have... pad it out. + if (advanceExpected > advance) { - // Advance is how wide in pixels the glyph is - auto& advance = _glyphAdvances[i]; + // Get the amount of space we have leftover. + const auto diff = advanceExpected - advance; - // Offsets is how far to move the origin (in pixels) from where it is - auto& offset = _glyphOffsets[i]; + // Move the X offset (pixels to the right from the left edge) by half the excess space + // so half of it will be left of the glyph and the other half on the right. + offset.advanceOffset += diff / 2; - // Get how many columns we expected the glyph to have and mutiply into pixels. - const auto columns = _textClusterColumns[i]; - const auto advanceExpected = static_cast(columns * _width); + // Set the advance to the perfect width we want. + advance = advanceExpected; + } + // If what we expect is smaller than what we have... rescale the font size to get a smaller glyph to fit. + else if (advanceExpected < advance) + { + // We need to retrieve the design information for this specific glyph so we can figure out the appropriate + // height proportional to the width that we desire. + INT32 advanceInDesignUnits; + RETURN_IF_FAILED(run.fontFace->GetDesignGlyphAdvances(1, &_glyphIndices[i], &advanceInDesignUnits)); - // If what we expect is bigger than what we have... pad it out. - if (advanceExpected > advance) - { - // Get the amount of space we have leftover. - const auto diff = advanceExpected - advance; + // When things are drawn, we want the font size (as specified in the base font in the original format) + // to be scaled by some factor. + // i.e. if the original font size was 16, we might want to draw this glyph with a 15.2 size font so + // the width (and height) of the glyph will shrink to fit the monospace cell box. - // Move the X offset (pixels to the right from the left edge) by half the excess space - // so half of it will be left of the glyph and the other half on the right. - offset.advanceOffset += diff / 2; + // This pattern is copied from the DxRenderer's algorithm for figuring out the font height for a specific width + // and was advised by the DirectWrite team. + const float widthAdvance = static_cast(advanceInDesignUnits) / metrics.designUnitsPerEm; + const auto fontSizeWant = advanceExpected / widthAdvance; + run.fontScale = fontSizeWant / _format->GetFontSize(); - // Set the advance to the perfect width we want. - advance = advanceExpected; - } - // If what we expect is smaller than what we have... rescale the font size to get a smaller glyph to fit. - else if (advanceExpected < advance) - { - // We need to retrieve the design information for this specific glyph so we can figure out the appropriate - // height proportional to the width that we desire. - INT32 advanceInDesignUnits; - RETURN_IF_FAILED(face1->GetDesignGlyphAdvances(1, &_glyphIndices[i], &advanceInDesignUnits)); - - DWRITE_GLYPH_METRICS glyphMetrics; - RETURN_IF_FAILED(face1->GetDesignGlyphMetrics(&_glyphIndices[i], 1, &glyphMetrics)); - - - // When things are drawn, we want the font size (as specified in the base font in the original format) - // to be scaled by some factor. - // i.e. if the original font size was 16, we might want to draw this glyph with a 15.2 size font so - // the width (and height) of the glyph will shrink to fit the monospace cell box. - - // This pattern is copied from the DxRenderer's algorithm for figuring out the font height for a specific width - // and was advised by the DirectWrite team. - const float widthAdvance = static_cast(advanceInDesignUnits) / metrics.designUnitsPerEm; - const auto fontSizeWant = advanceExpected / widthAdvance; - run.fontScale = fontSizeWant / fontSizeFormat; - - // Set the advance to the perfect width that we want. - advance = advanceExpected; - } + // Set the advance to the perfect width that we want. + advance = advanceExpected; } } @@ -398,15 +457,12 @@ HRESULT CustomTextLayout::_ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphSta // 0.0f // ); //} - - // Set the final glyph count of this run and advance the starting glyph. - run.glyphCount = actualGlyphCount; - glyphStart += actualGlyphCount; } CATCH_RETURN(); return S_OK; } + // Routine Description: // - Takes the analyzed and shaped textual information from the layout process and // forwards it into the given renderer in a run-by-run fashion. @@ -434,24 +490,12 @@ HRESULT CustomTextLayout::_DrawGlyphRuns(_In_opt_ void* clientDrawingContext, // Get the run Run& run = _runs.at(runIndex); - // Get the font face from the font metadata provided by the fallback analysis - ::Microsoft::WRL::ComPtr face; - if (run.font) - { - RETURN_IF_FAILED(run.font->CreateFontFace(&face)); - } - else - { - face = _font; - } - - // Prepare the glyph run and description objects by converting our // internal storage representation into something that matches DWrite's structures. DWRITE_GLYPH_RUN glyphRun = { 0 }; glyphRun.bidiLevel = run.bidiLevel; glyphRun.fontEmSize = _format->GetFontSize() * run.fontScale; - glyphRun.fontFace = face.Get(); + glyphRun.fontFace = run.fontFace.Get(); glyphRun.glyphAdvances = _glyphAdvances.data() + run.glyphStart; glyphRun.glyphCount = run.glyphCount; glyphRun.glyphIndices = _glyphIndices.data() + run.glyphStart; @@ -467,12 +511,12 @@ HRESULT CustomTextLayout::_DrawGlyphRuns(_In_opt_ void* clientDrawingContext, // Try to draw it RETURN_IF_FAILED(renderer->DrawGlyphRun(clientDrawingContext, - mutableOrigin.x, - mutableOrigin.y, - DWRITE_MEASURING_MODE_NATURAL, - &glyphRun, - &glyphRunDescription, - nullptr)); + mutableOrigin.x, + mutableOrigin.y, + DWRITE_MEASURING_MODE_NATURAL, + &glyphRun, + &glyphRunDescription, + nullptr)); // Shift origin to the right for the next run based on the amount of space consumed. mutableOrigin.x = std::accumulate(_glyphAdvances.begin() + run.glyphStart, @@ -826,7 +870,22 @@ HRESULT STDMETHODCALLTYPE CustomTextLayout::_SetMappedFont(UINT32 textPosition, while (textLength > 0) { auto& run = _FetchNextRun(textLength); - run.font = font; + + if (font != nullptr) + { + // Get font face from font metadata + ::Microsoft::WRL::ComPtr face; + RETURN_IF_FAILED(font->CreateFontFace(&face)); + + // QI for Face5 interface from base face interface, store into run + RETURN_IF_FAILED(face.As(&run.fontFace)); + } + else + { + run.fontFace = _font; + } + + // Store the font scale as well. run.fontScale = scale; } } @@ -890,7 +949,7 @@ CustomTextLayout::LinkedRun& CustomTextLayout::_FetchNextRun(UINT32& textLength) // - - Updates internal state void CustomTextLayout::_SetCurrentRun(const UINT32 textPosition) { - + if (_runIndex < _runs.size() && _runs[_runIndex].ContainsTextPosition(textPosition)) @@ -912,7 +971,7 @@ void CustomTextLayout::_SetCurrentRun(const UINT32 textPosition) // - - Updates internal state, the back half will be selected after running void CustomTextLayout::_SplitCurrentRun(const UINT32 splitPosition) { - + UINT32 runTextStart = _runs.at(_runIndex).textStart; if (splitPosition <= runTextStart) diff --git a/src/renderer/dx/CustomTextLayout.h b/src/renderer/dx/CustomTextLayout.h index 61595c24b2..fdd39a1152 100644 --- a/src/renderer/dx/CustomTextLayout.h +++ b/src/renderer/dx/CustomTextLayout.h @@ -29,6 +29,9 @@ namespace Microsoft::Console::Render const std::basic_string_view<::Microsoft::Console::Render::Cluster> clusters, size_t const width); + [[nodiscard]] + HRESULT STDMETHODCALLTYPE GetColumns(_Out_ UINT32* columns); + // IDWriteTextLayout methods (but we don't actually want to implement them all, so just this one matching the existing interface) [[nodiscard]] HRESULT STDMETHODCALLTYPE Draw(_In_opt_ void* clientDrawingContext, @@ -87,7 +90,7 @@ namespace Microsoft::Console::Render script(), isNumberSubstituted(), isSideways(), - font{ nullptr }, + fontFace{ nullptr }, fontScale{ 1.0 } { } @@ -99,7 +102,7 @@ namespace Microsoft::Console::Render UINT8 bidiLevel; bool isNumberSubstituted; bool isSideways; - ::Microsoft::WRL::ComPtr font; + ::Microsoft::WRL::ComPtr fontFace; FLOAT fontScale; inline bool ContainsTextPosition(UINT32 desiredTextPosition) const @@ -142,6 +145,10 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphStart) noexcept; [[nodiscard]] + HRESULT _CorrectGlyphRuns() noexcept; + [[nodiscard]] + HRESULT _CorrectGlyphRun(const UINT32 runIndex) noexcept; + [[nodiscard]] HRESULT _DrawGlyphRuns(_In_opt_ void* clientDrawingContext, IDWriteTextRenderer* renderer, const D2D_POINT_2F origin) noexcept; diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 9b44bb58d5..be0f3c7661 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -1317,14 +1317,28 @@ HRESULT DxEngine::GetFontSize(_Out_ COORD* const pFontSize) noexcept // Routine Description: // - Currently unused by this renderer. // Arguments: -// - glyph - -// - pResult - Filled with false. +// - glyph - The glyph run to process for column width. +// - pResult - True if it should take two columns. False if it should take one. // Return Value: -// - S_OK +// - S_OK or relevant DirectWrite error. [[nodiscard]] -HRESULT DxEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const pResult) noexcept +HRESULT DxEngine::IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept { - *pResult = false; + Cluster cluster(glyph, 0); // columns don't matter, we're doing analysis not layout. + + // Create the text layout + CustomTextLayout layout(_dwriteFactory.Get(), + _dwriteTextAnalyzer.Get(), + _dwriteTextFormat.Get(), + _dwriteFontFace.Get(), + { &cluster, 1 }, + _glyphCell.cx); + + UINT32 columns = 0; + RETURN_IF_FAILED(layout.GetColumns(&columns)); + + *pResult = columns != 1; + return S_OK; } diff --git a/src/types/CodepointWidthDetector.cpp b/src/types/CodepointWidthDetector.cpp index 61cb9a6e0b..cf113134ce 100644 --- a/src/types/CodepointWidthDetector.cpp +++ b/src/types/CodepointWidthDetector.cpp @@ -43,15 +43,13 @@ CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) c // - true if wch is wide bool CodepointWidthDetector::IsWide(const wchar_t wch) const noexcept { - const auto width = GetCharWidth(wch); - if (width == CodepointWidth::Invalid) + try { - return _lookupIsWide({ &wch, 1 }); - } - else - { - return width == CodepointWidth::Wide; + return IsWide({ &wch, 1 }); } + CATCH_LOG(); + + return true; } // Routine Description: @@ -65,11 +63,28 @@ bool CodepointWidthDetector::IsWide(const std::wstring_view glyph) const THROW_HR_IF(E_INVALIDARG, glyph.empty()); if (glyph.size() == 1) { - const auto width = GetCharWidth(glyph.front()); + // We first attempt to look at our custom quick lookup table of char width preferences. + const auto width = GetQuickCharWidth(glyph.front()); + + // If it's invalid, the quick width had no opinion, so go to the lookup table. if (width == CodepointWidth::Invalid) { return _lookupIsWide(glyph); } + // If it's ambiguous, the quick width wanted us to ask the font directly, try that if we can. + // If not, go to the lookup table. + else if (width == CodepointWidth::Ambiguous) + { + if (_hasFallback) + { + return _checkFallbackViaCache(glyph); + } + else + { + return _lookupIsWide(glyph); + } + } + // Otherwise, return Wide as True and Narrow as False. else { return width == CodepointWidth::Wide; @@ -89,20 +104,55 @@ bool CodepointWidthDetector::IsWide(const std::wstring_view glyph) const // - true if codepoint is wide or if it can't be confirmed to be narrow bool CodepointWidthDetector::_lookupIsWide(const std::wstring_view glyph) const noexcept { - const CodepointWidth width = GetWidth(glyph); - if (width == CodepointWidth::Ambiguous) + try { - if (_hasFallback) + // Use our generated table to try to lookup the width based on the Unicode standard. + const CodepointWidth width = GetWidth(glyph); + + // If it's ambiguous, then ask the font if we can. + if (width == CodepointWidth::Ambiguous) { - return _pfnFallbackMethod(glyph); + if (_hasFallback) + { + return _checkFallbackViaCache(glyph); + } } + // If it's not ambiguous, it should say wide or narrow. Turn that into True = Wide or False = Narrow. + else + { + return width == CodepointWidth::Wide; + } + } + CATCH_LOG(); + + // If we got this far, we couldn't figure it out. + // It's better to be too wide than too narrow. + return true; +} + +// Routine Description: +// - Checks the fallback function but caches the results until the font changes +// because the lookup function is usually very expensive and will return the same results +// for the same inputs. +// Arguments: +// - glyph - the utf16 encoded codepoint to check width of +// - true if codepoint is wide or false if it is narrow +bool CodepointWidthDetector::_checkFallbackViaCache(const std::wstring_view glyph) const +{ + const std::wstring findMe{ glyph }; + + // TODO: Cache needs to be emptied when font changes. + auto it = _fallbackCache.find(findMe); + if (it == _fallbackCache.end()) + { + auto result = _pfnFallbackMethod(glyph); + _fallbackCache.insert_or_assign(findMe, result); + return result; } else { - return width == CodepointWidth::Wide; + return it->second; } - // better to be too wide than too narrow - return true; } // Routine Description: @@ -146,6 +196,19 @@ void CodepointWidthDetector::SetFallbackMethod(std::function +// Return Value: +// - +void CodepointWidthDetector::NotifyFontChanged() const noexcept +{ + _fallbackCache.clear(); +} + void CodepointWidthDetector::_populateUnicodeSearchMap() { // generated from http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt diff --git a/src/types/GlyphWidth.cpp b/src/types/GlyphWidth.cpp index 68f87957ed..b92935c31b 100644 --- a/src/types/GlyphWidth.cpp +++ b/src/types/GlyphWidth.cpp @@ -37,3 +37,14 @@ void SetGlyphWidthFallback(std::function pfnFallb { widthDetector.SetFallbackMethod(pfnFallback); } + +// Function Description: +// - Forwards notification about font changing to glyph width detector +// Arguments: +// - +// Return Value: +// - +void NotifyGlyphWidthFontChanged() +{ + widthDetector.NotifyFontChanged(); +} diff --git a/src/types/convert.cpp b/src/types/convert.cpp index 6ec1ae6c6b..a87912ff5e 100644 --- a/src/types/convert.cpp +++ b/src/types/convert.cpp @@ -143,7 +143,7 @@ std::deque> CharToKeyEvents(const wchar_t wch, WORD CharType = 0; GetStringTypeW(CT_CTYPE3, &wch, 1, &CharType); - if (WI_IsFlagSet(CharType, C3_ALPHA) || GetCharWidth(wch) == CodepointWidth::Wide) + if (WI_IsFlagSet(CharType, C3_ALPHA) || GetQuickCharWidth(wch) == CodepointWidth::Wide) { keyState = 0; } @@ -341,7 +341,10 @@ std::deque> SynthesizeNumpadEvents(const wchar_t wch, // display font data (cached) instead. // May-23-2017 migrie Forced Box-Drawing Characters (x2500-x257F) to narrow. // Jan-16-2018 migrie Seperated core lookup from asking the renderer the width -CodepointWidth GetCharWidth(const wchar_t wch) noexcept +// May-01-2019 MiNiksa Forced lookup-via-renderer for retroactively recategorized emoji +// that used to be narrow but now might be wide. (approx x2194-x2b55, not inclusive) +// Also forced block characters segment (x2580-x259F) to narrow +CodepointWidth GetQuickCharWidth(const wchar_t wch) noexcept { // 0x00-0x1F is ambiguous by font if (0x20 <= wch && wch <= 0x7e) @@ -372,7 +375,103 @@ CodepointWidth GetCharWidth(const wchar_t wch) noexcept { return CodepointWidth::Narrow; } + // 0x2580 - 0x259F is the block element characters. + // Technically these are ambiguous width, but many many things assume they're narrow. + else if (0x2580 <= wch && wch <= 0x259F) + { + return CodepointWidth::Narrow; + } // 0x2010 - 0x2B59 varies between narrow, ambiguous, and wide by character and font (Unicode 9.0) + // However, there are a bunch of retroactive-emoji in this range. Things that weren't emoji and then they became + // "emoji" later. As a result, they jumped from a fixed narrow definition to a now ambiguous definition. + // There are others in this range already defined as wide or ambiguous, but we're just going to + // implicitly say they're all ambiguous here to force a font lookup. + // I picked the ones that looked like color double-wide emoji in my browser that weren't already + // covered easily by the half-width/full-width table (see CodepointWidthDetector.cpp) + // See https://unicode.org/Public/emoji/12.0/emoji-data.txt + else if ((0x2194 <= wch && wch <= 0x2199) || + (0x21A9 <= wch && wch <= 0x21AA) || + (0x231A <= wch && wch <= 0x231B) || + 0x2328 == wch || + 0x23CF == wch || + (0x23E9 <= wch && wch <= 0x23F3) || + (0x23F8 <= wch && wch <= 0x23FA) || + 0x24C2 == wch || + (0x25AA <= wch && wch <= 0x25AB) || + 0x25B6 == wch || + 0x25C0 == wch || + (0x25FB <= wch && wch <= 0x25FE) || + (0x2600 <= wch && wch <= 0x2604) || + 0x260E == wch || + 0x2611 == wch || + (0x2614 <= wch && wch <= 0x2615) || + 0x2618 == wch || + 0x261D == wch || + 0x2620 == wch || + (0x2622 <= wch && wch <= 0x2623) || + 0x2626 == wch || + 0x262A == wch || + (0x262E <= wch && wch <= 0x262F) || + (0x2638 <= wch && wch <= 0x263A) || + 0x2640 == wch || + 0x2642 == wch || + (0x2648 <= wch && wch <= 0x2653) || + (0x265F <= wch && wch <= 0x2660) || + 0x2663 == wch || + (0x2665 <= wch && wch <= 0x2666) || + 0x2668 == wch || + 0x267B == wch || + (0x267E <= wch && wch <= 0x267F) || + (0x2692 <= wch && wch <= 0x2697) || + 0x2699 == wch || + (0x269B <= wch && wch <= 0x269C) || + (0x26A0 <= wch && wch <= 0x26A1) || + (0x26AA <= wch && wch <= 0x26AB) || + (0x26B0 <= wch && wch <= 0x26B1) || + (0x26BD <= wch && wch <= 0x26BE) || + (0x26C4 <= wch && wch <= 0x26C5) || + 0x26C8 == wch || + 0x26CE == wch || + 0x26CF == wch || + 0x26D1 == wch || + (0x26D3 <= wch && wch <= 0x26D4) || + (0x26E9 <= wch && wch <= 0x26EA) || + (0x26F0 <= wch && wch <= 0x26F5) || + (0x26F7 <= wch && wch <= 0x26FA) || + 0x26FD == wch || + 0x2702 == wch || + 0x2705 == wch || + (0x2708 <= wch && wch <= 0x2709) || + (0x270A <= wch && wch <= 0x270B) || + (0x270C <= wch && wch <= 0x270D) || + 0x270F == wch || + 0x2712 == wch || + 0x2714 == wch || + 0x2716 == wch || + 0x271D == wch || + 0x2721 == wch || + 0x2728 == wch || + (0x2733 <= wch && wch <= 0x2734) || + 0x2744 == wch || + 0x2747 == wch || + 0x274C == wch || + 0x274E == wch || + (0x2753 <= wch && wch <= 0x2755) || + 0x2757 == wch || + (0x2763 <= wch && wch <= 0x2764) || + (0x2795 <= wch && wch <= 0x2797) || + 0x27A1 == wch || + 0x27B0 == wch || + 0x27BF == wch || + (0x2934 <= wch && wch <= 0x2935) || + (0x2B05 <= wch && wch <= 0x2B07) || + (0x2B1B <= wch && wch <= 0x2B1C) || + 0x2B50 == wch || + 0x2B55 == wch + ) + { + return CodepointWidth::Ambiguous; + } else if (0x2B5A <= wch && wch <= 0x2E44) { // From Unicode 9.0, this range is narrow (assorted languages) diff --git a/src/types/inc/CodepointWidthDetector.hpp b/src/types/inc/CodepointWidthDetector.hpp index 689c520048..ecac9b8085 100644 --- a/src/types/inc/CodepointWidthDetector.hpp +++ b/src/types/inc/CodepointWidthDetector.hpp @@ -107,6 +107,7 @@ public: bool IsWide(const std::wstring_view glyph) const; bool IsWide(const wchar_t wch) const noexcept; void SetFallbackMethod(std::function pfnFallback); + void NotifyFontChanged() const noexcept; #ifdef UNIT_TESTING friend class CodepointWidthDetectorTests; @@ -114,9 +115,11 @@ public: private: bool _lookupIsWide(const std::wstring_view glyph) const noexcept; + bool _checkFallbackViaCache(const std::wstring_view glyph) const; unsigned int _extractCodepoint(const std::wstring_view glyph) const noexcept; void _populateUnicodeSearchMap(); + mutable std::map _fallbackCache; std::map _map; std::function _pfnFallbackMethod; bool _hasFallback = false; diff --git a/src/types/inc/GlyphWidth.hpp b/src/types/inc/GlyphWidth.hpp index 45f611ae6d..87190617cf 100644 --- a/src/types/inc/GlyphWidth.hpp +++ b/src/types/inc/GlyphWidth.hpp @@ -12,3 +12,4 @@ Abstract: bool IsGlyphFullWidth(const std::wstring_view glyph); bool IsGlyphFullWidth(const wchar_t wch); void SetGlyphWidthFallback(std::function pfnFallback); +void NotifyGlyphWidthFontChanged(); diff --git a/src/types/inc/convert.hpp b/src/types/inc/convert.hpp index 68842767d8..10b574e6c5 100644 --- a/src/types/inc/convert.hpp +++ b/src/types/inc/convert.hpp @@ -45,6 +45,6 @@ std::deque> SynthesizeKeyboardEvents(const wchar_t wch std::deque> SynthesizeNumpadEvents(const wchar_t wch, const unsigned int codepage); -CodepointWidth GetCharWidth(const wchar_t wch) noexcept; +CodepointWidth GetQuickCharWidth(const wchar_t wch) noexcept; wchar_t Utf16ToUcs2(const std::wstring_view charData);