Minecraft Inventory Management

11

Управлять инвентарем Minecraft сложно. У вас есть 17 бриллиантов, но вам нужно 7, чтобы изготовить стол для зачарования, кирку и меч. Вы берете их и щелкаете правой кнопкой 7 раз? Или вы щелкаете правой кнопкой один раз, дважды щелкаете правой кнопкой мыши и берете 7 влево? Это так запутанно!

для тех из вас, кто сейчас в замешательстве, не волнуйтесь, я объясню все через секунду

Вызов

Учитывая размер стопки предметов и желаемую сумму, определите наименьшее количество кликов, чтобы получить эту сумму. Вам нужно только обработать до 64 для обоих входов, и вы можете предположить, что у вас есть бесконечные слоты инвентаря. Вы не можете использовать трюк перетаскивания для распространения.

Определения

Опись представляет собой набор слотов , где вы можете хранить предметы.

Слот представляет собой место для хранения в вашем инвентаре , где можно разместить до одного типа элемента.

Стека является количество элементов , размещенных в одной и той же группе. Для целей этой задачи стек - это просто набор элементов в одном месте (поэтому игнорируйте размер стека)

Курсор Ваша заостренная штуковина. Этот курсор. У него могут быть предметы "на нем"; другими словами, если вы нажали на слот и подняли предметы, предметы, которые вы подняли, находятся «на курсоре», пока вы не положите их вниз.

Характеристики

Есть четыре возможных ситуации. Либо у вас есть элемент на вашем курсоре, либо у вас его нет, и либо вы щелкаете левой кнопкой мыши, либо щелкаете правой кнопкой мыши.

Если на вашем курсоре нет элемента, и вы щелкаете левой кнопкой мыши по слоту, вы берете весь стек.

Если на вашем курсоре нет элемента, и вы щелкаете правой кнопкой мыши по слоту, вы берете половину стопки, округленную в большую сторону.

Если на вашем курсоре есть предмет и вы щелкаете левой кнопкой мыши по слоту, вы помещаете все предметы в этот слот. (Для всех вас, игроков Minecraft, у вас не будет> 64 предметов для этого испытания, и они все 64-стекируемые, и у вас есть только один тип, поэтому обмен предметами здесь не применяется)

Если у вас есть элемент на вашем курсоре, и вы щелкаете правой кнопкой мыши по слоту, вы помещаете один элемент в этот слот.

Итак, вы начинаете со всех данных предметов (первый ввод или второй; вы можете выбрать порядок) в слоте, и вы хотите закончить с желаемым количеством (другой ввод) в вашем курсоре.

Давайте рассмотрим пример. Допустим, вы начинаете с 17 предметов и хотите получить 7. Сначала вы щелкаете правой кнопкой мыши по стеку, что означает, что вы подняли 9 и в этом слоте 8. Затем, если вы снова щелкнете правой кнопкой мыши по стеку, вы поместите один предмет обратно в слот, и у вас останется 8, а в слоте - 9. Наконец, вы снова щелкните правой кнопкой мыши, и у вас будет 7, а в слоте - 10. Таким образом, вы бы вернулись 3(количество кликов).

Если вам удастся превзойти меня в игре, скажите, и я отредактирую пример: P

Тестовые случаи

Они генерируются вручную, поэтому, пожалуйста, сообщите мне, если есть какие-либо ошибки. Я делаю управление запасами с помощью щелчка правой кнопкой мыши, поэтому у меня нет опыта оптимального управления запасами: P

Given, Desired -> Output
17, 7 -> 3
64, 8 -> 5
63, 8 -> 5
10, 10 -> 1
10, 0 -> 0 # note this case
25, 17 -> 7

Пояснения

Этот вызов может быть сложным для игроков не из Minecraft, я понятия не имею. Вот несколько объяснений.

64, 8 -> 5 потому что вы выбираете 32 с помощью правого щелчка, поместите его вниз, поднимите 16, поместите его вниз, затем поднимите 8.

63, 8 -> 5 по той же причине.

25, 17 -> 7 потому что вы подняли 13, поместите его вниз, возьмите 6 из остатка 12, поместите 2 обратно в оставшийся стек, а затем поместите 4 в курсоре в 13, а затем поднимите их.

правила

  • Применяются стандартные лазейки
  • Вы можете предположить, что 0 <= desired <= given <= 64
  • Вы можете принимать входные данные в любом порядке и выполнять ввод / вывод в любом разумном формате.
HyperNeutrino
источник
1
ae-mod.info
Стивен
Связанные
AdmBorkBork
2
Так что это как-государственной машины , которая начинается с состояния 0,[n], может перейти: (1) от 0,[a,b,...]до a,[b,...], b,[a,...], ceil(a/2),[floor(a/2),b,...], или ceil(b/2),[a,floor(b/2),...]; или (2) из x,[a,b,...]( x>0) до x-1,[a+1,b,...], x-1,[a,b+1,...], x-1,[a,b,...,1], 0,[a+x,b,...], 0,[a,b+x,...], 0,[a,b,...,x]. Задача состоит в том, чтобы найти минимально возможные переходы от точки 0,[g]g к точке, t,Lгде tнаходится желаемая цель и Lесть ли какой-либо список?
Джонатан Аллан

Ответы:

2

C ++ , 498 482 457 байт

Если эта функция вызывается только один раз, она может быть 455 байтов.

Я обнаружил, что почти каждый онлайн-компилятор GCC (включая TIO) запрещает мне опускать тип функции f. Однако GCC на моем компьютере позволяет это, и я не знаю почему.

Этот может обрабатывать большие входные данные, если слот может содержать такое количество элементов (хотя требуется больший массив и, вероятно, закончится время).

#import<bits/stdc++.h>
#define t N.first
#define X n.erase(n.find
#define p(c){if(c==r)return l;if(L.emplace(w={n,c},l).second)Q[U++]=w;}
#define T(S,C)n.insert(S);p(C)X(S));
using m=std::multiset<int>;using s=std::pair<m,int>;s Q[99999];int x,l,B,U;int f(int a,int r){if(!r)return 0;std::map<s,int>L;s f({a},B=0),w,N;L[Q[U=1]=f];for(;;){l=L[N=Q[B++]]+1;x=N.second;t.insert(0);for(int i:t){m n=t;X(i));if(x){T(i+x,0)T(i+1,x-1)}if(!x&&i){p(i)T(i/2,i-i/2)}}}}

Ungolfed:

#include <map>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

struct state {
    multiset<int> t; int q;
    bool operator<(const state& i) const { return make_pair(t, q) < make_pair(i.t, i.q); }
};

int f(int a, int target) {
    if (target == 0) return 0;

    map<state, int> len;
    queue<state> qu;
    state first = {{a}, 0};
    qu.push(first);
    len[first] = 0;

    #define push(c) { state a = {n, c}; auto t = len.insert({a, l + 1}); if (t.second) { \
        if (a.q == target) return l + 1; qu.push(a); \
    } } // push new state into queue and check for termination
    #define next(stk, cur) { n.insert(stk); push(cur); n.erase(n.find(stk)); }
    // insert new stack, push new state, erase the stack (for another use)

    while (qu.size()) { // BFS cycle
        state now = qu.front();
        qu.pop();

        int q = now.q;
        int l = len[now];

        multiset<int> n(now.t);
        for (int i : now.t) { // click on non-empty stack
            n.erase(n.find(i));
            if (!q) { // nothing on cursor
                push(i); // click left
                next(i / 2, (i + 1) / 2); // click right
            }
            else { // item on cursor
                next(i + q, 0); // click left
                next(i + 1, q - 1); // click right
            }
            n.insert(i);
        }
        if (q) { // click on empty stack
            next(q, 0); // click left
            next(1, q - 1); // click right
        }
    }
}
Колера Су
источник
1

Желе , 74 байта

Ẏċ⁴¬
HĊ,$Ḟµ€1¦€F€;⁸Ḣ,$€
‘1¦€ṭ€⁹’¤
+1¦€⁹ṭ€0;ç
⁹Ȧ‘Ḥ¤ŀ
Ṫ;0ṙJ$çḢ
Wṭ0WÇ€Ẏ$ÑпL’

Полная программа с первым вводом (3-й аргумент) текущего стека и вторым вводом (4-й аргумент) искомого курсора.

Попробуйте онлайн! Из-за внедрения это истекает 60-секундным тайм-аутом для25, 17тестового примера. Это можно исправить, удалив избыточность, оставленную для игры в гольф, с использованием этого 84 байта (который отфильтровывает стеки нулевого размера и сортирует оставшиесяḟ€Ṣ¥0¦€0в конце ссылки 6 и сохраняет только уникальные состояния на каждом шаге с использованиемQ$в Main ссылка на сайт).

Как?

Программа реализует определенный конечный автомат.
Он создает исходное состояние, [0, [argument 1]]
затем последовательно переходит ко всем следующим возможным состояниям,
пока одно из них не будет найдено соответствующим [argument 2, [...]].

Примечание: запись программы находится в «Основной ссылке», которая является самой нижней ( Wṭ0WÇ€Ẏ$ÑпL’)

Ẏċ⁴¬ - Link 1, test a list of states for not having the desired cursor
Ẏ    - tighten by one
  ⁴  - program's fourth argument (second input) - desired cursor
 ċ   - count occurrences (the stack list will never match, so just inspecting the cursors)
   ¬ - logical negation

HĊ,$Ḟµ€1¦€F€;⁸Ḣ,$€ - Link 2, next states given a 0 cursor: list, rotatedStacks; number currentCursor (unused)
     µ€1¦€         - for each rotation of rotatedStacks apply to the first element:
H                  -   halve
   $               -   last two links as a monad
 Ċ                 -     ceiling
  ,                -     pair
    Ḟ              -   floor (vectorises) -- i.e. n -> [floor(ceil(n/2)),floor(n/2)]
                                                     = [ceil(n/2),floor(n/2)]
          F€       - flatten each -- i.e. each [[c1,f1],s2, s3,...] -> [c1,f1,s2,s3,...]
             ⁸     - chain's left argument, rotatedStacks
            ;      - concatenate -- i.e. [[c1,f1,s2,s3,...],[c2,f2,s3,...,s1],...,[s1,s2,s3,...],[s2,s3,...,s1],...]
                $€ - last two links as a monad for each:
              Ḣ    -   head
               ,   -   pair -- i.e. [c1,f1,s2,s3,...] -> [c1,[f1,s2,s3,...]]

‘1¦€ṭ€⁹’¤ - Link 3, next states given a non-0 cursor and a right-click: list, rotatedStacks; number currentCursor
 1¦€      - for each rotation of rotatedStacks apply to the first element:
‘         -   increment -- i.e. place an item into the first stack of each rotation
        ¤ - nilad followed by link(s) as a nilad:
      ⁹   -   chain's right argument -- currentCursor
       ’  -   decrement
    ṭ€    - tack each -- i.e. [s1-1,s2,s2,...] -> [currentCursor-1,[s1-1,s2,s2,...]]

+1¦€⁹ṭ€0;ç - Link 4, next states given a non-0 cursor: list, rotatedStacks; number currentCursor
 1¦€       - for each rotation of rotatedStacks apply to the first element:
    ⁹      -   chain's right argument -- currentCursor
+          -   add
     ṭ€0   - tack each to zero -- i.e. [s1+currentCursor,s2,s3,...] -> [0,[s1+currentCursor,s2,s3,...]]
         ç - call the last link (3) as a dyad -- get the right-click states
        ;  - concatenate

⁹Ȧ‘Ḥ¤ŀ - Link 5, next states: list, rotatedStacks; number currentCursor
     ŀ - call link at the given index as a dyad...
    ¤  -   nilad followed by link(s) as a nilad:
⁹      -     chain's right argument -- currentCursor
 Ȧ     -     any & all -- for our purposes zero if zero, one if not
  ‘    -     increment
   Ḥ   -     double
       - -- i.e. call link 2 if currentCursor is zero else call link 4

Ṫ;0ṙJ$çḢ - Link 6, next states: currentState  e.g. [cc, [s1, s2, s3, ...]]
Ṫ        - tail -- get the stacks, [s1, s2, s3, ...]
 ;0      - concatenate a zero - add an empty stack to the options for use
     $   - last two links as a monad for each:
    J    -   range(length)
   ṙ     -   rotate left by -- i.e. [[s2,s3,0,...,s1],[s3,0,...,s1,s2],[0,...,s1,s2,s3],[...,s1,s2,s3,0],...[s1,s2,s3,0,...]]
       Ḣ - head -- get the currentCursor, cc
      ç  - call the last link (5) as a dyad

Wṭ0WÇ€Ẏ$ÑпL’ - Main link: initialStack, requiredCursor
W             - wrap -- [initialStack]
 ṭ0           - tack to zero -- [0, [initialStack]]
   W          - wrap -- [[0, [initialStack]]]
         п   - loop while, collecting the results:
        Ñ     - ...condition: call next link (1) as a monad -- cursor not found
       $      - ...do: last two links as a monad:
    ǀ        -   call the last link (6) as a monad for each
      Ẏ       -   flatten the resulting list by one level
           L  - length
            ’ - decremented (the collect while loop keeps the input too)
Джонатан Аллан
источник