#include <bits/stdc++.h>   enum QueryType { kArea = 1, kCrossProduct = 2 };   int64_t ask(QueryType query_type, int64_t first_index, int64_t second_index,               int64_t third_index) {     std::cout << query_type <<     << first_index + 1 <<     << second_index + 1               <<     << third_index + 1 << std::endl               << std::flush;     std::cout.flush();     int64_t answer;     std::cin >> answer;     return answer;   }   void answer(const std::vector<int64_t>& permutation) {     std::cout <<  0 ;     for (auto index : permutation) {       std::cout <<     << index + 1;     }     std::cout << std::endl << std::flush;     std::cout.flush();   }   int main() {     int64_t vertex_count;     std::cin >> vertex_count;     std::vector<int64_t> left, right;     for (int64_t third_index = 2; third_index < vertex_count; ++third_index) {       if (ask(kCrossProduct, 0, 1, third_index) == 1) {         left.push_back(third_index);       } else {         right.push_back(third_index);       }     }     std::vector<int64_t> area(vertex_count);     for (int64_t third_index = 2; third_index < vertex_count; ++third_index) {       area[third_index] = ask(kArea, 0, 1, third_index);     }     std::vector<int64_t> permutation = {0};     if (!right.empty()) {       int64_t rightmost = *std::max_element(           right.begin(), right.end(), [&](int64_t first, int64_t second) -> bool {             return area[first] < area[second];           });       std::vector<int64_t> right_bottom, right_top;       for (auto vertex : right) {         if (vertex != rightmost) {           if (ask(kCrossProduct, 0, rightmost, vertex) == -1) {             right_bottom.push_back(vertex);           } else {             right_top.push_back(vertex);           }         }       }       std::sort(right_bottom.begin(), right_bottom.end(),                 [&](int64_t first, int64_t second) -> bool {                   return area[first] < area[second];                 });       std::copy(right_bottom.begin(), right_bottom.end(),                 std::back_inserter(permutation));       permutation.push_back(rightmost);       std::sort(right_top.begin(), right_top.end(),                 [&](int64_t first, int64_t second) -> bool {                   return area[first] > area[second];                 });       std::copy(right_top.begin(), right_top.end(),                 std::back_inserter(permutation));     }     permutation.push_back(1);     if (!left.empty()) {       int64_t leftmost = *std::max_element(           left.begin(), left.end(), [&](int64_t first, int64_t second) -> bool {             return area[first] < area[second];           });       std::vector<int64_t> left_bottom, left_top;       for (auto vertex : left) {         if (vertex != leftmost) {           if (ask(kCrossProduct, 1, leftmost, vertex) == -1) {             left_bottom.push_back(vertex);           } else {             left_top.push_back(vertex);           }         }       }       std::sort(left_bottom.begin(), left_bottom.end(),                 [&](int64_t first, int64_t second) -> bool {                   return area[first] < area[second];                 });       std::copy(left_bottom.begin(), left_bottom.end(),                 std::back_inserter(permutation));       permutation.push_back(leftmost);       std::sort(left_top.begin(), left_top.end(),                 [&](int64_t first, int64_t second) -> bool {                   return area[first] > area[second];                 });       std::copy(left_top.begin(), left_top.end(),                 std::back_inserter(permutation));     }     answer(permutation);     return 0;   }