#include <iostream>
#include <vector>
#include <limits>
#include <algorithm>
#include <limits.h>
#include <chrono>
#include <fstream>
#include <unordered_map>
#include <string>

#include "main.h"

typedef std::pair<int, int> Position;

const int EMPTY = -2;
const Position UNKNOWN = {-1, -1};

using namespace std;

vector<vector<int>> heights_to_mat(const vector<int>& heights, int H) {
    int W = heights.size();
    vector<vector<int>> m(W, vector<int>(H, EMPTY));
    int k = 0;
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            m[i][j] = k++;
        }
    }
    return m;
}

State::State(const vector<vector<int>> _bay = {}, const vector<int> _heights = {}, int _H = 0,  int _max_ind = -1) {
    H = _H;
    heights = _heights;
    W = heights.size();
    n = 0;
    if (_bay.empty()) {
        bay = heights_to_mat(heights, H);
    } else {
        bay = _bay;
    }

    max_ind = _max_ind;
    if (max_ind == -1) {
        for (const auto& l : bay)
            for (int x : l)
                max_ind = max(max_ind, x);
    }

    position = vector<Position>(max_ind + 1, UNKNOWN);
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            int val = bay[i][j];
            if (val >= 0)
                position[val] = {i, j};
            n++;
        }
    }
}


State State::copy() const {
    State s;
    s.H = H;
    s.W = W;
    s.n = n;
    s.max_ind = max_ind;
    s.position = position;
    s.heights = heights;
    s.bay = bay;
    return s;
}

int State::top(int i) const {
    if (heights[i] > 0)
        return bay[i][heights[i] - 1];
    return EMPTY;
}

void State::move(int i, int j) {
    if (heights[j] < H && heights[i] > 0) {
        int v  = top(i);
        bay[j][heights[j]] = v;
        bay[i][heights[i] - 1] = EMPTY;
        heights[i]--;
        heights[j]++;
        position[v] = {j, heights[j] - 1};
    }
}

void State::retrieve(int i) {
    if (heights[i] > 0) {
        heights[i]--;
        int v = bay[i][heights[i]];
        position[v] = UNKNOWN;
        bay[i][heights[i]] = EMPTY;
        n--;
    }
}

void State::add(int i, int x) {
    if (heights[i] < H) {
        bay[i][heights[i]] = x;
        heights[i]++;
        position[x] = {i, heights[i] - 1};
        n++;
    }
}

pair<int, int> State::get_position(int x) const {
    if (x < position.size()) {
        return position[x];
    }
    return UNKNOWN;
}

void State::print_bay() {
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            std::cout << bay[i][j] << " ";
        }
        std::cout << endl;
    }
}

class Ordered_State State::apply_order(const vector<int>& order) {
    Ordered_State os;
    os.bay = bay;
    os.heights = heights;
    os.H = H;
    os.W = W;
    os.n = n;
    os.max_ind = max_ind;
    os.position = position;
    os.min_container = 0;
    int k = 0;
    for (int x : order) {
        Position pos = get_position(x);
        int i = pos.first, j = pos.second;
        os.bay[i][j] = k++;
    }
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            os.position[os.bay[i][j]] = {i,j};
        }
    }
    return os;
}

Ordered_State::Ordered_State() : State() {
    min_container = 0;
}

string Ordered_State::to_string() const {
    string res = "";
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            res += std::to_string(bay[i][j] - min_container) + " ";
        }
        res += ",";
    }
    return res;
}

void Ordered_State::retrieve(int i) {
    State::retrieve(i);
    min_container++;
}

void Ordered_State::add(int i, int x) {
    State::add(i, x);
    min_container--;
}

bool Ordered_State::operator==(const Ordered_State& other) const {
    if (heights != other.heights || n != other.n) {
        return false;
    }
    for (int i = 0; i < W; i++) {
        for (int j = 0; j < heights[i]; j++) {
            if (bay[i][j] - min_container != other.bay[i][j] - other.min_container) {
                return false;
            }
        }
    }
    return true;
}

std::unordered_map<string, int> memo;

vector<vector<int>> gen_all_seq(int n, int k, int forbidden = -1) {
    vector<vector<int>> result;
    if (k == 0) {
        result.push_back({});
        return result;
    }
    vector<int> seq(k, 0);
    while (true) {
        // Check for forbidden value
        bool valid = true;
        for (int i = 0; i < k; ++i) {
            if (seq[i] == forbidden) {
                valid = false;
                break;
            }
        }
        if (valid) result.push_back(seq);

        // Increment sequence
        int pos = k - 1;
        while (pos >= 0) {
            seq[pos]++;
            if (seq[pos] < n) break;
            seq[pos] = 0;
            pos--;
        }
        if (pos < 0) break;
    }
    return result;
}

int opt(Ordered_State& s, int depth = 0) {
    string c = s.to_string();
    if (memo.find(c) != memo.end()) {
        return memo[c];
    }
    if (s.n == 1) {
        return 0;
    } 
    Position req = s.get_position(s.min_container);
    int i = req.first, j = req.second;
    int to_move = s.heights[i] - j - 1;
    vector<vector<int>> all_seq = gen_all_seq(s.W, to_move, i);
    int mini = 1000000;
    for (vector<int>& seq : all_seq) {
        for (int x : seq) {
            s.move(i,x);
        }
        int removed_index = s.top(i);
        s.retrieve(i);
        int v = opt(s, depth + 1);
        s.add(i, removed_index);
        auto it = seq.end();
        while (it != seq.begin()) {
            --it;
            s.move(*it, i);
        }
        mini = min(mini, v + to_move);
    }
    memo[c] = mini;
    return mini;
}

double ratios(State& ref_s, State& s, int cost, vector<int> &order, Position req = UNKNOWN) {
    if (s.n == 0) {
        Ordered_State ref_os = ref_s.apply_order(order);
        int v = opt(ref_os);
        if (v == 0 && cost > 0) return 100000.0;
        if (v == 0 && cost == 0) return 1.0;
        return static_cast<double>(cost) / static_cast<double>(v);
    }

    if (req == UNKNOWN) {
        double maxi = 0;
        for (int i = 0; i < s.W; i++) {
            for (int j = 0; j < s.heights[i]; j++) {
                req = {i, j};
                int x = s.bay[i][j];
                order.push_back(x);
                maxi = max(maxi, ratios(ref_s, s, cost, order, req));
                order.pop_back();
            }
        }
        return maxi;
    }

    int i = req.first, j = req.second;
    int to_move = s.heights[i] - j - 1;
    vector<vector<int>> all_seq = gen_all_seq(s.W, to_move, i);
    double mini = numeric_limits<double>::infinity();
    for (vector<int>& seq : all_seq) {
        for (int x : seq) {
            s.move(i, x);
        }
        int removed_index = s.top(i);
        s.retrieve(i);
        double v = ratios(ref_s, s, cost + to_move, order);
        s.add(i, removed_index);
        auto it = seq.end();
        while (it != seq.begin()) {
            --it;
            s.move(*it, i);
        }
        mini = min(mini, v);
    }
    return mini;
}

std::vector<std::vector<int>> gen_all_state(int n){
    std::vector<std::vector<int>> result;
    for (int a = n/3; a <= n; a++) {
        for (int b = (n-a+1)/2; b <= n - a && b <= a; b++) {
            int c = n - a - b;
            result.push_back({a, b, c});   
        }
    }
    return result;
}

void backtrack(int n, int w, int start, std::vector<int> &current, std::vector<std::vector<int>> &results) {
    if ((int)current.size() == w) {
        if (n == 0) results.push_back(current);
        return;
    }

    for (int i = min(n, start); i >= 0; --i) {
        current.push_back(i);
        backtrack(n - i, w, i, current, results);
        current.pop_back();
    }
}

std::vector<std::vector<int>> generateSequences(int n, int w) {
    std::vector<std::vector<int>> results;  // now local to this function
    std::vector<int> current;
    backtrack(n, w, n + 1, current, results);
    return results;
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    int w;
    int x;
    std::cin >> w;
    std::cin >> x;
    for (auto v : generateSequences(x,w)){
        State s({}, v, 15);
        
        vector<int> order;
        State ref_s = s.copy();
        for (auto x : v) {
            cout << x << ", ";
        }
        cout << " ==> ";
        cout  << ratios(ref_s, s, 0, order) << endl;
    
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end - start;
    cout << "Elapsed time: " << elapsed.count() << " seconds" << endl;
    
    
    return 0;
}
