From 9ffb332deac2026cd9eeb17d2d4ce03604676ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 17 Dec 2022 12:25:48 +0100 Subject: [PATCH] Day 17. --- 2022/day17.py | 156 ++++++++++++++++++++++++++++++++++++++++++ 2022/inputs/day17.txt | 1 + 2 files changed, 157 insertions(+) create mode 100644 2022/day17.py create mode 100644 2022/inputs/day17.txt diff --git a/2022/day17.py b/2022/day17.py new file mode 100644 index 0000000..32e1c38 --- /dev/null +++ b/2022/day17.py @@ -0,0 +1,156 @@ +# -*- encoding: utf-8 -*- + +""" +Part 2: + The idea is to find a repeatable tower to not have to calculate up to the given + number. + + The issue here is that you can consume a variable number of jets per rock, so you + cannot simply build a tower of hight LCM(len(ROCKS), len(JETS)), you need to find + a repeat point. The easiest repeat point is one where the incoming rock is the + first one (horizontal line) at the same place in the jet sequence. + + The first rock cannot pass any rock present in the tower, so we know if we start + with the same sequence of jets, it will end at the exact same positions (bottom) + and following rocks will follow the same pattern. + + What I did: + 1. Place rocks as in part 1 but keep tracks of the (rock 0, jet) previously done + (where jet is the index in the sequence, not just '<' or '>'). When a + (rock 0, jet) pair gets repeats, stop the process. + 2. At this points, you have places N rocks and the number of rocks between the + two (rock 0, jet) points is K. You have 1000... - N rocks to place, and you + can repeat sequence of K blocks by building towers of hight K starting with + rock 0 and at position "jet" in the sequence of jets. + 3. Once this is done, you are left with (1000... - N) % K rocks to place, starting + again at index "jet" in the sequence of jets. +""" + +import sys +from typing import Sequence, TypeVar + +import numpy as np + +T = TypeVar("T") + + +def print_tower(tower: np.ndarray, out: str = "#"): + print("-" * (tower.shape[1] + 2)) + non_empty = False + for row in reversed(range(1, tower.shape[0])): + if not non_empty and not tower[row, :].any(): + continue + non_empty = True + print("|" + "".join(out if c else "." for c in tower[row, :]) + "|") + print("+" + "-" * tower.shape[1] + "+") + + +def tower_hight(tower: np.ndarray) -> int: + return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1) + + +def next_cycle(sequence: Sequence[T], index: int) -> tuple[T, int]: + t = sequence[index] + index = (index + 1) % len(sequence) + return t, index + + +ROCKS = [ + np.array([(0, 0), (0, 1), (0, 2), (0, 3)]), + np.array([(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)]), + np.array([(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]), + np.array([(0, 0), (1, 0), (2, 0), (3, 0)]), + np.array([(0, 0), (0, 1), (1, 0), (1, 1)]), +] + +WIDTH = 7 +START_X = 2 + +EMPTY_BLOCKS = np.zeros((10, WIDTH), dtype=bool) + + +def build_tower( + n_rocks: int, + jets: str, + early_stop: bool = False, + init: np.ndarray = np.ones(WIDTH, dtype=bool), +) -> tuple[np.ndarray, int, tuple[int, int], int]: + + tower = EMPTY_BLOCKS.copy() + tower[0, :] = init + + done_at: dict[tuple[int, int], int] = {} + i_jet, i_rock = 0, 0 + rock_count = 0 + + for rock_count in range(n_rocks): + + if early_stop: + if i_rock == 0 and (i_rock, i_jet) in done_at: + break + done_at[i_rock, i_jet] = rock_count + + y_start = tower.shape[0] - tower[::-1, :].argmax(axis=0).min() + 3 + rock, i_rock = next_cycle(ROCKS, i_rock) + + rock_y = rock[:, 0] + y_start + rock_x = rock[:, 1] + START_X + + if rock_y.max() >= tower.shape[0]: + tower = np.concatenate([tower, EMPTY_BLOCKS], axis=0) + + while True: + + jet, i_jet = next_cycle(jets, i_jet) + + dx = 0 + if jet == ">" and rock_x.max() < WIDTH - 1: + dx = 1 + elif jet == "<" and rock_x.min() > 0: + dx = -1 + + if dx != 0 and not tower[rock_y, rock_x + dx].any(): + rock_x = rock_x + dx + + # move down + rock_y -= 1 + + if tower[rock_y, rock_x].any(): + rock_y += 1 + break + + tower[rock_y, rock_x] = True + + return tower, rock_count, (i_rock, i_jet), done_at.get((i_rock, i_jet), -1) + + +line = sys.stdin.read().strip() + +tower, *_ = build_tower(2022, line) +answer_1 = tower_hight(tower) +print(f"answer 1 is {answer_1}") + +total_rocks = 1_000_000_000_000 +tower_1, n_rocks_1, (i_rocks_1, i_jet_1), prev_1 = build_tower(total_rocks, line, True) + +# shift the line +line = line[i_jet_1:] + line[:i_jet_1] + +# remaining rocks +remaining_rocks = total_rocks - n_rocks_1 +n_repeat_rocks = n_rocks_1 - prev_1 + +# repeated tower +n_repeat_towers = remaining_rocks // n_repeat_rocks +tower_repeat, *_ = build_tower(n_repeat_rocks, line) + +# remaining tower +remaining_rocks = remaining_rocks % n_repeat_rocks +tower_remaining, *_ = build_tower(remaining_rocks, line) + +answer_2 = ( + tower_hight(tower_1) + + tower_hight(tower_repeat) * n_repeat_towers + + tower_hight(tower_remaining) +) +print(f"answer 2 is {answer_2}") diff --git a/2022/inputs/day17.txt b/2022/inputs/day17.txt new file mode 100644 index 0000000..07f3945 --- /dev/null +++ b/2022/inputs/day17.txt @@ -0,0 +1 @@ +><<<<><<>><<>><><<<>>><<<<>>>><<>>><>>><<<>><<<><<<><><><>>>><<>>><<<<>>><>><<<<>><><<<<>>><<<>>><<>><<<>>><>>>><<<<>>>><<<<><>><<<>>><<<<>><<<<>>>><<<<>>><<>>><<<>>><>>><<<<>>><<<<>>>><>>>><<>>><<><<<>>>><><<<<>>>><>><<>><<<><<<<>><<><<<<>>><>><<><<<>>><<<>>><<><<<<>><>><<<><<<>>>><>>>><<<>><<<<>>>><<<>>>><><<<<>>>><<<<>>>><<<<><<<>>>><><<<>>><<<><<><<<>>><<<><<>>>><<<>>>><<<>>><<><>>><<><>>>><><><<>>><<<>><<<>><><>>><<<>>><<<<><>><>>>><<><<<>>>><<><<<<>>><><<>>>><<<<>>>><<><<<<>><<><><>>>><<>><<>><<<<><>>><><<<>><<<>><><>>>><<<>><<<<>>><<><>>>><>>>><<<>>><<<<>>><><<<<>>><>>>><>>><<>>>><<>><<>>><<>><><>><<<<>>><<><<>><<<<><<<>>>><>>><>>><<<>>><<<>>>><<>>><<<<>><<>>>><><<<><>><<<><<<<>>><><<<><<<<>><>><<<<><<<>><>>><<<<>>>><<>>>><<<<>>><><<<>>><<<<><>><<<>><<<<><>>><>>>><<>>><<<>>>><<>>><><<<><<<<><<><>>>><><>>>><<>>><<<<>><<<<><<>>><<><<<><<<<>>><><<<>>>><>>>><<<><<<>><<><<<>>>><<<<>><><<<<>>>><<>>>><<>><<>><<<>><<<<>><>>><<<<>>>><><<>>><<>>><>>><<<<>>><<<<>>><<>><>><<<>><<<>>>><<<>>>><<>><<<><><>>><<<<>><<>>>><<><><<<><>>>><<<>><<<>>>><<<<><<>>><<>>>><<><<<<>><<>>><<<<>><>>><<>>>><<<<><><>>><<<<>>>><>>>><<>>>><<<<><<>><<<><<<>><<<>>>><<<><<<<>><<<<>><<<<>>>><<<>>>><>><<<>>>><<<>>><<><><<<>><<<>><>>><>><><<<<>><<<<>>>><<<>>><>>><<><><<>>>><<<<><><<<>>>><<>><<>>><<<<>>>><>>>><>><<<>><<<<>>>><><<><<>>>><<<>><<>>><<<<>><<>>><<<<>>>><<<>>><<<><>><<><>>>><<>>>><<<><>>><>>>><<<<>>><<<>><<>>><<<<><<<>>><<>>><<<<>>><<>><<<><>>><><>>>><<>>>><<>><<<<><<<>>><<<<>><<<>><>><<<>><>>><<<>>>><>><><<>>><<>>><<<>>><<>><<<<>>>><<>><<>>><<>>><<>>><<>><><<<>>>><>>>><><<<>>><>>><<<<>>><<<<><>>>><<<<><<><<<>>>><<<>><<<><><<<<>>><<>>><<<<>>>><<>>><<<><<<<>>>><<<<>><<<><<>>><>><<>><<<<>><>>>><<>><<<>>><<<><<>>><<<><<<<><<<<><<>><>>>><>><>><<>>><<<<>>>><<<<>>><<<<><<<<><<<><>>><>>><<<<>><<>>>><><>>><>>>><><>>>><<<>><<>><<<<><>>>><<<><<<<><>>>><<>>><<<>>>><<>>>><<<<><<<<>>>><<><<<<>><<<>><>>><<<<><<>><<<>>><>><<<<>>>><<>>><<<>>><>><<<>>>><>><<<><<<<>>><<<<>><<>>><<<>>>><<<>>><><<><<<><<>>>><<>>><<>>>><>>>><<<<><><>>>><<<>>><<<>>>><<>><<<<><<<>>><<<>>>><>><<>>><<<>>>><>><><<<<>>>><>><<<<>>>><<<<>><>>>><<><<<<>><><<<>>><<<<><<<<><>><>>>><<<>>>><<<>><<>>>><>><<<>>><<<>>><<<<>>><<<<><<>><<<<>><>>><>>><<>>><<<><<<<>>>><<<>>><<>>><<<<>><><<<>>>><><<<<>>><<<>>><<<>><<>>>><<>>><<<<>>><<>>><>>>><<>><<<>>>><<<<>>>><<<<><<><><<>>>><<<<><<>>><<<<>>><<<<>><<><>>><>><<>>>><<<<>><<<>>><<<<>><<>><<><<>>><<<>><<<>>>><<>>><<<>>>><<<<>>><<<<>><<>>>><<<>>>><>><<<<>>><>>><<><<>>>><<<>>><>>><<<>><<<<><><<<>>><<<><<<>><<<<><<<>><<<<>>>><>><>><>>>><<<><<<>>><<<><<<<>>>><<>>>><<<>><<>><<<<>><>><<<><<<<>><<<>>>><<>>>><<>>>><>>>><<<<>>><<>>>><<>>>><<>><<<>>><>>>><<<<><>>>><<<<><>>>><<<>>>><<<<>>><<<<>><><<<<>>><><>><<<<>>><<<>>><><<<>>>><<<>>>><<><<<<><<<<><<><<<<>>><>>>><<>>>><<<>>>><<<>>><<<<>>><>><<<><<<<>>>><<<<>>><<<<>>>><<<<><<<>><<<>>>><<<><<<<><>><<<<>><><<<>>><>><<<>>><<>><<>>><>><>>><<>>><<<>>>><>><<<>><<>>><<<<>>>><>><><<>><>><<<<><><<>>><<<<>>>><<>>><<<<>>><<<<><>>><<<>>>><<<<>>><<<>>>><<<>><<><><<<<>>><<>>>><<>>><<><<<<>>>><>><<>><<<<>><>>><<<<>><<>>>><<<<>>><<>><>><>><><<<>>>><<<>>><<>><><<>>>><<<>>><<<>>>><<<<><<<>><>>><>>>><<<<><<<<>>>><<<>><<<<><<<<>>><<<<>>>><>>><<<<>>>><<<>><<<>><<<>>><<<<>>><<<>>>><>>><><<>>><>>>><<>>><<>>>><<<>><<<><<>>><<>>>><<<<>><><<<<><<<>><>>>><<<<>>>><<<<>>><<<<><><>>>><<>><>>><<>>>><<>>>><<<<>>><><<>>><<<<><<<><<>>><>>><>><>>>><>><<<>>>><<>>><<<>>><<>><<<<>>><<>>><<><<<<><<>>>><<<<><>>>><<<>><<><<<<><<><<>>>><<><<<<>>><<>>><>><>>><>>>><>>>><<>><<<<><<<<>>>><>>><<>>>><<<<>>><<><<<<>>><<<<>><>>>><>><<<<>>><<>><<<>><<>>><<<<>>>><<<>>>><>>>><>>>><<<<><>>><>>>><<<>><>><<><<<><<>>>><<<<>><<>>><<>>><<<<>><<<<><<<>>>><<<>><<>>>><<<>>>><<><><<<<>>>><><<>>><<>>>><<<>>><<>><<><<<><<<>>>><><<<>>><<<<>><>>>><<<><<><<<<>>>><<><<<<>>>><<<>><><<>>>><>>>><<<<><<<><<<>>>><<>><>>><<<>>>><<>>>><>><<<><<><<<<>>>><<>>>><<<>><<>><<<<><<>><<<>>>><<><<<>>><<<<>>><<<<><<>><<<>>>><>>>><<<<>>><>><<<<>>>><<<><<<<>>>><<<>>>><<><<<<>>>><<<<><<>>>><<><<><>>><>>><>>><>>>><<<<><<<<>>>><>><<<<>><<<<>>><<<<>>>><>><<<>>>><>>>><>>>><<>>>><>><<<>><><<>><<>>><>><><>>>><>>>><>>>><<<>><<><<<<>>>><><>>><><>><>><<>>><<>><<>>><<<<><<<>>><<<<>>>><<<<><<<>>><<<<>>>><<<<>>>><>>><><>><<<<>>>><<<<>><<><><<<><<>><<<<>><<<>><<<>>><<<>><<<>><><<>>>><<<<><<>>>><<><<<>><<<<>>><<<>>><<<>><>><<<<>><<<<><<<<>><<<<><>>><<<<>><<<<>>><<<<><<><>><<<>><>>>><>>>><>>>><<<<>><<<<><<>>><>>>><<<<>>><<<><<<>>><<<>><<><<>>><<<>>>><<<>>>><<<<>><>>>><<<<>>><>>><<>>>><<>>>><>>><<<><>>><<<><>>>><<<<>>><<<>><<<>>>><<<<>>>><<><><><<<><<>>>><<<<><<<>><<>><<<<>>><<>>><<<><<<>>>><<>><>>><>>><<<<><<<>>><<<><<<><<<>><<>>><<><<>>>><<<<>>><<<>>>><<>><<<<>>>><<><<<<><<>>><<<><>>>><<<><<>>>><>>><<>>><<<<>><<>>>><<<>>><<<>>>><<<<>>>><<<><<<>>><<<><<<>>><<<<><<>>>><>>>><<<>>>><>>><>>>><<<>><<<<><<<<><<<<>><<<<><<<<><>><<><<<<>>><<<<>>><<>>><<<>>>><<<>>>><<<>><<<>><<<><<<>>><<>>>><><<<>><<<>>><<>><<<<><<>>><>><<<>>>><<<<>>>><<>>><<>><<><<<<><<<>>>><<<<>>>><<>>><<>><<<>>><>>>><<<>><>>>><<>>>><<<<>><<<<>>>><<>><>>><><<><<>>>><<>><<><>>>><<>><<<<>>>><>>><><<<<>>><<<<>>>><<>>>><<>>>><<<<>><<<>>><<>>><>>>><<<><<<><<<>><>><><>>>><<>><<<<>><<<<>><><>><<>>>><<<><<<><>>><<<>>><<<>>>><<<>>><<<>>>><>>>><<<>><>>>><<<>>>><<<>>>><<<<><>>>><<<<>>>><>>><<<>>><<>><<><<<>>>><<<>>>><<<>><>><<<<>><<<>><<<>>><<<<><<<<>>>><<<<>>><<<<>><<<<>><<><>>><<<>>><<<<><<<>>><<<<><>>><<<>>>><>>>><><<<<>>>><><>><<>>>><>>><<<<>>><<<>><>><<<<><<<<>>><><<<<>>>><>><>><<<<>><<>><<<<>><<>>><<>>><<<>>>><<>>><<>><<<<>>><<>>>><<><<>><<<<>>><<<<><<<<><<<><>>><<>><<<<><<<>>>><>>>><><<<><<><<<<>><<<>><>>>><<<<>><<><<<><<<<>>>><<<><<>>>><><<><<<<><<<<>>><<<<>>>><<>>><<<><<<>>>><><<>>>><><<><<<<><<>>>><><<>><<>><>>><<><<<>><<>>>><<<<><<<<><><>>>><<<<>>><<<<>>><<>>>><<<><<<>><<<>>>><<<<><<<<>><<<<>>><<<<>>><>>><<<><<><<<<>>>><>><<>>><>><<<<>>><>>>><<>>>><<<<><<>>><<<<><<>><><<>>>><>><<>><<<<>><<>><<<<><<<<>>>><<<>><<>>><<><<<<>>>><<<>>>><<>>>><>>><<<>>><><<>><<>>><>>><>>>><<>>><<<>>>><><<<<><<>><<<<>>>><>><<<<><<<<><<<<>>>><<<><<<<>><<<>>>><<<<>><>>>><>><<<<>><>>><><<<>><><<<<>>><>>><<<>>>><<<>><<<<><<><<<><>>><>>>><<>>>><<<<>>><>>>><>>>><<>><<>>><<<<>>><<>>><<>>>><<<><<>>>><<<<>><>><<<>>><<<<>>>><>>><<<>>>><<<>><<>><<>>>><<<>>><<<>>>><>><<>><<<<><>>>><>><<>><>><>><>><<<>><<><>>>><>>><<<<>>><<<>><<<<>><<<<>><><<<<><<<<>><<<<>>><<>>>><><<<<>><<<<>><<<<>><>><>>><<><<>>><<<><<<>>><>>><><<<>>>><<<<><<<>>>><<>><>>><<><<>><<<>><<<<><<<<>>><>>><<><<>>>><<<><<><<<<>>>><<<<><<>><>>><<<<><<<>>>><<>><<<><<<>>><>>>><>>><<>>><>>><<<<>><>>>><<><>>>><<<><<><<<<>>><<<>>>><<><><<>><<<<><<>><<><<<<>><<><<><<<<>><>><<<>>><<><<<>>><<<<>>><>>><><><<>>>><<><<<<><>><>>>><<<<><<<<>>><<<<>>>><>><<<>><<<>><<<<>>><<>>><<<<>>>><<<<>><<>><<>><<<<>><>>>><<><>>>><<<>>>><<<>><>>>><<<>>><<>>><<>><><<<<>>><<>><<<<>><<<><<>>><<<>>>><<>>><<>>>><<<<>>>><>>><><<<<>>><<<>>><<<>><<>>><<<<><<<>><<<>><<><>>><<<<><<>><<<<>><<><<><>>>><>>><<>>>><<<<>>><<><<<>><<<>>>><<>>>><>>>><<>><<<>>><>>>><<>><<<>>>><<<>><<<<>>>><<<<><<>>><>>><<<><<>><>>><>>><<<>><<<<>><<<>>><>><<<>><<<<>>><<><><<<<>><<<><<<<>>><>>>><<<><<<<>><<<>><<><<<>>>><<<<>><>>><<<>><<>>><<<>><<<>>>><<<>>><<<<><<>><><<<>>><<<<>>>><<>>><>>>><<>>><<<<>>><>><<<>><>><<<<>><<<<><<>>><<><<>>>><<<><>>>><<<>>><<<>>><<>><<<<>>><<>>>><<<<>>><<><<<>><<>>>><<<<><<<<>>>><<<<>>><<<>><<>>><<<><>>><<>>><><>>>><<>><>><<<<>>>><<<>>><<<<>>>><>><<<<>><<>><<<>>><<<<>>><<<>>><<>><<<>>>><<>>><<>><<<><<<>>><<>>><<<>>>><<<<>><<<<>><<<>>><<<>>><<>>>><<<<>>>><<><<<<><>><>>>><<><<>>><<<<><<<<>>>><>>><<<><>><<>>><<<<>>><<>>>><<<>>>><>>>><<<>><><<>>><<><<<>><<>><>>><<<<>><>>>><<>><>>><<<<>><<>>>><<><<<<>>>><<<>>><>>><<<><>>><>><<<<><>>>><<<<><<<<>>><>>><><<>>><<>>><><<<<><<<><>><>>>><<<>>>><><>><><>><<<<><<<><<<>>>><<<>>><<>>><<<>><<<><<>>><>>>><<><<>>>><<<<>><<>><>>><<<<>>><<<>>>><<<<>><<<<>>>><<>><<<>><<<>><<<>>>><<<<>>>><>><<<<>>>><><><>>><>>><<<>>><>><<<<>>>><<><<<>>>><<>>><<<><<<<>><<<><>>><<>>><<<<>>>><><<<<>><<<>><<<>><<<>><<>>>><<<>>>><<<>>><<<><<<><<<><<<<><>><<>>><><<<><<<>>><<<<>>>><<<>>><>>><><<<>><<<>>>><<><><<<<>>>><<><<<>>>><<<>>>><<><<<<>>>><<<><<<>>>><<>>>><<><><<<<>>><<<><<<><><<>>>><<>>>><<<>>>><<>><<><>>>><<<<>>>><<<<>>><<<<>><<<><<><>><<<>>>><>><>><<<<><><><><<<<>>><<<<>><<>><>><<>><<<>>>><<<>>>><<<<>>>><<<>><<<>>>><<>>>><<<><<<>>><>>><<<>>><<<<>>><<<<>>><>>><<<<>>><<<<>>><<<>><<<<><<<>>><<<<>><<<><<<>>><<<<>><<>><<<<><<<<><><>>><<>><><<<<>>>><<>>><<<>><<><><>>><>>>><>>>><<<<>>><<<<>>>><<>>><<<<><<<<>>>><<>><<<>>><<>>>><<<>><<<<>><><<<<>>><<>><<<<>>><<<<>>><>>><>>><<<<>>><<<<>>>><>>>><<<<>>><><<><>>>><><<<<>>><>>>><<>>>><<><<<<>>><<<>>>><<<>>><<<<>><<<><<<<><<<<>><<<>>>><<<<>>><<<><<<<>>><<<<>>><<>>><<<>>>><>>>><<>>><<<><<<><<<<>><<<<>>>><<>>><<<>>>><<<>><<<<><<<>>>><<<<>><<<<><<><<<<>>><<<>>>><<<><>><<<>><>><<>>><<><<<><><<<>><<>>>><<><>><<<>>><<>>>><>>>><<<<>>><<>>>><<>>><<>><<<><<<<><>>><<><<><>>><<<<>>>><<<>>>><<>>>><<<<>>>><<<><<<<><>>><<>><<<><<>>><>>><<<>>><<>>><<>>>><<><<<<>>><>><>><<<><<<<>><<<<>>>><>>><<>>>><<<<>><<>>>><<><>><<<>><<<><<<>>>><<>><<<>>><<<<>>><>>><>>><<<<>>>><<<>><<<>><<<<><<<>><<<>>><<>><<<>><<>><<<>>><<<<><<>>>><<><>><<>>><<<>>>><><>>>><>>>><><<<<>>>><<>><<>><>>>><<>><<>><<<<>><<>><<<<>>>><>><<<<><><>><<>><<<<>>><<<<>><<<><<<>><<<><<<>><<<<>>>><>>><<<>>>><<<>>>><<<>>>><<>>>><<>><>>>><<<>>><<<<>><>>><<<>><>>><<<>>>><<<<><>><<<<><<>>>><<<>>>><<<<>>><>>><<<<><<>><>>><<<>>><>>>><<<>>><<<>><><>><<>>><<<>><<<>><>><<>>><<<>>><><>>><<<>>>><<><>>><<>>>><<<<>>>><<<<>><<<<><<>>>><<<>><<>>>><<>>><<>>><<>>><<><<<<><<<>>><<<><>>><<<<><<<>>>><<<>>>><<<<><<>>>><<<>><<<>>>><<<<>>>><<<<>>><>>><<><<<><<<>>><<<<>>>><<<<>>>><<><><<<<>>>><<>><<<<>>><<<>><>>><<<>>><>><<<>>><>><<<><<>><>>><<<>><<>><>><<>>><>><<<><<<>>><<<<>><<<<>>><>>>><<<<><<<<>>>><>>><><<<<>>><<<<>>>><>><<>>>><<<<>>><<<<>><><<>>>><<>>><<<<>><<<>>><<<><<<<>>>><>><<>>><<>>><>>><<>>><<>><<<<>><<>>>><<<<>><<>>><<>><<>>><>>><<<>>>><<<>>>><<<<>>><>><<<>>><<<><<>>>><><<<>>>><<>><<>>>><>>><<>>>><><<>>><<<><>><<<>><>>>><>>>><<<>><<>>>><>><<>>>><<>><<<<>>>><<<<><>>><>>>><<>><<><<<><<><<<<>>><<<<>>>><<>><<>>><><<<>><>>>><<<>>><><<><<<>>><<<<>>><>>><<><<><<>><>><<><<>>><<<<